Added some components & styles

This commit is contained in:
Adina Țeudan 2021-10-02 15:44:19 +03:00
parent 25d66040d0
commit 53f8f0af29
11 changed files with 261 additions and 6 deletions

14
src/assets/icons/logout.svg Executable file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg height="14px" version="1.1" viewBox="0 0 17 14" width="17px" xmlns="http://www.w3.org/2000/svg"
>
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<defs></defs>
<g fill="none" fill-rule="evenodd" id="Artboard" stroke="none" stroke-width="1"
transform="translate(-488.000000, -4752.000000)">
<g fill="currentColor" id="User-Menu" transform="translate(456.000000, 4454.000000)">
<path
d="M48.7966936,304.522526 C49.0677688,304.796017 49.0677688,305.203983 48.7966936,305.477474 L46.4800677,307.794882 C46.2071762,308.068373 45.7989742,308.068373 45.5260828,307.794882 L45.0488633,307.317862 L46.6839417,305.681457 L38.6810935,305.681457 C38.3069461,305.681457 38,305.374347 38,305 C38,304.625653 38.3069461,304.318543 38.6810935,304.318543 L46.6839417,304.318543 L45.0488633,302.682138 L45.5260828,302.205118 C45.7989742,301.931627 46.2071762,301.931627 46.4800677,302.205118 L48.7966936,304.522526 Z M35.5184445,312 C33.6163541,312 32.0629803,310.462957 32,308.500218 L32,301.499782 C32.0629803,299.537043 33.6163541,298 35.5184445,298 L39.6083615,298 C41.4791731,298 42.9682985,299.571064 43,301.499782 C43,301.891457 42.7142638,302.186304 42.3342684,302.186304 C41.9546957,302.186304 41.6689594,301.891457 41.6689594,301.499782 C41.6689594,300.322138 40.7491931,299.373481 39.6083615,299.373481 L35.5184445,299.373481 C34.377613,299.373481 33.395289,300.289862 33.3310406,301.499782 L33.3310406,308.500218 C33.3935982,309.677862 34.3446434,310.626519 35.5184445,310.626519 L39.6083615,310.626519 C40.7491931,310.626519 41.6689594,309.677862 41.6689594,308.500218 C41.6689594,308.108543 41.9546957,307.813696 42.3342684,307.813696 C42.7142638,307.813696 43,308.108543 43,308.500218 C43,310.430681 41.4774823,312 39.6083615,312 L35.5184445,312 Z"
id="logout_icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,8 @@
<svg height="384pt" viewBox="0 -53 384 384" width="384pt" xmlns="http://www.w3.org/2000/svg">
<path
d="m368 154.667969h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/>
<path
d="m368 32h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/>
<path
d="m368 277.332031h-352c-8.832031 0-16-7.167969-16-16s7.167969-16 16-16h352c8.832031 0 16 7.167969 16 16s-7.167969 16-16 16zm0 0"/>
</svg>

After

Width:  |  Height:  |  Size: 525 B

View File

@ -0,0 +1,90 @@
.oval,
.square {
font-weight: 600;
display: flex;
justify-content: center;
align-items: center;
height: 24px;
width: 24px;
min-width: 24px;
font-size: 10px;
line-height: 12px;
text-align: center;
text-transform: uppercase;
border: none;
box-sizing: border-box;
&.large {
height: 32px;
width: 32px;
font-size: 13px;
}
&.gray-dark {
background-color: var(--iqser-grey-6);
}
&.gray-primary {
background-color: var(--iqser-grey-6);
color: var(--iqser-primary);
}
&.lightgray-dark {
background-color: var(--iqser-grey-4);
}
&.lightgray-primary {
background-color: var(--iqser-grey-4);
color: var(--iqser-primary);
}
&.darkgray-white {
background-color: var(--iqser-accent);
color: var(--iqser-white);
}
&.lightgray-white {
background-color: var(--iqser-grey-5);
color: var(--iqser-white);
}
&.primary--white {
background-color: var(--iqser-primary);
color: var(--iqser-white);
}
&.white-dark {
border: 1px solid var(--iqser-grey-4);
}
&.inactive {
background-color: var(--iqser-grey-6);
color: var(--iqser-grey-7);
}
}
.oval {
border-radius: 50%;
}
.stats-subtitle {
display: flex;
> div {
display: flex;
justify-content: center;
align-items: center;
width: fit-content;
mat-icon {
width: 10px;
height: 10px;
line-height: 13px;
margin-right: 6px;
}
&:not(:last-child) {
margin-right: 12px;
}
}
}

View File

@ -5,3 +5,4 @@
@use 'common-full-pages';
@use 'common-layout';
@use 'common-dialogs';
@use 'common-components';

View File

@ -6,7 +6,7 @@ import { DomSanitizer } from '@angular/platform-browser';
@NgModule({
imports: [CommonModule, MatIconModule],
declarations: [],
exports: [MatIconModule]
exports: [MatIconModule],
})
export class IqserIconsModule {
constructor(private readonly _iconRegistry: MatIconRegistry, private readonly _sanitizer: DomSanitizer) {
@ -20,14 +20,20 @@ export class IqserIconsModule {
'help-outline',
'lanes',
'list',
'logout',
'menu',
'offline',
'refresh',
'search',
'sort-asc',
'sort-desc'
'sort-desc',
]);
icons.forEach(icon => {
_iconRegistry.addSvgIconInNamespace('iqser', icon, _sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/${icon}.svg`));
_iconRegistry.addSvgIconInNamespace(
'iqser',
icon,
_sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/${icon}.svg`),
);
});
}
}

View File

@ -0,0 +1,40 @@
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Injectable, InjectionToken, Injector } from '@angular/core';
import { from, of } from 'rxjs';
import { LoadingService } from '../loading';
@Injectable({
providedIn: 'root',
})
export class CompositeRouteGuard implements CanActivate {
constructor(protected readonly _injector: Injector, private readonly _loadingService: LoadingService) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
this._loadingService.start();
const routeGuards = <InjectionToken<CanActivate>[]>route.data.routeGuards;
if (routeGuards) {
for (let i = 0; i < routeGuards.length; i++) {
const routeGuard = this._injector.get<CanActivate>(routeGuards[i]);
let canActivateResult = routeGuard.canActivate(route, state);
if (canActivateResult instanceof Promise) {
canActivateResult = from(canActivateResult);
}
if (typeof canActivateResult === 'boolean' || canActivateResult instanceof UrlTree) {
canActivateResult = of(canActivateResult);
}
const result = await canActivateResult.toPromise();
if (!result) {
this._loadingService.stop();
return false;
}
}
}
this._loadingService.stop();
return true;
}
}

View File

@ -0,0 +1,56 @@
import { Injectable } from '@angular/core';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { ComponentType } from '@angular/cdk/portal';
export const largeDialogConfig: MatDialogConfig = {
width: '90vw',
maxWidth: '90vw',
maxHeight: '90vh',
autoFocus: false,
} as const;
export const defaultDialogConfig: MatDialogConfig = {
width: '662px',
maxWidth: '90vw',
autoFocus: false,
} as const;
@Injectable()
export abstract class DialogService<T extends string> {
protected readonly _config: {
[key in T]: {
component: ComponentType<unknown>;
dialogConfig?: MatDialogConfig;
};
};
protected constructor(protected readonly _dialog: MatDialog) {}
openDialog(
type: T,
$event: MouseEvent,
data: unknown,
cb?: (...params) => unknown,
finallyCb?: (...params) => unknown | Promise<unknown>,
): MatDialogRef<unknown> {
const config = this._config[type];
$event?.stopPropagation();
const ref = this._dialog.open(config.component, {
...defaultDialogConfig,
...(config.dialogConfig || {}),
data,
});
// eslint-disable-next-line @typescript-eslint/no-misused-promises
ref.afterClosed().subscribe(async result => {
if (result && cb) {
await cb(result);
}
if (finallyCb) {
await finallyCb(result);
}
});
return ref;
}
}

View File

@ -1,3 +1,5 @@
export * from './dialog.service';
export * from './toaster.service';
export * from './error-message.service';
export * from './generic.service';
export * from './composite-route.guard';

View File

@ -1,15 +1,15 @@
import {tap} from 'rxjs/operators';
import { tap } from 'rxjs/operators';
export function capitalize(value: string): string {
if (!value) {
return "";
return '';
}
return value.charAt(0).toUpperCase() + value.slice(1);
}
export function humanize(value: string, lowercase = true): string {
if (!value) {
return "";
return '';
}
const words = (lowercase ? value.toLowerCase() : value).split(/[ \-_]+/);
@ -17,3 +17,11 @@ export function humanize(value: string, lowercase = true): string {
}
export const log = tap(console.log);
export const toNumber = (str: string) => {
try {
return parseInt(`${str}`.replace(/\D/g, ''), 10);
} catch (e) {
return 0;
}
};

View File

@ -12,3 +12,4 @@ export * from './decorators/debounce.decorator';
export * from './decorators/on-change.decorator';
export * from './http-encoder';
export * from './types/iqser-types';
export * from './pruning-translation-loader';

View File

@ -0,0 +1,29 @@
import { HttpClient } from '@angular/common/http';
import { TranslateLoader } from '@ngx-translate/core';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
export class PruningTranslationLoader implements TranslateLoader {
constructor(private _http: HttpClient, private _prefix: string, private _suffix: string) {}
getTranslation(lang: string): Observable<Record<string, unknown>> {
return this._http
.get(`${this._prefix}${lang}${this._suffix}`)
.pipe(map((result: Record<string, unknown>) => this._process(result)));
}
private _process(object: unknown): Record<string, unknown> {
return (
Object.keys(object)
// eslint-disable-next-line no-prototype-builtins
.filter(key => object.hasOwnProperty(key) && object[key] !== '')
.reduce(
(result: Record<string, unknown>, key) => (
(result[key] = typeof object[key] === 'object' ? this._process(object[key]) : object[key]),
result
),
{},
)
);
}
}