Issues with Server-Sent Events and Delays Using Flask and JavaScript

I’m working on a web application using Flask for the backend and JavaScript for the frontend, employing Server-Sent Events (SSE) to manage real-time data updates. However, I am experiencing unexpected delays and repetitive message display issues. Every 10 seconds it shows 10 messages all at once not one per second.

Below is my JavaScript client-side code and a hypothetical Flask server-side setup.

Client-side JavaScript:

<script>
    var userId = {{ user_id|tojson }};
    const eventSource = new EventSource("/stream");
    eventSource.onmessage = function(event) {
        const message = JSON.parse(event.data);
        const messageContent = `<div class="${message.me === userId ? 'message me' : 'message'}">
                                    <div class="bubble">${message.text}</div>
                                    <div class="time">${message.time}</div>
                                </div>`;
        document.querySelector(".message-content").innerHTML += messageContent;
    };

    function sendMessage(event) {
        event.preventDefault();
        const input = document.querySelector(".message-form input[type='text']");
        const message = input.value.trim();
        if (message !== "") {
            fetch("/send_message", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({ message: message })
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error("Failed to send message");
                }
                input.value = ""; // Clear input field after sending message
            })
            .catch(error => console.error(error));
        }
    }
</script>

Server-side Flask (Hypothetical):

with open('msg','r') as file:
    messages = eval(file.read() + ']')
@app.route('/stream')
def stream():
    def y():
        while True:
            yield 'data: ' + dumps(messages[-1]) + 'nn'
            sleep(1)
    return Response(y(), mimetype='text/event-stream')
@app.route('/send_message', methods=['POST'])
def send_message():
    message = {'text':request.json.get('message'),'time':datetime.datetime.now().strftime("%H:%M:%S"),'me':current_user.id}
    messages.append(message)
    with open('msg','a') as file:
        file.write(str(message) + ',')
    socketio.emit('new_message', message, broadcast=True)
    return jsonify({'status': 'success'})

msg file:

[{'text': 'Welcome', 'time': '04:32:13', 'me': 'sadra'}

Can’t Get styled-components to Pass any props

So I just began using styled-components and I’m sorry if there is some very basic error I’m making. But I’ve looked over the docs a dozen times now and can’t find any way to get it to work with absolutely anything passed using the ${(props) => props.variable} method shown in the official instructions.

Here’s the React Component I’m using the prop in:

import { styled } from 'styled-components';
import Box from './Box';

const BOARD = styled.div`
  display: grid;
  grid-template-columns: ${(props) => 'repeat(3, 320px)'};
  grid-template-rows: ${(props) => 'repeat(3, 320px)'};
  gap: ${(props) => props.boxSpacing};
  background-color: black;
  padding: ${(props) => '20px'};
`;

export default function Board(props) {

  console.log(props)
  return (
    <BOARD>
      <Box /><Box /><Box /><Box /><Box /><Box /><Box /><Box /><Box />
    </BOARD>
  );
}

And here’s my App component where I pass the prop that isn’t getting through:

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import Board from './components/board/Board.jsx';
import './App.css';


function App() {
  const [count, setCount] = useState(0)
  
  return (
    <>
      <Board boxSpacing={'20px'} />
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.jsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App

I’ve tried:

  1. Using the $ before variables that shows up a lot in the docs. As far as I know this is just to prevent custom props from conflicting with normal HTML attributes that already exist on elements. But, I wasn’t sure if perhaps styled-components uses this in some other way. It didn’t change anything.

  2. I tried destructuring props just for the hell of it.

  3. I tried every method of passing the value to the component that I could think of in the App file. boxSpacing={} with a variable or just with the value in ”.

  4. I tried removing all variables and still using the function:
    (props) => 'the actual CSS here';
    …to see if everything was installed properly or if I’d missed something in the basic syntax. This
    worked. So it seems that the functions are being evaluated and passing something to normal CSS. It
    only becomes a problem when a variable is involved.

PS Everything I’m finding is REALLY old looking. Class based components and the ‘render()’ function. Even the official docs don’t seem to offer anything more current. I heard that styled components was popular currently. Is this no longer the case? Should I be using something else to allow for component scoping and using variables within my CSS?

My jest file isn’t using the correct return

I’m pretty sure that it will be something easy to fix, but I’ve been stucked with this for a while. I’m building a background (back-end) test file using Jest. Here’s my background.test.js
`

const fileConnection = require('../background');
const firebaseConnection = require('../background');
const stripeConnection = require('../background');

test('File Test', () => {
  expect(fileConnection).toBe(true);
});

describe('Background Test', () => {
  test('Firebase connection', async () => {
    expect(firebaseConnection).not.toBe(null);
  });
  test('Stripe and Back-End connection', async () => {
    expect(stripeConnection).not.toBe(null);
  });
});

`

And my background.js file:

import { db } from 'firebase/firestore';

let test = false;

/**
 *
 */
function fileConnection() {
  test = true;
  return test;
}

/**
 *
 */
function firebaseConnection() {
  try {
    return db;
  } catch (error) {
    return null;
  }
}

/**
 *
 */
function stripeConnection() {
  // the backend stripe connection is on CENSORED
  // So I need to check if the connection is working
  try {
    fetch('CENSORED');
    return 'Stripe connection is working';
  } catch (error) {
    return null;
  }
}

module.exports = (fileConnection, firebaseConnection, stripeConnection);

Now, the error I’m getting is this one:

 ✕ File Test (4 ms)
  Background Test
    ✓ Firebase connection (1 ms)
    ✓ Stripe and Back-End connection (1 ms)

  ● File Test

    expect(received).toBe(expected) // Object.is equality

    Expected: true
    Received: [Function stripeConnection]

       7 |
       8 | test('File Test', () => {
    >  9 |   expect(fileConnection).toBe(true);
         |                          ^
      10 | });
      11 |
      12 | describe('Background Test', () => {

      at Object.toBe (src/test/background.test.js:9:26)

As you can see, I’m getting the response of the stripe connection on the file test function. I believe that it can have something to do with the way I’m exporting my .js file. Thanks for helping me!

I’ve tried changing the way I use the exports, and I’m not sure why the connection with firebase isn’t dropping that error. Only the stripe connection does. I’ve tried copying the code style but it won’t work.

How to normilize values in D3 circle packing

I am using d3 and need to create a chicle packer where the value associated with each node only affects the ratio between other child nodes and does not scale up the parent. Here is my current implementation that packs the circles.

    type WritableNode = {
    id: number
    name: string;
    value?: number | null;
    children?: WritableNode[];
    fillColor: string;
    
};
const root = d3.hierarchy<WritableNode>(data)
    .sum(d => d.value ?? 0) // Only use the node's own value
    .sort((a, b) => (b.value ?? 0) - (a.value ?? 0)); // Keep sorting if needed
    
console.log("Root with value sum and sort:", root);
const pack = d3.pack<WritableNode>()
    .size([width, height])
    .padding(d => {
        // Keep your dynamic padding logic
        if (d.depth > 1 && d.children) {
            return 6; // Adjust padding for non-root nodes with children
        } else if (d.depth === 1) {
            return 6; // Consistent padding for root's direct children
        } else if (d.depth === 0) {
            return 8; // Slightly larger padding for the root node
        } else {
            return 3; // Minimal padding for leaf nodes
        }
    });

nodes = pack(root);

this produces this: enter image description here
all of the nodes have a value of 1. so i would like them to have a 1 to 1 ratio, but one is being scaled up due to its child nodes.

I have tried normalizing the values manually but to no avail, also some basic resizing algorithms but have come up empty.

Error creating token for Token2022Form: TypeError: Cannot read properties of undefined (reading ‘call’)

At the execution stage of function createInitializeInstruction I receive an error:

    Error creating token for Token2022Form: TypeError: Cannot read properties of undefined (reading 'call')
    at Hash.CipherBase (index.js:7:1)
    at new Hash (browser.js:9:1)
    at createHash (browser.js:29:1)
    at splDiscriminate (splDiscriminate.ts:4:1)
    at createInitializeInstruction (instruction.ts:51:1)
    at createInitializeInstructionReact (createInitializeInstructionReact.js:21:1)
    at Object.create (main.b9dcefd2038733fdf419.hot-update.js:218:495)
    at async handleCreateToken2022 (index.jsx:140:1)

name, symbol, umi have string values, mint, metadata, minyAuthority, updateAuthority have valid values.

Here’s my code:

import { useState } from 'react';
import {
    ComputeBudgetProgram,
    Connection,
    Keypair,
    PublicKey,
    sendAndConfirmRawTransaction,
    SystemProgram,
    Transaction,
    BlockheightBasedTransactionConfirmationStrategy
} from '@solana/web3.js';
import {    
    createInitializeInterestBearingMintInstruction,
    createInitializeMetadataPointerInstruction,
    createInitializeMintCloseAuthorityInstruction,
    createInitializeMintInstruction,
    createInitializeNonTransferableMintInstruction,
    createInitializePermanentDelegateInstruction,
    createInitializeTransferFeeConfigInstruction,
    createInitializeTransferHookInstruction,
    createMintToInstruction,
    createAssociatedTokenAccountInstruction,
    getAssociatedTokenAddressSync,
    ExtensionType,
    getMintLen,
    LENGTH_SIZE,
    TOKEN_2022_PROGRAM_ID,
    TYPE_SIZE} from '@solana/spl-token';
import { TokenMetadata, createInitializeInstruction, pack } from '@solana/spl-token-metadata';
import { useWallet } from "@solana/wallet-adapter-react";
import BigNumber from "bignumber.js";
import API_KEY from "../../action/API_KEY/api_key";
import bs58 from "bs58";

export const useToken22Minter = () => {    
    const network = 'devnet'
    const [connection] = useState(new Connection(`https://${network}.helius-rpc.com/?api-key=${API_KEY}`, 'confirmed'));
    const { publicKey } = useWallet();
    const wallet = useWallet();

    const toPublicKey = (k) => {
        if (!k) {
            return null;
        }        return new PublicKey(k);
    };

    const buildExtensionsInstructions = (mint, config, nonTransferableData) => {
        const ixs = [];
        const extensionsTypes = [ExtensionType.MetadataPointer];
        const hasExtensions = Object.values(config).some(value => value);

        if (hasExtensions) {
            if (config.transferFee) {
                ixs.push(
                    createInitializeTransferFeeConfigInstruction(
                        mint,
                        toPublicKey(config.transferFee.transferAuthority),
                        toPublicKey(config.transferFee.withdrawAuthority),
                        config.transferFee.basisPoints,
                        new BigNumber(config.transferFee.maximumFee.toString()),
                        TOKEN_2022_PROGRAM_ID
                    )
                );
                extensionsTypes.push(ExtensionType.TransferFeeConfig);
            }
            if (config.transferHook) {
                ixs.push(
                    createInitializeTransferHookInstruction(
                        mint,
                        toPublicKey(config.transferHook.authority),
                        toPublicKey(config.transferHook.programId),
                        TOKEN_2022_PROGRAM_ID
                    )
                );
                extensionsTypes.push(ExtensionType.TransferHook);
            }
            if (config.permanentDelegate) {
                ixs.push(
                    createInitializePermanentDelegateInstruction(
                        mint,
                        toPublicKey(config.permanentDelegate.authority),
                        TOKEN_2022_PROGRAM_ID
                    )
                );
                extensionsTypes.push(ExtensionType.PermanentDelegate);
            }
            if (config.mintCloseAuthority) {
                ixs.push(
                    createInitializeMintCloseAuthorityInstruction(
                        mint,
                        toPublicKey(config.mintCloseAuthority.authority),
                        TOKEN_2022_PROGRAM_ID
                    )
                );
                extensionsTypes.push(ExtensionType.MintCloseAuthority);
            }
            if (config.interestBearing) {
                ixs.push(
                    createInitializeInterestBearingMintInstruction(
                        mint,
                        toPublicKey(config.interestBearing.authority),
                        config.interestBearing.rate,
                        TOKEN_2022_PROGRAM_ID
                    )
                );
                extensionsTypes.push(ExtensionType.InterestBearingConfig);
            }
            if (nonTransferableData) {
                ixs.push(createInitializeNonTransferableMintInstruction(mint, TOKEN_2022_PROGRAM_ID));
                extensionsTypes.push(ExtensionType.NonTransferable);
            }
        }
        return { ixs, extensionsTypes };
    };

    const create = async (metadata = { name: '', symbol: '', uri: '' }, extensionsConfig, amount, decimals2022) => {
        const pubKey = publicKey;
        const mint = Keypair.generate();
        const ata = getAssociatedTokenAddressSync(mint.publicKey, pubKey, undefined, TOKEN_2022_PROGRAM_ID);
        const decimals = decimals2022;

        const metaData: TokenMetadata = {
            mint: mint.publicKey,
            name: metadata.name,
            symbol: metadata.symbol,
            uri: metadata.uri,
            additionalMetadata: [],
        };

        const { ixs, extensionsTypes } = buildExtensionsInstructions(mint.publicKey, extensionsConfig, extensionsConfig.nonTransferable);
        const priceIx = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1000000 });

        const mintLen = getMintLen(extensionsTypes);
        const metadataLen = TYPE_SIZE + LENGTH_SIZE + pack(metaData).length;

        const mintLamports = await connection.getMinimumBalanceForRentExemption(mintLen + metadataLen);
        const hash = await connection.getLatestBlockhash('confirmed');

        const mintTransaction = new Transaction({
            feePayer: pubKey,
            blockhash: hash.blockhash,
            lastValidBlockHeight: hash.lastValidBlockHeight
        }).add(
            priceIx,
            SystemProgram.createAccount({
                fromPubkey: pubKey,
                newAccountPubkey: mint.publicKey,
                space: mintLen,
                lamports: mintLamports,
                programId: TOKEN_2022_PROGRAM_ID
            }),
            createInitializeMetadataPointerInstruction(mint.publicKey, pubKey, mint.publicKey, TOKEN_2022_PROGRAM_ID),
            ...ixs,
            createInitializeMintInstruction(mint.publicKey, decimals, pubKey, null, TOKEN_2022_PROGRAM_ID),
            createInitializeInstruction({
                programId: TOKEN_2022_PROGRAM_ID,
                mint: mint.publicKey,
                metadata: mint.publicKey,
                name: metaData.name,
                symbol: metaData.symbol,
                uri: metaData.uri,
                mintAuthority: pubKey,
                updateAuthority: pubKey,
            }),
            createAssociatedTokenAccountInstruction(pubKey, ata, pubKey, mint.publicKey, TOKEN_2022_PROGRAM_ID),
            createMintToInstruction(mint.publicKey, ata, pubKey, new BigNumber(amount), undefined, TOKEN_2022_PROGRAM_ID)
        );
        mintTransaction.partialSign(mint);
        const signedTx = await wallet.signTransaction(mintTransaction);
        const rawTx = signedTx.serialize();
        const confirmationStrategy: BlockheightBasedTransactionConfirmationStrategy = {
            lastValidBlockHeight: hash.lastValidBlockHeight,
            signature: bs58.encode(signedTx.signature),
            blockhash: hash.blockhash,
        };
        const signature = await sendAndConfirmRawTransaction(connection, rawTx, confirmationStrategy);

        return { mint: mint.publicKey.toString(), signature };
    };

    return { create };
};

The code for the createInitializeInstruction function in the @solana/spl-token-metadata library:

import type { StructToEncoderTuple } from '@solana/codecs-data-structures';
import { getBooleanEncoder, getBytesEncoder, getDataEnumCodec, getStructEncoder } from '@solana/codecs-data-structures';
import { getU64Encoder } from '@solana/codecs-numbers';
import { getStringEncoder } from '@solana/codecs-strings';
import { getOptionEncoder } from '@solana/options';
import { splDiscriminate } from '@solana/spl-type-length-value';
import type { PublicKey } from '@solana/web3.js';
import { TransactionInstruction } from '@solana/web3.js';

import type { Field } from './field.js';
import { getFieldCodec, getFieldConfig } from './field.js';

function packInstruction<T extends object>(
    layout: StructToEncoderTuple<T>,
    discriminator: Uint8Array,
    values: T): Buffer {
    const encoder = getStructEncoder(layout);
    const data = encoder.encode(values);
    return Buffer.concat([discriminator, data]);
}/** * Initializes a TLV entry with the basic token-metadata fields. * * Assumes that the provided mint is an SPL token mint, that the metadata * account is allocated and assigned to the program, and that the metadata * account has enough lamports to cover the rent-exempt reserve. */export interface InitializeInstructionArgs {    programId: PublicKey;
    metadata: PublicKey;
    updateAuthority: PublicKey;
    mint: PublicKey;
    mintAuthority: PublicKey;
    name: string;
    symbol: string;
    uri: string;
}
export function createInitializeInstruction(args: InitializeInstructionArgs): TransactionInstruction {
    const { programId, metadata, updateAuthority, mint, mintAuthority, name, symbol, uri } = args;
    return new TransactionInstruction({
        programId,
        keys: [
            { isSigner: false, isWritable: true, pubkey: metadata },
            { isSigner: false, isWritable: false, pubkey: updateAuthority },
            { isSigner: false, isWritable: false, pubkey: mint },
            { isSigner: true, isWritable: false, pubkey: mintAuthority },
        ],
        data: packInstruction(
            [
                ['name', getStringEncoder()],
                ['symbol', getStringEncoder()],
                ['uri', getStringEncoder()],
            ],
            splDiscriminate('spl_token_metadata_interface:initialize_account'),
            { name, symbol, uri }
        ),
    });
}/** * If the field does not exist on the account, it will be created. * If the field does exist, it will be overwritten. */export interface UpdateFieldInstruction {
    programId: PublicKey;
    metadata: PublicKey;
    updateAuthority: PublicKey;
    field: Field | string;
    value: string;
}
export function createUpdateFieldInstruction(args: UpdateFieldInstruction): TransactionInstruction {    
    const { programId, metadata, updateAuthority, field, value } = args;
    return new TransactionInstruction({
        programId,
        keys: [
            { isSigner: false, isWritable: true, pubkey: metadata },
            { isSigner: true, isWritable: false, pubkey: updateAuthority },
        ],
        data: packInstruction(
            [
                ['field', getDataEnumCodec(getFieldCodec())],
                ['value', getStringEncoder()],
            ],
            splDiscriminate('spl_token_metadata_interface:updating_field'),
            { field: getFieldConfig(field), value }
        ),
    });
}
export interface RemoveKeyInstructionArgs {
    programId: PublicKey;
    metadata: PublicKey;
    updateAuthority: PublicKey;
    key: string;
    idempotent: boolean;
}
export function createRemoveKeyInstruction(args: RemoveKeyInstructionArgs) {
    const { programId, metadata, updateAuthority, key, idempotent } = args;
    return new TransactionInstruction({
        programId,
        keys: [
            { isSigner: false, isWritable: true, pubkey: metadata },
            { isSigner: true, isWritable: false, pubkey: updateAuthority },
        ],
        data: packInstruction(
            [
                ['idempotent', getBooleanEncoder()],
                ['key', getStringEncoder()],
            ],
            splDiscriminate('spl_token_metadata_interface:remove_key_ix'),
            { idempotent, key }
        ),
    });
}
export interface UpdateAuthorityInstructionArgs {
    programId: PublicKey;
    metadata: PublicKey;
    oldAuthority: PublicKey;
    newAuthority: PublicKey | null;
}

export function createUpdateAuthorityInstruction(args: UpdateAuthorityInstructionArgs): TransactionInstruction {
    const { programId, metadata, oldAuthority, newAuthority } = args;

    const newAuthorityBuffer = Buffer.alloc(32);
    if (newAuthority) {
        newAuthorityBuffer.set(newAuthority.toBuffer());
    } else {
        newAuthorityBuffer.fill(0);
    }
    return new TransactionInstruction({
        programId,
        keys: [
            { isSigner: false, isWritable: true, pubkey: metadata },
            { isSigner: true, isWritable: false, pubkey: oldAuthority },
        ],
        data: packInstruction(
            [['newAuthority', getBytesEncoder({ size: 32 })]],
            splDiscriminate('spl_token_metadata_interface:update_the_authority'),
            { newAuthority: newAuthorityBuffer }
        ),
    });
}
export interface EmitInstructionArgs {
    programId: PublicKey;
    metadata: PublicKey;
    start?: bigint;
    end?: bigint;
}
export function createEmitInstruction(args: EmitInstructionArgs): TransactionInstruction {
    const { programId, metadata, start, end } = args;
    return new TransactionInstruction({
        programId,
        keys: [{ isSigner: false, isWritable: false, pubkey: metadata }],
        data: packInstruction(
            [
                ['start', getOptionEncoder(getU64Encoder())],
                ['end', getOptionEncoder(getU64Encoder())],
            ],
            splDiscriminate('spl_token_metadata_interface:emitter'),
            { start: start ?? null, end: end ?? null }
        ),
    });}

I would be grateful for any help.

I’m stumped, I’ve looked through a bunch of guides, but the recommendations don’t work for me 🙁

How to target only webview rendering with CSS?

The website in question renders correctly on various Firefox browsers, Mac, and IOS browsers, Edge, Chrome, and Chromium, on both desktop and mobile.

However, when it is viewed from webview, either from a link clicked on android facebook app, or even actually the duck duck go mobile android app, one of the font sizes is larger and pushes outside of its container div, breaking the view.

I’ve been developing front-end for 10 years, but have yet to explore any webview customizations.

How to target webview rendering from CSS (or if need be JavaScript)?

Efficient algorithm for partial reordering

Consider the following array of objects:

[
{v: 'a'},
{v: 'b'},
{v: 'c', ptr: 'b'},
{v: 'd', ptr: 'a'},
{v: 'e'},
]

Some of the objects contain a ptr property, referencing the v property value of an object that it should directly preceed. Two objects will never attempt to directly preceed the same object, and there will never be a loop (e.g. a->b->c->a) in the array.

Therefore, here are two possible valid rearrangements of the objects:

[
{v: 'e'},
{v: 'd', ptr: 'a'},
{v: 'a'},
{v: 'c', ptr: 'b'},
{v: 'b'},
]
[
{v: 'c', ptr: 'b'},
{v: 'b'},
{v: 'd', ptr: 'a'},
{v: 'a'},
{v: 'e'}
]

It doesn’t matter at all where objects appear in the output, if there is no ptr property referencing it. All that matters is that certain objects directly preceed others where the ptr property requests it.

What is a reasonably efficient algorithm to perform this kind of rearrangement?

Although the data is guaranteed to not contain loops, the rearrangement should be careful not to get into an infinite loop where it keeps rearranging the objects forever.

Note that although these examples use strings for v and ptr, the actual application will involve DOM elements as the values for v and ptr references. Therefore, the solution should only be able to compare v and ptr properties for equality.

Puppeteer PDF- Table Headers Overlapping When Deployed to Docker Container

For one reason or another, I can’t get these PDFs to generate properly when I have this deployed. It appears to be an issue with Puppeteer because I can get it to print correctly even when I open the html in Chrome and print to pdf. See below for the docker file, puppeteer implementation, and HTML (It’s a bit of a mess because of how the template is built, but you’ll get the idea):

FROM node:20-alpine

RUN apk add --no-cache 
    chromium 
    nss 
    freetype 
    freetype-dev 
    harfbuzz 
    ca-certificates 
    ttf-freefont 
    fontconfig

RUN fc-cache -f -v

# Set environment variable to use Puppeteer with Chromium installed in non-standard location
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
COPY .npmrc ./

# RUN npm install
# If you are building your code for production
RUN npm install pm2 -g
RUN npm ci --only=production

# Bundle app source
COPY . .

EXPOSE 4042

CMD [ "pm2-runtime", "start", "/usr/src/app/process.yml" ]
import { launch } from 'puppeteer';

class FormatDocsApi {
    async formatHtmlString({ htmlString }) {
        const browser = await launch({
            headless: true,
            args: [
                '--disable-features=IsolateOrigins',
                '--disable-site-isolation-trials',
                '--autoplay-policy=user-gesture-required',
                '--disable-background-networking',
                '--disable-background-timer-throttling',
                '--disable-backgrounding-occluded-windows',
                '--disable-breakpad',
                '--disable-client-side-phishing-detection',
                '--disable-component-update',
                '--disable-default-apps',
                '--disable-dev-shm-usage',
                '--disable-domain-reliability',
                '--disable-extensions',
                '--disable-features=AudioServiceOutOfProcess',
                '--disable-hang-monitor',
                '--disable-ipc-flooding-protection',
                '--disable-notifications',
                '--disable-offer-store-unmasked-wallet-cards',
                '--disable-popup-blocking',
                '--disable-print-preview',
                '--disable-prompt-on-repost',
                '--disable-renderer-backgrounding',
                '--disable-setuid-sandbox',
                '--disable-speech-api',
                '--disable-sync',
                '--hide-scrollbars',
                '--ignore-gpu-blacklist',
                '--metrics-recording-only',
                '--mute-audio',
                '--no-default-browser-check',
                '--no-first-run',
                '--no-pings',
                '--no-sandbox',
                '--no-zygote',
                '--password-store=basic',
                '--use-gl=swiftshader',
                '--use-mock-keychain',
            ],
        });
        console.log('Browser launched:', await browser.version());
        const page = await browser.newPage();
        console.log('page created');
        await page.emulateMediaType('print');
        await page.evaluateHandle('document.fonts.ready');
        await page.setContent(htmlString, { waitUntil: 'networkidle0' });
        const pdfOptions = {
            displayHeaderFooter: true,
            preferCSSPageSize: true,
            format: 'A4',
            headerTemplate: '<div></div>',
            footerTemplate:
                "<div style="font-size:8px; text-align:end; width:100%; margin:0px 10px 0px 10px;"><span class='pageNumber'></span> / <span class='totalPages'></span></div>",
            margin: {
                top: '40px',
                bottom: '40px',
                left: '40px',
                right: '40px',
            },
        };
        console.log('PDF buffer generating now...');
        const pdfBuffer = await page.pdf(pdfOptions);
        // Close the browser
        await browser.close();
        return pdfBuffer; // Return a success message or data
    }
}

export { FormatDocsApi };

HTML/CSS

Example of issue

I’m running node 20, puppeteer v22, and browser is Chrome/123.0.6312.122.
I’ve been battling this for weeks and thought upgrading Node to 20 and Puppeteer to v22 would be the ticket, but it’s still not working when deployed.

Dropzone JS showing up but with the normal file upload overtop of it

Dropzone JS is showing up like so:

Picture of problem with dropzonejs

I have called the CSS file in the head of my site:

<link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" />

And the JS file in footer with all the other JS (of course after the jquery).

<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>

Form Code:

<form action="#" id="upload" class="dropzone" method="post" enctype="multipart/form-data">
                                        <input type="file" name="file" id="file" required>
                                    </form>

I tried to move the javascript file to the header so it would be ran before the rest of the page loaded, but that did no change. I added basic config options like setting “clickable” to false and indeed it wouldn’t let me click the area anymore to try and upload. But I cannot seem to get rid of the regular ol file upload thing.

Also, i uploaded something by dropping. It does try to do it. Only problem is the old file thing is still showing up for unknown reasoning.

Uncaught TypeError: request.response.getContent is not a function in devtools extension manifest 3

enter image description here

I’m trying to follow https://betterprogramming.pub/chrome-extension-intercepting-and-reading-the-body-of-http-requests-dd9ebdf2348b to create a devtools panel in order to grab the response of a specific post request on a website. I’ve started with the instructions in the second part of the article, to create a basic devtools panel (which appears to work). I followed this with a discussion of the devtools.network API at https://developer.chrome.com/docs/extensions/reference/api/devtools/network#type-Request

Here is the manifest.json:

{
  "manifest_version": 3,
  "name": "Extension",
  "version": "1.0",
  "description": "Description",
  "devtools_page": "devtools.html"
}

devtools.html:

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

devtools.js:

chrome.devtools.panels.create("MyPanel", null, 'panel.html');

panel.html:

<html>
    <body>
        <script src="panel.js"></script>
    </body>
</html>

panel.js:

function handleRequestFinished(request) {
  // console.log("Server IP: ", request.serverIPAddress);
  // request.getContent().then(([content, mimeType]) => {
  request.response.getContent().then(([content, mimeType]) => {
    console.log("Content: ", content);
    console.log("MIME type: ", mimeType);
  });
}

chrome.devtools.network.onRequestFinished.addListener(handleRequestFinished);

I’m getting the error in the title. What am I doing wrong?

How do I display my wishlist where there are mulitple different databases my information is required from?

I have created a code that stores the users’ saves onto a database, however I have only stored the id of the items the users save, not the name or anything. What query / code would I use? so far I have the code to save the item but not to upload them

@app.route("/add_favourite", methods=["POST"]) # / contact page
def add_favourite():
    if request.method == "POST":
        TablePk = request.form.get("TablePk")
        Id = request.form.get("Id")
        CustomerId = request.form.get("CustomerId")
        dbObject = Database(DB_FILE)
        # Check if that is already added
        # May be remove favourite
        if dbObject.addFavourite(TablePk, Id, CustomerId):
          return "<span class='badge text-bg-success'>Added!</span>"
    def addFavourite(self, TablePk, Id, CustomerId):
        """
        Adds an entry to the 'Favourite' table in the database.

        output:
        - string - If successful, returns a list of records. Otherwise, returns an error message " something went wrong".
        """
        cursor = self.connection.cursor()
        query = f"INSERT INTO Favourite ({TablePk}, 'CustomerId') VALUES ({Id}, {CustomerId});"
        print(query)  #  for debugging 
        try:
            cursor.execute(query)
            self.connection.commit()
            return True
        except:
            print("Something went wrong")  
    $(".favourite-btn").on("click", function (e) {
        e.preventDefault();
        $(".badge").hide("slow"); 
        var button = "#" + $(this).attr('id');
        console.log(button);
        var data = { "TablePk":$(button).attr("data-table"), "Id":$(button).attr("data-id"), "CustomerId":$(button).attr("data-user") }
        console.log(data);
        $.ajax({
            url: "/add_favourite",
            data: data,
            type: "POST",
            success: function (response) {
                $(button).after(response);
                setTimeout(function () {
                    $(".badge").hide("slow");
                }, 3000);
            }

        });
    });

I tried to make a code to link the id to the id of each database and extract data from there but I am a little stuck on the query to use.

Promise.resolve() as return vs simply value return in chaining

I am finding it very difficult to answer the promise chaining order question. Especially when I have return type as Promise object instead of string, I tried executing it in browser and understand same but still its difficult for me. So far I know then() itself returns a Promise now say onfuldilled callback also return new Promise using Promise.resolve() then to which Promise object the subchain “then” will be applicable and please can someone explain the output(in browser) for this code

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    new Promise((resolve, reject) => {
      console.log(2111111 + "==========>1");
      resolve(2111111 + "==========>1");
    })
      .then((res) => {
        console.log(res);
        return Promise.resolve(4);
      })
      .then((res) => {
        console.log(res);
      });

    new Promise((resolve, reject) => {
      console.log(2);
      resolve(2);
    })
      .then((res) => {
        console.log(res);
        return 2;
      })
      .then((res) => {
        console.log(res);
        return 22;
      })
      .then((res) => {
        console.log(res);
        return 23;
      })
      .then((res) => {
        console.log(res);
        return 24;
      });

    console.log(555555555555);
  </script>
</html>

Completely different result lets ignore that.

Clicking browser back button auto-activates event listener

I have a strange problem that only occurs in some browsers which I cannot find a solution to anywhere.

Here’s the objective:

Make a simple page with a hyperlink.
When the hyperlink is clicked, a box immediately appears telling the user to wait while the next page is being fetched from the network.
If the visitor doesn’t have javascript, then the box won’t appear and the next page would attempt to load. The non-javascript version is fine, but the javascript version gives problems.

In Firefox version 123.0 and on Chrome 122 for Windows 10, I have the problem where if a user attempts to load the next page then clicks the back button on their browser, the box appears automatically (which should not happen).

In Seamonkey 2.53.18.2 everything works correctly.

Here is the PHP code I used that can reproduce the problem. Heck, the problem may also be reproduced without using the PHP portion.

<?php
//this code fragment simulates when the resource was last updated
//so then I load the resource once and generate status 304 when user clicks the back button

date_default_timezone_set('America/Toronto');
$uset=strtotime("2024-04-13 6:20PM"); 
$lmod=gmdate("D, d M Y H:i:s T",$uset);
$ifms=$_SERVER["HTTP_IF_MODIFIED_SINCE"];
header('Last-Modified: '.$lmod,true);
if (isset($ifms{1}) && $ifms===$lmod){
header('HTTP/1.1 304 NM',true);exit();
}
?>
<!DOCTYPE HTML>
<html>
<head>
<style>
#wbox{
display:none;
border-radius:1em;
border:1px solid black;
background:#FFFFAA;
color:#000000
}
</style>
</head>
<body>
<h1>Content loader</h1>
<a ID="clickee" href="something.htm">Click here</a>
<div ID="wbox">
<h2>Loading contents...</h2>
</div>
<script>
function showbox(){
document.getElementById('wbox').style.display="block";
}
document.getElementById('clickee').addEventListener("click",showbox);
</script>
</body>
</html>

Could it be that the new browsers are experiencing bugs or is there something I can do to my code to prevent the “loading contents” box from automatically appearing when the user returns to the page by clicking the “back” button.

Oh, and if the user clicks the refresh/reload button after clicking the back button, the problem goes away but its an inconvenience to click 2 buttons when only 1 should be clicked.

As mentioned above, I tested my code in multiple browsers. the “loading contents” box should only appear when leaving the page, not when re-entering the page by use of the browser’s “back” button.

Having trouble figuring how to populate HTML div with database entries (PHP) [closed]

A brief context of my project: it is basically a registry of several interconnected things (users, permissions for borrowing keys and environments registered for these keys). I’m only using HTML/Javascript and PHP.

On my home page I have a section for the user to register environments (study room, library, computer room, etc.), new users (actually people who work in that location, who can borrow keys for the registered environments) and register permissions for borrowing keys. All these parts were made using several divs on a single page, but they are activated or deactivated using javascript (there is a sidebar that opens these sections. Register environments/register users/register permissions, and consult environments/consult users/consult permissions).

Everything is fine so far, I managed to register all of them, everything is sent to the database without problems. Then later I did a delete function to exclude environments and users, which also worked.

My problem is in the new section to editing of environments and users. The editing part is also one of those javascript-enabled hidden divs, in case that information is useful.

I need the ID value for the item I’m editing so that I can use an UPDATE query later, but I don’t know the best way to store this value anywhere. And the only time I got closer to achieving it, only my first edit button on the list ended up working, the rest didn’t.

I’m not going to post my code because besides it being a little messy, I just wanted to know a good way on how to accomplish this, and not some correction in some part of my code. But if necessary, I’ll post it in the comments.

A little draft of how it’s organized (the div and the database entries)