160 lines
4.4 KiB
TypeScript
160 lines
4.4 KiB
TypeScript
import { ITrackable } from '@iqser/common-ui';
|
|
import type { IqserEventTarget, List } from '@iqser/common-ui/lib/utils';
|
|
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
|
import { Dayjs } from 'dayjs';
|
|
import { AbstractControl } from '@angular/forms';
|
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
|
|
export function hexToRgb(hex: string) {
|
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
return result
|
|
? {
|
|
r: parseInt(result[1], 16),
|
|
g: parseInt(result[2], 16),
|
|
b: parseInt(result[3], 16),
|
|
}
|
|
: null;
|
|
}
|
|
|
|
export function hexToRgba(hex: string, alpha: number) {
|
|
const rgb = hexToRgb(hex);
|
|
return rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : null;
|
|
}
|
|
|
|
export function getFirstRelevantTextPart(text: string, direction: 'FORWARD' | 'BACKWARD') {
|
|
let spaceCount = 0;
|
|
let accumulator = '';
|
|
const breakChars = [':', ' '];
|
|
|
|
const handle = (i: number) => {
|
|
const char = text[i];
|
|
if (breakChars.indexOf(char) >= 0) {
|
|
spaceCount += 1;
|
|
}
|
|
|
|
accumulator += char;
|
|
|
|
return spaceCount >= 3;
|
|
};
|
|
|
|
if (direction === 'FORWARD') {
|
|
for (let i = 0; i < text.length; i++) {
|
|
const shouldBreak = handle(i);
|
|
if (shouldBreak) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for (let i = text.length - 1; i >= 0; i--) {
|
|
const shouldBreak = handle(i);
|
|
if (shouldBreak) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (direction === 'BACKWARD') {
|
|
accumulator = accumulator.split('').reverse().join('');
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
export function lastIndexOfEnd(str: string, search: string) {
|
|
const io = str.lastIndexOf(search);
|
|
return io === -1 ? -1 : io + search.length;
|
|
}
|
|
|
|
export function toNumber(str: string) {
|
|
try {
|
|
return parseInt(`${str}`.replace(/\D/g, ''), 10);
|
|
} catch (e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
export function removeBraces(str: string): string {
|
|
return str.replace(/[{}]/g, '');
|
|
}
|
|
|
|
export function toSnakeCase(str: string): string {
|
|
return str
|
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
.replace(/[\s_]+/g, '_')
|
|
.toLowerCase();
|
|
}
|
|
|
|
export function compareLists(l1: string[], l2: string[]) {
|
|
if (l1.length !== l2.length) {
|
|
return true;
|
|
}
|
|
|
|
for (let idx = 0; idx < l1.length; ++idx) {
|
|
if (l1[idx] !== l2[idx]) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
export const byPage = (page: number) => (annotation: AnnotationWrapper) => annotation.pageNumber === page;
|
|
|
|
export function byId<T extends ITrackable>(id: string) {
|
|
return (item: T) => item.id === id;
|
|
}
|
|
|
|
export function getLast<T>(list: List<T>) {
|
|
return list[list.length - 1];
|
|
}
|
|
|
|
export const dateWithoutTime = (date: Dayjs) => date.set('h', 0).set('m', 0).set('s', 0).set('ms', 0);
|
|
|
|
export function hasChanges<T>(left: T, right: T) {
|
|
return JSON.stringify(left) !== JSON.stringify(right);
|
|
}
|
|
|
|
export function moveElementInArray<T>(array: T[], element: T, index: number) {
|
|
const result = array.filter(e => e !== element);
|
|
result.splice(index, 0, element);
|
|
return result;
|
|
}
|
|
|
|
export function calcTextWidthInPixels(text: string): number {
|
|
const temporaryElement = document.createElement('span');
|
|
document.body.appendChild(temporaryElement);
|
|
|
|
temporaryElement.style.font = 'times new roman';
|
|
temporaryElement.style.fontSize = 13 + 'px';
|
|
temporaryElement.style.height = 'auto';
|
|
temporaryElement.style.width = 'auto';
|
|
temporaryElement.style.position = 'absolute';
|
|
temporaryElement.style.whiteSpace = 'no-wrap';
|
|
temporaryElement.innerHTML = text;
|
|
|
|
const width = Math.ceil(temporaryElement.clientWidth);
|
|
document.body.removeChild(temporaryElement);
|
|
|
|
return width;
|
|
}
|
|
|
|
export function stringToBoolean(str: string): boolean {
|
|
return str === 'true';
|
|
}
|
|
|
|
export function urlFileId() {
|
|
const splitUrl = window.location.href.split('/');
|
|
const fileId = splitUrl[splitUrl.length - 1];
|
|
return fileId.split('?')[0];
|
|
}
|
|
|
|
export function formControlToSignal<T>(control: AbstractControl<T>) {
|
|
return toSignal(control.valueChanges, { initialValue: control.value });
|
|
}
|
|
|
|
export function isTargetInput(event: Event) {
|
|
return (event?.target as IqserEventTarget)?.localName === 'input';
|
|
}
|
|
|
|
export function isTargetTextArea(event: Event) {
|
|
return (event?.target as IqserEventTarget)?.localName === 'textarea';
|
|
}
|