Check if start and end datetime overlaps with an array of datetime

I have an array of objects with the following format:

const timeframes = [{
  dateStart: '2023-09-20 08:00:00',
  dateEnd: '2023-09-22 09:00:00',
}, {
  dateStart: '2023-09-26 18:00:00',
  dateEnd: '2023-09-29 22:35:00',
}];

Assuming the length of this array to be a finite number, how do I check if the range of datetime values, timeframes, overlaps a datetime value provided by user, i.e. const datetimeProvided = {dateStart: '2023-09-21 07:45:00', dateEnd: '2023-09-27 09:00:00'}?

How to create a PeerJS connection

I am trying to create a PeerJS connection where the host creates a connection by getting a generated Peer ID by calling peer.generateID(). The host should then get this ID on screen and share with his/her client to connect and record some information in the localStorage. However no Peer ID is generated for connection and no message displayed as shown below:

<html>
<head>
  <title>Peer to Peer Activity</title>
  <script src="https://cdn.peerjs.io/latest/peerjs.min.js"></script>
</head>
<body>
  <h1>Peer to Peer Activity</h1>

  <p>Select an option:</p>

  <button onclick="createHost()">Create Host</button>
  <button onclick="joinHost()">Join Host</button>

  <input type="text" id="messageInput" />
  <button onclick="sendMessage()">Send Message</button>

  <div id="message"></div>

  <script>
    // Create a PeerJS object
    var peer = new PeerJS();

    // Create a data channel
    var dataChannel = peer.createDataChannel('my-channel');

    // Listen for incoming messages
    dataChannel.onmessage = function(event) {
      // Update the message on the screen
      document.getElementById('message').innerHTML = event.data;

      // Save the message to local storage
      localStorage.setItem('message', event.data);
    };

    // Create a host
    function createHost() {
      // Generate a peer ID
      var peerID = peer.generateID();

      // Create a new host session
      var session = peer.createSession({
        id: peerID
      });
      

      // Listen for incoming connections
      session.on('connection', function(connection) {
        // Accept the connection
        connection.accept();

        // Set the data channel for the connection
        dataChannel = connection.dataChannel;
      });

      // Update the message on the screen
      document.getElementById('message').innerHTML = 'You are now hosting a session. Share the following peer ID with the other device: ' + peerID;
    };

    // Join a host
    function joinHost() {
      // Get the peer ID of the host device
      var hostPeerID = document.getElementById('hostPeerID').value;

      // Connect to the host device
      peer.connect(hostPeerID);

      // Listen for incoming connections
      peer.on('connection', function(connection) {
        // Accept the connection
        connection.accept();

        // Set the data channel for the connection
        dataChannel = connection.dataChannel;
      });

      // Update the message on the screen
      document.getElementById('message').innerHTML = 'You are now connected to the host device.';
    };

    // Send a message
    function sendMessage() {
      // Get the message from the text input
      var message = document.getElementById('messageInput').value;

      // Send the message to the other device
      dataChannel.send(message);

      // Clear the text input
      document.getElementById('messageInput').value = '';
    };
  </script>
</body>
</html>

I would like to get an assistance on why my code is not working as expected and how it should be written.

Bun + stricjs application – how to add access logs / middleware functionality

I’ve been trying to use Bun + stricjs for a very simple web backend. And I need to execute custom code before every request is processed without having to handle the paths myself

I tried registering a custom handler but when I request to /view/file.html the code for applying business rules is not executed.

// .....
export default new Router({hostname: "0.0.0.0"})
  .use('GET', "/*", ctx => {
    console.log(`Applying super complex business rules`);
  })
  .get("/view/*", dir("./public"));

ITN Callback from PayFast Returns Empty Body

I have a NodeJS Express app that returns a status 200 to PayFast on successful payment and logs the body of the response to the console. The problem is that the body is always empty and I cannot find any of the Payment’s details in the response.

I tried to log the whole response in order to locate any data but was unsuccessful.

app.post('/PayFastTest', (req, res) =>{ res.sendStatus(200); console.log(req.body) });

Pop-Up Form to Edit/Update Note From SQL Table Doesn’t Work

I am very close to completing this project I am working on. I can add new note, fetch it, delete it, but trying to edit it is not working. I have a form, similar to the one used to add new note.

I used console.log and it gives me a result, however the form still doesn’t com up.

Please help me review the code and offer help/suggestions. It’s urgent, thank you!

notes.php


<?php
// Initialize the session
session_start();

// Check if the user is logged in
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
    header("location: login.php");
    exit;
}

// Include config file
require_once "config.php";

// Handle add note request
if (isset($_POST["add_note"])) {
    $title = $_POST["title"];
    $description = $_POST["description"];
    
    // Check if title and description are not empty
    if (!empty($title) && !empty($description)) {
        $user_id = $_SESSION["id"];
        $sql = "INSERT INTO notes (user_id, title, description, date_published) VALUES (?, ?, ?, NOW())";

        if ($stmt = $mysqli->prepare($sql)) {
            $stmt->bind_param("iss", $user_id, $title, $description);
            if ($stmt->execute()) {
                // Note added successfully
                header("Location: notes.php");
            } else {
                echo "Error adding the note.";
            }
            $stmt->close();
        } else {
            echo "Error preparing the statement.";
        }
    } else {
        echo "Title and description are required.";
    }
}

// Fetch notes for the current user
$user_id = $_SESSION["id"];
$sql = "SELECT * FROM notes WHERE user_id = ?";

if ($stmt = $mysqli->prepare($sql)) {
    $stmt->bind_param("i", $user_id);
    if ($stmt->execute()) {
        $result = $stmt->get_result();

        echo '<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Notes | Noted App</title>
    <link rel="stylesheet" href="notes.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Iconscout Link For Icons -->
    <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

    <link href="https://fonts.googleapis.com/css?family=Roboto:400,500,300,700" rel="stylesheet" type="text/css">

    <link href="https://fonts.googleapis.com/css?family=Nunito:400,700,300" rel="stylesheet" type="text/css">
    <!--[if lt IE 9]>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script>
    <![endif]-->
  </head>
  <body>
    <ul class="nav-links">
      <li class="center"><a href="#">Dashboard</a></li>
      <li class="upward"><a href="#">About</a></li>
      <li class="forward"><a href="logout.php">Logout</a></li>
    </ul> 
    
    <!-- Add new note popup form -->
    <div class="popup-box" id="add-note-popup">
      <div class="popup">
        <div class="content">
          <header>
            <p>Add a New Note</p>
            <i class="uil uil-times" id="closeAddNotePopup"></i>
          </header>
          <form action="" method="post">
            <div class="row title">
              <label for="title">Title</label>
              <input type="text" spellcheck="false" id="title" name="title">
            </div>
            <div class="row description">
              <label for="desc">Description</label>
              <textarea spellcheck="false" id="desc" name="description"></textarea>
            </div>
            <button type="submit" name="add_note">Add Note</button>
          </form>
        </div>
      </div>
    </div>

    <!-- Edit note popup form -->
    <div class="popup-box" id="edit-note-popup">
      <div class="popup">
        <div class="content">
          <header>
            <p>Edit Note</p>
            <i class="uil uil-times" id="closeEditNotePopup"></i>
          </header>
          <form action="" method="post">
            <div class="row title">
              <label for="title">Title</label>
              <input type="text" spellcheck="false" id="title" name="title">
            </div>
            <div class="row description">
              <label for="desc">Description</label>
              <textarea spellcheck="false" id="desc" name="description"></textarea>
            </div>
            <button type="submit" name="update_note">Update Note</button>
          </form>
        </div>
      </div>
    </div>
    
    <div class="wrapper">
      <li class="add-box" id="addNewNoteButton">
        <div class="icon"><i class="uil uil-plus"></i></div>
        <p>Add new note</p>
      </li>
      <div class="notes-list">'; // Start the notes list
      
      while ($row = $result->fetch_assoc()) {
        // Format the date
        $formattedDate = date("F j, Y", strtotime($row['date_published']));

        echo '<li class="note">
            <div class="details">
                <p>' . $row['title'] . '</p>
                <span>' . nl2br($row['description']) . '</span>
            </div>
            <div class="bottom-content"> 
                <span>' . $formattedDate . '</span>
                <div class="settings">
                <i class="uil uil-ellipsis-h" onclick="showMenu(this)" data-note-id="' . $row['note_id'] . '"></i>
                <ul class="menu">
                  <li class="edit-note" data-note-id="' . $row['note_id'] . '" data-title="' . $row['title'] . '" data-description="' . addslashes($row['description']) . '"><i class="uil uil-pen"></i>Edit</li>
                  <li class="delete-note" data-note-id="' . $row['note_id'] . '"><i class="uil uil-trash"></i>Delete</li>

                </ul>
            </div>

          </div>
        </li>';
      }

      echo '</div></div>';

      echo '<form action="delete_note.php" method="post" id="deleteForm" enctype="application/x-www-form-urlencoded">
            <input type="hidden" id="deleteNoteId" name="delete_note" value="">
          </form>';

          echo ' <form action="update_note.php" method="post" id="updateForm" enctype="application/x-www-form-urlencoded">
          <input type="hidden" id="updateNoteId" name="note_id" value="">
          <input type="hidden" id="updateNoteTitle" name="title" value="">
          <input type="hidden" id="updateNoteDescription" name="description" value="">
          </form>';

      echo'</body>
      <script src="notescript.js"></script>
    </html>';
    } else {
        echo "Error fetching notes.";
    }
    $stmt->close();
}
$mysqli->close();
?>

notescript.js

document.addEventListener("DOMContentLoaded", function () {
    const addNewNoteButton = document.getElementById("addNewNoteButton");
    const addNotePopup = document.getElementById("add-note-popup");
    const closeAddNotePopup = document.getElementById("closeAddNotePopup");
    const editNoteButtons = document.querySelectorAll(".edit-note");
    const deleteNoteButtons = document.querySelectorAll(".delete-note");
    const popupBox = document.querySelector(".popup-box");
    const closeIcon = popupBox.querySelector("header i");
    const popupTitle = popupBox.querySelector("header p");
    const descTag = popupBox.querySelector("textarea");
    const titleTag = popupBox.querySelector("input");
    const notesList = document.querySelector(".notes-list");

    addNewNoteButton.addEventListener("click", () => {
        popupTitle.innerText = "Add a new Note";
        addNewNoteButton.innerText = "Add Note";
        addNotePopup.classList.add("show");
        if (window.innerWidth > 660) titleTag.focus();
    });

    closeIcon.addEventListener("click", () => {
        titleTag.value = descTag.value = "";
        popupBox.classList.remove("show");
        document.querySelector("body").style.overflow = "auto";
    });

    window.showMenu = function (elem) {
        elem.parentElement.classList.add("show");
        document.addEventListener("click", e => {
            if (e.target.tagName != "I" || e.target != elem) {
                elem.parentElement.classList.remove("show");
            }
        });
    }

// Edit note buttons
editNoteButtons.forEach((editButton) => {
    editButton.addEventListener("click", () => {
        const noteId = editButton.dataset.noteId;
        const title = editButton.dataset.title;
        const description = editButton.dataset.description;

        console.log('edit menu has been clicked!');


        // Populate the edit note popup with the note's details
        const titleInput = document.getElementById("title");
        const descInput = document.getElementById("desc");
        titleInput.value = title;
        descInput.value = description;

        // Set the edit form's action to the correct URL (update_note.php)
        document.getElementById("updateForm").action = "update_note.php";

        // Add hidden inputs to track the note being edited
        const updateNoteId = document.getElementById("updateNoteId");
        const updateNoteTitle = document.getElementById("updateNoteTitle");
        const updateNoteDescription = document.getElementById("updateNoteDescription");

        updateNoteId.value = noteId;
        updateNoteTitle.value = title;
        updateNoteDescription.value = description;

        // Display the edit note popup
        const editNotePopup = document.getElementById("edit-note-popup");
        editNotePopup.style.display = "block";
    });
});




    // Delete note buttons
    deleteNoteButtons.forEach((deleteButton) => {
        const noteId = deleteButton.dataset.noteId;

        deleteButton.addEventListener("click", () => {
            const confirmDel = confirm("Are you sure you want to delete this note?");
            if (confirmDel) {
                // Create a FormData object and append the noteId
                const formData = new FormData();
                formData.append("delete_note", noteId);

                // Use fetch to send the FormData
                fetch("delete_note.php", {
                    method: "POST",
                    body: formData,
                })
                .then(response => response.json())
                .then(data => {
                    // Handle the response here, e.g., remove the deleted note from the UI
                    console.log(data);
                    if (data.success) {
                        // Note deleted successfully, remove it from the UI
                        const noteToDelete = deleteButton.closest(".note");
                        noteToDelete.remove();
                    }
                })
                .catch(error => {
                    console.error("Error:", error);
                });
            }
        });
    });
});

notes.css

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  background: #88ABFF;
}
::selection{
  color: #fff;
  background: #618cf8;
}
.wrapper{
  margin: 50px;
  display: grid;
  gap: 25px;
  grid-template-columns: repeat(auto-fill, 265px);
}
.wrapper li{
  height: 250px;
  list-style: none;
  border-radius: 5px;
  padding: 15px 20px 20px;
  background: #fff;
  box-shadow: 0 4px 8px rgba(0,0,0,0.05);
}
.add-box, .icon, .bottom-content, 
.popup, header, .settings .menu li{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.add-box{
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
}
.add-box .icon{
  height: 78px;
  width: 78px;
  color: #88ABFF;
  font-size: 40px;
  border-radius: 50%;
  justify-content: center;
  border: 2px dashed #88ABFF;
}
.add-box p{
  color: #88ABFF;
  font-weight: 500;
  margin-top: 20px;
}
.note{
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.note .details{
  max-height: 165px;
  overflow-y: auto;
}
.note .details::-webkit-scrollbar,
.popup textarea::-webkit-scrollbar{
  width: 0;
}
.note .details:hover::-webkit-scrollbar,
.popup textarea:hover::-webkit-scrollbar{
  width: 5px;
}
.note .details:hover::-webkit-scrollbar-track,
.popup textarea:hover::-webkit-scrollbar-track{
  background: #f1f1f1;
  border-radius: 25px;
}
.note .details:hover::-webkit-scrollbar-thumb,
.popup textarea:hover::-webkit-scrollbar-thumb{
  background: #e6e6e6;
  border-radius: 25px;
}
.note p{
  font-size: 22px;
  font-weight: 500;
}
.note span{
  display: block;
  color: #575757;
  font-size: 16px;
  margin-top: 5px;
}
.note .bottom-content{
  padding-top: 10px;
  border-top: 1px solid #ccc;
}
.bottom-content span{
  color: #6D6D6D;
  font-size: 14px;
}
.bottom-content .settings{
  position: relative;
}
.bottom-content .settings i{
  color: #6D6D6D;
  cursor: pointer;
  font-size: 15px;
}
.settings .menu{
  z-index: 1;
  bottom: 0;
  right: -5px;
  padding: 5px 0;
  background: #fff;
  position: absolute;
  border-radius: 4px;
  transform: scale(0);
  transform-origin: bottom right;
  box-shadow: 0 0 6px rgba(0,0,0,0.15);
  transition: transform 0.2s ease;
}
.settings.show .menu{
  transform: scale(1);
}
.settings .menu li{
  height: 25px;
  font-size: 16px;
  margin-bottom: 2px;
  padding: 17px 15px;
  cursor: pointer;
  box-shadow: none;
  border-radius: 0;
  justify-content: flex-start;
}
.menu li:last-child{
  margin-bottom: 0;
}
.menu li:hover{
  background: #f5f5f5;
}
.menu li i{
  padding-right: 8px;
}

.popup-box{
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2;
  height: 100%;
  width: 100%;
  background: rgba(0,0,0,0.4);
}
.popup-box .popup{
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: 100%;
  max-width: 400px;
  justify-content: center;
  transform: translate(-50%, -50%) scale(0.95);
}
.popup-box, .popup{
  opacity: 0;
  pointer-events: none;
  transition: all 0.25s ease;
}
.popup-box.show, .popup-box.show .popup{
  opacity: 1;
  pointer-events: auto;
}
.popup-box.show .popup{
  transform: translate(-50%, -50%) scale(1);
}
.popup .content{
  border-radius: 5px;
  background: #fff;
  width: calc(100% - 15px);
  box-shadow: 0 0 15px rgba(0,0,0,0.1);
}
.content header{
  padding: 15px 25px;
  border-bottom: 1px solid #ccc;
}
.content header p{
  font-size: 20px;
  font-weight: 500;
}
.content header i{
  color: #8b8989;
  cursor: pointer;
  font-size: 23px;
}
.content form{
  margin: 15px 25px 35px;
}
.content form .row{
  margin-bottom: 20px;
}
form .row label{
  font-size: 18px;
  display: block;
  margin-bottom: 6px;
}
form :where(input, textarea){
  height: 50px;
  width: 100%;
  outline: none;
  font-size: 17px;
  padding: 0 15px;
  border-radius: 4px;
  border: 1px solid #999;
}
form :where(input, textarea):focus{
  box-shadow: 0 2px 4px rgba(0,0,0,0.11);
}
form .row textarea{
  height: 150px;
  resize: none;
  padding: 8px 15px;
}
form button{
  width: 100%;
  height: 50px;
  color: #fff;
  outline: none;
  border: none;
  cursor: pointer;
  font-size: 17px;
  border-radius: 4px;
  background: #6A93F8;
}

@media (max-width: 660px){
  .wrapper{
    margin: 15px;
    gap: 15px;
    grid-template-columns: repeat(auto-fill, 100%);
  }
  .popup-box .popup{
    max-width: calc(100% - 15px);
  }
  .bottom-content .settings i{
    font-size: 17px;
  }
}

.nav-links{
    display: flex;
    align-items: center;
    background: #fff;
    padding: 20px 15px;
    border-radius: 12px;
    box-shadow: 0 5px 10px rgba(0,0,0,0.2);
  }
  .nav-links li{
    list-style: none;
    margin: 0 12px;
  }
  .nav-links li a{
    position: relative;
    color: #333;
    font-size: 20px;
    font-weight: 500;
    padding: 6px 0;
    text-decoration: none;
  }
  .nav-links li a:before{
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    height: 3px;
    width: 0%;
    background: #34efdf;
    border-radius: 12px;
    transition: all 0.4s ease;
  }
  .nav-links li a:hover:before{
    width: 100%;
  }
  .nav-links li.center a:before{
    left: 50%;
    transform: translateX(-50%);
  }
  .nav-links li.upward a:before{
    width: 100%;
    bottom: -5px;
    opacity: 0;
  }
  .nav-links li.upward a:hover:before{
    bottom: 0px;
    opacity: 1;
  }
  .nav-links li.forward a:before{
    width: 100%;
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.4s ease;
  }
  .nav-links li.forward a:hover:before{
    transform: scaleX(1);
    transform-origin: left;
  }

  .notes-list {
    display: contents;
    margin: 0;
    padding: 0;
    border: none;
  }

  .showMenu {
    padding: 0;
    border: 0;
    border: 0;
  }
  
  #edit-note-popup {
    display: none; /* Hide the popup by default */
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
    width: 300px; /* Adjust the width as needed */
    padding: 20px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    z-index: 999; /* Ensure the popup is on top of other elements */
}

#edit-note-popup header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#edit-note-popup header p {
    font-size: 18px;
    font-weight: bold;
    margin: 0;
}

#edit-note-popup header i {
    cursor: pointer;
    font-size: 24px;
    color: #333;
}

#edit-note-popup form {
    margin-top: 10px;
}

#edit-note-popup form label {
    font-size: 14px;
    display: block;
    margin-bottom: 5px;
}

#edit-note-popup form input[type="text"],
#edit-note-popup form textarea {
    width: 100%;
    padding: 10px;
    margin-bottom: 15px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 14px;
}

#edit-note-popup form button {
    background-color: #007BFF;
    color: #fff;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
}

#edit-note-popup form button:hover {
    background-color: #0056b3;
}

update_note.php

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

session_start();

if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
    // Redirect to login page or handle unauthorized access as needed
    echo json_encode(array("error" => "Unauthorized access"));
    exit;
}

require_once "config.php";

// Get POST data
$data = $_POST;

if (empty($data["note_id"]) || empty($data["title"]) || empty($data["description"])) {
    echo json_encode(array("error" => "Note ID, title, and description are required"));
    exit;
}

$noteIdToUpdate = $data["note_id"];
$titleToUpdate = $data["title"];
$descriptionToUpdate = $data["description"];

// Prepare and execute the SQL statement to update the note
$sql = "UPDATE notes SET title = ?, description = ? WHERE note_id = ? AND user_id = ?";

if ($stmt = $mysqli->prepare($sql)) {
    $stmt->bind_param("ssii", $titleToUpdate, $descriptionToUpdate, $noteIdToUpdate, $_SESSION["id"]);

    if ($stmt->execute()) {
        echo json_encode(array("success" => true));
    } else {
        echo json_encode(array("error" => "Error updating the note"));
    }

    $stmt->close();
} else {
    echo json_encode(array("error" => "Error preparing the statement"));
}

$mysqli->close();
?>

I tried to handle the edit/update note part, expecting a pop up form anytime the edit icon or text is clicked but it doesn’t bring up anything.

How to Shopify Display Exc VAT Price for Product Variants?

Been working on a website where I want two prices to appear on the product page.

  1. Default Inc VAT Price
  2. Exc VAT Price, which would be the default price divided by 1.2

We’re using the enterprise theme and I’ve managed to get it to display on the product page by amending the main-product.liquid file.

          {%- when 'price' -%}
            <div class="product-info__block product-info__block--sm product-price" {{ block.shopify_attributes }}>
              <div class="product-info__price">
                {% render 'price', product: product, use_variant: true %}
                <p> {{ product.price | divided_by: 1.2 | money }} ex. VAT </p>
              </div>

However, the problem I have now is that the price doesn’t update when clicking on different variations that the product has, the default price does update, just not the Exc VAT price I’ve added in.

Any pointers? Thanks.

Hide JavaScript source in another JavaScript file?

So far I have an HTML file with something like:

<script src="http://example.com/script"></script>

But I want to hide this “http://example.com/script” from my main HTML file. So is it possible to do something like:

<script src="script1.js"></script>

And set script1.js to execute the script the same way
<script src="http://example.com/script"></script>
does?

In script1.js tell that
src="http://example.com/script"
something like that?

Could not connect, server may not be running

I keep trying to join mysql database using sequelize,

dbconfig

const Sequelize = require('sequelize')
  
// Creating new Object of Sequelize
const sequelize = new Sequelize(
    'mysql-server',
    'root',
    'toor', {
  
        // Explicitly specifying 
        // mysql database
        dialect: 'mysql',
  
        // So by default, host is 'localhost'           
        host: 'localhost'
    }
);
  
module.exports = sequelize

models/index.js

const sequelize = require('../configs/dbConfig');
const {DataTypes} = require('sequelize');

//connect the
sequelize.authenticate()
.then(() => {
    console.log('connected to the databse')
})
.catch(err => {
    console.log('Error'+ err)
})

but i keep getting this error “ErrorSequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:3306” on the terminal and on the database i get this error’Could not connect, server may not be running. Unable to connect to localhost ‘

im pretty sure i copied the credentials properly

Why wont my images load in my React Vite project?

Public Folder>>
leaves.jpg

App.jsx:

function App() {
return (
<img src="./public/leaves.jpg" alt "img" />
)
}

The image is showing up on my image-preview extension which usually indicated the path is correct, I’m not sure what I’m doing wrong. It doesn’t return an error when I try to use this method. I also tried importing the image like: import leaves from './public/leaves.jpg' and plugging it in like: <img src={leaves} alt "img" />, but it was throwing an error that the file couldn’t be found.

Any help would be appreciated, thank you.

@aws-sdk/client-sns nothing happens when sending sms

Using aws-sdk v2 previously works fine before.
I’m trying to use the v3 now and somehow, I get a good response but sms is never received. I wonder if there’s some settings I’m missing here.

Here are the steps I took approach.

  1. Created a new policy just to publish sns
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "*"
        }
    ]
}
  1. The user is attached to the policy, then created access token + secret access token for the user.

  2. Created code.

import { PublishCommand, SNSClient } from '@aws-sdk/client-sns';

export const sendSms = async () => {

  try {
    const client = new SNSClient({credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY as string,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string
      }});

    const input = { // PublishInput
      PhoneNumber: "+16045181234",
      Message: "test message", // required
    };
    const command = new PublishCommand(input);
    const response = await client.send(command);

    console.log(new Date());
    console.log(response, 'response ');

    return;
  } catch (e: any) {
      console.log(e, 'SEND SMS');
  }
}

  1. Getting the response
{
  '$metadata': {
    httpStatusCode: 200,
    requestId: '6c3f80ea-3ff2-5c38-bda6-dd6e27661c74',
    extendedRequestId: undefined,
    cfId: undefined,
    attempts: 1,
    totalRetryDelay: 0
  },
  MessageId: 'a94988b1-ba63-5f5b-a647-d535a2f78f17'
}

But not getting any messages on mobile at all and no error thrown too.

Thank you in advance for any suggestions or advices.

Threebox adding tooltips to building layer

I am trying to get a marker/label/tooltip placed on top of a 3d building but cannot seem to find a solution. I’ve started looking at Threebox and seem to have been able to place a tooltip on the building following the example given in Threebox docs. The issue here is this section of the example code places the popup at the bottom of the building, whereas the tooltip is at the top.

function onSelectedFeatureChange(e) {
            let feature = e.detail;
            if (feature && feature.state && feature.state.select) {

                if (popup) popup.remove();

                let center = [];
                let coords = tb.getFeatureCenter(feature, null, 0);

                center.push([coords[0], coords[1]]);

                //TODO: this creates a Mapbox popup in the same coords the Threebox popup to see the difference
                popup = new mapboxgl.Popup({ offset: 0 })
                    .setLngLat(center[0].slice())
                    .setHTML('<strong>' + (feature.id || feature.type) + '</strong >')
                    .addTo(map);

                let geoJson = {
                    "geometry": feature.geometry,
                    "type": "Feature",
                    "properties": feature.properties
                }
                console.log(JSON.stringify(geoJson, null, 2))

            }


        }

enter image description here

  • How can I place the popup in the same position as the tooltip?

  • If I am not able to place the popup in the location of the tooltip, how can I change the value inside of the tooltip?

  • If I cannot change the value inside of the tooltip, how do I add a new tooltip to the selected building? The feature that is returned in the onSelectedFeatureChange function has a addTooltip method, but it requires an obj in order to place the tooltip.

How to pass image as a prop in Vue.JS with Vite?

I cant pass image as an props in Vue + Vite.
So i have my component with the code:

 <div name="image">
        **<img :src="getImageUrl()"** :alt="imageDesc" />
      </div>
      <div name="card title" class="mt-5 border-2 border-blue-600 text-center text-xl font-bold">
        {{ title }}
      </div>
      <div
        name="card description"
        class="border-2 border-red-600 text-center font-semibold text-gray-500"
      >
        {{ description }}
      </div>

and the script:

<script setup>
import { defineProps } from 'vue'
const props = defineProps({
  title: String,
  description: String,
  imageURL: String,
  imageDesc: String
})

function getImageUrl() {
  // This path must be correct for your file
  return new URL(`../assets/img/landing_page/${props.imageURL}`, import.meta.url)
}
</script>

and i use it like:

<offer-section-card
      title="Vue"
      description="Vue3 is a modern JavaScript framework for building user interfaces.
      Created and maintained by Javascript legend Evan You. It combines best of React and AngularJS."
      image-url="vue.png"
      image-desc="Vue logo"
    ></offer-section-card>

the paths are:

C:UsersuserDesktopp1srcassetsimglanding_pagevue.png -> to image
C:UsersuserDesktopp1srccomponentsLandingPageCmpsOfferSection.vue -> to parent cmp
C:UsersuserDesktopp1srccomponentsLandingPageCmpsOfferSectionCard.vue -> to child component

so require() doesnt work with Vite and i found this solution, but it also doesnt work. Even i manualy put the right path the image doesnt work. I tried also using image-url, imageURL and so on.

Like it is very basic functinality i and use the newest verstion of Vue. Is it supposed to be like easy framework or what? Why image as a prop is such a big deal…

Factory functions and composition

I have the following code in JavaScript:

const calculateDiameter = (circle) => ({
  get diameter() {
    return (circle.radius * 2);
  }
});

const calculateCircumfrance = (circle) => ({
  get circumfrance () {
    return (2 * (22 / 7) * circle.radius)
  }
});

const createCircle = (radius) => {
  const circle = {
    radius
  };
  
  return Object.assign(
    circle,
    calculateDiameter(circle),
    calculateCircumfrance(circle)
  )
}

// Create a cirlce
const myCircle = createCircle(2);
console.log( myCircle.diameter ) // returns: 4
console.log( myCircle.circumfrance ) // returns: 12.571428571428571

What I’d like to do is pass the output of calculateDiameter() to calculateCircumfrance(), so here is what I did:

// The following function was NOT modified
const calculateDiameter = (circle) => ({
  get diameter() {
    return (circle.radius * 2);
  }
});

const calculateCircumfrance2 = (circle) => ({
  get circumfrance () {
    return ((22 / 7) * circle.diameter)
  }
});

const createCircle2 = (radius) => {
  const circle = {
    radius
  };

  const circleWithDiameter = Object.assign(
    circle,
    calculateDiameter(circle),
  )
  
  return Object.assign(
    circleWithDiameter,
    calculateCircumfrance2(circleWithDiameter)
  )
}

// Create a cirlce
const myCircle2 = createCircle2(2);
console.log( myCircle2.diameter ) // returns: 4
console.log( myCircle2.circumfrance ) // returns: 12.571428571428571

Is this approach described in createCircle2() correct? In other words, should I create a middle step object (i.e., circleWithDiameter) to allow me to pass the diameter to calculateCircumfrance2()? It seems like an overload. Is there a more succinct way or direct way to call calculateDiameter() from within calculateCircumfrance2()?

The reason for this question is I will have a very complex object (as opposed to the circle), and those middle steps seem to be too convoluted.

Vue 3 shows previous route in onMounted

I’m using Vue with a dynamic navigation based on my backend. An endpoint decides what page to display based on the current route.

I’ve made a simplified version below with the relevant parts. Everything works fine, except for when I use a <router-link> or router.push to one of my routes. In the onMounted callback of my target page, the route seems to be the previous route (see AboutView.vue below).

I’ve tried await router.isReady(), but as far as I can tell it’s not relevant here, it’s only used for an initial page view.

Sample repo built with node 16.13.2: https://github.com/tietoevry-johan/vue-routing

App.vue

<template>
  <router-view/>
</template>

router.ts

export const currentPage = ref('HomeView')

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      name: "PageSelector",
      path: "/:catchAll(.*)",
      component: PageSelector
    }
  ]
});

router.beforeEach(async (to, _, next) => {
  currentPage.value = await getComponentByPath(to.path)
  next()
})

async function getComponentByPath(path: string) {
  return path === '/' ? 'HomeView' : 'AboutView'
}

PageSelector.vue

<template>
  <component :is="currentPage" />
</template>

<script lang="ts">
import { defineComponent } from "vue"
import AboutView from "@/views/AboutView.vue"
import HomeView from "@/views/HomeView.vue"
import { currentPage } from "@/router"

export default defineComponent({
  // eslint-disable-next-line vue/no-unused-components
  components: { HomeView, AboutView },
  setup() {
    return {
      currentPage
    }
  }
})
</script>

AboutView.vue

<template>
  about
</template>

<script lang="ts">
import router from "@/router";
import { defineComponent, onMounted } from "vue";

export default defineComponent({
  setup() {
    onMounted(() => {
      console.log(router.currentRoute.value?.fullPath) // prints / instead of /about
      // when clicking a router link or router push to this page
    })
  }
})

</script>

I am learning to make a website usign nodejs, express, mongoose, handlebars. trouble deleting a reply to a comment on a webpage

I am learning to create a website that allows users to post blogs, users to comment on the blogs and users to reply to those comments. I have used replies[this] in the comment schema to deal with replies to comments. But I am having trouble being able to allow the user to delete these replies. Here is my server side code to delete comments and replies.

// Delete a specific comment or reply
app.get('/deleteComment/:postId/:commentId', requireLogin, async (req, res) => {
    try {
        const currentUser = req.user; 
        const { replyId } = req.query; 
        const foundPost = await Post.findById(req.params.postId);
        
        if (replyId) {  // If it's a reply
            const comment = foundPost.comments.id(req.params.commentId);
            const reply = comment.replies.id(replyId);
            
            // Check if the user is the author of the reply
            if (reply.commentUser.toString() !== currentUser._id.toString()) {
                return res.status(403).send('Permission denied: You can only delete your own replies.');
            }

            reply.remove();
        } else {  // It's a top-level comment
            const comment = foundPost.comments.id(req.params.commentId);

            // Check if the user is the author of the comment
            if (comment.commentUser.toString() !== req.user._id.toString()) {
                return res.status(403).send('Permission denied: You can only delete your own comments.');
            }

        
            comment.remove();
        }
        
        await foundPost.save();
        res.status(200).send('Deleted successfully');
    } catch (err) {
        console.log(err);
        res.status(500).send("An error occurred");
    }
});

Here is my front end,

  <a href="#" onclick="deleteComment('{{../post._id}}', '{{_id}}')">
            <i class="fa fa-trash post-icons"></i>
          </a>
  function deleteComment(postId, commentId) {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', `/deleteComment/${postId}/${commentId}`, true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                location.reload(); 
            } else if (xhr.status === 403) {
               
                alert('Permission denied: You can only delete your own comments.');
            } else {
               
                alert('An error occurred while deleting the comment.');
            }
        }
    };
    xhr.send();
}

Replies are stored as objects in an array inside the comments array in mongoose
comments: Array
0: Object
commentUser ObjectId: 650
commentBody: “Hello World”
dateCreated: 2023
replies: Array
0: Object
commentUser: Object
commentBody: “Hello World Replies”
dateCreated: 2023

Every time I try to delete a reply, I get 404 errors. I can delete comments, its just replies. I have tried numerous thing like changing routes and functions to include replyId but it just keeps giving the 404 error. Any ideas why its not working?

I have tried numerous thing like changing routes and functions to include replyId.