API documentation using swagger, YAML syntax error

I am learning API documentation using swagger (open API version 3)

I am trying to document the post route.

Here is my YAML syntax.

/**
 * @swagger
 * /home: 
 *  post:
 *      summary: create a new product
 *      tags: [Products]
 *      requestBody:
 *          required: true
 *          content:
 *              application/json:
 *                  schema:                 
 *                      $ref: "#/components/schemas/Product"
 * 
 *      responses:
 *          200:
 *              description: The product was inserted successfully
 *              content:
 *                  application/json:
 *                      schema:
 *                          $ref: "#/components/schemas/Product"
 *         500:
 *              description: Some server error
 * 
 */

I have thoroughly gone through this code. Yet, I keep running into this error:

Here's the report:


 Error in ./routes/route.js :
YAMLSyntaxError: All collection items must start at the same column at line 3, column 6:

     summary: create a new product
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^…

Connecting Quickbooks OAuth through Google Apps Script

I’m trying to connect Quickbooks API through OAuth. I’ve added the OAuth 2 library to the Apps Script and deployed the Web App. The Web App URL is what I’m using as an URI in the OAuthService call and I’ve also set it up in the Quickbooks URI parameters. I get the Quickbooks site to open to authorize, but then I keep getting errors from Google or Intuit.

Code looks like this:

function getAuthorizationUrl() {
  console.log('getAuthorizationUrl called');
  var service = getOAuthService();
  if (!service.hasAccess()) {
    var authorizationUrl = service.getAuthorizationUrl();
    return authorizationUrl;
  }
}

function getOAuthService() {
  var REDIRECT_URI = 'https://script.google.com/macros/s/[SCRIPT_ID]/usercallback/';
  return OAuth2.createService('QuickBooks')
      .setAuthorizationBaseUrl('https://appcenter.intuit.com/connect/oauth2')
      .setTokenUrl('https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer')
      .setClientId(CLIENT_ID)
      .setClientSecret(CLIENT_SECRET)
      .setRedirectUri(REDIRECT_URI)
      .setCallbackFunction('authCallback')
      .setPropertyStore(PropertiesService.getUserProperties())
      .setScope('com.intuit.quickbooks.accounting')
      .setTokenHeaders({
        'Content-Type': 'application/x-www-form-urlencoded'
      });
}

I’m currently getting this error even though the URIs are the same in both ends.

Error message

The redirect_uri query parameter value is invalid. Make sure it is
listed in the Redirect URIs section on your app’s keys tab and matches
it exactly. Click here to learn more about the redirect_uri query
parameter.

Any suggestion? I’ve tried all possible configurations for the URI.

How to draw a background image into a ‘pie’ of chart js

`

var images = [
  new Image(),
  new Image(),
  new Image(),
  new Image(),
  new Image(),
  new Image()
];
//Set the source of each image
images[0].src = 'images/img1.png';
images[1].src = 'images/img2.jpg';
images[2].src = 'images/img3.jpg';
images[3].src = 'images/img4.jpg';
images[4].src = 'images/img5.jpg';
images[5].src = 'images/img6.jpg';
//Create chart
let myChart = new Chart(wheel, {
  //Plugin for displaying text on pie chart
  plugins: [ChartDataLabels],
  //Chart Type Pie
  type: "pie",
  data: {
    //Labels(values which are to be displayed on chart)
    labels: [`Tarde denpaseo`, "Noche dencine", "Día denpicnic", "Parrilladan en lanmontaña", "Tour denfiesta", "Paseo denplaya"],
    //Settings for dataset/pie
    datasets: [
      {
        //backgroundColor: pieColors,
        data: data,
      },
    ],
  },
  options: {
    //Responsive chart
    responsive: true,
    animation: { duration: 0 },
    plugins: {
      //Draw a background image for each piece
      drawBackgroundImages: {
        beforeDraw: (chart) => {
          const ctx = chart.ctx;
          const chartArea = chart.chartArea;
          const meta = chart.getDatasetMeta(0);
          const radius = meta.controller._radius;
          const centerX = (chartArea.left + chartArea.right) / 2;
          const centerY = (chartArea.top + chartArea.bottom) / 2;

          meta.data.forEach((element, index) => {
        const startAngle = element._model.startAngle;
        const endAngle = element._model.endAngle;
        const midAngle = startAngle + (endAngle - startAngle) / 2;

        const x = centerX + Math.cos(midAngle) * radius / 2;
        const y = centerY + Math.sin(midAngle) * radius / 2;

        ctx.drawImage(images[index], x - radius / 4, y - radius / 4, radius / 2, radius / 2);
          });
        }
      },

i test use the method onload() to see if the images are loading and they are. Also try with diferent images types as png and jpg. The funcionality of the code is complete except this. Any suggestion i will apreciate The project is a sping wheel
enter image description here

AppScript to split spreadsheet into multiple spreadsheets (based on condition) + automatic email sending of new excel files as attachments

I am newbie in terms of AppScript but I have been trying to make something work with chat gpt.
Unfortunately the codes proposed by chatgpt have different flaws and it seems to go in circles going back and forth with some issues.

I have a spreadsheet with data for around 80 suppliers.
In this spreadsheet I have two sheets:

  • PO Level: supplier service level per purchasing order
  • Item Level: supplier service level at SKU level

Based on original file I need to create a script that will split the original file into one file per supplier that will contain the same data and format as original file, but only for a certain supplier.
Then after creating these files and saving them on GDrive, I need the script to send emails to those suppliers attaching the files as excel, not as a link, based on a different spreadsheet where I have the email addresses.

I have tried multiple codes proposed by chatgpt but either they are attached as pdf or they are attached as link (not the file directly). The issue that appears the most often is related to the script creating pdf’s and then not being able to convert them to excel. It has a hard time creating the files directly .xlsx

This is the code below, maybe someone can give me a hint on how I should approach this task, maybe it’s not possible to do them all in one script, I don’t know to be honest..

Script below (FYI:I have replaced the links to the google drive with XXXX)

function splitDataBySupplier() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var poSheet = spreadsheet.getSheetByName("PO Level");
  var itemSheet = spreadsheet.getSheetByName("Item Level");
  var dataRangePO = poSheet.getDataRange();
  var dataRangeItem = itemSheet.getDataRange();
  var dataPO = dataRangePO.getValues();
  var dataItem = dataRangeItem.getValues();

  // Load email addresses from separate spreadsheet
  var emailSpreadsheet = SpreadsheetApp.openById("XXXY");
  var emailSheet = emailSpreadsheet.getSheetByName("Emails");
  var emailRange = emailSheet.getDataRange();
  var emailData = emailRange.getValues();
  var emailMap = {};
  emailData.forEach(function(row) {
    emailMap[row[0]] = row[1];
  });

  var suppliers = {}; // Object to store data for each supplier

  // Iterate over PO Level data
  for (var i = 1; i < dataPO.length; i++) { // Start from 1 to skip headers
    var supplierName = dataPO[i][2]; // Assuming Supplier name is in the third column
    if (!suppliers[supplierName]) {
      suppliers[supplierName] = { poData: [], itemData: [] };
    }
    suppliers[supplierName].poData.push(dataPO[i]);
  }

  // Iterate over Item Level data
  for (var j = 1; j < dataItem.length; j++) { // Start from 1 to skip headers
    var supplierName = dataItem[j][2]; // Assuming Supplier name is in the third column
    suppliers[supplierName].itemData.push(dataItem[j]);
  }

  // Process data for each supplier
  for (var supplier in suppliers) {
    if (suppliers.hasOwnProperty(supplier)) {
      var supplierData = suppliers[supplier];
      var newSpreadsheet = SpreadsheetApp.create(supplier + ".xlsx"); // Create a new spreadsheet in Excel format
      var newPOSheet = newSpreadsheet.getActiveSheet();
      newPOSheet.setName("Performanta / Comanda");
      var newItemSheet = newSpreadsheet.insertSheet();
      newItemSheet.setName("Performanta / Articol");

      // Write header row for PO Level sheet
      var poHeader = poSheet.getRange(1, 1, 1, poSheet.getLastColumn()).getValues()[0];
      newPOSheet.appendRow(poHeader);
      // Write data to PO Level sheet
      newPOSheet.getRange(2, 1, supplierData.poData.length, supplierData.poData[0].length).setValues(supplierData.poData);

      // Write header row for Item Level sheet
      var itemHeader = itemSheet.getRange(1, 1, 1, itemSheet.getLastColumn()).getValues()[0];
      newItemSheet.appendRow(itemHeader);
      // Write data to Item Level sheet
      newItemSheet.getRange(2, 1, supplierData.itemData.length, supplierData.itemData[0].length).setValues(supplierData.itemData);

      // Get recipient email from emailMap
      var emailAddress = emailMap[supplier];
      if (emailAddress) {
        // Send email with attachment
        sendEmailWithAttachment(emailAddress, supplier, newSpreadsheet);
      } else {
        Logger.log("Email address not found for supplier: " + supplier);
      }
    }
  }
}

function sendEmailWithAttachment(emailAddress, supplier, spreadsheet) {
  var folder = DriveApp.getFolderById("XXXX");
  var file = DriveApp.getFileById(spreadsheet.getId());
  var blob = file.getBlob();

  var message = "Performanta lunara a livrarilor " + supplier + "nn";
  message += "Buna ziua!nn";
  message += "Am atasat fisierul unde puteti vedea performanta livrarilor din luna precedenta.n";
  message += "Va rugam sa verificati fisierul, iar in maxim 48 de ore sa reveniti catre noi cu un raspuns legat de cum putem imbunatati livrarile, astfel incat performanta livrarilor la nivel de articol sa fie minim 95%.nn";
  message += "Multumesc!";

  MailApp.sendEmail(emailAddress, "Performanta lunara a livrarilor " + supplier, message, {
    attachments: [blob]
  });
}

I also attached a copy of the file.
https://docs.google.com/spreadsheets/d/1TDFStSarmNvOjf416aGGfSpJUcHIZG_ULv6rHg6ICXw/edit#gid=1933877440

Thanks a lot!

How to allow the user to scroll when they are continuously pulled down as new data arrives?

I want to create something like a chat where the scroll automatically pulls down when the user receives new messages. However, I am facing a problem when the user tries to scroll up. When I am scrolling up and receive a new message, my scroll always pulls down.

Here is a sample of code: link

Could someone explain or provide a code example on how to address this issue?

Axios request automatically fired a second time after a delay

In my nodejs application, I have an Axios API call that involves extensive operations and takes approximately 3 minutes to complete. The issue I’m facing is that, despite the initial call not encountering any problems or finishing its execution, a duplicate request is automatically triggered after approximately 2 minutes.

I haven’t been able to identify the reason behind the automatic second call. My suspicion is that there might be a timeout mechanism causing a reissue of the request if the initial one doesn’t complete within a certain timeframe.

Here’s the code snippet:

  axios
  .get(`http://${MICROSERVICE_HOST}:${MICROSERVICE_PORT}/SchemaExp/` + rd, {
    headers: {
      token: req.cookies.token,
    },
  })
  .then(function (response) {
    resolve(response);
  })
  .catch(function (error) {
    reject(error);
  })
  .finally(function () {
    console.log("finally");
  });

Any insights or suggestions on how to resolve this issue would be greatly appreciated. Thank you in advance

Language switcher – Flags in option XSLT IdoSell

I would like to modify the current xslt code so that a flag is also displayed next to the language name. Currently, the language is displayed in option and as far as I know, it is not possible to insert a flag there. The flags are located under this path “/gfx/standards/[id].svg’)”, e.g. ‘/gfx/standards/pol.svg’, ‘/gfx/standards/eng.svg’. Is there a good person here who will help me with this?

Below is the entire code and script.

<?xml version="1.0" encoding="UTF-8"?>
<iai:component>
    <iai:componentsdata>
        <cdata-start/>
        <div id="freeShipping" class="col-12">
            <div style="display: flex; justify-content: space-between; align-items: center;">
                <!-- Social Icons -->
                <div id="social-icons-left">
                    <ul class="social-icons">
                        <iaixsl:for-each select="/shop/contact/contact_nodes/node[@type='text' and @title='Facebook']">
                        <a href="{@value}" title="{@title}" class="footer_contact__item footer_contact__item--facebook d-flex align-items-center justify-content-center">
                            <i class="icon-facebook"></i>
                        </a>
                    </iaixsl:for-each>
                    <iaixsl:for-each select="/shop/contact/contact_nodes/node[@type='text' and @title='Instagram']">
                        <a href="{@value}" title="{@title}" class="footer_contact__item footer_contact__item--instagram d-flex align-items-center justify-content-center">
                            <i class="icon-instagram"></i>
                        </a>
                    </iaixsl:for-each>
                    </ul>
                </div>
                </div>
                <!-- Settings for language and currency selection -->
                <div class="menu_settings_right">
                  <form id="languageCurrencyForm" action="/settings.php" method="POST">
                    <!-- Language Selection -->
<select name="lang" id="languageSelect" class="menu_settings_language_select">
    <iaixsl:for-each select="/shop/language/option">
        <option>
            <iaixsl:attribute name="value"><iaixsl:value-of select="@id"/></iaixsl:attribute>
            <iaixsl:if test="@selected='true'">
                <iaixsl:attribute name="selected">selected</iaixsl:attribute>
            </iaixsl:if>
            <iaixsl:choose>
                <iaixsl:when test="@id='pol'"><iai:variable vid="Polski"/></iaixsl:when>
                <iaixsl:when test="@id='eng'"><iai:variable vid="English"/></iaixsl:when>
                <iaixsl:when test="@id='ger'"><iai:variable vid="German"/></iaixsl:when>
                <iaixsl:when test="@id='fre'"><iai:variable vid="French"/></iaixsl:when>
                <iaixsl:when test="@id='spa'"><iai:variable vid="Spanish"/></iaixsl:when>
                <iaixsl:when test="@id='cze'"><iai:variable vid="Czech"/></iaixsl:when>
                <iaixsl:when test="@id='lit'"><iai:variable vid="Lithuanian"/></iaixsl:when>
                <iaixsl:when test="@id='slo'"><iai:variable vid="Slovak"/></iaixsl:when>
                <iaixsl:when test="@id='por'"><iai:variable vid="Portuguese"/></iaixsl:when>
                <iaixsl:when test="@id='rum'"><iai:variable vid="Romanian"/></iaixsl:when>
                <iaixsl:when test="@id='ita'"><iai:variable vid="Italian"/></iaixsl:when>
                <iaixsl:when test="@id='rus'"><iai:variable vid="Russian"/></iaixsl:when>
                <iaixsl:when test="@id='ukr'"><iai:variable vid="Ukrainian"/></iaixsl:when>
                <!-- Dodaj więcej warunków dla innych języków -->
                <iaixsl:otherwise><iaixsl:value-of select="@name"/></iaixsl:otherwise>
            </iaixsl:choose>
        </option>
    </iaixsl:for-each>
</select>

                    <!-- Currency Selection -->
                    <select name="curr" id="currencySelect" class="menu_settings_currency_select">
                      <iaixsl:for-each select="/shop/currency/option">
                        <option>
                          <iaixsl:attribute name="value"><iaixsl:value-of select="@id"/></iaixsl:attribute>
                          <iaixsl:if test="@selected='true'">
                            <iaixsl:attribute name="selected">selected</iaixsl:attribute>
                          </iaixsl:if>
                          <iaixsl:value-of select="@id"/> <iaixsl:text> </iaixsl:text><iaixsl:value-of select="@symbol"/>
                        </option>
                    </iaixsl:for-each>
                    </select>
                    </form>
                </div>
            </div>
        <cdata-end/>
    </iai:componentsdata>
</iai:component>
document.addEventListener('DOMContentLoaded', function () {
    var languageSelect = document.getElementById('languageSelect');
    var currencySelect = document.getElementById('currencySelect');

    languageSelect.addEventListener('change', function () {
        document.getElementById('languageCurrencyForm').submit();
    });

    currencySelect.addEventListener('change', function () {
        document.getElementById('languageCurrencyForm').submit();
    });
});

I tried to create a custom switcher, but I couldn’t connect it to xslt. Languages are loaded automatically depending on what they are available in the store. ChatGPT failed.

regeneratorRuntime is not defined with gulp

I’m trying to use an asynchronous function and it’s giving me the following error ‘regeneratorRuntime is not defined’. I saw a possible solution, but it’s for webpack, I’m using gulp, can anyone help me?

I’m using gulp version 4.0.2

This was the solution I found for webpack, can anyone help me adjust this for gulp, please?
Babel 6 regeneratorRuntime is not defined

The code below is the gulpfile.js file

// Load modules
const config = require('./.core/config.json');
const rename = require('gulp-rename');
const gulp = require('gulp');
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const browserSync = require('browser-sync').create();
const concat = require('gulp-concat');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
const imagemin = require('gulp-imagemin');
const webp = require('gulp-webp');
const minify = require('gulp-minify');
const gzip = require('gulp-gzip');
const robots = require('gulp-robots');
var awspublish = require('gulp-awspublish');

function generateRobots() {
    gulp.task('default', function () {
        gulp.src('index.html')
            .pipe(
                robots({
                    useragent: '*',
                    allow: ['/'],
                    disallow: ['cgi-bin/'],
                })
            )
            .pipe(gulp.dest('robots.txt'));
    });
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// SASS

function compliaSass() {
    return gulp
        .src('.core/scss/*.scss')
        .pipe(sass({ outputStyle: 'compressed' }))
        .pipe(
            autoprefixer({
                browsers: ['last 2 versions'],
                cascade: false,
            })
        )
        .pipe(minify())
        .pipe(gulp.dest('assets/css/'))
        .pipe(browserSync.stream());
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// JS Main

function gulpJS() {
    return gulp
        .src(['.core/js/*.js'])
        .pipe(concat('main.js'))
        .pipe(
            babel({
                presets: ['env'],
            })
        )
        .pipe(uglify())
        .pipe(gulp.dest('assets/js/'))
        .pipe(browserSync.stream());
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// SASS Plugins

function pluginsJs() {
    return gulp
        .src(['node_modules/jquery/dist/jquery.min.js'])
        .pipe(concat('plugins.js'))
        .pipe(gulp.dest('assets/js/'))
        .pipe(browserSync.stream());
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Live Browser

function browser() {
    browserSync.init({
        server: {
            baseDir: './',
        },
    });
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Minify images
function imageMin() {
    return gulp
        .src(['.core/images/*'])
        .pipe(
            imagemin([
                imagemin.gifsicle({ interlaced: true }),
                imagemin.mozjpeg({ quality: 20, progressive: true }),
                imagemin.optipng({ optimizationLevel: 5 }),
                imagemin.svgo({
                    plugins: [{ removeViewBox: true }, { cleanupIDs: false }],
                }),
            ])
        )
        .pipe(gulp.dest('assets/images/'));
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Images WEBP

function webP() {
    return gulp
        .src(['.core/images/*'])
        .pipe(webp())
        .pipe(gulp.dest('assets/images/'));
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// AWS PUBLISHER

function deployAWS(files, target, header) {
    var publisher = awspublish.create({
        region: 'us-east-2',
        params: {
            Bucket: 'scompa-deploy',
        },
        credentials: {
            accessKeyId: 'AKIA4AWYGPOJZDXTKMHO',
            secretAccessKey: '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',
        },
    });

    return (
        gulp
            .src(files)
            .pipe(
                rename(function (path) {
                    path.dirname = target + path.dirname;
                })
            )
            .pipe(publisher.publish(header, { noAcl: true }))
            //.pipe(publisher.sync())
            .pipe(publisher.cache())
            .pipe(
                awspublish.reporter({
                    states: ['create', 'update', 'delete'],
                })
            )
    );
}

function sendFiles() {
    let stream = gulp.src(['.']);

    for (let i = 0, len = config.paths.length; i < len; i++) {
        let obj = config.paths[i];
        deployAWS(obj.filter, obj.target, obj.header);
    }
    return stream;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// DEPLOY FTP

function deployFTP() {
    var conn = ftp.create({
        host: 'IP',
        user: 'USER',
        password: 'PASS',
        parallel: 10,
        log: gutil.log,
    });

    var globs = ['assets/**', 'index.html'];

    return gulp
        .src(globs, { base: '.', buffer: false })
        .pipe(conn.newer('.')) // only upload newer files
        .pipe(conn.dest('.'));
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Watch

function watch() {
    gulp.watch(['.core/scss/**/*'], compliaSass);
    gulp.watch(['.core/js/*.js'], gulpJS);
    gulp.watch(['.core/js/plugins/*.js'], pluginsJs);
    gulp.watch(['*.html']).on('change', browserSync.reload);
}

exports.compliaSass = compliaSass;
exports.gulpJS = gulpJS;
exports.pluginsJs = pluginsJs;
exports.browser = browser;
exports.watch = watch;
exports.imageMin = imageMin;
exports.webP = webP;
exports.generateRobots = generateRobots;
exports.deployAWS = deployAWS;
exports.sendFiles = sendFiles;
exports.deployFTP = deployFTP;

exports.default = gulp.parallel(
    watch,
    browser,
    compliaSass,
    gulpJS,
    pluginsJs,
    generateRobots
);

Refreshing the state daily in react-native

I need to show a daily video in my react-native app. This is a randomized video from a local json that has the thumbnail, title, and url. I have it so that it modifies the state at 00:00:00 hrs with a random video from the json. However, on initial load the state is showing empty. How can I make the randomize function fire once (when they install the app) but only randomize on 00:00:00hrs after that?

import AsyncStorage from '@react-native-async-storage/async-storage';
import dailyvideo from '../assets/data/dailyvideo';

const [time, setTime] = useState(new Date());

const INITIAL_STATE = {
  title: 'Seoi Nage',
  url: 'seoinage.mp4',
  thumbnail: "seionage.jpeg"
}  

const [newvideo, setNewVideo] = useState(INITIAL_STATE)

const getTheState = async () => {
  const videotitle = await AsyncStorage.getItem("title")
  const videourl = await AsyncStorage.getItem("url")
  const videothumbnail = await AsyncStorage.getItem("thumbnail")
  
  setNewVideo({
      title: videotitle,
      url: videourl,
      thumbnail: videothumbnail
    }
  )
}

const handleRandomVideo = async () => {
  const randomIndex = Math.floor(Math.random() * allwaza.length);
  const randomItem = allwaza[randomIndex];

  try {
    await AsyncStorage.multiSet(
      [
        ["title", randomItem.title],
        ["url", randomItem.url],
        ["thumbnail", randomItem.thumbnail]
      ]
    )
  } catch (error) {
    console.error(error);
  }
}


useEffect(() => {   
  const interval = setInterval(() => {
    setTime(new Date());
  }, 1000);

  return () => {
    clearInterval(interval);
  };
}, []);


useEffect(() => {
  if (time.getHours() === 0 && time.getMinutes() === 0 && time.getSeconds() ===0) {   
    handleRandomVideo()
  }
  
  getTheState()

}, [time]);

return (
   <View>
      <Text>Today's Suggested Tech </Text>
      <View>
        // This fires a VideoPlayer component that handles the url 
        <TouchableOpacity onPress={() => navigation.navigate('VideoPlayer', {data: newvideo})}>         
          <Image source={{uri: newvideo.thumbnail}}/>
        </TouchableOpacity> 
        <Text> {newvideo.title} </Text>
      </View>
   </View>
)

For clarification, the video shows up and plays when it is set to storage. My issue is, on a fresh install, the storage is empty until the next 00:00:00hrs hit. It’s bad UX. I need it to run immediately on a fresh install and then at 00:00:00 after that. Sorry if I’m over explaining it. Thanks in advance

Should you separate users and usersList in node

I’m fairly new to Node.js and Express and I’m currently building the server after building most of the frontend (React) of a complex app.
In the app I separated the mock data in users and usersList because I did not want the API calls to be too heavy to only render the list of users with all the details that each user include.
My usersList schema is as such:

const usersListSchema = mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
    },
    lastName: {
      type: String,
      required: true,
    },
   }

while my user schema is:

const usersSchema = mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
    },
    lastName: {
      type: String,
      required: true,
    },
    ... 20 other properties
   }

Now my question is:
Is it the right way and if yes, when I will create a new user will I need to POST on 2 url (“url/user-list” & “url/user” for exemple) or is there another way to achieve this in on POST request.

Thank you

Chart.js showing old data on hover

I’m using chart.js for my laravel project.
I have one chart & 3 buttons

when user clicks on button 0 with id =’0′

i will update the data & lables of the current chart using this code

My Code

    var ctx = document.getElementById("chartBig1").getContext('2d');

    var gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);

    gradientStroke.addColorStop(1, 'rgba(72,72,176,0.1)');
    gradientStroke.addColorStop(0.4, 'rgba(72,72,176,0.0)');
    gradientStroke.addColorStop(0, 'rgba(119,52,169,0)'); //purple colors

    var config = {
        type: 'line',
        data: {
            labels: @json($userDataMonth['labels']),
            datasets: [{
                label: "Users",
                fill: true,
                backgroundColor: gradientStroke,
                borderColor: '#d346b1',
                borderWidth: 2,
                borderDash: [],
                borderDashOffset: 0.0,
                pointBackgroundColor: '#d346b1',
                pointBorderColor: 'rgba(255,255,255,0)',
                pointHoverBackgroundColor: '#d346b1',
                pointBorderWidth: 20,
                pointHoverRadius: 4,
                pointHoverBorderWidth: 15,
                pointRadius: 4,
                data: @json($userDataMonth['data']),
            }]
        },
        options: gradientChartOptionsConfigurationWithTooltipPurple
    };
    var myChartData = new Chart(ctx, config);

    $("#0").click(function() {
        var data = myChartData.config.data;
        data.datasets[0].data = @json($userDataMonth['data']);
        data.labels = @json($userDataMonth['labels']);
        myChartData.update();
    });

    $("#1").click(function() {
        var data = myChartData.config.data;
        data.datasets[0].data = @json($userDataWeek['data']);
        data.labels = @json($userDataWeek['labels']);
        myChartData.update();
    });

    $("#2").click(function() {
        var data = myChartData.config.data;
        data.datasets[0].data = @json($userDataDay['data']);
        data.labels = @json($userDataDay['labels']);
        myChartData.update();
    });

The issue is the chart shows old data when i hover over it (view below gif for more clearity)

enter image description here

How to graceful shutdown an express docker app?

I recently watched a Docker course where the teacher explained that for a container to close correctly the error code must be 0, the problem is that my container ends its process with a code 137.

Therefore I have been looking and trying some way to make the exit code 0 but I have not been able to.

index.js:

const express = require("express");

const app = express();

const port = 3000;

app.get("/", (req, res) => {
  res.send("Hello, Express!");
});

app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

Dockerfile:

FROM node:latest

COPY ["package.json", "package-lock.json", "/usr/src/"]

WORKDIR /usr/src/

RUN npm install

COPY [".", "/usr/src/"]

EXPOSE 3000

CMD ["node", "index.js"]

To use this container I did:

docker build -t express .

Then

docker run --name app -p 5000:3000 -d express

To inspect the process of app I did:

docker exec app ps -ef

Output:

UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  1 11:40 ?        00:00:00 node index.js
root          14       0 50 11:40 ?        00:00:00 ps -ef

This is the output after “docker stop app”, the container wait 10 second or so before stop

This is the output after docker ps -l:

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                        PORTS     NAMES
7e7916725120   express   "docker-entrypoint.s…"   24 seconds ago   Exited (137) 10 seconds ago             app

I uploaded the repo in case you need it:

https://github.com/ivandez/express-so

How would we be able to check “foo != null” without using loosely equality operator, in a single condition? [duplicate]

As JavaScript is currently discouraging the use of loosely comparison (!= and ==) how would we be able to check this in a single condition?

A colleague who is more of a .NET engineer asked me once how would I be able to do this comparison ON ONE CODITION without using the loosely equality operator.

foo != null

NOTE: It should only reject null and undefined, but allow values like 0 and "".

DOCS: Here are some articles where we can see that the use of loosely equality is discouraged in Javascript: