chartjs-chart-financial in next.js is not showing

I am working on a simple Chart dashboard app in Next.js, using Chart.js. I am trying to add a Candlestick chart component, for which I use the chartjs-chart-financial library. However I only get an empty graph, with just the number and axis

Here is my source code

'use client'

import { Chart, Bar } from "react-chartjs-2"
import "chartjs-chart-financial"

import "chartjs-adapter-date-fns";
import { enUS } from "date-fns/locale"

export default function CandlestickChart() {

    const chartData = {
        datasets: [
            {
                label: "Candlestick Chart",
                data: [{ t: new Date("2023-08-01"), o: 100, h: 120, l: 90, c: 110 }],
            }
        ]
    };

    return (
        <Chart type="candlestick" data={chartData} options={{
                scales: {
                    x: {
                        type: "time",
                        adapters: {
                            date: {
                                locale: enUS,
                            }
                        }
                    }
                }
            }}/>
    )

}

I have tried using Bar instead of Chart, which yields in a slightly different result

while also adding a typescript error, saying how Bar does not have a type prop. I also tried adding type: "candlestick" to the dataset in chartData. But in both Chart and Bar cases, it yields the same result as the first picture, but produces a typescript error about how the chartData dataset is incompatible with the expected one. Here is what and how I register the scales and elements

Chart.register(CategoryScale, TimeScale, CandlestickController, CandlestickElement);

I have tried looking at all the examples, and stackoverflow posts I could find. I only found a single post with the same issue, despite them not using react, but that post has gotten zero answers.

I am trying to retrieve the value of the full name field in the stripe modal, but i get undefined

Issue with Retrieving the Full Name in Stripe Checkout Modal
I am trying to retrieve the value of the full name field in the Stripe Checkout modal so that I can include it in the email I send after payment. However, the fullName is coming through as undefined in the email. I attempted to retrieve it using elements.getElement(‘payment’).getValue(), but that didn’t work. I also tried removing the field and adjusting the CSS, but the issue persists.

Below is my React component for handling Stripe payments and sending emails:

import React, { useState, useEffect } from 'react';
import { useStripe, useElements, Elements, PaymentElement } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import { useLocation } from 'react-router-dom';

const stripePromise = loadStripe('your-publishable-key-here');

const sendEmail = async (paymentIntentId, email, fullName) => {
  try {
    const response = await fetch('http://localhost:5000/send-email', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ paymentIntentId, email, fullName }),
    });
    const data = await response.json();
    if (data.success) {
      console.log('Email sent successfully');
    } else {
      console.error('Failed to send email');
    }
  } catch (error) {
    console.error('Error sending email:', error);
  }
};

const CheckoutForm = ({ clientSecret, email }) => {
  const stripe = useStripe();
  const elements = useElements();
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (event) => {
    event.preventDefault();

    if (!stripe || !elements) {
      return;
    }

    try {
      setLoading(true);
      const { error, paymentIntent } = await stripe.confirmPayment({
        elements,
        confirmParams: {
          return_url: window.location.href,
        },
      });

      if (error) {
        console.error('Payment Error:', error);
        alert('Payment failed! Please try again.');
      } else if (paymentIntent && paymentIntent.status === 'succeeded') {
        console.log('Payment Intent:', paymentIntent);
        alert('Payment successful!');
        
        // Retrieve full name from the payment element
        const { error: elementsError, value: { name } } = await elements.getElement('payment').getValue();
        
        if (elementsError) {
          console.error('Error retrieving name:', elementsError);
        } else {
          await sendEmail(paymentIntent.id, email, name);
        }
      }
    } catch (error) {
      console.error('Error in handleSubmit:', error);
      alert('An error occurred. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div>
        <label className="block text-lg font-medium mb-2">Payment Information</label>
        <PaymentElement options={{
          fields: {
            billingDetails: {
              name: 'auto',
            },
          },
        }} />
      </div>
      <button
        type="submit"
        className="w-full py-3 bg-red-600 text-white font-semibold rounded-lg hover:bg-red-700 transition duration-300"
        disabled={loading || !clientSecret}
      >
        {loading ? 'Processing...' : 'Pay Now with iDEAL'}
      </button>
    </form>
  );
};

const Checkout = () => {
  const [clientSecret, setClientSecret] = useState('');
  const location = useLocation();
  const state = location.state || {};

  const { individualCount = 0, familyCount = 0, totalCost = 0, email = '' } = state;

  useEffect(() => {
    const fetchClientSecret = async () => {
      if (totalCost === 0) {
        console.error("Total cost is zero or undefined.");
        return;
      }

      const response = await fetch('http://localhost:5000/create-payment-intent', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
          amount: totalCost * 100, // amount in cents
          individualCount,
          familyCount,
          totalCost,
          email,
        }),
      });

      const data = await response.json();
      setClientSecret(data.clientSecret);
    };

    fetchClientSecret();
  }, [individualCount, familyCount, totalCost, email]);

  return (
    <div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
      <h1 className="text-4xl font-bold text-center mb-8 text-gray-900">Checkout</h1>
      <div className="mb-8 text-center">
        <h2 className="text-3xl font-semibold mb-4">Total Cost</h2>
        <p className="text-4xl font-bold text-red-600">€{(totalCost || 0).toFixed(2)}</p>
      </div>
      {clientSecret && (
        <Elements stripe={stripePromise} options={{ clientSecret }}>
          <CheckoutForm clientSecret={clientSecret} email={email} />
        </Elements>
      )}
    </div>
  );
};

export default Checkout;

How to design a backend API for a chat application using Node.js, Express.js, and MongoDB? [closed]

I am new to backend development and recently started learning Node.js. I’m working on a chat application and plan to use Node.js with Express.js and MongoDB as the backend. Since I’m still learning, I want to understand how to structure the backend API for managing users, messages, and real-time interactions.

Some specific points I need guidance on:

  1. How should I structure the endpoints for sending and receiving messages between users?
  2. What is the best way to handle user authentication and session management?
  3. What would be a good database schema for storing users, chat rooms, and messages in
    MongoDB?

Any advice or examples would be greatly appreciated!

Custom Routes in NextJS to support countries and languages

My site paths are like –

or –

https://www.example.com/[countryCode]/[languageCode]/products

Though libraries like – next-intl provides a way to deal with languages only but not if it has some previous country code attached to it.

Let me know any pointer on this.

How do I access nested JSON array values in Javascript? [duplicate]

I have a php file that generates some JSON. Then an HTML loads the JSON via JavaScript and tries to display some of the values contained in the JSON. I’m struggling with the JavaScript syntax to access the “Decision”:”Maybe” JSON data, to display “Maybe” in a paragraph.

step1.php generates the following JSON

{
    "LeadResponses": [
        {
        "MessageId": "48a71eaa-291e-47a3-978b-ce61f3155706",
        "Decision": "Maybe",
        "BrandName": "CashPower",
        "DecisionReasons": [
            "LES: Consent not given",
            "LES: BureauBcc700Data not collected",
            "LES: PrismStockData not collected",
            "LES: PreQualificationLite Unknown Result"
        ],
        "CustomerType": "New"
        }
    ],
    "MessageId": "dd826184-37e5-4084-935a-ede1c8261745"
}

Then tryajax3.html loads the JSON and tries to display some values – answer 1, 2, 3, and 4 dont display “Maybe” which is what i hoped for

<html>
<body>

    <p id="thejson">placeholder json</p>
    <p id="answer1">placeholder answer1</p>
    <p id="answer2">placeholder answer2</p>
    <p id="answer3">placeholder answer3</p>
    <p id="answer4">placeholder answer4</p>
    <p id="answer5">placeholder answer5</p>

    <script>
        const xmlhttp = new XMLHttpRequest();
        xmlhttp.onload = function () {

            const myObj = JSON.parse(this.responseText);

            // These work
            document.getElementById("thejson").innerHTML = JSON.stringify(myObj);
            document.getElementById("answer5").innerHTML = myObj.MessageId;

            // These dont work - they display "undefined"
            document.getElementById("answer1").innerHTML = myObj.Decision;
            document.getElementById("answer2").innerHTML = myObj.LeadResponses.Decision;
            document.getElementById("answer3").innerHTML = myObj.LeadResponses["Decision"];

            // This displays [object Object]
            document.getElementById("answer4").innerHTML = myObj.LeadResponses;
        }
        xmlhttp.open("GET", "step1.php");
        xmlhttp.send();
    </script>
</body>
</html>

The code above shows the following output from the HTML code

Testing setState from async functions inside hook’s useEffect

I’m writing a hook that uses configcat to fetch a feature flag value for my react-native application.

The hook I drafted looks like this:

import * as configcat from "configcat-js";
import { useEffect, useMemo, useState } from "react";

type FeatureFlagHookResult = [boolean | undefined, boolean, unknown];

/**
 * Hook that returns the value of a feature flag from ConfigCat
 * @param key The key of the feature flag
 * @returns A tuple containing the value of the feature flag, a boolean indicating if the value is ready, and an error if one occurred
 */
export function useFeatureFlag(key: string): FeatureFlagHookResult {
  const [value, setValue] = useState<boolean>();
  const [isReady, setIsReady] = useState(false);
  const [error, setError] = useState<unknown>(null);

  const client = useMemo(() => {
    if (!process.env.EXPO_PUBLIC_CONFIGCAT_SDK_KEY) {
      throw new Error(
        "ConfigCat SDK key is missing. Add EXPO_PUBLIC_CONFIGCAT_SDK_KEY to the .env file.",
      );
    }
    const logger = __DEV__
      ? configcat.createConsoleLogger(configcat.LogLevel.Info)
      : undefined;

    return configcat.getClient(
      process.env.EXPO_PUBLIC_CONFIGCAT_SDK_KEY,
      configcat.PollingMode.AutoPoll,
      {
        logger,
      },
    );
  }, []);

  useEffect(() => {
    async function fetchValue() {
      try {
        const value = await client.getValueAsync(key, false);
        setValue(value);
      } catch (e) {
        setError(e);
      } finally {
        setIsReady(true);
      }
    }
    fetchValue();
  }, [client, key]);

  return [value, isReady, error];
}

the corresponding test like this:

import { renderHook, waitFor } from "@testing-library/react-native";
import * as configcat from "configcat-js";

import { useFeatureFlag } from "./useFeatureFlag";

describe("useFeatureFlag", () => {
  it("should return the value of a feature flag from ConfigCat", async () => {
    const mockGetValueAsync = jest.fn().mockResolvedValue(true);
    const mockClient = {
      getValueAsync: mockGetValueAsync,
    };
    jest.spyOn(configcat, "getClient").mockReturnValue(mockClient as any);

    const { result } = renderHook(() => useFeatureFlag("key"));

    expect(result.current).toEqual([undefined, false, null]);

    await waitFor(() => {
      expect(result.current).toEqual([true, true, null]);
      expect(mockGetValueAsync).toHaveBeenCalledWith("key", false);
    });
  });

  it("should return an error if one occurred", async () => {
    const mockGetValueAsync = jest.fn().mockRejectedValue(new Error("error"));
    const mockClient = {
      getValueAsync: mockGetValueAsync,
    };
    jest.spyOn(configcat, "getClient").mockReturnValue(mockClient as any);

    const { result } = renderHook(() => useFeatureFlag("key"));

    expect(result.current).toEqual([undefined, false, null]);

    await waitFor(() => {
      expect(result.current).toEqual([undefined, true, new Error("error")]);
      expect(mockGetValueAsync).toHaveBeenCalledWith("key", false);
    });
  });
});

given the code works well, the test fails due to some issues setting isReady flag:

 FAIL  src/configcat/useFeatureFlag.test.ts
  useFeatureFlag
    ✕ should return the value of a feature flag from ConfigCat (13 ms)
    ✕ should return an error if one occurred (6 ms)

  ● useFeatureFlag › should return the value of a feature flag from ConfigCat

    expect(received).toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 1

      Array [
        true,
    -   true,
    +   false,
        null,
      ]

      16 |     expect(result.current).toEqual([undefined, false, null]);
      17 |
    > 18 |     await waitFor(() => {
         |                  ^
      19 |       expect(result.current).toEqual([true, true, null]);
      20 |       expect(mockGetValueAsync).toHaveBeenCalledWith("key", false);
      21 |     });

      at Object.<anonymous> (src/configcat/useFeatureFlag.test.ts:18:18)
      at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17)
      at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9)
      at node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:7
      at Object.<anonymous> (node_modules/@babel/runtime/helpers/asyncToGenerator.js:14:12)

  ● useFeatureFlag › should return an error if one occurred

    expect(received).toEqual(expected) // deep equality

    - Expected  - 1
    + Received  + 1

      Array [
        undefined,
    -   true,
    +   false,
        [Error: error],
      ]

      33 |     expect(result.current).toEqual([undefined, false, null]);
      34 |
    > 35 |     await waitFor(() => {
         |                  ^
      36 |       expect(result.current).toEqual([undefined, true, new Error("error")]);
      37 |       expect(mockGetValueAsync).toHaveBeenCalledWith("key", false);
      38 |     });

      at Object.<anonymous> (src/configcat/useFeatureFlag.test.ts:35:18)
      at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17)
      at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9)
      at node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:7
      at Object.<anonymous> (node_modules/@babel/runtime/helpers/asyncToGenerator.js:14:12)

Test Suites: 1 failed, 1 total
Tests:       2 failed, 2 total
Snapshots:   0 total
Time:        0.676 s, estimated 3 s
Ran all test suites matching /useFeatureFlag/i.

One interesting thing that I discovered is that if I call setIsReady twice, everything seems to work. I tried to experiment with promises, async functions, fake timers etc, but no permutation worked so far. What do I miss?

Leaflet control radio does not remain disabled

I am using JavaScript to add disabled=disabled attributes to the .leaflet-control-layers-selector radio inputs.

The disabled attribute remains on the inputs until the user hovers over the .leaflet-control-layers-toggle anchor at which point the disabled attribute disappears.

Is there a more Leaflet-y approach to disabling the base maps or should I try a different approach (such as an event listener on .leaflet-control-layers-toggle to add the attributes then instead)?

How do I get the container of the repeater in Velo, when I have its data?

I am trying to make a button, which scrolls to the container of the repeater. Every tutorial, question on SO or documentation describes the other way around – how to get data from container (by OnClick event for example). However not a single one suggests, how can I do, what I’m trying to do.

This is the fragment of the code I have:

$w.onReady(function () {
    $w('Button').onClick((event) => {
        let whichButtonWasPressed = event.target.id; //The letter of the button
        let repeater = $w('#repeater1');
        for (let i = 0; i < repeater.data.length; i++) {
            if (whichButtonWasPressed == repeater.data[i].nazwisko[0]) //Compare the button letter with the first letter of surname of the author of the container
            {
                console.log(repeater.data[i]);
                break;
                
            }
        }
    })
});

To explain the code:
On Click of a button with a letter it saves, which letter it represents, checks the data of the repeater, finds the first match of a surname. Then is the moment where I am stuck. I just need to get the object (container), to call a ScrollTo() function.

Ideas I’ve come up with, but don’t work:
$w() with id, that is stored in the data of the repeater, is not working (my guess is that it’s an id which is assigned after the repeater is filled with data, so it doesn’t exist in that context
The repeater object for some reason does not have children property, so I cannot just loop for every child container and compare strings.
I cannot use DOM, as Velo forbids that.
There is one question (downvoted) about that, where people suggest using DOM, however, as previously stated, that is impossible because of limitations of the WIX editor.

Use cocoscreator cammand Build WEB_mobile

i useing nodejs child_process to call …CocosCreator.exe –project projectPath –build “platform=web-desktop;debug=true”

jenkins looks finish but stop on —build task finsih— BUT!! jenkins is not stop

and i wait 10m ago and it still on —build task finsih—

is anyone khow to stop it or how to fixed

Targeting Dynamic Chatbox in for Chrome Extension

I’m working on a Chrome extension for my university project, and I’m almost done (about 90% completed). The extension opens Messenger.com and navigates to a specific chat link, but I’m having trouble targeting the chatbox (typing area). The issue is that the CSS Selector/XPath/JS Path seems to be dynamic, and I can’t get a reliable way to select the chat input field.

I’ve tried various solutions and watched tons of videos, but I can’t find a working approach to input text into the chatbox and trigger the send button.

Any advice or suggestions on how to handle dynamic elements like this would be greatly appreciated. This is the final step of my project!

How to use relative path in Next Image?

I want to fetch corresponding product image on each dynamic route in my NextJS project, like this:

    export default function singleProductPage({ params }) {
    const { product_code } = params;
    const imagePath = `../../../../assets/products/Hammer/${product_code}.jpg`;

    return (
        <div>
            <Image src={imagePath} width={300} height={300} alt="xx" />
        </div>
    );
}

But it doesn’t work at all. I use require module instead:

const imagePath = require(`../../../../assets/products/Hammer/${product_code}.jpg`);

It works but got a warning “Only plain objects can be passed to Client Components from Server Components. Module objects are not supported.”

Is there a better way to do this?

Round up a year to the next World Cup year in Javascript

I would like to know how to round up a year to the next World Cup year, like 2024 -> 2026, 2026->2026, or 2031 -> 2034

I really can’t figure out the formula, but I guess I should use the % operator?

My attempt:

let worldCupYear;
const remain = thisYear % 4;
if(remain === 0){
  worldCupYear = 2+ thisYear
}else if(remain != 2){
  worldCupYear = remain + thisYear;
}else{
  worldCupYear = thisYear;
}

Image clipping through navbar when I change opacity

I am using JavaScript to make the background content of my webpage have reduced opacity when the ‘sidebar’ appears.

I have div with the class “burger-icon” which is inside the nav.

I have div with the class “sidebar sidebar-hidden”, which is a hidden sidebar that appears when you click the burger-icon.

And finally, I have a div with the class “frontimage”, which is an image underneath the navbar.

I added position: sticky; to the nav, and now I’ve noticed that when I hit the burger-icon, the image is appearing on-top of the nav when I open the sidebar. This is happening because my background-color for the nav is white, and with the reduced opacity, the image appears through the nav. Changing the z-index doesn’t solve this problem. Does anyone have any ideas?

Here is my html:

<body>
    <nav>
        <div class="burger-icon">
            <span></span>
            <span></span>
        </div>
        <div class="bottom-bar"></div>
    </nav>

    <div class="sidebar sidebar-hidden">
        <div class="close-btn">&times;</div>
    </div>

    <div class="frontimage">
        <img src="imagesa320new.jpg" alt="frontimage">
        <div class="overlay-text">
        </div>
    </div>
</body>

Here is my css:

nav{
  position: sticky;
  top: 0;
  width: 100%;
  z-index: 1;
  background-color: #fff;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: Copperplate, Papyrus, fantasy;
  padding-bottom: 50px;
}

.sidebar {
  z-index: 2;
  position: fixed;
  top: 0;
  width: 500px;
  height: 100%;
  background-color: #fa9537;
  text-align: center;
  text-transform: uppercase;
  font-family: Verdana, sans-serif;
}

.sidebar-hidden {
  display: none;
}

.nav-hidden {
  opacity: 0.5;
}

and here is my JavaScript code:

const sidebar = document.querySelector(".sidebar");
const burgericon = document.querySelector(".burger-icon");
const closebtn = document.querySelector(".close-btn");
const nav = document.querySelector("nav");
const frontimage = document.querySelector(".frontimage");

const opensidebar = function () {
  sidebar.classList.remove("sidebar-hidden");
  nav.classList.add("nav-hidden");
  frontimage.classList.add("nav-hidden");
};

const closesidebar = function () {
  sidebar.classList.add("sidebar-hidden");
  nav.classList.remove("nav-hidden");
  frontimage.classList.remove("nav-hidden");
};

burgericon.addEventListener("click", opensidebar);
closebtn.addEventListener("click", closesidebar);

Webgl2 not loading png

So i have not been able to find any documentation on this problem. I have a 128×128 .png that is loaded by Webgl. Before hand,it loads a solid blue block before the image loads. The solid blue block loads and no errors pop up but the image isn’t able to load.

main.js:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
import { TheShaders } from "./shaders.js";
import { initTextureBuffer2DVec2, isPowerOf2 } from "./texture.js";
import { loadTexture } from "./texture.js";
var shaders = new TheShaders();
var canvas = document.getElementById("canvaselement");
if (canvas === null)
    throw new Error("Could not find canvas element");
var gl = canvas.getContext("webgl2");
if (gl === null)
    throw new Error("Could not get WebGL context");
//triangle
var TestvertexShader = gl.createShader(gl.VERTEX_SHADER);
if (TestvertexShader === null)
    throw new Error("Could not establish vertex shader");
var TestvertexShaderCode = shaders.Testvertexshader;
// Step 3: Attach the shader code to the vertex shader
gl.shaderSource(TestvertexShader, TestvertexShaderCode);
// Step 4: Compile the vertex shader
gl.compileShader(TestvertexShader);
console.log(gl.getShaderInfoLog(TestvertexShader));
var TestfragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
if (TestfragmentShader === null)
    throw new Error("Could not establish fragment shader"); // handle possibility of null
// Step 2: Write the fragment shader code
var TestfragmentShaderCode = shaders.Testfragmentshader;
// Step 3: Attach the shader code to the fragment shader
gl.shaderSource(TestfragmentShader, TestfragmentShaderCode);
// Step 4: Compile the fragment shader
gl.compileShader(TestfragmentShader);
console.log(gl.getShaderInfoLog(TestfragmentShader));

var vertices = new Float32Array([0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5]);
var indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
var shaderProgram = gl.createProgram();
if (shaderProgram === null)
    throw new Error("Could not create shader program");
// Step 2: Attach the vertex and fragment shaders to the program
gl.attachShader(shaderProgram, TestvertexShader);
gl.attachShader(shaderProgram, TestfragmentShader);
gl.linkProgram(shaderProgram);
// Step 3: Activate the program as part of the rendering pipeline
if (gl.useProgram(shaderProgram) === null)
    throw new Error("shader program not able to use");
// Step 1: Initialize the array of vertices for our triangle
// Step 2: Create a new buffer object
var vertex_buffer = gl.createBuffer();
// Step 3: Bind the object to `gl.ARRAY_BUFFER`
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
// Step 4: Pass the array of vertices to `gl.ARRAY_BUFFER
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// Create and bind the element buffer
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
initTextureBuffer2DVec2(gl, vertices, shaderProgram, "a_texcoord");
var Testtexture = loadTexture(gl, "pixil-frame-0 (3).png");
if(Testtexture === null){
    console.log("haioshdioas");
}
else{
    console.log("ok");
    console.log(Testtexture);
}

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
// Tell WebGL we want to affect texture unit 0
gl.activeTexture(gl.TEXTURE0);
// Bind the texture to texture unit 0
gl.bindTexture(gl.TEXTURE_2D, Testtexture);
var TestuSampler = gl.getUniformLocation(shaderProgram, "u_texture");
// Tell the shader we bound the texture to texture unit 0
gl.uniform1i(TestuSampler, 0);
// Step 5: Get the location of the `coordinates` attribute of the vertex shader
var coordinates = gl.getAttribLocation(shaderProgram, "coordinates");
gl.vertexAttribPointer(coordinates, 2, gl.FLOAT, false, 8, 0);
// Step 6: Enable the attribute to receive vertices from the vertex buffer
gl.enableVertexAttribArray(coordinates);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.0, 0.5, 0.5, 1.0);
gl.enable(gl.DEPTH_TEST);
if (gl.clear(gl.COLOR_BUFFER_BIT) === null)
    throw new Error("uncleared");
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
console.log(gl.getParameter(gl.MAX_VERTEX_ATTRIBS) - 1);

shaders.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TheShaders = void 0;
var TheShaders = /** @class */ (function () {
    function TheShaders() {
        this.Testvertexshader = "n  attribute vec2 coordinates;nattribute vec2 a_texcoord;nvarying vec2 v_texcoord;nn  void main(void) {n    gl_Position = vec4(coordinates, 0.0, 1.0);n     // Pass the texcoord to the fragment shader.n     v_texcoord = a_texcoord;n  }";
        this.Testfragmentshader = "n    uniform sampler2D u_texture;nvarying highp vec2 v_texcoord;n nvoid main() {n   gl_FragColor = texture2D(u_texture, v_texcoord);n}";
    }
    return TheShaders;
}());
export{TheShaders};

texture.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

export {initTextureBuffer2DVec2, isPowerOf2,loadTexture};
// Initialize a texture and load an image.
// When the image finished loading copy it into the texture.
//
function loadTexture(gl, url) {
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    // Because images have to be downloaded over the internet
    // they might take a moment until they are ready.
    // Until then put a single pixel in the texture so we can
    // use it immediately. When the image has finished downloading
    // we'll update the texture with the contents of the image.
    var level = 0;
    var internalFormat = gl.RGBA;
    var width = 1;
    var height = 1;
    var border = 0;
    var srcFormat = gl.RGBA;
    var srcType = gl.UNSIGNED_BYTE;
    var pixel = new Uint8Array([0, 1, 255, 255]); // opaque blue
    gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, width, height, border, srcFormat, srcType, pixel);
    var image = new Image();
    image.addEventListener('load', function() {
        image.src = url;
        gl.bindTexture(gl.TEXTURE_2D, texture);
        gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, image);
        // WebGL1 has different requirements for power of 2 images
        // vs. non power of 2 images so check if the image is a
        // power of 2 in both dimensions.
        if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
            // Yes, it's a power of 2. Generate mips.
            gl.generateMipmap(gl.TEXTURE_2D);
        }
        else {
            // No, it's not a power of 2. Turn off mips and set
            // wrapping to clamp to edge
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
        }
        console.log(gl.getError());
    });
    return texture;
}
function isPowerOf2(value) {
    return (value & (value - 1)) === 0;
}
function initTextureBuffer2DVec2(gl, textureCoordinates, shaderProgram, Attribname) {
    var textureCoordBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
    var texcoordLocation = gl.getAttribLocation(shaderProgram, Attribname);
    console.log(texcoordLocation);
    gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
    gl.enableVertexAttribArray(texcoordLocation);
    return textureCoordBuffer;
}

I tried to change the image from 100×100 to 128×128 as mentioned before. I searched for so long any resemblance to this problem and it didn’t help. I tried changing the shaders’ code but nothing worked.

google tasks API “Error fetching tasks: Error: Failed to fetch tasks: 401 Unauthorized”

I’m trying to build a simple tasks web app where users can login with their google accounts and access google tasks via the API. It’s basically for my own use where I want to add an advanced search functionality. I’m not using and don’t want to use any backend services, simple react, javascript app.

However I’m having errors at the start where the app tries to fetch the tasklists via the google API.

Error response body: {
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "errors": [
      {
        "message": "Invalid Credentials",
        "domain": "global",
        "reason": "authError",
        "location": "Authorization",
        "locationType": "header"
      }
    ],
    "status": "UNAUTHENTICATED"
  }
}
Tasks.js:54
    fetchTasks Tasks.js:54
    Tasks Tasks.js:11
    React 7
    workLoop scheduler.development.js:266
    flushWork scheduler.development.js:239
    performWorkUntilDeadline scheduler.development.js:533
    (Async: EventHandlerNonNull)
    js scheduler.development.js:571
    js scheduler.development.js:633
    factory react refresh:6
    Webpack 24
Error fetching tasks: Error: Failed to fetch tasks: 401 Unauthorized
    fetchTasks Tasks.js:55
    Tasks Tasks.js:11

Also in the network tab, I see 401 Unauthorized error when using GET method to access tasks.googleapis.com

I believe I configured google cloud correctly. I tried to add the screenshots however my message was seen as spam so I removed them.

  • Google Tasks API is enabled.
  • javascript origins dhould be OK.
  • Redirect URLs also should be OK.
  • client ID is correct in .env file.
  • authorized domain are not necessary at this point but:
  • scopes are added
  • test users are added

Here are my files:

const loadGoogleScript = () => {
    return new Promise((resolve) => {
        if (typeof window.google !== 'undefined') {
            resolve();
        } else {
            const script = document.createElement('script');
            script.src = 'https://accounts.google.com/gsi/client';
            script.async = true;
            script.defer = true;
            script.onload = resolve;
            document.body.appendChild(script);
        }
    });
};

export const initializeGoogleAuth = async () => {
    await loadGoogleScript();
    console.log("Using Client ID:", process.env.REACT_APP_GOOGLE_CLIENT_ID);
    window.google.accounts.id.initialize({
        client_id: process.env.REACT_APP_GOOGLE_CLIENT_ID,
        callback: handleCredentialResponse,
        scope: 'email profile https://www.googleapis.com/auth/tasks'
    });
};

export const handleCredentialResponse = (response) => {
    if (response.error) {
        console.error("Error during Google Sign-In:", response.error);
        return;
    }
    console.log("Encoded JWT ID token: " + response.credential);
    const decodedToken = JSON.parse(atob(response.credential.split('.')[1]));
    console.log("Decoded token:", decodedToken);

    localStorage.setItem('token', response.credential);
    localStorage.setItem('user', JSON.stringify({
        name: decodedToken.name,
        email: decodedToken.email
    }));
    window.location.href = '/welcome';
};

export const renderGoogleSignInButton = () => {
    if (typeof window.google !== 'undefined') {
        window.google.accounts.id.renderButton(
            document.getElementById("googleSignInButton"),
            {
                theme: "outline",
                size: "large",
                type: "standard",
                shape: "rectangular",
                text: "signin_with",
                logo_alignment: "left",
            }
        );
        window.google.accounts.id.prompt();
    } else {
        console.error('Google Sign-In script not loaded');
    }
};

export const isAuthenticated = () => {
    return localStorage.getItem('user') !== null;
};

export const logout = () => {
    localStorage.removeItem('user');
    localStorage.removeItem('token');
    window.location.href = '/';
};

export const getAccessToken = () => {
    return localStorage.getItem('token');
};
import React, { useState, useEffect } from 'react';
import { getAccessToken } from '../services/auth';

const Tasks = () => {
    const [tasks, setTasks] = useState([]);
    const [newTask, setNewTask] = useState('');
    const [searchTerm, setSearchTerm] = useState('');
    const [error, setError] = useState(null);

    useEffect(() => {
        fetchTasks();
    }, []);

    const logRequest = (url, options) => {
        console.log('Outgoing request:', {
            url,
            method: options.method || 'GET',
            headers: options.headers,
            body: options.body
        });
    };

    const logResponse = async (response) => {
        const clone = response.clone();
        const data = await clone.text();
        console.log('Response received:', {
            status: response.status,
            statusText: response.statusText,
            headers: Object.fromEntries(response.headers.entries()),
            data: data
        });
    };

    const fetchTasks = async () => {
        try {
            const accessToken = getAccessToken();
            if (!accessToken) {
                throw new Error('No access token available');
            }

            console.log('Access Token:', accessToken);

            const response = await fetch('https://tasks.googleapis.com/tasks/v1/users/@me/lists', {
                headers: {
                    'Authorization': `Bearer ${accessToken}`
                }
            });

            console.log('Response status:', response.status);
            console.log('Response headers:', JSON.stringify([...response.headers]));

            if (!response.ok) {
                const errorBody = await response.text();
                console.error('Error response body:', errorBody);
                throw new Error(`Failed to fetch tasks: ${response.status} ${response.statusText}`);
            }

            const data = await response.json();
            console.log('Tasks response:', data);
            setTasks(data.items || []);
        } catch (error) {
            console.error('Error fetching tasks:', error);
            console.error('Error stack:', error.stack);
            setError('Failed to fetch tasks. Please try again.');
        }
    };

    const addTask = async () => {
        try {
            const accessToken = getAccessToken();
            if (!accessToken) {
                throw new Error('No access token available');
            }

            const response = await fetch('https://tasks.googleapis.com/tasks/v1/lists/@default/tasks', {
                method: 'POST',
                headers: {
                    'Authorization': `Bearer ${accessToken}`,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ title: newTask })
            });

            if (!response.ok) {
                throw new Error('Failed to add task');
            }

            const data = await response.json();
            setTasks([...tasks, data]);
            setNewTask('');
        } catch (error) {
            console.error('Error adding task:', error);
            setError('Failed to add task. Please try again.');
        }
    };

    const deleteTask = async (taskId) => {
        try {
            const accessToken = getAccessToken();
            if (!accessToken) {
                throw new Error('No access token available');
            }

            const response = await fetch(`https://tasks.googleapis.com/tasks/v1/lists/@default/tasks/${taskId}`, {
                method: 'DELETE',
                headers: {
                    'Authorization': `Bearer ${accessToken}`
                }
            });

            if (!response.ok) {
                throw new Error('Failed to delete task');
            }

            setTasks(tasks.filter(task => task.id !== taskId));
        } catch (error) {
            console.error('Error deleting task:', error);
            setError('Failed to delete task. Please try again.');
        }
    };

    const editTask = async (taskId, newTitle) => {
        try {
            const accessToken = getAccessToken();
            if (!accessToken) {
                throw new Error('No access token available');
            }

            const response = await fetch(`https://tasks.googleapis.com/tasks/v1/lists/@default/tasks/${taskId}`, {
                method: 'PATCH',
                headers: {
                    'Authorization': `Bearer ${accessToken}`,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ title: newTitle })
            });

            if (!response.ok) {
                throw new Error('Failed to edit task');
            }

            const data = await response.json();
            setTasks(tasks.map(task => task.id === taskId ? data : task));
        } catch (error) {
            console.error('Error editing task:', error);
            setError('Failed to edit task. Please try again.');
        }
    };

    const filteredTasks = tasks.filter(task =>
        task.title.toLowerCase().includes(searchTerm.toLowerCase())
    );

    return (
        <div>
            <h2>My Tasks</h2>
            {error && <p style={{ color: 'red' }}>{error}</p>}
            <input
                type="text"
                placeholder="Search tasks"
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
            />
            <div>
                <input
                    type="text"
                    placeholder="Add new task"
                    value={newTask}
                    onChange={(e) => setNewTask(e.target.value)}
                />
                <button onClick={addTask}>Add Task</button>
            </div>
            {filteredTasks.length === 0 ? (
                <p>No tasks found.</p>
            ) : (
                <ul>
                    {filteredTasks.map(task => (
                        <li key={task.id}>
                            {task.title}
                            <button onClick={() => deleteTask(task.id)}>Delete</button>
                            <button onClick={() => editTask(task.id, prompt('Enter new title', task.title))}>Edit</button>
                        </li>
                    ))}
                </ul>
            )}
        </div>
    );
};

export default Tasks;

The only successful approach was to use mongoDB at backend but I don’t want to use any backend services.