Widget stays always active even after toggle

I have a widget that is just a basic toggle that returns a true (2) or false (1) value based on the position of the toggle. I am really not sure why, but the widget never turns off even when I try and toggle it (i.e always stays active).

Checking console log, I can see the value it is trying to send is a 1, but the widget does not seem to update its position or value to the attribute.

This is using javascript and angular.

let settings;
let attributeService;
let utils;
let translate;
let $scope;
let map;

self.onInit = function() {
    self.ctx.ngZone.run(function() {
        init();
        self.ctx.detectChanges(true);
    });
};


function init() {
    $scope = self.ctx.$scope;
    attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));
    utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));
    translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));
    $scope.toastTargetId = 'input-widget' + utils.guid();
    settings = utils.deepClone(self.ctx.settings) || {};
    settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);

    $scope.isValidParameter = true;
    $scope.dataKeyDetected = false;
    $scope.message = translate.instant('widgets.input-widgets.no-entity-selected');

    settings.trueValue = utils.defaultValue(utils.customTranslation(settings.trueValue, settings.trueValue), true);
    settings.falseValue = utils.defaultValue(utils.customTranslation(settings.falseValue, settings.falseValue), false);

    map = {
        true: settings.trueValue,
        false: settings.falseValue
    };
    
    $scope.slideToggleValue = false;
    $scope.currentValue = map[$scope.slideToggleValue];

    $scope.attributeUpdateFormGroup = $scope.fb.group({slideToggleValue: [$scope.slideToggleValue]});

    $scope.changed = function() {
        $scope.slideToggleValue = $scope.attributeUpdateFormGroup.get('slideToggleValue').value;
        $scope.currentValue = map[$scope.slideToggleValue];
        $scope.updateAttribute();
    };

    if (self.ctx.datasources && self.ctx.datasources.length) {
        var datasource = self.ctx.datasources[0];
        if (datasource.type === 'entity') {
            if (datasource.entityType === 'DEVICE') {
                if (datasource.entityType && datasource.entityId) {
                    $scope.entityName = datasource.entityName;
                    if (settings.widgetTitle && settings.widgetTitle.length) {
                        $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);
                    } else {
                        $scope.titleTemplate = self.ctx.widgetConfig.title;
                    }
    
                    $scope.entityDetected = true;
                }
            } else {
                $scope.message = translate.instant('widgets.input-widgets.not-allowed-entity');
            }
        }
        if (datasource.dataKeys.length) {
            if (datasource.dataKeys[0].type !== "attribute") {
                $scope.isValidParameter = false;
            } else {
                $scope.currentKey = datasource.dataKeys[0].name;
                $scope.dataKeyType = datasource.dataKeys[0].type;
                $scope.dataKeyDetected = true;
            }
        }
    }

    self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);

    $scope.updateAttribute = function() {
        if ($scope.entityDetected) {
            var datasource = self.ctx.datasources[0];
            var valueToSend = $scope.slideToggleValue === 2 ? 2 : 1;
            console.log("ValueToSend: ", valueToSend)
            attributeService.saveEntityAttributes(
                datasource.entity.id,
                'SHARED_SCOPE',
                [
                    {
                        key: $scope.currentKey,
                        value: valueToSend
                        // value: $scope.slideToggleValue || false
                    }
                ]
            ).subscribe(
                function success() {
                    if (settings.showResultMessage) {
                        $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);
                    }
                },
                function fail() {
                    if (settings.showResultMessage) {
                        $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);
                    }
                }
            );
        console.log("1: ", parseInt($scope.slideToggleValue))
        }
    };
}

self.onDataUpdated = function() {
    try {
        if ($scope.dataKeyDetected) {
            // $scope.slideToggleValue = self.ctx.data[0].data[0][1] === 'true';
            console.log("A:",self.ctx.data[0].data[0][1])
            $scope.slideToggleValue = self.ctx.data[0].data[0][1] === 2 ? 2 : 1
            $scope.currentValue = map[$scope.slideToggleValue];
            $scope.attributeUpdateFormGroup.get('slideToggleValue').patchValue($scope.slideToggleValue);
            self.ctx.detectChanges();
            console.log("B:",self.ctx.data[0].data)
        }
    } catch (e) {
        console.log(e);
    }
}

self.onResize = function() {}

self.typeParameters = function() {
    return {
        maxDatasources: 1,
        maxDataKeys: 1,
        singleEntity: true
    }
}

self.onDestroy = function() {}

my toggle switch:

                    <mat-slide-toggle formControlName="slideToggleValue" (change)="changed()"
                                      aria-label="{{'widgets.input-widgets.switch-timeseries-value' | translate}}"
                                      class="custom-slide-toggle">
                        {{ slideToggleValue.checked ? 2 : 1 }}  
                    </mat-slide-toggle>

Why isn’t my ternary condition rendering the correct ui?

function AllBooks() {
  const { authenticated, name } = useContext(UserContext);
  const API_URL = 'http://localhost:8080/api/books';
  const [books, setBooks] = useState([]);
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const BOOKS_PER_PAGE = 20; // Number of books to display per page

  const title = 'All Books';

  useEffect(() => {
    const fetchBooks = async () => {
      try {
        const response = await axios.get(API_URL);
        const allBooks = response.data;
        const totalPages = Math.ceil(allBooks.length / BOOKS_PER_PAGE);
        setTotalPages(totalPages);

        const startIndex = (currentPage - 1) * BOOKS_PER_PAGE;
        const endIndex = startIndex + BOOKS_PER_PAGE;
        const booksToDisplay = allBooks.slice(startIndex, endIndex);

        setBooks(booksToDisplay);
      } catch (error) {
        console.error('Error fetching books:', error);
      }
    };

    fetchBooks();
    console.log(authenticated);
  }, [currentPage]);

  const handlePageChange = (event, pageNumber) => {
    console.log('Selected Page:', pageNumber);
    setCurrentPage(pageNumber);
  };

  return (
    <div className="allBooks">
      {authenticated ? <UserHeader name={name} /> : <LandingHeader />}
      <BrowserHeader title={title} />
      <div className="booksContainer">
        <div className="gridContainer">
          <div className="sidebar">
            <Categorynav />
          </div>
          <div className="booksGrid">
            {books ? books.map((b) => <Book key={b._id} book={b} />) : null}
          </div>
          <Pagination
            className="listNav"
            count={totalPages}
            page={currentPage}
            onChange={handlePageChange}
          />
        </div>
      </div>
    </div>
  );
}

export default AllBooks;

This component renders books in a grid. The component is supposed to render a different header if a user is not authenticated. Authentication information is stored in a context object. I logged the value of is authenticated to the console and it’s false. However, the UserHeader component is still rendered.

Trying to fetch the value from a Drupal post field is returning a div instead of only the value

I’m creating a new post type on Drupal and I’m trying to load the values to a node template(html.twig) so I can apply some CSS and some javascript

<article class="content">
    <h1 >{{label}}</h1>
    <div>{{ content.field_name }}</div>
    <div>{{ content.field_image }}</div>
    <div>
      <div class="price">{{ content.field_price }}</div>
      <div class="price">{{content.field_redirect_id_number}}</div>
      <button class="btn btn-warning ced-btn-med" add-to-cart={{content.field_redirect_id_number}}>ADD TO CART</button>
      <div>{{ content.body }}</div>
    </div>
</article>

enter image description here

As you can see in the image the return from the content.field_redirect_id_number is a div and not only the value. This is a issue because as you can see I’m trying to do a javascript call using this value but it keeps breaking my call because of the div wrap

I’m expecting a way to fetch only the value of a field without this html wrapping

Changing text and picture with one button using Javascript

So I’ve created a very basic practice page, where clicking each button will bring up a picture of the country. Below the picture is some text.

My question is, how do you go about making the text below the picture also change with each button? For example, changing from “This is a picture of Spain” to “This is a picture of Northern Ireland” etc when you hit the different buttons.

I read somewhere you can have multiple onclick events with ; between them, but I’m very new to Javascript and haven’t been able to work out how to use multiple onclick events.

My HTML with script Javascript is below:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Birds</title>
    <link rel="stylesheet" type="text/css" href="styling.css">

</head>

<body>
    <main>
   
        <h1>Places</h1>
        <h2>Subheading Goes Here</h2>
        <img id="bannerImage" src="https://www.planetware.com/wpimages/2020/03/portugal-in-pictures-beautiful-places-to-photograph-lisbon.jpg" /> <br> <br />
        <p id ="text">This is a picture of Northern Ireland</p>
        <nav>
            <button class="mainbuttons" onclick="changeImage('https://www.planetware.com/wpimages/2020/03/portugal-in-pictures-beautiful-places-to-photograph-lisbon.jpg')">Northern Ireland</button>
            <button class="mainbuttons" onclick="changeImage('https://theworldpursuit.com/wp-content/uploads/2021/01/things-to-do-in-northern-ireland.jpg')">Ireland</button>
            <button class="mainbuttons" onclick="changeImage('https://d32uwaumftsuh7.cloudfront.net/Pictures/768x432/7/2/0/22720_gameofthronesthedarkhedges_thekingsroad_master_529527_crop.jpg')">Scotland</button>
            <button class="mainbuttons" onclick="changeImage('https://media.cntraveller.com/photos/611bf776db797d0116fd53ab/master/w_1600,c_limit/causeway-coast-in-antrim-northern-ireland-gettyimages-1193546847.jpg')">Wales</button>
            <button class="mainbuttons" onclick="changeImage('https://onhisowntrip.com/wp-content/uploads/2020/08/Great-British-Chefs-1.jpg')">Spain</button>         
        </nav>

        <button id="themechanger" onclick="toggleTheme()">Toggle Theme</button>

<script>
function changeImage(fileName) {
let img = document.querySelector('#bannerImage');
img.setAttribute('src', fileName);
}

function toggleTheme(){
window.theme = typeof(window.theme)==='string' ? window.theme : 'root';
var switchToTheme = window.theme === 'root' ? 'dark' : 'root';
window.theme = switchToTheme;
document.querySelector('html').setAttribute('data-theme',switchToTheme);
}
</script>

</body>


    </main>
     
</body>
</div>
</html>

I’ve tried various internet tutorials, but nothing seems to fit

Is there any way to retrieve bytes from an iframe whose src is a pdf blob?

I have a web page with an iframe and a number of cards representing client submissions to an online form. When the user clicks a submission, the following things occur:

  • Using pdf-lib, a local PDF file is loaded.
  • The fillable fields of this PDF are populated with the submission data.
  • Then, we save the bytes and create a blob and url.
  • Finally, the iframe has its src set to this url.

The whole process looks something like this:

const src = "{{ pdf path here}}.pdf";
const existingBytes = await fetch(src).then(res => res.arrayBuffer());

const doc = await PDFDocument.load(existingBytes);
const form = doc.getForm();
fillSubmittedInformation(form, data); // This function just fills form fields.

const bytes = await doc.save();const blob = new Blob([bytes], { type: "application/pdf" });
const url = URL.createObjectURL(blob);

const preview = document.getElementById("pdf") as HTMLIFrameElement;
preview.src = url;

The user can then edit the content of the fillable fields of the PDF with using their browser’s native PDF viewer. What I would like to do is to then be able to get the bytes of the PDF when the user clicks a button, and use them. Specifically once the user is done I’d like to flatten the form and download the PDF, but the specifics aren’t really important.

Unfortunately, after a few hours of searching I have come up short. Many online sources as well as ChatGPT suggest accessing preview.contentWindow.document, but this results in an exception since blob urls are considered as separate origins. This thread would seem to suggest that it is not possible with an iframe. I have also tried with an embed but to no success. While online sources have not yielded a working solution, I can’t see why something this simple would have no solution. I would just like to know if this is feasible, and perhaps a point in the right direction.

Put simply:
Given an iframe whose src is a blob url and whose content has been manipulated, (how) can I retrieve it’s current byte data?

How can I link an onclick function to my button in such a way that it affects a paragraph using the value of a input bar?

I created a input box, a button and a paragraph but I wanted to use a variable, which is the value of whatever is typed into the input box, to change the content of the inner HTML of the paragraph.

I coded it this way:

document.getElementById(“buttonId”).onclick = function() {

var x = "";
x = document.getElementById("inputBoxId").value;

document.getElementById(“paragraphId”).inner HTML = textEntered

}

I expected that when the button is clicked, the content of the paragraph will change to whatever is entered into the input box. But, it seems there’s something I’m not doing right coz it’s not working.

I can’t set the “onclick” attribute of an element in JS

I’m working in vanilla JS. Here is my function as of now

function displayQueue() {
    queueDiv.innerHTML = "";
    for (var i = 0; i < queue.length; i++) {
        let newDiv = document.createElement("div");
        newDiv.id = i;
        var playIcon = document.createElement("img");
        playIcon.id = "P" + i;
        playIcon.src = "icons/play-solid.svg";
        // this wont work:
        playIcon.onload = function() {
            playIcon.onclick = playIconFunc;
        }
        newDiv.appendChild(playIcon);
        if (queueNames[queue[i]].length > 15) {
            newDiv.innerHTML += queueNames[queue[i]].slice(0, 15) + "...";
        } else {
            newDiv.innerHTML += queueNames[queue[i]];
        }
        let deleteIcon = document.createElement("img");
        deleteIcon.src = "icons/x-solid.svg";
        newDiv.appendChild(deleteIcon);
        queueDiv.appendChild(newDiv);
    }
}

I have tried setting it to an anonymous function, I have tried it without the “onload” thing first. I have tried it as let and var. To no avail. What could I be doing wrong?
PS: I will be more than happy to provide more of my code if needed.

Angular 12 – save and retrieve time of video

I am trying to save and retreive time range for the video. All works well except when i click on the time it is not calculating accurately. If i have saved the beginning of the time, when i click on the time it is taking me to the end of the video. Please help.

Component :

`
import { Component, ViewChild, AfterViewInit, ElementRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
  @ViewChild('videoPlayer') videoPlayer: ElementRef | undefined;
  newComment: string = '';
  comments: any[] = [];
  highlightedTimeRange: { start: number, end: number } | null = null;
  currentProgress: number = 0;
  
  isDragging: boolean = false;
  selectionStart: number | null = null;
  selectionEnd: number | null = null;
   // Properties to store the start and end times of the selected time range
   savedStartTime: number | null = null;
   savedEndTime: number | null = null;
    // Array to store comments with their associated time ranges
  commentsArr: { start: number, end: number, text: string, user: string }[] = [];
  videoDuration: number = 0; // Initialize with '0:00' for now
  progressBarWidth: number = 0;


  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit() {
    const videoElement = this.videoPlayer.nativeElement;
    videoElement.addEventListener('timeupdate', this.onTimeUpdate.bind(this));
  }

  annotateTimeSegment() {
    const videoElement = this.videoPlayer.nativeElement;
    videoElement.pause();
  }

  formatDuration(seconds: number): string {
    const minutes = Math.floor(seconds / 60);
    const remainingSeconds = Math.floor(seconds % 60);
    return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
  }
  

   // Method to handle the drag event
   onProgressBarDrag(event: MouseEvent) {
    debugger;
    const progressBar = this.elementRef.nativeElement.querySelector('.progress-bar');
    const progressBarRect = progressBar.getBoundingClientRect();
    const progressBarWidth = progressBar.offsetWidth;
    const offsetX = event.clientX - progressBarRect.left;
    const newPosition = (offsetX / progressBarWidth) * 100;

    if (this.isDragging) {
      // Restrict within 0-100 range and set selectionStart and selectionEnd accordingly
      this.selectionStart = this.selectionStart === null ? newPosition : Math.min(this.selectionStart, newPosition);
      this.selectionEnd = Math.max(this.selectionStart, newPosition);
    }
  }

  // Method to seek to a specific position in the video
  seekToPosition(position: number) {
    const videoElement = this.videoPlayer.nativeElement;
    const newTime = (position / 100) * this.videoDuration;
    videoElement.currentTime = newTime;
  }
  

  onProgressBarClick(event: MouseEvent) {
    const progressBar = this.elementRef.nativeElement.querySelector('.progress-bar');
    const progressBarRect = progressBar.getBoundingClientRect();
    const progressBarWidth = progressBar.offsetWidth;
    const offsetX = event.clientX - progressBarRect.left;
    const newPosition = (offsetX / progressBarWidth) * 100;

    // Seek to the clicked position
    this.seekToPosition(newPosition);
  }

  addCommentForSelection() {
    debugger;
    const videoElement = this.videoPlayer.nativeElement;
    const duration = videoElement.duration;

    if (this.selectionStart !== null && this.selectionEnd !== null) {
      const start = (this.selectionStart / 100) * duration;
      const end = (this.selectionEnd / 100) * duration;

      const comment = {
        start: start,
        end: end,
        text: this.newComment,
        user: 'shirish'
      };

      this.comments.push(comment);
      this.newComment = ''; // Clear the comment input field
    }
  }

  
  addComment() {
    const videoElement = this.videoPlayer.nativeElement;
    const currentTime = videoElement.currentTime;
    const comment = {
      time: currentTime,
      text: this.newComment,
      user: 'bhummas'
    };
    this.comments.push(comment); // Store the comment in the array
    this.newComment = ''; // Clear the comment input field
    videoElement.play(); // Resume video playback
  }

  goToTime(time: number) {
    const videoElement = this.videoPlayer.nativeElement;
    videoElement.currentTime = time;
    videoElement.pause();
  }

  goToTimeTimeRange(time: number) {
    const videoElement = this.videoPlayer.nativeElement;
    const middleTime = (this.savedStartTime + this.savedEndTime) / 2;
  
    // Ensure the middleTime is within the valid range
    const currentTime = Math.max(Math.min(middleTime, videoElement.duration), 0);
    videoElement.currentTime = currentTime;
    videoElement.pause(); // Ensure the video resumes playback after seeking
  }
  
  
  
  
  onTimeUpdate() {
    const videoElement = this.videoPlayer.nativeElement;
    if (videoElement) {
      const currentTime = videoElement.currentTime;
      const duration = videoElement.duration;
      this.currentProgress = (currentTime / duration) * 100;
      this.videoDuration = duration; // Store the duration in seconds
    }
  }
  
  
  

  onMetadataLoaded() {
    const videoElement = this.videoPlayer.nativeElement;
    this.videoDuration = videoElement.duration;
    this.currentProgress = 0; // Reset currentProgress when video metadata is loaded
  
    const progressBar = this.elementRef.nativeElement.querySelector('.progress-bar');
    this.progressBarWidth = progressBar.offsetWidth; // Store the progress bar width
  
    // Set the initial progress bar width based on the video's duration
    progressBar.style.width = `${this.progressBarWidth}px`;
  }
  
  
  
  
  
  

   // Method to handle the "Save" button click event
 // Method to handle the "Save" button click event
 onSaveTimeRange() {
  if (this.selectionStart !== null && this.selectionEnd !== null) {
    this.savedStartTime = this.selectionStart;
    this.savedEndTime = this.selectionEnd;

    const comment = {
      start: this.savedStartTime,
      end: this.savedEndTime,
      text: this.newComment,
      user: 'shirish'
    };
  
    this.commentsArr.push(comment);
    this.selectionStart = null;
    this.selectionEnd = null;

  }


}
  
isHighlightedTimeRange(start: number, end: number): boolean {
  return this.savedStartTime !== null && this.savedEndTime !== null &&
    this.savedStartTime === start && this.savedEndTime === end;
}
  
}`

html


<div class="video-container">
  <div class="video-wrapper">
    <video #videoPlayer controls (timeupdate)="onTimeUpdate()"  (loadedmetadata)="onMetadataLoaded()">
      <source src="assets/test1.mp4" type="video/mp4">
    </video>
    <div class="progress-bar"
         (mousedown)="isDragging = true; onProgressBarDrag($event)"
         (mousemove)="isDragging && onProgressBarDrag($event)"
         (mouseup)="isDragging = false"
    >
      <div class="progress" [style.width.%]="currentProgress"></div>
      <div class="selection" [style.left.%]="selectionStart" [style.width.%]="selectionEnd - selectionStart"
           [class.highlighted]="isHighlightedTimeRange(selectionStart, selectionEnd)"
      ></div>
    </div>
  </div>

  <div class="comments-container">
    <h2>Comments</h2>
    <div class="comment" *ngFor="let comment of comments" (click)="goToTime(comment.time)">
      <p>{{ comment.user }} - {{ comment.text }} ({{ comment.time }}s)</p>
    </div>
  </div>
</div>

<div class="button-container">
  <button (click)="annotateTimeSegment()">Annotate Time Segment</button>
  <div class="add-comment">
    <label for="comment"> Comment:</label>
    <input type="text" id="comment" [(ngModel)]="newComment" placeholder="Enter your comment">
    <button (click)="addCommentForSelection()">Submit</button>
  </div>
</div>

<button (click)="onSaveTimeRange()">Save Time Range</button>
<p *ngIf="savedStartTime !== null && savedEndTime !== null">
  Saved Time Range: {{ savedStartTime }}s - {{ savedEndTime }}s
</p>

<div class="comments-container">
  <h2>Comments</h2>
  <div class="comment" *ngFor="let comment of commentsArr" (click)="goToTimeTimeRange(comment.start)">
    <p>{{ comment.user }} - {{ comment.text }} ({{ comment.start }}s - {{ comment.end }}s)</p>
  </div>
</div>

Mock jest of a function inside a JS module

Is there a way to mock a function that is inside of a module like this?
I want to mock foo() function in a test without export it. Please could you help?

file.js

function foo(){
  // function 1
  return 'value'
}

function baz(){
  const data = foo()
  return data
}

export default baz

I tried like some

jest.mock('./path', () => ({
  ...jest.requireActual('./path'),
  __esModule: true,
  default: jest.fn(),
  foo(): jest.fn().mockResolvedValue('mockedValue')
}))

and didn’t work

Also tried another Google things but it looks like I can only mock what is exported

Regular expression doesn’t work in Chrome [duplicate]

I am trying to add validation to an email field using JavaScript and have attempted to use the following pattern:

pattern="[a-z0-9].!#$%&'*+/=?^_`{|}~-]+@[a-z-]+(.[a-z]{2,})+"

This works fine in several browsers but not Chrome, where I always get some variation of the following error:

Pattern attribute value [a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z-]+(.[a-z]{2,})+ is not a valid regular expression: Uncaught SyntaxError: Invalid regular expression: /[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z-]+(.[a-z]{2,})+/v: Invalid character in character class

I’ve tried a lot of variations, including escaping several characters or removing them entirely, with the same results. I’m assuming this has something to do with the /v flag, but I have no idea how to fix it. Has anyone else encountered this?

I’m looking for help to finish solving my exercise on node.js methods

enter image description hereI’m new here and learning Node.js, although right now, I’m going for methods (GET, PUT, POST, DELETE), but I am having some problems with the POST y following methods:

  1. When I go to run the app.js file (in this case Routing.js), I get an error in the terminal as I shown in image 1.
  2. I can run the file “stories” with nodemon on server localhost:3000 but, I have to go down to an array parameter to get to it. The contruction of file is in image:2
  3. I can’t send “Send Request” of PUT type in the http file also gives me an error, I’ve been trying to solve it for several days. Image:3. And, I can only attempt to send a “Send Request by running the the file “stories” on the server.

Please, I’d greatly appreciate your help to finish solving this situation.

MERN server deployment not finding static client files

I’m trying to deploy my application using render.com free instances and the client side deployed just fine , however when trying to deploy my server side code I’m getting this error when i go the url:

{"message":"ENOENT: no such file or directory, stat '/opt/render/project/src/client/dist/index.html'","stack":null}

I’m using vite and the index.html is in the directory client/dist/index.html

this is my server side index.js:

import express from "express";
import path, { dirname } from "path";
import dotenv from "dotenv";
import cookieParser from "cookie-parser";
import connectDB from "./database/db.js";
import userRoutes from "./routes/usersRoutes.js";
import scoresRoutes from "./routes/scoresRoutes.js";
import { notFound, errorHandler } from "./middleware/errorMiddleware.js";
import { fileURLToPath } from "url";
dotenv.config();

connectDB();

const app = express();
const port = process.env.PORT || 5000;

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

app.use("/api/users/scores", scoresRoutes);
app.use("/api/users", userRoutes);

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

if (process.env.NODE_ENV === "production") {
  const clientDistPath = path.resolve(__dirname, "..", "client", "dist");
  console.log("clientDistPath:", clientDistPath);
  app.use(express.static(clientDistPath));

  app.get("*", (req, res) => res.sendFile(path.resolve(clientDistPath, "index.html")));
} else {
  app.get("/", (req, res) => res.send("Server is ready"));
}

app.use(notFound);
app.use(errorHandler);

app.listen(port, () => console.log(`Server is started on port ${port}`));

I have put all the necessary env files into render.com and for
root directory i have it under server.

when i test the npm install and the npm start locally it works just fine when i go to my localhost:5000. I only get the error when i go to the render api url.

I was expecting for the render api url to show the message Server is ready

Lock the orientation of a website made in Webflow

I want to lock the orientation of my website to Portrait mode as there is no point having a Landscape mode on it. Two options works for me:

  1. Completley locking the orientation so on a user’s screen rotation event, nothing happens (menaning, a website stays in Portrait mode).

  2. Making some good looking message that appears only when an user is in Landscape mode.

I tried looking for an answer here in Stack Overflow, but nothing helped.

Paypal button container sets background to white

I’m using the paypal api and I’m currently implementing the paypal buttons(sandbox mode). When I create them, the container background is set to white and can’t change it. I’m currently using svelte and paypal-js.

<script>
  import { loadScript } from "@paypal/paypal-js";
  import { onMount } from "svelte";
  import { userState } from "../stores/userStores";
  import { get } from "svelte/store";
  export let id = "";

  const CLIENT_ID =
    "AU-sL3infZxD_5xBKmtNPEZDTe5_MKEgAOAe00k3-k0qWjdhfVZwo4AHt428r2gNJIaYlJRVp-9iUC4H";
  let payload = {
        id: id,
      };
  loadScript({
    clientId:
      "AU-sL3infZxD_5xBKmtNPEZDTe5_MKEgAOAe00k3-k0qWjdhfVZwo4AHt428r2gNJIaYlJRVp-9iUC4H",
  }).then((paypal) => {
    paypal
      .Buttons({
        style: {
          color: "black",
          shape: "pill",
        },
        createOrder: async () => {
          // Set up the transaction
          console.log(payload);
          const request = await fetch(
            "http://127.0.0.1:3000/payments/request",
            {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify(payload),
            }
          );

          const data = await request.json();
          return data.id;
        },
        onApprove: async (data, actions) => {
          const request = await fetch(
            "http://127.0.0.1:3000/payments/capture",
            {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                orderID: data.orderID,
                email : $userState.email,
              }),
            }
          );
          const captureData = await request.json();
          return captureData;
        },
        onError: (err) => {
          // Log error if something goes wrong during approval
          console.error(err);
        },
      })
      .render("#paypal-button-container");
  });
</script>

<div
  id="paypal-button-container"
/>

<style>

</style>

Here a screenshot of the problem:
Screenshot

I would the background to be transparent but it’s white