disabling the dates that already have an event in fullcalendar library

First of all, here is the code:

 <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/locale-all.min.js'></script>
  <script>
    $(document).ready(function() {
      var calendar = $('#calendar').fullCalendar({
        plugins: ['dayGrid', 'interaction'],
        locale: 'sr-latn',
        selectable: true,
        selectHelper: true,
        editable: true,
        eventLimit: true,
        eventOverlap: true,
        events: './appdata/load-events.php',
        select: function(start, end) {
          var title = prompt('Unesite naziv događaja:');
          var eventData;
          if (title) {
            eventData = {
              title: title,
              start: start,
              end: end
            };
            calendar.fullCalendar('renderEvent', eventData, true); // stick? = true
            $.ajax({
              url: './appdata/add-event.php',
              data: 'title=' + title + '&start=' + start.format() + '&end=' + end.format(),
              type: 'POST',
              dataType: 'json',
              success: function(response) {}
            });
          }
          calendar.fullCalendar('unselect');
        },
      });
    });

as you can see I am using fullcalendar library and the version 3.10.2 since for some reason I can’t load newer ones it pops up with GET 404 error in console, anyway I need a way to make days that are occupied by the events from the database not clickable, meaning that you can’t add events to those days again, Here are the codes from php:

add-event.php

  <?php
include('./connect-to-base.php');

if (isset($_POST['title']) && isset($_POST['start']) && isset($_POST['end'])) {
    $title = $_POST['title'];
    $start = $_POST['start'];
    $end = $_POST['end'];

    $sql = "INSERT INTO events(title, start, end) values('$title', '$start', '$end')";
    $result = mysqli_query($conn, $sql);
    echo json_encode($result);
}

and load-events.php

<?php
include('./connect-to-base.php');

$sql = "SELECT * FROM events";
$result = mysqli_query($conn, $sql);

$events = array();

while ($row = mysqli_fetch_assoc($result)) {
    $title = $row['title'];
    $start = $row['start'];
    $end = $row['end'];

    $events[] = array(
        'title' => $title,
        'start' => $start,
        'end' => $end
    );
}

echo json_encode($events);

the connect-to-base.php is just the classic connection php

I have tried using “selectConstraint” and some other things that ChatGPT reccomended like “selectAllow” but that’s for newer versions right?

Moving the indicator icon to show the overflow of the table to the user with JavaScript

I want when the user scrolls down the page and reaches the table, the pointer icon will be shown for a short time, move to the left, and then hide.
This is for the user to notice the overflow of the table.

The script code I wrote will be moved by just clicking on the pointer icon. And this is not what I want.

But I want when the user scrolls and reaches the table the indicator icon which is initially hidden will appear and move to the left and then hide.

I am a beginner in javascript and I don’t know how to edit this simple code to achieve my goal.

$('.icon_over').click(function() {
    $(this).toggleClass('icon_over-toggle');
});
html,
body {
    max-width: 100% !important;
    overflow-x: hidden !important;
    overflow-y: auto !important;
}

body {
    background: #eee;
    direction: ltr;
    margin: 2rem 3rem;
    padding: 20px;
}

.body-page h1 {
    font-size: 3rem;
    padding: 10px;
}

.body-page p {
    font-size: 1.5rem;
    line-height: 50px;
    text-align: left;
    padding: 15px;
    margin: 40px;
}

.box_table {
    overflow-x: scroll;
    position: relative;
}

.icon_over {
    font-size: 100px;
    color: #ff4949;
    position: absolute;
    top: 60px;
    right: 60px;
    z-index: 9;
    padding: 0;
    cursor: pointer;
    transition: all 1.5s ease-in-out;
}

.icon_over-toggle {
    right: 75%;
    background: #ffffff82;
    border-radius: 50%;
    padding: 20px;
    transition: all 1.5s ease-in-out;
}

.column_header {
    font-size: 3rem;
    white-space: nowrap;
    padding: 20px;
    color: #fff;
    background: #5b5effb5;
}

.column_header:nth-last-of-type(2n-2) {
    background: #7ebcff;
}

.row_content {
    font-size: 2rem;
    padding: 10px;
    color: #000;
    background: #5b5effcf;
}

.row_content:nth-of-type(2n-1) {
    background: #95c8ff;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="body-page">
        <h1> Title content site </h1>

        <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Nulla sed, labore corrupti doloremque doloribus
            eveniet, fugit est perferendis consequuntur nostrum reiciendis vel et eius! Excepturi sit dolorem numquam
            magni consectetur et enim delectus in labore iste. Consequatur eveniet natus laudantium quaerat cupiditate
            accusantium quisquam error dolorem optio provident dolorum minima esse blanditiis eligendi velit inventore
            at culpa quis voluptates aliquam ab animi, iure hic? Repellendus commodi ullam numquam vel, tenetur iure
            dis ipsum minima dolorem dolore facilis
            id molestiae quisquam suscipit earum cum, repellat maxime vel neque. Illum laudantium quasi doloremque cum
            doloremque velit! Dolor aspernatur accusamus ex! Possimus dolor blanditiis debitis iusto harum facilis illo
            voluptatibus labore deserunt.
        </p>




        <div class="box_table">

            <span class="bi bi-hand-index-thumb-fill icon_over"></span>

            <table class="table-page">
                <thead>
                    <tr class="column-table">
                        <th class="column_header">Header column 1</th>
                        <th class="column_header">Header column 2</th>
                        <th class="column_header">Header column 3</th>
                        <th class="column_header">Header column 4</th>
                        <th class="column_header">Header column 5</th>
                        <th class="column_header">Header column 6</th>
                    </tr>
                </thead>
    
    
                <tbody>
                    <tr class="row-table">
                        <td class="row_content">
                            <span>Content column 1 (Row 1)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 2 (Row 1)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 3 (Row 1)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 4 (Row 1)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 5 (Row 1)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 6 (Row 1)</span>
                        </td>
                    </tr>
    
                    <tr class="row-table">
                        <td class="row_content">
                            <span>Content column 1 (Row 2)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 2 (Row 2)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 3 (Row 2)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 4 (Row 2)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 5 (Row 2)</span>
                        </td>
    
                        <td class="row_content">
                            <span>Content column 6 (Row 2)</span>
                        </td>
                    </tr>
                </tbody>
            </table>

        </div>

Any way to use ‘this’ (or another keyword) to refer to the innermost nested objects? [duplicate]

My code needs to handle several scenarios that involve importing specific files. The info for each scenario is stored in a JavaScript object. I would like one property to reflect the import filename and another property to reflect the import filepath. I also want to avoid having to update the filename in two places each time I create an object for a new scenario

Current Setup

    // Cross-Scenario Variables
    static inputFolder = './resources/xl-data/'

    // Import Scenarios
    static scenario = {
        scenario01: {
            scenarioDescription: "Scenario 01",
            importFilename: "scenario01.xlsx",
            importFilePath: this.inputFolder + "scenario01.xlsx",
        },
        scenario02: {
        },
        // etc
    }

Ideal Setup

    // Cross-Scenario Variables
    static inputFolder = './resources/xl-data/'

    // Import Scenarios
    static scenario = {
        scenario01: {
            scenarioDescription: "Scenario 01",
            importFilename: "scenario01.xlsx",
            importFilePath: this.inputFolder + **this.**importFilename,
        },
        scenario02: {
        },
        // etc
    }

I am already using the ‘this’ keyword to access a global property. Is there another keyword I could use to refer to the innermost of several nested objects?

I want some way to refer to the importFilename property from inside of the scenario01 object.

HTML5 Canvas circle has wrong border size

In Figma I have created a shape composed of circular images one next to the other. These images have a radius of 1px. Zooming in, this is what you see:

enter image description here

I am trying to recreate the same component in canvas HTML. Every individual circular avatar is made with:

ctx.save()
ctx.fillStyle = 'white'
ctx.beginPath()
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true)
ctx.strokeStyle = 'white'
if (this.outline) {
  ctx.lineWidth = 1
  ctx.stroke()
}
ctx.closePath()
ctx.clip()
ctx.drawImage(this.image, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2)
ctx.restore()

When zooming in, this is what you see:

enter image description here

As you can see, the outline takes up two pixels. Why? I tried doing ctx.lineWidth = 0.5 but this simply changes the outline’s opacities.

How can I fix it? Thanks.

How to populate dropdown list with MongoDB info, between two different models?

I’m a beginner in web programming and I’m stuck on the basics, specifically MongoDB.So, I have a Device model in which I already have several devices on which I regularly perform CRUD (works good).

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const DeviceSchema = new Schema({
  inventoryNumber: String,
  deviceDescription: String,
  supplier: String,
  price: String,
  comment: String,
  debits: [
    {
      type: Schema.Types.ObjectId,
      ref: "Debit",
    },
  ],
});

module.exports = mongoose.model("Device", DeviceSchema);

Next, I have a Debit model in which it should have info about the Device model.


const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const DebitSchema = new Schema({
  debitDate: String,
  devices: [
    {
      type: Schema.Types.ObjectId,
      ref: "Device",
    },
  ],
  employees: [
    {
      type: Schema.Types.ObjectId,
      ref: "Employee",
    },
  ],
});

module.exports = mongoose.model("Debit", DebitSchema);

When creating a new Debit (using new.ejs), I want to have a dropdown list with data from the Device model within the form (for example: device.deviceDescription).

For example, I have 5 devices (Device) in the database and I want to display them in the dropdown list when creating a new Debit.

So the question is, how to fill the dropdown list with data from Devices, how to connect these two models so that I can see the Devices model from Debits?

Thanks in advance!

I tried iteration but it didn’t work. I’m really stuck.

Why does “Cannot GET” appear when I access the page on google using node, but the route in React works?

I’m building an application with Reactjs and Nodejs and I’ve built all my routes using React-Router-Dom

`

<BrowserRouter>
  <Routes>

    <Route path='/' element={<Home />} />
    <Route path='/receitas' element={<Receitas />} />
    <Route path='/receita/:id' element={<ReceitaPage />} />
    <Route path='/login' element={<Login />} />
    <Route path='/crud' element={<Crud />} />
    <Route path='/ebook/:id' element={<EbookPage />} />

  </Routes>

</BrowserRouter>`

When I move between my pages using the front-end buttons, the site works correctly because either I use the functionality <Link to={}> </Link/> or I use UseNavigate();.

But I’m having problems when I access the site directly with the link, I’ll show you a picture of when I use the button on the page: Image Here

When I access the same link writing in the browser itself, this message appears to me: Second Image Here

The browser recognizes it as another type of route.

I’m using Nodejs for my Back-End and I really don’t know what to do about it. Can anyone help me, why I don’t know if I can fix it using Reactjs or Nodejs?

Why home is not defined?

I am not sure why home is not defined when i do this in app.js? I tried to reference home.js with app.js by adding code

import {home} from "home.js";

into app.js but then i got an error that said “Cannot use import statement outside a module”

Is that reference enough and should i focus my self to solve the second one error?

Index.html

<!DOCTYPE html>
<head>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>

<body>

    <div id="app" class="container">
        <h3 class="d-flex justify-content-center">
            FrontEnd Test
        </h3>
        <h5 class="d-flex justify-content-center">
            Employee Portal
        </h5>

        <nav class="navbar navbar-expand-sm bg-light navbar-dark">
            <ul class="navbar-nav">
                <li class="nav-item m-1">
                    <router-link class="btn btn-light btn-outline-primary"
                    to="/home">Home</router-link>
                </li>
                <li class="nav-item m-1">
                    <router-link class="btn btn-light btn-outline-primary"
                    to="/department">Department</router-link>
                </li>
                <li class="nav-item m-1">
                    <router-link class="btn btn-light btn-outline-primary"
                    to="/employee">Employee</router-link>
                </li>
            </ul>
        </nav>
        <router-view></router-view>
    </div>


   
    <script src="variables.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.4/axios.min.js"></script>
    <script src="https://unpkg.com/vue@3"></script>
    <script src="https://unpkg.com/vue-router@4"></script>   
    <script src="app.js"></script>
    <script src="home.js"></script>
    <script src="department.js"></script>
    <script src="employee.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
    
    
</body>
</html>

home.js

const home = { template: `<h1>This home</h1>` }

app.js

    {path:'/home',component:home},
    {path:'/employee',component:employee},
    {path:'/department',component:department}
]

const router = new VueRouter({
    routes
})

const app = new Vue({
    router
}).$mount('#app')

Suggestion why home is not defined?

Upstream image response failed in Next.js with Medium story API

I’m trying to use the Medium story API to fetch and display an image in my Next.js app, but I keep getting an “upstream image response failed” error. The error message looks like this:

upstream image response failed for https://cdn-images-1.medium.com/max/1024/1*M3RCzNQD96vHtVo0TSphVg.jpeg 403

I’ve checked the URL and it seems to be correct, but I can’t figure out why the image isn’t loading. Can anyone help me diagnose and fix this issue?

Code:

Here is the relevant code that I’m using to fetch and display the image:

articles.jsx

import ArticleCard from '../components/ArticleCard';
import styles from '../styles/ArticlesPage.module.css';

const ArticlesPage = ({ articles }) => {
  return (
    <>
      <h3>
        Recent Posts from{' '}
        <a
          href="https://medium.com/@yasmine.daly"
          target="_blank"
          rel="noopener"
          className={styles.underline}
        >
          Medium
        </a>
      </h3>
      <div className={styles.container}>
        {articles.map((article) => (
          <ArticleCard key={article.id} article={article} />
        ))}
      </div>
    </>
  );
};

export async function getStaticProps() {
  const res = await fetch(
    `https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/@yasmine.daly`
  );

  const data = await res.json();

  return {
    props: { title: 'Articles', articles: data.items },
    revalidate: 60,
  };
}

export default ArticlesPage;

ArticleCard.jsx

import cheerio from 'cheerio';
import Image from 'next/image';
import striptags from 'striptags';
import EyeIcon from '../components/icons/EyeIcon';
import HeartIcon from '../components/icons/HeartIcon';
import CommentIcon from '../components/icons/CommentIcon';
import styles from '../styles/ArticleCard.module.css';

const ArticleCard = ({ article }) => {

  return (
    <div className={styles.container}>
      <a
        href={article.url}
        target="_blank"
        rel="noopener noreferrer"
      >
        <Image
          src={article.thumbnail}
          alt={article.title}
          width={300}
          height={150}
        />
        <h3 className={styles.title}>{article.title}</h3>
      </a>
      <div className={styles.content}>
        <p>{striptags(article.content.substr(0, 300))}...</p>
      </div>
    </div>
  );
};

export default ArticleCard;

Any help or advice would be greatly appreciated. Thank you!

How do position Search box on top of this datatable?

I am trying to position the searchbox outside the datatables on top of my page.

I have created an input search text-box on top but I am not sure how to append the datatables search into my search textbox.

Here is what I have. Please see link to code below. Thanks.

https://live.datatables.net/fofimale/51/edit

var filtered = [];

$(document).ready( function () {

  var table = $('#example').DataTable({
    
paging: false,
scrollX: true,
scrollCollapse: true,
lengthChange: false,
searching: true,
ordering: false,
fixedColumns:   {
            left: 1
},
    

initComplete: function () {
   $.fn.dataTable.ext.search.push(
        function( settings, searchData, index, rowData, counter ) {
            // Don't display rows if nothing is checked
            if (filtered.length === 0) {
                return true;
            } else if (filtered.includes(searchData[1])) {
                 return true;
            }
            return false;
        }
      );
    }
  });
  
  $('.filter').on('change', function() {
    var val = $(this).val();
    var checked = $(this).prop('checked');
    var index = filtered.indexOf( val );
    
    if (checked && index === -1) {
      filtered.push(val);
    } else if (!checked && index > -1) {
      filtered.splice(index, 2);
    }
    //console.log(filtered);
    table.draw();
  });
} );
<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>

    <link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
    <script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script>

    <meta charset=utf-8 />
    <title>DataTables - JS Bin</title>
  </head>
  <body>
    <input type="text" id="myInputTextField">
    <div class="container">
    
      <label><input type="checkbox" class="filter" value="Technical Author" unchecked />Technical Author</label>
      <label><input type="checkbox" class="filter" value="Software Engineer" unchecked />Software Engineer</label>
      <label><input type="checkbox" class="filter" value="System Architect" unchecked />System Architect</label>

      <table id="example" class="display nowrap" width="100%">
        <thead>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </thead>

        <tfoot>
          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
          </tr>
        </tfoot>

        <tbody>
          <tr>
            <td>Tiger Nixon</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>61</td>
            <td>2011/04/25</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Garrett Winters</td>
            <td>Director</td>
            <td>Edinburgh</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Ashton Cox</td>
            <td>Technical Author</td>
            <td>San Francisco</td>
            <td>66</td>
            <td>2009/01/12</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Cedric Kelly</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>22</td>
            <td>2012/03/29</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Jenna Elliott</td>
            <td>Financial Controller</td>
            <td>Edinburgh</td>
            <td>33</td>
            <td>2008/11/28</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Brielle Williamson</td>
            <td>Integration Specialist</td>
            <td>New York</td>
            <td>61</td>
            <td>2012/12/02</td>
            <td>$4,525</td>
          </tr>
          <tr>
            <td>Herrod Chandler</td>
            <td>Sales Assistant</td>
            <td>San Francisco</td>
            <td>59</td>
            <td>2012/08/06</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Rhona Davidson</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>55</td>
            <td>2010/10/14</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Colleen Hurst</td>
            <td>Javascript Developer</td>
            <td>San Francisco</td>
            <td>39</td>
            <td>2009/09/15</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Sonya Frost</td>
            <td>Software Engineer</td>
            <td>Edinburgh</td>
            <td>23</td>
            <td>2008/12/13</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Jena Gaines</td>
            <td>System Architect</td>
            <td>London</td>
            <td>30</td>
            <td>2008/12/19</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Quinn Flynn</td>
            <td>Financial Controller</td>
            <td>Edinburgh</td>
            <td>22</td>
            <td>2013/03/03</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Charde Marshall</td>
            <td>Regional Director</td>
            <td>San Francisco</td>
            <td>36</td>
            <td>2008/10/16</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Haley Kennedy</td>
            <td>Senior Marketing Designer</td>
            <td>London</td>
            <td>43</td>
            <td>2012/12/18</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Tatyana Fitzpatrick</td>
            <td>Regional Director</td>
            <td>London</td>
            <td>19</td>
            <td>2010/03/17</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Michael Silva</td>
            <td>Senior Marketing Designer</td>
            <td>London</td>
            <td>66</td>
            <td>2012/11/27</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Paul Byrd</td>
            <td>Javascript Developer</td>
            <td>New York</td>
            <td>64</td>
            <td>2010/06/09</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Gloria Little</td>
            <td>Systems Administrator</td>
            <td>New York</td>
            <td>59</td>
            <td>2009/04/10</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Bradley Greer</td>
            <td>Software Engineer</td>
            <td>London</td>
            <td>41</td>
            <td>2012/10/13</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Dai Rios</td>
            <td>System Architect</td>
            <td>Edinburgh</td>
            <td>35</td>
            <td>2012/09/26</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Jenette Caldwell</td>
            <td>Financial Controller</td>
            <td>New York</td>
            <td>30</td>
            <td>2011/09/03</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Yuri Berry</td>
            <td>System Architect</td>
            <td>New York</td>
            <td>40</td>
            <td>2009/06/25</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Caesar Vance</td>
            <td>Technical Author</td>
            <td>New York</td>
            <td>21</td>
            <td>2011/12/12</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Doris Wilder</td>
            <td>Sales Assistant</td>
            <td>Edinburgh</td>
            <td>23</td>
            <td>2010/09/20</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Angelica Ramos</td>
            <td>System Architect</td>
            <td>London</td>
            <td>36</td>
            <td>2009/10/09</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Gavin Joyce</td>
            <td>Developer</td>
            <td>Edinburgh</td>
            <td>42</td>
            <td>2010/12/22</td>
            <td>$4,525</td>
          </tr>
          <tr>
            <td>Jennifer Chang</td>
            <td>Regional Director</td>
            <td>London</td>
            <td>28</td>
            <td>2010/11/14</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Brenden Wagner</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>18</td>
            <td>2011/06/07</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Ebony Grimes</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>48</td>
            <td>2010/03/11</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Russell Chavez</td>
            <td>Director</td>
            <td>Edinburgh</td>
            <td>20</td>
            <td>2011/08/14</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Michelle House</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>37</td>
            <td>2011/06/02</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Suki Burks</td>
            <td>Developer</td>
            <td>London</td>
            <td>53</td>
            <td>2009/10/22</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Prescott Bartlett</td>
            <td>Technical Author</td>
            <td>London</td>
            <td>27</td>
            <td>2011/05/07</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Gavin Cortez</td>
            <td>Technical Author</td>
            <td>San Francisco</td>
            <td>22</td>
            <td>2008/10/26</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Martena Mccray</td>
            <td>Integration Specialist</td>
            <td>Edinburgh</td>
            <td>46</td>
            <td>2011/03/09</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Unity Butler</td>
            <td>Senior Marketing Designer</td>
            <td>San Francisco</td>
            <td>47</td>
            <td>2009/12/09</td>
            <td>$3,750</td>
          </tr>
          <tr>
            <td>Howard Hatfield</td>
            <td>Financial Controller</td>
            <td>San Francisco</td>
            <td>51</td>
            <td>2008/12/16</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Hope Fuentes</td>
            <td>Financial Controller</td>
            <td>San Francisco</td>
            <td>41</td>
            <td>2010/02/12</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Vivian Harrell</td>
            <td>System Architect</td>
            <td>San Francisco</td>
            <td>62</td>
            <td>2009/02/14</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Timothy Mooney</td>
            <td>Financial Controller</td>
            <td>London</td>
            <td>37</td>
            <td>2008/12/11</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Jackson Bradshaw</td>
            <td>Director</td>
            <td>New York</td>
            <td>65</td>
            <td>2008/09/26</td>
            <td>$5,000</td>
          </tr>
          <tr>
            <td>Miriam Weiss</td>
            <td>Support Engineer</td>
            <td>Edinburgh</td>
            <td>64</td>
            <td>2011/02/03</td>
            <td>$4,965</td>
          </tr>
          <tr>
            <td>Bruno Nash</td>
            <td>Software Engineer</td>
            <td>London</td>
            <td>38</td>
            <td>2011/05/03</td>
            <td>$4,200</td>
          </tr>
          <tr>
            <td>Odessa Jackson</td>
            <td>Support Engineer</td>
            <td>Edinburgh</td>
            <td>37</td>
            <td>2009/08/19</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Thor Walton</td>
            <td>Developer</td>
            <td>New York</td>
            <td>61</td>
            <td>2013/08/11</td>
            <td>$3,600</td>
          </tr>
          <tr>
            <td>Finn Camacho</td>
            <td>Support Engineer</td>
            <td>San Francisco</td>
            <td>47</td>
            <td>2009/07/07</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Elton Baldwin</td>
            <td>Data Coordinator</td>
            <td>Edinburgh</td>
            <td>64</td>
            <td>2012/04/09</td>
            <td>$6,730</td>
          </tr>
          <tr>
            <td>Zenaida Frank</td>
            <td>Software Engineer</td>
            <td>New York</td>
            <td>63</td>
            <td>2010/01/04</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Zorita Serrano</td>
            <td>Software Engineer</td>
            <td>San Francisco</td>
            <td>56</td>
            <td>2012/06/01</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Jennifer Acosta</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>43</td>
            <td>2013/02/01</td>
            <td>$2,875</td>
          </tr>
          <tr>
            <td>Cara Stevens</td>
            <td>Sales Assistant</td>
            <td>New York</td>
            <td>46</td>
            <td>2011/12/06</td>
            <td>$4,800</td>
          </tr>
          <tr>
            <td>Hermione Butler</td>
            <td>Director</td>
            <td>London</td>
            <td>47</td>
            <td>2011/03/21</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Lael Greer</td>
            <td>Systems Administrator</td>
            <td>London</td>
            <td>21</td>
            <td>2009/02/27</td>
            <td>$3,120</td>
          </tr>
          <tr>
            <td>Jonas Alexander</td>
            <td>Developer</td>
            <td>San Francisco</td>
            <td>30</td>
            <td>2010/07/14</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Shad Decker</td>
            <td>Regional Director</td>
            <td>Edinburgh</td>
            <td>51</td>
            <td>2008/11/13</td>
            <td>$5,300</td>
          </tr>
          <tr>
            <td>Michael Bruce</td>
            <td>Javascript Developer</td>
            <td>Edinburgh</td>
            <td>29</td>
            <td>2011/06/27</td>
            <td>$4,080</td>
          </tr>
          <tr>
            <td>Donna Snider</td>
            <td>System Architect</td>
            <td>New York</td>
            <td>27</td>
            <td>2011/01/25</td>
            <td>$3,120</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>
</html>

Webpage loading a big image and it appears as if the image is not loading and title / image are mismatched

This is a tricky issue and may not be easy to solve.

The issue is, for our current system, the images / photos are very big, such as 5MB or 6MB each, and even though we may have a system to convert them into thumbnail and smaller images, such as 50kb or 150kb, it may still be a few months away and not in our control.

If we have vanilla JavaScript to load a second image, such as in an image preview modal on the webpage, when the user clicks on “Toggle” to see the next image (and Toggle again to see the next image), there are two issues:

  1. the title and image mismatch with each other

  2. the user cannot know that the image is being loaded. It is as if there is no reaction after clicking

The code is:

        document
          .querySelector("#toggle-button")
          .addEventListener("click", () => {
            toggle = !toggle;
            filename = `${toggle ? "beach.jpg" : "mountain.jpg"}?${Date.now()}`;
            elMsg.innerHTML = `<span>Title is ${
              toggle ? "Beach" : "Mountain and Lake"
            }</span>`;
            elImage.src = filename;
          });

and you can try the code here:
https://codesandbox.io/s/awesome-morse-3cu2st?file=/index.html

To make the effect more obvious, please go to DevTool on Google Chrome, and then Network Tab, and change the “No Throttling” to “Slow 3G” speed.

Then you will see issue #1 and issue #2 mentioned above.

Note that here, I am using a Date.now() to attach to the filename, so that the image URL is:

https://3cu2st.csb.app/mountain.jpg?1678390253200

so as to bust the cache, for demo purpose to show the two issues.

It is the same if I use React, with the code:

function App() {
  const [toggle, setToggle] = useState(true);

  const imageFilename = `${
    toggle ? "beach.jpg" : "mountain.jpg"
  }?${Date.now()}`;

  return (
    <div className="App">
      <div id="msg">
        <span>toggle is {JSON.stringify(toggle)}</span>
        <span>imageFilename is {imageFilename}</span>
        <span>Title is {toggle ? "Beach" : "Mountain and Lake"}</span>
        <button onClick={() => setToggle((f) => !f)}>Toggle</button>
      </div>
      <img src={imageFilename} alt="a big file" />
    </div>
  );
}

You can try it here:
https://codesandbox.io/s/relaxed-heyrovsky-pi8unt?file=/src/App.js

Image 2 (mountain.jpg) is about 1.5MB, and the issue is more profound if the file is like 5MB or 6MB.

So what is a good way to handle this? If possible, I’d hope not to use complicated methods, such as using a spinner and use a two step method perhaps to first show a blank image placeholder, and then set the src to the new one… because it is such an overkill for the purpose of just showing an image.

If it is Vanilla JavaScript, I did think of one quick method, which is to replace the whole <img /> each time:

elImageContainer.innerHTML = `<img src="${filename}" />`;

You can try it at
https://codesandbox.io/s/bold-waterfall-xuhw1m?file=/index.html

But I don’t think it can be done in React, which is what the project is using, because I think the new virtual DOM is created and is diff’ed with the previous virtual DOM, and there is no way to tell whether it is a new <img /> element like in the Vanilla JavaScript case.

Is there a good solution to this?

Attempting to set up firebase and firestore with electron

I wish to set up a firestore in order to run a simple global chat application. I currently have a main.js file with the following;

// Electron code above removed.

const fireapp = firebase.initializeApp(firebaseConfig)

// Get a Firestore instance
let firestore = firebase.firestore();

// Reference to the 'messages' collection
const messagesRef = firestore.collection('messages')

// Submit message to Firestore
messageForm.addEventListener('submit', (event) => {
  event.preventDefault() // prevent page reload on form submission

  const message = messageInput.value
  if (!message || message.length < 2) { return } 
  messageInput.value = '' // clear the input field after sending the message

  // Append the sent message to the console body
  const sentMessage = document.createElement('p')
  sentMessage.textContent = `YOU > ${message}`
  sentMessage.classList.add('sent-message')
  consoleBody.appendChild(sentMessage)
  consoleBody.scrollTop = consoleBody.scrollHeight

  // Save message to Firestore
  messagesRef.add({
    sender: 'YOU',
    text: message
  })
})

// Listen for new messages in Firestore
messagesRef.onSnapshot((querySnapshot) => {
  querySnapshot.forEach((doc) => {
    const message = doc.data()

    // Append the received message to the console body
    const receivedMessage = document.createElement('p')
    receivedMessage.textContent = `${message.sender} > ${message.text}`
    consoleBody.appendChild(receivedMessage)
    consoleBody.scrollTop = consoleBody.scrollHeight
  })
})

Executing this resulted in the error
“firebase.firestore is not a function”

I have no idea how to fix this; as I was expecting it to just work.

Conditional Route immediately executes inside Switch

I have a Switch with a series of Route elements in my main container:

AppContainer.js

<Switch>
  <Route exact path={`/app/:slug/`}>
    <Redirect to={`/app/${slug}/home`} />
  </Route>
  <ProtectedRoute
    path='/app/:slug/userAdmin/'
    component={UserAdminContainer}
    message={'This page is read-only'}
  />
  [snip]
  <Route
    path='/app/:kappSlug/protectedRoute/'
    render={(props) => (
      <ReadOnlyError message={props.message} />
    )}
  />
</Switch>

Along with the ProtectedRoute.js

const ProtectedRoute = (props) => {
  const { message } = props;
  const { isReadOnlyUser } = useUser();
    
  return (
    isReadOnlyUser
      ?
        <Redirect
          to={{
            pathname: '/app/:kappSlug/protectedRoute/',
            state: {message}
          }}
        />
      : <Route {...props} />
  )
}

My problem is that when AppContainer renders, it is then immediately redirected to the ProtectedRoute of "/admin", when it should only render if that button was hit. I’m a longtime Java dev, brand new to React. I’m sure there’s something about the rendering process I’m not understanding.

woocommerce_form_field in Checkout, not being included in wc-ajax=checkout call?

I have tried for days adding an additional field to my checkout page, but it isn’t working.

I have successfully displayed the field just after the additional notes as expected. BUT, when submitting the form with “Place Order” button, with the field filled in, the “empty field error” displays.

I can see that when reviewing the $_POST data in Firebug, the field does not exist within the data.

Below is the HTML generated by WordPress including my custom field.

<div class="woocommerce-additional-fields">
    <h3>Additional information</h3>
    <div class="woocommerce-additional-fields__field-wrapper">
        <p class="form-row notes" id="order_comments_field" data-priority=""><label for="order_comments" class="">Order notes&nbsp;<span class="optional">(optional)</span></label><span class="woocommerce-input-wrapper"><textarea name="order_comments" class="input-text " id="order_comments" placeholder="Notes about your order, e.g. special notes for delivery."  cols="5"rows="4"></textarea></span></p>
    </div>

    <div id="my_custom_checkout_field">
    <h2>My Field</h2>
        <p class="form-row my-field-class form-row-wide" id="my_field_name_field" data-priority=""><label for="my_field_name" class="">Fill in this field&nbsp;<span class="optional">(optional)</span></label><span class="woocommerce-input-wrapper"><input type="text" class="input-text " name="my_field_name" id="my_field_name" placeholder="Enter something"  value=""  /></span></p>
    </div>
</div>
      

To try and simplify this as much as possible, I am now using JUST the code provided by the WC docs.

Below is the code included within functions.php:


/**
 * Add the field to the checkout
 */
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );

function my_custom_checkout_field( $checkout ) {

    echo '<div id="my_custom_checkout_field"><h2>' . __('My Field') . '</h2>';

    woocommerce_form_field( 'my_field_name', array(
        'type'          => 'text',
        'class'         => array('my-field-class form-row-wide'),
        'label'         => __('Fill in this field'),
        'placeholder'   => __('Enter something'),
        ), $checkout->get_value( 'my_field_name' ));

    echo '</div>';

}

/**
 * Process the checkout
 */
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');

function my_custom_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['my_field_name'] )
        wc_add_notice( __( 'Please enter something into this new shiny field.' ), 'error' );
}

The only other variable in this cart design, is that I am using the Square Payments Gateway Plugin.

**Additionally, in my original personalized code, I am requiring this field. Thank you for any advise!

Advice on backend structure for multiple apps and integrations

I’m looking for some architecture/structure advice for a company I’m working for.

The company has several web apps and websites:

  • 3 marketing websites with contact and registration forms
  • 4 customer platforms. Each platform is specific to one of their products
  • 1 sales tool which can be used by potential customers or sales agents to make several offers.
  • 1 customer relationship management (CRM) to follow up all products, support tickets, internal tasks, dashboard graphs, customer data, generate exports

At this point all these apps have their own frontend and backend which leads to a lot of duplicate code and hard to maintain. Think of helpers functions, validation rules, mongoose models, database CRUD operations.

I’m going to try and tell a bit about the different parts in what – in my opinion – can be important information.

The sales tool and marketing websites are using api-keys to send and receive data to a backend. The customer platforms are using an api-key for public routes and an api-key + user based access token for private customer routes. The CRM is used by employees and external partners. Authorization is done with a user based access token.

The next step in the journey is to create integrations with several partners (sales channels, subcontractors). They will push data into the system and will have access to read data from customers to which they are assigned.

Based on this information I would like to receive advice about making one api or splitting them in something like an internal, customer and partner api. If we split, is there a way to reuse helper functions, CRUD operations and mongoose Models? If it’s one big api, how can we take control of all the routes? For example /contracts from a user perspective will return all the contracts of that user but from the perspective of a partner or employee /contracts will be a paginated result of 50 contracts while /customers/:customerId/contracts will lead to the contracts of a specific customer. In addition, a partner may get less data back at this endpoint than if the call from the crm is done by an employee.

One thing to keep in mind is that there are some cron jobs for sending out emails, creating reports, clean up data and generating exports. These tasks are taking some memory and cpu. Platforms should not be inconvenienced by these actions.

Frontends are currently build with React. Backends with ExpressJS/NodeJS

Prepared statement only executes once, until I delete my broser’s cache

For a list of events, I dynamically create buttons for entering whether the user can attend the event or not. I add EventListeners to the buttons, so that they execute prepared statements when clicked.
The “no”-button works at the first time, inserting a row into table ‘absences’, but if the user clicks “no”, then “yes” (which deletes the row) and then “no” again, the second “no” does not insert a row into the database again.

Here’s how the EventListeners for the “no”-buttons are created (while looping through the date_ids):

btn_no.addEventListener('click', (function(date_id) {
    return async function() {
        var return_value;

           var data = {date_id: date_id,
                        user_id: user["user_id"],
                        isAbsent: 1};
            return_value = await preparedInsert("absences", data);
        

        if (return_value != "") { // error
            try {alert("Error: " + JSON.parse(return_value));}
            catch {alert("Error: " + return_value);}
            return;
        }


        // .. here follows styling of the affected dates in the list
    }
})(date_id));

The js-function preparedInsert() looks like this:

function preparedInsert(table_name,data) {
    var t = encodeURIComponent(table_name);
    var d = encodeURIComponent(JSON.stringify(data));

    return new Promise( resolve => {
        request = new XMLHttpRequest();
        request.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                resolve(this.responseText);
            }
        }
        request.open("GET", "includes/preparedInsert.inc.php?t="+t+"&d="+d);
        request.send();
    } );
}

Lastly, preparedInsert.inc.php:

<?php
    include "dbh.inc.php"; // get $conn

    $table_name = $_GET["t"];
    $data       = json_decode($_GET["d"]);

    $types = "";
    $columns = "";
    $placeholders = "";
    $values = [];
    foreach ($data as $key => $value) {
        $types .= "s";
        $columns .= $key . ",";
        $placeholders .= "?,";
        $values[] = $value;
    }
    $columns = substr($columns, 0, -1); // delete trailing comma
    $placeholders = substr($placeholders, 0, -1); // delete trailing comma
    $sql = "INSERT INTO $table_name ($columns) VALUES ($placeholders)";
    // INSERT INTO table_name (column1, column2, ...) VALUES (?, ?, ...);

    try {
        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$values);
        $stmt->execute();
    } catch (mysqli_sql_exception $e) {
        echo "Error: " . $e;
    }

    if ($conn->error) {echo json_encode($conn->error);}

No errors are thrown anywhere: I tried adding $driver = new mysqli_driver(); $driver->report_mode = MYSQLI_REPORT_ALL;, mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); and error_reporting(E_ALL); to the top of preparedInsert.inc.php but got no errors.

Every function seems to run as intended: I tried adding console-logging or echoing everywhere and it always works.

The “no”-button only works again when I clear my browser’s cache, so I’d guess it has to do with the caching of prepared statements? But I don’t understand them well enough to see why it wouldn’t execute the same query a second time.

For some reason, the equally-created “yes”-button works perfectly twice. In case it hints to a notable difference, here’s its EventListener:

btn_yes.addEventListener('click', (function(date_id) {
    return async function() {
        var absence = user["absences"][date_id];

        var condition = {absence_id: absence["absence_id"]};
        var return_value = await preparedDelete("absences", condition);

        if (return_value != "") { // error
            try {alert("Error: " + JSON.parse(return_value));}
            catch {alert("Error: " + return_value);}
            return;
        }

        // .. here follows styling the affected dates in the list
    }
})(date_id));

..and the preparedDelete.inc.php that’s opened in the quasi-identical js-function preparedDelete():

<?php
    include "dbh.inc.php"; // get $conn

    $table_name = $_GET["t"];
    $conditions = json_decode($_GET["c"]);

    $types = "";
    $placeholder_string = "";
    $values = [];
    foreach ($conditions as $key => $value) {
        $types .= "s";
        $placeholder_string .= $key . " = ? AND ";
        $values[] = $value;
    }
    $placeholder_string = substr($placeholder_string, 0, -4); // delete trailing AND
    $sql = "DELETE FROM $table_name WHERE $placeholder_string";
    // DELETE FROM $table_name WHERE key1 = ? AND key2 = ? AND...

    try {
        $stmt = $conn->prepare($sql);
        $stmt->bind_param($types, ...$values);
        $stmt->execute();
    } catch (mysqli_sql_exception $e) {
        echo "Fehler: " . $e;
    }

    if ($conn->error) {echo json_encode($conn->error);}