Django/CKEditor – config for extraProviders

How can I configure a simple extraProvider for local media in my CKEDITOR_5_CONFIGS in the settings.py file? I tested the configuration below via javascript and it worked fine, but when I switched to python, I got the error Uncaught CKEditorError: this._previewRenderer is not a function. I’m almost giving up and moving on to another alternative, such as directly editing the app.js file of the django-ckedtor-5 library. Any suggestions?

CKEDITOR_5_CONFIGS = {
    ...
    'mediaEmbed': {
        'previewsInData': True,
        'extraProviders': [
            {
                'name': 'LocalProvider',
                'url': '/^https?://[^/]+/media/videos/(.+.(mp4|avi|mov|webm|ogg|mkv))$/',
                'html': 'match => `<video width="640" height="360" controls><source src="${match[0]}" type="video/${match[2]}">Seu navegador não suporta vídeo.</video>`'
            },
        ]
    }
}

enter image description here

enter image description here

how to fully customize element-plus component (tree)

Im building a text editor.
the app has a folder structure where the user can create folders with childrens in it (files and other folders), or just an empty file without children.

Im using the “Tree” component from Elementplus: https://element-plus.org/en-US/component/tree.

I need to fully customize the component e.g change the tree node icon if the element isnt a folder. or change the color and form of the icon.

Is that possible? i couldnt find anything helpful.

Extending the chart line beyond its limits in ECharts when using the inside dataZoom

Please tell me how to make the chart line always extend beyond its limits to the left or right, even when it’s null.
my chart 1

I highlighted the desired result in red on the screenshot, but it’s most convenient to look at the example I prepared. If you hold down the right mouse button on the chart and move left/right, it will become clear what the problem is.

my example

I would be very grateful for any advice. Thank you in advance!

How to resize uploaded video?

I have a code that allows users to upload a video. Currently, I’ve set the requirement for videos to be 1920×1080 to match my existing code. However, I realized that allowing videos of any size would be much better.

To handle this, I tried to use JavaScript to resize uploaded videos to 1920×1080. But so far I couldn’t figure out a solution.

If the video’s aspect ratio doesn’t match, I’d like to add black padding to the sides or top as needed to maintain the correct dimensions.


I see this is possible using FFMPEG but I am not exactly sure how to integrate JS with FFMPEG.

My code:

Dropzone.options.dropper = {
    headers: {
        "Content-Type": "video/mp4",
        "Cache-Control": "public, max-age=31536000",
    },
    method: "put",
    paramName: "file",
    chunking: false,
    maxFiles: 1,
    timeout: null,
    dictDefaultMessage: "Video Upload",
    acceptedFiles: ".mp4",
    maxFilesize: 10240,
    autoProcessQueue: false,
    createImageThumbnails: true,

    init: function () {
        var dropzoneInstance = this;
        this.on("sending", (file, xhr) => {
            file.name = file.name.replace(/[^a-z0-9-.]/gi, '_').toLowerCase()
            console.log(
                "sending",
                file.name,
                "to",
                Dropzone.instances[0].options.url
            );
            let _send = xhr.send;
            xhr.send = function () {
                _send.call(xhr, file);
            };
        });
        this.on("error", (file, errorMessage) => {
            console.error("Upload error: " + errorMessage);
        });
        this.on("addedfile", (file) => {
            if (file.size > 10 * 1024 * 1024 * 1024) {
                document.getElementsByClassName(
                    "dz-default dz-message"
                )[0].style.display = "block";
                var errors = document.getElementsByClassName("dz-preview dz-error");
                for (var i = 0; i < errors.length; i++) {
                    errors.item(i).style.display = "none";
                }
                var progressb = document.getElementsByClassName("dz-progress");
                console.log(progressb);
                for (var i = 0; i < progressb.length; i++) {
                    progressb.item(i).style.display = "none";
                }
                this.removeFile(file);
                window.alert(
                    "Only videos that are under 10GB in size are supported. Please upload another video."
                );
                return false;
            } else if (!file.type.match(".mp4")) {
                document.getElementsByClassName(
                    "dz-default dz-message"
                )[0].style.display = "block";
                var errors = document.getElementsByClassName("dz-preview dz-error");
                for (var i = 0; i < errors.length; i++) {
                    errors.item(i).style.display = "none";
                }
                var progressb = document.getElementsByClassName("dz-progress");
                console.log(progressb);
                for (var i = 0; i < progressb.length; i++) {
                    progressb.item(i).style.display = "none";
                }
                this.removeFile(file);
                window.alert(
                    "Only videos that are h264 codec and .mp4 filetype are supported. Please upload another video."
                );
                return false;
            }
            console.log(file);
            const video = document.createElement("video");
            video.src = URL.createObjectURL(file);
            video.addEventListener("loadeddata", function (e) {
                var width = video.videoWidth,
                    height = video.videoHeight;
                console.log(`${width}x${height}`);
                if (width === 1920 && height === 1080) {
                    const filename = file.name;
                    const url = `/get_signed_url?filename=${encodeURIComponent(
                        filename
                    )}`;
                    console.log(url);
                    fetch(url, {
                        method: "GET",
                    })
                        .then((response) => response.json())
                        .then((data) => {
                            var signedUrl = data.signed_url;
                            Dropzone.instances[0].options.url = signedUrl;
                            console.log(signedUrl);
                            document.getElementsByClassName(
                                "dz-default dz-message"
                            )[0].style.display = "block";
                            var progressb = document.getElementsByClassName("dz-progress");
                            console.log(progressb);
                            for (var i = 0; i < progressb.length; i++) {
                                progressb.item(i).style.display = "none";
                            }
                            dropzoneInstance.files[0].status = "queued";
                            dropzoneInstance.processQueue();
                        })
                        .catch((error) => {
                            console.error("Fetch error: " + error);
                        });
                } else {
                    document.getElementsByClassName(
                        "dz-default dz-message"
                    )[0].style.display = "block";
                    var errors = document.getElementsByClassName("dz-preview dz-error");
                    for (var i = 0; i < errors.length; i++) {
                        errors.item(i).style.display = "none";
                    }
                    var progressb = document.getElementsByClassName("dz-progress");
                    console.log(progressb);
                    for (var i = 0; i < progressb.length; i++) {
                        progressb.item(i).style.display = "none";
                    }
                    dropzoneInstance.removeFile(file);
                    window.alert(
                        "Only videos that are 1920x1080 resolution are supported. Please upload another video."
                    );
                    return false;
                }
            });
        });
    },
};

It might be a bit long but basically the idea is to resize the video after upload.

Any help appreciated.

Handling tuples in URL query

I got myself into a big mess trying to add support for arrays in query arguments for an API.

The way I am handling this now is join array by commas

const params = new URLSearchParams()
params.append("arrParam", arr.join(","))

And on the sever I am splitting by comma. This works just of one dimension arrays.

Problem now is that I have an argument that is supposed to be a tuple, like ["abc", 0]
And I should be able to pass array of tuples too, in the query. That means I need to support multidimensional arrays.

Is there an abstract way of doing this, that would work for any array/array of tuples, without adding a “special case” on both client and server?

Vue Splitter – Resize gutter for each SplitterPanel

We have a Splitter with three SplitterPanels. We would like the gutter between the first two panels to be fixed and the gutter between the other two panels to be moveable.

So basically we have this code:

  <Splitter class="main-splitter" :key="layoutState.splitterKey.value" :style="splitterTop" :gutterSize="0">
    <SplitterPanel>
      ...
    </SplitterPanel>
    <SplitterPanel>
      ...
    </SplitterPanel>
    <SplitterPanel>
      ...
    </SplitterPanel>
  </Splitter>

As I set gutterSize to zero in the Splitter tag, the gutter is neither moveable between the first nor between the other two panels. What I tried to get the result I want is that I set gutterSize to different values in the SplitterPanel tags instead of the Splitter tag, but that did not work out.

Is there a way to achieve what we want using Vue?

Cannot change the style with input box text from Javascript [duplicate]

I have made a practice page for myself in my journey to learn coding.
Apologize in advance that I’m a total newbie.

This is the code:

I’m not copy-pasting the whole page as it’s gonna be way too long.

function updateFlex() {
  let flexDirectionInput = document.querySelector("#flexdirectioninput");
  let wrapInput = document.querySelector("#wrapinput");
  let justifyContentInput = document.querySelector("#justifycontentinput");
  let alignItemsInput = document.querySelector("#alignitemsinput");
  let alignContentInput = document.querySelector("#aligncontentinput");
  let flexDirectionInputValue = flexDirectionInput.value;
  let wrapInputValue = wrapInput.value;
  let justifyContentInputValue = justifyContentInput.value;
  let alignItemsInputValue = alignItemsInput.value;
  let alignContentInputValue = alignContentInput.value;

  let flexBox = document.getElementById("layoutflex");
  
  flexBox.style.flexDirection = flexDirectionInputValue;
  flexBox.style.flexWrap = wrapInputValue;
  flexBox.style.justifyContent = justifyContentInputValue;
  flexBox.style.alignItems = alignItemsInputValue;
  flexBox.style.alignContent = alignContentInputValue;
  
flexBox.style.backgroundColor = "red";

  const testing123 = window.getComputedStyle(flexBox);
  console.log(
    testing123.getPropertyValue("flex-direction"),
    flexDirectionInputValue
  );
}
<p>Flex-direction :</p>
<select name="" id="flexdirectioninput" onchange="updateFlex()">
  <option value="column;">Column</option>
  <option value="row;">Row</option>
  <option value="column-reverse;">Column Reverse</option>
  <option value="row-reverse;">Row Reverse</option>
</select>
<div class="layout-header">Flex Box</div>
<div class="layout-flex boxshadow" id="layoutflex">
  <div class="layout-boxes"></div>
</div>

I have tried using console log, it shows that the flexDirectionInput have correct value, but not updating the style for flex-direction.

Looking for a JavaScript library that generates .js files from .sql file either through a build-time preprocessor or cli tool

Is there a library that allows me to save the SQL code in a file, like say createUser.sql,

-- @param {String} $1:name The name of the user
-- @param {String} $2:email The email id of the user

INSERT INTO "user" ("name", "email")
VALUES (:name, :email)

then I can run a command like db preprocess and it will generate a createUser.js file that I can just import and call wherever I want

import { createUser } from "@db/preprocesed"

export const GET = async () => {
    await createUser("name", "email")
}

I know Prisma’s TypedSql can do something like this but it is limited to select statements. I want to run updates, inserts and multiple SQL commands within a single file.

I tried to create a prisma-generator for this; you can find it on NPM prisma-client-procedure-generator. It uses prisma.$executeRaw under the hood, so doesn’t support multiple statements within a single .sql file.

Is there truely nothing of sorts out there or am I blind?
I am using SQLite so stored procedures are not an option; triggers are cumbersome to work with as I need to iterate and modify the SQL scripts often during development.

Creating a Bar Graph to compare two values (graph doesn’t always start at zero)

I have already entered the code to make the bar graph start at zero, although whenever my numInput.value becomes less than totalEmissions, the graph for some reason starts at numInput.value, rendering part of the chart unvisible.

Here is a code snippet of the js:

const maxValue = Math.max(totalEmissions, numInput.value);
const canvasHeight = maxValue * 10; // Adjust the multiplier as needed for better visibility

barGraphA.innerHTML = `<canvas id="barChartA" style="width:100%; max-width:350px; height:${canvasHeight}px;"></canvas>`;

new Chart("barChartA", {
    type: 'bar',
    data: {
        labels: ['Your Emissions', 'Your Estimate'],
        datasets: [{
            label: 'Tons of CO2 (Every Year)',
            data: [totalEmissions, numInput.value],
            backgroundColor: [
                'rgba(54, 162, 235, 0.2)',
                'rgba(153, 102, 255, 0.2)',
            ],
            borderColor: [
                'rgba(54, 162, 235, 1)',
                'rgba(153, 102, 255, 1)',
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            y: {
                beginAtZero: true,
                min: 0, // Start y-axis at 0
                max: maxValue + 10 // Set max to a bit higher than the max value

            }
        }
    }
});

Here is a sreenshot of what my chart looks like when numInput.value is greater than totalEmissions. the numInput.value bar seems as though it’s not there because the chart starts at its value.

How to use JS in Statamic templates?

I want to import js file in some antlers template and use in it function from js file
Example:

<div id="logout" class="logout hidden" onclick="logout()">
  <i class="material-icons">logout</i>
</div>
{{ vite src="resources/js/header.js" }}

Header.js:

function logout(){
  return apiService.get('/logout')
}

But in console I have error that

“TypeError: logout is not a function
at HTMLDivElement.onclick”

How to use JS in Statamic CMS template???

Can we change multiple variable dynamically using same function?

I have two similar functions, clearSubstitutions and handleApply, that need to handle two input fields:
EnteredAvailableZoneValues
and EnteredUnavailableZoneValue
These fields should behave similarly, with only the variable they refer to being different. The issue I’m facing is that I don’t want to duplicate the code for handling both input fields and their corresponding logic.

The two fields (EnteredAvailableZoneValues and EnteredUnavailableZoneValues) essentially serve the same purpose. They allow users to enter zone values, and both should follow the same pattern when it comes to applying zones or clearing them. The main difference is that one deals with “available” zones, and the other with “unavailable” zones.

What I Tried:
Passing arrays by reference: I initially tried passing arrays by reference to avoid duplicating code, but that approach didn’t work as expected, by reference i mean, i passed the respective variable and updated in the same function, but the original variable doesn’t change.

Writing separate functions: I thought of writing separate functions for each zone (Available and Unavailable), but this led to code duplication, which I wanted to avoid.

The Goal:
I want to write efficient and reusable code, where both the clearSubstitutions and handleApply functions can handle both EnteredAvailableZoneValues and EnteredUnavailableZoneValues without duplicating logic. The challenge is figuring out how to make the functions work for both input fields in a flexible and clean way, without writing redundant code for each one.

HTML snippet

  <!-- Available Zones Section -->
  <div>
    <span>{{ 'Available in' }}</span>
    <input [(ngModel)]="enteredAvailableZoneValues" />
    <span *ngIf="enteredAvailableZoneValues" (click)="handleApply(true)">APPLY</span>
    <div *ngIf="enteredAvailableZones?.length > 0">
      <div (click)="clearSubstitution(true)">Clear All</div>
      <div *ngFor="let zone of enteredAvailableZones">
        <span>{{ zone.name }} <strong (click)="clearSubstitution(true, zone.id)">X</strong></span>
      </div>
    </div>
  </div>

  <!-- Not Available Zones Section -->
  <div>
    <span>{{ 'Not Available in' }}</span>
    <input [(ngModel)]="enteredUnAvailableZoneValues" />
    <span *ngIf="enteredUnAvailableZoneValues" (click)="handleApply(false)">APPLY</span>
    <div *ngIf="enteredUnAvailableZones?.length > 0">
      <div (click)="clearSubstitution(false)">Clear All</div>
      <div *ngFor="let zone of enteredUnAvailableZones">
        <span>{{ zone.name }} <strong (click)="clearSubstitution(false, zone.id)">X</strong></span>
      </div>
    </div>
  </div>
</div>

Typescript code snippet

enteredAvailableZoneValues = '';
enteredUnAvailableZoneValues = '';
enteredAvailableZones: any[] = [];
enteredUnAvailableZones: any[] = [];

handleApply(isAvailableZone: boolean) {
  if (!this.enteredAvailableZoneValues && !this.enteredUnAvailableZoneValues) { return; }

  const zoneType = isAvailableZone ? 'enteredAvailableZoneValues' : 'enteredUnAvailableZoneValues';
  const zoneServiceMethod = isAvailableZone ? 'getZonesByAvailableIds' : 'getZonesByUnavailableIds';
  
  this.zoneService[zoneServiceMethod](this[zoneType]).subscribe(
    (zones: any[]) => {
      if (isAvailableZone) {
        this.enteredAvailableZones = zones;
      } else {
        this.enteredUnAvailableZones = zones;
      }
    },
    error => {
      console.error('Error fetching zones', error);
    }
  );
}

clearSubstitution(isAvailableZone: boolean, id?: string) {
  const zoneArray = isAvailableZone ? this.enteredAvailableZones : this.enteredUnAvailableZones;
  
  if (id) {
    const index = zoneArray.findIndex(zone => zone.id === id);
    if (index !== -1) zoneArray.splice(index, 1);
  } else {
    zoneArray.length = 0; // Clear all zones
  }
}

React-Dates DateRangePicker: Start Date Appears Disabled When Switching from End Date

I am using the library ‘react-dates’ DateRangePicker in my React project.
I have implemented logic where:

  • The start date should be selectable at any time.
  • The end date should only be selectable after a start date is chosen.

Issue

  • If I click the end date first, it correctly disables all dates (as expected), but when I directly switch to selecting a start date while the end date calendar is open, all start dates appear disabled.
  • However, if I initially click the start date, it shows enabled dates as expected). Then, if I switch to the end date, it correctly shows disabled dates, and when I switch back to the start date, it again shows enabled dates. This works fine in this flow (start → end → start), but the reverse flow (end → start) causes the issue.

My DateRangePicker Component:

import { DateRangePicker } from "react-dates";

const MyDateRangePicker = () => {
  const [startDate, setStartDate] = useState(null);
  const [endDate, setEndDate] = useState(null);
  const [focusedInput, setFocusInput] = useState(null);
  const [visibleMonth, setVisibleMonth] = useState(moment());

  return (
    <DateRangePicker
      startDate={startDate}
      startDateId="startDate"
      endDate={endDate}
      endDateId="endDate"
      numberOfMonths={1}
      minimumNights={0}
      isOutsideRange={(day) => {
        const today = moment().startOf("day");
        if (focusedInput === "startDate") {
          return day.isAfter(today, "day");
        }
        if (focusedInput === "endDate") {
          return !startDate || day.isAfter(moment(), "day");
        }
        return false;
      }}
      onDatesChange={({ startDate, endDate }) => {
        startDate?.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
        endDate?.set({ hour: 0, minute: 0, second: 0, millisecond: 0 });
        setStartDate(startDate);
        setEndDate(endDate);
        if (startDate !== null && endDate !== null) {
          getAnalytics1(startDate, endDate);
        }
      }}
      focusedInput={focusedInput}
      onFocusChange={(focusedInput) => {
        setFocusInput(focusedInput);
        if (focusedInput === "startDate" && startDate) {
          setVisibleMonth(startDate);
        } else if (focusedInput === "endDate" && endDate) {
          setVisibleMonth(endDate);
        }
      }}
      initialVisibleMonth={() => visibleMonth}
    />
  );
};

Expected Behavior

  • When switching from start → end → start, everything works fine.
  • When switching from end → start, the start date appears disabled
    incorrectly.

How can I fix this behavior in react-dates?

Any help would be appreciated!

Trying to develop tabbed UI, but buttons are only visible on page load

Here is my code:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My API App</title>
    <link rel="stylesheet" href="style.css">
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <script src="https://unpkg.com/[email protected]/dist/cross-fetch.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script type="importmap">
        {
          "imports": {
            "react": "https://esm.sh/react",
            "react-dom/client": "https://esm.sh/react-dom/client",
            "react/jsx-runtime": "https://esm.sh/react/jsx-runtime",
            "sql.js": "/node_modules/sql.js/dist/sql-wasm.js"
          }
        }
    </script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container mx-auto p-4">
        <h1 class="text-2xl font-bold mb-6">Boxergy API App</h1>

        <!-- Tabs Container -->
        <div class="mb-8">
            <!-- Tab Navigation -->
            <div class="flex border-b border-gray-200">
                <button class="py-2 px-4 font-medium text-blue-600 border-b-2 border-blue-600 tab-button active" data-tab="givenergy">
                    GivEnergy System
                </button>
                <button class="py-2 px-4 font-medium text-gray-500 hover:text-blue-600 tab-button" data-tab="alphaess">
                    AlphaESS System
                </button>
            </div>

            <!-- Tab Content -->
            <div class="bg-white rounded-lg shadow-md mt-1">
                <!-- GivEnergy Tab -->
                <div id="givenergy-tab" class="tab-content active p-4">
                    <div class="mb-6 border-b pb-6">
                        <h2 class="text-xl font-bold mb-4">System Data</h2>
                        <input type="text" id="serial-givenergy-data" placeholder="GivEnergy Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-givenergy-data-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch GivEnergy System Data
                        </button>
                        <div id="givenergy-system-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                    </div>

                    <div>
                        <h2 class="text-xl font-bold mb-4">System Events</h2>
                        <input type="text" id="serial-givenergy-events" placeholder="GivEnergy Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-givenergy-events-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch GivEnergy Events
                        </button>
                        <div id="givenergy-events-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                        <canvas id="givenergyChart" class="mt-4 h-64"></canvas>
                    </div>
                </div>

                <!-- AlphaESS Tab -->
                <div id="alphaess-tab" class="tab-content hidden p-4">
                    <div class="mb-6 border-b pb-6">
                        <h2 class="text-xl font-bold mb-4">System Data</h2>
                        <input type="text" id="serial-alphaess-data" placeholder="AlphaESS Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-alphaess-data-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch AlphaESS System Data
                        </button>
                        <div id="alphaess-system-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                    </div>

                    <div>
                        <h2 class="text-xl font-bold mb-4">Historical Data</h2>
                        <input type="text" id="serial-alphaess-historical" placeholder="AlphaESS Serial Number" class="w-full p-2 border rounded mb-2">
                        <div class="grid grid-cols-2 gap-2 mb-2">
                            <div>
                                <label class="block text-sm">Start Time:</label>
                                <input type="datetime-local" id="alphaess-start-time" class="w-full p-2 border rounded">
                            </div>
                            <div>
                                <label class="block text-sm">End Time:</label>
                                <input type="datetime-local" id="alphaess-end-time" class="w-full p-2 border rounded">
                            </div>
                        </div>
                        <button id="fetch-alphaess-historical-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch AlphaESS Historical Data
                        </button>
                        <div id="alphaess-historical-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                        <div id="alphaess-power-flow-container" class="mt-4"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="root"></div>
    <script src="bundle.js" type="module"></script>
    <script src="client.js"></script>
    <script src="alphaess-fetcher.js"></script>

    <!-- Tab Functionality Script -->
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const tabButtons = document.querySelectorAll('.tab-button');
            const tabContents = document.querySelectorAll('.tab-content');

            tabButtons.forEach(button => {
                button.addEventListener('click', function () {
                    const tabId = this.getAttribute('data-tab');

                    tabButtons.forEach(btn => {
                        btn.classList.remove('active', 'text-blue-600', 'border-b-2', 'border-blue-600');
                        btn.classList.add('text-gray-500');
                    });

                    tabContents.forEach(content => {
                        content.style.display = 'none';
                        content.classList.remove('active');
                    });

                    this.classList.add('active', 'text-blue-600', 'border-b-2', 'border-blue-600');
                    this.classList.remove('text-gray-500');

                    const activeContent = document.getElementById(`${tabId}-tab`);
                    activeContent.style.display = 'block';
                    activeContent.classList.add('active');

                    const buttons = activeContent.querySelectorAll('button');
                    buttons.forEach(btn => {
                        btn.style.display = 'inline-block';
                        btn.style.visibility = 'visible';
                    });

                    const inputs = activeContent.querySelectorAll('input');
                    inputs.forEach(input => {
                        input.style.display = 'block';
                        input.style.visibility = 'visible';
                    });
                });
            });
        });
    </script>
</body>
</html>

style.css

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Reset some default browser styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Arial', sans-serif;
    background-color: #f4f4f4;
    color: #333;
    line-height: 1.6;
    padding: 20px;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    background: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
}

h1, h2, h3 {
    margin-bottom: 20px;
    color: #444;
}

button {
    display: inline-block;
    background: #007bff;
    color: #fff;
    border: none;
    padding: 10px 20px;
    margin: 10px 0;
    border-radius: 5px;
    cursor: pointer;
    transition: background 0.3s ease;
}

    button:hover {
        background: #0056b3;
    }

input[type="text"] {
    width: 100%;
    padding: 10px;
    margin: 10px 0;
    border: 1px solid #ccc;
    border-radius: 5px;
}

#root {
    margin-top: 20px;
}

#givenergyChart {
    margin-top: 20px;
}

.output {
    background: #f9f9f9;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    margin-top: 10px;
    white-space: pre-wrap;
}

input[type="text"] {
    width: 20%;
}

.api-section {
    margin-bottom: 30px;
    padding: 15px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background-color: #f9f9f9;
}

.datetime-inputs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 10px 0;
}

    .datetime-inputs label {
        display: flex;
        flex-direction: column;
        font-size: 14px;
    }

    .datetime-inputs input {
        padding: 8px;
        border: 1px solid #ccc;
        border-radius: 4px;
    }

.error {
    color: #d9534f;
    font-weight: bold;
}

/* Fix button display issues */
button {
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Fix input field display issues */
input[type="text"],
input[type="datetime-local"] {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Ensure tab content is displayed properly */
.tab-content.active {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Fix the tab buttons */
.tab-button {
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: [
        "./src/**/*.{js,jsx,ts,tsx}",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}

When I refresh the page, the buttons momentarily appear, but then immediately disappear. When I am in the GivEnergy tab, and hover over the ‘Alpha ESS system’ button the button text is visible, but oddly enough the reverse is not true, i.e. the ‘GivEnergy system’ button text is never visible under any circumstances. Please note I am not at all sure if Tailwind is correctly installed. In Visual Studio I am seeing the warning ‘”tailwind” is not a known ‘@’ directive.’ for all the lines starting @tailwind in styles.css. I did spend good deal of time trying to troubleshoot the Tailwind install including checking the relevant Windows environment variable was entered correctly and numerous terminal commands, but without success.

Can anyone help please? I have tried several AIs but none have been able to solve the problem and in fact their suggestions only made mattes worse. Thanks in advance.

How can i apply is-toggled styles when the button is clicked clicked [closed]

The class (.is-toggled) is added when clicked on the button , but the styles for the button when clicked is not getting applied…

.is-toggled {
  background-color: lightgray;
  border: none;
  padding: 10px;
  border-radius: 5px;
  cursor: pointer;
}

.gaming-btn {
  background-color: black;
  color: white;
  border: none;
  padding: 10px;
  border-radius: 5px;
  cursor: pointer;
}
<button class="gaming-btn" onclick="
     const btn = document.querySelector('.gaming-btn');

      if(btn.classList.contains('is-toggled')) {
        btn.classList.remove('is-toggled')
      } else {
        btn.classList.add('is-toggled');
      }
    ">Gaming</button>