The height in the lightbox gallery disappears when switching tabs on the tabpanel

I use a tabpanel, on the first tab I have a lightbox gallery, on the first page load it works fine, but then there are problems

Sometimes when I switch to the profile tab, then back to the home tab, the styles in the gallery can fly off and it will lose all its set height and merge with the footer

I was given one solution

var overviewEl = document.getElementById('overview-tab');
    overviewEl.addEventListener('shown.bs.tab', function (event) {
        let masonryGrid = $('.masonry-grid').masonry({
            itemSelector: '.grid-item',
            columnWidth: '.grid-sizer',
            percentPosition: true
        });
        setTimeout(function() {
            masonryGrid.masonry('layout')
        }, 200);
        setTimeout(function() {
            masonryGrid.masonry('layout')
        }, 1000);
        setTimeout(function() {
            masonryGrid.masonry('layout')
        }, 3000);
    });

But this only works when I switch to this tab, and when I reload the page, the gallery itself will not work at all

How can I modify this code so that the gallery is loaded when opening a page with an active tab and then also when switching to this tab?

html, body {
  margin: 0;
  padding: 0;
  font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
  font-size: 14px;
}

.tab-content {
  padding: 100px;
}

.masonry-grid {
  margin: 30px -10px 20px;
}
.grid-item, .grid-sizer {
  float: left;
  width: 35%;
  padding: 10px;
}
.grid-item div {
  background: FFFFFF;
  border-radius: 8px;
  box-shadow: 0 2px 8px 0 rgba(37, 33, 97, 0.1);
}
.grid-item img {
  width: 100%;
  border-radius: 5px;
}

.footer {
  padding: 40px 0;
  position: relative;
  width: 100%;
  bottom: 0;
}

.line {
  position: absolute;
  width: 100%;
  height: 1px;
  top: 0;
  background: red;
}

.copy {
  text-align: center;
  font-size: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">

<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />

<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.4/css/lightbox.css" integrity="sha512-Woz+DqWYJ51bpVk5Fv0yES/edIMXjj3Ynda+KWTIkGoynAMHrqTcDUQltbipuiaD5ymEo9520lyoVOo9jCQOCA==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<nav>
  <div class="nav nav-tabs" id="nav-tab" role="tablist">
    <button class="nav-link active" id="nav-home-tab" data-bs-toggle="tab" data-bs-target="#nav-home" type="button" role="tab" aria-controls="nav-home" aria-selected="true">
                                Home
                            </button>
    <button class="nav-link" id="nav-profile-tab" data-bs-toggle="tab" data-bs-target="#nav-profile" type="button" role="tab" aria-controls="nav-profile" aria-selected="false">
                                Profile
                            </button>
  </div>
</nav>
<div class="tab-content" id="nav-tabContent">
  <div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab">Home
  <div class="rows">
                            <div class="masonry-grid" data-ma-sonry="{ 'itemSelector': '.grid-item'}" style="position: relative; height:640px;">
                                <div class="grid-item" style="position: absolute;">
                                    <div><a href="https://i.imgur.com/3M8MxvZ.jpg" data-lightbox="image-1" data-title="image 1"><img src="https://i.imgur.com/3M8MxvZ.jpg" alt=""></a></div>
                                </div>
                                <div class="grid-item" style="position: absolute;">
                                    <div><a href="https://i.imgur.com/3yAfpYK.jpg" data-lightbox="image-1" data-title="image 2"><img src="https://i.imgur.com/3yAfpYK.jpg" alt=""></a></div>
                                </div>
                                <div class="grid-item" style="position: absolute;">
                                    <div><a href="https://i.imgur.com/CEdPx8x.jpg" data-lightbox="image-1" data-title="image 3"><img src="https://i.imgur.com/CEdPx8x.jpg" alt=""></a></div>
                                </div>
                                <div class="grid-sizer"></div>
                            </div>
                        </div>
  
  </div>
  <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab">Profile</div>
</div>

<footer class="footer">
    <div class="line"></div>
    <div class="copy">FOOTER</div>
</footer>

<script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/3.3.0/masonry.pkgd.min.js" integrity="sha512-coKEwkkVJR6lO1aL/rJeVFojNKG1DRNbAfuxcvFC98W9TYBO9TQIVFXiHBBx6dRL9+effSNEYIr/5vLe5HENVg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.4/js/lightbox.js" integrity="sha512-MBa5biLyZuJEdQR7TkouL0i1HAqpq8lh8suPgA//wpxGx4fU1SGz1hGSlZhYmm+b7HkoncCWpfVKN3NDcowZgQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script>
            let masonryGrid = $('.masonry-grid').masonry({
                itemSelector: '.grid-item',
                columnWidth: '.grid-sizer',
                percentPosition: true
            });
            setTimeout(function() {
                masonryGrid.masonry('layout')
            }, 200);
            setTimeout(function() {
                masonryGrid.masonry('layout')
            }, 1000);
            setTimeout(function() {
                masonryGrid.masonry('layout')
            }, 3000);
</script>

Error message for empty field validation still showing after valid input in vue 3

I am working on developing some user forms. In my application, i am creating custom validation. It is working fine. But, error message for that empty field validation rule is still showing after any valid input.

I am not able to understand why that condition is not working.

// Validators.js

import { reactive, computed } from 'vue';

const state = reactive({
  errorMessage: '',
});
export default function useValidators() {
  const errorMessage = computed(() => state.errorMessage);
  const hasError = computed(() => !!state.errorMessage);
  const isEmpty = (fieldName, fieldValue) => {
    if (!fieldValue) {
      state.errorMessage = `The ${fieldName} can not be empty`;
      return;
    }
    state.errorMessage = ''; 
  };
  return {
    isEmpty,
    errorMessage,
    hasError,
  };
}

Here is the form validation code.

    import { reactive } from 'vue';
import useValidators from './useValidators';

const errors = reactive({});
const { hasError, errorMessage, isEmpty } = useValidators();
export default function useFormValidation() {
  const validateInputField = (fieldName, fieldValue) => {
    if (!fieldValue) {
      errors[fieldName] = isEmpty(fieldName, fieldValue);
    }
  };
  return {
    errors,
    isEmpty,
    validateInputField,
    errorMessage,
    hasError,
  };
}

This form validation js i am importing in my component like this way.

    <template>
<my-input-component :message-type="hasError && 'negative'"
           :message ="errorMessage">
  <label slot="label" for="example-input">Name of this place:</label>
  <input
      type="text"
      name="example-input"
      id="example-input"
      v-model="nameField"
      @keyup="validateInput"
      @blur="validateInput"
      />
</my-input-component>

</template>

<script setup>
import useFormValidation from '@/utilities/useFormValidation';


const nameField = ref('');
const {
  validateInputField, errorMessage, hasError,
} = useFormValidation();

const validateInput = () => {
  validateInputField('name', nameField.value);
};

</script>

I am not sure why this error message variable is not updating. That ‘isEmpty’ function what i have done wrong?

Datatable.net export to excel autofit width

I am building this report in html and then have a option to export the data into excel. I have it setup for word wrap which is now working but all the columns are 75 width. Can this be base on the data length? or can I use some type of autofit width?

$("#Report").DataTable({
       paging: false,
       scrollX: true,
       order: [[3, 'asc']],
       buttons: [
           {
            extend: 'excelHtml5',
            title: "Report - " + moment().format('MM-DD-YYYY'),
            exportOptions: {
                 stripHtml: false,
                 stripNewlines: false,
                 format: {
                    body: function (data, column, row) {
                    return data.replace(/<brs*/?>/ig, "n")
                               .replace(/(<([^>]+)>)/ig, "");
                    }
                  }
                  },
                  customize: function (xlsx) {
                    var sheet = xlsx.xl.worksheets['sheet1.xml'];
                    $('row c', sheet).attr('s', '55');
                    var col = $("col", sheet);
                    col.each(function () {
                         $(this).attr('width', 75);
                    });
                    }
                  }
                ]
      });

Jest not recognizing import statement in a Node.js and Lerna monorepo

I’m working on a Lerna monorepo project which includes multiple Node.js packages. Each package uses ES6 syntax, notably the import statement for modules.

When I try to run Jest tests, I’m encountering the following error:

“SyntaxError: Cannot use import statement outside a module”

This error is triggered by any file using the import statement.

Here are some relevant details about my setup:

- Node version: v18.16.0 (set by .nvmrc and being recognized)
- Using Lerna for monorepo management
- Babel is configured and works correctly for the build process
- The jest.config.js and babel.config.js files are in the project's root directory
- Each package has "type": "module" in its package.json

Here are the some files:

jest.config.js:

module.exports = {
transform: {
  '^.+\.jsx?$': 'babel-jest',
},

};

babel.config.js:

module.exports = { presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
],
};

lerna.json:

{
 "$schema": "node_modules/lerna/schemas/lerna-schema.json",
 "useWorkspaces": true,
  "packages": ["services/*"],
  "version": "0.0.0"
}

Still, Jest doesn’t seem to recognize the import statements in my files.
Any idea about what could be the issue and how might I solve it?

Thanks a lot!!

Uncaught TypeError: Cannot read properties of null (reading ‘cloneNode’) [duplicate]

What did I do wrong that gives an error. I don’t understand why she appeared

Uncaught TypeError: Cannot read properties of null (reading ‘cloneNode’)

`    useEffect(()=>{
    for (let i = 1; i < test; ++i) {
        var clone = document.getElementById('thediv').cloneNode(true);
        document.getElementById("containerWrapper").appendChild(clone);
    }
},[])`

I tried to change the location of this part of the code in the file. It didn’t help

What is the React pattern where the children prop accepts a function?

I am trying to find the name of the React pattern where a component’s children prop accepts a function, allowing a component to pass data to arbitrary children.

Here’s an example of this pattern from Formik’s docs:

<Formik>
  {({ handleSubmit, handleChange, handleBlur, values, errors }) => (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        onChange={handleChange}
        onBlur={handleBlur}
        value={values.name}
        name="name"
      />
      {errors.name &&
        <div>
          {errors.name}
        </div>}
      <button type="submit">Submit</button>
    </form>
  )}
</Formik>

I tried searching for descriptions of this pattern, but was not able to find anything.

Does this pattern have a name? Are there good uses for it? Is it an anti-pattern?

Vue.js Build and Deploy to NGINX TypeError: Cannot use ‘in’ operator to search for ‘path’ in undefined

I am developing an E-Commerce. It is Vue.js with Django Rest Framework. It was working perfectly fine on my local machine. I had absolutely no errors. Now, once I did “npm run build” (I created the project by “vue create myproject”) and uploaded it to my server, some pages stopped working, and on some pages there are tons of error codes. The APIs are working fine and can be accessed and the data served seen. The main problem is the Vue.js build that I get that doesn’t work well. I hope you can help me.

For example here I should have my products, but I get this:
enter image description here

Here is what my broken homepage looks like (it should show the most sold products):
enter image description here

Here is My router:

import { createRouter, createWebHistory } from 'vue-router'
import store from '../store'
import axios from 'axios'

import Home from '../views/Home.vue'
import Products from '../views/shop/Products.vue'
import Product from '../views/shop/Product.vue'
import About from '../views/About.vue'
import Corporate from '../views/Corporate.vue'
import Contact from '../views/Contact.vue'
import ContactThankYou from '../views/ContactThankYou.vue'
import Login from '../views/auth/Login.vue'
import SignUp from '../views/auth/SignUp.vue'
import ResetPassword from '../views/auth/ResetPassword.vue'
import ResetPasswordToken from '../views/auth/ResetPasswordToken.vue'
import ResetPasswordMessage from '../views/auth/ResetPasswordMessage.vue'
import ResetSetNewPassword from '../views/auth/ResetSetNewPassword.vue'
import Account from '../views/auth/Account.vue'
import ComplaintsBook from '../views/ComplaintsBook.vue'
import PrivacyPolicy from '../views/PrivacyPolicy.vue'
import Favorites from '../views/Favorites.vue'
import Cart from '../views/shop/Cart.vue'
import Checkout from '../views/shop/Checkout.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
  },
  {
    path: '/productos',
    name: 'products',
    component: Products,
  },
  {
    path: '/:product_slug/',
    name: 'Product',
    component: Product,
  },
  {
    path: '/nosotros',
    name: 'about',
    component: About,
  },
  {
    path: '/corporativo',
    name: 'corporate',
    component: Corporate,
  },
  {
    path: '/contacto',
    name: 'contact',
    component: Contact,
  },
  {
    path: '/gracias-por-su-mensaje',
    name: 'contactthankyou',
    component: ContactThankYou,
  },
  {
    path: '/favoritos',
    name: 'favorites',
    component: Favorites,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/carrito',
    name: 'cart',
    component: Cart,
  },
  {
    path: '/finalizar-la-compra',
    name: 'checkout',
    component: Checkout,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/entrar',
    name: 'login',
    component: Login,
  },
  {
    path: '/registro',
    name: 'register',
    component: SignUp,
  },
  {
    path: '/cuenta',
    name: 'account',
    component: Account,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/recuperar-cuenta',
    name: 'resetpassword',
    component: ResetPassword,
  },
  {
    path: '/recuperar-cuenta-mensaje',
    name: 'resetpasswordmessage',
    component: ResetPasswordMessage,
  },
  {
    path: '/recuperar/:token_slug/',
    name: 'ResetPasswordToken',
    component: ResetPasswordToken,
  },
  {
    path: '/recuperar-token',
    name: 'resetsetnewpassword',
    component: ResetSetNewPassword,
  },
  {
    path: '/libro-de-reclamaciones',
    name: 'complaintsbook',
    component: ComplaintsBook,
  },
  {
    path: '/terminos-y-condiciones',
    name: 'privacypolicy',
    component: PrivacyPolicy,
  },
]


const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requireLogin) && !store.state.isAuthenticated) {
    next({ name: 'login', query: { to: to.path } });
  } else {
    next()
  }
})

export default router

Here is my main index.js:

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap'
import axios from 'axios'

import '../scss/custom.scss'

import '@fortawesome/fontawesome-free/css/all.css'
import '@fortawesome/fontawesome-free/js/all.js'

axios.defaults.baseURL = 'myserveriphere:8000'

createApp(App).use(store).use(router, axios).mount('#app')

Here is my Package.json:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
  },
  "dependencies": {
    "@popperjs/core": "^2.11.6",
    "axios": "^1.2.1",
    "bootstrap": "^5.2.2",
    "core-js": "^3.8.3",
    "vue": "^3.2.13",
    "vue-router": "^4.0.3",
    "vuex": "^4.0.0"
  },
  "devDependencies": {
    "@fortawesome/fontawesome-free": "^6.2.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "sass": "^1.32.7",
    "sass-loader": "^12.0.0"
  }
}

And here is my Nginx setup:

upstream ecologic_app_server {
    server unix:/webapps/ecologic/backend/venv/run/gunicorn.sock fail_timeout=0;
}



server {
    listen 8000;
    listen [::]:8000;
    server_name myipserverhere;

    client_max_body_size 40M;


    location / {
        root /webapps/ecologic/frontend;
        try_files $uri /index.html;
        index index.html index.htm;
    }

    location /static/ {
        root /webapps/ecologic/backend;
    }

    location /media/ {
        root /webapps/ecologic/backend;
    }


    location /api/v1/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Host $http_host;
        proxy_pass http://ecologic_app_server/api/v1/;
        proxy_ssl_session_reuse off;
        proxy_redirect off;
    }

    location /admin/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://ecologic_app_server/admin/;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

}

I tried adding permissions on my Nginx server, nothing works, the same error. At this point I have no idea what is wrong. I tried the same setup in the past and it was working fine. I hope that you could help me out with that or at least point to the right direction. Thank you!

Dynamically switch between component or `template`

So I have a complex Vue monorepo setup which involves some apps running in Vue2 and some other running in Vue3.

In the monorepo I also got some packages which sometimes expose components (to be consumed by both Vue2 and Vue3 with vue-demi).

The problem is that for some technical requirements I need to have some components defined as a fragment within a table (Several nodes under template), some of it related to a11y . I know that vue3 already allows this but in vue2 is not possible.

So I was tempted to use vue-frag for the vue2 side. What is the issue? That library is not compatible with vue3.

So my question is, is there a possibility to switch between the template‘s vue3 tag and Fragment from vue-frag ?

Something like:

  // This actually does not work, because it try to interpret template as an HTML tag
 <component :is="isVue2 ? Fragment : 'template'>
   <-- ... --/>
 </component>

matomo api timeout on fetching

I’m trying to integrate data collected with Matomo within my website but whenever the API is being fetched console says: ERR_CONNECTION_TIMED_OUT. I’ve checked the firewall as well as testing another network. I even set the timout to like 10 mins but it keeps erroring.

Thats what my code currently looks like, maybe there’s a mistake

var apiUrl = 'https://dummy.matomo.de/';
        var auth_token = 'dummyAuthToken12345';
        // Matomo Site ID
        var siteId = '5';
        // Matomo Method
        var exitPage = '&method=Actions.getExitPageUrls';
 fetch(apiUrl + '?module=API' + exitPage + '&idSite=' + siteId + '&segment=' + companyName + '&token_auth=' + auth_token + '&format=json', {timeout: 60000})
            .then(response => {
var totalVisits = data[0]['nb_visits'];

I can’t figure out how my Django React Create Form returns, ‘Unsupported Media Type: /api/auctions/’

My Django REST API uploads an auction correctly (including the required images) when I make a post request in Postman. However, my React auctioncreateform.js file does not successfully create an auction and instead returns the error below: ‘Unsupported Media Type: /api/auctions/’.

THE FORM WORKS AS INTENDED when I remove the uploaded_images values/attributes from the project. The post request through the form shows an error when I include the uploaded_images field.

console.log(values); in my auctioncreateform.js returns these:


bestdeals: false

car_specification: [12] (1)

category: 1

duration: 7

make: 1

model: 1

name: "jhjh"

overview: "<p>gfgfg</p>"

reserveprice: 0

start_time: "2023-05-27T10:53"

starting_price: 0

type: "SUV"

uploaded_images: Array (1)
0 File {path: "BM945737_dec96f.jpeg", name: "BM945737_dec96f.jpeg", lastModified: 1684687221000, webkitRelativePath: "", size: 83369, …}

Array Prototype

year: "2012"

Below is my auctioncreateform.js

import React, { useState, useEffect } from "react";
import clsx from "clsx"
import { Formik, Form, Field, ErrorMessage } from "formik"
import { useSnackbar } from "notistack"
import Alert from 'react-bootstrap/Alert';
import Container from 'react-bootstrap/Container';



import axios from "axios";
import FilesDropzone from "../../../../components/Files-Dropzone";

import { postAuctionAxios } from '../../../../services/AuctionService'
import { YupAuctionValidation } from "./schema/YupAuctionValidation"
import { AuctionDefaultValue } from "./schema/AuctionDefaultValue"
import { useNavigate } from "react-router"



const AuctionCreateForm = props => {
 ....
  return (
    <Container>

    <Formik
      initialValues={AuctionDefaultValue}
      validationSchema={YupAuctionValidation}
      onSubmit={async (values, formikHelpers) => {
        console.log(values);

        
        try {
          const token = localStorage.getItem("token");
          console.log(token)
          const { uploaded_images, ...otherValues } = values;
          console.log('Uploaded Images:', uploaded_images);
          
          await postAuctionAxios(values, { headers: { 'Content-Type': 'multipart/form-data' } });


          
          formikHelpers.setStatus({ success: true })
          formikHelpers.setSubmitting(false)
          enqueueSnackbar("Auction Created", {
            variant: "success"
          })
          .push("list-auctions")
        } catch (err) {
          alert("Something happened. Please try again.")
          setError(err.message)
          formikHelpers.setStatus({ success: false })
          formikHelpers.setSubmitting(false)
        }
        //console.log(err.message)
      }}
      
    >
      {formikProps => (
        <form onSubmit={formikProps.handleSubmit} className="">
          <Grid container spacing={3}>
            <Grid item xs={12} lg={8}>
      .....
              <Box mt={3}>
                <Card>
                  <CardHeader title="Upload Images" />
                  <Divider />
                  <CardContent>
                  <FilesDropzone onFilesChange={(files) => formikProps.setFieldValue('uploaded_images', files)} />
                  </CardContent>
                </Card>
              </Box>
              
             ....
       
          <Box mt={2}>
            <Button
              color="primary"
              variant="contained"
              type="submit"
              disabled={formikProps.isSubmitting}
            >
              Create auction
            </Button>
          </Box>
        </form>
      )}
    </Formik>
    )}
    </Container>
  );
};

export default AuctionCreateForm;
      

My imported Dropzone.js component is as follows:

import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
import { Box, Typography, List, ListItem, ListItemAvatar, Avatar, ListItemText, IconButton } from "@mui/material";
import { Delete as DeleteIcon } from "@mui/icons-material";

const FilesDropzone = ({ onFilesChange }) => {
  const handleDrop = useCallback(
    (acceptedFiles) => {
      if (onFilesChange) {
        onFilesChange(acceptedFiles);
      }
    },
    [onFilesChange]
  );

  const { getRootProps, getInputProps, isDragActive, acceptedFiles } = useDropzone({
    onDrop: handleDrop,
    accept: 'image/*',
    multiple: true,
  });

  const handleRemoveFile = (index) => {
    if (onFilesChange) {
      const updatedFiles = [...acceptedFiles];
      updatedFiles.splice(index, 1);
      onFilesChange(updatedFiles);
    }
  };

  return (
    <Box {...getRootProps()} p={2} border={1} borderColor="grey.400" borderRadius={4}>
      <input {...getInputProps()} />
      {isDragActive ? (
        <Typography variant="body1">Drop the files here...</Typography>
      ) : (
        <Typography variant="body1">Drag and drop files here or click to browse</Typography>
      )}
      {acceptedFiles.length > 0 && (
        <Box mt={2}>
          <List>
            {acceptedFiles.map((file, index) => (
              <ListItem key={index}>
                <ListItemAvatar>
                  <Avatar variant="rounded" src={URL.createObjectURL(file)} />
                </ListItemAvatar>
                <ListItemText primary={file.name} secondary={`${(file.size / 1024).toFixed(2)} KB`} />
                <IconButton onClick={() => handleRemoveFile(index)}>
                  <DeleteIcon />
                </IconButton>
              </ListItem>
            ))}
          </List>
        </Box>
      )}
    </Box>
 
};

export default FilesDropzone;

Please let me know if you need more code including the backend. I can’t find a way to solve this.

Formatting contents of a code fence in VS Code

In VS Code, I have a code fence, in this case it is a javascript-marked fence. I’d like to be able to select the contents of the fence and format it and have my default formatter do its thing, but it keeps trying to use the Markdown formatter that I have. Ideally, VS Code would know that there is a fence there and apply the correct formatter to the contents of each fence based on the language identifier, but that might be asking too much.

Is what I’m after even possible? I’ve tried selecting the text and doing “Format Selection…”, but that doesn’t do anything. The only thing I can think of is to open a new file, mark it as JavaScript, paste in the code from the fence, format it, and then put it back in the markdown fence. There has to be an easier way.

How to nested map for res.json() in express

I am working on an express application (server-side) that provides movie information to users but I am trying to send a JSON response like this:

{
  "title": "Star Trek: First Contact",
  "year": 1996,
  "runtime": 111,
  "genres": [
    "Action",
    "Adventure",
    "Drama"
  ],
  "country": "United States",
  "principals": [
    {
      "id": "nm0005772",
      "category": "cinematographer",
      "name": "Matthew F. Leonetti",
      "characters": []
    },
    {
      "id": "nm0001772",
      "category": "actor",
      "name": "Patrick Stewart",
      "characters": [
        "Picard"
      ]
    },
    {
      "id": "nm0000408",
      "category": "actor",
      "name": "Jonathan Frakes",
      "characters": [
        "Riker"
      ]
    },
    {
      "id": "nm0000653",
      "category": "actor",
      "name": "Brent Spiner",
      "characters": [
        "Data"
      ]
    },
    {
      "id": "nm0000996",
      "category": "actor",
      "name": "LeVar Burton",
      "characters": [
        "Geordi"
      ]
    },
    {
      "id": "nm0734472",
      "category": "writer",
      "name": "Gene Roddenberry",
      "characters": []
    },
    {
      "id": "nm0075834",
      "category": "writer",
      "name": "Rick Berman",
      "characters": []
    },
    {
      "id": "nm0103804",
      "category": "writer",
      "name": "Brannon Braga",
      "characters": []
    },
    {
      "id": "nm0601822",
      "category": "writer",
      "name": "Ronald D. Moore",
      "characters": []
    },
    {
      "id": "nm0000025",
      "category": "composer",
      "name": "Jerry Goldsmith",
      "characters": []
    }
  ],
  "boxoffice": 92027888,
  "poster": "https://m.media-amazon.com/images/M/MV5BYzMzZmE3MTItODYzYy00YWI5LWFkNWMtZTY5NmU2MDkxYWI1XkEyXkFqcGdeQXVyMjUzOTY1NTc@._V1_SX300.jpg",
  "plot": "The Borg travel back in time intent on preventing Earth's first contact with an alien species. Captain Picard and his crew pursue them to ensure that Zefram Cochrane makes his maiden flight reaching warp speed."
}

The problem is that I can’t seem to get the principals data to output as it would return {} instead:

{
  "title": "Star Trek: First Contact",
  "year": 1996,
  "runtime": 111,
  "genres": [
    "Action",
    "Adventure",
    "Drama"
  ],
  "country": "United States",
  "principals": {},
  "boxoffice": 92027888,
  "poster": "https://m.media-amazon.com/images/M/MV5BYzMzZmE3MTItODYzYy00YWI5LWFkNWMtZTY5NmU2MDkxYWI1XkEyXkFqcGdeQXVyMjUzOTY1NTc@._V1_SX300.jpg",
  "plot": "The Borg travel back in time intent on preventing Earth's first contact with an alien species. Captain Picard and his crew pursue them to ensure that Zefram Cochrane makes his maiden flight reaching warp speed."
}

The objects outside such as title, year, runtime, genres, etc. are all in a table called basics, meanwhile every object inside principals are in another table called principals.

Here is what I’ve done so far:

router.get('/movies/data/:imdbID', function(req, res, next) {

  const queryMovie = req.db.from('basics').select(
      'primaryTitle', 
      'year',
      'runtimeMinutes', 
      'genres', 
      'country', 
      'boxoffice', 
      'poster', 
      'plot'
    ).where('tconst', req.params.imdbID)
  
  const queryPrincipals = req.db.from('principals').select('nconst', 'category', 'name', 'characters').where('tconst', req.params.imdbID)

  queryMovie.then((movieData) => {
    const movie = movieData.map(data => {
      return {
        title: data.tconst,
        year: data.year,
        runtime: data.runtimeMinutes,
        country: data.country,
        principals: queryPrincipals.then((principals) => {
          principals.map(principal => {
            return {
              id: principal.nconst,
              category: principal.category,
              name: principal.name,
              characters: principal.characters
            }
          })
        }),
        boxoffice: data.genres,
        poster: data.genres,
        plot: data.plot
      }
    })
    res.json(movie)
  })
});