chore: copia de libs/shared con prefijo Pi y APIs de terceros actualizadas
This commit is contained in:
40
libs/ui/src/lib/util/affix/affix.directive.ts
Normal file
40
libs/ui/src/lib/util/affix/affix.directive.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Directive, ElementRef, HostBinding, Input, OnInit, Renderer2 } from '@angular/core';
|
||||
import { unit } from '../models';
|
||||
|
||||
@Directive()
|
||||
export abstract class PiBaseAffixDirective implements OnInit {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return ['pi-affix', `pi-affix__appearance--${this.appearance}`].join(' ');
|
||||
}
|
||||
|
||||
@Input() unit: unit | string | undefined;
|
||||
@Input() appearance: 'ghost' | 'fill' = 'ghost';
|
||||
|
||||
constructor(private renderer: Renderer2, private el: ElementRef) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.unit) {
|
||||
const span = this.renderer.createElement('span');
|
||||
const text = this.renderer.createText(this.unit);
|
||||
|
||||
this.renderer.appendChild(span, text);
|
||||
this.renderer.appendChild(this.el.nativeElement, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: 'pi-prefix',
|
||||
})
|
||||
export class PiPrefixDirective extends PiBaseAffixDirective {
|
||||
@HostBinding('class') className = 'pi-affix__prefix';
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: 'pi-suffix',
|
||||
})
|
||||
export class PiSuffixDirective extends PiBaseAffixDirective {
|
||||
@HostBinding('class') className = 'pi-affix__suffix';
|
||||
}
|
||||
3
libs/ui/src/lib/util/affix/index.ts
Normal file
3
libs/ui/src/lib/util/affix/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './affix.directive';
|
||||
|
||||
export * from './util-affix.module';
|
||||
10
libs/ui/src/lib/util/affix/util-affix.module.ts
Normal file
10
libs/ui/src/lib/util/affix/util-affix.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { PiPrefixDirective, PiSuffixDirective } from './affix.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [PiPrefixDirective, PiSuffixDirective],
|
||||
exports: [PiPrefixDirective, PiSuffixDirective],
|
||||
})
|
||||
export class PiSharedUtilAffixModule {}
|
||||
44
libs/ui/src/lib/util/amplitude/amplitude.service.ts
Normal file
44
libs/ui/src/lib/util/amplitude/amplitude.service.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AmplitudeService {
|
||||
private amp: any;
|
||||
private ampEnabled = false;
|
||||
|
||||
constructor(@Inject(PLATFORM_ID) public platformId: object) {
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
this.amp = (window as any).amplitude;
|
||||
if (this.amp) this.ampEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
trackEvent(eventName: string, extraParam?: any): void {
|
||||
if (!this.ampEnabled) {
|
||||
this.enableCheck();
|
||||
return;
|
||||
}
|
||||
this.amp.logEvent(eventName, extraParam);
|
||||
console.log('Event tracked: ', eventName, extraParam);
|
||||
}
|
||||
|
||||
identifyUser(tag: string, data: unknown): void {
|
||||
const identify1: unknown = new this.amp.Identify().set(tag, data);
|
||||
this.amp.identify(identify1);
|
||||
}
|
||||
|
||||
identifyUserMultiple(data: unknown): void {
|
||||
const identify: unknown = new this.amp.setUserProperties(data);
|
||||
this.amp.identify(identify);
|
||||
}
|
||||
|
||||
setUserId(userId: string): void {
|
||||
this.amp.setUserId(userId);
|
||||
}
|
||||
|
||||
private enableCheck(): void {
|
||||
if (!this.ampEnabled) console.log('Amplitude is not working');
|
||||
}
|
||||
}
|
||||
70
libs/ui/src/lib/util/amplitude/events.ts
Normal file
70
libs/ui/src/lib/util/amplitude/events.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
export const AMP_EVENTS: Record <string, string> = {
|
||||
// PUBLIC EVENTS
|
||||
APP_OPENED: 'App Opened',
|
||||
GOOGLE_SIGNIN_SUCCESS: 'Sign in with Google Success',
|
||||
LOGIN_SUCCESS: 'Login Success',
|
||||
USER_REGISTERED: 'User Registered',
|
||||
WEB_OPENED: 'Web Opened',
|
||||
|
||||
// AUTHENTICATION
|
||||
EMAIL_PASSWORD_PAGE_VIEWED: 'Email and Password Page Viewed',
|
||||
PERSONAL_INFORMATION_PAGE_VIEWED: 'Personal Information and User Type Page Viewed',
|
||||
PERSONAL_INFO_UPDATED: 'Personal Information Updated',
|
||||
|
||||
// PRIVATE EVENTS
|
||||
// COMPANY FORM
|
||||
COMPANY_DETAILS_VIEWED: 'Company Details Viewed',
|
||||
COMPANY_LIST_VIEWED: 'Company List Viewed',
|
||||
COMPANY_MODIFIED: 'Company Modified',
|
||||
COMPANY_REGISTERED: 'Company Registered',
|
||||
|
||||
// DEALS
|
||||
CONNECTED_COMPANY: 'Connected Company',
|
||||
DEAL_ACCEPTED: 'Deal Accepted',
|
||||
DEAL_VIEWED: 'Deal Viewed',
|
||||
DEALBOX_VIEWED: 'Dealbox Viewed',
|
||||
|
||||
// QA
|
||||
QA_SESSION_CREATED: 'QA Session Created',
|
||||
QUESTION_ADDED: 'Question Added',
|
||||
QUESTION_ANSWERED: 'Question Answered',
|
||||
QUESTIONS_SENT: 'Questions Sent',
|
||||
ANSWERS_SENT: 'Answers Sent',
|
||||
|
||||
|
||||
// INVESTOR FORM
|
||||
SUBSCRIBE: 'Subscribe',
|
||||
SUBSCRIBE_PRICING_PAGE_VIEWED: 'Subscribe Pricing Page Viewed',
|
||||
USER_SUBSCRIBED: 'User Subscribed',
|
||||
THESIS_SAVED: 'Thesis Saved',
|
||||
THESIS_FORM_VIEWED: 'Thesis Form Viewed',
|
||||
SUBSCRIBE_PRICING_VIEW: 'Subscribe Pricing Page Viewed',
|
||||
|
||||
// COMPANY PUBLIC
|
||||
BASIC_PANEL_SAVED: 'Basic Panel Saved',
|
||||
PROFIT_LOSS_PANEL_SAVED: ' Profit And Loss Panel Saved',
|
||||
BALANCE_PANEL_SAVED: 'Balance Panel Saved',
|
||||
BUSINESS_PLAN_PANEL_SAVED: 'Business Plan Panel Saved',
|
||||
TEAM_PANEL_SAVED: 'Team Panel Saved',
|
||||
INVESTMENT_TRANSACTION_SAVED: 'Investment Transaction Panel Saved',
|
||||
PRODUCTS_CLIENTS_SAVED: 'Products And Clients Panel Saved',
|
||||
MY_COMPANY_OPENED: 'My Company Opened',
|
||||
|
||||
TEASER_TYPEFORM_OPENED: 'Teaser Typeform Opened',
|
||||
TEASER_TYPEFORM_MODAL_OPENED: 'Teaser Typeform Modal Opened',
|
||||
TEASER_TYPEFORM_MODAL_CLOSED: 'Teaser Typeform Modal Closed',
|
||||
|
||||
// INVESTOR LIST
|
||||
INVESTOR_LIST_VIEWED: 'Investor List Viewed',
|
||||
TEASER_DOWNLOADED: 'Teaser Downloaded',
|
||||
|
||||
// ADVISOR
|
||||
ADVISOR_COMPANY_CREATION_FORM_PAGE_VIEWED: 'Advisor Company Creation Form Page Viewed',
|
||||
ADVISOR_COMPANY_REGISTERED: 'Advisor Company Registered',
|
||||
ADVISOR_COMPANY_MODIFIED: 'Advisor Company Modified',
|
||||
|
||||
|
||||
// WEB
|
||||
VALORAR_MI_EMPRESA_TYPEFORM_MODAL_OPENED: 'Valorar Mi Empresa Typeform Modal Opened',
|
||||
VENDER_MI_EMPRESA_TYPEFORM_MODAL_OPENED: 'Vender Mi Empresa Typeform Modal Opened'
|
||||
};
|
||||
5
libs/ui/src/lib/util/amplitude/index.ts
Normal file
5
libs/ui/src/lib/util/amplitude/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// Amplitude services
|
||||
export * from './amplitude.service';
|
||||
|
||||
// Events
|
||||
export * from './events';
|
||||
116
libs/ui/src/lib/util/color/directives/colors.directive.ts
Normal file
116
libs/ui/src/lib/util/color/directives/colors.directive.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { Directive, HostBinding, Input, OnInit } from '@angular/core';
|
||||
import { density, mode, opacity, styleType } from '../../../styles';
|
||||
|
||||
@Directive()
|
||||
export abstract class PiBaseColor implements OnInit {
|
||||
@HostBinding('class') get commonClasses(): string {
|
||||
return [this.densityClass, this.modeClass].join(' ');
|
||||
}
|
||||
@Input() density: density = '';
|
||||
@Input() opacity: opacity = '100';
|
||||
@Input() mode: mode = 'dark';
|
||||
|
||||
ngOnInit(): void {
|
||||
this.densityClass;
|
||||
}
|
||||
protected get densityClass(): string {
|
||||
return !!this.density ? `pi-color__density--${this.density}` : '';
|
||||
}
|
||||
protected get modeClass(): string {
|
||||
return this.mode && `pi-color__mode--${this.mode}`;
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-dynamic-color]',
|
||||
})
|
||||
export class PiDynamicColorDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return this.colorClass;
|
||||
}
|
||||
|
||||
@Input() color!: styleType;
|
||||
|
||||
protected get colorClass(): string {
|
||||
return !!this.color && `pi-color__${this.color}`;
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-primary]',
|
||||
})
|
||||
export class PiColorPrimaryDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__primary';
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-accent]',
|
||||
})
|
||||
export class PiColorAccentDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__accent';
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-warn]',
|
||||
})
|
||||
export class PiColorWarnDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__warn';
|
||||
}
|
||||
}
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-success]',
|
||||
})
|
||||
export class PiColorSuccessDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__success';
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-highlighted]',
|
||||
})
|
||||
export class PiColorHighlightedDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__highlighted';
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-white]',
|
||||
})
|
||||
export class PiColorWhiteDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__white';
|
||||
}
|
||||
}
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-grey]',
|
||||
})
|
||||
export class PiColorGreyDirective extends PiBaseColor {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__grey';
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-black]',
|
||||
})
|
||||
export class PiColorBlackDirective {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-color__black';
|
||||
}
|
||||
}
|
||||
1
libs/ui/src/lib/util/color/entities/color.type.ts
Normal file
1
libs/ui/src/lib/util/color/entities/color.type.ts
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
libs/ui/src/lib/util/color/index.ts
Normal file
3
libs/ui/src/lib/util/color/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './util-color.module';
|
||||
|
||||
export * from './directives/colors.directive';
|
||||
42
libs/ui/src/lib/util/color/util-color.module.ts
Normal file
42
libs/ui/src/lib/util/color/util-color.module.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import {
|
||||
PiColorAccentDirective,
|
||||
PiColorBlackDirective,
|
||||
PiColorWarnDirective,
|
||||
PiColorGreyDirective,
|
||||
PiColorHighlightedDirective,
|
||||
PiColorPrimaryDirective,
|
||||
PiColorSuccessDirective,
|
||||
PiColorWhiteDirective,
|
||||
PiDynamicColorDirective,
|
||||
} from './directives/colors.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule],
|
||||
declarations: [
|
||||
PiDynamicColorDirective,
|
||||
PiColorPrimaryDirective,
|
||||
PiColorAccentDirective,
|
||||
PiColorSuccessDirective,
|
||||
PiColorWarnDirective,
|
||||
PiColorHighlightedDirective,
|
||||
PiColorWhiteDirective,
|
||||
PiColorGreyDirective,
|
||||
PiColorBlackDirective,
|
||||
],
|
||||
exports: [
|
||||
PiDynamicColorDirective,
|
||||
PiColorPrimaryDirective,
|
||||
PiColorAccentDirective,
|
||||
PiColorSuccessDirective,
|
||||
PiColorWarnDirective,
|
||||
PiColorHighlightedDirective,
|
||||
PiColorWhiteDirective,
|
||||
PiColorGreyDirective,
|
||||
PiColorBlackDirective,
|
||||
],
|
||||
})
|
||||
export class PiSharedUtilColorModule {}
|
||||
159
libs/ui/src/lib/util/common/common.ts
Normal file
159
libs/ui/src/lib/util/common/common.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
// Angular
|
||||
import { HttpParams } from '@angular/common/http';
|
||||
import { Inject, PLATFORM_ID } from '@angular/core';
|
||||
|
||||
// Shared
|
||||
import { Params } from '../models';
|
||||
import { timer } from 'rxjs';
|
||||
export class Commons {
|
||||
constructor(@Inject(PLATFORM_ID) public platformId: object) {}
|
||||
|
||||
static followUrl($event: MouseEvent, item: { url: string }): void {
|
||||
Commons.followExternalUrl($event, item);
|
||||
}
|
||||
|
||||
static followExternalUrl(
|
||||
$event: MouseEvent,
|
||||
item: { url: string; externalLink?: boolean }
|
||||
): void {
|
||||
if (
|
||||
item &&
|
||||
item.url &&
|
||||
(item.externalLink || $event.button === 1 || ($event.button === 0 && $event.ctrlKey))
|
||||
) {
|
||||
Commons.openExternalUrl(item.url);
|
||||
}
|
||||
}
|
||||
|
||||
static openExternalSelfUrl(url: string): void {
|
||||
Commons.openExternalUrl(url, '_self');
|
||||
}
|
||||
|
||||
static openExternalUrlWithoutParams(url: string, target?: string): void {
|
||||
window.open(url, target || '_blank');
|
||||
}
|
||||
|
||||
|
||||
static openExternalUrl(url: string, target?: string): void {
|
||||
window.open(url + window.location.search, target || '_blank');
|
||||
}
|
||||
|
||||
static downloadPDFBase64(pdf: string, name: string): void {
|
||||
const linkSource = `data:application/pdf;base64,${pdf}`;
|
||||
const downloadLink: HTMLAnchorElement = document.createElement('a');
|
||||
const fileName: string = name;
|
||||
downloadLink.href = linkSource;
|
||||
downloadLink.download = fileName;
|
||||
downloadLink.click();
|
||||
}
|
||||
|
||||
static downloadPDF(url: string, name: string, target?: string): void {
|
||||
const targetLink = target || '_self';
|
||||
let link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = name;
|
||||
link.target = targetLink;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
link = null;
|
||||
}
|
||||
|
||||
static getDefaultLanguage(): string {
|
||||
return navigator.language.split('-')[0] as string;
|
||||
}
|
||||
|
||||
static getFullName(user: { name: string; lastName: string }): string {
|
||||
if (!user || !user.name) {
|
||||
return ' ';
|
||||
}
|
||||
if (!user.lastName) {
|
||||
return user.name;
|
||||
}
|
||||
return `${user.name} ${user.lastName}`;
|
||||
}
|
||||
|
||||
static setParamsToQueryUrl(obj: Params): string {
|
||||
let params: string = '';
|
||||
for (const key in obj) {
|
||||
if (obj[key]) {
|
||||
const element = obj[key];
|
||||
params = params + '&' + key + '=' + element;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
static isEmpty(obj: unknown): boolean {
|
||||
if (!obj) {
|
||||
return true;
|
||||
}
|
||||
return JSON.stringify(obj) === JSON.stringify({});
|
||||
}
|
||||
|
||||
static isNotEmpty(obj: unknown): boolean {
|
||||
return !this.isEmpty(obj);
|
||||
}
|
||||
|
||||
static isStringEmpty = (str: string) => !str?.length;
|
||||
|
||||
static buildRangeString(
|
||||
minValue: number,
|
||||
maxValue: number,
|
||||
unit: string,
|
||||
defaultLocale?: string
|
||||
): string {
|
||||
if (!!minValue && !!maxValue) {
|
||||
return `${minValue}${unit} - ${maxValue}${unit}`;
|
||||
}
|
||||
if (!!minValue) {
|
||||
return `>${minValue}${unit}`;
|
||||
}
|
||||
if (!!maxValue) {
|
||||
return `<${maxValue}${unit}`;
|
||||
}
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
static removeEmptyValuesFromObject(obj: unknown): unknown {
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).filter(
|
||||
([_, v]) => v != null && v !== '' && (v as Array<string>).length !== 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
static removeNullValuesFromQueryParams(params: HttpParams) {
|
||||
const paramsKeysAux = params.keys();
|
||||
paramsKeysAux.forEach((key) => {
|
||||
const value = params.get(key);
|
||||
if (value === null || value === undefined || value === '' || value === 'null') {
|
||||
params['map'].delete(key);
|
||||
}
|
||||
});
|
||||
return params;
|
||||
}
|
||||
|
||||
static removeDiacriticsFromString(str: string): string {
|
||||
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
}
|
||||
|
||||
static getScrollParent(node: HTMLElement): HTMLElement {
|
||||
if (node == null) {
|
||||
return null;
|
||||
}
|
||||
if (node.scrollHeight > node.clientHeight) {
|
||||
return node;
|
||||
} else {
|
||||
return this.getScrollParent(node.parentNode as HTMLElement);
|
||||
}
|
||||
}
|
||||
|
||||
static createIntervalUsingTimer(delayValue1: number, delayValue2: number) {
|
||||
return timer(delayValue1, delayValue2);
|
||||
}
|
||||
|
||||
static isNotNullish(value: unknown): boolean {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
}
|
||||
4
libs/ui/src/lib/util/common/index.ts
Normal file
4
libs/ui/src/lib/util/common/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// Common
|
||||
export * from './common';
|
||||
export * from './sector';
|
||||
export * from './select-options';
|
||||
26
libs/ui/src/lib/util/common/sector.ts
Normal file
26
libs/ui/src/lib/util/common/sector.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// Angular
|
||||
import { Inject, PLATFORM_ID } from '@angular/core';
|
||||
import { Sector } from '../models';
|
||||
import { SectorType, SectorUidMatchLocale } from '../models';
|
||||
|
||||
export class SectorCommons {
|
||||
constructor(@Inject(PLATFORM_ID) public platformId: object) {}
|
||||
|
||||
static getSectorLocaleFromUid(uid: string): string {
|
||||
const sectorLocale: string = SectorUidMatchLocale[uid as SectorType];
|
||||
return `common.sectors.${sectorLocale}`;
|
||||
}
|
||||
|
||||
static getLocaleListFromUidList(sectorUids: Array<string>): Array<string> {
|
||||
return sectorUids?.map((uid) => SectorCommons.getSectorLocaleFromUid(uid));
|
||||
}
|
||||
|
||||
static convertUidListToSectorList(sectorUids: Array<string>, sectors: Array<Sector>): Array<Sector> {
|
||||
return sectors?.filter((sector) => sectorUids?.includes(sector.sectorUid));
|
||||
}
|
||||
|
||||
static convertSectorListToUidList(sectors: Array<Sector>): Array<string> {
|
||||
return sectors?.map((sector) => sector?.sectorUid);
|
||||
}
|
||||
}
|
||||
|
||||
21
libs/ui/src/lib/util/common/select-options.ts
Normal file
21
libs/ui/src/lib/util/common/select-options.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Inject, PLATFORM_ID } from '@angular/core';
|
||||
import { SelectOption } from '../../ui/select';
|
||||
|
||||
export class SelectOptionsCommons {
|
||||
constructor(@Inject(PLATFORM_ID) public platformId: object) {}
|
||||
|
||||
static convertStringstoSelectOptions(
|
||||
values: Array<any>,
|
||||
options: Array<SelectOption>
|
||||
): Array<SelectOption> {
|
||||
return options?.filter((item) => values?.includes(item.value));
|
||||
}
|
||||
|
||||
static convertSelectOptionstoStrings(options: Array<SelectOption>): Array<any> {
|
||||
return options?.map((item) => item?.value);
|
||||
}
|
||||
|
||||
static getSelectOptionValue(value: string, options: Array<any>): any {
|
||||
return options?.find((item) => item?.value == value);
|
||||
}
|
||||
}
|
||||
1
libs/ui/src/lib/util/dato-cms/graphql.module.ts
Normal file
1
libs/ui/src/lib/util/dato-cms/graphql.module.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const datoCms = "https://graphql.datocms.com/"; // our GraphQL API
|
||||
1
libs/ui/src/lib/util/dato-cms/index.ts
Normal file
1
libs/ui/src/lib/util/dato-cms/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './util-dato-cms.module';
|
||||
36
libs/ui/src/lib/util/dato-cms/util-dato-cms.module.ts
Normal file
36
libs/ui/src/lib/util/dato-cms/util-dato-cms.module.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
|
||||
|
||||
// Apollo
|
||||
import { InMemoryCache } from '@apollo/client/core';
|
||||
import { APOLLO_OPTIONS } from 'apollo-angular';
|
||||
import { HttpLink } from 'apollo-angular/http';
|
||||
|
||||
// Shared
|
||||
import { environment } from '../environments';
|
||||
|
||||
// datoCMS
|
||||
import { datoCms } from './graphql.module';
|
||||
|
||||
/**
|
||||
* Sustituye a `PiSharedUtilDatoCmsModule`: apollo-angular ya no expone
|
||||
* `ApolloModule`, la configuración se hace con providers.
|
||||
*/
|
||||
export function providePiDatoCms(): EnvironmentProviders {
|
||||
return makeEnvironmentProviders([
|
||||
{
|
||||
provide: APOLLO_OPTIONS,
|
||||
useFactory: (httpLink: HttpLink) => {
|
||||
return {
|
||||
cache: new InMemoryCache(),
|
||||
link: httpLink.create({
|
||||
uri: datoCms,
|
||||
headers: {
|
||||
Authorization: environment.DATO_KEY,
|
||||
} as any,
|
||||
}),
|
||||
};
|
||||
},
|
||||
deps: [HttpLink],
|
||||
},
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Angular
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// Ngrx
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
// Rxjs
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// State
|
||||
import { Browser, Device, Size } from '../entities/device-configs.model';
|
||||
import * as fromActions from '../state/device-configs.actions';
|
||||
import * as fromState from '../state/device-configs.reducer';
|
||||
import * as fromSelectors from '../state/device-configs.selectors';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DeviceConfigsFacade {
|
||||
// Device
|
||||
readonly device$: Observable<Device> = this.store.select(fromSelectors.getDevice);
|
||||
readonly size$: Observable<Size> = this.store.select(fromSelectors.getSize);
|
||||
readonly isSmallDevice$: Observable<boolean> = this.store.select(fromSelectors.getIsSmallDevice);
|
||||
|
||||
// Browser
|
||||
readonly browser$: Observable<Browser> = this.store.select(fromSelectors.getBrowser);
|
||||
|
||||
constructor(private store: Store<fromState.DeviceConfigsState>) {}
|
||||
|
||||
getBrowser(): void {
|
||||
this.store.dispatch(fromActions.BrowserActions.getBrowser());
|
||||
}
|
||||
|
||||
setDevice(device: Device): void {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceType({ device }));
|
||||
}
|
||||
}
|
||||
19
libs/ui/src/lib/util/device-configs/entities/breakpoints.ts
Normal file
19
libs/ui/src/lib/util/device-configs/entities/breakpoints.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// BreakPoint Observer
|
||||
// Main Breakpoints
|
||||
export const MaxMobileBreakpoint = '(max-width: 640px)';
|
||||
export const MinTabletBreakpoint = '(min-width: 640px)';
|
||||
export const MaxTabletBreakpoint = '(max-width: 1240px)';
|
||||
export const MinDesktopBreakpoint = '(min-width: 1240px)';
|
||||
|
||||
// Inner Breakpoints
|
||||
export const MinTabletSmallBreakpoint = '(min-width: 640px)';
|
||||
export const MaxTabletSmallBreakpoint = '(max-width: 992px)';
|
||||
export const MinTabletLargeBreakpoint = '(min-width: 992px)';
|
||||
export const MaxTabletLargeBreakpoint = '(max-width: 1240px)';
|
||||
|
||||
export const MinDesktopSmallBreakpoint = '(min-width: 1240px)';
|
||||
export const MaxDesktopSmallBreakpoint = '(max-width: 1440px)';
|
||||
export const MinDesktopMediumBreakpoint = '(min-width: 1440px)';
|
||||
export const MaxDesktopMediumBreakpoint = '(max-width: 1920px)';
|
||||
|
||||
export const MinDesktopLargeBreakpoint = '(min-width: 1920px)';
|
||||
@@ -0,0 +1,5 @@
|
||||
export type Device = 'MOBILE' | 'TABLET' | 'DESKTOP';
|
||||
|
||||
export type Size = 'SMALL' | 'MEDIUM' | 'LARGE';
|
||||
|
||||
export type Browser = 'EXPLORER' | 'FIREFOX' | 'EDGE' | 'CHROME' | 'SAFARI' | 'UNKNOWN';
|
||||
18
libs/ui/src/lib/util/device-configs/index.ts
Normal file
18
libs/ui/src/lib/util/device-configs/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Application
|
||||
export * from './application/device-configs.facade';
|
||||
|
||||
// Entities
|
||||
export * from './entities/breakpoints';
|
||||
export * from './entities/device-configs.model';
|
||||
|
||||
// Services
|
||||
export * from './services/device-configs.service';
|
||||
|
||||
// State
|
||||
export * from './state/device-configs.actions';
|
||||
export * from './state/device-configs.effects';
|
||||
export * from './state/device-configs.selectors';
|
||||
export * from './state/device-configs.reducer';
|
||||
import * as DeviceTypeActions from './state/device-configs.actions';
|
||||
import * as DeviceTypeSelectors from './state/device-configs.selectors';
|
||||
export { DeviceTypeActions, DeviceTypeSelectors };
|
||||
@@ -0,0 +1,176 @@
|
||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
// Entities
|
||||
import {
|
||||
MaxDesktopMediumBreakpoint,
|
||||
MaxDesktopSmallBreakpoint,
|
||||
MaxMobileBreakpoint,
|
||||
MaxTabletBreakpoint,
|
||||
MaxTabletLargeBreakpoint,
|
||||
MaxTabletSmallBreakpoint,
|
||||
MinDesktopBreakpoint,
|
||||
MinDesktopLargeBreakpoint,
|
||||
MinDesktopMediumBreakpoint,
|
||||
MinDesktopSmallBreakpoint,
|
||||
MinTabletBreakpoint,
|
||||
MinTabletLargeBreakpoint,
|
||||
MinTabletSmallBreakpoint,
|
||||
} from '../entities/breakpoints';
|
||||
import { Browser } from '../entities/device-configs.model';
|
||||
|
||||
// State
|
||||
import * as fromActions from '../state/device-configs.actions';
|
||||
import { DeviceConfigsState } from '../state/device-configs.reducer';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DeviceConfigsService {
|
||||
private htmlTag!: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private store: Store<DeviceConfigsState>,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
@Inject(PLATFORM_ID) public platformId: Object
|
||||
) {
|
||||
this.deviceConfigsHandler();
|
||||
}
|
||||
|
||||
getUserBrowser(): Browser {
|
||||
const userAgent = window.navigator.userAgent;
|
||||
if (/MSIE|Trident/.test(userAgent)) {
|
||||
return 'EXPLORER';
|
||||
} else if (/Firefox/.test(userAgent)) {
|
||||
return'FIREFOX';
|
||||
} else if (/Edg|Edge/.test(userAgent)) {
|
||||
return 'EDGE';
|
||||
} else if (/Chrome/.test(userAgent) && !/Edg|Edge/.test(userAgent)) {
|
||||
return 'CHROME';
|
||||
} else if (/Safari/.test(userAgent) && !/Edg|Edge/.test(userAgent)) {
|
||||
return 'SAFARI';
|
||||
} else {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
}
|
||||
|
||||
private deviceConfigsHandler(): void {
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
this.htmlTag = this.document?.documentElement;
|
||||
this.breakpointObserver
|
||||
.observe([
|
||||
MaxMobileBreakpoint,
|
||||
MinTabletBreakpoint,
|
||||
MaxTabletBreakpoint,
|
||||
MinDesktopBreakpoint,
|
||||
// Inner
|
||||
MinTabletSmallBreakpoint,
|
||||
MaxTabletSmallBreakpoint,
|
||||
MinTabletLargeBreakpoint,
|
||||
MaxTabletLargeBreakpoint,
|
||||
MinDesktopSmallBreakpoint,
|
||||
MaxDesktopSmallBreakpoint,
|
||||
MinDesktopMediumBreakpoint,
|
||||
MaxDesktopMediumBreakpoint,
|
||||
MinDesktopLargeBreakpoint,
|
||||
])
|
||||
.subscribe((result) => {
|
||||
if (result.matches) {
|
||||
// Mobile
|
||||
if (result.breakpoints[MaxMobileBreakpoint]) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceType({ device: 'MOBILE' }));
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'SMALL' }));
|
||||
this.setClassIsMobile();
|
||||
}
|
||||
// Tablet
|
||||
if (
|
||||
result.breakpoints[MinTabletBreakpoint] &&
|
||||
result.breakpoints[MaxTabletBreakpoint]
|
||||
) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceType({ device: 'TABLET' }));
|
||||
this.setClassIsTablet();
|
||||
// Tablet S
|
||||
if (
|
||||
result.breakpoints[MinTabletSmallBreakpoint] &&
|
||||
result.breakpoints[MaxTabletSmallBreakpoint]
|
||||
) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'SMALL' }));
|
||||
this.setClassIsTabletSmall();
|
||||
}
|
||||
// Tablet L
|
||||
if (
|
||||
result.breakpoints[MinTabletLargeBreakpoint] &&
|
||||
result.breakpoints[MaxTabletLargeBreakpoint]
|
||||
) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'LARGE' }));
|
||||
this.setClassIsTabletLarge();
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop
|
||||
if (result.breakpoints[MinDesktopBreakpoint]) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceType({ device: 'DESKTOP' }));
|
||||
this.setClassIsDesktop();
|
||||
// Desktop S
|
||||
if (
|
||||
result.breakpoints[MinDesktopSmallBreakpoint] &&
|
||||
result.breakpoints[MaxDesktopSmallBreakpoint]
|
||||
) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'SMALL' }));
|
||||
this.setClassIsDesktopSmall();
|
||||
}
|
||||
// Desktop M
|
||||
if (
|
||||
result.breakpoints[MinDesktopMediumBreakpoint] &&
|
||||
result.breakpoints[MaxDesktopMediumBreakpoint]
|
||||
) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'MEDIUM' }));
|
||||
this.setClassIsDesktopMedium();
|
||||
}
|
||||
// Desktop L
|
||||
if (result.breakpoints[MinDesktopLargeBreakpoint]) {
|
||||
this.store.dispatch(fromActions.DeviceActions.saveDeviceSize({ size: 'LARGE' }));
|
||||
this.setClassIsDesktopLarge();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private setClassIsMobile(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-mobile');
|
||||
}
|
||||
|
||||
private setClassIsTablet(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-tablet');
|
||||
}
|
||||
|
||||
private setClassIsTabletSmall(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-tablet is-tablet__small');
|
||||
}
|
||||
|
||||
private setClassIsTabletLarge(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-tablet is-tablet__large');
|
||||
}
|
||||
|
||||
private setClassIsDesktop(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-desktop');
|
||||
}
|
||||
|
||||
private setClassIsDesktopSmall(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-desktop is-desktop__small');
|
||||
}
|
||||
|
||||
private setClassIsDesktopMedium(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-desktop is-desktop__medium');
|
||||
}
|
||||
|
||||
private setClassIsDesktopLarge(): void {
|
||||
this.htmlTag.setAttribute('class', 'is-desktop is-desktop__large');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { createActionGroup, emptyProps, props } from '@ngrx/store';
|
||||
|
||||
// Entities
|
||||
import { Device, Size, Browser } from '../entities/device-configs.model';
|
||||
|
||||
|
||||
export const DeviceActions = createActionGroup({
|
||||
source: '[Main] Get Device Breakpoints',
|
||||
events: {
|
||||
'Save Device Type': props<{ device: Device }>(),
|
||||
'Save Device Size': props<{ size: Size }>()
|
||||
},
|
||||
});
|
||||
|
||||
export const BrowserActions = createActionGroup({
|
||||
source: '[Main] Get Browser',
|
||||
events: {
|
||||
'Get Browser': emptyProps(),
|
||||
'Get Browser Success': props<{ response: Browser }>(),
|
||||
'Get Browser Error': emptyProps(),
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// Rxjs
|
||||
import { of } from 'rxjs';
|
||||
import { catchError, exhaustMap, map } from 'rxjs/operators';
|
||||
|
||||
// Ngrx
|
||||
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
|
||||
// Actions
|
||||
import * as fromActions from './device-configs.actions';
|
||||
|
||||
// Service
|
||||
import { DeviceConfigsService } from '../services/device-configs.service';
|
||||
|
||||
@Injectable()
|
||||
export class DeviceConfigsEffects {
|
||||
constructor(private deviceConfigsService: DeviceConfigsService, private actions: Actions) {}
|
||||
|
||||
getBrowser$ = createEffect(() => {
|
||||
return this.actions.pipe(
|
||||
ofType(fromActions.BrowserActions.getBrowser),
|
||||
exhaustMap(() =>
|
||||
of(this.deviceConfigsService.getUserBrowser()).pipe(
|
||||
map((response) => {
|
||||
return fromActions.BrowserActions.getBrowserSuccess({ response });
|
||||
}),
|
||||
catchError(() => {
|
||||
return of(fromActions.BrowserActions.getBrowserError());
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { createReducer, on } from '@ngrx/store';
|
||||
import * as fromActions from './device-configs.actions';
|
||||
|
||||
import { Device, Size, Browser } from '../entities/device-configs.model';
|
||||
|
||||
export const featureKey = 'CORE_deviceConfigs';
|
||||
|
||||
export interface DeviceConfigsState {
|
||||
device: Device;
|
||||
size: Size;
|
||||
browser: Browser
|
||||
}
|
||||
|
||||
export const initialState: DeviceConfigsState = {
|
||||
device: 'DESKTOP',
|
||||
size: null,
|
||||
browser: 'UNKNOWN'
|
||||
};
|
||||
|
||||
export const deviceConfigsReducer = createReducer(
|
||||
initialState,
|
||||
on(fromActions.DeviceActions.saveDeviceType, (state, action) => {
|
||||
return { ...state, device: action.device };
|
||||
}),
|
||||
|
||||
on(fromActions.DeviceActions.saveDeviceSize, (state, action) => {
|
||||
return { ...state, size: action.size };
|
||||
}),
|
||||
on(fromActions.BrowserActions.getBrowserSuccess, (state, action) => {
|
||||
return { ...state, browser: action.response };
|
||||
})
|
||||
);
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createSelector, createFeatureSelector } from '@ngrx/store';
|
||||
|
||||
import * as fromReducer from './device-configs.reducer';
|
||||
|
||||
export const getFeatureState = createFeatureSelector<fromReducer.DeviceConfigsState>(
|
||||
fromReducer.featureKey
|
||||
);
|
||||
|
||||
// Device Breakpoints
|
||||
export const getDevice = createSelector(getFeatureState, (state) => state.device);
|
||||
export const getSize = createSelector(getFeatureState, (state) => state.size);
|
||||
|
||||
// Mobile & Tablet S
|
||||
export const getIsSmallDevice = createSelector(getFeatureState, (state) => {
|
||||
return state.device !== 'DESKTOP' && state.size !== 'LARGE';
|
||||
});
|
||||
|
||||
// Browser
|
||||
export const getBrowser = createSelector(getFeatureState, (state) => state.browser);
|
||||
26
libs/ui/src/lib/util/environments/environment.dev.ts
Normal file
26
libs/ui/src/lib/util/environments/environment.dev.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export const environment: any = {
|
||||
production: false,
|
||||
mandatorySignIn: false,
|
||||
authenticationFlowType: 'USER_SRP_AUTH',
|
||||
identityPoolId: 'eu-west-1:25f8388c-3826-4d38-acaa-0bfcb3f6251f',
|
||||
region: 'eu-west-1',
|
||||
identityPoolRegion: 'eu-west-1',
|
||||
userPoolId: 'eu-west-1_vYyt3eApk',
|
||||
userPoolWebClientId: '4bss36r712padssbhco9vg2uej',
|
||||
API: 'https://d1u3b69g4c.execute-api.eu-west-1.amazonaws.com/staging/',
|
||||
CREATE_LEAD_INVESTOR:
|
||||
'https://d1u3b69g4c.execute-api.eu-west-1.amazonaws.com/staging/lead/investor',
|
||||
COGNITO_ID: '4bss36r712padssbhco9vg2uej',
|
||||
INTERCOM_IDENTITY_VERIFICATION_SECRET: 'jpIdk_gk6pGDaJkTOMpfEWzhaoTKCi6zpR-GbkRi',
|
||||
DATO_KEY: 'Bearer ca9c292a00a5ca85e7b08e5a04185a',
|
||||
DATO_DEV_ENVIRONMENT: 'development',
|
||||
DATO_PROD_ENVIRONMENT: 'master',
|
||||
oauth: {
|
||||
domain: 'staging-oauth.deale.es',
|
||||
scope: ['phone', 'email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
|
||||
redirectSignIn: 'https://staging-app.deale.es/auth',
|
||||
redirectSignOut: 'https://staging-app.deale.es/auth',
|
||||
responseType: 'code',
|
||||
},
|
||||
federationTarget: 'COGNITO_USER_POOLS',
|
||||
};
|
||||
25
libs/ui/src/lib/util/environments/environment.prod.ts
Normal file
25
libs/ui/src/lib/util/environments/environment.prod.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export const environment: any = {
|
||||
production: true,
|
||||
identityPoolId: 'eu-west-1:571db516-5c84-40bd-bd16-aeb121805dea',
|
||||
region: 'eu-west-1',
|
||||
identityPoolRegion: 'eu-west-1',
|
||||
userPoolId: 'eu-west-1_nZwcGc84a',
|
||||
userPoolWebClientId: '31k1diku58oftoddd35l5ablri',
|
||||
mandatorySignIn: false,
|
||||
authenticationFlowType: 'USER_SRP_AUTH',
|
||||
API: 'https://9e02sawl11.execute-api.eu-west-1.amazonaws.com/prod/',
|
||||
CREATE_LEAD_INVESTOR: 'https://9e02sawl11.execute-api.eu-west-1.amazonaws.com/prod/lead/investor',
|
||||
COGNITO_ID: '31k1diku58oftoddd35l5ablri',
|
||||
INTERCOM_IDENTITY_VERIFICATION_SECRET: "jpIdk_gk6pGDaJkTOMpfEWzhaoTKCi6zpR-GbkRi",
|
||||
DATO_KEY: 'Bearer ca9c292a00a5ca85e7b08e5a04185a',
|
||||
DATO_DEV_ENVIRONMENT: 'development',
|
||||
DATO_PROD_ENVIRONMENT: 'master',
|
||||
oauth: {
|
||||
domain: 'oauth.deale.es',
|
||||
scope: ['phone', 'email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
|
||||
redirectSignIn: 'https://app.deale.es/auth',
|
||||
redirectSignOut: 'https://app.deale.es/auth',
|
||||
responseType: 'code',
|
||||
},
|
||||
federationTarget: 'COGNITO_USER_POOLS',
|
||||
};
|
||||
39
libs/ui/src/lib/util/environments/environment.ts
Normal file
39
libs/ui/src/lib/util/environments/environment.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment: any = {
|
||||
production: false,
|
||||
mandatorySignIn: false,
|
||||
authenticationFlowType: 'USER_SRP_AUTH',
|
||||
identityPoolId: 'eu-west-1:25f8388c-3826-4d38-acaa-0bfcb3f6251f',
|
||||
region: 'eu-west-1',
|
||||
identityPoolRegion: 'eu-west-1',
|
||||
userPoolId: 'eu-west-1_vYyt3eApk',
|
||||
userPoolWebClientId: '4bss36r712padssbhco9vg2uej',
|
||||
API: 'https://d1u3b69g4c.execute-api.eu-west-1.amazonaws.com/staging/',
|
||||
CREATE_LEAD_INVESTOR:
|
||||
'https://d1u3b69g4c.execute-api.eu-west-1.amazonaws.com/staging/lead/investor',
|
||||
COGNITO_ID: '4bss36r712padssbhco9vg2uej',
|
||||
INTERCOM_IDENTITY_VERIFICATION_SECRET: 'jpIdk_gk6pGDaJkTOMpfEWzhaoTKCi6zpR-GbkRi',
|
||||
DATO_KEY: 'Bearer ca9c292a00a5ca85e7b08e5a04185a',
|
||||
DATO_DEV_ENVIRONMENT: 'development',
|
||||
DATO_PROD_ENVIRONMENT: 'master',
|
||||
oauth: {
|
||||
domain: 'staging-oauth.deale.es',
|
||||
scope: ['phone', 'email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
|
||||
redirectSignIn: 'https://staging-app.deale.es/auth',
|
||||
redirectSignOut: 'https://staging-app.deale.es/auth',
|
||||
responseType: 'code',
|
||||
},
|
||||
federationTarget: 'COGNITO_USER_POOLS',
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
|
||||
1
libs/ui/src/lib/util/environments/index.ts
Normal file
1
libs/ui/src/lib/util/environments/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './environment';
|
||||
52
libs/ui/src/lib/util/form-control/form-control.ts
Normal file
52
libs/ui/src/lib/util/form-control/form-control.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { ControlContainer, ControlValueAccessor } from '@angular/forms';
|
||||
|
||||
@Injectable()
|
||||
export class PiFormControl implements ControlValueAccessor {
|
||||
value: number | string | Array<string> | boolean;
|
||||
|
||||
onChange = (value: number | string | Array<string> | boolean) => {};
|
||||
|
||||
onTouched = () => {};
|
||||
|
||||
disabled = false;
|
||||
focused = false;
|
||||
touched = false;
|
||||
|
||||
constructor(protected injector: Injector) {}
|
||||
|
||||
get controlContainer(): any {
|
||||
return this.injector.get(ControlContainer);
|
||||
}
|
||||
|
||||
writeValue(value: number | string | Array<string> | boolean) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
registerOnChange(onChange: any) {
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
registerOnTouched(onTouched: any) {
|
||||
this.onTouched = onTouched;
|
||||
}
|
||||
|
||||
markAsTouched() {
|
||||
if (!this.touched) {
|
||||
this.onTouched();
|
||||
this.touched = true;
|
||||
}
|
||||
}
|
||||
|
||||
setDisabledState(disabled: boolean) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
onFocus(): void {
|
||||
this.focused = true;
|
||||
}
|
||||
|
||||
onBlur(): void {
|
||||
this.focused = false;
|
||||
}
|
||||
}
|
||||
1
libs/ui/src/lib/util/form-control/index.ts
Normal file
1
libs/ui/src/lib/util/form-control/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './form-control';
|
||||
29
libs/ui/src/lib/util/icon-registry/icon-registry.service.ts
Normal file
29
libs/ui/src/lib/util/icon-registry/icon-registry.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { customIcons } from './icons.data';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class IconRegistryService {
|
||||
constructor(
|
||||
private matIconRegistry: MatIconRegistry,
|
||||
private domSanitizer: DomSanitizer
|
||||
) {}
|
||||
|
||||
init(): void {
|
||||
this.registerIcons(customIcons, 'assets/icons/');
|
||||
}
|
||||
|
||||
registerIcons(icons: Array<string>, path: string) {
|
||||
icons.forEach((icon) => {
|
||||
this.matIconRegistry.addSvgIcon(
|
||||
icon,
|
||||
this.domSanitizer.bypassSecurityTrustResourceUrl(path + icon + '.svg')
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
167
libs/ui/src/lib/util/icon-registry/icons.data.ts
Normal file
167
libs/ui/src/lib/util/icon-registry/icons.data.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
export const customIcons = [
|
||||
'add-stroked',
|
||||
'add',
|
||||
'agriculture',
|
||||
'arrow-back',
|
||||
'arrow-down',
|
||||
'arrow-forward',
|
||||
'arrow-secondary-back',
|
||||
'arrow-secondary-down',
|
||||
'arrow-secondary-forward',
|
||||
'arrow-secondary-up',
|
||||
'arrow-up',
|
||||
'arrow-up-rounded',
|
||||
'attachment',
|
||||
'bankruptcy',
|
||||
'biotech',
|
||||
'briefcase',
|
||||
'box',
|
||||
'buildings',
|
||||
'calendar',
|
||||
'calendar-plus',
|
||||
'calendly',
|
||||
'caret',
|
||||
'chat',
|
||||
'check-rounded',
|
||||
'check',
|
||||
'chemistry-and-materials',
|
||||
'chevron-back',
|
||||
'chevron-down',
|
||||
'chevron-forward',
|
||||
'chevron-up',
|
||||
'choose',
|
||||
'circle',
|
||||
'click',
|
||||
'clip',
|
||||
'close-rounded',
|
||||
'close',
|
||||
'coin',
|
||||
'coins',
|
||||
'connect',
|
||||
'construction',
|
||||
'consumer',
|
||||
'dashboard',
|
||||
'dealbox',
|
||||
'details',
|
||||
'diagram',
|
||||
'dialog',
|
||||
'distribution',
|
||||
'document',
|
||||
'document-add',
|
||||
'document-search',
|
||||
'document-euro',
|
||||
'document-substract',
|
||||
'dollar',
|
||||
'double-chevron-back',
|
||||
'download-teaser',
|
||||
'download',
|
||||
'due-diligence',
|
||||
'e-commerce',
|
||||
'ebitda',
|
||||
'edit',
|
||||
'education',
|
||||
'email',
|
||||
'email-plus',
|
||||
'enter',
|
||||
'entertainment',
|
||||
'estimation-time',
|
||||
'euro',
|
||||
'exclamation',
|
||||
'exclusivity',
|
||||
'expand',
|
||||
'eye-off',
|
||||
'eye',
|
||||
'file-coins',
|
||||
'filter',
|
||||
'financial-services',
|
||||
'flag-grey',
|
||||
'focus',
|
||||
'globe',
|
||||
'google',
|
||||
'graphic',
|
||||
'grid',
|
||||
'hamburguer',
|
||||
'headquarters',
|
||||
'healthcare',
|
||||
'hospitality',
|
||||
'industrial',
|
||||
'info',
|
||||
'it-internet',
|
||||
'legal',
|
||||
'light-bulb',
|
||||
'link',
|
||||
'linkedin',
|
||||
'list',
|
||||
'location',
|
||||
'lock',
|
||||
'login',
|
||||
'logistics',
|
||||
'manufacturing',
|
||||
'marketing-media',
|
||||
'meeting',
|
||||
'messages',
|
||||
'messages-left',
|
||||
'messy-coin-stack',
|
||||
'metric-down-arrow',
|
||||
'metric-up-arrow',
|
||||
'mining',
|
||||
'mobility',
|
||||
'money-transfer',
|
||||
'more',
|
||||
'my-company',
|
||||
'nif-company',
|
||||
'notification-off',
|
||||
'notification-on',
|
||||
'operations',
|
||||
'opportunities',
|
||||
'optimum',
|
||||
'other-services',
|
||||
'percentage',
|
||||
'person-lines',
|
||||
'phone',
|
||||
'phone-arrow',
|
||||
'physical',
|
||||
'play-arrow',
|
||||
'premium',
|
||||
'pricing',
|
||||
'professional-services',
|
||||
'public-administration',
|
||||
'purchase-mandates',
|
||||
'question',
|
||||
'raw-materials',
|
||||
'real-estate',
|
||||
'search',
|
||||
'select',
|
||||
'sell-mandates',
|
||||
'send-information',
|
||||
'shareholders',
|
||||
'signature',
|
||||
'sort',
|
||||
'star-primary',
|
||||
'star-fill',
|
||||
'star-outline',
|
||||
'substract-stroked',
|
||||
'substract',
|
||||
'support',
|
||||
'telecomunications',
|
||||
'telephone',
|
||||
'telephone-fill',
|
||||
'time-detail',
|
||||
'time-zone',
|
||||
'transmission',
|
||||
'transport-logistics',
|
||||
'trash',
|
||||
'twitter',
|
||||
'upload',
|
||||
'user-profile',
|
||||
'user-profile-advisor',
|
||||
'user-profile-company',
|
||||
'user',
|
||||
'utilities',
|
||||
'verification-list',
|
||||
'verified-money',
|
||||
'website',
|
||||
'whatsapp',
|
||||
'youtube',
|
||||
'zoom',
|
||||
];
|
||||
3
libs/ui/src/lib/util/icon-registry/index.ts
Normal file
3
libs/ui/src/lib/util/icon-registry/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './util-icon-registry.module';
|
||||
|
||||
export * from './icon-registry.service';
|
||||
@@ -0,0 +1,16 @@
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { IconRegistryService } from './icon-registry.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: (iconRegistryService: IconRegistryService) => {
|
||||
return () => iconRegistryService.init();
|
||||
},
|
||||
deps: [IconRegistryService],
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class PiSharedUtilIconRegistryModule {}
|
||||
1
libs/ui/src/lib/util/infinite-scroll/index.ts
Normal file
1
libs/ui/src/lib/util/infinite-scroll/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './infinite-scroll.data';
|
||||
@@ -0,0 +1,6 @@
|
||||
export enum INFINITE_SCROLL {
|
||||
page = 1,
|
||||
limit = 12,
|
||||
throttle = 50,
|
||||
scrollDistance = 2,
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Angular
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// Ngrx
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
// Rxjs
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// State
|
||||
import * as fromSelectors from '../state/list-configs.selectors';
|
||||
import * as fromActions from '../state/list-configs.actions';
|
||||
import * as fromState from '../state/list-configs.reducer';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ListConfigsFacade {
|
||||
readonly mode$: Observable<fromState.ListMode> = this.store.select(fromSelectors.getListMode);
|
||||
|
||||
constructor(private store: Store<fromState.ListConfigsState>) {}
|
||||
|
||||
setListMode(payload: fromState.ListMode): void {
|
||||
this.store.dispatch(fromActions.setListMode({ payload }));
|
||||
}
|
||||
|
||||
resetListMode(): void {
|
||||
this.store.dispatch(fromActions.resetListMode());
|
||||
}
|
||||
}
|
||||
7
libs/ui/src/lib/util/list-configs/index.ts
Normal file
7
libs/ui/src/lib/util/list-configs/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// Facade
|
||||
export * from './application/list-configs.facade';
|
||||
|
||||
// State
|
||||
export * from './state/list-configs.actions';
|
||||
export * from './state/list-configs.selectors';
|
||||
export * from './state/list-configs.reducer';
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createAction, props } from '@ngrx/store';
|
||||
|
||||
import { ListMode } from './list-configs.reducer';
|
||||
|
||||
export enum ListModeActionsType {
|
||||
SET_LIST_MODE = '[Main] Set List Mode',
|
||||
RESET_LIST_MODE = '[Main] Reset List Mode',
|
||||
}
|
||||
|
||||
export const setListMode = createAction(
|
||||
ListModeActionsType.SET_LIST_MODE,
|
||||
props<{ payload: ListMode }>()
|
||||
);
|
||||
|
||||
export const resetListMode = createAction(ListModeActionsType.RESET_LIST_MODE);
|
||||
@@ -0,0 +1,25 @@
|
||||
import { createReducer, on } from '@ngrx/store';
|
||||
|
||||
import { resetListMode, setListMode } from './list-configs.actions';
|
||||
|
||||
export const featureKey = 'CORE_listConfigs';
|
||||
|
||||
export interface ListConfigsState {
|
||||
mode: ListMode;
|
||||
}
|
||||
|
||||
export type ListMode = 'grid' | 'list';
|
||||
|
||||
export const initialState: ListConfigsState = {
|
||||
mode: 'list',
|
||||
};
|
||||
|
||||
export const listConfigsReducer = createReducer(
|
||||
initialState,
|
||||
on(setListMode, (state, action) => {
|
||||
return { ...state, mode: action.payload };
|
||||
}),
|
||||
on(resetListMode, (state) => {
|
||||
return { ...initialState };
|
||||
})
|
||||
);
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||
|
||||
import * as fromReducer from './list-configs.reducer';
|
||||
|
||||
export const getFeatureState = createFeatureSelector<fromReducer.ListConfigsState>(
|
||||
fromReducer.featureKey
|
||||
);
|
||||
|
||||
export const getListMode = createSelector(getFeatureState, (state) => state.mode);
|
||||
28
libs/ui/src/lib/util/loaders/aplication/loader.facade.ts
Normal file
28
libs/ui/src/lib/util/loaders/aplication/loader.facade.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// Angular
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
// RxJS
|
||||
import { Observable, Subscribable } from 'rxjs';
|
||||
|
||||
// NgRx
|
||||
import { Store, select } from '@ngrx/store';
|
||||
|
||||
// Store
|
||||
import * as LoaderSelectors from '../state/loader.selectors';
|
||||
import * as LoaderActions from '../state/loader.actions';
|
||||
|
||||
@Injectable()
|
||||
export class LoaderFacade {
|
||||
loader$: Observable<boolean> = this.store.pipe(select(LoaderSelectors.getLoader));
|
||||
showLoader$: Observable<unknown> | Subscribable<unknown> | Promise<unknown>;
|
||||
|
||||
constructor(private store: Store) {}
|
||||
|
||||
showLoader() {
|
||||
this.store.dispatch(LoaderActions.showLoader());
|
||||
}
|
||||
|
||||
hideLoader() {
|
||||
this.store.dispatch(LoaderActions.hideLoader());
|
||||
}
|
||||
}
|
||||
11
libs/ui/src/lib/util/loaders/index.ts
Normal file
11
libs/ui/src/lib/util/loaders/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// Module
|
||||
export * from './util-loader.module';
|
||||
|
||||
// Facade
|
||||
export * from './aplication/loader.facade';
|
||||
|
||||
// State
|
||||
export * from './state/loader.actions';
|
||||
export * from './state/loader.reducer';
|
||||
export * from './state/loader.selectors';
|
||||
|
||||
6
libs/ui/src/lib/util/loaders/state/loader.actions.ts
Normal file
6
libs/ui/src/lib/util/loaders/state/loader.actions.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// NgRx
|
||||
import { createAction } from '@ngrx/store';
|
||||
|
||||
export const showLoader = createAction('[Loader] Show Loader');
|
||||
|
||||
export const hideLoader = createAction('[Loader] Hide Loader');
|
||||
37
libs/ui/src/lib/util/loaders/state/loader.reducer.ts
Normal file
37
libs/ui/src/lib/util/loaders/state/loader.reducer.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
// NgRx
|
||||
import { createReducer, on, Action } from '@ngrx/store';
|
||||
|
||||
// Store
|
||||
import * as LoaderActions from './loader.actions';
|
||||
|
||||
export const loadersKey = 'CORE_loaderState';
|
||||
|
||||
export interface LoaderState {
|
||||
loader: boolean;
|
||||
}
|
||||
|
||||
export const initialLoaderState: LoaderState = {
|
||||
loader: false,
|
||||
};
|
||||
|
||||
export const loaderReducer = createReducer(
|
||||
initialLoaderState,
|
||||
|
||||
on(LoaderActions.showLoader, (state) => {
|
||||
return {
|
||||
...state,
|
||||
loader: true,
|
||||
};
|
||||
}),
|
||||
|
||||
on(LoaderActions.hideLoader, (state) => {
|
||||
return {
|
||||
...state,
|
||||
loader: false,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
export function loaderReducerFunction(state: LoaderState | undefined, action: Action) {
|
||||
return loaderReducer(state, action);
|
||||
}
|
||||
11
libs/ui/src/lib/util/loaders/state/loader.selectors.ts
Normal file
11
libs/ui/src/lib/util/loaders/state/loader.selectors.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
// NgRx
|
||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||
|
||||
// Store
|
||||
import { loadersKey, LoaderState } from './loader.reducer';
|
||||
|
||||
export const selectLoaderState = createFeatureSelector<LoaderState>(loadersKey);
|
||||
|
||||
export const getLoader = createSelector(selectLoaderState, (state) => {
|
||||
return state.loader;
|
||||
});
|
||||
13
libs/ui/src/lib/util/loaders/util-loader.module.ts
Normal file
13
libs/ui/src/lib/util/loaders/util-loader.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
|
||||
import * as fromReducer from './state/loader.reducer';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
StoreModule.forFeature(fromReducer.loadersKey, fromReducer.loaderReducerFunction),
|
||||
],
|
||||
})
|
||||
export class PiSharedUtilLoadersModule {}
|
||||
1
libs/ui/src/lib/util/local-storage/index.ts
Normal file
1
libs/ui/src/lib/util/local-storage/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './local-storage.service';
|
||||
26
libs/ui/src/lib/util/local-storage/local-storage.service.ts
Normal file
26
libs/ui/src/lib/util/local-storage/local-storage.service.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// Angular
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LocalStorageService {
|
||||
constructor(@Inject(PLATFORM_ID) public platformId: Object) {}
|
||||
|
||||
getItem(tag: string) {
|
||||
if (isPlatformBrowser(this.platformId)) {
|
||||
const value = (window as any).localStorage.getItem(tag);
|
||||
if (value) return JSON.parse(value);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setItem(tag: string, value: any) {
|
||||
if (isPlatformBrowser(this.platformId))
|
||||
(window as Window).localStorage.setItem(tag, JSON.stringify(value));
|
||||
}
|
||||
|
||||
deleteItem(tag: string) {
|
||||
if (isPlatformBrowser(this.platformId))
|
||||
(window as Window).localStorage.removeItem(tag);
|
||||
}
|
||||
}
|
||||
54
libs/ui/src/lib/util/menu/base.menu.component.ts
Normal file
54
libs/ui/src/lib/util/menu/base.menu.component.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
// Angular
|
||||
import { ContentChild, Directive, HostBinding, Input, TemplateRef } from '@angular/core';
|
||||
|
||||
// Style definitions
|
||||
import { MenuEntry, MenuItemText } from './entities/menu-entry.model';
|
||||
|
||||
@Directive()
|
||||
export abstract class PiBaseMenuComponent {
|
||||
@HostBinding('class') baseClassName = 'pi-menu pi-menu__parent';
|
||||
|
||||
isMouseOver = false;
|
||||
|
||||
@Input()
|
||||
label: string;
|
||||
|
||||
_menuItems: Array<MenuEntry> = [];
|
||||
|
||||
@Input()
|
||||
set menuItems(menuItems: MenuEntry[]) {
|
||||
this._menuItems = menuItems;
|
||||
}
|
||||
|
||||
get menuItems(): MenuEntry[] {
|
||||
return this._menuItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent Menu
|
||||
*/
|
||||
@ContentChild('parentMenuTemplate', { static: false })
|
||||
parentMenuTemplateRef: TemplateRef<unknown> | undefined;
|
||||
|
||||
/**
|
||||
* Children Menu (Level 1)
|
||||
*/
|
||||
@ContentChild('childMenuTemplate', { static: false })
|
||||
childMenuTemplateRef: TemplateRef<unknown> | undefined;
|
||||
|
||||
/**
|
||||
* Additional Children Menu (Level 1)
|
||||
*/
|
||||
@ContentChild('childAsideMenuTemplate', { static: false })
|
||||
childAsideMenuTemplateRef: TemplateRef<unknown> | undefined;
|
||||
|
||||
/**
|
||||
* Additional Children Menu (Level 1)
|
||||
*/
|
||||
@ContentChild('asideMenuTemplate', { static: false })
|
||||
asideMenuTemplateRef: TemplateRef<unknown> | undefined;
|
||||
|
||||
trackByFn(index: number, item: MenuEntry): MenuItemText | string | undefined {
|
||||
return item.label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
HostBinding,
|
||||
HostListener,
|
||||
Renderer2
|
||||
} from '@angular/core';
|
||||
|
||||
@Directive()
|
||||
export abstract class PiBaseMenuEventItem {
|
||||
@HostBinding('class') className = 'pi-menu-event-item';
|
||||
|
||||
constructor(
|
||||
protected el: ElementRef,
|
||||
protected renderer: Renderer2
|
||||
) {}
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
if (!this.isChildrenVisible()) {
|
||||
this.setIsVisible();
|
||||
} else {
|
||||
this.setIsHidden();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
onDocumentClick(event: MouseEvent) {
|
||||
if (!this.el.nativeElement.contains(event.target)) {
|
||||
this.setIsHidden();
|
||||
}
|
||||
}
|
||||
|
||||
protected setIsVisible(): void {
|
||||
const parent = this.el.nativeElement as HTMLElement;
|
||||
const children = (parent.children as HTMLCollection).item(1) ?? null;
|
||||
|
||||
parent && this.renderer.addClass(parent, 'is-selected');
|
||||
children && this.renderer.addClass(children, 'is-visible');
|
||||
}
|
||||
|
||||
protected setIsHidden(): void {
|
||||
const parent = this.el.nativeElement;
|
||||
const children = (parent.children as HTMLCollection).item(1) ?? null;
|
||||
|
||||
parent && this.renderer.removeClass(parent, 'is-selected');
|
||||
children && this.renderer.removeClass(children, 'is-visible');
|
||||
}
|
||||
|
||||
protected isChildrenVisible(): boolean {
|
||||
const parent = this.el.nativeElement as HTMLElement;
|
||||
const children = (parent.children as HTMLCollection).item(1) ?? null;
|
||||
|
||||
return children?.classList.contains('is-visible');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Directive, ElementRef, HostBinding, HostListener, Renderer2 } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-menu-event-children]',
|
||||
})
|
||||
export class PiMenuEventChildrenDirective {
|
||||
@HostBinding('class') className = 'pi-menu pi-menu__children';
|
||||
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
||||
|
||||
@HostListener('click') onClickMenuItem() {
|
||||
const menuChildren = this.el.nativeElement;
|
||||
this.renderer.removeClass(menuChildren, 'is-visible');
|
||||
}
|
||||
}
|
||||
15
libs/ui/src/lib/util/menu/directives/menu-entry.directive.ts
Normal file
15
libs/ui/src/lib/util/menu/directives/menu-entry.directive.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Directive, HostBinding, Input } from '@angular/core';
|
||||
import { MenuEntryContext } from '../entities/menu-entry.model';
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-menu-entry]',
|
||||
})
|
||||
export class PiMenuEntryDirective {
|
||||
@HostBinding('class') get classes(): string {
|
||||
const contextClass = this.context && `pi-menu-entry__context--${this.context}`;
|
||||
return ['pi-menu-entry', contextClass].join(' ');
|
||||
}
|
||||
|
||||
@Input() context: MenuEntryContext = 'parent-menu';
|
||||
}
|
||||
46
libs/ui/src/lib/util/menu/entities/menu-entry.model.ts
Normal file
46
libs/ui/src/lib/util/menu/entities/menu-entry.model.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { styleType } from '../../../styles';
|
||||
|
||||
export type MenuEntry = Partial<{
|
||||
id: number;
|
||||
icon?: MenuItemIcon | string;
|
||||
label?: MenuItemText | string;
|
||||
route?: string | null;
|
||||
link?: string;
|
||||
userProfile?: string;
|
||||
rights?: Array<Rights>;
|
||||
// Parent & Child Level 1
|
||||
entries?: Array<MenuEntry>;
|
||||
// Child Additional Level 1
|
||||
asideEntries?: Array<MenuEntry>;
|
||||
state?: boolean;
|
||||
data?: any;
|
||||
isDisabled?: boolean;
|
||||
isActive?: boolean;
|
||||
anchor?: string;
|
||||
color?: styleType;
|
||||
}>;
|
||||
|
||||
export type Rights = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export interface MenuItemIcon {
|
||||
name: string;
|
||||
color?: styleType;
|
||||
}
|
||||
|
||||
export interface MenuItemText {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface FooterLink {
|
||||
id: number;
|
||||
icon?: string;
|
||||
label?: string;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
// Defines where the menu entry belongs
|
||||
export type MenuEntryContext = 'parent-menu' | 'children-menu' | 'children-submenu' | 'aside-menu';
|
||||
9
libs/ui/src/lib/util/menu/index.ts
Normal file
9
libs/ui/src/lib/util/menu/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './ui-menu.module';
|
||||
|
||||
export * from './entities/menu-entry.model';
|
||||
|
||||
export * from './base.menu.component';
|
||||
|
||||
export * from './directives/base-menu-item.directive';
|
||||
export * from './directives/menu-children.directive';
|
||||
export * from './directives/menu-entry.directive';
|
||||
20
libs/ui/src/lib/util/menu/ui-menu.module.ts
Normal file
20
libs/ui/src/lib/util/menu/ui-menu.module.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// Angular
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { TranslatePipe, TranslateDirective } from '@ngx-translate/core';
|
||||
|
||||
// Directives
|
||||
import { PiMenuEventChildrenDirective } from './directives/menu-children.directive';
|
||||
import { PiMenuEntryDirective } from './directives/menu-entry.directive';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, TranslatePipe, TranslateDirective],
|
||||
declarations: [
|
||||
PiMenuEventChildrenDirective,
|
||||
PiMenuEntryDirective,
|
||||
],
|
||||
exports: [PiMenuEventChildrenDirective, PiMenuEntryDirective],
|
||||
})
|
||||
export class PiSharedUtilMenuModule {}
|
||||
23
libs/ui/src/lib/util/models/chart-data.ts
Normal file
23
libs/ui/src/lib/util/models/chart-data.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
export interface Dataset {
|
||||
label: string;
|
||||
data: Array<number>;
|
||||
borderColor: DatasetColor;
|
||||
cubicInterpolationMode: 'monotone' | 'default';
|
||||
unit?: string;
|
||||
unitPosition?: 'before' | 'after';
|
||||
backgroundColor?: DatasetColor;
|
||||
}
|
||||
|
||||
export enum DatasetColor {
|
||||
primary = '#799ef0',
|
||||
primary50 = '#F0F4FF',
|
||||
highlighted = '#0D2A6B',
|
||||
highlighted50 = '#EEF1fB',
|
||||
accent = '#EDA82A',
|
||||
accent50 = '#FFFAED',
|
||||
grey = '#AEAEB6',
|
||||
grey50 = '#F3F4F4',
|
||||
grey75 = '#EEEFF1',
|
||||
grey300 = '#89888F',
|
||||
white= '#FFFFFF',
|
||||
}
|
||||
5
libs/ui/src/lib/util/models/date.ts
Normal file
5
libs/ui/src/lib/util/models/date.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface Date {
|
||||
day: string;
|
||||
month: string;
|
||||
weekDay?: string;
|
||||
}
|
||||
4
libs/ui/src/lib/util/models/faqs.ts
Normal file
4
libs/ui/src/lib/util/models/faqs.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface FAQ {
|
||||
question: string;
|
||||
answer: string;
|
||||
}
|
||||
7
libs/ui/src/lib/util/models/index.ts
Normal file
7
libs/ui/src/lib/util/models/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './chart-data';
|
||||
export * from './faqs';
|
||||
export * from './params';
|
||||
export * from './pricing';
|
||||
export * from './sector';
|
||||
export * from './unit';
|
||||
export * from './date';
|
||||
3
libs/ui/src/lib/util/models/params.ts
Normal file
3
libs/ui/src/lib/util/models/params.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface Params {
|
||||
[key: string]: string;
|
||||
}
|
||||
59
libs/ui/src/lib/util/models/pricing.ts
Normal file
59
libs/ui/src/lib/util/models/pricing.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { mode, theming } from '../../styles';
|
||||
|
||||
export enum UserType {
|
||||
INVESTOR = 'INVESTOR',
|
||||
COMPANY = 'COMPANY',
|
||||
ADVISOR = 'ADVISOR',
|
||||
ADMIN = 'ADMIN',
|
||||
}
|
||||
|
||||
export enum PricingPlanType {
|
||||
FREE = 'FREE',
|
||||
BASIC = 'BASIC',
|
||||
PREMIUM = 'PREMIUM',
|
||||
}
|
||||
|
||||
export enum BillingCycleType {
|
||||
MONTHLY = 'MONTHLY',
|
||||
YEARLY = 'YEARLY',
|
||||
BIANNUAL = 'BIANNUAL',
|
||||
QUARTERLY = 'QUARTERLY',
|
||||
}
|
||||
|
||||
export interface PricingCardLocales {
|
||||
cta?: string;
|
||||
icon: string;
|
||||
priceSuffix: string;
|
||||
subtitle: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface PricingPlan {
|
||||
billingCycle: BillingCycleType;
|
||||
price: number;
|
||||
planType: PricingPlanType;
|
||||
mode: mode;
|
||||
color: theming;
|
||||
featureOverview: Array<string>;
|
||||
priceHelpText?: Array<string>;
|
||||
}
|
||||
|
||||
export interface PricingPlanCompleteInfo extends PricingPlan, PricingCardLocales {}
|
||||
|
||||
export interface BillingCycleOption {
|
||||
value: BillingCycleType;
|
||||
label: string;
|
||||
discount?: number;
|
||||
}
|
||||
|
||||
export interface Feature {
|
||||
isEnabledFor: Array<PricingPlanType>;
|
||||
localeKey: string;
|
||||
categoryLocaleKey?: string;
|
||||
}
|
||||
|
||||
export interface Phase {
|
||||
icon: string;
|
||||
features: Array<Feature>;
|
||||
localeKey: string;
|
||||
}
|
||||
62
libs/ui/src/lib/util/models/sector.ts
Normal file
62
libs/ui/src/lib/util/models/sector.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
export enum SectorUidMatchLocale {
|
||||
AGRICULTURE_FORESTRY_FISHING = 'agricultureAndOthers',
|
||||
CONSTRUCTION = 'construction',
|
||||
CONSUMER = 'consumer',
|
||||
DISTRIBUTION_WHOLESALE_TRADE = 'distributionWholesaleTrade',
|
||||
E_COMMERCE = 'ecommerce',
|
||||
EDUCATION = 'education',
|
||||
ENTERTAINMENT = 'entertainment',
|
||||
FINANCIAL_SERVICES_INSURANCE = 'financialServicesInsurance',
|
||||
HEALTHCARE = 'healthcare',
|
||||
HOSPITALITY = 'hospitality',
|
||||
IT_INTERNET = 'itInternet',
|
||||
LEGAL_ACCOUNTING_MANAGEMENT_SERVICES = 'legalAccountingManagementServices',
|
||||
MANUFACTURING = 'manufacturing',
|
||||
MARKETING_MEDIA = 'marketingMedia',
|
||||
MINING_OTHER_CHEMICAL_MATERIALS_EXTRACTION = 'miningAndChemicals',
|
||||
MOBILITY = 'mobility',
|
||||
OTHER_SERVICES = 'otherServices',
|
||||
PHYSICAL_AND_LIFE_SCIENCES = 'scientificServices',
|
||||
PUBLIC_ADMINISTRATION = 'publicAdministration',
|
||||
REAL_ESTATE = 'realEstate',
|
||||
TELECOMUNICATIONS = 'telecommunications',
|
||||
TRANSPORT_LOGISTICS = 'transportLogistics',
|
||||
UTILITIES = 'utilities',
|
||||
}
|
||||
|
||||
export enum SectorType {
|
||||
AGRICULTURE_FORESTRY_FISHING = 'AGRICULTURE_FORESTRY_FISHING',
|
||||
CONSTRUCTION = 'CONSTRUCTION',
|
||||
CONSUMER = 'CONSUMER',
|
||||
DISTRIBUTION_WHOLESALE_TRADE = 'DISTRIBUTION_WHOLESALE_TRADE',
|
||||
E_COMMERCE = 'E_COMMERCE',
|
||||
EDUCATION = 'EDUCATION',
|
||||
ENTERTAINMENT = 'ENTERTAINMENT',
|
||||
FINANCIAL_SERVICES_INSURANCE = 'FINANCIAL_SERVICES_INSURANCE',
|
||||
HEALTHCARE = 'HEALTHCARE',
|
||||
HOSPITALITY = 'HOSPITALITY',
|
||||
IT_INTERNET = 'IT_INTERNET',
|
||||
LEGAL_ACCOUNTING_MANAGEMENT_SERVICES = 'LEGAL_ACCOUNTING_MANAGEMENT_SERVICES',
|
||||
MANUFACTURING = 'MANUFACTURING',
|
||||
MARKETING_MEDIA = 'MARKETING_MEDIA',
|
||||
MINING_OTHER_CHEMICAL_MATERIALS_EXTRACTION = 'MINING_OTHER_CHEMICAL_MATERIALS_EXTRACTION',
|
||||
MOBILITY = 'MOBILITY',
|
||||
OTHER_SERVICES = 'OTHER_SERVICES',
|
||||
PHYSICAL_AND_LIFE_SCIENCES = 'PHYSICAL_AND_LIFE_SCIENCES',
|
||||
PUBLIC_ADMINISTRATION = 'PUBLIC_ADMINISTRATION',
|
||||
REAL_ESTATE = 'REAL_ESTATE',
|
||||
TELECOMUNICATIONS = 'TELECOMUNICATIONS',
|
||||
TRANSPORT_LOGISTICS = 'TRANSPORT_LOGISTICS',
|
||||
UTILITIES = 'UTILITIES',
|
||||
}
|
||||
|
||||
/**
|
||||
* Movido aquí desde `deale-saas/util/models` (lib de aplicación, fuera del
|
||||
* alcance de esta librería) porque `SectorCommons` lo necesita.
|
||||
*/
|
||||
export interface Sector {
|
||||
description: string;
|
||||
name: string;
|
||||
sectorUid: string;
|
||||
icon?: string;
|
||||
}
|
||||
1
libs/ui/src/lib/util/models/unit.ts
Normal file
1
libs/ui/src/lib/util/models/unit.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type unit = '€' | '%' | '$' | 'M' | 'x' | '';
|
||||
4
libs/ui/src/lib/util/pipes/index.ts
Normal file
4
libs/ui/src/lib/util/pipes/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// pipes
|
||||
export * from './util-pipes.module';
|
||||
|
||||
export * from './pipes';
|
||||
80
libs/ui/src/lib/util/pipes/pipes.ts
Normal file
80
libs/ui/src/lib/util/pipes/pipes.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
standalone: false,
|
||||
name: 'numberFormat',
|
||||
})
|
||||
export class NumberFormatPipe implements PipeTransform {
|
||||
transform(value: unknown, ...args: Array<unknown>): unknown {
|
||||
return new Intl.NumberFormat('de-DE').format(+value);
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false, name: 'replace' })
|
||||
export class ReplacePipe implements PipeTransform {
|
||||
transform(value: string, strToReplace: string, replacementStr: string): string {
|
||||
if (!value || !strToReplace || !replacementStr) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return value.replace(new RegExp(strToReplace, 'g'), replacementStr);
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false,
|
||||
name: 'sanitizerAltImage',
|
||||
})
|
||||
export class SanitizerAltImagePipe implements PipeTransform {
|
||||
transform(name: string): string {
|
||||
return this.sanitizeAltImage(name);
|
||||
}
|
||||
|
||||
private sanitizeAltImage(name: string): string {
|
||||
return name.split('.').slice(0, -1).join('.').replace(/-/g, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false,
|
||||
name: 'firstWord',
|
||||
})
|
||||
export class FirstWordPipe implements PipeTransform {
|
||||
transform(value: string): string {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
return value.split(' ')[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false, name: 'truncate' })
|
||||
export class TruncatePipe implements PipeTransform {
|
||||
transform(text: string, length: number = 20, suffix: string = '...'): string {
|
||||
if (text.length > length) {
|
||||
const truncated: string = text.substring(0, length).trim() + suffix;
|
||||
return truncated;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false, name: 'maxTwoDecimals' })
|
||||
export class MaxTwoDecimalsPipe implements PipeTransform {
|
||||
transform(value: unknown, ...args: Array<unknown>): unknown {
|
||||
return Math.round(+value * 100) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
standalone: false, name: 'anonymize' })
|
||||
export class AnonymizePipe implements PipeTransform {
|
||||
transform(text?: string, length = 1, char = '*') {
|
||||
return text?.split(' ').map(word =>
|
||||
word.split('').map((letter, index) => (index < length ? letter : char)).join('')
|
||||
).join(' ')
|
||||
}
|
||||
}
|
||||
13
libs/ui/src/lib/util/pipes/util-pipes.module.ts
Normal file
13
libs/ui/src/lib/util/pipes/util-pipes.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// Angular
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
// Pipes
|
||||
import { AnonymizePipe, FirstWordPipe, MaxTwoDecimalsPipe, NumberFormatPipe, SanitizerAltImagePipe, TruncatePipe } from './pipes';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [AnonymizePipe, FirstWordPipe, NumberFormatPipe, SanitizerAltImagePipe, TruncatePipe, MaxTwoDecimalsPipe ],
|
||||
exports: [AnonymizePipe, FirstWordPipe, NumberFormatPipe, SanitizerAltImagePipe, TruncatePipe, MaxTwoDecimalsPipe],
|
||||
})
|
||||
export class PiSharedUtilPipesModule {}
|
||||
31
libs/ui/src/lib/util/router-store/custom-route-serializer.ts
Normal file
31
libs/ui/src/lib/util/router-store/custom-route-serializer.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// Angular
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
// Router
|
||||
import { RouterStateUrl } from './state/router.reducer';
|
||||
|
||||
// Ngrx
|
||||
import * as fromRouter from '@ngrx/router-store';
|
||||
|
||||
export class CustomSerializer implements fromRouter.RouterStateSerializer<RouterStateUrl> {
|
||||
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
|
||||
const { url } = routerState;
|
||||
const { queryParams } = routerState.root;
|
||||
|
||||
let route: ActivatedRouteSnapshot = routerState.root;
|
||||
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild;
|
||||
}
|
||||
const { params, routeConfig } = route;
|
||||
|
||||
// Only return an object including the URL, params and query params
|
||||
// instead of the entire snapshot
|
||||
return {
|
||||
url,
|
||||
params,
|
||||
queryParams,
|
||||
title: typeof routeConfig?.title === 'string' ? routeConfig.title : '',
|
||||
};
|
||||
}
|
||||
}
|
||||
11
libs/ui/src/lib/util/router-store/error-handler.ts
Normal file
11
libs/ui/src/lib/util/router-store/error-handler.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { ErrorHandler, Injectable, Injector } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalErrorHandler implements ErrorHandler {
|
||||
constructor(private injector: Injector) { }
|
||||
handleError(error: any) {
|
||||
const router = this.injector.get(Router);
|
||||
console.error(error.stack.toString());
|
||||
}
|
||||
}
|
||||
10
libs/ui/src/lib/util/router-store/index.ts
Normal file
10
libs/ui/src/lib/util/router-store/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export * from './util-router-store.module';
|
||||
|
||||
// State
|
||||
export * from './state/router.actions';
|
||||
export * from './state/router.effects';
|
||||
export * from './state/router.reducer';
|
||||
export * from './state/router.selectors';
|
||||
|
||||
// Error handler
|
||||
export * from './error-handler';
|
||||
29
libs/ui/src/lib/util/router-store/state/router.actions.ts
Normal file
29
libs/ui/src/lib/util/router-store/state/router.actions.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { NavigationExtras } from '@angular/router';
|
||||
|
||||
import { createAction, props } from '@ngrx/store';
|
||||
|
||||
export const navigateTo = createAction(
|
||||
'[Core Router] Navigate To',
|
||||
props<{
|
||||
payload: {
|
||||
path: any[];
|
||||
query?: object;
|
||||
extras?: NavigationExtras;
|
||||
};
|
||||
}>()
|
||||
);
|
||||
|
||||
export const navigateRefreshTo = createAction(
|
||||
'[Core Router] Navigate Refresh To',
|
||||
props<{
|
||||
payload: {
|
||||
path: any[];
|
||||
query?: object;
|
||||
extras?: NavigationExtras;
|
||||
};
|
||||
}>()
|
||||
);
|
||||
|
||||
export const navigateBack = createAction('[Core Router] Navigate Back');
|
||||
|
||||
export const navigateForward = createAction('[Core Router] Navigate Forward');
|
||||
74
libs/ui/src/lib/util/router-store/state/router.effects.ts
Normal file
74
libs/ui/src/lib/util/router-store/state/router.effects.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
|
||||
import * as RouterActions from './router.actions';
|
||||
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class RouterEffects {
|
||||
navigateTo$ = createEffect(
|
||||
() => {
|
||||
return this.action$.pipe(
|
||||
ofType(RouterActions.navigateTo),
|
||||
map((action) => {
|
||||
return action.payload;
|
||||
}),
|
||||
tap(({ path, query: queryParams, extras }) => {
|
||||
this._router.navigate(path, { queryParams, ...extras });
|
||||
})
|
||||
);
|
||||
},
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
navigateRefreshTo$ = createEffect(
|
||||
() => {
|
||||
return this.action$.pipe(
|
||||
ofType(RouterActions.navigateRefreshTo),
|
||||
map((action) => {
|
||||
return action.payload;
|
||||
}),
|
||||
tap(({ path, query: queryParams, extras }) => {
|
||||
this._router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
this._router.onSameUrlNavigation = 'reload';
|
||||
this._router.navigate(path, { queryParams, ...extras });
|
||||
})
|
||||
);
|
||||
},
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
navigateBack$ = createEffect(
|
||||
() => {
|
||||
return this.action$.pipe(
|
||||
ofType(RouterActions.navigateBack),
|
||||
tap(() => {
|
||||
this._location.back();
|
||||
})
|
||||
);
|
||||
},
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
navigateForward$ = createEffect(
|
||||
() => {
|
||||
return this.action$.pipe(
|
||||
ofType(RouterActions.navigateForward),
|
||||
tap(() => {
|
||||
this._location.forward();
|
||||
})
|
||||
);
|
||||
},
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
constructor(
|
||||
private _location: Location,
|
||||
private action$: Actions,
|
||||
private _router: Router
|
||||
) {}
|
||||
}
|
||||
16
libs/ui/src/lib/util/router-store/state/router.reducer.ts
Normal file
16
libs/ui/src/lib/util/router-store/state/router.reducer.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as fromRouter from '@ngrx/router-store';
|
||||
|
||||
import { Params } from '@angular/router';
|
||||
|
||||
export const coreRouterFeatureKey = 'CORE_router';
|
||||
|
||||
export interface RouterStateUrl {
|
||||
url: string;
|
||||
queryParams: Params;
|
||||
params: Params;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface RouterState {
|
||||
routerReducer: fromRouter.RouterReducerState<RouterStateUrl>;
|
||||
}
|
||||
15
libs/ui/src/lib/util/router-store/state/router.selectors.ts
Normal file
15
libs/ui/src/lib/util/router-store/state/router.selectors.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||
|
||||
import * as fromRouter from '@ngrx/router-store';
|
||||
|
||||
import * as fromReducer from './router.reducer';
|
||||
|
||||
export const getRouterState = createFeatureSelector<
|
||||
fromRouter.RouterReducerState<fromReducer.RouterStateUrl>
|
||||
>(fromReducer.coreRouterFeatureKey);
|
||||
|
||||
export const getTitle = createSelector(getRouterState, (state) => {
|
||||
return state?.state?.title
|
||||
});
|
||||
|
||||
export const getRoute = createSelector(getRouterState, (state) => state?.state?.url);
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ErrorHandler, NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { RouterState, StoreRouterConnectingModule } from '@ngrx/router-store';
|
||||
import { CustomSerializer } from './custom-route-serializer';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
StoreRouterConnectingModule.forRoot({
|
||||
routerState: RouterState.Minimal,
|
||||
serializer: CustomSerializer,
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class PiSharedUtilRouterStoreModule {}
|
||||
1
libs/ui/src/lib/util/schema/index.ts
Normal file
1
libs/ui/src/lib/util/schema/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './schema.service';
|
||||
20
libs/ui/src/lib/util/schema/schema.service.ts
Normal file
20
libs/ui/src/lib/util/schema/schema.service.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// Angular
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable, Renderer2 } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SchemaService {
|
||||
script: HTMLScriptElement;
|
||||
|
||||
constructor(@Inject(DOCUMENT) private doc: Document) {}
|
||||
|
||||
loadJsScript(renderer: Renderer2, data: any): HTMLScriptElement {
|
||||
const script = renderer.createElement('script');
|
||||
script.type = 'application/ld+json';
|
||||
script.text = `${JSON.stringify(data)}`;
|
||||
renderer.appendChild(this.doc.body, script);
|
||||
return script;
|
||||
}
|
||||
}
|
||||
5
libs/ui/src/lib/util/scroll-to/index.ts
Normal file
5
libs/ui/src/lib/util/scroll-to/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './scroll-to.module';
|
||||
|
||||
export * from './scroll-to.directive';
|
||||
|
||||
export * from './scroll-to.service';
|
||||
15
libs/ui/src/lib/util/scroll-to/scroll-to.directive.ts
Normal file
15
libs/ui/src/lib/util/scroll-to/scroll-to.directive.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {
|
||||
Directive,
|
||||
HostBinding
|
||||
} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-scroll-to-element]',
|
||||
})
|
||||
export class PiScrollToElementDirective {
|
||||
@HostBinding('class') get classes(): string {
|
||||
return 'pi-scroll-to pi-scroll-to__element';
|
||||
}
|
||||
}
|
||||
|
||||
12
libs/ui/src/lib/util/scroll-to/scroll-to.module.ts
Normal file
12
libs/ui/src/lib/util/scroll-to/scroll-to.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { PiScrollToElementDirective } from './scroll-to.directive';
|
||||
import { PiSharedUtilScrollService } from './scroll-to.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [PiScrollToElementDirective],
|
||||
exports: [PiScrollToElementDirective],
|
||||
providers: [PiSharedUtilScrollService],
|
||||
})
|
||||
export class PiSharedUtilScrollToModule {}
|
||||
43
libs/ui/src/lib/util/scroll-to/scroll-to.service.ts
Normal file
43
libs/ui/src/lib/util/scroll-to/scroll-to.service.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ElementRef, Injectable, QueryList } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class PiSharedUtilScrollService {
|
||||
scrollToNextElement(elements: QueryList<ElementRef>): void {
|
||||
for (let i = 0; i <= elements.length; i++) {
|
||||
const element: ElementRef = elements.toArray()[i];
|
||||
if (this.isScrolledToBottom()) {
|
||||
this.scrollToTop();
|
||||
break;
|
||||
}
|
||||
if (i === elements.length) {
|
||||
this.scrollToBottom();
|
||||
break;
|
||||
}
|
||||
if (this.isElementInView(element.nativeElement)) {
|
||||
element.nativeElement.scrollIntoView({ behavior: 'smooth' });
|
||||
break;
|
||||
}
|
||||
this.scrollToTop();
|
||||
}
|
||||
}
|
||||
|
||||
isElementInView(element: Element): boolean {
|
||||
const rect = element.getBoundingClientRect();
|
||||
return rect.top > 40;
|
||||
}
|
||||
|
||||
scrollToTop(): void {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
scrollToBottom(): void {
|
||||
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
isScrolledToBottom(): boolean {
|
||||
const documentHeight = document.body.scrollHeight;
|
||||
const currentScroll = window.scrollY + window.innerHeight;
|
||||
return documentHeight <= currentScroll;
|
||||
}
|
||||
}
|
||||
|
||||
58
libs/ui/src/lib/util/status/directives/status.directive.ts
Normal file
58
libs/ui/src/lib/util/status/directives/status.directive.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Directive, OnChanges, HostBinding, Input, SimpleChanges } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-disabled]',
|
||||
})
|
||||
export class PiDisabledDirective implements OnChanges {
|
||||
@HostBinding('style.opacity') get opacity(): number {
|
||||
return this.isDisabled ? 0.33 : 1;
|
||||
}
|
||||
@HostBinding('class') get classes(): string | boolean {
|
||||
return [this.isDisabled && 'is-disabled'].join(' ');
|
||||
}
|
||||
|
||||
@Input() isDisabled: boolean;
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes) {
|
||||
this.isDisabled = changes['isDisabled'].currentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[is-active]',
|
||||
})
|
||||
export class PiIsActiveDirective {
|
||||
@HostBinding('class') get classes(): string | boolean {
|
||||
return [this.isActive ? 'is-active' : '', 'pi-status'].join(' ');
|
||||
}
|
||||
|
||||
@Input() isActive!: boolean;
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes) {
|
||||
this.isActive = changes['isActive'].currentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[is-visited]',
|
||||
})
|
||||
export class PiIsVisitedDirective {
|
||||
@HostBinding('class') get classes(): string | boolean {
|
||||
return [this.isVisited ? 'is-visited' : '', 'pi-status'].join(' ');
|
||||
}
|
||||
|
||||
@Input() isVisited!: boolean;
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes) {
|
||||
this.isVisited = changes['isVisited'].currentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
libs/ui/src/lib/util/status/entities/status.model.ts
Normal file
1
libs/ui/src/lib/util/status/entities/status.model.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type status = 'success' | 'error' | 'pending' | 'info' | 'disabled';
|
||||
5
libs/ui/src/lib/util/status/index.ts
Normal file
5
libs/ui/src/lib/util/status/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './shared-util-status.module';
|
||||
|
||||
export * from './directives/status.directive';
|
||||
|
||||
export * from './entities/status.model';
|
||||
22
libs/ui/src/lib/util/status/shared-util-status.module.ts
Normal file
22
libs/ui/src/lib/util/status/shared-util-status.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
PiDisabledDirective,
|
||||
PiIsActiveDirective,
|
||||
PiIsVisitedDirective,
|
||||
} from './directives/status.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [
|
||||
PiDisabledDirective,
|
||||
PiIsActiveDirective,
|
||||
PiIsVisitedDirective
|
||||
],
|
||||
exports: [
|
||||
PiDisabledDirective,
|
||||
PiIsActiveDirective,
|
||||
PiIsVisitedDirective,
|
||||
],
|
||||
})
|
||||
export class PiSharedUtilStatusModule {}
|
||||
7
libs/ui/src/lib/util/translate/custom-initializer.ts
Normal file
7
libs/ui/src/lib/util/translate/custom-initializer.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
export function appInitializerFactory(translateService: TranslateService) {
|
||||
return () => {
|
||||
translateService.use('es');
|
||||
};
|
||||
}
|
||||
27
libs/ui/src/lib/util/translate/i18n.service.ts
Normal file
27
libs/ui/src/lib/util/translate/i18n.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class I18nService {
|
||||
constructor(private translateService: TranslateService) {}
|
||||
|
||||
setLanguage(lang: string): Observable<any> {
|
||||
return new Observable((observer) => {
|
||||
this.translateService.use(lang).subscribe({
|
||||
next: () => {
|
||||
observer.next();
|
||||
observer.complete();
|
||||
},
|
||||
|
||||
error: (error: any) => observer.error(error),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getTranslation(key: string): Observable<string> {
|
||||
return this.translateService.get(key);
|
||||
}
|
||||
}
|
||||
18
libs/ui/src/lib/util/translate/index.ts
Normal file
18
libs/ui/src/lib/util/translate/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export * from './translate.module';
|
||||
|
||||
// Initializer
|
||||
export * from './custom-initializer';
|
||||
|
||||
// Data
|
||||
export * from './translate.data';
|
||||
|
||||
// Model
|
||||
export * from './translate.model';
|
||||
|
||||
// Translate server
|
||||
export * from './loaders/translate-browser.loader';
|
||||
export * from './loaders/translate-server.loader';
|
||||
|
||||
|
||||
// Service
|
||||
export * from './i18n.service';
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateLoader } from '@ngx-translate/core';
|
||||
|
||||
import { makeStateKey, StateKey, TransferState } from '@angular/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
export class TranslateBrowserLoader implements TranslateLoader {
|
||||
constructor(private http: HttpClient, private transferState: TransferState) {}
|
||||
|
||||
public getTranslation(lang: string): Observable<any> {
|
||||
const key: StateKey<number> = makeStateKey<number>(
|
||||
'transfer-translate-' + lang
|
||||
);
|
||||
const data = this.transferState.get(key, null);
|
||||
|
||||
// First we are looking for the translations in transfer-state,
|
||||
// if none found, http load as fallback
|
||||
if (data) {
|
||||
return new Observable((observer) => {
|
||||
observer.next(data);
|
||||
observer.complete();
|
||||
});
|
||||
} else {
|
||||
return new TranslateHttpLoader(this.http).getTranslation(lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function translateBrowserLoaderFactory(
|
||||
httpClient: HttpClient,
|
||||
transferState: TransferState
|
||||
) {
|
||||
return new TranslateBrowserLoader(httpClient, transferState);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateLoader } from '@ngx-translate/core';
|
||||
import { makeStateKey, StateKey, TransferState } from '@angular/core';
|
||||
import { join } from 'path';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
export class TranslateServerLoader implements TranslateLoader {
|
||||
constructor(
|
||||
private transferState: TransferState,
|
||||
private prefix: string = 'i18n',
|
||||
private suffix: string = '.json'
|
||||
) {}
|
||||
|
||||
public getTranslation(lang: string): Observable<any> {
|
||||
return new Observable((observer) => {
|
||||
const assets_folder = join(
|
||||
process.cwd(),
|
||||
'dist',
|
||||
'deale-website', // Your project name here
|
||||
'browser',
|
||||
'assets',
|
||||
this.prefix
|
||||
);
|
||||
|
||||
const jsonData = JSON.parse(readFileSync(`${assets_folder}/${lang}${this.suffix}`, 'utf8'));
|
||||
|
||||
// Here we save the translations in the transfer-state
|
||||
const key: StateKey<number> = makeStateKey<number>('transfer-translate-' + lang);
|
||||
this.transferState.set(key, jsonData);
|
||||
|
||||
observer.next(jsonData);
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function translateServerLoaderFactory(transferState: TransferState) {
|
||||
return new TranslateServerLoader(transferState);
|
||||
}
|
||||
10
libs/ui/src/lib/util/translate/translate.data.ts
Normal file
10
libs/ui/src/lib/util/translate/translate.data.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { LanguageProps } from './translate.model';
|
||||
|
||||
export const LANGUAGES: Map<string, LanguageProps> = new Map([
|
||||
['es', { languageCombo: 'common.languages.spanish', rtl: false, currency: 'EUR' }],
|
||||
['en', { languageCombo: 'common.languages.english', rtl: false, currency: 'USD' }],
|
||||
['ca', { languageCombo: 'common.languages.catalan', rtl: false, currency: 'EUR' }],
|
||||
['de', { languageCombo: 'common.languages.german', rtl: false, currency: 'EUR' }],
|
||||
['it', { languageCombo: 'common.languages.italian', rtl: false, currency: 'EUR' }],
|
||||
['fr', { languageCombo: 'common.languages.french', rtl: false, currency: 'EUR' }],
|
||||
]);
|
||||
10
libs/ui/src/lib/util/translate/translate.model.ts
Normal file
10
libs/ui/src/lib/util/translate/translate.model.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface LanguageProps {
|
||||
languageCombo: string;
|
||||
rtl: boolean;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export interface Language {
|
||||
locale: string;
|
||||
value: string;
|
||||
}
|
||||
28
libs/ui/src/lib/util/translate/translate.module.ts
Normal file
28
libs/ui/src/lib/util/translate/translate.module.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { EnvironmentProviders, makeEnvironmentProviders, provideAppInitializer, inject } from '@angular/core';
|
||||
|
||||
import { TranslateLoader, TranslateService, provideTranslateService } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
import { appInitializerFactory } from './custom-initializer';
|
||||
|
||||
export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
||||
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sustituye a `PiSharedUtilTranslateModule`: ngx-translate 18 ya no expone
|
||||
* `TranslateModule.forRoot()`, la configuración se hace con providers.
|
||||
*/
|
||||
export function providePiTranslate(): EnvironmentProviders {
|
||||
return makeEnvironmentProviders([
|
||||
provideTranslateService({
|
||||
fallbackLang: 'es',
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useFactory: createTranslateLoader,
|
||||
deps: [HttpClient],
|
||||
},
|
||||
}),
|
||||
provideAppInitializer(() => appInitializerFactory(inject(TranslateService))()),
|
||||
]);
|
||||
}
|
||||
18
libs/ui/src/lib/util/validator/definitions.ts
Normal file
18
libs/ui/src/lib/util/validator/definitions.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export const TextFieldMaxLength = 300;
|
||||
export const dniPattern = /^[\d]{8}[A-Za-z]{1}$/;
|
||||
export const niePattern = /^[A-Za-z]{1}[\d]{7}[A-Za-z]{1}$/;
|
||||
export const nifPattern = /^([A-Za-z][0-9]{8}|[0-9]{8}[A-Za-z])$/;
|
||||
export const urlPattern = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
|
||||
export const emailPattern =
|
||||
/^[A-Za-z0-9.+\-_]*@[A-Za-z0-9.\-_]*\.[A-Za-z]{1,20}$/;
|
||||
export const phonePattern = /^(\+34|0034|34)?[ -]*(6|7|8|9)[ -]*([0-9][ -]*){8}$/;
|
||||
export const passwordPattern = /^.{8,}$/;
|
||||
export const fieldNamePattern = /^[A-Za-z0-9_]*$/;
|
||||
export const onlyPositiveNumberPattern = /^[1-9]+[0-9]*$/;
|
||||
export const positiveNumbersWithDecimals = /^\d+([.,]\d{0,2})?$/;
|
||||
export const positiveNumbersIncludingZero = /^(0|\d+|\d+.\d+)$/;
|
||||
export const onlyNumbersPattern = /^[0-9]*$/;
|
||||
export const onlyNumbersDecimalsPattern = /^[0-9]*(\\,[0-9]{0,2})?$/;
|
||||
export const repeatedPattern = /^(?!.*(\w)\1{3,}).+$/;
|
||||
export const cognitoPhonePattern = /^\+[1-9]\d{10,14}$/;
|
||||
export const monthYearPattern = /^(0[1-9]|1[0-2])\/([0-9]{2})$/;
|
||||
2
libs/ui/src/lib/util/validator/index.ts
Normal file
2
libs/ui/src/lib/util/validator/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './definitions';
|
||||
export * from './utils';
|
||||
263
libs/ui/src/lib/util/validator/utils.ts
Normal file
263
libs/ui/src/lib/util/validator/utils.ts
Normal file
@@ -0,0 +1,263 @@
|
||||
import { AbstractControl, FormGroup, ValidationErrors, ValidatorFn } from '@angular/forms';
|
||||
import { environment } from '../environments';
|
||||
import {
|
||||
dniPattern,
|
||||
emailPattern,
|
||||
urlPattern,
|
||||
niePattern,
|
||||
nifPattern,
|
||||
onlyNumbersDecimalsPattern,
|
||||
onlyNumbersPattern,
|
||||
onlyPositiveNumberPattern,
|
||||
passwordPattern,
|
||||
phonePattern,
|
||||
positiveNumbersWithDecimals,
|
||||
positiveNumbersIncludingZero,
|
||||
repeatedPattern,
|
||||
cognitoPhonePattern,
|
||||
monthYearPattern,
|
||||
} from './definitions';
|
||||
|
||||
export function validateRequired(control: AbstractControl): ValidationErrors | null {
|
||||
const value: string = control.value as string;
|
||||
if (value === null || value === undefined || value === '' || value.length === 0) {
|
||||
return { message: ['common.validator.requiredField'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateRequiredIfDirty(control: AbstractControl): ValidationErrors | null {
|
||||
const value: string = control.value as string;
|
||||
if (value === null || value === undefined || value === '' || value.length === 0 || value === 'undefined') {
|
||||
if (control.dirty) {
|
||||
return { message: ['common.validator.requiredField'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateNotZero(control: AbstractControl): ValidationErrors | null {
|
||||
const value: number = control.value as number;
|
||||
if (value === 0) {
|
||||
return { message: ['common.validator.requiredField'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateRequiredWithoutMessage(control: AbstractControl): ValidationErrors | null {
|
||||
const value: boolean = control.value as boolean;
|
||||
if (!value) {
|
||||
return { message: [''] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validatePassword(control: AbstractControl): ValidationErrors | null {
|
||||
const password: string = control.value as string;
|
||||
if (password && !passwordPattern.test(password)) {
|
||||
return { message: ['common.validator.minimumPasswordCharacters'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateEmail(control: AbstractControl): ValidationErrors | null {
|
||||
const email: string = control.value as string;
|
||||
if (email && !emailPattern.test(email)) {
|
||||
return { message: ['common.validator.enterValidEmail'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateUrl(control: AbstractControl): ValidationErrors | null {
|
||||
const url: string = control.value as string;
|
||||
if (url && !urlPattern.test(url)) {
|
||||
return { message: ['common.validator.enterValidUrl'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validatePhone(control: AbstractControl): ValidationErrors | null {
|
||||
const phone: string = control.value as string;
|
||||
if (phone && !phonePattern.test(phone)) {
|
||||
return { message: ['common.validator.enterValidPhoneNumber'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateCognitoPhone(control: AbstractControl): ValidationErrors | null {
|
||||
const phone: string = control.value as string;
|
||||
if (phone && !cognitoPhonePattern.test(phone)) {
|
||||
return { message: ['common.validator.enterValidPhoneNumber'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateMaxLength(maxLength: number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const maxChars: string = control.value as string;
|
||||
if (maxChars && maxChars.length > maxLength) {
|
||||
return {
|
||||
message: [
|
||||
'common.validator.noMoreThanCharacters.1',
|
||||
`${maxLength}`,
|
||||
'common.validator.noMoreThanCharacters.2',
|
||||
],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
export function validateMinLength(minLength: number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const minChars: string = control.value as string;
|
||||
if (minChars && minChars.length <= minLength) {
|
||||
return {
|
||||
message: [
|
||||
'common.validator.noLessThanCharacters.1',
|
||||
`${minLength}`,
|
||||
'common.validator.noLessThanCharacters.2',
|
||||
],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
export function validateMaximumNumber(maximum: number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const num: number = control.value as number;
|
||||
if (maximum && num > Number(maximum)) {
|
||||
return {
|
||||
message: ['common.validator.noMoreThanMaxNumber.1', `${maximum}`],
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
export function validateMinimumNumber(minimum: number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const num: number = control.value as number;
|
||||
if (minimum && num < Number(minimum)) {
|
||||
return { message: ['common.validator.noLessThanMinNumbers', minimum] };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
export function validatePositiveNumber(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !onlyPositiveNumberPattern.test(num)) {
|
||||
return { message: ['common.validator.onlyPositiveNumbers'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateNif(control: AbstractControl): ValidationErrors | null {
|
||||
const nif: string = control.value as string;
|
||||
if (nif && !nifPattern.test(nif)) {
|
||||
return { message: ['common.validator.letterAndNumberNIF'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateNifInvestor(control: AbstractControl): ValidationErrors | null {
|
||||
const nif: string = control.value as string;
|
||||
if (nif && !nifPattern.test(nif) && !dniPattern.test(nif) && !niePattern.test(nif)) {
|
||||
return { message: ['common.validator.incorrectNIF'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateNifProd(control: AbstractControl): ValidationErrors | null {
|
||||
const nif: string = control.value as string;
|
||||
if (environment.production) {
|
||||
if (nif && (nif === 'A00000000' || nif === 'B00000000')) {
|
||||
return { message: ['common.validator.invalidNIF'] };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateOnlyNumbers(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !onlyNumbersPattern.test(num)) {
|
||||
return { message: ['common.validator.onlyNumbers'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateOnlyNumbersWithDecimals(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !onlyNumbersDecimalsPattern.test(num)) {
|
||||
return { message: ['common.validator.numbersWithDecimals'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validatePositiveNumbersWithDecimals(
|
||||
control: AbstractControl
|
||||
): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !positiveNumbersWithDecimals.test(num)) {
|
||||
return { message: ['common.validator.numbersWithDecimals'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validatePositiveNumbersIncludingZero(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !positiveNumbersIncludingZero.test(num)) {
|
||||
return { message: ['common.validator.positiveNumbersIncludingZero']}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateNotOnlyNumbers(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && onlyNumbersPattern.test(num)) {
|
||||
return { message: ['common.validator.notOnlyNumbers'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function notRepeatedChar(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !repeatedPattern.test(num)) {
|
||||
return { message: ['common.validator.incorrectName'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function validateMultipleChoiceRequired(control: AbstractControl): ValidationErrors | null {
|
||||
const choices: { [key: string]: boolean } = control.value as {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
let selected: boolean = false;
|
||||
|
||||
selected = !!choices ? Object.entries(choices)?.some(([key, value]) => value) : null;
|
||||
|
||||
if (choices && !selected) {
|
||||
return { message: ['common.validator.atLeastOneOption'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function rangeValidator(control: AbstractControl): ValidationErrors | null {
|
||||
const from = Number(control.get('from').value);
|
||||
const to = Number(control.get('to').value);
|
||||
if (!from || !to) return null;
|
||||
return from <= to
|
||||
? null
|
||||
: { message: ['common.validator.minNotSuperiorToMax'] };
|
||||
}
|
||||
|
||||
export function validateMonthYear(control: AbstractControl): ValidationErrors | null {
|
||||
const num: string = control.value as string;
|
||||
if (num && !monthYearPattern.test(num)) {
|
||||
return { message: ['common.validator.monthYear'] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
21
libs/ui/src/lib/util/value/directives/value.directive.ts
Normal file
21
libs/ui/src/lib/util/value/directives/value.directive.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Directive, HostBinding, Input } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
standalone: false,
|
||||
selector: '[pi-value]',
|
||||
})
|
||||
export class PiValueDirective {
|
||||
@HostBinding('class') get classes(): string | boolean {
|
||||
return ['pi-value', this.value > 0 ? 'is-positive' : 'is-negative'].join(' ');
|
||||
}
|
||||
|
||||
@Input() value!: number;
|
||||
|
||||
checkValue(): string {
|
||||
if (this.value > 0) {
|
||||
return 'is-positive';
|
||||
} else {
|
||||
return 'is-negative';
|
||||
}
|
||||
}
|
||||
}
|
||||
3
libs/ui/src/lib/util/value/index.ts
Normal file
3
libs/ui/src/lib/util/value/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './util-value.module';
|
||||
|
||||
export * from './directives/value.directive';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user