red-ui/apps/red-ui/src/app/utils/functions.ts

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';
}