Selecting a default value for filter_select from crosstalk in R shiny using JS not working

I am trying to apply default value for Gender filter to be ‘ALL’. I am using filter_select() to create the filters. When the run report button is pressed, the shared data is created, the filters are generated and the datatable is rendered. The table loads and the filters work but the default value is not set. I am using the JS solution from this post.

library(shiny)
library(DT)
library(crosstalk)

# Sample data for demonstration
dat <- structure(list(`Disease-name` = c(4002L, 4002L, 4002L, 4002L, 
                                         4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 
                                         4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 
                                         4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 4002L, 
                                         4002L, 4002L, 4002L, 4002L, 4002L), grp = c("TD", "PD", "ND", 
                                                                                     "ND", "PD", "ND", "PD", "PD", "ND", "TD", "TD", "TD", "TD", "ND", 
                                                                                     "ND", "ND", "PD", "ND", "PD", "ND", "PD", "ND", "PD", "TD", "TD", 
                                                                                     "TD", "TD", "PD", "PD", "PD", "ND", "ND", "PD", "TD", "TD", "TD"
                                         ), Gender = c("ALL", "MALE", "MALE", "MALE", "MALE", "MALE", 
                                                       "MALE", "MALE", "MALE", "MALE", "MALE", "MALE", "MALE", "ALL", 
                                                       "ALL", "FEMALE", "FEMALE", "FEMALE", "FEMALE", "FEMALE", "FEMALE", 
                                                       "FEMALE", "FEMALE", "FEMALE", "FEMALE", "FEMALE", "FEMALE", "ALL", 
                                                       "ALL", "ALL", "ALL", "ALL", "ALL", "ALL", "ALL", "ALL"), u_numpat = c(8L, 
                                                                                                                             5L, 0L, 6L, 46L, 54L, 206L, 257L, 60L, 5L, 52L, 260L, 317L, 2L, 
                                                                                                                             12L, 6L, 55L, 66L, 304L, 2L, 1L, 74L, 360L, 61L, 370L, 3L, 434L, 
                                                                                                                             6L, 617L, 510L, 134L, 120L, 101L, 630L, 113L, 751L), w_numpat = c(179.82524660264, 
                                                                                                                                                                                               105.148541663513, 0, 258, 1686.50661547721, 847, 3077.00035384634, 
                                                                                                                                                                                               4868.65551098707, 1105, 105.148541663513, 1944.50661547721, 3924.00035384634, 
                                                                                                                                                                                               5973.65551098707, 53, 527, 269, 2229.29975337235, 1105, 4389.38128191602, 
                                                                                                                                                                                               53, 21.676704939127, 1427, 6640.3577402275, 2498.29975337235, 
                                                                                                                                                                                               5494.38128191602, 74.676704939127, 8067.3577402275, 126.82524660264, 
                                                                                                                                                                                               11509.0132512146, 7466.38163576236, 2532, 1952, 3915.80636884956, 
                                                                                                                                                                                               9418.38163576236, 4442.80636884956, 14041.0132512146), `Age-Group` = c("under 18", 
                                                                                                                                                                                                                                                                      "under 18", "under 18", "65 and over", "65 and over", "18 to 64", 
                                                                                                                                                                                                                                                                      "18 to 64", "ALL", "ALL", "under 18", "65 and over", "18 to 64", 
                                                                                                                                                                                                                                                                      "ALL", "under 18", "65 and over", "65 and over", "65 and over", 
                                                                                                                                                                                                                                                                      "18 to 64", "18 to 64", "under 18", "under 18", "ALL", "ALL", 
                                                                                                                                                                                                                                                                      "65 and over", "18 to 64", "under 18", "ALL", "under 18", "ALL", 
                                                                                                                                                                                                                                                                      "18 to 64", "ALL", "18 to 64", "65 and over", "18 to 64", "65 and over", 
                                                                                                                                                                                                                                                                      "ALL")), row.names = c(NA, 36L), class = "data.frame")
ui <- page_navbar(
  tags$head(
    #includeCSS(file.path('www', 'style2.css')),
    shinyjs::useShinyjs(),
    
    # Add JavaScript code to set default value for gender filter
    tags$script(HTML("
      $(document).ready(function() {
        $('#filter_gender').find('.selectized').selectize()[0].selectize.setValue('ALL', false);
      });
    "))
  ),
  
  navbarMenu("Batch Cohort Analysis", icon = icon('ranking-star'), 
             tabPanel("Cohort Selection",
                      layout_sidebar(
                        fillable = TRUE,
                        fill = TRUE,
                        full_screen = TRUE,
                        sidebar = sidebar(
                          width = 500,
                          id = 'sidebar',
                          bg = 'white',
                          accordion(
                            id = "myAccordion",
                            accordion_panel(
                              title = "User Inputs", icon = bsicons::bs_icon('menu-app'),
                              actionButton(inputId = "run_report", label = "Run Report"),
                              uiOutput("filtera")
                            )
                          )
                        ),
                        
                        mainPanel(
                          width = 12,
                          div(id='headingtxt', "Main Content Area"),
                          DTOutput("report_table")  # Use DTOutput to render the table
                        )
                      )
             )
  )
)

server <- function(input, output, session) {
  
  observeEvent(input$run_report, {
    req(SharedData)
    shared_data <- SharedData$new(dat)
    
    output$filtera <- renderUI({
      
      
      tagList(
        h4("Filters"),  # Heading for the filters
        fluidRow(
          column(3, filter_select("filter_gender", "Select Gender", shared_data, ~Gender)),  # Gender filter
          column(3, filter_select("filter_disease", "Select Cohort", shared_data, ~`Disease-name`)),  # Cohort filter
          column(3, filter_select("filter_age", "Select Age Group", shared_data, ~`Age-Group`))
        )
      )
    })
    
    output$report_table <- renderDT({
      filtered_data <- shared_data$data()
      
      
      
      datatable(filtered_data, options = list(
        pageLength = 10,
        autoWidth = TRUE,
        dom = 'bfrtip',  # Add buttons and filtering
        buttons = c('csv', 'excel'),  # Add export buttons
        columnDefs = list(
          list(className = 'dt-left', targets = c(0, 1))  # Center align all columns
        )
      ), rownames = FALSE) %>%
        formatRound(columns = c(4:6), digits = 0)  # Use dt for better table rendering
    })
    
    
  })
  
}

shinyApp(ui = ui, server = server)

How to prevent clicking buttons under a css popover’s backdrop?

I am implementing simple popover elements across my website.
They take c. 80% of the viewport’s width, so I have enabled a blur effect backdrop around the popover.

.mb_popbox::backdrop {
    backdrop-filter: blur(5px);

}

The problem:

When clicking outside the popover:

The desired effect should be to shut down the popover element by clicking just ANYWEHERE on the outside.

Unfortunately, when clicking randomly on the outside area, sometimes active a links or buttons are activated. Very annoying

An example

html:

<button type="button" popovertarget="menu_topics" title=""><i class="fas fa-list"></i></button>

<div class="mb_popbox" style="padding:5rem;" id="menu_topics" popover>
    <h3 style="">Menu</h3>
    <p>
     
    </p>
    <ul class="no_bullets" rel="topics" style="">
        
        <li><a href="{{URL::to('/')}}">Link 1</a></li>

    </ul>
    <p style="text-align: right;"><button class="" popovertarget="menu_topics" popovertargetaction="hide" title="">Zamknij</button></p>
</div>

CSS:

.mb_popbox {
  width: 70%;
  margin: 2rem auto;
  min-height: 20rem;
  max-height: 80%;
  padding: 3rem;  
  background: #444;
  color: #fff;
  border: 3px solid #eee;

}

.mb_popbox::backdrop {
    backdrop-filter: blur(5px);

}

TODO

Is there any by-the book way to prevent the accidental link & button clicks?

A workaround is obvious: do a 100% wide and 100% high div and then build the actual usable content 80% wide and 80% high on top of the backdrop area. Plus necessary js for clicks on the “outside” I wish to avoid this as it is not elegant imo.

This infinite carousel is not working as intended and I have not been able to find the issue thus far

I have a carousel that I’m using to display products. It shows 3 cards at a time on the desktop viewport and it should start with product 1, 2, & 3. Instead, it starts with 5, 6, & 1.

Then as I click on the right button to move it, it will go to product 2 then on another click, instead of going to product 3, it reverts back to the 5, 6, 1 order.

I’m using Shopify’s liquid file format. Here is my code:

  const wrapper = document.querySelector(".wrapper");
  const carousel = document.querySelector(".carousel");
  const firstCardWidth = carousel.querySelector(".card").offsetWidth;
  const arrowBtns = document.querySelectorAll(".wrapper i");
  const carouselChildrens = [...carousel.children];
  
  let isDragging = false, isAutoPlay = true, startX, startScrollLeft, timeoutId;
  
  // Get the number of cards that can fit in the carousel at once
  let cardPerView = Math.round(carousel.offsetWidth / firstCardWidth);
  
  // Insert copies of the last few cards to beginning of carousel for infinite scrolling
  carouselChildrens.slice(-cardPerView).reverse().forEach(card => {
    carousel.insertAdjacentHTML("afterbegin", card.outerHTML);
  });
  
  // Insert copies of the first few cards to end of carousel for infinite scrolling
  carouselChildrens.slice(0, cardPerView).forEach(card => {
    carousel.insertAdjacentHTML("beforeend", card.outerHTML);
  });
  
  // Scroll the carousel at appropriate postition to hide first few duplicate cards on Firefox
  carousel.classList.add("no-transition");
  carousel.scrollLeft = carousel.offsetWidth;
  carousel.classList.remove("no-transition");
  
  // Add event listeners for the arrow buttons to scroll the carousel left and right
  arrowBtns.forEach(btn => {
    btn.addEventListener("click", () => {
      carousel.scrollLeft += btn.id == "left" ? -firstCardWidth : firstCardWidth;
    });
  });
  
  const dragStart = (e) => {
    isDragging = true;
    carousel.classList.add("dragging");
    // Records the initial cursor and scroll position of the carousel
    startX = e.pageX;
    startScrollLeft = carousel.scrollLeft;
  }
  
  const dragging = (e) => {
    if (!isDragging) return; // if isDragging is false return from here
    // Updates the scroll position of the carousel based on the cursor movement
    carousel.scrollLeft = startScrollLeft - (e.pageX - startX);
  }
  
  const dragStop = () => {
    isDragging = false;
    carousel.classList.remove("dragging");
  }
  
  const infiniteScroll = () => {
    // If the carousel is at the beginning, scroll to the end
    if (carousel.scrollLeft === 0) {
      carousel.classList.add("no-transition");
      carousel.scrollLeft = carousel.scrollWidth - (2 * carousel.offsetWidth);
      carousel.classList.remove("no-transition");
    }
    // If the carousel is at the end, scroll to the beginning
    else if (Math.ceil(carousel.scrollLeft) === carousel.scrollWidth - carousel.offsetWidth) {
      carousel.classList.add("no-transition");
      carousel.scrollLeft = carousel.offsetWidth;
      carousel.classList.remove("no-transition");
    }
  
    // Clear existing timeout & start autoplay if mouse is not hovering over carousel
    clearTimeout(timeoutId);
    if (!wrapper.matches(":hover")) autoPlay();
  }
  
  const autoPlay = () => {
    if (window.innerWidth < 800 || !isAutoPlay) return; // Return if window is smaller than 800 or isAutoPlay is false
    // Autoplay the carousel after every 2500 ms
    timeoutId = setTimeout(() => carousel.scrollLeft += firstCardWidth, 2500);
  }
  autoPlay();
  
  carousel.addEventListener("mousedown", dragStart);
  carousel.addEventListener("mousemove", dragging);
  document.addEventListener("mouseup", dragStop);
  carousel.addEventListener("scroll", infiniteScroll);
  wrapper.addEventListener("mouseenter", () => clearTimeout(timeoutId));
  wrapper.addEventListener("mouseleave", autoPlay);
#shopify-section-template--16302064730196__product_slider_epcazc {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
}

.product-slider__wrapper-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
}

.wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  max-width: 1100px;
  width: 100%;
  position: relative;
}

.wrapper i {
  font-size: 4rem;
  font-weight: 300;
  color: #fff;
  top: 50%;
  height: 50px;
  width: 50px;
  cursor: pointer;
  position: relative;
  text-align: center;
  line-height: 50px;
  transform: translateY(-50%);
  transition: transform 0.1s linear;
}

.wrapper i:active {
  transform: translateY(-50%) scale(0.85);
}

.wrapper i:first-child {
  padding-right: 20px;
}

.wrapper i:last-child {
  padding-left: 20px;
}

.carousel {
  scroll-behavior: smooth;
}

.wrapper .carousel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% / 3) - 12px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: 16px;
  border-radius: 8px;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding: 0;
  justify-content: center;
}

.carousel::-webkit-scrollbar {
  display: none;
}

.carousel.no-transition {
  scroll-behavior: auto;
}

.carousel.dragging {
  scroll-snap-type: none;
  scroll-behavior: auto;
}

.carousel.dragging .card {
  cursor: grab;
  user-select: none;
}

.carousel :where(.card, .img) {
  display: flex;
  justify-content: center;
  align-items: center;
}

.carousel .card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  scroll-snap-align: start;
  height: 360px;
  list-style: none;
  background: #fff;
  cursor: pointer;
  flex-direction: column;
  border-radius: 8px;
}

.carousel .card .img {
  height: 70%;
  width: 100%;
}

.card .img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-slider__details-container {
  background: #000;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
  height: 30%;
}

.product-slider__title {
  color: #fff;
  font-family: 'Genos', serif;
  font-weight: 500;
  font-size: 1.7rem;
  padding: 1.5rem 1rem;
  text-align: center;
  margin: 0;
}

.product-slider__price {
  color: #fff;
  font-family: 'Genos', serif;
  font-weight: 500;
  font-size: 1.55rem;
  padding-bottom: 1rem;
  margin: 0;
}

.carousel .card span {
  color: #6A6D78;
  font-size: 1.31rem;
}

@media screen and (max-width: 900px) {
  .wrapper .carousel {
      grid-auto-columns: calc((100% / 2) - 9px);
  }
}

@media screen and (max-width: 600px) {
  .wrapper .carousel {
      grid-auto-columns: 100%;
  }

  .carousel .card {
      height: auto;
      max-height: 350px;
  }
}

.best-sellers-container {
  padding: 0 15px;
  background-color: #111111;
  width: 100%;
}

.best-sellers {
  background-image: url(https://cdn.shopify.com/s/files/1/0611/6589/5764/files/pexels-michael-brennan-173741263-14591950.jpg?v=1738795837);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 50% 50%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: relative;
  border-top-left-radius: 25px;
  border-top-right-radius: 25px;
  overflow: hidden;
  padding: 3rem 0;
}

.bg-overlay {
  display: block;
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: rgba(0,0,0,0.3);
  top: 0;
}

.best-sellers-title-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 10;
}

.best-sellers-title-container h2 {
  color: #fff;
  font-family: 'Genos', serif;
  font-size: calc(var(--font-heading-scale) * 7rem);
  text-transform: uppercase;
  text-align: center;
  line-height: 1.2;
  font-weight: 500;
  position: relative;
  bottom: 15px;
  letter-spacing: -2px;
  margin: 0;
}

@media only screen and (max-width: 750px) {
  .best-sellers-container {
    padding: 0 10px;
  }
  
  .best-sellers-title-container h2 {
    font-size: calc(var(--font-heading-scale) * 4.5rem);
    margin-top: 0;
    bottom: 10px;
  }
}

.best-sellers-title-container p {
  color: #fff;
  font-family: 'Montserrat', serif;
  font-size: 1.5rem;
  text-align: center;
  letter-spacing: 0;
  margin-top: 0;
  max-width: 600px;
}

.best-sellers__grid-item {
  border-radius: 3px;
  overflow: hidden;
}
<div class="best-sellers-container">
  <div class="best-sellers"
    id="collection-template--16302064730196__featured_collection_d6PVfW"
    data-id="template--16302064730196__featured_collection_d6PVfW">
    <div class="bg-overlay"></div>
    <div
      class="best-sellers-title-container">
      <h4 class="sub-title-heading">Check out our</h4>
      <h2 class="title inline-richtext h1 scroll-trigger animate--slide-in">
        Best Sellers
      </h2>
      <p>From timeless classics to the latest trends, these hand-picked selections have consistently received high
        praise. Explore our curated collection of top-rated items and find your next favorite today.</p>
    </div>

    <div class="product-slider__wrapper-container">
      <div class="wrapper">
        <i id="left" class="fa-solid fa-angle-left"></i>
        <ul class="carousel">
          {% assign best_products = collections['best-sellers'].products | sort_natural: 'title' %}
          <li class="card">
            <div class="img">
              <img src="{{ best_products[0].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[0].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[0].price | money }}</h2>
            </div>
          </li>
          <li class="card">
            <div class="img">
              <img src="{{ best_products[1].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[1].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[1].price | money }}</h2>
            </div>
          </li>
          <li class="card">
            <div class="img">
              <img src="{{ best_products[2].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[2].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[2].price | money }}</h2>
            </div>
          </li>
          <li class="card">
            <div class="img">
              <img src="{{ best_products[3].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[3].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[3].price | money }}</h2>
            </div>
          </li>
          <li class="card">
            <div class="img">
              <img src="{{ best_products[4].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[4].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[4].price | money }}</h2>
            </div>
          </li>
          <li class="card">
            <div class="img">
              <img src="{{ best_products[5].featured_media | image_url: width: 533 }}" alt="img" draggable="false"
                width="" height="">
            </div>
            <div class="product-slider__details-container">
              <h2 class="product-slider__title">{{ best_products[5].title }}</h2>
              <h2 class="product-slider__price">{{ best_products[5].price | money }}</h2>
            </div>
          </li>
        </ul>
        <i id="right" class="fa-solid fa-angle-right"></i>
      </div>
    </div>
  </div>
</div>

I just need this carousel to start on 1, 2, & 3 and keep scrolling right when clicking the right button without reverting abruptly and same thing when the left button is clicked. Been stuck on this issue for the past couple days and would really appreciate some help. Thank you in advance.

How to update calendar color through sheets?

Here is the code I have to add the sheets events to the calendar, and I have also linked the sheets document, I am looking to add some code that will allow me to change the color of my calendar events that are completed (True in column E) to gray when I run my google script program. If it matters, by default the calendar color is yellow. Thanks!

Google Sheets: https://docs.google.com/spreadsheets/d/1_txF7ooW9Ty9gQ9a9wLMBlfg5phzGcPjJ_UP-ehNQmM/edit?usp=sharing

function oneDate(){
  let sheet = SpreadsheetApp.getActiveSheet()
  let id = SpreadsheetApp.getActive().getRange("D1").getValue()
  // assignments needs to include all the info for the events, not just the title
  let assignments = SpreadsheetApp.getActive().getRangeByName("fullList").getValues().filter(array => array.slice(0, -1).some(value => value !== ''));

  // console.log(id)
  // console.log(assignments)


  assignments.forEach(function(e,index){
    // added e[1] so it only includes events WITHOUT a checkbox and WITH a title
    if(!e[0] && e[1]){
      CalendarApp.getCalendarById(id)
      .createAllDayEvent(
        // gets title from column B (referenced by e[1])
        e[1],
        // gets date from column C (referenced by e[2])
        e[2]);
        // keeps track of which row loop is on
        let newIndex = index+5
        // checks the box in column A after event created
        sheet.getRange("A"+ newIndex).setValue(true);

      
    }
  })
}

I’ve tried integrating .setColor(Color) to my .createAllDayEvent, but could not figure out if that was the correct way to do it, any way I tried adding it I was getting an error that .setColor was not a function of .createAllDayEvent. I also tried adding .setColor as another line as a {description} of .createAllDayEvent, but got the same error

SVG sprite icon not showing when I deployed the web app

SVG sprite icon not showing when I deployed the web app. On the console when you inspect, they are there, but not showing, I noticed the svg icon has its height x width = 0x0. I don’t experience this problem when working on the code editor.

I tested the dist folder, for the build via live-server in VS Code. The svg does not show for build. I also have an image that doesn’t show, same as the svg. Both are located in the same image folder as the svg sprite. It behaves like it is a path problem, like the location is empty but it can’t be, because my logo from the same folder loads. It could also be the bundler I use, Parcel.

icon not showing with height x width = 0x0

a generic image should load when API image is N/A

My app is a single page application built with Javascript-modules, html, sass and parcel. I imported the svg sprite and a jpg image from the img folder. The html for each render is written with Javascript

import icons from "url:../../img/sprite.svg";
import poster from "url:../../img/background/generic-poster.jpg";

The script for my package.json looks like this, maybe there is something wrong with the build process

"scripts": {
    "clean:output": "rimraf dist",
    "start": "parcel index.html",
    "build": "parcel build index.html --dist-dir ./dist"
  },

My home page isn’t written in JavaScript and it still has the same problem of icon not showing.

<header class="header">
            <a class="header__logo--link"><img src="src/img/popcorn-2.png" class="header__logo" alt="logo" />
            </a>
            <form class="search">
                <input type="text" class="search__field" placeholder="Your movie awaits..." />
                <button class="btn btn--search">
                    <div class="svg__icon-box">
                        <svg class="svg__icon svg__icon--search">
                            <use href="src/img/sprite.svg#icon-search"></use>
                        </svg>
                    </div>
                </button>
            </form>

            <button class="btn btn--watchlist">
                <div class="svg__icon-box">
                    <svg class="svg__icon svg__icon--bookmarks">
                        <use href="src/img/sprite.svg#icon-bookmarks1"></use>
                    </svg>
                    <span>Watchlist</span>
                </div>
            </button>
        </header>

the admin credentials could not be passed i don’t know why i tried so many ways the values does not get to the admin routes

as we see from here the authcontext gets called in the admin but it does not recieves any values, and it does not works.

Issue:
I am implementing authentication in my React app using AuthContext. The authentication seems to work, but inside the /admin/* routes, useAuth() does not receive any values. As a result, the authentication does not work correctly in admin routes.

What I Have Tried:

Confirmed that AuthContext.Provider wraps the entire app.

Verified that localStorage stores user and role correctly.

Checked useEffect in AuthContext to ensure it initializes correctly.

Used console.log inside useAuth() within admin components, and it logs undefined.

import { useNavigate } from 'react-router-dom';
import axios from 'axios';

interface AuthContextType {
  user: any | null;
  isAdmin: boolean;
  signIn: (email: string, password: string) => Promise<void>;
  signUp: (email: string, password: string) => Promise<void>;
  signOut: () => Promise<void>;
  resetPassword: (email: string) => Promise<void>;
  updatePassword: (password: string) => Promise<void>;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<any | null>(null);
  const [isAdmin, setIsAdmin] = useState(false);
  const [isInitialized, setIsInitialized] = useState(false);
  const navigate = useNavigate();

  useEffect(() => {
    const storedUser = localStorage.getItem('user');
    const storedRole = localStorage.getItem('role'); 
  
    if (storedUser && storedRole) {
      try {
        const parsedUser = JSON.parse(storedUser);
        setUser(parsedUser);
        setIsAdmin(storedRole === 'admin'); 
      } catch (error) {
        console.error('Error parsing stored user:', error);
      }
    } else {
      setUser(null);
      setIsAdmin(false);
    }
  
    setIsInitialized(true);
  }, []);
  
  
  
  
  

  const signIn = async (email: string, password: string) => {
    try {
      const response = await axios.post('http://localhost:4500/api/auth/login', { email, password });
      const { accessToken, role } = response.data;
  
      localStorage.setItem('accessToken', accessToken);
      localStorage.setItem('role', role);
      localStorage.setItem('user', JSON.stringify({ email, role }));
  
      setUser({ email, role });
      setIsAdmin(role === 'admin'); // Update state properly
  
      if (role === 'admin') {
        navigate('/admin/dashboard'); 
      } else {
        navigate('/');
      }
    } catch (error) {
      console.error('Error signing in:', error);
      throw new Error('Invalid credentials');
    }
  };
  
  
  

  const signUp = async (email: string, password: string) => {
    try {
      const response = await axios.post('http://localhost:4500/api/auth/signup', { email, password });

      const { accessToken, refreshToken, user } = response.data;

      localStorage.setItem('accessToken', accessToken);
      localStorage.setItem('refreshToken', refreshToken);
      localStorage.setItem('user', JSON.stringify(user));

      setUser(user);
      navigate('/');
    } catch (error) {
      console.error('Error signing up:', error);
      throw new Error('Failed to sign up');
    }
  };

  const signOut = async () => {
    localStorage.removeItem('accessToken');
    localStorage.removeItem('refreshToken');
    localStorage.removeItem('user');
    setUser(null);
    setIsAdmin(false);
    navigate('/login');
  };

  const resetPassword = async (email: string) => {
    try {
      const response = await axios.post('http://localhost:4500/reset-password', { email });

      if (response.status !== 200) {
        throw new Error('Failed to send reset email');
      }
    } catch (error) {
      console.error('Error resetting password:', error);
      throw new Error('Failed to send reset email');
    }
  };

  const updatePassword = async (password: string) => {
    try {
      const response = await axios.post('http://localhost:4500/update-password', { password });

      if (response.status !== 200) {
        throw new Error('Failed to update password');
      }
    } catch (error) {
      console.error('Error updating password:', error);
      throw new Error('Failed to update password');
    }
  };

  if (!isInitialized) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-50">
        <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-600"></div>
      </div>
    );
  }

  return (
    <AuthContext.Provider value={{
      user,
      signIn,
      signUp,
      signOut,
      resetPassword,
      updatePassword,
    }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};


import React from 'react';
import {
    BrowserRouter as Router,
    Routes,
    Route,
    Navigate,
} from 'react-router-dom';

import Navbar from './components/Navbar';
import Home from './pages/Home';
import Competition from './pages/Competition';
import Leaderboard from './pages/Leaderboard';
import Login from './pages/Login';
import ResetPassword from './pages/ResetPassword';
import Dashboard from './pages/admin/Dashboard';
import Registrations from './pages/admin/Registrations';
import Exams from './pages/admin/Exams';
import { AuthProvider, useAuth } from './pages/context/AuthContext';
import AdminLayout from './pages/AdminLayout';

const PrivateRoute = ({ children }) => {
    const { user } = useAuth();
    if (!user) {
        return <Navigate to="/login" />;
    }
    if (user && user.role === 'admin') {
        return <Navigate to="/admin/dashboard" />;
    }
    return children;
};

const AdminRoute = ({ children }) => {
    const { user } = useAuth();
    if (!user) {
        return <Navigate to="/" />;
    }
    return children;
};

const AppRoutes = () => {
    return (
        <Routes>
            <Route path="/login" element={<Login />} />
            <Route path="/reset-password" element={<ResetPassword />} />
            <Route
                path="/admin/*"
                element={
                    <AdminRoute>
                        <AdminLayout>
                            <Routes>
                                <Route index element={<Navigate to="dashboard" />} />
                                <Route path="dashboard" element={<Dashboard />} />
                                <Route path="registrations" element={<Registrations />} />
                                <Route path="exams" element={<Exams />} />
                            </Routes>
                        </AdminLayout>
                    </AdminRoute>
                }
            />

            {/* Public/Protected routes */}
            <Route
                path="/"
                element={
                    <>
                        <Navbar />
                        <main className="container mx-auto px-4 py-8">
                            <Routes>
                                <Route index element={<Home />} />
                                <Route
                                    path="competition"
                                    element={
                                        <PrivateRoute>
                                            <Competition />
                                        </PrivateRoute>
                                    }
                                />
                                <Route path="leaderboard" element={<Leaderboard />} />
                            </Routes>
                        </main>
                    </>
                }
            />
        </Routes>
    );
};

function App() {
    return (
        <Router>
            <AuthProvider>
                <AppRoutes />
            </AuthProvider>
        </Router>
    );
}

export default App;

tabulator selectableRange causing table to not load

I am working with tabulator and everything works fine until I try and use selectableRange. currently I allow for rows to be selected but I wanted to change that and select cells instead. naturally I followed tabulator’s documentation which is to use selectableRange:true etc, but that literally causes my table to just disappear. comment that line out and the table loads. has this happened to anyone else? i’ve even disabled selectableRows and nothing is fixing this issue.

Iterating Assets in an Incisor project?

Is it possible to iterate through the assets in the Assets folder within an Incisor project?

I need to access asset files from within my code and would like to iterate over the assets in the Assets folder. Additionally, I want to manipulate these assets at runtime. Is there a way to achieve this?

Flash Flask messages with a fetch request from JavaScript

I’ve developed a cafe app using flask. I watched like 2 or 3 tutorials, and started to create as much as I could. Following this code from a form

<!-- login.html -->
<body>
    <h1>Login</h1>
    <div>
        {% for m in get_flashed_messages() %}
        <div>{{ m }}</div>
        {% endfor %}
    </div>

    <form method="POST">
        <label for="email">Email</label>
        <input type="text" name="email" id="email">
        <label for="password">Password</label>
        <input type="password" name="password" id="password">
        <input type="submit" id="submit" value="Login">
    </form>
</body>

and controller like this:

from flask import *

app = Flask(__name__)
app.secret_key = 'secret'
app.debug = True

@app.route("/", methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form.get('email')
        pwd = request.form.get('password')
        
        if email and pwd:
            flash("Success!")
            return redirect(url_for('home'))
        else:
            flash("Email and password required!")
    return render_template('login.html')

@app.route("/home/")
def home():
    return render_template('home.html')

if __name__ == '__main__':
    app.run()

When the form is not complete, after click submit button, the page “reloads” and displays the flashed message as expected in the same page, and also when is complete, displays the flashed message in home.html. That’s Ok.

<!-- home.html -->
<!DOCTYPE html>
<html>
<body>
    <div>
        {% for m in get_flashed_messages() %}
        <div>{{ m }}</div>
        {% endfor %}
    </div>
    <h1>Logging successful</h1>
</body>
</html>

However, the issue is, when I try to do the “same” but from JavaScript with a fetch and JSON requests like this:

    <script>
        window.onload = function () {
            let email = document.getElementById('email');
            let pwd = document.getElementById('password');
            let submit = document.getElementById('submit');
            submit.addEventListener('click', async function () {
                let data = {'email': email.value,
                    'password': pwd.value
                };

                let request = {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(data)
                };
                let response = await fetch("/", request)
                console.log(response);
            });
        }
    </script>

It doesnt “reload” the page, more over it doesnt show the flashed messages as I would expect. I just want to submit data from JavaScript and, the flash messages to work as expected, show after the request is complete, as it were a form, but without a form. Is it that possible in first place? It’s been a month and I cannot figure out how to do it, I’m giving up on this.

BTW I changed the <form> to <div> in order to send it not as form, and of course, read request.json for JS thing

I’ve read the documentation, but it only shows an example with form html method, that is what I wrote first.

I’ve also tried to see what is the response like let response = await fetch("/", data).then(r => r.text()) and it logs the HTML that **does contain** the flashed message. I mean, it’s just right there, but it doesn’t do anything about it, nor show the flashed messages. Also, I read that you can manually redirect with if(response.redirected) window.location.href = response.url And it redirects, but again no flash message are shown.

I wouldn’t like to rewrite the HTML code like


document.open();
document.write(html);
document.close();

Because is only overlapping the HTML, and when reloads is not the actual page that was redirected in first place.

Change Enter, Up, and Down arrow key actions to use multiple radio groups, using Javascript/JQuery

I have made an offline decision support tool in a single html page.

The page asks a series of Y/N questions, with strictly binary branching, using horizontally arranged radio buttons. Then shows the relevant hidden div, either with more questions – or terminating with advice.

JQuery is used for the slice function, which helps hide previously answered questions, when earlier responses are changed.

The default keyboard shortcuts are almost unknown to my audience. Therefore, I feel no guilt changing the keyboard actions.

Q1. I would like to re-task the Up and Down arrow keys to navigate to the next/previous radio group respectively – with focus (mimic TAB and Shift+TAB)

Q2. I would also like to re-task the enter key to select the current radio button and move on – with focus (mimic Space). I am not submitting a form, so I have no other use for the enter key.

My incomplete keyboard handler is below.

<head>

<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<!-- https://github.com/jquery/jquery/blob/main/LICENSE.txt -->

<script>

window.addEventListener('keydown', function (e) {

    // Process e object
    var key = e.which
    if (e.ctrlKey)  { key = "ctrl"+key;     }
    if (e.altKey)   { key = "alt"+key;      }
    if (e.shiftKey) { key = "shift"+key;    }

    // Ctrl+C
    if (key == "ctrl67") {
        // Preserve default
        return;
    }

    // Ctrl+F
    if (key == "ctrl70") {
        // Preserve default
        return;
    }

    // Radio Button Shortcuts

    // Space
    if (key == "32") {
        // Preserve default
        return;
    }

    // TAB
    if (key == "9") {
        // Preserve default
        return;
    }

    // Shift+TAB
    if (key == "shift9") {
        // Preserve default
        return;
    }

    // LeftArrow
    if (key == "37") {
        // Preserve default
        return;
    }

    // RightArrow
    if (key == "39") {
        // Preserve default
        return;
    }

    // Enter        - if radio button send space
    if (key == "13") {
        if($("input[type=radio]").is(':focus')){
            // Dissable default
            e.preventDefault();
            // Simulate Space
            // TODO:
        } else {
            // Preserve default
            return;
        }
    }

    // DownArrow    - if radio button send TAB
    if (key == "40") {
        if($("input[type=radio]").is(':focus')){
            // Dissable default
            e.preventDefault();
            // Simulate TAB to move to next radio group
            // TODO:

        } else {
            // Preserve default
            return;
        }
    }

    // UpArrow      - if radio button send Shift+TAB
    if (key == "38") {
        if($("input[type=radio]").is(':focus')){
            // Dissable default
            e.preventDefault();
            // Simulate Shift+TAB to move to prev radio group
            // TODO:

        } else {
            // Preserve default
            return;
        }
    }

    // Dissable fall-through and all remaining keyboard shortcuts
    e.preventDefault();
});

</script>
</head>

Any help appreciated.

Kind Regards Gavin Holt

onClick() function and darkmode toggle function

So, I have a dark mode button that works fine when light mode is enabled but if I use the auto detect css media query and page starts in darkmode the button will not do anything because it’s already in dark mode. My question is how can I make the same darkmode button work and switch page to light mode instead of adding a sperate button for light mode?

HTML

<button onclick="dark_mode()"> dark mode </button>

CSS

.dark-mode {
  css code for dark mode here
}

JS

 function dark_mode() {
    var element = document.body;
    element.classList.toggle("dark-mode");
 }

How to avoid the login window when accessing a Facebook profile page onload?

It can be anything; like an URL variable that we can put after or in front of the URL to avoid the login window when accessing a Facebook page…

So: we have a redirect to https://www.facebook.com/szabo.zsolt.guriga, but we’d like, at least, to temporarily disable the login window, so it doesn’t show up immediately.

Currently, we see this in an instant when visiting the page:

screenshot-of-the-problem

Unfortunately, there’s no change in the URL when closing that window…

Why will Photoshop Batch files not compress

I am attempting to resize and compress a batch file is Photoshop. It does everything else, resize, create folders, and save. But it does not appear to be compressing the images. Any idea why this would be? I have tried many variations of this, I did use Google and LLMs. The only difference I get is complete failure. As said, this will almost work, it just will not compress the images.



// variables
var inputFolder = Folder.selectDialog("SELECT A FOLDER OF IMAGES TO RESIZE");
var outputFolder = inputFolder

// check that the folder has files in it
if (inputFolder != null) {
    var fileList = inputFolder.getFiles(/.+.(?:gif|jpe?g|[ew]mf|eps|tiff?|psd|pdf|bmp|png)$/i);
} else {
    alert("Couldn't find any files. Check your directory path and try again.");
    Exit();
}

// set background color
var BGcolor = new SolidColor();  
BGcolor.rgb.red = 255;  
BGcolor.rgb.green = 255;  
BGcolor.rgb.blue = 255;  
    
// set your color as background color  
backgroundColor.rgb.hexValue = BGcolor.rgb.hexValue;  

//  new image sizes
var large = 900;
var normal = 600;
var thumbnail = 300;

//  new image name extentions
var largeNameExt = '_l';
var normalNameExt = '_n';
var thumbnailNameExt = '_t';

// set jpeg save options
var jpegSaveOptions = new JPEGSaveOptions();
jpegSaveOptions.embedColorProfile = true;
jpegSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpegSaveOptions.matte = MatteType.NONE;
jpegSaveOptions.quality = 12;

// error logging
var errors = [];

/* 
Function: createFolder
Description: creates the new folders for export 
imageSize: the new image size used to create the folder path
*/
function createFolders(imageSize) {
    var addFolder = new Folder(outputFolder + '/' + imageSize.toString() + 'px' + '/');
    addFolder.create();
} // createFolders


// Set jpeg save options with quality adjustments
function setJPEGQuality(saveOptions, targetSizeKB) {
    var quality = 12; // Start with maximum quality
    var tempFile = new File("~/Desktop/temp.jpg");
    
    do {
        saveOptions.quality = quality;
        doc.saveAs(tempFile, saveOptions, true, Extension.LOWERCASE);
        var fileSize = tempFile.length / 1024; // Convert bytes to KB

        if (fileSize > targetSizeKB) {
            quality -= 1; // Reduce quality to decrease file size
        } else {
            break; // Exit the loop if target size is met
        }
    } while (quality > 0);

    tempFile.remove(); // Clean up the temp file
}

// CreateImages function
function createImages() {
    // add new folder paths
    createFolders(large);
    createFolders(normal);
    createFolders(thumbnail);

    // trim the images then resize
    for (var i = 0; i < fileList.length; i++) {
        // open the image
        try {
            var doc = app.open(fileList[i]);
            // set the output locations and names
            var fileName = fileList[i].name.replace(/.(?:gif|jpe?g|[ew]mf|eps|tiff?|psd|pdf|bmp|png)$/, '');
            var saveImgLarge = new File(outputFolder + "/" + large.toString() + 'px' + '/' + fileName + largeNameExt + '.jpg');
            var saveImgNormal = new File(outputFolder + "/" + normal.toString() + 'px' + '/' + fileName + normalNameExt + '.jpg');
            var saveImgThumbnail = new File(outputFolder + "/" + thumbnail.toString() + 'px' + '/' + fileName + thumbnailNameExt + '.jpg');

            // trim whitespace
            doc.trim();

            // Resize and save images
            // Large
            if (doc.height > doc.width) {
                doc.resizeImage(null, UnitValue(large, "px"), 72, ResampleMethod.BICUBICAUTOMATIC);
            } else {
                doc.resizeImage(UnitValue(large, "px"), null, 72, ResampleMethod.BICUBICAUTOMATIC);
            }
            doc.resizeCanvas(large, large, AnchorPosition.MIDDLECENTER);
            setJPEGQuality(jpegSaveOptions, 70); // Adjust quality to target size 70 KB
            doc.saveAs(saveImgLarge, jpegSaveOptions, true, Extension.LOWERCASE);

            // Normal
            doc.resizeImage(UnitValue(normal, "px"), UnitValue(normal, "px"), 72, ResampleMethod.BICUBICAUTOMATIC);
            setJPEGQuality(jpegSaveOptions, 50); // Adjust quality to target size 50 KB
            doc.saveAs(saveImgNormal, jpegSaveOptions, true, Extension.LOWERCASE);

            // Thumbnail
            doc.resizeImage(UnitValue(thumbnail, "px"), UnitValue(thumbnail, "px"), 72, ResampleMethod.BICUBICAUTOMATIC);
            setJPEGQuality(jpegSaveOptions, 20); // Adjust quality to target size 20 KB
            doc.saveAs(saveImgThumbnail, jpegSaveOptions, true, Extension.LOWERCASE);

            doc.close(SaveOptions.DONOTSAVECHANGES);
        } catch (err) {
            errors.push(fileList[i].name);
        }
    }
}


createImages();

if (errors.length > 0) {
    alert("Oops! We ran into some errors.nWhile the program did run successfully, you will still need to double-check the files listed below for issues like these:" + "nn1) Files are corrupt (files don't open, or cause an error when you try to open them)n2) Files have unusual characters in their file namesn3) Files are not one of these types of image files:ngif, jpeg, jpg, eps, tiff, tif, psd, pdf, bmp, png" + "nn*** FILE ERRORS ***n" + errors.join("n"));
} else {
    alert("Task Completed!");
}

I tried the above code (any many variations). I am expecting it to resize and compress images.

How to show different tooltips for target and bar in Highcharts bullet graph?

I am implementing a bullet graph using Highcharts and need help with configuring tooltips.

My requirement is,
When hovering over the target line: Show target-related details.
When hovering over the bullet bar: Show revenue related details in my case.
Currently, both the target and the bar show the same tooltip. I want them to display different information depending on where the user hovers.

This is what I followed: https://www.highcharts.com/demo/highcharts/bullet-graph

Here’s the code sandbox link for the implementation that I have done: https://codepen.io/Bhagya-Krishna-the-selector/pen/gbOpLvM

Issue:
The tooltip currently shows the same information for both the bar and the target.
I want separate tooltips:
Bar hover: Show Revenue data(e.g., Revenue: 275)
Target hover: Show target details (e.g., Target: 250)

Any guidance or code samples would be greatly appreciated!

How to make event emitter work with typescript?

Is there any way to have types for callback arguments, instead of any‘s ?

type Listener = {
  callback: (...data: any[]) => void,
  once: boolean;
}

class EventEmitter{

  eventMap: Map<string, Listener[]> = new Map();


  on(event: string, callback: Listener["callback"], once: boolean = false) {
    const listeners = this.eventMap.get(event) ?? [];
    listeners.push({ callback, once });
    this.eventMap.set(event, listeners);
    return this;
  }

  once(event: string, callback: Listener['callback']): this {
    this.on(event, callback, true);
    return this;
  }

  emit(event: string, ...data: any[]) {
    const listeners = this.eventMap.get(event) ?? [];

    for (let i = 0; i < listeners.length; i++) {
      const { callback, once } = listeners[i];

      callback(...data);
      if (once) {
        listeners.splice(i, 1);
        this.eventMap.set(event, listeners);
      }
    }
  }
}

Emit has to accept any, because it’s the entry point. Say I call this:

events.emit("x", 1, true); 
events.emit("y", "test"); 

I want the callbacks hooked on x to see the actual types, like:

events.on("x", (arg1, arg2) => { // <= args should have types number and bool

and

events.on("y", (arg1) => { // <= args should have type string