Date and Time picker alignment issue with bootstrap 5.3 version and formIO “flatpickr-calendar”

I am working in FORMIO + bootstrap 5.3 version + flatpickr-calendar.
I added date and time picker for Start date, Start time fields using FORMIO
I added required validation on these fields.. at js end because some condition required for validation.
I used code like below

formio.getComponent("startDate").component.validate.required = true
formio.getComponent("startTime").component.validate.required = true

With this above code.. when i focus in the element field for open date picker or time picker. both picker’s aligment become wrong. Some time below 100px.. Some time above.

When i hide this required=true.. then both date and time picker work correctly.

Please suggest what i need to do here. because i need both fields required on some cases. I can’t make it required from FORMIO.

ExTester Automated Test Visual Studio Code Change version on the Extension Plugin

When I open the plugin extension page,
When I click Uninstall more actions button,
Then install another version and uninstall options listed,
And other versions listed to change version of the plugin.

And it can’t locate the Install Another Version.. submenu item:

  1. Change Version extension:
    TimeoutError: Waiting for element to be located By(xpath, //li[contains(text(), “Install Another Version…”)])
    Wait timed out after 15192ms
import { expect } from 'chai';
import { ExtensionsViewSection, SideBarView, ActivityBar, ExtensionsViewItem, InputBox } from 'vscode-extension-tester';
import { By, until, WebDriver } from 'selenium-webdriver';

describe('Change Version of the Plugin Extension', () => {
    let section: ExtensionsViewSection;
    let items: ExtensionsViewItem[];
    let driver: WebDriver;

    before(async function () {
        this.timeout(120000); // Increase timeout to allow more time for loading and actions

        // Open the Extensions view
        const viewControl = await new ActivityBar().getViewControl('Extensions');
        if (!viewControl) throw new Error('Extensions view not found');
        await viewControl.openView();

        // Get the Installed section in the Extensions view
        section = await new SideBarView().getContent().getSection('Installed') as ExtensionsViewSection;
        driver = section.getDriver(); // Initialize WebDriver for more granular control
    });

    it('should change the version of theP lugin extension', async () => {
        // Clear any previous searches and find installed extensions
        await section.clearSearch();
        items = await section.getVisibleItems() as ExtensionsViewItem[];

        // Find the Plugin extension in the installed section
        const plugin = items.find(async (item) => (await item.getTitle()) === 'PLugin');
        expect(plugin).to.exist;

        if (plugin) {
            const isInstalled = await plugin.isInstalled();
            expect(isInstalled).to.be.true;

            // Right-click on the plugin to open the context menu
            await plugin.openContextMenu();
            console.log('Opened context menu for Plugin extension.');

            // Select the "Install Another Version..." option from the context menu
            const installAnotherVersionItem = await driver.wait(
                until.elementLocated(By.xpath('//li[contains(text(), "Install Another Version...")]')),
                15000
            );
            await installAnotherVersionItem.click();
            console.log('Clicked "Install Another Version..." Plugin extension.');
        }
    });
});

Contao select box with chosen=true not working

I am looking to update the second select box based on first selectbox value change.

let event = new Event {'chosen:updated'};
document.getElementById('selectboxSecond').dispatchEvent(event);

but actual select box have new innerHTML i updated using javascript but the div contao created is not updating. without jQuery i wanna do. Can someone please help me what i am doing wrong .

Getter and setter ignored in a custom element

I came accross an odd problem using WebComponents and composing them. I created a minimal HTML page to reproduce the problem.

I’m basically trying to build the following structure :

  • custom list
  • containing custom items
  • each item containing a custom input to show the item name

My custom input is a wrapper to add label to a basic input and I use get and set on my custom input so that its value mirror the basic input value.

It works perfectly in isolation : getting and setting the value of my custom input gets and sets the value of the basic input inside it.
It also works fine inside my custom item : getting and setting its item correctly mirrors the item name on the custom input.

But when I manage items through my custom list, it breaks. The getter and setter of my custom input seem to have disappeared and fallback to a normal property with no accessors functions.

Here’s the minimal code to reproduce the problem :

    const customInputTemplate = document.createElement("template");
    customInputTemplate.innerHTML = `
    <label id="label" for="input"></label>
    <input id="input" type="text" />
    `;

    window.customElements.define("my-custom-input", class MyCustomInput extends HTMLElement {
      static get observedAttributes() {
        return ["label"]
      }

      constructor() {
        super();
        this.attachShadow({ mode: "open"});
        this.shadowRoot.appendChild(customInputTemplate.content.cloneNode(true));

        this.labelElemenet =  this.shadowRoot.getElementById("label");
        this.inputElement = this.shadowRoot.getElementById("input");
      }

      get value() { // This seems to be ignored or unset in certain cases
        return this.inputElement.value;
      }

      set value(newValue) { // This also has the problem
        this.inputElement.value = newValue;
      }

      attributeChangedCallback(name, oldValue, newValue) {
        if (name === "label") {
          this.labelElemenet.innerText = newValue;
        }
      }
    });

    const customItemTemplate = document.createElement("template");
    customItemTemplate.innerHTML = `
      <li>
        <my-custom-input id="custom-input" label="Item :"></my-custom-input>
      </li>
    `;

    window.customElements.define("my-custom-item", class MyCustomItem extends HTMLElement {
      #item;

      constructor() {
        super();
        this.attachShadow({ mode: "open"});
        this.shadowRoot.appendChild(customItemTemplate.content.cloneNode(true));

        this.customInputElement =  this.shadowRoot.getElementById("custom-input");
      }

      get item() {
        return this.#item;
      }

      set item(newItem) {
        this.#item = newItem;
        this.#render();
      }

      #render() {
        if (this.customInputElement.value !== this.#item.name) {
          this.customInputElement.value = this.#item.name
        }
      }
    });

    const customListTemplate = document.createElement("template");
    customListTemplate.innerHTML = `
      <ul>
        <slot></slot>
      </ul>
    `;

    window.customElements.define("my-custom-list", class MyCustomList extends HTMLElement {
      #items;

      constructor() {
        super();
        this.attachShadow({ mode: "open"});
        this.shadowRoot.appendChild(customListTemplate.content.cloneNode(true));
      }

      get items() {
        return this.#items;
      }

      set items(newItems) {
        this.#items = newItems;
        this.#render();
      }

      #render() {
        this.replaceChildren(...this.#items.map(item => {
          const itemElement = document.createElement("my-custom-item");
          itemElement.item = item; // This is where things get broken
          return itemElement;
        }));
      }
    });

    const customInputElement = document.getElementById("my-custom-input");
    customInputElement.value = "Some value for my custom input";

    const customItemElement = document.getElementById("my-custom-item");
    customItemElement.item = { id: "Z", name: "Some name for my custom item"};

    const listElement = document.getElementById("my-list");

    listElement.items = [
      { id: "A", name: "Item A" },
      { id: "B", name: "Item B" },
      { id: "C", name: "Item C" },
    ];

    // All inputs are empty instead of showing the item names

    const firstItem = listElement.querySelector("my-custom-item");
    const customInputOfFirstItem = firstItem.shadowRoot.querySelector("my-custom-input");

    console.log("customInputOfFirstItem.value = ", customInputOfFirstItem.value); // Correctly logs "Item A"

    // Trying to force value
    customInputOfFirstItem.value = "Updated item A";
    console.log("After forcing value, customInputOfFirstItem.value = ", customInputOfFirstItem.value); // Correctly logs "Updated item A"

    // But ...
    const originalInput = customInputOfFirstItem.shadowRoot.getElementById("input");
    console.log("Original input value = ", originalInput.value); // Logs empty value
    // Forcing it
    originalInput.value = "Forced inside value for item A";
    console.log("After forcing inside value, customInputOfFirstItem.value = ", customInputOfFirstItem.value); // Still logs "Updated item A"

    // It's acting as if getter (line 37) and setter (line 41) where ignored or somewhat unset in the process
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Web Component</title>
</head>

<body>
  <h3>Custom input, works fine</h3>
  <my-custom-input id="my-custom-input" label="Custom input"></my-custom-input>

  <h3>Custom item, also works fine</h3>
  <my-custom-item id="my-custom-item"></my-custom-item>

  <h3>Inside custom list, does not work</h3>
  <my-custom-list id="my-list"></my-custom-list>
</body>

</html>

Does Google allow trusted web applications to access USB devices ? If yes, how to set it up? [closed]

I work for an information kiosk development company and I was given the task of creating a library for working with USB devices in an information kiosk. I implemented this using “navigator.usb”, but ran into a problem: this implementation requires the user to manually press a button to grant access to the USB device. However, I need the connection to happen automatically, without user interaction. I found that automatic access can be configured using “Chrome Enterprise Policy”. However, I don’t understand how to apply these policies in an Electron js application. How can I configure and use “Chrome Enterprise Policy” in Electron js to automatically connect USB devices? Is this possible?

Make the element sticky untill the scroll driven animation is finished

Here’s what I’m trying to achieve:

enter image description here

-when the elements become visible to the user, the scroll-driven rotate animation starts on them one-by-one,and all 3 elements become sticky (meaning that they do not disappear while the user is scrolling down) until the animation on the last one is finished.
-when the animation is finished, the page returns to its normal behavior

Executable code:

This code doesn’t make the elements sticky when needed.

document.addEventListener('DOMContentLoaded', function() {
  const elements = document.querySelectorAll('.animation');
  let delay = 0;

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.style.animationDelay = `${delay}s`;
        entry.target.style.animationPlayState = 'running';
        console.log('running');

        // Add sticky class when the element is in view
        entry.target.classList.add('sticky');

        delay += 2.5; // Increase delay for the next element
        observer.unobserve(entry.target); // Stop observing once the animation is triggered
      }
    });
  }, {
    threshold: 0.5
  }); // Trigger when 50% of the element is in view

  elements.forEach(element => {
    console.log('paused');
    element.style.animationPlayState = 'paused'; // Pause animation until triggered
    observer.observe(element);

    // Remove sticky class after the animation ends
    element.addEventListener('animationend', () => {
      console.log('animationend')
      element.classList.remove('sticky');
    });
  });
});
.content {
  width: 75%;
  max-width: 800px;
  margin: 0 auto;
}

p,
h1 {
  font-family: Arial, Helvetica, sans-serif;
}

h1 {
  font-size: 3rem;
}

p {
  font-size: 1.5rem;
  line-height: 1.5;
}

.animation {
  view-timeline: --subjectReveal block;
  animation-timeline: --subjectReveal;
  width: 200px;
  height: 200px;
  background-color: bisque;
  animation-iteration-count: 1;
  animation-name: mymove;
  animation-duration: 3s;
  position: relative;
  /* Normal position */
}

.animation:nth-child(1) {
  animation-delay: calc(var(--subjectReveal) * 1);
}

.animation:nth-child(2) {
  animation-delay: calc(var(--subjectReveal) * 2);
}

.animation:nth-child(3) {
  animation-delay: calc(var(--subjectReveal) * 3);
}


/* Define the sticky behavior */

.sticky {
  position: sticky;
  top: 10px;
  /* Adjust top as needed */
  z-index: 10;
  /* Ensure it stays on top */
}

@keyframes mymove {
  0% {
    opacity: 1;
    transform: rotate(0deg);
  }
  50% {
    opacity: 1;
    transform: rotate(90deg);
  }
  100% {
    opacity: 1;
    transform: rotate(180deg);
  }
}




.as-console-wrapper { height:50px; }
Scroll this
<div style="height:1000px; min-height: 300px; max-width: 100%; display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
  <div class="animation"></div>
  <div class="animation"></div>
  <div class="animation"></div>
</div>

How to check css property already present in an element in javascript

I have a div

<div id="myDiv" style="border:1px solid white; width:20px; height: 100px">....</div>

now in Js, if border css property is already present I need to remove that by using

let element = document.getElementById("myDiv")
element.style.removeProperty("border");

if border css property not present, need to add

let element = document.getElementById("myDiv")
element.style.border = '1px solid white'

but, How to check whether the css property(border) exists or not in element(myDiv)

Why do my line graph dashed grid lines disappear when I hover over graph point data?

My Chart.js line graph dashed border grid line vanishes for few few seconds when I hover over graph point data. This also happens when I activate and deactivate datasets using the “This Month” and “Last Month” toggles.
Also, my data line appears to be backwards of those grid lines. The grid lines are supposed to be backward of the data line.

I tried increasing the z index for data lines, but it still shows the data line backward of the grid line.
Also, regarding the grid line disappearing concerns, I tried plain grid lines, which worked, but I wanted to use dashed border grid lines.

I want those grid lines to be backward of the data line, and when I hover over a graph point, it should stay fixed rather than disappear for a few seconds. Also, when I activate and deactivate a data line using the toggle option, the grid line should not vanish at all.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Line graph</title>
    <link rel="stylesheet" href="../css/bootstrap.min.css">
    <style>
        .market-activity-chart-container {
            width: 100%;
            height: auto;
            margin: 0 auto;
        }

        .market-activity-chart-container canvas {
            background: #ffffff; 
            width: 100%; 
            max-width: 700px;
            height: 100%; 
        }

        .market-this-months,
        .market-last-months {
            display: flex;
            align-items: center;
            gap: 8px;
            cursor: pointer;
            opacity: 0.5;
            transition: opacity 0.3s; 
        }

        .market-this-months.active,
        .market-last-months.active {
            opacity: 1;
        }

        .market-months-flex {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 16px;
        }

    </style>
</head>
<body>

    <div class="row justify-content-center">
        <div class="col-5">
            <div class="dashboard-card">
                <div class="market-activity-chart-container">
                    <canvas id="marketActivityChart"></canvas>
                </div>
                <div class="market-months-flex">
                    <div class="market-this-months active" id="toggleThisMonth">
                        <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
                            <circle cx="6" cy="6" r="4.5" fill="white" stroke="#5159A7" stroke-width="3"/>
                        </svg>
                        <span>This Month</span>
                    </div>
                    <div class="market-last-months" id="toggleLastMonth">
                        <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
                            <circle cx="6" cy="6" r="4.5" fill="white" stroke="#F8C140" stroke-width="3"/>
                        </svg>
                        <span>Last Month</span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <script src="../js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script>
        const ctxMarketActivity = document.getElementById('marketActivityChart').getContext('2d');

        const marketActivityData = {
            labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
            datasets: [
                {
                    label: 'This Month',
                    data: [5500, 2800, 3800, 3900, 7800, 5800, 7600, 4000],
                    borderColor: '#4F45B6',
                    borderWidth: 5,
                    fill: false,
                    tension: 0,
                    pointRadius: 0, 
                    pointHoverRadius: 5, 
                    order: 2,
                },
                {
                    label: 'Last Month',
                    data: [3800, 2700, 2800, 1400, 6000, 5500, 5600, 3800],
                    borderColor: '#F8C140',
                    borderWidth: 5,
                    fill: false,
                    tension: 0,
                    pointRadius: 0, 
                    pointHoverRadius: 5, 
                    order: 2,
                }
            ]
        };

        const marketActivityChart = new Chart(ctxMarketActivity, {
            type: 'line',
            data: marketActivityData,
            options: {
                responsive: true,
                scales: {
                    y: {
                        beginAtZero: false,
                        min: 1000,
                        max: 10000,
                        ticks: {
                            stepSize: 2000,
                            callback: function(value) {
                                return value >= 1000 ? value / 1000 + 'k' : value;
                            },
                            font: {
                                family: 'Gilroy-Medium',
                                size: 18,
                                style: 'normal',
                                weight: '400'
                            },
                            color: '#101839',
                            lineHeight: 34,
                            textTransform: 'capitalize',
                            opacity: 0.4,
                            padding: 16
                        },
                        grid: {
                            display: false
                        },
                        border: {
                            display: false
                        }
                    },
                    x: {
                        ticks: {
                            display: false
                        },
                        grid: {
                            display: false
                        }
                    }
                },
                plugins: {
                    legend: {
                        display: false
                    },
                    tooltip: {
                        enabled: false, 
                        external: function(context) {
                            const { chart, tooltip } = context;
                            const tooltipEl = document.querySelector('.chartjs-tooltip') || document.createElement('div');

                            if (!document.querySelector('.chartjs-tooltip')) {
                                tooltipEl.classList.add('chartjs-tooltip');
                                tooltipEl.style.position = 'absolute';
                                tooltipEl.style.pointerEvents = 'none';
                                tooltipEl.style.color = '#fff';
                                tooltipEl.style.padding = '10px 28px'; 
                                tooltipEl.style.borderRadius = '10px';
                                tooltipEl.style.fontSize = '20px';
                                tooltipEl.style.fontFamily = 'Arial, sans-serif';
                                tooltipEl.style.zIndex = 1000; 
                                document.body.appendChild(tooltipEl);
                            }

                            if (tooltip.opacity === 0) {
                                tooltipEl.style.opacity = 0;
                                return;
                            }

                            // Determine tooltip background color based on dataset
                            const datasetIndex = tooltip.dataPoints[0].datasetIndex;
                            tooltipEl.style.backgroundColor = datasetIndex === 1 ? '#F8C140' : '#5159A7';

                            // Tooltip content
                            const tooltipData = tooltip.dataPoints.map(dp => `<div>${dp.formattedValue}</div>`).join('');
                            tooltipEl.innerHTML = tooltipData;

                            // Tooltip position
                            const position = chart.canvas.getBoundingClientRect();
                            tooltipEl.style.opacity = 1;
                            tooltipEl.style.left = `${position.left + window.pageXOffset + tooltip.caretX}px`;
                            tooltipEl.style.top = `${position.top + window.pageYOffset + tooltip.caretY}px`;
                        }
                    }
                },
                animation: {
                    onComplete: function() {
                        const chartArea = marketActivityChart.chartArea;
                        const yScale = marketActivityChart.scales.y;
                        const ctx = marketActivityChart.ctx;

                        const yLabels = yScale.ticks.map(tick => tick.value);

                        ctx.save();
                        ctx.strokeStyle = '#A098AE';
                        ctx.lineWidth = 1;
                        ctx.setLineDash([6, 6]);

                        yLabels.forEach(label => {
                            const yPos = yScale.getPixelForValue(label);
                            ctx.beginPath();
                            ctx.moveTo(chartArea.left, yPos);
                            ctx.lineTo(chartArea.right, yPos);
                            ctx.stroke();
                        });

                        ctx.restore();
                    }
                },
                elements: {
                    point: {
                        radius: function(context) {
                            return context.active ? 5 : 0;
                        }
                    }
                }
            }
        });

        function updateToggleStates() {
            const thisMonthButton = document.querySelector('.market-this-months');
            const lastMonthButton = document.querySelector('.market-last-months');
            
            // Check dataset visibility and update classes
            if (marketActivityChart.getDatasetMeta(0).hidden) {
                thisMonthButton.classList.add('inactive');
                thisMonthButton.classList.remove('active');
            } else {
                thisMonthButton.classList.add('active');
                thisMonthButton.classList.remove('inactive');
            }

            if (marketActivityChart.getDatasetMeta(1).hidden) {
                lastMonthButton.classList.add('inactive');
                lastMonthButton.classList.remove('active');
            } else {
                lastMonthButton.classList.add('active');
                lastMonthButton.classList.remove('inactive');
            }
        }

        updateToggleStates();

        // Toggle visibility 
        document.querySelector('.market-this-months').addEventListener('click', function() {
            const dataset = marketActivityChart.getDatasetMeta(0);
            dataset.hidden = !dataset.hidden;
            marketActivityChart.update();

            updateToggleStates();
        });

        document.querySelector('.market-last-months').addEventListener('click', function() {
            const dataset = marketActivityChart.getDatasetMeta(1);
            dataset.hidden = !dataset.hidden;
            marketActivityChart.update();
            updateToggleStates();
        });
       
    </script>
</body>
</html>

Expo React Native : Build failed: Gradle build failed with unknown error. See logs for the “Run gradlew” phase for more information

I can’t build my application with expo for android. Everything works fine on emulators.

I launch the command line

eas build -p android --profile preview

With this config in my file eas.json

{
  "build": {
    "preview": {
      "android": {
        "buildType": "apk"
      }
    }
  }
}

I get this error in expo console

> Task :expo-modules-core:configureCMakeRelWithDebInfo[arm64-v8a]
"Install CMake 3.22.1 v.3.22.1" finished.
> Task :react-native-ad-manager:extractReleaseAnnotations
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:createBundleReleaseJsAndAssets'.
> Process 'command 'node'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 3m 26s
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.8/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
370 actionable tasks: 370 executed
Error: Gradle build failed with unknown error. See logs for the "Run gradlew" phase for more information.

When I check with this command line

npx expo-doctor

My dependencies everything seems correct

✔ Check Expo config for common issues
✔ Check package.json for common issues
✔ Check native tooling versions
✔ Check if the project meets version requirements for submission to app stores
✔ Check dependencies for packages that should not be installed directly
✔ Check for common project setup issues
✔ Check for app config fields that may not be synced in a non-CNG project
✔ Check npm/ yarn versions
✔ Check for issues with metro config
✔ Check Expo config (app.json/ app.config.js) schema
✔ Check for legacy global CLI installed locally
✔ Check that native modules do not use incompatible support packages
✔ Check that packages match versions required by installed Expo SDK
✔ Check that native modules use compatible support package versions for installed Expo SDK

Didn't find any issues with the project!

My app.json

{
  "expo": {
    "name": "Breathe",
    "slug": "Breathe",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "light",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "cover",
      "backgroundColor": "#2196F3"
    },
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.mergelight.breathe"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.mergelight.breathe"
    },
    "web": {
      "favicon": "./assets/favicon.png"
    },
    "plugins": [
      "expo-secure-store",
      "expo-localization"
    ],
    "extra": {
      "eas": {
        "projectId": "..."
      }
    }
  }
}

Can you help me get my android build ?
Thx

Is there a way to find the inverse of a higher order function?

Let’s say I have a higher order function that repeats a function twice:

const twice = f => x => f(f(x))

Is there any way I can write a function where I input the result of an instance of evaluation of twice, and it can return f?

const find_f (twice, result) => f

I have experimented with a lot of versions but can’t seem to find a way to “extract” f from the twice function.

What is the mechanism of to fetch and listen data in React

I would like to learn best approach to use SSR and CSR in React/NextJS. I watch a lot videos on Youtube about SSR and I learn the basics and theoretical knowledge about the theory of rendering.

Even if they are helpful, i did not see any case deeply linked to daily conditions.

Lets image we have 3 files. Dashboard page includes GeneralComponentInDashboard and FetchButtonComponent. GeneralComponentInDashboard has SubGenericComponentInGeneralComponent.

/dashboard/page.tsx
/Component/GeneralComponentInDashboard/page.tsx
Component/SubGenericComponentInGeneralComponent
Component/FetchButtonComponent

And also we use state management library (Redux, MobX etc, please share your suggestion)

The condition should be:

  • Initial data will be fetched from API while page loading. [It return array of models lets say [ [name: string, surname: string], …]. SSR.

  • When the user click the fetch button, new dataset will be set to array and display on GeneralComponentInDashboard without reloading page.

  • SubGenericComponentInGeneralComponent will be generic component as I sad, it takes only model (name: string, surname: string)

How should be the approach of building website with best performance in this popular scenario ? What page or component should be ‘use client’ and also where should be fetching operation ?

Additonally, I am open the suggestion of libraries to make process fast.

Thanks for your reply.

The condition should be:

  • Initial data will be fetched from API while page loading. [It return array of models lets say [ [name: string, surname: string], …]. SSR.

  • When the user click the fetch button, new dataset will be set to array and display on GeneralComponentInDashboard without reloading page.

  • SubGenericComponentInGeneralComponent will be generic component as I sad, it takes only model (name: string, surname: string)

Lambda function body is null

I have a front-end and a backend where I am setting up for the first time AWS lambda functions. However, from my frontend POST request, I receive null data in the body.

As I understand, it is sending OPTIONS first to validate the headers, and after that should send the POST request. But this isn’t happening. I am unsure if the order should be happening under the hood.

Any help will be appreciated.

Frontend req:

const sendConfig = async () => {
        const url = 'http://127.0.0.1:3000/api/data/config'; // TODO: change to real env api url
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(configuration),
                mode: 'cors'
            });

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

            const result = await response.json();
            console.log("Config: ", result);
        } catch (error) {
            console.log('Error:', error.message);
        }
    };

Backend:

module.exports.configDataHandler = async (event, context) => {
        if (event.httpMethod === 'OPTIONS') {
            console.log("event: ", event)
            return {
                statusCode: 200,
                headers: {
                    'Access-Control-Allow-Origin': 'http://localhost:3000', // Substitua pela origem correta
                    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
                    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
                },
                body: null
            };
        }
    
        try {
            console.log("Received event: ", event);
    
            const body = JSON.parse(event.body);
            console.log("Received config: ", body);
    
            return {
                statusCode: 200,
                body: JSON.stringify({ message: 'Received config:', body })
            };
        }
        catch (error) {
            console.error('Error processing request:', error);
            return {
                statusCode: 500,
                body: JSON.stringify({ message: error.message })
            };
        }
    };

Lambda:

  ConfigFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: server.configDataHandler
      Runtime: nodejs18.x
      CodeUri: .
      Timeout: 60
      Environment:
        Variables:
          NODE_ENV: dev
      Events:
        DataApi:
          Type: Api
          Properties:
            Path: /api/data/config
            Method: any

Next.js access (req) in Server Action

So i have a client side where there’s a button. The button calls a Server Action (Server Function) and it all works well. But i can’t access the request of the client. Such as if i want to rate limit the user so they can’t spam it.

request returns undefined.

neither do i want to send their ip from the client because then i would have to trust the client and its easy to spoof the parameters.

'use client';

import { Test } from '@/app/actions/test';

export default function TestPage() {
  return <button onClick={() => Test()}>Test</button>;
}
'use server';

import { NextRequest } from 'next/server';

export async function Test(request: NextRequest) {
  console.log(request);
}

All links on google are purple i have not found a solution to this problem.

Firestore Security Rules: getUserOrganization() Not Returning Correct Value for Matching Document ID

I’m working on setting up Firestore security rules, but I’m facing an issue where my custom function getUserOrganization() doesn’t seem to return the correct value when used in matching conditions. Specifically, the function is supposed to return the organization ID of the authenticated user, but the matching condition doesn’t seem to work as expected.

  • I have the following security rules to restrict access to documents in the Organisations collection based on the user’s organization:
rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
  
    match /Users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
    
    match /Organisations/{orgId} {
      allow read, write: if request.auth != null && getUserOrganization() == orgId;
      
      match /{subcollection=**}/{docId} {
        allow read, write: if request.auth != null && getUserOrganization() == orgId;
      }
    }
  }

  // Function to get the user's organization from their document
  function getUserOrganization() {
    return get(/databases/$(database)/documents/Users/$(request.auth.uid)).data.organisation.id;
  }
}

Issue

When I try to access an organization document using the rule:

allow read, write: if request.auth != null && getUserOrganization() == orgId;

It throws a permission error. However, if I hardcode the organization ID like this:

allow read, write: if request.auth != null && "Sjc7mG12B0LPPe5bcJOf" == orgId;

The rule works as expected, and access is granted.

This leads me to believe that the getUserOrganization() function might not be returning the correct value or might be returning a value in a different format (e.g., different data type, string encoding, etc.).

What I’ve Tried:

  • Verified that the organization ID in the user’s document is correctly set and matches the organization document ID.
  • Confirmed that the getUserOrganization() function is correctly fetching the organization ID from the user’s document.

Additional Information:

  • The getUserOrganization() function is supposed to return the organization ID from the user’s document in the Users collection.
  • The organisations.id field in the Users document is a string, and it matches the ID of documents in the Organisations collection.

Any insights or suggestions on how to fix this issue would be greatly appreciated.