Node package updates completed

This commit is contained in:
Colin Dawson 2026-01-31 22:08:33 +00:00
parent be964d195c
commit 01d6924dc4
5 changed files with 154 additions and 145 deletions

View File

@ -4,52 +4,52 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@ckeditor/ckeditor5-react": "^6.1.0", "@ckeditor/ckeditor5-react": "^10.0.0",
"@fortawesome/fontawesome-pro": "^6.5.0", "@fortawesome/fontawesome-pro": "^6.7.2",
"@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.2.1", "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/pro-duotone-svg-icons": "^6.5.0", "@fortawesome/pro-duotone-svg-icons": "^6.7.2",
"@fortawesome/pro-light-svg-icons": "^6.5.0", "@fortawesome/pro-light-svg-icons": "^6.7.2",
"@fortawesome/pro-regular-svg-icons": "^6.5.0", "@fortawesome/pro-regular-svg-icons": "^6.7.2",
"@fortawesome/pro-solid-svg-icons": "^6.5.0", "@fortawesome/pro-solid-svg-icons": "^6.7.2",
"@fortawesome/pro-thin-svg-icons": "^6.5.1", "@fortawesome/pro-thin-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.2",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^14.0.0", "@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.1", "@types/jest": "^29.5.14",
"@types/js-cookie": "^3.0.6", "@types/js-cookie": "^3.0.6",
"@types/lodash.debounce": "^4.0.7", "@types/lodash.debounce": "^4.0.9",
"@types/react": "^18.0.17", "@types/react": "^18.3.27",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.3.7",
"axios": "^1.4.0", "axios": "^1.7.9",
"bootstrap": "^5.3.0-alpha3", "bootstrap": "^5.3.8",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"ckeditor5": "^43.1.0", "ckeditor5": "^47.4.0",
"ckeditor5-premium-features": "^43.1.0", "ckeditor5-premium-features": "^47.4.0",
"concurrently": "^8.2.2", "concurrently": "^9.2.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"date-fns": "^2.30.0", "date-fns": "^4.1.0",
"html-react-parser": "^3.0.16", "html-react-parser": "^5.2.15",
"i18next": "^22.5.1", "i18next": "^25.8.0",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"joi": "^17.9.1", "joi": "^17.13.3",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"jwt-decode": "^3.1.2", "jwt-decode": "^4.0.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"nodemon": "^3.1.4", "nodemon": "^3.1.11",
"react": "^18.2.0", "react": "^18.3.1",
"react-bootstrap": "^2.7.4", "react-bootstrap": "^2.10.8",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-helmet-async": "^1.3.0", "react-helmet-async": "^2.0.5",
"react-i18next": "^12.3.1", "react-i18next": "^16.5.4",
"react-router-dom": "^6.10.0", "react-router-dom": "^7.13.0",
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
"react-toastify": "^9.1.2", "react-toastify": "^11.0.5",
"react-toggle": "^4.1.3", "react-toggle": "^4.1.3",
"runtime-env-cra": "^0.2.4", "runtime-env-cra": "^0.2.4",
"sass": "^1.62.0", "sass": "^1.97.3",
"web-vitals": "^3.3.1" "web-vitals": "^5.1.0"
}, },
"scripts": { "scripts": {
"build-css": "sass src/Sass/global.scss public/styles.css", "build-css": "sass src/Sass/global.scss public/styles.css",
@ -85,8 +85,8 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.2.3", "@types/node": "^22.13.5",
"@types/react-toggle": "^4.0.3", "@types/react-toggle": "^4.0.5",
"i18n-unused": "^0.19.0", "i18n-unused": "^0.19.0",
"i18next-parser": "^9.3.0", "i18next-parser": "^9.3.0",
"react-app-rewired": "^2.2.1", "react-app-rewired": "^2.2.1",

View File

@ -37,7 +37,7 @@ const CustomFieldsEditor: React.FC<CustomFieldsEditorProps> = ({
const columns: Column<CustomField>[] = useMemo( const columns: Column<CustomField>[] = useMemo(
() => [{ key: "name", label: t("Name"), order: "asc" }], () => [{ key: "name", label: t("Name"), order: "asc" }],
[], [t],
); );
const paginated: Paginated<CustomField> = useMemo( const paginated: Paginated<CustomField> = useMemo(

View File

@ -1,119 +1,127 @@
import { Plugin, Widget, toWidget, viewToModelPositionOutsideModelElement } from 'ckeditor5'; import {
import FieldCommand from './fieldcommand'; Plugin,
Widget,
toWidget,
viewToModelPositionOutsideModelElement,
} from "ckeditor5";
import FieldCommand from "./fieldcommand";
String.prototype.rtrim = function (s) { // Helper functions to avoid extending String prototype
if (s === undefined) const rtrim = (str, s) => {
s = '\\s'; if (s === undefined) s = "\\s";
return this.replace(new RegExp("[" + s + "]*$"), ''); return str.replace(new RegExp("[" + s + "]*$"), "");
}; };
String.prototype.ltrim = function (s) { const ltrim = (str, s) => {
if (s === undefined) if (s === undefined) s = "\\s";
s = '\\s'; return str.replace(new RegExp("^[" + s + "]*"), "");
return this.replace(new RegExp("^[" + s + "]*"), '');
}; };
export class FieldConfig{ export class FieldConfig {
fields = [ ] fields = [];
} }
export default class FieldEditing extends Plugin { export default class FieldEditing extends Plugin {
static get requires() { static get requires() {
return [ Widget ]; return [Widget];
} }
init() { init() {
this._defineSchema(); this._defineSchema();
this._defineConverters(); this._defineConverters();
this.editor.commands.add( 'field', new FieldCommand( this.editor ) ); this.editor.commands.add("field", new FieldCommand(this.editor));
this.editor.editing.mapper.on( this.editor.editing.mapper.on(
'viewToModelPosition', "viewToModelPosition",
viewToModelPositionOutsideModelElement( this.editor.model, viewElement => viewElement.hasClass( 'field' ) ) viewToModelPositionOutsideModelElement(this.editor.model, (viewElement) =>
); viewElement.hasClass("field"),
this.editor.config.define( 'fieldConfig', FieldConfig ); ),
} );
this.editor.config.define("fieldConfig", FieldConfig);
}
_defineSchema() { _defineSchema() {
const schema = this.editor.model.schema; const schema = this.editor.model.schema;
schema.register( 'field', { schema.register("field", {
// Behaves like a self-contained inline object (e.g. an inline image) // Behaves like a self-contained inline object (e.g. an inline image)
// allowed in places where $text is allowed (e.g. in paragraphs). // allowed in places where $text is allowed (e.g. in paragraphs).
// The inline widget can have the same attributes as text (for example linkHref, bold). // The inline widget can have the same attributes as text (for example linkHref, bold).
inheritAllFrom: '$inlineObject', inheritAllFrom: "$inlineObject",
// The field can have many types, like date, name, surname, etc: // The field can have many types, like date, name, surname, etc:
allowAttributes: [ 'field' ] allowAttributes: ["field"],
} ); });
} }
_defineConverters() { _defineConverters() {
const conversion = this.editor.conversion; const conversion = this.editor.conversion;
conversion.for( 'upcast' ).elementToElement( { conversion.for("upcast").elementToElement({
view: { view: {
name: 'span', name: "span",
classes: [ 'field' ] classes: ["field"],
}, },
model: (viewElement, conversionApi) => { model: (viewElement, conversionApi) => {
// Extract the "name" from "{name}". // Extract the "name" from "{name}".
if (viewElement === undefined) { if (viewElement === undefined) {
return null; return null;
}
const { writer } = conversionApi;
const name = viewElement.getChild(0)?._textData;
const fieldtype = viewElement.getAttribute("fieldtype");
const guid = viewElement.getAttribute("guid");
const fieldid = viewElement.getAttribute("fieldid");
const field = {
name,
type: fieldtype,
guid,
fieldid
};
return writer.createElement('field', { field });
}
} );
conversion.for( 'editingDowncast' ).elementToElement( {
model: 'field',
view: ( modelItem, { writer: viewWriter } ) => {
const widgetElement = createfieldView( modelItem, viewWriter );
// Enable widget handling on a field element inside the editing view.
return toWidget( widgetElement, viewWriter );
}
} );
conversion.for( 'dataDowncast' ).elementToElement( {
model: 'field',
view: ( modelItem, { writer: viewWriter } ) => createfieldView( modelItem, viewWriter )
} );
// Helper method for both downcast converters.
// function createfieldView( modelItem : Element, viewWriter : DowncastWriter ) {
function createfieldView( modelItem, viewWriter ) {
const field = modelItem.getAttribute( 'field' ); //todo any is a cop out.
const fieldView = viewWriter.createContainerElement( 'span', {
class: 'field',
fieldType: field.type,
guid: field.guid,
fieldid: (field.guid !== undefined) ? null : field.id
} );
// Insert the field name (as a text).
const innerText = viewWriter.createText( '{' + field.name.ltrim('{').rtrim('}') + '}' );
viewWriter.insert( viewWriter.createPositionAt( fieldView, 0 ), innerText );
return fieldView;
} }
const { writer } = conversionApi;
const name = viewElement.getChild(0)?._textData;
const fieldtype = viewElement.getAttribute("fieldtype");
const guid = viewElement.getAttribute("guid");
const fieldid = viewElement.getAttribute("fieldid");
const field = {
name,
type: fieldtype,
guid,
fieldid,
};
return writer.createElement("field", { field });
},
});
conversion.for("editingDowncast").elementToElement({
model: "field",
view: (modelItem, { writer: viewWriter }) => {
const widgetElement = createfieldView(modelItem, viewWriter);
// Enable widget handling on a field element inside the editing view.
return toWidget(widgetElement, viewWriter);
},
});
conversion.for("dataDowncast").elementToElement({
model: "field",
view: (modelItem, { writer: viewWriter }) =>
createfieldView(modelItem, viewWriter),
});
// Helper method for both downcast converters.
// function createfieldView( modelItem : Element, viewWriter : DowncastWriter ) {
function createfieldView(modelItem, viewWriter) {
const field = modelItem.getAttribute("field"); //todo any is a cop out.
const fieldView = viewWriter.createContainerElement("span", {
class: "field",
fieldType: field.type,
guid: field.guid,
fieldid: field.guid !== undefined ? null : field.id,
});
// Insert the field name (as a text).
const innerText = viewWriter.createText(
"{" + rtrim(ltrim(field.name, "{"), "}") + "}",
);
viewWriter.insert(viewWriter.createPositionAt(fieldView, 0), innerText);
return fieldView;
} }
} }
}

View File

@ -46,6 +46,7 @@ export default function BlockedIPs() {
useEffect(() => { useEffect(() => {
loadPage(pagedData.page, pagedData.pageSize); loadPage(pagedData.page, pagedData.pageSize);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // initial load only }, []); // initial load only
const handleSort = useCallback( const handleSort = useCallback(

View File

@ -1,4 +1,4 @@
import jwt_decode from "jwt-decode"; import { jwtDecode } from "jwt-decode";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import httpService from "../../../services/httpService"; import httpService from "../../../services/httpService";
import { IEmailUserAction } from "../models/IEmailUserAction"; import { IEmailUserAction } from "../models/IEmailUserAction";
@ -58,7 +58,7 @@ export function hasToken(): boolean {
export function tokenExpired(): boolean { export function tokenExpired(): boolean {
const jwt = getJwt(); const jwt = getJwt();
if (jwt) { if (jwt) {
const decodedToken: any = jwt_decode(jwt); const decodedToken: any = jwtDecode(jwt);
const expiry: Date = new Date(decodedToken.exp * 1000); const expiry: Date = new Date(decodedToken.exp * 1000);
const now: Date = new Date(Date.now()); const now: Date = new Date(Date.now());
@ -74,7 +74,7 @@ export function getCurrentUser(): JwtToken | null {
try { try {
const jwt = getJwt(); const jwt = getJwt();
if (jwt) { if (jwt) {
const decodedToken: any = jwt_decode(jwt); const decodedToken: any = jwtDecode(jwt);
const expiry: Date = new Date(decodedToken.exp * 1000); const expiry: Date = new Date(decodedToken.exp * 1000);
const now: Date = new Date(Date.now()); const now: Date = new Date(Date.now());