Invoice not properly generating my PDF, but previewing the invoice works

I am trying to create a invoice page using Node.js and I created it using HTML/CSS. I noticed that when I want to preview the invoice and product on localhost, it works fine and I get the result I want. But generating the PDF doesn’t work. I tried re-creating it with smaller boilerplate code and still receiving the same error. Please help, thanks!

Error Image

Invoice Image Preview

I need the preview of my invoice code, to show up downloaded and able to be previewed in a PDF file.
app.js file
app.js file 2nd
css file
HTML file

How to reload the current page with a different html template after a Task completes in Django?

I’m working on a Django project where I need to handle a task that runs in the background. Once the task is completed, I want to reload the current page, but I also need it to load a specific HTML template on that same URL.

Currently, I’m using AJAX to poll the status of the task, and once it’s completed, I receive a JSON response from the server indicating the task’s completion. My goal is to reload the current page when the task is done, so the user can see the updated content.

I want that if the user visits the page later or deletes or reloads the tab the new template is what is loaded and not the old one.

Here’s my django view:

@csrf_protect
def initiate_transcription(request, session_id):

    file_name = request.session.get('uploaded_file_name')
    file_path = request.session.get('uploaded_file_path')

    try:
        transcribed_doc = TranscribedDocument.objects.get(id=session_id)
    except TranscribedDocument.DoesNotExist:
        return JsonResponse({'status': 'error', 'message': 'Document not found'}, status=404)


    if request.method == 'GET':
        if not file_name or not file_path:
            return redirect(reverse('transcribeSubmit'))
    
    if request.method == 'POST':

        if not file_name or not file_path:
            return redirect(reverse('transcribeSubmit'))
        else:
        
            try:
                if transcribed_doc.state == 'not_started':
                    
                    transcribed_doc.state = 'in_progress'
                    transcribed_doc.save()
                
                    audio_language = request.POST.get('audio_language')
                    output_file_type = request.POST.get('output_file_type')

                    task = transcribe_file_task.delay(file_path, audio_language, output_file_type, 'ai_transcribe_output', session_id)
                
                    return JsonResponse({'status': 'success', 'task_id': task.id})
                elif transcribed_doc.state == 'completed':
                    return render(request, 'transcribe/transcript-download.html')
            except Exception as e:
                #return HttpResponse(status=500)
                return JsonResponse({'status': 'error', 'error': 'No file uploaded'})

    return render(request, 'transcribe/transcribe-complete-en.html')

@csrf_protect
def poll_task_status(request, task_id):
    
    import base64
    task_result = AsyncResult(task_id)
    
    if task_result.ready():
        session_id = request.session.get('session_id')
        try:
            transcribed_doc = TranscribedDocument.objects.get(id=session_id)
            
            if transcribed_doc.output_file:
                transcribed_doc.state = 'completed'
                transcript_path = transcribed_doc.output_file.url
                transcript_name = os.path.basename(transcript_path)
                transcript_path_response = requests.get(transcript_path)
                
                if transcript_path_response.status_code == 200:
                    file_content = transcript_path_response.content
                    file_content_base64 = base64.b64encode(file_content).decode('utf-8')
                    
                    response_data = {
                        'status': 'completed',
                        'file_content': file_content_base64,
                        
                        'content_type': 'text/plain; charset=utf-8',
                        'filename': transcript_name
                        }
                    return JsonResponse(response_data)
                    #return render(request, 'transcribe/transcript-download.html')
                    

                    #context = {
                        #'download_url': transcribed_doc.output_file.url,
                        #'filename': transcribed_doc.output_file.name,
                        #}
                
                else:
                    return JsonResponse({'status': 'error', 'message': 'Failed to retrieve file'}, status=500)
            else:
                return JsonResponse({'status': 'terminated', 'message': 'Transcription was terminated before completion'})
        
        except TranscribedDocument.DoesNotExist:
            return JsonResponse({'status': 'error', 'message': 'Transcription document not found'}, status=404)
    
    elif task_result.state == 'REVOKED':
        transcribed_doc.state = 'terminated'
        transcribed_doc.save()
        return JsonResponse({'status': 'terminated', 'message': 'Transcription was terminated'})
    
    else:
        return JsonResponse({'status': 'pending'})

Here is my JS:

form.addEventListener('submit', function(event) {
    event.preventDefault();
    isTranscribing = true;

    const transcribeField = document.querySelector('.transcribe-output-lang-select')
    
    transcribeField.style.opacity = '0';
    setTimeout(function() {
        transcribeField.style.display = 'none';
        transcribingFileField.style.display = 'block';
        errorDiv.style.opacity = '0';
        errorDiv.style.display = 'none';

    }, 300); 
    setTimeout(function() {
        transcribingFileField.style.opacity = '1'

    }, 500); 
   
    const formData = new FormData(form);
 
    const xhr = new XMLHttpRequest();
    xhr.onload = function() {
        if (xhr.status == 200) {
            const response = JSON.parse(xhr.responseText);
            if (response.status === 'success') {
                pollTaskStatus(response.task_id);
            } else {
                showError('An error occurred while initiating the transcription.');
            }
        } else {
            showError('An error occurred while uploading the file.');
        }
    };

    xhr.onerror = function() {
        showError('An error occurred while uploading the file.');
    };

    xhr.open('POST', form.action, true);
    xhr.send(formData);
});

function pollTaskStatus(taskId) {
    currentTaskId = taskId;
    console.log(currentTaskId)
    pollInterval = setInterval(() => {
        const xhr = new XMLHttpRequest();
        xhr.onload = function() {
            if (xhr.status == 200) {
                const response = JSON.parse(xhr.responseText);
                if (response.status === 'completed') {
                    console.log('sent');
                    //console.log(response.filename);
                    showTranscriptionComplete();
                    clearInterval(pollInterval); // Stop polling once completed
                    isTranscribing = false; // Set to false when transcription is complete
                }
            } else {
                showError('An error occurred.');
                clearInterval(pollInterval); // Stop polling on error
                isTranscribing = false; // Set to false on errors
            }
        };
        xhr.onerror = function() {
            showError('Connection error. Please check your network connection and try again.');
            clearInterval(pollInterval); // Stop polling on network error
            isTranscribing = false; // Set to false on network error
            
        };
        xhr.open('GET', `/transcribe/poll_task_status/${taskId}/`, true);
        xhr.send();
    }, 5000); // Poll every 5 seconds
}

My server-side view returns a JSON response with the status of the task. When the task is completed, I want the page to reload with a specific HTML template that I’ve written.

How can I ensure that the correct HTML template is loaded upon page reload without changing the URL?

How can I fix this problem and make it work properly?

The script previously worked in this interface:
enter image description here

This is the current page and I got everything out of “validatetoken”
**enter image description here

This is the programming that each script documentation has

  • getData.js:
const data = require("./constants.json");

const authorization = data["authorization"];
const languageCode = data["languageCode"];

async function getData() {
  const res = await fetch("https://graph.rosettastone.com/graphql", {
    credentials: "include",
    headers: {
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0",
      Accept: "*/*",
      "Accept-Language": "en-US,en;q=0.5",
      "content-type": "application/json",
      authorization: authorization,
      "x-request-id": "66a4813c-8077-4509-9875-6c10608b9933",
      "Sec-Fetch-Dest": "empty",
      "Sec-Fetch-Mode": "cors",
      "Sec-Fetch-Site": "same-site",
    },
    referrer: "https://totale.rosettastone.com/",
    body:
      '{"operationName":"GetCourseMenu","variables":{"languageCode":"' +
      languageCode +
      '","filter":"ALL","chunking":false,"includeMilestoneInLessonFour":true},"query":"query GetCourseMenu($languageCode: String!, $filter: String!, $includeMilestoneInLessonFour: Boolean!, $chunking: Boolean!) {\n  courseMenu(\n    languageCode: $languageCode\n    includeMilestoneInLessonFour: $includeMilestoneInLessonFour\n    chunking: $chunking\n    filter: $filter\n  ) {
n    currentCourseId\n    bookmarkToUseOnload {\n      course\n      bookmarkToUseOnload\n      __typename\n    }\n    speechEnabledBookmark {\n      course\n      unitIndex\n      lessonIndex\n      pathType\n      __typename\n    }\n    speechDisabledBookmark {\n      course
n      unitIndex\n      lessonIndex\n      pathType\n      __typename\n    }\n    curriculumDefaults {\n      course\n      curriculumId\n      resource\n      __typename\n    }\n    viperDefinedCurricula {\n      id\n      course\n      firstExerciseId\n      exerciseCount\n      nameByLocale {\n        curriculumId\n        locale\n        curriculumNameLocalized\n        __typename\n      }\n      descriptionByLocale {\n        curriculumId\n        locale\n        curriculumDescriptionLocalized\n        __typename\n      }\n      __typename\n    }\n    showCurriculumChooser {\n      course\n      showCurriculumChooser\n      __typename\n    }\n    numberOfUnits\n    units {\n      id\n      index\n      unitNumber\n      titleKey\n      color\n      colorDesaturated\n      lessons {\n        id\n        index\n        titleKey\n        lessonNumber\n        paths {\n          unitIndex\n          lessonIndex\n          curriculumLessonIndex\n          sectionIndex\n          index\n          type\n          id\n          course\n          resource\n          scoreThreshold\n          timeEstimate\n          numChallenges\n          numberOfChallengesSeen\n          complete\n          scoreCorrect\n          scoreIncorrect\n          scoreSkipped\n          percentCorrectForDisplay\n          percentIncorrect\n          percentSkipped\n          percentComplete\n          pathCourseMenuDisplayState\n          __typename\n        }\n        __typename\n      }\n      __typename\n    }\n    __typename\n  }\n  tutoringSummary {\n    status\n    canSchedule\n    userTimezone\n    nextSession {\n      startTimeStamp\n      lessonNumber\n      unitNumber\n      coachName\n      __typename\n    }\n    __typename\n  }\n}\n"}',
    method: "POST",
    mode: "cors",
  });
  const data = await res.json();
  return data;
}

module.exports = getData;
  • index.js

const getData = require("./getData.js");
const constants = require("./constants.json");
const makeRequest = require("./makeRequest.js");

async function main() {
  const originalData = await getData();
  const data = JSON.parse(JSON.stringify(originalData)).data;
  console.log("Data received");
  console.log(originalData);
  const units = data.courseMenu.lessons((unit) =>
    constants["unitsToComplete"].includes(unit.unitNumber)
  );

  units.forEach((unit) => {
    // Start Time should reset for each unit
    const startTime = Date.now() - getRndInteger(0, 86400000);
    let timeSoFar = 0;

    // Loop through each lesson
    unit.lessons.forEach((category) => {
      // Loop through each category
      category.paths.forEach(
        ({
          unitIndex,
          curriculumLessonIndex,
          type,
          course,
          numChallenges,
          timeEstimate,
        }) => {
          // This is the lesson portion

          // Randomize the time it took to complete lesson based off given estimate
          const timeInMinutes =
            timeEstimate +
            getRndInteger(
              -1 * Math.floor(timeEstimate / 3),
              Math.floor(timeEstimate / 3)
            );

          // Convert that time to milliseconds
          const timeInMilliseconds =
            timeInMinutes * 60000 + getRndInteger(0, 6000);

          // For randomizing how much is correct
          // const percentCorrect = getRndInteger(87, 100);

          // Keep track of what time it was submitted
          timeSoFar += timeInMilliseconds;
          // Randomize a little bit
          timeSoFar += getRndInteger(0, 60000);

          // Choose what percent correct is done
          // Use the randomize function for a range (e.g. getRndInteger(87, 100))
          const percentCorrect = getRndInteger(89, 100);
          // const percentCorrect = 100;

          const questionsCorrect = Math.ceil(
            numChallenges * (percentCorrect / 100)
          );

          // Check if lesson has been completed
          // Can't do if (percentCorrect == 100) because of rounding
          const completed = !!(questionsCorrect == numChallenges) + "";

          // The time the lesson will be marked as completed
          // Will reset for each unit
          let timeCompleted = startTime + timeSoFar;

          makeRequest({
            course,
            lessonIndex: curriculumLessonIndex,
            questionAmount: numChallenges,
            questionsCorrect,
            unitIndex: unitIndex % 4,
            time: timeInMilliseconds,
            type,
            completed,
            timeCompleted,
          });
        }
      );
    });
  });

  console.log("Finished (wait for requests)!!");
}

function getRndInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
main();

  • **makeRequest.js:
    **
const data = require("./constants.json");

async function makeRequest({
  course,
  unitIndex,
  lessonIndex,
  type,
  questionAmount,
  time,
  questionsCorrect,
  completed,
  timeCompleted,
}) {
  console.log(
    course,
    unitIndex,
    lessonIndex,
    type,
    questionAmount,
    time,
    questionsCorrect,
    completed
  );
  const body =
    "<path_score>n    <course>" +
    course +
    "</course>n    <unit_index>" +
    unitIndex +
    "</unit_index>n    <lesson_index>" +
    lessonIndex +
    "</lesson_index>n    <path_type>" +
    type +
    "</path_type>n    <occurrence>1</occurrence>n    <complete>" +
    completed +
    "</complete>n    <score_correct>" +
    questionsCorrect +
    "</score_correct>n    <score_incorrect>" +
    (questionAmount - questionsCorrect) +
    '</score_incorrect>n    <score_skipped type="fmcp">0</score_skipped>n    <number_of_challenges>' +
    questionAmount +
    "</number_of_challenges>n    <delta_time>" +
    time +
    "</delta_time>n    <version>185054</version>n    <updated_at>" +
    timeCompleted +
    "</updated_at>n    <is_lagged_review_path>false</is_lagged_review_path>n</path_score>";

  const res = await fetch(
    "https://tracking.rosettastone.com/ee/ce/" +
      data["schoolName"] +
      "/users/" +
      data["userId"] +
      "/path_scores?course=" +
      course +
      "&unit_index=" +
      unitIndex +
      "&lesson_index=" +
      lessonIndex +
      "&path_type=" +
      type +
      "&occurrence=1&_method=put",
    {
      credentials: "omit",
      headers: {
        "User-Agent":
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0",
        Accept: "*/*",
        "Accept-Language": "en-US,en;q=0.5",
        "content-type": "text/xml",
        "x-rosettastone-app-version": "ZoomCourse/11.11.2",
        "x-rosettastone-protocol-version": "8",
        "x-rosettastone-session-token": data["sessionToken"],
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-site",
      },
      referrer: "https://totale.rosettastone.com/",
      body: body,
      method: "POST",
      mode: "cors",
    }
  );
  console.log(`Status ${res.status} (200 means success)`);
  console.log(`Time: ${Date().toLocaleString()}`);
}

module.exports = makeRequest;
  • constants.json
{
  "person": "YOUR_NAME (Not Required)",
  "authorization": "YOUR_AUTHORIZATION_TOKEN",
  "sessionToken": "YOUR_SESSION_TOKEN",
  "schoolName": "YOUR_SCHOOL_NAME",
  "unitsToComplete": [1, 2, 3],
  "userId": "YOUR_USER_ID",
  "languageCode": "YOUR_LANGUAGE_CODE"
}

I’m getting this error:

Data received
{
errors: [
{
error: true,
message: "Client info is not defined, and is needed in order to call Sqrl/LCP. If you're not expecting to call Sqrl/LCP via the graph server, you may need to include more necessary welcome_packet values.",
code: 'GRAPHQL_VALIDATION_FAILED',
path: [Array]
},
{
error: true,
message: "Client info is not defined, and is needed in order to call Sqrl/LCP. If you're not expecting to call Sqrl/LCP via the graph server, you may need to include more necessary welcome_packet values.",
code: 'GRAPHQL_VALIDATION_FAILED',
path: [Array]
}
],
data: { courseMenu: null, tutoringSummary: null }
}
C:UsersAdrianzDownloadsRosetta-Stone-Script-mainindex.js:10
const units = data.courseMenu.units.filter((unit) =>
^
TypeError: Cannot read properties of null (reading 'units')
at main (C:UsersAdrianzDownloadsRosetta-Stone-Script-mainindex.js:10:33)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

I tried several things:

  1. I tried using chatgpt to help me solve the problems but without success.
  2. Then I was looking at the APIs but there was no video that I could clearly understand
  3. I was uploading my problem to Reddit and a person told me to look for the .env files but I don’t know where they are located

What I hoped to achieve with this is that I could solve the course activities in a quick way as I did previously in the lower course.

So I leveled up in the course the whole interface changed so I don’t know how to do it

Getting and changing the text content in Lexical Editor on React

So, I’m using the lexical editor in my react project. My app get the text from a API that transcribe audio and then I need to put on the Lexical editor, but I’m having problem to manipulate the text, I just don’t know how to do.

TextEditor.tsx:


import { useEffect } from "react";

import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";

import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { ListPlugin } from "@lexical/react/LexicalListPlugin";

import { EditorState } from "lexical";
import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { HeadingNode } from "@lexical/rich-text";
import { ListNode, ListItemNode } from '@lexical/list';

import { ToolBarPlugin } from "./Toolbar";

interface TextEditorProps {
  value: string;
  readOnly: boolean;
}

const theme = {
  // apenas css | exemplo:
  // heading: {
  //   h1: "classe-do-h1"
  // } // importa arquivo css com os estilos
};


function onError(error: Error): void {
  console.error(error);
}

const MyOnChangePuglin = (props: { onChange: (editorState: EditorState) => void }): null => {
  const [editor] = useLexicalComposerContext();
  const { onChange } = props;
  useEffect(() => {
    return editor.registerUpdateListener(({ editorState }) => {
      onChange(editorState);
    });
  }, [onChange, editor]);
  return null;
};

export function TextEditor({ value, readOnly }: TextEditorProps) {
  const initialConfig = {
    namespace: "MyEditor",
    theme,
    onError,
    nodes: [HeadingNode, ListNode, ListItemNode]
  };

  return (
    <LexicalComposer initialConfig={initialConfig}>
      <ToolBarPlugin />
      <ListPlugin />
      <RichTextPlugin
        contentEditable={
          <ContentEditable
            className={`min-h-[500px] border-[1px] border-[#d4d4d4] p-4 rounded-md shadow-lg bg-[#f8f8f8] overflow-y-auto focus:outline-none ${
              readOnly ? "cursor-not-allowed" : "cursor-text"
            }`}
          />
        }
        ErrorBoundary={LexicalErrorBoundary}
      />
      <MyOnChangePuglin onChange={(editorState) => console.log(editorState._nodeMap)} />
      <HistoryPlugin />
    </LexicalComposer>
  );
}

How I was passing the text to the older TextArea

   <TextEditor value={transcription} readOnly={editorState} />
// transcription has all the text that will come by the API

I was looking at this page, but I could make it work:
https://lexical.dev/docs/concepts/editor-state

How to Display a Loader While Waiting for Server-Side Data Fetch in Next.js?

I’m working on a Next.js application where I’m using getServerSession and getHotelAvail to fetch data server-side in the Search component. However, when the user submits the search form, the page waits on the form (even though an url is pushed) and only when getHotelAvail finishes, the Search component with the fetched data renders. This causes the user to experience a delay without any feedback that the data is being loaded.

For reasons unknown to me this only happens when building the project, on development it works as expected.

Form Submission Logic:

else {
  let obj = { 
    ...values, 
    checkIn: format(date.from, "yyyy-MM-dd"), 
    checkOut: format(date.to, "yyyy-MM-dd"), 
    city: values.city.city, 
    lat: values.city.lat, 
    lng: values.city.lng 
  };
  
  if (values.city.state_province) obj.state = values.city.state_province;

  let x = getPairs(obj)
    .map(([[key0, ...keysRest], value]) =>
      `${key0}${keysRest.map(a => `[${a}]`).join('')}=${value}`)
    .join('&');
    
  router.push(`/search?${x}`);
  router.refresh();

  if (path === "/search") {
    window.history.replaceState(null, '', `/search?${x}`);
    window.location.reload();
    router.refresh();
  }
}

Search Results Component:

const Search = async ({ searchParams }) => {
  try {
    const session = await getServerSession(authOptions);
    if(!session.user.name) throw new Error('Unauthorized User');
    
    const user = await getUserById(session.user.name);
    if(!user.status) throw new Error('Unauthorized User');
    
    const data = await getHotelAvail(parseSearchParams(searchParams));
    if(!data.list?.length) throw new Error('No hotels available for this search');
    
    // Render logic...
  } catch (error) {
    // Error handling...
  }
};

How can I implement a loader or some sort of visual feedback to the user during the data fetch, while still maintaining the server-side requests? The goal is to show the loader as soon as the form is submitted and not wait until the data is fully loaded.

Any guidance on the best practices for handling this in Next.js would be greatly appreciated.

I used to have a skeleton but the same would happend.

I tried to set the loader in the submit logic but it still the same, the Search Result Component and the loader would only render after getHotelAvail finishes.

What’s The Difference in Let and Var In Context of Closure [duplicate]

is in this code the loop in each iteration will create a new Lexical Env ?
because here i see that the outer Lexical of the inner function gets changed every time
unlike if i use var
i mean that var actually skipped the block don’t care about at all

var result = [];;
 
for (let i = 0; i < 5; i++) {
  result[i] = function () {
    console.log(i);
  };
}
result[0](); // 0
result[1](); // 1
result[2](); // 2
result[3](); // 3
result[4](); // 4

Three.js efficient way to build a block terrain

what I’m trying to achieve is not easy to explain.
But what I’m trying to do is build a “boxy” terrain that represents an elevation grid.

The issue that I’m now facing is that three.js is doing a great smooth terrain.
From this example: https://threejs.org/examples/#physics_ammo_terrain

I manage to build an utility class that build a terrain.

export class CubeGrid extends THREE.Group {
  private terrain: THREE.Mesh<THREE.BufferGeometry, THREE.MeshPhongMaterial>;
  private width: number;
  private depth: number;

  private terrainWidth = 30;
  private terrainDepth = 30;

  constructor(depth: number, width: number) {
    super();

    this.depth = depth;
    this.width = width;

    const terrainMaxHeight = 2;
    const terrainMinHeight = 0;

    const heightData = generateHeight(this.terrainWidth, this.terrainDepth, terrainMinHeight, terrainMaxHeight);

    const geometry = new THREE.PlaneGeometry(this.width, this.depth, this.terrainWidth - 1, this.terrainDepth - 1);
    geometry.rotateX(Math.PI / 2);
    const vertices = geometry.attributes.position.array;

    for (let i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
      // j + 1 because it is the y component that we modify
      vertices[j + 1] = heightData[i];
    }
    geometry.computeVertexNormals();
    const groundMaterial = new THREE.MeshPhongMaterial({ color: 0xc7c7c7, side: THREE.DoubleSide });

    this.terrain = new THREE.Mesh(geometry, groundMaterial);
    this.terrain.castShadow = false;
    this.terrain.receiveShadow = false;
    this.terrain.rotateX(Math.PI);
    this.add(this.terrain);
  }

  updateGrid(data) {
    const heightData = data;

    const geometry = new THREE.PlaneGeometry(this.width, this.depth, this.terrainWidth - 1, this.terrainDepth - 1);
    geometry.rotateX(Math.PI / 2);
    const vertices = geometry.attributes.position.array;

    for (let i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
      // j + 1 because it is the y component that we modify
      vertices[j + 1] = heightData[i];
    }
    geometry.computeVertexNormals();
    this.terrain.geometry.dispose();
    this.terrain.geometry = geometry;
  }
}

The main issue is that this does not have the “boxy” effect I’m looking for.

This is my result:
my current result

But I’m trying to do something like this:
what i want

In that example, the “data” I’d be using to create the terrain would be something like this:

const data = [
    2,1,1,
    4,1,1,
    6,4,1
]

How could I achieve that “boxy” effect?
I tried to simply create a lot of boxes, but I will be instantiating a loot of boxes (100×100 grid), and I dont want to loose performance.

Thanks in advance!

AppsScript – String.replace(/s/g,””) deletes one of the characters when the string contains at least 2 % signs separated by only whitespace

I encountered this weird bug while working on an internal library for my work. We use App Script which is based on Javascript. However, there is a weird quirk with the string.replace() function that is causing problems.

Managers often include spaces when sending commands to our email bot so we have a function in a library which removes whitespace. It is:

function cleanSpaces(string){
  return string.replace(/s/g,"")
}

This function works fine unless the string has at least 2 ampersands separated by at least 1 whitespace character and no other characters.

This is a problem because some of the commands sent to the email bot use special characters, including %s to encode data for the request. Inconsistent behaviors when processing the data could cause problems long term, and I don’t know if this bug affects any other special characters.

For testing, I made a function in apps script and a dummy html page. The apps script test function has the following code (with ‘testString’ replaced with the test string):

function myFunction() {
  let string = 'testString'
  Logger.log(cleanSpaces(testString))
}

And the html document has the following code (with ‘testString’ replaced with the test string):

<html><body>
<p id="test"></p>

<script>
let string = 'testString';
string = string.replace(/s/g,"");
document.getElementById("testString").innerHTML = string;
</script>

</body></html>

When the string is set to something like ‘Hello World’, both functions correctly output HelloWorld

When the string is set to something like ‘ % 4 %4% 4%’, both functions correctly output %4%4%4%

However, when the string is set to something like ‘% %’, the html document correctly outputs %% but the Apps Script incorrectly outputs %.

Could someone please let me know why this happens and what (if anything) can be done to fix it.

problems with sequelize intermediate table

10 days ago I come with this problem I run out of ideas. what happens is that I have a many to many relationship between the entities of orders and equipment that are borrowed. the problem is as follows, I OrdersEquipments model in which I request the id of each team and award them to the order to have a strict control. The problem is that in the forOf cycle when updating the fieldName with their respective model I load a column that should not be because it is not being requested which is pdasId as we will see in the console below:

beforeCreate console:


pcsId VAMOS BIEN OrdersEquipment {
  dataValues: { pdasId: null, orderId: 6, pcsId: 1 },
  _previousDataValues: { orderId: undefined, pcsId: undefined },
  uniqno: 1,
  _changed: Set(2) { 'orderId', 'pcsId' },
  _options: {
    isNewRecord: true,
    _schema: null,
    _schemaDelimiter: '',
    attributes: undefined,
    include: undefined,
    raw: undefined,
    silent: undefined
  },
  isNewRecord: true
}

CODE JS:

export const createOrder = async (req, res) => {
  try {
    const {
      responsibility,
      event,
      note,
      state,
      userId,
      pdaCount,
      handiesCount,
      pcsCount,
      printHardCount,
      printPocketCount,
      celusCount,
      complementsCount,
    } = req.body;

    const selectEquipment = async (model, count) => {
      const availableEquipments = await model.findAll({ where: { userId: 1 } });
      if (availableEquipments.length < count) {
        throw new Error(
          `No hay suficientes equipos disponibles de tipo ${model.name}`
        );
      }
      return availableEquipments.slice(0, count);
    };

    const selectedPDAs = await selectEquipment(PDAS, pdaCount);
    const selectedCelus = await selectEquipment(CELUS, celusCount);
    const selectedPCs = await selectEquipment(PCS, pcsCount);
    const selectedPrintHards = await selectEquipment(
      HARDTICKET,
      printHardCount
    );
    const selectedPrintPockets = await selectEquipment(
      POCKET,
      printPocketCount
    );
    const selectedHandies = await selectEquipment(HANDIES, handiesCount);
    const selectedComplements = await selectEquipment(
      COMPLEMENT,
      complementsCount
    );

    if (
      selectedPDAs.length === pdaCount &&
      selectedCelus.length === celusCount &&
      selectedPCs.length === pcsCount &&
      selectedPrintHards.length === printHardCount &&
      selectedPrintPockets.length === printPocketCount &&
      selectedHandies.length === handiesCount &&
      selectedComplements.length === complementsCount
    ) {
      const newOrder = await ORDERS.create({
        responsibility,
        event,
        note,
        state,
        userId,
      });

      const assignEquipmentsToOrder = async (equipments, model) => {
        for (const equipment of equipments) {
          console.log(model.name)
          const fieldName = `${model.name.toLowerCase()}Id`;

          const newOrderEquipment = {
            orderId: newOrder.id,
            [fieldName]: equipment.id,
          };
    await ordersEquipmentModel.beforeCreate((newOrderEquipment) => {
        if (newOrderEquipment[fieldName] != null) {
          console.log(fieldName, "VAMOS BIEN", newOrderEquipment);
        } else {
          console.log("VAMO MAL", newOrderEquipment);
        }
      });
          await ordersEquipmentModel.create(newOrderEquipment);

          equipment.userId = userId;
          await equipment.save();
        }
      };

      await assignEquipmentsToOrder(selectedPDAs, PDAS);
      await assignEquipmentsToOrder(selectedPCs, PCS);
      await assignEquipmentsToOrder(selectedPrintHards, HARDTICKET);
      await assignEquipmentsToOrder(selectedPrintPockets, POCKET);
      await assignEquipmentsToOrder(selectedCelus, CELUS);
      await assignEquipmentsToOrder(selectedHandies, HANDIES);
      await assignEquipmentsToOrder(selectedComplements, COMPLEMENT);

      return res.status(200).json(newOrder);
    } else {
      throw new Error("No se pudieron asignar todos los equipos solicitados.");
    }
  } catch (error) {
    return res.status(500).json({ message: error.message });
  }
};

I hope you can understand it is the first time I post in a forum, thank you very much!

I tried modifying the model relationships but the error persisted, also the controller logic. The only way I found that it works is when I make the post request and I don’t ask for any entity except the pdas in which the error is the following: “message”: “the null value in the column ‘pdasId’ of the relationship ‘OrdersEquipments’ violates the constraint of not null” and I tried adding the allowNull in the model orderEquipments and it didn’t work either.`

Have created HTML form – struggling to get it to send email to my client with the user input data from the form

I have been learning HTML, CSS and Javascript so far and have built an enquiries form on a website that I am building.

In order for my client to be able to easily gather the data that form users submit, I would like to get the form to send an email to her email address, with the information that the user has inputted, when they click the submit button.

I understand that I may need to use PHP to do this but I haven’t learnt any PHP yet, as I’ve not yet started back-end languages – I have been learning front-end so far.

I have included my HTML code below. I can provide the CSS code if needed. I would like some guidance as to: –

  • Whether it’s worth trying to work out how to do this through PHP yet, or whether it’s worth shelving the form functionality until further down the line when I have started learning back-end languages.
  • Whether there is an alternative simple way of enabling my client to gather the user data, bearing in mind that she does not have coding skills, that does not involve use of back-end languages (does not have to involve emailing her the form data, as long as it is simple for her to use).
  • Some guidance on how I would go about sorting this through PHP. I have seen snippets of PHP code that are relevant to this issue, but I am struggling to understand them.
            <form id="enquiriesForm" class="flex-item">
                <label for="firstName" class="flex-item"><h5><b>First Name</b></h5></label>
                    <input type="text" id="firstName" name="firstName" class="flex-item" required>
                <br />
                <label for="secondName" class="flex-item"><h5><b>Second Name</b></h5></label>
                    <input type="text" id="secondName" name="secondName" class="flex-item"                    required>
                <br />
                <label for="emailAddress" class="flex-item"><h5><b>Email Address</b></h5></label>
                    <input type="email" id="emailAddress" name="emailAddress" class="flex-item" required>
                <br />
                <label for="phoneNumber" class="flex-item"><h5><b>Phone Number <h6><b>(optional field)</b></h6></b></h5></label>
                    <input type="number" id="phoneNumber" name="phoneNumber" class="flex-item">
                <br />
                <h5 class="flex-item"><b>Please choose the services that you are interested in</b></h5> <h6><b>(you can select more than one option)</b></h6>
                    <input type="checkbox" id="option1" name="option" value="blockOfFourClasses" class="flex-item">
                        <label for="option1" class="flex-item"><b>Block of Four Classes at Venue</b></label>
                    <input type="checkbox" id="option2" name="option" value="privateTuitionOwnHome" class="flex-item">
                        <label for="option2" class="flex-item"><b>Private Tuition in my Own Home</b></label>    
                    <input type="checkbox" id="option3" name="option" value="privateTuitionStudio" class="flex-item">
                        <label for="option3" class="flex-item"><b>Private Tuition in Mirrored Studio</b></label>
                    <input type="checkbox" id="option4" name="option" value="antenatalConsultation" class="flex-item">
                        <label for="option4" class="flex-item"><b>Antenatal Consultation</b></label>
                <br />
                <h5 class="flex-item"><b>Do you want to be added to our mailing list?</b></h5>
                    <input type="radio" id="radio1" name="yesNo" value="yes" class="flex-item">
                        <label for="radio1" class="flex-item"><b>Yes</b></label>
                    <input type="radio" id="radio2" name="yesNo" value="no" class="flex-item">
                        <label for="radio2" class="flex-item"><b>No</b></label>
                <br />
                <label for="freeTextComments" class="flex-item"><h5><b>Please Type Your Enquiry Here</b></h5></label>
                    <textarea id="comment" name="comment" rows="4" cols="30" class="flex-item"></textarea>
                <br />
                <br />   
                <button type="button" id="submitButton" class="flex-item"><span><h4><strong>Submit</strong></h4></span></button> 
</form>

I was ideally trying to avoid using a Javascript function to process the user input, unless I can get the Javascript function to email the users’ input to my client (which I understand that I can’t). This is because I presumed that a Javascript function would be too complicated for someone who does not how to code to access the user data.

If I am wrong on this and there is a relatively simple way of sorting this, and her accessing the user data, through Javascript, I would appreciate some guidance on this.

Why does el.scrollIntoView() cause the whole container to move?

I have nested overflow-y: auto elements, with a full page which is scrollable, and the sidebar which is independently scrollable. When I hover on something in the main content area, I want the sidebar nav link to scroll into view (to the top or center, if possible), but when I call sideBarNavLink.scrollIntoView(), it scrolls the entire content/page so the whole content goes up and is cut off on the bottom. My page is relatively complicated to reproduce.

Is there some trick to making scrollIntoView reliable and work as you’d expect? Do I need position: relative and stuff like that to get it to work or something? Or do I need to roll my own scroll into view function?

$(document).ready(() => {
  $('.link').click((e) => {
    e.currentTarget.scrollIntoView({ behavior: 'smooth', block: 'start' })
  })
})
.page {
  padding: 16px;
  background: yellow;
  display: flex;
  width: 100%;
  height: 300px;
  overflow-y: auto;
}

.content {
  padding: 16px;
  background: blue;
  flex: 1;
}

.sidebar {
  padding: 16px;
  background: pink;
  overflow-y: auto;
  height: 100%;
  width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="page">
  <div class="sidebar">
    <ul>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
      <li class="link">a</li>
    </ul>
  </div>
  <div class="content">
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
  </div>
</div>

Notice when you click on an “a” (a .link class), it scrolls the whole StackOverflow post into view! Why…

How to Run a Specific Spec File During `globalSetup` in Playwright?

I’m trying to run a specific spec file (math.spec.js) during the globalSetup phase in Playwright. The goal is to execute this spec file before any other tests run.

Here’s the structure of my project:

/my-project
|-- tests/
|   |-- e2e/
|       |-- pos/
|           |-- math.spec.js
|-- playwright.config.js
|-- global-setup.js

In global-setup.js, I want to run the math.spec.js file using the Playwright test runner. I’ve tried using Node’s child_process to execute the command, but I’m not sure if this is the best approach or if there is a built-in way in Playwright to handle this.

global-setup.js:

const { execSync } = require('child_process');

module.exports = async () => {
  try {
    // Attempt to run the specific spec file
    execSync('npx playwright test tests/e2e/pos/math.spec.js', { stdio: 'inherit' });
  } catch (error) {
    console.error('Error running math.spec.js in global setup:', error);
    process.exit(1); // Exit with a failure code if the test fails
  }
};

playwright.config.js:

import { defineConfig } from '@playwright/test';

export default defineConfig({
  globalSetup: require.resolve('./global-setup.js'),
  // Other configurations...
});

Questions:

  • Is this the correct way to run a specific spec file during globalSetup in Playwright?
  • Are there any best practices or potential issues with this approach?
  • Is there a more Playwright-native way to achieve this?

I’m using Playwright version 1.46.1 and Node.js version 20.15.1.

Injected contentScript via background.js is not respecting match pattern

Expected behaviour

For injected content script to run on specific pages that I set within my manifest.json

Current behaviour

Contentscript is injected on every page. Or atleast I seem to see errors in console for background indicating background.js:1 Uncaught (in promise) Error: Cannot access contents of url... ". Maybe it’s working but I don’t want to see these errors!

Manifest.json – I also tried host_permission as I understand this is relevant permission for programmatic injection

{
  "content_scripts": [
    {
      "matches": [
        "https://example-01.au/*",
        "https://example-03.com/*",
        "https://example-02.eu/*"
      ],
      "js": ["contentscript.js"]
    }
  ],
  "permissions": [
    "tabs",
    "contextMenus",
    "offscreen",
    "clipboardWrite",
    "tabGroups",
    "storage",
    "scripting",
    "activeTab"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "host_permissions": [
    "https://example-01.au/*",
    "https://example-03.com/*",
    "https://example-02.eu/*"
  ]
}

Background.js

chrome.tabs.onActivated.addListener((info) => {
  chrome.tabs.get(info.tabId, (tab) => {
    if (tab.url?.startsWith('chrome://')) return undefined;
    chrome.scripting
      .executeScript({
        target: { tabId: info.tabId },
        files: ['contentScript.js']
      })
      .then(() => {
        console.log('Scripted Injected');
      });
  });
});

It’s not clear from the docs. But, do ineed to programmatically set up page matches within my background.js?