mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-11 18:26:04 +00:00
Initial commit
This commit is contained in:
37
assets/js/hooks/Mapper/utils/contextManager.ts
Normal file
37
assets/js/hooks/Mapper/utils/contextManager.ts
Normal 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();
|
||||
2
assets/js/hooks/Mapper/utils/contextStore/index.ts
Normal file
2
assets/js/hooks/Mapper/utils/contextStore/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './types';
|
||||
export * from './useContextStore.ts';
|
||||
23
assets/js/hooks/Mapper/utils/contextStore/types.ts
Normal file
23
assets/js/hooks/Mapper/utils/contextStore/types.ts
Normal 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;
|
||||
};
|
||||
80
assets/js/hooks/Mapper/utils/contextStore/useContextStore.ts
Normal file
80
assets/js/hooks/Mapper/utils/contextStore/useContextStore.ts
Normal 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 };
|
||||
};
|
||||
14
assets/js/hooks/Mapper/utils/decompressToJson.ts
Normal file
14
assets/js/hooks/Mapper/utils/decompressToJson.ts
Normal 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);
|
||||
};
|
||||
11
assets/js/hooks/Mapper/utils/getQueryVariable.ts
Normal file
11
assets/js/hooks/Mapper/utils/getQueryVariable.ts
Normal 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;
|
||||
};
|
||||
3
assets/js/hooks/Mapper/utils/index.ts
Normal file
3
assets/js/hooks/Mapper/utils/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './contextStore';
|
||||
export * from './decompressToJson';
|
||||
export * from './getQueryVariable';
|
||||
19
assets/js/hooks/Mapper/utils/kgToTons.ts
Normal file
19
assets/js/hooks/Mapper/utils/kgToTons.ts
Normal 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;
|
||||
};
|
||||
90
assets/js/hooks/Mapper/utils/labelsManager.ts
Normal file
90
assets/js/hooks/Mapper/utils/labelsManager.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user