Remove unused dependencies, misc. small fixes
This commit is contained in:
parent
0bebbd9b23
commit
2b4381fa3c
@ -1,6 +1,5 @@
|
|||||||
const { join, dirname } = require("path");
|
const { join, dirname } = require("node:path");
|
||||||
|
const { promises: fs } = require("node:fs");
|
||||||
const { promises: fs } = require("fs");
|
|
||||||
|
|
||||||
const api = require("./api");
|
const api = require("./api");
|
||||||
|
|
||||||
@ -26,19 +25,19 @@ const Api = output =>
|
|||||||
|
|
||||||
const Redoc = output =>
|
const Redoc = output =>
|
||||||
fs.copyFile(join(
|
fs.copyFile(join(
|
||||||
dirname(require.resolve('redoc')),
|
dirname(require.resolve("redoc")),
|
||||||
'redoc.standalone.js'),
|
"redoc.standalone.js"),
|
||||||
output);
|
output);
|
||||||
|
|
||||||
module.exports = (async () => {
|
module.exports = (async () => {
|
||||||
const out = join(__dirname, 'static');
|
const out = join(__dirname, "static");
|
||||||
const apiFile = 'api.json';
|
const apiFile = "api.json";
|
||||||
const redocFile = 'redoc.js';
|
const redocFile = "redoc.js";
|
||||||
await fs.mkdir(out, { recursive: true });
|
await fs.mkdir(out, { recursive: true });
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
Api(join(out, apiFile)),
|
Api(join(out, apiFile)),
|
||||||
Redoc(join(out, redocFile)),
|
Redoc(join(out, redocFile)),
|
||||||
Template(join(out, 'index.html'), {
|
Template(join(out, "index.html"), {
|
||||||
api: apiFile,
|
api: apiFile,
|
||||||
title: api.info.title,
|
title: api.info.title,
|
||||||
redoc: redocFile
|
redoc: redocFile
|
||||||
|
1123
package-lock.json
generated
1123
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -4,8 +4,8 @@
|
|||||||
"description": "Modern URL shortener.",
|
"description": "Modern URL shortener.",
|
||||||
"main": "./server/server.js",
|
"main": "./server/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "cross-env NODE_ENV=development node --watch-path=./server --watch-path=./custom server/server.js",
|
"dev": "node --env-file-if-exists=.env --watch-path=./server --watch-path=./custom server/server.js",
|
||||||
"start": "cross-env NODE_ENV=production node server/server.js",
|
"start": "node --env-file-if-exists=.env server/server.js --production",
|
||||||
"migrate": "knex migrate:latest",
|
"migrate": "knex migrate:latest",
|
||||||
"migrate:make": "knex migrate:make",
|
"migrate:make": "knex migrate:make",
|
||||||
"docs:build": "cd docs/api && node generate && cd ../.."
|
"docs:build": "cd docs/api && node generate && cd ../.."
|
||||||
@ -25,12 +25,11 @@
|
|||||||
"homepage": "https://github.com/thedevs-network/kutt#readme",
|
"homepage": "https://github.com/thedevs-network/kutt#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
|
"better-sqlite3": "^11.8.1",
|
||||||
"bull": "4.16.5",
|
"bull": "4.16.5",
|
||||||
"cookie-parser": "1.4.7",
|
"cookie-parser": "1.4.7",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"cross-env": "7.0.3",
|
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
"dotenv": "16.0.3",
|
|
||||||
"envalid": "8.0.0",
|
"envalid": "8.0.0",
|
||||||
"express": "4.21.2",
|
"express": "4.21.2",
|
||||||
"express-rate-limit": "7.5.0",
|
"express-rate-limit": "7.5.0",
|
||||||
@ -45,8 +44,6 @@
|
|||||||
"ms": "2.1.3",
|
"ms": "2.1.3",
|
||||||
"mysql2": "3.12.0",
|
"mysql2": "3.12.0",
|
||||||
"nanoid": "3.3.8",
|
"nanoid": "3.3.8",
|
||||||
"node-cron": "3.0.3",
|
|
||||||
"node-mailer": "0.1.1",
|
|
||||||
"nodemailer": "6.9.16",
|
"nodemailer": "6.9.16",
|
||||||
"passport": "0.7.0",
|
"passport": "0.7.0",
|
||||||
"passport-jwt": "4.0.1",
|
"passport-jwt": "4.0.1",
|
||||||
@ -55,9 +52,7 @@
|
|||||||
"pg": "8.13.1",
|
"pg": "8.13.1",
|
||||||
"pg-query-stream": "4.7.1",
|
"pg-query-stream": "4.7.1",
|
||||||
"rate-limit-redis": "4.2.0",
|
"rate-limit-redis": "4.2.0",
|
||||||
"sqlite3": "5.1.7",
|
"useragent": "2.3.0"
|
||||||
"useragent": "2.3.0",
|
|
||||||
"uuid": "10.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "2.4.2",
|
"@types/bcryptjs": "2.4.2",
|
||||||
@ -68,7 +63,6 @@
|
|||||||
"@types/jsonwebtoken": "7.2.8",
|
"@types/jsonwebtoken": "7.2.8",
|
||||||
"@types/ms": "0.7.31",
|
"@types/ms": "0.7.31",
|
||||||
"@types/node": "18.11.9",
|
"@types/node": "18.11.9",
|
||||||
"@types/node-cron": "2.0.2",
|
|
||||||
"@types/nodemailer": "6.4.6",
|
"@types/nodemailer": "6.4.6",
|
||||||
"@types/pg": "8.11.10",
|
"@types/pg": "8.11.10",
|
||||||
"redoc": "2.2.0"
|
"redoc": "2.2.0"
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
const cron = require("node-cron");
|
|
||||||
|
|
||||||
const query = require("./queries");
|
const query = require("./queries");
|
||||||
const utils = require("./utils");
|
const utils = require("./utils");
|
||||||
const env = require("./env");
|
|
||||||
|
|
||||||
// check and delete links 30 secoonds
|
// check and delete links 30 secoonds
|
||||||
cron.schedule("*/30 * * * * *", function() {
|
setInterval(function () {
|
||||||
query.link.batchRemove({ expire_in: ["<", utils.dateToUTC(new Date())] }).catch();
|
query.link.batchRemove({ expire_in: ["<", utils.dateToUTC(new Date())] }).catch();
|
||||||
});
|
}, 30_000);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
require("dotenv").config();
|
|
||||||
const { cleanEnv, num, str, bool } = require("envalid");
|
const { cleanEnv, num, str, bool } = require("envalid");
|
||||||
|
|
||||||
const supportedDBClients = [
|
const supportedDBClients = [
|
||||||
@ -20,6 +19,9 @@ if (process.env.JWT_SECRET === "") {
|
|||||||
delete process.env.JWT_SECRET;
|
delete process.env.JWT_SECRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if NODE_ENV is not already set, set it based on --production argument
|
||||||
|
process.env.NODE_ENV ??= process.argv.includes("--production") ? "production" : "development";
|
||||||
|
|
||||||
const env = cleanEnv(process.env, {
|
const env = cleanEnv(process.env, {
|
||||||
PORT: num({ default: 3000 }),
|
PORT: num({ default: 3000 }),
|
||||||
SITE_NAME: str({ example: "Kutt", default: "Kutt" }),
|
SITE_NAME: str({ example: "Kutt", default: "Kutt" }),
|
||||||
@ -27,7 +29,7 @@ const env = cleanEnv(process.env, {
|
|||||||
LINK_LENGTH: num({ default: 6 }),
|
LINK_LENGTH: num({ default: 6 }),
|
||||||
LINK_CUSTOM_ALPHABET: str({ default: "abcdefghkmnpqrstuvwxyzABCDEFGHKLMNPQRSTUVWXYZ23456789" }),
|
LINK_CUSTOM_ALPHABET: str({ default: "abcdefghkmnpqrstuvwxyzABCDEFGHKLMNPQRSTUVWXYZ23456789" }),
|
||||||
TRUST_PROXY: bool({ default: true }),
|
TRUST_PROXY: bool({ default: true }),
|
||||||
DB_CLIENT: str({ choices: supportedDBClients, default: "sqlite3" }),
|
DB_CLIENT: str({ choices: supportedDBClients, default: "better-sqlite3" }),
|
||||||
DB_FILENAME: str({ default: "db/data" }),
|
DB_FILENAME: str({ default: "db/data" }),
|
||||||
DB_HOST: str({ default: "localhost" }),
|
DB_HOST: str({ default: "localhost" }),
|
||||||
DB_PORT: num({ default: 5432 }),
|
DB_PORT: num({ default: 5432 }),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const { differenceInDays, differenceInMinutes, addMinutes, subMinutes } = require("date-fns");
|
const { differenceInDays, addMinutes } = require("date-fns");
|
||||||
const { nanoid } = require("nanoid");
|
const { nanoid } = require("nanoid");
|
||||||
const passport = require("passport");
|
const passport = require("passport");
|
||||||
const { v4: uuid } = require("uuid");
|
const { randomUUID } = require("node:crypto");
|
||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
|
|
||||||
const { ROLES } = require("../consts");
|
const { ROLES } = require("../consts");
|
||||||
@ -227,7 +227,7 @@ async function resetPassword(req, res) {
|
|||||||
const user = await query.user.update(
|
const user = await query.user.update(
|
||||||
{ email: req.body.email },
|
{ email: req.body.email },
|
||||||
{
|
{
|
||||||
reset_password_token: uuid(),
|
reset_password_token: randomUUID(),
|
||||||
reset_password_expires: utils.dateToUTC(addMinutes(new Date(), 30))
|
reset_password_expires: utils.dateToUTC(addMinutes(new Date(), 30))
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -298,7 +298,7 @@ async function changeEmailRequest(req, res) {
|
|||||||
{ id: req.user.id },
|
{ id: req.user.id },
|
||||||
{
|
{
|
||||||
change_email_address: email,
|
change_email_address: email,
|
||||||
change_email_token: uuid(),
|
change_email_token: randomUUID(),
|
||||||
change_email_expires: utils.dateToUTC(addMinutes(new Date(), 30))
|
change_email_expires: utils.dateToUTC(addMinutes(new Date(), 30))
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
const { differenceInSeconds } = require("date-fns");
|
const { differenceInSeconds } = require("date-fns");
|
||||||
const promisify = require("util").promisify;
|
const promisify = require("node:util").promisify;
|
||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
const { isbot } = require("isbot");
|
const { isbot } = require("isbot");
|
||||||
const URL = require("url");
|
const URL = require("node:url");
|
||||||
const dns = require("dns");
|
const dns = require("node:dns");
|
||||||
|
|
||||||
const validators = require("./validators.handler");
|
const validators = require("./validators.handler");
|
||||||
const map = require("../utils/map.json");
|
const map = require("../utils/map.json");
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
const { isAfter, subDays, subHours, addMilliseconds, differenceInHours } = require("date-fns");
|
const { addMilliseconds } = require("date-fns");
|
||||||
const { body, param, query: queryValidator } = require("express-validator");
|
const { body, param, query: queryValidator } = require("express-validator");
|
||||||
const promisify = require("util").promisify;
|
const promisify = require("node:util").promisify;
|
||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
const dns = require("dns");
|
const dns = require("node:dns");
|
||||||
const URL = require("url");
|
const URL = require("node:url");
|
||||||
const ms = require("ms");
|
const ms = require("ms");
|
||||||
|
|
||||||
const { ROLES } = require("../consts");
|
const { ROLES } = require("../consts");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const nodemailer = require("nodemailer");
|
const nodemailer = require("nodemailer");
|
||||||
const path = require("path");
|
const path = require("node:path");
|
||||||
const fs = require("fs");
|
const fs = require("node:fs");
|
||||||
|
|
||||||
const { resetMailText, verifyMailText, changeEmailText } = require("./text");
|
const { resetMailText, verifyMailText, changeEmailText } = require("./text");
|
||||||
const { CustomError } = require("../utils");
|
const { CustomError } = require("../utils");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const { addMinutes } = require("date-fns");
|
const { addMinutes } = require("date-fns");
|
||||||
const { v4: uuid } = require("uuid");
|
const { randomUUID } = require("node:crypto");
|
||||||
|
|
||||||
const { ROLES } = require("../consts");
|
const { ROLES } = require("../consts");
|
||||||
const utils = require("../utils");
|
const utils = require("../utils");
|
||||||
@ -42,7 +42,7 @@ async function add(params, user) {
|
|||||||
password: params.password,
|
password: params.password,
|
||||||
...(params.role && { role: params.role }),
|
...(params.role && { role: params.role }),
|
||||||
...(params.verified !== undefined && { verified: params.verified }),
|
...(params.verified !== undefined && { verified: params.verified }),
|
||||||
verification_token: uuid(),
|
verification_token: randomUUID(),
|
||||||
verification_expires: utils.dateToUTC(addMinutes(new Date(), 60))
|
verification_expires: utils.dateToUTC(addMinutes(new Date(), 60))
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ async function getAdmin(match, params) {
|
|||||||
async function totalAdmin(match, params) {
|
async function totalAdmin(match, params) {
|
||||||
const query = knex("users")
|
const query = knex("users")
|
||||||
.count("* as count")
|
.count("* as count")
|
||||||
.fromRaw('users')
|
.fromRaw("users")
|
||||||
.where(normalizeMatch(match));
|
.where(normalizeMatch(match));
|
||||||
|
|
||||||
if (params?.search) {
|
if (params?.search) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const Queue = require("bull");
|
const Queue = require("bull");
|
||||||
const path = require("path");
|
const path = require("node:path");
|
||||||
|
|
||||||
const env = require("../env");
|
const env = require("../env");
|
||||||
|
|
||||||
@ -19,8 +19,8 @@ if (env.REDIS_ENABLED) {
|
|||||||
visit.on("completed", job => job.remove());
|
visit.on("completed", job => job.remove());
|
||||||
|
|
||||||
// TODO: handler error
|
// TODO: handler error
|
||||||
// visit.on('error', function (error) {
|
// visit.on("error", function (error) {
|
||||||
// console.log('error');
|
// console.log("error");
|
||||||
// });
|
// });
|
||||||
} else {
|
} else {
|
||||||
const visitProcessor = require(path.resolve(__dirname, "visit.js"));
|
const visitProcessor = require(path.resolve(__dirname, "visit.js"));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const useragent = require("useragent");
|
const useragent = require("useragent");
|
||||||
const geoip = require("geoip-lite");
|
const geoip = require("geoip-lite");
|
||||||
const URL = require("url");
|
const URL = require("node:url");
|
||||||
|
|
||||||
const { removeWww } = require("../utils");
|
const { removeWww } = require("../utils");
|
||||||
const query = require("../queries");
|
const query = require("../queries");
|
||||||
|
@ -4,7 +4,7 @@ const cookieParser = require("cookie-parser");
|
|||||||
const passport = require("passport");
|
const passport = require("passport");
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const helmet = require("helmet");
|
const helmet = require("helmet");
|
||||||
const path = require("path");
|
const path = require("node:path");
|
||||||
const hbs = require("hbs");
|
const hbs = require("hbs");
|
||||||
|
|
||||||
const helpers = require("./handlers/helpers.handler");
|
const helpers = require("./handlers/helpers.handler");
|
||||||
|
@ -360,7 +360,7 @@ function registerHandlebarsHelpers() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
hbs.registerHelper("block", function(name) {
|
hbs.registerHelper("block", function(name) {
|
||||||
const val = (blocks[name] || []).join('\n');
|
const val = (blocks[name] || []).join("\n");
|
||||||
blocks[name] = [];
|
blocks[name] = [];
|
||||||
return val;
|
return val;
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// htmx.logAll();
|
// htmx.logAll();
|
||||||
|
|
||||||
// add text/html accept header to receive html instead of json for the requests
|
// add text/html accept header to receive html instead of json for the requests
|
||||||
document.body.addEventListener('htmx:configRequest', function(evt) {
|
document.body.addEventListener("htmx:configRequest", function(evt) {
|
||||||
evt.detail.headers["Accept"] = "text/html,*/*";
|
evt.detail.headers["Accept"] = "text/html,*/*";
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -21,8 +21,8 @@ function resetForm(id) {
|
|||||||
form.reset();
|
form.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.body.addEventListener('resetChangePasswordForm', resetForm("change-password"));
|
document.body.addEventListener("resetChangePasswordForm", resetForm("change-password"));
|
||||||
document.body.addEventListener('resetChangeEmailForm', resetForm("change-email"));
|
document.body.addEventListener("resetChangeEmailForm", resetForm("change-email"));
|
||||||
|
|
||||||
// an htmx extension to use the specifed params in the path instead of the query or body
|
// an htmx extension to use the specifed params in the path instead of the query or body
|
||||||
htmx.defineExtension("path-params", {
|
htmx.defineExtension("path-params", {
|
||||||
@ -31,7 +31,7 @@ htmx.defineExtension("path-params", {
|
|||||||
evt.detail.path = evt.detail.path.replace(/{([^}]+)}/g, function(_, param) {
|
evt.detail.path = evt.detail.path.replace(/{([^}]+)}/g, function(_, param) {
|
||||||
var val = evt.detail.parameters[param]
|
var val = evt.detail.parameters[param]
|
||||||
delete evt.detail.parameters[param]
|
delete evt.detail.parameters[param]
|
||||||
return val === undefined ? '{' + param + '}' : encodeURIComponent(val)
|
return val === undefined ? "{" + param + "}" : encodeURIComponent(val)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,8 +145,8 @@ window.addEventListener("click", function(event) {
|
|||||||
|
|
||||||
// handle navigation in the table of links
|
// handle navigation in the table of links
|
||||||
function setLinksLimit(event) {
|
function setLinksLimit(event) {
|
||||||
const buttons = Array.from(document.querySelectorAll('table .nav .limit button'));
|
const buttons = Array.from(document.querySelectorAll("table .nav .limit button"));
|
||||||
const limitInput = document.querySelector('#limit');
|
const limitInput = document.querySelector("#limit");
|
||||||
if (!limitInput || !buttons || !buttons.length) return;
|
if (!limitInput || !buttons || !buttons.length) return;
|
||||||
limitInput.value = event.target.textContent;
|
limitInput.value = event.target.textContent;
|
||||||
buttons.forEach(b => {
|
buttons.forEach(b => {
|
||||||
@ -155,56 +155,56 @@ function setLinksLimit(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setLinksSkip(event, action) {
|
function setLinksSkip(event, action) {
|
||||||
const buttons = Array.from(document.querySelectorAll('table .nav .pagination button'));
|
const buttons = Array.from(document.querySelectorAll("table .nav .pagination button"));
|
||||||
const limitElm = document.querySelector('#limit');
|
const limitElm = document.querySelector("#limit");
|
||||||
const totalElm = document.querySelector('#total');
|
const totalElm = document.querySelector("#total");
|
||||||
const skipElm = document.querySelector('#skip');
|
const skipElm = document.querySelector("#skip");
|
||||||
if (!buttons || !limitElm || !totalElm || !skipElm) return;
|
if (!buttons || !limitElm || !totalElm || !skipElm) return;
|
||||||
const skip = parseInt(skipElm.value);
|
const skip = parseInt(skipElm.value);
|
||||||
const limit = parseInt(limitElm.value);
|
const limit = parseInt(limitElm.value);
|
||||||
const total = parseInt(totalElm.value);
|
const total = parseInt(totalElm.value);
|
||||||
skipElm.value = action === "next" ? skip + limit : Math.max(skip - limit, 0);
|
skipElm.value = action === "next" ? skip + limit : Math.max(skip - limit, 0);
|
||||||
document.querySelectorAll('.pagination .next').forEach(elm => {
|
document.querySelectorAll(".pagination .next").forEach(elm => {
|
||||||
elm.disabled = total <= parseInt(skipElm.value) + limit;
|
elm.disabled = total <= parseInt(skipElm.value) + limit;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.pagination .prev').forEach(elm => {
|
document.querySelectorAll(".pagination .prev").forEach(elm => {
|
||||||
elm.disabled = parseInt(skipElm.value) <= 0;
|
elm.disabled = parseInt(skipElm.value) <= 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLinksNav() {
|
function updateLinksNav() {
|
||||||
const totalElm = document.querySelector('#total');
|
const totalElm = document.querySelector("#total");
|
||||||
const skipElm = document.querySelector('#skip');
|
const skipElm = document.querySelector("#skip");
|
||||||
const limitElm = document.querySelector('#limit');
|
const limitElm = document.querySelector("#limit");
|
||||||
if (!totalElm || !skipElm || !limitElm) return;
|
if (!totalElm || !skipElm || !limitElm) return;
|
||||||
const total = parseInt(totalElm.value);
|
const total = parseInt(totalElm.value);
|
||||||
const skip = parseInt(skipElm.value);
|
const skip = parseInt(skipElm.value);
|
||||||
const limit = parseInt(limitElm.value);
|
const limit = parseInt(limitElm.value);
|
||||||
document.querySelectorAll('.pagination .next').forEach(elm => {
|
document.querySelectorAll(".pagination .next").forEach(elm => {
|
||||||
elm.disabled = total <= skip + limit;
|
elm.disabled = total <= skip + limit;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.pagination .prev').forEach(elm => {
|
document.querySelectorAll(".pagination .prev").forEach(elm => {
|
||||||
elm.disabled = skip <= 0;
|
elm.disabled = skip <= 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetTableNav() {
|
function resetTableNav() {
|
||||||
const totalElm = document.querySelector('#total');
|
const totalElm = document.querySelector("#total");
|
||||||
const skipElm = document.querySelector('#skip');
|
const skipElm = document.querySelector("#skip");
|
||||||
const limitElm = document.querySelector('#limit');
|
const limitElm = document.querySelector("#limit");
|
||||||
if (!totalElm || !skipElm || !limitElm) return;
|
if (!totalElm || !skipElm || !limitElm) return;
|
||||||
skipElm.value = 0;
|
skipElm.value = 0;
|
||||||
limitElm.value = 10;
|
limitElm.value = 10;
|
||||||
const total = parseInt(totalElm.value);
|
const total = parseInt(totalElm.value);
|
||||||
const skip = parseInt(skipElm.value);
|
const skip = parseInt(skipElm.value);
|
||||||
const limit = parseInt(limitElm.value);
|
const limit = parseInt(limitElm.value);
|
||||||
document.querySelectorAll('.pagination .next').forEach(elm => {
|
document.querySelectorAll(".pagination .next").forEach(elm => {
|
||||||
elm.disabled = total <= skip + limit;
|
elm.disabled = total <= skip + limit;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.pagination .prev').forEach(elm => {
|
document.querySelectorAll(".pagination .prev").forEach(elm => {
|
||||||
elm.disabled = skip <= 0;
|
elm.disabled = skip <= 0;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('table .nav .limit button').forEach(b => {
|
document.querySelectorAll("table .nav .limit button").forEach(b => {
|
||||||
b.disabled = b.textContent === limit.toString();
|
b.disabled = b.textContent === limit.toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -261,43 +261,43 @@ onSearchInputLoad();
|
|||||||
|
|
||||||
// create user checkbox control
|
// create user checkbox control
|
||||||
function canSendVerificationEmail() {
|
function canSendVerificationEmail() {
|
||||||
const canSendVerificationEmail = !document.getElementById('create-user-verified').checked && !document.getElementById('create-user-banned').checked;
|
const canSendVerificationEmail = !document.getElementById("create-user-verified").checked && !document.getElementById("create-user-banned").checked;
|
||||||
const checkbox = document.getElementById('send-email-label');
|
const checkbox = document.getElementById("send-email-label");
|
||||||
if (canSendVerificationEmail)
|
if (canSendVerificationEmail)
|
||||||
checkbox.classList.remove('hidden');
|
checkbox.classList.remove("hidden");
|
||||||
if (!canSendVerificationEmail && !checkbox.classList.contains('hidden'))
|
if (!canSendVerificationEmail && !checkbox.classList.contains("hidden"))
|
||||||
checkbox.classList.add('hidden');
|
checkbox.classList.add("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
// htmx prefetch extension
|
// htmx prefetch extension
|
||||||
// https://github.com/bigskysoftware/htmx-extensions/blob/main/src/preload/README.md
|
// https://github.com/bigskysoftware/htmx-extensions/blob/main/src/preload/README.md
|
||||||
htmx.defineExtension('preload', {
|
htmx.defineExtension("preload", {
|
||||||
onEvent: function(name, event) {
|
onEvent: function(name, event) {
|
||||||
if (name !== 'htmx:afterProcessNode') {
|
if (name !== "htmx:afterProcessNode") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var attr = function(node, property) {
|
var attr = function(node, property) {
|
||||||
if (node == undefined) { return undefined }
|
if (node == undefined) { return undefined }
|
||||||
return node.getAttribute(property) || node.getAttribute('data-' + property) || attr(node.parentElement, property)
|
return node.getAttribute(property) || node.getAttribute("data-" + property) || attr(node.parentElement, property)
|
||||||
}
|
}
|
||||||
var load = function(node) {
|
var load = function(node) {
|
||||||
var done = function(html) {
|
var done = function(html) {
|
||||||
if (!node.preloadAlways) {
|
if (!node.preloadAlways) {
|
||||||
node.preloadState = 'DONE'
|
node.preloadState = "DONE"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr(node, 'preload-images') == 'true') {
|
if (attr(node, "preload-images") == "true") {
|
||||||
document.createElement('div').innerHTML = html
|
document.createElement("div").innerHTML = html
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
if (node.preloadState !== 'READY') {
|
if (node.preloadState !== "READY") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var hxGet = node.getAttribute('hx-get') || node.getAttribute('data-hx-get')
|
var hxGet = node.getAttribute("hx-get") || node.getAttribute("data-hx-get")
|
||||||
if (hxGet) {
|
if (hxGet) {
|
||||||
htmx.ajax('GET', hxGet, {
|
htmx.ajax("GET", hxGet, {
|
||||||
source: node,
|
source: node,
|
||||||
handler: function(elt, info) {
|
handler: function(elt, info) {
|
||||||
done(info.xhr.responseText)
|
done(info.xhr.responseText)
|
||||||
@ -305,30 +305,30 @@ htmx.defineExtension('preload', {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (node.getAttribute('href')) {
|
if (node.getAttribute("href")) {
|
||||||
var r = new XMLHttpRequest()
|
var r = new XMLHttpRequest()
|
||||||
r.open('GET', node.getAttribute('href'))
|
r.open("GET", node.getAttribute("href"))
|
||||||
r.onload = function() { done(r.responseText) }
|
r.onload = function() { done(r.responseText) }
|
||||||
r.send()
|
r.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var init = function(node) {
|
var init = function(node) {
|
||||||
if (node.getAttribute('href') + node.getAttribute('hx-get') + node.getAttribute('data-hx-get') == '') {
|
if (node.getAttribute("href") + node.getAttribute("hx-get") + node.getAttribute("data-hx-get") == "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (node.preloadState !== undefined) {
|
if (node.preloadState !== undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var on = attr(node, 'preload') || 'mousedown'
|
var on = attr(node, "preload") || "mousedown"
|
||||||
const always = on.indexOf('always') !== -1
|
const always = on.indexOf("always") !== -1
|
||||||
if (always) {
|
if (always) {
|
||||||
on = on.replace('always', '').trim()
|
on = on.replace("always", "").trim()
|
||||||
}
|
}
|
||||||
node.addEventListener(on, function(evt) {
|
node.addEventListener(on, function(evt) {
|
||||||
if (node.preloadState === 'PAUSE') {
|
if (node.preloadState === "PAUSE") {
|
||||||
node.preloadState = 'READY'
|
node.preloadState = "READY"
|
||||||
if (on === 'mouseover') {
|
if (on === "mouseover") {
|
||||||
window.setTimeout(load(node), 100)
|
window.setTimeout(load(node), 100)
|
||||||
} else {
|
} else {
|
||||||
load(node)()
|
load(node)()
|
||||||
@ -336,27 +336,27 @@ htmx.defineExtension('preload', {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
switch (on) {
|
switch (on) {
|
||||||
case 'mouseover':
|
case "mouseover":
|
||||||
node.addEventListener('touchstart', load(node))
|
node.addEventListener("touchstart", load(node))
|
||||||
node.addEventListener('mouseout', function(evt) {
|
node.addEventListener("mouseout", function(evt) {
|
||||||
if ((evt.target === node) && (node.preloadState === 'READY')) {
|
if ((evt.target === node) && (node.preloadState === "READY")) {
|
||||||
node.preloadState = 'PAUSE'
|
node.preloadState = "PAUSE"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'mousedown':
|
case "mousedown":
|
||||||
node.addEventListener('touchstart', load(node))
|
node.addEventListener("touchstart", load(node))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
node.preloadState = 'PAUSE'
|
node.preloadState = "PAUSE"
|
||||||
node.preloadAlways = always
|
node.preloadAlways = always
|
||||||
htmx.trigger(node, 'preload:init')
|
htmx.trigger(node, "preload:init")
|
||||||
}
|
}
|
||||||
const parent = event.target || event.detail.elt;
|
const parent = event.target || event.detail.elt;
|
||||||
parent.querySelectorAll("[preload]").forEach(function(node) {
|
parent.querySelectorAll("[preload]").forEach(function(node) {
|
||||||
init(node)
|
init(node)
|
||||||
node.querySelectorAll('a,[hx-get],[data-hx-get]').forEach(init)
|
node.querySelectorAll("a,[hx-get],[data-hx-get]").forEach(init)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
Loading…
x
Reference in New Issue
Block a user