import React, { createContext, useCallback, useMemo, useRef, useState } from 'react';
import { ToastViewport } from './ToastViewport';
export const ToastContext = createContext(undefined);
let counter = 0;
function encodeCursor(row) {
if (!row) return null;
const payload = JSON.stringify({ t: row.created_at, id: row.id });
return Buffer.from(payload, 'utf8').toString('base64url');
}
module FlashHelper
FLASH_CLASSES = {
"notice" => "flash--success",
"alert" => "flash--error",
"error" => "flash--error"
}.freeze
class ApiError extends Error {
constructor(statusCode, message, code) {
super(message);
this.name = 'ApiError';
this.statusCode = statusCode;
this.code = code || null;
class BatchLoader {
constructor(batchFn, { cacheKeyFn = (k) => k } = {}) {
this.batchFn = batchFn;
this.cacheKeyFn = cacheKeyFn;
this.cache = new Map();
this.queue = [];
const crypto = require('crypto');
function computeStrongEtag(body) {
const buf = Buffer.isBuffer(body) ? body : Buffer.from(String(body));
const digest = crypto.createHash('sha1').update(buf).digest('base64');
return '"' + digest + '"';
import { Controller } from "@hotwired/stimulus"
import { NotificationsApi } from "notifications_api"
export default class extends Controller {
static targets = ["notification"]
static values = {
module TimeAgoHelper
def time_ago_tag(time, locale: I18n.locale, **options)
return if time.blank?
time = time.to_time
fallback = l(time, format: :short)
const express = require('express');
const multer = require('multer');
const os = require('os');
const fs = require('fs/promises');
const { parseCsvStream } = require('./csvStreamParser');
require 'set'
require 'json'
class Broadcaster
def initialize
@mutex = Mutex.new
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["field"]
validateField(event) {
const fs = require('fs');
const readline = require('readline');
async function* streamCsvRows(filePath) {
const stream = fs.createReadStream(filePath, { encoding: 'utf8' });
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });