Initial commit

This commit is contained in:
Dmitry Popov
2024-09-18 01:55:30 +04:00
parent 6a96a5f56e
commit 4136aaad76
1675 changed files with 124664 additions and 1 deletions

View File

@@ -0,0 +1,37 @@
import { ContextMenu } from 'primereact/contextmenu';
class ContextManager {
private prev: ContextMenu | null = null;
private prevId: string | null = null;
next(id: string | null, ctx: ContextMenu | null) {
if (id === null && this.prev !== null) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
this.prev.hide();
return;
}
if (this.prevId === id) {
return;
}
if (this.prev !== null && this.prevId !== id) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
this.prev.hide();
}
this.prev = ctx;
this.prevId = id;
}
reset() {
if (this.prev != null) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
this.prev.hide();
}
}
}
export const ctxManager = new ContextManager();

View File

@@ -0,0 +1,2 @@
export * from './types';
export * from './useContextStore.ts';

View File

@@ -0,0 +1,23 @@
export type AnyProperty<T> = T[keyof T];
export type PCDHandleBeforeUpdate<T> = (
newVal: AnyProperty<T>,
prev: AnyProperty<T>,
) => {
value: AnyProperty<T>;
prevent?: boolean;
} | void;
export type UpdateFunc<T> = (props: T) => Partial<T>;
export type ContextStoreDataUpdate<T> = (values: Partial<T> | UpdateFunc<T>, force?: boolean) => void;
export type ContextStoreDataOpts<T> = {
notNeedRerender?: boolean;
handleBeforeUpdate?: PCDHandleBeforeUpdate<T>;
onAfterAUpdate?: (values: Partial<T>) => void;
};
export type ProvideConstateDataReturnType<T> = {
update: ContextStoreDataUpdate<T>;
ref: T;
};

View File

@@ -0,0 +1,80 @@
import { useCallback, useRef, useState } from 'react';
import { ContextStoreDataOpts, ProvideConstateDataReturnType, ContextStoreDataUpdate } from './types';
export const useContextStore = <T>(
initialValue: T,
{ notNeedRerender = false, handleBeforeUpdate, onAfterAUpdate }: ContextStoreDataOpts<T> = {},
): ProvideConstateDataReturnType<T> => {
const ref = useRef<T>(initialValue);
const [, setRerenderKey] = useState(0);
const refWrapper = useRef({ notNeedRerender, handleBeforeUpdate, onAfterAUpdate });
refWrapper.current = { notNeedRerender, handleBeforeUpdate, onAfterAUpdate };
const update: ContextStoreDataUpdate<T> = useCallback((valOrFunc, force = false) => {
// It need to force prevent unnecessary rerendering
// update will create once
const { notNeedRerender, handleBeforeUpdate, onAfterAUpdate } = refWrapper.current;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const availableKeys = Object.keys(ref.current);
const values = typeof valOrFunc === 'function' ? valOrFunc(ref.current) : valOrFunc;
let callRerender = false;
Object.keys(values).forEach(key => {
if (!availableKeys.includes(key)) {
// TODO maybe need show error
return;
}
if (!handleBeforeUpdate || force) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref.current[key] = values[key];
// !notNeedRerender && setRerenderKey(x => x + 1);
if (!notNeedRerender) {
callRerender = true;
}
return;
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const updateResult = handleBeforeUpdate(values[key], ref.current[key]);
if (!updateResult) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref.current[key] = values[key];
// !notNeedRerender && setRerenderKey(x => x + 1);
if (!notNeedRerender) {
callRerender = true;
}
return;
}
if (updateResult?.prevent) {
return;
}
if (Object.keys(updateResult).includes('value')) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref.current[key] = updateResult.value;
// !notNeedRerender && setRerenderKey(x => x + 1);
if (!notNeedRerender) {
callRerender = true;
}
return;
}
});
if (callRerender) {
setRerenderKey(x => x + 1);
}
onAfterAUpdate?.(ref.current);
}, []);
return { update, ref: ref.current };
};

View File

@@ -0,0 +1,14 @@
import pako from 'pako';
export const decompressToJson = (base64string: string) => {
const base64_decoded = atob(base64string);
const charData = base64_decoded.split('').map(function (x) {
return x.charCodeAt(0);
});
const zlibData = new Uint8Array(charData);
const inflatedData = pako.inflate(zlibData, {
to: 'string',
});
return JSON.parse(inflatedData);
};

View File

@@ -0,0 +1,11 @@
export const getQueryVariable = (variable: string) => {
const query = window.location.search.substring(1);
const vars = query.split('&');
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=');
if (pair[0] == variable) {
return pair[1];
}
}
return false;
};

View File

@@ -0,0 +1,3 @@
export * from './contextStore';
export * from './decompressToJson';
export * from './getQueryVariable';

View File

@@ -0,0 +1,19 @@
const formatWithSpaces = (num: number): string => {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
};
export const kgToTons = (kg: number): string => {
const tons = kg / 1000;
let formattedTons: string;
if (tons >= 1000000) {
formattedTons = `${(tons / 1000000).toFixed(1)}M t`;
} else if (tons >= 100000) {
formattedTons = `${formatWithSpaces(Math.floor(tons))}k t`;
} else {
formattedTons = `${formatWithSpaces(parseFloat(tons.toFixed(3)))} t`;
}
return formattedTons;
};

View File

@@ -0,0 +1,90 @@
export type LabelsType = {
customLabel: string;
labels: string[];
};
export class LabelsManager {
protected labelsRaw: string;
protected parsedLabels: LabelsType = {
labels: [],
customLabel: '',
};
constructor(labels: string) {
this.labelsRaw = labels;
this.parsedLabels = this.parse();
}
parse(): LabelsType {
try {
return JSON.parse(this.labelsRaw) as LabelsType;
} catch (err) {
return {
customLabel: '',
labels: this.labelsRaw.split(','),
};
}
}
parse2(): LabelsType {
if (this.labelsRaw.length === 0) {
return {
labels: [],
customLabel: '',
};
}
const [labels, customLabel] = this.labelsRaw.split(':');
return {
labels: labels.split(','),
customLabel: customLabel ?? '',
};
}
toString() {
return JSON.stringify(this.parsedLabels);
}
toString2() {
return `${this.parsedLabels.labels.join(',')}`;
}
valueOf() {
return this.toString();
}
updateCustomLabel(label: string) {
this.parsedLabels.customLabel = label;
}
addLabels(labels: string[]) {
this.parsedLabels.labels = [...new Set([...this.parsedLabels.labels, ...labels])];
}
delLabels(labels: string[]) {
this.parsedLabels.labels = this.parsedLabels.labels.filter(x => !labels.includes(x));
}
hasLabel(label: string) {
return this.parsedLabels.labels.includes(label);
}
toggleLabel(label: string) {
if (this.parsedLabels.labels.includes(label)) {
this.delLabels([label]);
} else {
this.addLabels([label]);
}
}
clearLabels() {
this.parsedLabels.labels = [];
}
get customLabel() {
return this.parsedLabels.customLabel;
}
get list() {
return this.parsedLabels.labels;
}
}