which framework, angular or react? [closed]

I have a programming project, I am a student at a high school and it is based on the web, but I have a big dilemma when choosing the framework to work with, whether to work with Angular or React, which I have seen are the most used.

I really hope to learn how to work with the framework that I really hope to adapt to the framework, since I had only programmed locally with C# and C++.

how to implement nested javascript

I have a external js : math.js

My new project needs the math.js in multiple nested external js files.

I have external chart.js how needs math.js but also calculate.js

My main html loads chart.js and calculate.js

But I want if charts.js or calculate.js is loaded in a main html it loads also
math.js

Do not know the syntax to include only once the script if needed

How to use parameters in proxy

Facing a problem with proxying a parameter:

const Proxy = createProxyMiddleware({
target:’https://api.somesite.com/api/v2/mix/api?productType=GRID’,
changeOrigin: true,
}); app.use(‘/api’, Proxy);

app.listen(3004, () => { console.log(Proxy server is running at http://localhost:${3004}); });

The problem is that once I am making a request I’m getting a message like: “code”: “40019”,
“msg”: “Parameter GRID/ cannot be empty”,
“data”: null }

Is there a workaround?

A border appears on table header separating columns when on a high screen resolution

I have a table on my website that is just perfect on my default screen resolution (1400×800). The problem arrises whenever I set the screen to a higher resolution, like 3840×2160. Whenever I set the screen to that resolution, a border appears on my table header separating the columns. Here are some screenshots:

  1. Default screen resolution (1400×800):
    enter image description here

  2. Higher screen resolution (3840×2160:
    enter image description here

I’m using the table from shadcn and there are no styles applying borders or box shadow or anything. I spent almost 30 minutes applying styles to remove every kind of border/shadow/anything to pretty much all the elements (thead, tr, table).

Is this the default behavior for a 4K screen or why does this border shows up on a higher resolution screen?

Creating polygons on the map

It is necessary to implement a map that can be scaled and that will correspond to reality (for example, Google Maps), but it is also necessary to add the ability to mark areas to it, ideally to make it so that a person can poke at a road, for example, and an area is created that covers this entire road by its name, but this is not necessary, you can make a multi-area by the sequence of user marks. Also, the ability to create areas on another area is needed, that is, there may be an overlap. How can I implement this on ASP .NET Core, as I understand it, only js is probably here. Recommend libraries to solve my problem, preferably with a code example. Polygons should be editable (color, opacity)

How to stop the results repeating and keep updated record from the cart array?

This code shows the details of the products added. when i add another product it keeps the older record too and display old and new records.

I want to display only the current details of all the products added to cart.

document.querySelector(".js-cart-list").innerHTML +=
        itemsDetails.cartProductName +
        " Quantity: " +
        itemsDetails.quantity +
        " Product ID: " +
        itemsDetails.productId +
        "<br>";
 <p>List:<span class="js-cart-list"></span></p>

HTTP only cookie is not being sent from client side

I am running an express JS restful API on my backend that generates a JWT when a user is successfully authenticated via the /api/user/auth endpoint. I am sending the cookie back to the client via the res.cookie function and setting the flag as http only in the options parameter. On the client side/browser I am able to see the token being sent back in the set cookie response header from the server but when i check the application tab on chrome dev tools the token is not present. When i send subsequent http request from the client side using fetch it is sending a sessionid cookie ? Instead of the the token.
Fetch Request

Fetch request to /applications endpoint

Session id being inserted into /application http request ? (dont know why)

jwt is being specified in the set cookie header of the request to /user/auth

/user/auth endpoint controller

Middleware set up

/application router controller

Console output on /application route

Getting problems in selecting options in a Dropdown

This is the part I use to dynamicly create a Dropdown.

// Helper: Create Dropdown
const createDropdown = (id, options, selectedOption = [], labelText, isMultiSelect = false) => {
  console.log(`Creating dropdown for ${labelText} with ID: ${id}`);
  console.log(`Initial selectedOption:`, selectedOption);
  console.log(`Options provided:`, options);
  console.log(`Multi-select: ${isMultiSelect}`);

  const container = document.createElement("div");
  container.classList.add("dropdown-container");

  // Create the dropdown HTML
  container.innerHTML = `
    <label for="${id}" class="dropdown-label">${labelText}</label>
    <div class="select" id="${id}">
      <div class="selected">
        ${isMultiSelect ? 
          (selectedOption.length > 0 ? selectedOption.map(option => `<span class="selected-item">${option}</span>`).join('') : "Select options") :
          (selectedOption.length > 0 ? `<span class="selected-item">${selectedOption}</span>` : "Select an option")
        }
      </div>
      <div class="options">
        ${options.map(option => `
          <div>
            ${isMultiSelect ? 
              `<input type="checkbox" id="${id}-${option}" name="${id}" value="${option}" ${selectedOption.includes(option) ? "checked" : ""}>`
              :
              `<input type="radio" id="${id}-${option}" name="${id}" value="${option}" ${selectedOption[0] === option ? "checked" : ""}>`
            }
            <label class="option" for="${id}-${option}" role="option" aria-selected="${selectedOption.includes(option)}">${option}</label>
          </div>`).join("")}
      </div>
    </div>`;

  // Debugging log for container creation
  console.log('Created dropdown container:', container);

  const inputs = container.querySelectorAll('input');
  console.log('Attached inputs:', inputs); // Log to ensure inputs are selected

  // Handle single-select (radio button change event) with event delegation
  container.addEventListener('change', (e) => {
    console.log("Inside Event Listener");
    // Check if the event target is a radio input
    if (!isMultiSelect && e.target.type === 'radio') {
      console.log("Single-select change detected:");
      console.log("Previously selected option:", selectedOption);
      console.log("Currently selected option:", e.target.value);

      // Update selectedOption when a radio button is selected
      selectedOption = [e.target.value];

      // Update the selected text to reflect the new selection
      const selectedText = container.querySelector(".selected");
      if (selectedText) {
        selectedText.innerHTML = `<span class="selected-item">${e.target.value}</span>`;
        console.log("Updated selected value (single-select):", selectedOption);
      }

      // Update the aria-selected attribute for all options
      const labels = container.querySelectorAll('.option');
      labels.forEach(label => {
        label.setAttribute('aria-selected', label.getAttribute('for') === `${id}-${e.target.value}`);
      });
    }
  });

  // Add event listeners to all radio buttons
  inputs.forEach(input => {
    input.addEventListener('change', (e) => {
      if (e.target.type === 'radio') {
        console.log('Radio button changed:', e.target.value);
      }
    });
  });

  return container;
};

Now the weird thing is, That When I first load the page, The Dropdown in CreateEntity works;

// Create Entity 
function entityCreateModal(entityType) {
  const modal = document.getElementById('entityCreateModal');
  const title = document.getElementById('entityCreateModalTitle');
  const promptMessageContainer = modal.querySelector('.entity-create-message');
  const submitButton = modal.querySelector('.submit-button');
  promptMessageContainer.innerHTML = '';  // Clear previous content

  // Function to handle entity creation and confirmation
  const createEntity = (entityName, entityData) => {
    window.openConfirmationModal('create', () => {
      saveEntityData(entityName, entityData);
      closeModal(modal.querySelector('#modal-close-button'), '#entityCreateModal');
      location.reload();
    }, entityName);
  };


  // Call handleFileUpload for Teacher and Student
  if (entityType === 'teacher' || entityType === 'student') {
    handleFileUpload({}, '#entityCreateModal');
  }

  // Switch based on entity type
  switch (entityType) {
    case 'teacher': {
      title.textContent = "Create Teacher";
      const teacherIdField = createTextField('teacherId', '', 'Teacher ID');
      const usernameField = createTextField('username', '', 'Username');
      const emailField = createTextField('email', '', 'Email ID');
      const genderDropdown = createDropdown('gender', ['Male', 'Female', 'Other'], 'Select Gender', 'Select Gender:');
      const curriculumDropdown = createDropdown('curriculum', ['CBSE', 'IPYP', 'IGCSE', 'IBDP'], 'Select Curriculum', 'Select Curriculum:');
      const gradeDropdown = createDropdown('grade', ['PRE NURSERY', 'NURSERY', 'LKG', 'UKG', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI-SCI', 'XI-COM', 'XI-HUM', 'XII-SCI', 'XII-COM', 'XII-HUM'], 'Select Grade', 'Select Grade:');
      promptMessageContainer.innerHTML = '<p>Please enter the details for the new Teacher.</p>';
      [teacherIdField, usernameField, emailField, genderDropdown, curriculumDropdown, gradeDropdown].forEach(field => promptMessageContainer.appendChild(field));
      createEntity('teacher', {});
      break;
    }

    case 'student': {
      title.textContent = "Create Student";
      const studentIdField = createTextField('studentId', '', 'Student ID');
      const studentNameField = createTextField('studentName', '', 'Student Name');
      const curriculumDropdown = createDropdown('curriculum', ['CBSE', 'IPYP', 'IGCSE', 'IBDP'], 'Select Curriculum', 'Select Curriculum:');
      const gradeDropdown = createDropdown('grade', ['PRE NURSERY', 'NURSERY', 'LKG', 'UKG', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII'], 'Select Grade', 'Select Grade:');
      const boardingDropdown = createDropdown('boarding', ['Day Boarder', 'Hostelite'], 'Select Boarding', 'Select Boarding:');
      const houseDropdown = createDropdown('house', ['Kingfisher (Blue)', 'Ibis (Red)', 'Token (Green)', 'Iora (Yellow)'], 'Select House', 'Select House:');
      const genderDropdown = createDropdown('gender', ['Male', 'Female', 'Other'], 'Select Gender', 'Select Gender:');
      const emailField = createTextField('email', '', 'Email ID');
      const bloodGroupDropdown = createDropdown('bloodGroup', ['A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', 'O+', 'O-'], 'Select Blood Group', 'Select Blood Group:');
      
      promptMessageContainer.innerHTML = '<p>Please enter the appropriate details for the new Student.</p>';
      
      // Append common fields
      [studentIdField, studentNameField, curriculumDropdown, gradeDropdown, genderDropdown, houseDropdown, boardingDropdown, bloodGroupDropdown, emailField].forEach(field => promptMessageContainer.appendChild(field));
    
      // Stream dropdown logic
      let streamDropdown = null;  // Declare the streamDropdown outside
    
      // Log the gradeDropdown element for inspection
      console.log("Grade Dropdown Element:", gradeDropdown); 
    
      gradeDropdown.addEventListener('change', () => {
        const selectedGrade = gradeDropdown.value;
    
        console.log("Inside change event listener");
        console.log("Selected Grade:", selectedGrade); 
    
        // Check for initial event or empty selection
        if (selectedGrade === '' || selectedGrade === undefined) {
          console.log('Initial event or empty selection. Ignoring.');
          return;
        }
    
        console.log('Dropdown changed. Selected value(s):', selectedGrade); 
        console.log('Grade dropdown change event triggered!');
        console.log('Grade dropdown value on change:', selectedGrade);
    
        // Proceed with the rest of your logic
        if (selectedGrade === 'XI' || selectedGrade === 'XII') {
          console.log('Grade is either XI or XII.');
    
          if (!streamDropdown) {
            console.log('Stream dropdown is being created and added to the DOM.');
            streamDropdown = createDropdown('stream', ['Science', 'Commerce', 'Humanities'], 'Select Stream', 'Select Stream:');
            promptMessageContainer.insertBefore(streamDropdown, boardingDropdown);  // Insert Stream just after Grade
          } else {
            console.log('Stream dropdown already exists in the DOM.');
          }
        } else {
          console.log('Grade is not XI or XII. Removing Stream dropdown if it exists.');
    
          if (streamDropdown) {
            console.log('Removing the Stream dropdown from the DOM.');
            promptMessageContainer.removeChild(streamDropdown);
            streamDropdown = null;
          } else {
            console.log('No Stream dropdown exists to remove.');
          }
        }
      });
    
      break;
    }
   

    case 'ticket': {
      title.textContent = "Create Ticket";
    
      const dropdown = createDropdown('affectedSystem', ['Admin Dashboard', 'Student Panel', 'Exams', 'Fees', 'Notices', 'Forget Password', 'Reset Password'],'Select a System', 'Select System:');      
      promptMessageContainer.innerHTML = '<p>Which system or component are you experiencing issues with?</p>';
      promptMessageContainer.appendChild(dropdown);
    
      submitButton.addEventListener('click', (event) => {
        event.preventDefault();
    
        const selectedSystem = dropdown.querySelector('.selected')?.textContent;
    
        if (!selectedSystem || selectedSystem === 'Select a System') {
          return alert("Please select a valid system.");
        }
    
        const [day, month, year] = new Date().toLocaleDateString('en-GB', { timeZone: 'Asia/Kolkata' }).split('/');
        const [hour, minute] = new Date().toLocaleTimeString('en-GB', { timeZone: 'Asia/Kolkata', hourCycle: 'h23' }).split(':');
        const ticketId = `T${year}${month.padStart(2, '0')}${day.padStart(2, '0')}${hour}${minute}`;
        
        const createdBy = sessionStorage.getItem("TeacherID") || "Unknown";
        const createdAt = `${day} ${new Date().toLocaleString('default', { month: 'long' })} ${year} - ${hour}:${minute}`;
        
        const priority = {
          'Admin Dashboard': 'High', 'Student Panel': 'High', 'Exams': 'High',
          'Fees': 'High', 'Notices': 'High', 'Forget Password': 'Medium',
          'Reset Password': 'Medium'
        }[selectedSystem] || 'Low';
    
        createEntity('ticket', { ticketId, createdBy, createdAt, affectedSystem: selectedSystem, status: "Open", priority });
      });
    
      break;
    }
        
    case 'system': {
      title.textContent = "Create System";
      const priorityDropdown = createDropdown('priority', ['Low', 'Medium', 'High'], 'Select Priority', 'Select Priority:');
      const systemIdField = createTextField('systemId', '', 'System ID');
      const systemNameField = createTextField('systemName', '', 'System Name');
      promptMessageContainer.innerHTML = '<p>Please enter the appropriate details for the new System.</p>';
      [systemIdField, systemNameField, priorityDropdown].forEach(field => promptMessageContainer.appendChild(field));

      // Move the listener attachment here to ensure it only runs once
      const submitHandler = (event) => {
        event.preventDefault();
        const selectedPriority = priorityDropdown.querySelector('.selected')?.textContent;

        if (!selectedPriority || selectedPriority === 'Select Priority') {
          return alert("Please select a valid priority.");
        }

        const systemId = systemIdField.querySelector("input")?.value.trim() || '';
        const systemName = systemNameField.querySelector("input")?.value.trim() || '';

        if (!systemId || !systemName) {
          return alert("Please enter both system ID and system name.");
        }

        createEntity('system', { systemId, systemName, status: 'Operational', priority: selectedPriority });
      };

      // Attach the listener after everything is ready
      submitButton.removeEventListener('click', submitHandler); // Prevent duplicate listeners
      submitButton.addEventListener('click', submitHandler);
      break;
    }

    default:
      console.error(`Unsupported entity type: ${entityType}`);
  }

  // Open modal and prevent background scroll
  modal.style.zIndex = '5';
  modal.style.display = 'flex';
  document.body.style.overflow = 'hidden';

  // Close modal
  document.getElementById('modal-close-button').addEventListener('click', () => closeModal(modal.querySelector('#modal-close-button'), '#entityCreateModal'));
}

But After I open the Edit Modal, and Try selecting an option there, It bricks both dropdowns (Edit & Create)

// Edit Modal
function openEditModal(entityType, entityData = {}) {
  const modal = document.getElementById("editModal");
  const form = document.getElementById("editModalForm");
  const closeButton = document.getElementById("editModalCloseButton");
  const saveButton = document.querySelector(".save-button");
  const deleteButton = document.querySelector(".edit-modal-delete-button");

  const titles = {
    ticket: "Edit Ticket",
    teacher: "Edit Teacher",
    student: "Edit Student",
    system: "Edit System"
  };

  const fields = {
    teacher: [
      ["Teacher ID", "teacherId"],
      ["Name", "name"],
      ["Username", "username"],
      ["Email", "email"],
      ["Gender", "gender"],
      ["Role", "role", ["Administrator", "IT Department", "Admission Department", "Accounts Department", "Discipline Committee", "Grade Coordinator", "Advisor", "Heads of Department", "Exam Department", "Class Teacher", "Subject Teacher"], true] // Multi-select for Role
    ],
    student: [
      ["Name", "name"],
      ["Student ID", "studentId"],
      ["Enrollment Status", "enrollmentStatus", ['Currently Studying', 'Transferred', 'Suspended', 'Graduated']]
    ],
    system: [
      ["System Name", "systemName"],
      ["Status", "status", ["Operational", "EP", "Down"]],
      ["Priority", "priority", ["High", "Medium", "Low"]]
    ],
    ticket: [
      ["Affected System", "affectedSystem"],
      ["Status", "status", ["Open", "In Progress", "Closed"]]
    ]
  };

  if (!fields[entityType]) {
    console.error("Unknown entity type:", entityType);
    return;
  }

  form.innerHTML = ""; // Reset form

  // Create form fields for the rest of the data
  fields[entityType].forEach(([label, dataField, options, isMultiSelect]) => {
    const fieldName = dataField;
    const labelText = label.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');  // Title case for labelText

    console.log(`Processing field: ${labelText} (dataField: ${dataField}, isMultiSelect: ${isMultiSelect})`);

    // Append either dropdown or text field based on options
    const isDropdown = options && Array.isArray(options) && options.length;
    
    if (isDropdown) {
      // For multi-select, initialize as an array
      const selectedValue = entityData[dataField] 
        ? (Array.isArray(entityData[dataField]) 
            ? entityData[dataField] 
            : [entityData[dataField]]) 
        : (isMultiSelect ? [] : "");
      
      console.log(`Creating dropdown for field: ${labelText} with options:`, options);
      form.appendChild(
        createDropdown(fieldName, options, selectedValue, labelText, isMultiSelect)
      );
    } else {
      form.appendChild(
        createTextField(fieldName, entityData[dataField] != null ? entityData[dataField] : "", labelText)
      );
    }
  });

  // Set modal title and entity ID
  document.getElementById("editModalTitle").textContent = titles[entityType];
  document.getElementById("modal-header-entity-ID").textContent = `${titles[entityType].split(" ")[1]} ID: ${entityData[`${entityType}Id`] || "N/A"}`;

  modal.style.display = "flex";
  modal.setAttribute("aria-hidden", "false");
  document.body.style.overflow = "hidden";

  closeButton.onclick = closeEditModal;
  window.onclick = (e) => e.target === modal && closeEditModal();

  saveButton.onclick = () => handleAction("save", entityType, entityData);
  deleteButton.onclick = () => handleAction("delete", entityType, entityData);

  function closeEditModal() {
    modal.style.display = "none";
    modal.setAttribute("aria-hidden", "true");
    document.body.style.overflow = "auto";
    console.log("Modal closed");
  }
}

I still can’t understand whats wrong. (I’m just learning to sorry if I missed something super obvious)

Displaying image from Google Drive link in React problem

I have the following React component that uses a Google Drive link to get the image. The backend is written in Django REST Framework which returns the URL link for the image. The original link is https://drive.google.com/file/d/1pYzwc1GOkO_HcKFuNdOBXd6XriFsIYec/view?usp=drive_link. I have modified the link so that the Google Drive interface is not required. But still, the link isn’t working.

Note: The link is working if I directly paste it into the browser though.

const  FetchImage = () => {
    const driveFileId = '1pYzwc1GOkO_HcKFuNdOBXd6XriFsIYec';
    const imageUrl = `https://drive.google.com/uc?export=view&id=${driveFileId}`;
  
    return <img src={imageUrl} alt="Drive Image" />;
}

export default FetchImage;

What would be the possible solution?

Why does Vite compile a separate jQuery file even when chunking it in the vite.config.js file in Laravel 11 project?

I’m developing an admin panel for a personal project using Laravel 11, and I’m using Vite (default with Laravel) for bundling assets. I’ve installed jQuery in my project, and while I have configured Vite to chunk it into a vendor file, I noticed that Vite is still generating a separate jQuery file.

Here’s the chunking configuration in my vite.config.js file:

manualChunks: {
    "core": ["axios"],
    "vendor": ["alpinejs", "bootstrap", "jquery"],
    "charts": ["d3"],
},

But after compiling, the file jquery-[hash].js is still generated. The contents of the file look like this:

import {r as u, g as f} from "./vendor-Dg7k8igf.js";
function c(t, n) {
    for (var o = 0; o < n.length; o++) {
        const e = n[o];
        if (typeof e != "string" && !Array.isArray(e)) {
            for (const r in e)
                if (r !== "default" && !(r in t)) {
                    const a = Object.getOwnPropertyDescriptor(e, r);
                    a && Object.defineProperty(t, r, a.get ? a : {
                        enumerable: !0,
                        get: () => e[r]
                    })
                }
        }
    }
    return Object.freeze(Object.defineProperty(t, Symbol.toStringTag, {
        value: "Module"
    }))
}
var s = u();
const i = f(s)
  , y = c({
    __proto__: null,
    default: i
}, [s]);
export {i as a, y as j};

Here is my full vite.config.js:

import {defineConfig} from 'vite';
import laravel from 'laravel-vite-plugin';
import manifestSRI from 'vite-plugin-manifest-sri';
import pkg from './package.json';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/assets/admin/sass/app.scss',
                'resources/assets/admin/js/app.js',
                'resources/assets/frontend/css/app.css',
                'resources/assets/frontend/js/app.js',
            ],
            detectTls: 'admin-panel.test',
            refresh: true,
        }),
        manifestSRI(),
    ],

    optimizeDeps: {
        include: Object.keys(pkg.dependencies),
    },

    build: {
        emptyOutDir: true,
        sourcemap: "hidden",
        minify: true,
        chunkSizeWarningLimit: 1000, // 1MB
        rollupOptions: {
            output: {
                minifyInternalExports: true,
                manualChunks: {
                    "core": ["axios"],
                    "vendor": ["alpinejs", "bootstrap", "jquery"],
                    "charts": ["d3"],
                },
                entryFileNames: 'assets/[name]-[hash].js',
                chunkFileNames: 'assets/[name]-[hash].js',
                assetFileNames: 'assets/[name]-[hash].[ext]',
                format: 'esm'
            }
        }
    }
});

Problem:

Even though I have chunked jquery under the vendor chunk, a separate file for jQuery (jquery-[hash].js) is still being generated. This isn’t the case for other vendor packages like alpinejs or bootstrap, which are being bundled correctly.

Could someone explain why this is happening and how I can ensure that jQuery is bundled with the rest of the vendor dependencies instead of being split into a separate file?

Why do SVG elements generated in JavaScript not have the same sizing as SVG elements defined directly in HTML?

I have buttons with SVG icons inside them that are added to the page using JavaScript. I would like these icons to behave as SVGs typically would in any other situation – obeying the CSS rules. However, when the buttons are generated, the sizing of the SVG (and the path within it) is strange – always 300px x 150px, which does not match the dimensions of the defined viewBox (in this case, 0 0 24 24) and is not influenced by any CSS. The path comes out at 24×24 pixels in the top right corner of this container and does not scale with the SVG container or the button element above that.

https://jsfiddle.net/zbsdum28/

If this exact same element is directly declared in HTML instead, it appears as expected – with the SVG matching the dimensions of the button element that it is placed in.

https://jsfiddle.net/cu9t3gsx/

I’ve tried adding various different CSS styles to try and account for this, and changing the attributes of the SVG, but while the SVG element does react, the path within it does not, remaining the same size. I assume the issue is with the way I am creating the element in JavaScript, but I don’t know why and I’ve not been able to find any way to correct it.

JavaScript:

var controls = true

if (controls == true) {
    // generate the reset button
    var resetSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");

    var resetSvgPath = document.createElementNS(
      "http://www.w3.org/2000/svg",
      "path",
    );

    resetSvg.setAttribute("class", "icon reset-icon");

    resetSvg.setAttribute("viewbox", "0 0 24 24");

    resetSvg.setAttribute("preserveAspectRatio", "xMinYMax meet");

    resetSvg.setAttribute("fill-rule", "evenodd");

    resetSvg.setAttribute("clip-rule", "evenodd");

    resetSvgPath.setAttribute(
      "d",
      "M2.458 9.012c-.297.947-.458 1.955-.458 3 0 5.52 4.481 10 10 10 5.52 0 10-4.48 10-10 0-5.519-4.48-10-10-10-2.121 0-4.083.668-5.703 1.796l1.703 2.204h-6.58l1.935-6.012 1.718 2.223c1.958-1.389 4.346-2.211 6.927-2.211 6.623 0 12 5.377 12 12s-5.377 11.988-12 11.988-12-5.365-12-11.988c0-1.036.132-2.041.379-3h2.079zm10.35-3.012c.292.821.375 1.346 1.01 1.609.637.264 1.073-.052 1.854-.423l1.142 1.142c-.373.787-.687 1.218-.423 1.854.262.634.784.716 1.609 1.009v1.617c-.816.29-1.347.375-1.61 1.01-.264.636.052 1.071.424 1.853l-1.142 1.142c-.79-.375-1.219-.687-1.85-.424-.639.265-.723.793-1.014 1.611h-1.616c-.292-.821-.375-1.347-1.01-1.61-.637-.264-1.072.052-1.854.423l-1.142-1.142c.366-.771.689-1.212.423-1.854-.263-.635-.793-.719-1.609-1.009v-1.617c.817-.29 1.346-.373 1.609-1.009.264-.637-.051-1.07-.423-1.854l1.142-1.142c.788.374 1.218.687 1.854.423.635-.263.719-.792 1.01-1.609h1.616zm-.808 8c-1.105 0-2-.896-2-2 0-1.105.895-2.001 2-2.001 1.104 0 2 .896 2 2.001 0 1.104-.896 2-2 2z",
    );

    resetSvg.appendChild(resetSvgPath);
    
    var resetButton = document.createElement("button");
    
    resetButton.classList.add("reset-button");
    
    resetButton.appendChild(resetSvg);
    
    document.body.appendChild(resetButton);
}

CSS:

button {
  width: 5rem;
}

Prevent Unauthorized Access to QR Code Generation Route

I am currently working on a 2-factor authentication system. I am generating a QR code in Base64 format in the backend. I am retrieving this with an app.get route.

The problem is that any user who knows the URL can get this Base64 code. In my case: http://localhost:3000/generate-qr/User123

How can I prevent the user from accessing this URL? What is the most effective way to prevent this?

This is my JavaScript (Backend) code:

app.get('/generate-qr/:username', async (req, res) => {
    const {username} = req.params;

    try {
        const connection = await connectToDatabase();

        const [rows] = await connection.execute('SELECT secret_key FROM authenticator.members WHERE account_name = ?', [username]);

        if (rows.length === 0) {
            return res.status(404).json({error: 'User not found'});
        }

        const secret_key = rows[0].secret_key;
        const service = 'UniversalCW';
        const oneTimePasswordAuthenticator = authenticator.keyuri(username, service, secret_key);

        qrcode.toDataURL(oneTimePasswordAuthenticator, (error, imageURL) => {
            if (error) {
                console.error('Error with QR code:', error);
                return res.status(500).json({error: 'Error generating QR code'});
            }
            res.json({qrcode: imageURL});
        });
    } catch (error) {
        console.error(error);
        res.status(500).json({error: 'Internal server error'});
    }
});

TypeError: animationBuilder is not a function

So the whole error is as follows:

@ionic_vue.js?v=bbc2dfce:18984 TypeError: animationBuilder is not a function at animation (chunk-YNRD7USV.js?v=bbc2dfce:838:17)

I know I can disable the entire animation using the following, and it removes the error, but I would like to disable only specific routes or specific functions, not the whole router.

<ion-router-outlet :animated="false" />

When I use it like this, I don’t have any problems.

import { useIonRouter } from '@ionic/vue';

const ionRouter = useIonRouter();


function clickLink() {
    ionRouter.push(url.value);
}

I have a problem when I put it inside another TypeScript file.

export function useCustomRouter() {
    const router = useIonRouter();
    const { activeOrganizationId } = useDaily();

    async function push(path: any) {
        try{
            await router.push(path, 'forward');
        } catch (e) {
            //console.error(e);
        }
    }

    async function back() {
        try{
            await router.back('none');
        } catch (e) {
            //console.error(e);
        }
    }

    async function goHome() {
        try{
            await router.push(`/${activeOrganizationId.value}/app/my-day`, 'forward');
        } catch (e) {
            //console.error(e);
        }
    }

    return {
        push,
        back,
        goHome,
    };
}

And then use it like this.


import { useCustomRouter } from '~/composables/useCustomRouter';

const router = useCustomRouter();


function clickLink() {
    router.push(url.value)
}

I get the animationBuilder problem in the console, and the only fix I found besides setting animated: false is using noAnimation like you can see below:

import { type AnimationBuilder, createAnimation } from '@ionic/vue';

export function useCustomRouter() {
    const noAnimation: AnimationBuilder = (baseEl, opts) => {
        return createAnimation().addElement(baseEl).duration(0);
    };

    const router = useIonRouter();
    const { activeOrganizationId } = useDaily();

    async function push(path: any) {
        try{
            await router.push(path, noAnimation);
        } catch (e) {
            //console.error(e);
        }
    }

    async function back() {
        try{
            await router.back(noAnimation);
        } catch (e) {
            //console.error(e);
        }
    }

    async function goHome() {
        try{
            await router.push(`/${activeOrganizationId.value}/app/my-day`, 'forward');
        } catch (e) {
            //console.error(e);
        }
    }

    return {
        push,
        back,
        goHome,
    };
}

So, is there not an easier way to define not to use the animation for this, for both the push and the back? Or is there another way to remove the error from the console?

What are some foolproof cache-busting methods to use (for HTML/CSS/JS files) when conventional techniques aren’t working?

Here’s what I’ve tried so far:

1) Added “no cache” commands to the .htaccess file (the site is hosted via Hostgator):

    <FilesMatch ".(html|htm|css|js)$">
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
    </FilesMatch>

2) Added a similar set of commands to the meta tags of the main index.html file:

    <meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
    <meta http-equiv="cache-control" content="max-age=0" />
    <meta http-equiv="expires" content="0" />
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
    <meta http-equiv="pragma" content="no-cache" />

3) Implemented index.js and index.css filename versioning.

So, any time I push updates to the website, I increment the filenames like so:

“index-v1.31.1.js” –> “index-v1.31.2.js”

“index-v1.31.1.css” –> “index-v1.31.2.css”

I do that by renaming/reuploading the files in the Files Manager itself, and I also update the references in the index.html file to point to these new versions like so:

<link rel="stylesheet" href="index-v1.31.2.css">
<script src="index-v1.31.2.js"></script>

PROBLEM: These methods aren’t working for some users.

What’s baffling to me is that some users are still seeing/using an older version of the website — a version that’s at least several days old. I can confirm this by the structure of the logs associated with their account.

Side question: How are they even running the website on files that don’t exist anymore?

What is also weird (maybe this is just how cacheing works?) is that the index.html file being run on this older version of the website is pointing to index.js and index.css filenames that don’t even exist anymore on the website/in the Files Manager section, yet it’s continuing to run the website on those older files.

OBJECTIVE: What are some other foolproof cache-busting methods I can use to GUARANTEE that people always are running the absolute newest version of the HTML/CSS/JS files?

Thanks