Datatable ajax reload with new data

So I already have my main table set up upon initial load in a javascript file as such:

let table = new DataTable('#UsersTable', {
    ajax: 'user_data',
    rowId: 'id',
    columns: [
        { data: 'id', className: 'dt-left' },
        { data: 'email' },
        { data: 'first_name' },
        { data: 'last_name' },
        { data: 'group' },
        { data: 'parent-group' },
        { data: 'role' },
        { data: 'create_date', className: 'dt-left' },
        { data: 'active' },
        { data: 'deleted' }
    ],
    layout: {
      topStart: 'buttons'
    },  
    buttons: [
      { extend: 'copy', text: '<i class="bi bi-clipboard-plus"></i> Copy', className: 'btn-primary btn-sm' },
      { extend: 'csv', text: '<i class="bi bi-filetype-csv"></i> CSV', className: 'btn-primary btn-sm' },
      { extend: 'excel', text: '<i class="bi bi-file-earmark-excel"></i> Excel', className: 'btn-primary btn-sm' },
      { extend: 'pdf', text: '<i class="bi bi-file-earmark-pdf"></i> PDF', className: 'btn-primary btn-sm' },
      { extend: 'print', text: '<i class="bi bi-printer"></i> Print', className: 'btn-primary btn-sm' }
    ],
    select: true,
    responsive: true,
    processing: true,  
    initComplete: function () {
      // Remove btn-secondary if still present
      document.querySelectorAll('.btn').forEach(btn => {
        btn.classList.remove('btn-secondary');
      });
    }
  });

but then when I’m in my user admin portal I have a filter function where the user should be able to filter down the data to a smaller data set. I want it to reload the table with the new data but the $(‘#UsersTable’).DataTable().ajax.reload(); of course just reloads the function from above. Here’s what I have that gets the correct filtered data:

 $('#filterform').submit(function() {
      event.preventDefault();
      
      var role_id = $('#role_id_ff').val();
      var is_active = $('#is_active_ff').val();
      var is_deleted = $('#is_deleted_ff').val();
      var license_type = $('#license_type_ff').val();
      var receive_news = $('#receive_news_ff').val();
      var receive_marketing = $('#receive_marketing_ff').val();
      var parent_id = $('#parent_id_ff').val();
      var group_id = $('#group_id_ff').val();

      $.ajax({
        url: "<?php echo base_url('/admin/users/get_list'); ?>", 
        type: "POST", 
        data: { // Data to be sent to the server as a plain object
          role_id: role_id,
          is_active: is_active,
          is_locked: 0,
          is_deleted: is_deleted,
          license_type: license_type,
          receive_news: receive_news,
          receive_marketing : receive_marketing,
          parent_id: parent_id,
          group_id: group_id
        },
        dataType: "json", // Expected data type from the server response (e.g., "json", "html", "text")
        success: function(response) {
          // Callback function executed on successful request
          console.log("Success:", response);
          
          //here I want to reload the table but with the new filtered data
          $('#UsersTable').DataTable().ajax.reload();
        },
        error: function(jqXHR, textStatus, errorThrown) {
          // Callback function executed on request error
          console.error("Error:", textStatus, errorThrown);
        }
      });
});

Kind of stuck here. I thought of just doing a new datatable call with the new data but it says I “can’t reinitialize”

Why does my input bar jump down and then return to its position after clicking the send button?

I’m building a chat interface using HTML, CSS, and JavaScript. Every time I send a message using the “Send” button, the input bar (where the user types messages) momentarily jumps down and then returns to its original position.

This only happens when I run the page using python3 -m http.server and open it on a mobile browser (like Chrome on Android). It seems like a layout reflow issue triggered by DOM updates or the virtual keyboard.

I have:

  • Used event.preventDefault() to stop default form behavior
  • Ensured the input stays focused after sending
  • Added padding to prevent overlap with the keyboard
  • Used position: fixed for the .chat-input-area

But the issue still persists.

to Reproduce

  1. Start a local server using python3 -m http.server
  2. Open the page on a mobile browser
  3. Type a message and click the Send button
  4. The input bar jumps down and comes back to its original position
const chatMessages = document.getElementById('chatMessages');
const chatInput = document.getElementById('chatMessageInput');
const sendBtn = document.getElementById('sendMessageBtn');

sendBtn.addEventListener('click', () => {
  const message = chatInput.value.trim();

  if (!message) return;

  const msgDiv = document.createElement('div');
  msgDiv.className = 'message';
  msgDiv.textContent = message;
  chatMessages.appendChild(msgDiv);
  chatInput.value = '';
  chatInput.focus();
  chatMessages.scrollTop = chatMessages.scrollHeight;
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body,
html {
  height: 100%;
  font-family: sans-serif;
}

.chat-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: #111;
  color: white;
}

.chat-messages {
  flex-grow: 1;
  overflow-y: auto;
  padding: 16px;
}

.message {
  margin: 8px 0;
}


.chat-input-area {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  padding: 12px;
  background: #222;
}

.chat-input-area input {
  flex: 1;
  padding: 10px;
  font-size: 1rem;
}

.chat-input-area button {
  padding: 10px 16px;
  margin-left: 8px;
  background: #8B5CF6;
  color: white;
  border: none;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>

<body>
  <div class="chat-container">
    <div class="chat-messages" id="chatMessages">
      <div class="message">Hello!</div>
    </div>
    <div class="chat-input-area">
      <input type="text" id="chatMessageInput" placeholder="Type a message..." />
      <button id="sendMessageBtn">Send</button>
    </div>
  </div>
</body>

</html>

Alter image after loading using html canvas

I want to draw a border around an image after it is loaded using new Image()

This works, I see the border, but modifying image.src inside the onload function calls onload again in an infinite loop. But how can I alter the image otherwise?

<!DOCTYPE html>
<html>
<body>
    <script>
        let image = new Image();
        image.onload = function () {
            console.log("onload");
            let canvas = document.createElement('canvas');
            let ctx = canvas.getContext('2d');
            ctx.drawImage(image, 0, 0);
            ctx.strokeStyle = 'red';
            ctx.lineWidth = 5;
            ctx.strokeRect(0, 0, image.width, image.height);
            image.src = canvas.toDataURL();
        };
        image.src = "https://placehold.co/600x400";
        document.body.appendChild(image);
    </script>
</body>
</html>

React Table with useRowSelect throws “Maximum update depth exceeded” when adding selection column

I had a functional table component, I tried to apply the checkbox to it using useRowSelect, but I always get the “Maximum update depth exceeded error”. I don’t know what to do.

import React, { useEffect, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { usePagination, useRowSelect, useSortBy, useTable } from "react-table";

import Icon from "@mui/material/Icon";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableContainer from "@mui/material/TableContainer";
import TableRow from "@mui/material/TableRow";

import pxToRem from "assets/theme/functions/pxToRem";
import classNames from "classnames";
import MDBox from "components/MDBox";
import MDPagination from "components/MDPagination";
import MDDataTableBodyCell from "components/MDTable/MDDataTableBodyCell";
import MDDataTableHeadCell from "components/MDTable/MDDataTableHeadCell";
import MDTypography from "components/MDTypography";
import { useMaterialUIController } from "context";
import useAppData from "context/AppContext";
import PropTypes from "prop-types";
import "regenerator-runtime/runtime.js";

export default function Table7({
    tableColumn,
    searchResult,
    searchAction,
    sizePerPage,
    paginationStyle,
    isSorted,
    noEndBorder,
    pageKeyMap,
    isPaginationServer,
    initialPageSize,
    buttonInRow,
    hideHeader,
    hideTotalEntries,
    fullwidth,
    rowClasses
}) {

    const { t } = useTranslation();
    const [controller] = useMaterialUIController();
    const { gridSpace, rowGap, columnGap } = controller;
    const { getSearchHistory } = useAppData();
    const columnsData = useMemo(() => tableColumn, [tableColumn]);
    const searchResultData = isPaginationServer
        ? searchResult
        : {
            currentPage: 1,
            pageSize: sizePerPage,
            total: searchResult.length,
            list: searchResult
        }

    const initialState = useMemo(() => {
        const searchHistory = getSearchHistory(pageKeyMap);
        return {
            pageSize: searchHistory.pageSize ?? initialPageSize,
            pageIndex: searchHistory.page ? searchHistory.page - 1 : 0,

        }
    }, [initialPageSize]);

    const IndeterminateCheckbox = React.forwardRef(
        ({ indeterminate, ...rest }, ref) => {
            const defaultRef = React.useRef()
            const resolvedRef = ref || defaultRef

            React.useEffect(() => {
                resolvedRef.current.indeterminate = indeterminate
            }, [resolvedRef, indeterminate])

            return (
                <>
                    <input type="checkbox" ref={resolvedRef} {...rest} />
                </>
            )
        }
    )

    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        prepareRow,
        rows,
        page,
        pageOptions,
        canPreviousPage,
        canNextPage,
        gotoPage,
        previousPage,
        nextPage,
        pageCount,
        setPageSize,
        state: { pageSize, pageIndex, sortBy, selectedRowIds }
    } = useTable({
        columns: columnsData,
        data: searchResultData.list ?? [],
        manualSortBy: isPaginationServer,
        manualPagination: isPaginationServer,
        pageCount: Math.ceil(searchResultData.total / searchResultData.pageSize),
        initialState: initialState,
    },
        useSortBy,
        usePagination,
        useRowSelect,
        hooks => {
            hooks.visibleColumns.push(columns => [
                // Let's make a column for selection
                {
                    id: 'selection',
                    // The header can use the table's getToggleAllRowsSelectedProps method
                    // to render a checkbox
                    Header: ({ getToggleAllPageRowsSelectedProps }) => (
                        <div>
                            <IndeterminateCheckbox {...getToggleAllPageRowsSelectedProps()} />
                        </div>
                    ),
                    // The cell can use the individual row's getToggleRowSelectedProps method
                    // to the render a checkbox
                    Cell: ({ row }) => (
                        <div>
                            <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
                        </div>
                    ),
                },
                ...columns,
            ])
        }
    )

    const searchHistory = getSearchHistory(pageKeyMap);
    useEffect(() => {
        if (isPaginationServer) {
            if (pageIndex !== searchHistory.page - 1) {
                gotoPage(0);
            }
        }
    }, [searchHistory]);


    useEffect(() => {
        if (isPaginationServer) {
            searchHistory.page = (pageIndex + 1);
            searchHistory.pageSize = pageSize;
            searchHistory.sortField = sortBy.length > 0 ? sortBy[0].id : null;
            searchHistory.sortOrder = sortBy.length > 0 ? sortBy[0].desc ? 'desc' : 'asc' : null;
            searchAction(searchHistory)
        }
    }, [pageIndex, sortBy, pageSize])


    const paginationComponent = useMemo(() => {
        let pagination = [];
        let lado = 2;

        // tamanho padrão
        let startPage = pageIndex - lado;
        let maxPage = pageIndex + lado;

        // controle para enconstar nas pontas
        if (startPage < 0) {
            maxPage += -1 * startPage;
        } else if (maxPage > pageCount - 1) {
            startPage -= maxPage - pageCount + 1;
        }

        // limpeza de paginas extras
        if (startPage < 0) {
            startPage = 0;
        }
        if (maxPage > pageCount - 1) {
            maxPage = pageCount - 1;
        }

        pagination.push(<MDPagination disabled={pageIndex == startPage} key={"first"} item onClick={() => gotoPage(0)}>
            <Icon sx={{ fontWeight: "bold" }}>first_page</Icon>
        </MDPagination>);
        pagination.push(<MDPagination disabled={pageIndex == startPage} key={"prev"} item onClick={() => previousPage()}>
            <Icon sx={{ fontWeight: "bold" }}>chevron_left</Icon>
        </MDPagination>);

        for (let currentPage = startPage; currentPage <= maxPage; currentPage++) {
            pagination.push(<MDPagination
                color={"primary"}
                item
                key={currentPage}
                onClick={() => gotoPage(currentPage)}
                active={currentPage == pageIndex}
            >
                {currentPage + 1}
            </MDPagination>);
        }

        pagination.push(<MDPagination disabled={pageIndex == pageCount - 1} key={"next"} item onClick={() => nextPage()}>
            <Icon sx={{ fontWeight: "bold" }}>chevron_right</Icon>
        </MDPagination>);
        pagination.push(<MDPagination disabled={pageIndex == pageCount - 1} key={"last"} item onClick={() => gotoPage(pageCount - 1)}>
            <Icon sx={{ fontWeight: "bold" }}>last_page</Icon>
        </MDPagination>);

        return pagination;
    }, [pageIndex, pageCount]);

    // A function that sets the sorted value for the table
    const setSortedValue = (column) => {
        let sortedValue;
        if (column.Header == null || (typeof column.Header != 'string')) {
            sortedValue = false;
        } else if (isSorted && column.isSorted) {
            sortedValue = column.isSortedDesc ? "desc" : "asce";
        } else {
            sortedValue = "none";
        }
        return sortedValue;
    };

    // Setting the entries starting point
    let entriesStart = searchResultData.total < 1 ? 0 : pageIndex * pageSize + 1;
    let entriesEnd = ((pageIndex === pageOptions.length - 1) || (searchResultData?.total < pageSize)) ? searchResultData?.total : pageSize * (pageIndex + 1);

    return (<>
        {/* <MDBox mt={2}> */}
        <TableContainer component={MDBox} mt={rowGap}
            sx={[{
                boxShadow: "none",
                borderRadius: 0,
                position: "relative",
            },
            fullwidth && {
                width: `calc(100% + ${pxToRem(48)})`,
                left: `${pxToRem(-24)}`,
            }
            ]}
        >
            <Table {...getTableProps()}>
                {!!!hideHeader && <MDBox component="thead">
                    {headerGroups.map((headerGroup, key) => (
                        <TableRow key={key} {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map((column, key) => (
                                <MDDataTableHeadCell
                                    key={key}
                                    {...column.getHeaderProps(isSorted && column.getSortByToggleProps({ title: undefined }))}
                                    width={column.width ? column.width : "auto"}
                                    align={column.align ? column.align : "left"}
                                    sorted={setSortedValue(column)}
                                >

                                    {column.Header != null && column.render("Header")}
                                </MDDataTableHeadCell>
                            ))}
                        </TableRow>
                    ))}
                </MDBox>}
                <TableBody {...getTableBodyProps()}>
                    {page.length === 0 ?
                        <MDDataTableBodyCell>
                            Nenhum Registro Encontrado
                        </MDDataTableBodyCell>
                        :
                        page.map((item, index) => {
                            prepareRow(item)
                            return (
                                <TableRow key={index} {...item.getRowProps({
                                    className: classNames(
                                        // { "striped": index % 2 === 0 },
                                        { "hasRowSelection": buttonInRow },
                                        rowClasses ? rowClasses(item.original, index) : null,
                                    ),
                                    style: { "borderBottom": "2px dashed #F0FBFC" }
                                })
                                }>
                                    {item.cells.map((cell) => (
                                        <MDDataTableBodyCell
                                            funcButtonInRow={buttonInRow ? () => buttonInRow(cell.row.original) : buttonInRow}
                                            key={index}
                                            noBorder={noEndBorder && rows.length - 1 === index}
                                            align={cell.column.align ? cell.column.align : "left"}
                                            {...cell.getCellProps()}
                                        >
                                            {cell.render("Cell")}
                                        </MDDataTableBodyCell>
                                    )
                                    )}
                                </TableRow>
                            );
                        })
                    }
                </TableBody>
            </Table>
        </TableContainer>
        {(!hideTotalEntries || pageCount > 1) && <MDBox
            display="flex"
            flexDirection={{ xs: "column", sm: "row" }}
            justifyContent="space-between"
            alignItems={{ xs: "flex-start", sm: "center" }}
            mt={rowGap}
        >
            {!hideTotalEntries && (
                <MDBox mb={{ xs: 3, sm: 0 }}>
                    <MDTypography
                        variant="button"
                        color="secondary"
                        fontWeight="regular"
                    >
                        {t('general.table.pagination', [entriesStart, entriesEnd, searchResultData.total])}
                    </MDTypography>
                </MDBox>
            )}

            {pageCount > 1 && (
                <MDPagination
                    variant={paginationStyle.variant ? paginationStyle.variant : 'gradient'}
                    color={paginationStyle.color ? paginationStyle.color : 'dark'}
                >
                    {paginationComponent}
                </MDPagination>
            )}
        </MDBox>}
        {/* </MDBox> */}
    </>);
}

Table7.defaultProps = {
    initialPageSize: 10,
    sizePerPage: { defaultValue: 10, sizes: [1, 5, 10, 15, 20, 25] },
    paginationStyle: { variant: "gradient", color: "dark" },
    isSorted: true,
    noEndBorder: false,
    searchResult: PropTypes.any.isRequired,
    columns: PropTypes.array.isRequired,
    isPaginationServer: false,
    pageKeyMap: null,
    buttonInRow: null,
    hideHeader: false,
    hideTotalEntries: false,
    fullwidth: true,
    rowClasses: null
};

Table7.propTypes = {
    initialPageSize: PropTypes.number,
    sizePerPage: PropTypes.oneOfType([
        PropTypes.shape({
            defaultValue: PropTypes.number,
            sizes: PropTypes.arrayOf(PropTypes.number),
        }),
    ]),
    paginationStyle: PropTypes.shape({
        variant: PropTypes.oneOf(["contained", "gradient"]),
        color: PropTypes.oneOf([
            "primary",
            "secondary",
            "info",
            "success",
            "warning",
            "error",
            "dark",
            "light",
        ]),
    }),
    isSorted: PropTypes.bool,
    noEndBorder: PropTypes.bool,
    isPaginationServer: PropTypes.bool,
    pageKeyMap: PropTypes.string,
    buttonInRow: PropTypes.func,
    hideHeader: PropTypes.bool,
    hideTotalEntries: PropTypes.bool,
    fullwidth: PropTypes.bool,
    rowClasses: PropTypes.string,
};

All you need to trigger the error is to uncomment the commented part. I took the checkbox implementation directly from the documentation

https://react-table-v7-docs.netlify.app/docs/examples/row-selection-and-pagination

what you tried -> useRowSelect to obtain a selection with checkbox

what you expected to happen -> to be able to select my records with the checkbox in the table

what actually resulted.-> Unhandled Runtime Error
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

How to interact with renderer from new button?

If I add new controls to the player (chordsOff, transpose, metronome) what to put in the “onclick” to access the abcjs-audio or the renderer?

Even something like simple play / stop didn’t work.
I have tried the same function as on the other buttons on the default player:

<button onclick="(function(t) { u(e.options.playPromiseHandler || e.options.playHandler, t, s, e.options.afterResume, !!e.options.playPromiseHandler) })();">Test U</button>

Error: u is not defined

Or:

<button onclick="abcjs.midi.startPlaying(document.getElementById('abcjs-midi-687e010d06e5e'));">Test play</button>

Error abcjs is not defined

Blocking SCORM Course Progress on LMS Communication Loss (SAP successfactor)

we’re working on a SCORM course developed in Articulate Storyline, and we’re trying to implement a specific client requirement — but we’re stuck.

**The requirement:
If the communication between the course and the LMS is interrupted, the course should:

  • block any further progress, and
  • display the following message:**

“Warning! Communication with the platform has been interrupted.
Please close the course and reopen it after checking your network connection.”

Any help would be truly appreciated!

Thanks so much in advance,
ALeksey

**What we’ve tried:
**Normally, we manage this kind of behavior directly through LMS settings, but in this case, the client insists that the logic must be handled within the SCORM itself.

We’ve tried everything we could think of to detect communication loss and trigger this behavior from within Storyline — but nothing has worked so far. At this point, we honestly don’t know what else to try.

Has anyone faced a similar situation?
Is there any workaround or JS-based solution that could help us detect LMS connection issues and respond accordingly from within the SCORM?

react-helmet-async page titles only update after reload, not on navigation

I have a React 19 app bootstrapped with Vite and using React Router v6. I want to set the browser tab title per page using react-helmet-async.
The updates only after I reload the page, but not when I navigate via router links.

A. main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { HelmetProvider } from 'react-helmet-async';
import './index.css';
import { UserProvider } from './context/UserContext';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <HelmetProvider>
      <UserProvider>
        <App />
      </UserProvider>
    </HelmetProvider>
  </React.StrictMode>
)

B. App Routing (App.jsx)

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Login from './pages/Login';
import Index from './pages/Index';
import PasswordReset from './pages/PasswordReset';
import PrivateRoute from './components/PrivateRoute';
// ... all your imports

export default function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/password-reset" element={<PasswordReset />} />
        {/* ...all your other routes, exactly as you pasted above... */}
        <Route path="/unauthorized" element={<div>❌ You are not authorized to view this page.</div>} />
      </Routes>
    </Router>
  );
}

C: Page example

import { useEffect, useState } from 'react';
import Layout from '../../components/Layout';
import LoadingIndicator from '../../components/shared/LoadingIndicator';
import ErrorMessage from '../../components/shared/ErrorMessage';
import axios from 'axios';
import { Helmet } from 'react-helmet-async'; // ← add this

export default function MapSearchLog() {
  const [logContent, setLogContent] = useState('');
  const [logDate, setLogDate] = useState('');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    axios
      .get('/api/dashboards/mapsearchlog', {
        withCredentials: true, // Use cookies/session for auth
      })
      .then((res) => {
        setLogDate(res.data.date || '');
        const rawContent = res.data.content || '';
        const plainText = rawContent
          .replace(/<brs*/?>/gi, 'n')
          .replace(/r/g, '');
        setLogContent(plainText);
        setError(null);
      })
      .catch((err) => {
        console.error(err);
        setError('Failed to load log file');
      })
      .finally(() => setLoading(false));
  }, []);

  return (
    <Layout>
      <Helmet>
        <title>Map Search Log</title>
      </Helmet>
      <div className="p-6 max-w-5xl mx-auto">
        <h1 className="text-2xl font-bold text-[#008C9E] mb-4">
          Map Search Log File
        </h1>
        <p className="mb-4 text-sm text-gray-500">
          Date:{' '}
          {logDate || new Date().toISOString().split('T')[0].replace(/-/g, '')}
        </p>

        {loading && <LoadingIndicator />}
        {error && <ErrorMessage message={error} />}

        {!loading && !error && (
          <>
            <button
              className="mb-3 px-4 py-2 bg-cyan-600 text-white rounded hover:bg-cyan-700 text-sm"
              onClick={() => {
                const blob = new Blob([logContent], { type: 'text/plain' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `mapsearch_log_${logDate || ''}.txt`;
                a.click();
                URL.revokeObjectURL(url);
              }}
            >
              Download Log
            </button>
            <pre className="p-4 bg-white rounded-lg border shadow text-sm whitespace-pre-wrap">
              {logContent}
            </pre>
          </>
        )}
      </div>
    </Layout>
  );
}

Above is some example of the code I used

react-helmet-async page titles only update after reload, not on navigation (Vite + React 19 + React Router 6)

I have a React 19 app bootstrapped with Vite and using React Router v6. I want to set the browser tab title per page using react-helmet-async.
The updates only after I reload the page, but not when I navigate via router links.

A. main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { HelmetProvider } from 'react-helmet-async';
import './index.css';
import { UserProvider } from './context/UserContext';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <HelmetProvider>
      <UserProvider>
        <App />
      </UserProvider>
    </HelmetProvider>
  </React.StrictMode>
)

B. App Routing (App.jsx)

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Login from './pages/Login';
import Index from './pages/Index';
import PasswordReset from './pages/PasswordReset';
import PrivateRoute from './components/PrivateRoute';
// ... all your imports

export default function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="/password-reset" element={<PasswordReset />} />
        {/* ...all your other routes, exactly as you pasted above... */}
        <Route path="/unauthorized" element={<div>❌ You are not authorized to view this page.</div>} />
      </Routes>
    </Router>
  );
}

C: Page example

import { useEffect, useState } from 'react';
import Layout from '../../components/Layout';
import LoadingIndicator from '../../components/shared/LoadingIndicator';
import ErrorMessage from '../../components/shared/ErrorMessage';
import axios from 'axios';
import { Helmet } from 'react-helmet-async'; // ← add this

export default function MapSearchLog() {
  const [logContent, setLogContent] = useState('');
  const [logDate, setLogDate] = useState('');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    axios
      .get('/api/dashboards/mapsearchlog', {
        withCredentials: true, // Use cookies/session for auth
      })
      .then((res) => {
        setLogDate(res.data.date || '');
        const rawContent = res.data.content || '';
        const plainText = rawContent
          .replace(/<brs*/?>/gi, 'n')
          .replace(/r/g, '');
        setLogContent(plainText);
        setError(null);
      })
      .catch((err) => {
        console.error(err);
        setError('Failed to load log file');
      })
      .finally(() => setLoading(false));
  }, []);

  return (
    <Layout>
      <Helmet>
        <title>Map Search Log</title>
      </Helmet>
      <div className="p-6 max-w-5xl mx-auto">
        <h1 className="text-2xl font-bold text-[#008C9E] mb-4">
          Map Search Log File
        </h1>
        <p className="mb-4 text-sm text-gray-500">
          Date:{' '}
          {logDate || new Date().toISOString().split('T')[0].replace(/-/g, '')}
        </p>

        {loading && <LoadingIndicator />}
        {error && <ErrorMessage message={error} />}

        {!loading && !error && (
          <>
            <button
              className="mb-3 px-4 py-2 bg-cyan-600 text-white rounded hover:bg-cyan-700 text-sm"
              onClick={() => {
                const blob = new Blob([logContent], { type: 'text/plain' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `mapsearch_log_${logDate || ''}.txt`;
                a.click();
                URL.revokeObjectURL(url);
              }}
            >
              Download Log
            </button>
            <pre className="p-4 bg-white rounded-lg border shadow text-sm whitespace-pre-wrap">
              {logContent}
            </pre>
          </>
        )}
      </div>
    </Layout>
  );
}

Above is some example of the code I used

Why does JavaScript map() return undefined without return in arrow function? [duplicate]

I’m trying to use JavaScript’s map function to extract names from an array of objects. I expected it to return an array of names like [“Alice”, “Bob”, “Charlie”], but it returned [undefined, undefined, undefined] when I forgot to include the return statement in my arrow function. I want to understand why this happens and when return is required.

Here’s the working code:

const users = [
  { name: "Alice", age: 25 },
  { name: "Bob", age: 30 },
  { name: "Charlie", age: 22 }
];

const names = users.map((user) => {
  return user.name;
});

console.log(names); // ["Alice", "Bob", "Charlie"]

And here’s what I accidentally did:

const names = users.map((user) => {
  user.name;
});

console.log(names); // [undefined, undefined, undefined]

Why does the second version return undefined? I thought arrow functions returned values automatically. How does using curly braces in arrow functions affect return behavior?

[undefined, undefined, undefined]

Why does Angular 18 (ESBuild) generate so many initial chunks after migrating from Angular 14?

I recently migrated my project from Angular 14 to Angular 18, and I’m noticing a huge increase in the number of initial chunks generated during the production build using ESBuild.

In Angular 14 (with Webpack), the build typically produced 3–5 initial JS bundles. But now, Angular 18 generates dozens of small initial chunks, even though I haven’t significantly changed the app structure or added lazy-loaded modules.

This raises concerns about:

  • Browser performance, since too many HTTP requests can delay loading.
  • The lack of control over how these chunks are split.
  • No apparent way to reduce or merge these chunks using configuration.

Questions:

  • Is this expected behavior in Angular 18 with ESBuild?
  • Is there any way to reduce or control the number of initial chunks?
  • Can I customize the chunking strategy like we used to with Webpack?

Additional Info:

Angular version: 18.x

Builder: ESBuild (default in Angular 18)

Total JS size is similar, but split across many files

enter image description here

display table data between the selected date range

I have a table where daily sales of products is recorded. The products which are not sold for a particular date is not recorded in the table. But in the blade page, I have to list out all the dates within a particular range of date selected by the user. For certain dates, where sales is zero, it should display as zero.

==========================================
product || total_sales  || date
A       || 500          || 2025-07-01
B       || 800          || 2025-07-01
A       || 200          || 2025-07-02
B       || 250          || 2025-07-02
A       || 500          || 2025-07-04
B       || 780          || 2025-07-04
A       || 180          || 2025-07-05
A       || 615          || 2025-07-06
B       || 756          || 2025-07-06
==========================================

Now if the user selects the date range between 07-01 to 07-05, then the output should be shown as::

==========================================
product || total_sales  || date
A       || 500          || 2025-07-01
B       || 800          || 2025-07-01
A       || 200          || 2025-07-02
B       || 250          || 2025-07-02
A       || 0            || 2025-07-03
B       || 0            || 2025-07-03
A       || 500          || 2025-07-04
B       || 780          || 2025-07-04
A       || 180          || 2025-07-05
B       || 0            || 2025-07-05
==========================================

How can I do it?

Controller class::

public function index()
    {
        try {
        
            $from = date('2025/07/01');
            $to = date('2025/07/05');
            $sales = Sales::whereBetween('sales_date_eng',[$from, $to])->get();
            return view('admin.sales', compact('sales'));
        } catch (Exception $exception) {
            return response()->json(['status'=>'error', 'error'=> $exception->getMessage()]);
        }
    }

How to display such data using laravel?

htaccess rewrite ‘some_category_and_tags_vars.ics’ to call ‘makethisics.php?vars=some_category_and_tags_vars’ [closed]

Exactly as stated above. I need to grab ANY request for an .ics file and redirect it to a standard .php file with the .ics filename as PHP variable.

The PHP file will then spit out an ics file with the correct headers using the category and tag variables to filter it appropriately.

I have coded everything and it all works – just need this rewrite so I can comply with Google Calendar subscription URL requirements.

Inserting into a table with a foreign key

I am trying to insert audio media for users into tables with foreign keys. I have a user table that registers users , an album table that is supposed to store album information for each users album and albumsongs table that is supposed to store songs for an album in the album table.

This is my SQL

users table
userid| username | password | profilepicture
PK/AI userid

albums table
albumid | userid | albumpicture | albumname | albumgenre
PK/AI albumid     
FK userid to users

albumsongs table
songid | userid | albumid | songname | songpath
PK/AI songid   
FK userid to users  
FK albumid to albums

This is my PHP code to insert album info into album table:

   <?php
         if(isset($_POST["submit1"])) {

        $albumname = $_POST['albumname'];
        $albumgenre = $_POST['albumgenre'];
        $id = mysqli_insert_id($conn);
       
        $imagename = $_FILES['image']['name'];
        $tempName = $_FILES['image']['tmp_name'];
        $filepath = "albumpictures/".$imagename;
        
        if(move_uploaded_file($tempName, $filepath)) {
        }

        $qry = "SELECT userid FROM user WHERE userid = '$id'";
        
        $result = mysqli_query($conn, $qry);
        $num_rows = mysqli_num_rows($result);

        if($num_rows > 0) {
            $sql = "INSERT INTO albums (userid, albumname, albumpicture, albumgenre) VALUES ('$id', '$albumname', '$imagename', '$albumgenre')";
              $result = mysqli_query($conn, $sql);
    }
}
?>

This is my php code to insert into albumsongs table:

  <?php
        if(isset($_POST["submit2"])) {

            $songaname1 = filter_input(INPUT_POST, 'songaname1', FILTER_SANITIZE_SPECIAL_CHARS);
            $id = mysqli_insert_id($conn); // Get the last inserted album ID

            $audioname1 = $_FILES['audio1']['name'];
            $audio_tmp1 = $_FILES['audio1']['tmp_name'];
            $audio_folder1 = "albums/".$audioname;
            if(move_uploaded_file($audio_tmp1, $audio_folder1)) {
               $sql1 = "INSERT INTO albumsongs (userid, songaname1, audio1) VALUES ('$id', '$songaname1', '$audioname1')";
               $result1 = mysqli_query($conn, $sql1);
            }
        }
        ?>

I have tried using mysqli_insert_id.

I would like album info to be inserted into album table and songs for the album to be inserted into albumsongs.

How to enqueue custom CSS and JS files in a WordPress child theme?

I’m building a custom WordPress theme for a client and using a child theme.

I want to enqueue my custom CSS (style.css) and a JavaScript file (custom.js) located in the child theme’s folder.

Here’s what I’ve tried in functions.php:

function my_custom_scripts() {
    wp_enqueue_style('my-style', get_stylesheet_directory_uri() . '/style.css');
    wp_enqueue_script('my-script', get_stylesheet_directory_uri() . '/custom.js');
}
add_action('wp_enqueue_scripts', 'my_custom_scripts');

Unable to install Composer [closed]

I’m trying to set up Composer on my Windows computer, but the installation keeps failing with the following message:

The PHP exe file you specified did not run correctly:
C:Program Filesphp8.3.9php.exe

The php.ini used by your command-line PHP is: C:Program Filesphp8.3.9php.ini

A setting in your php.ini could be causing the problem: Either the ‘extension_dir’ value is incorrect or a dll does not exist.

Program Output:

PHP Warning: Module “ldap” is already loaded

PHP Warning: Module “mysqli” is already loaded

PHP Warning: PHP Startup: Unable to load dynamic library ‘openssl.dll’ (tried: C:Program Filesphp8.3.9extopenssl.dll (The specified module could not be found), C:Program Filesphp8.3.9extphp_openssl.dll.dll (The specified module could not be found))

PHP Warning: PHP Startup: Unable to load dynamic library ‘php_wincache.dll’ (tried: C:Program Filesphp8.3.9extphp_wincache.dll (The specified module could not be found), C:Program Filesphp8.3.9extphp_php_wincache.dll.dll (The specified module could not be found))

I’ve seen similar issues that recommended uncommenting the line “extension=openssl.dll” in my php.ini file, but I’ve done that and I’m still getting the same error message. Does anyone know what I can do to resolve the issue and complete the installation?