mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
feat: refactor return feature components; remove deprecated files and implement new search bar input
This commit is contained in:
@@ -43,7 +43,7 @@ const meta: Meta<UiSearchBarComponentInputs> = {
|
|||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
props: { ...args, control: new FormControl(args.value) },
|
props: { ...args, control: new FormControl(args.value) },
|
||||||
template: `<ui-search-bar ${argsToTemplate(args, { exclude: ['placeholder', 'value', 'resetValue'] })}>
|
template: `<ui-search-bar ${argsToTemplate(args, { exclude: ['placeholder', 'value', 'resetValue'] })}>
|
||||||
<input [formControl]="control" type="text" uiSearchBarInput placeholder="${args.placeholder}" />
|
<input [formControl]="control" type="text" placeholder="${args.placeholder}" />
|
||||||
<ui-search-bar-clear value="${args.resetValue}"></ui-search-bar-clear>
|
<ui-search-bar-clear value="${args.resetValue}"></ui-search-bar-clear>
|
||||||
<button type="submit" uiIconButton color="brand">
|
<button type="submit" uiIconButton color="brand">
|
||||||
<ng-icon name="isaActionSearch"></ng-icon>
|
<ng-icon name="isaActionSearch"></ng-icon>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { inject } from '@angular/core';
|
import { inject } from '@angular/core';
|
||||||
import { ProcessService } from './process.service';
|
import { ProcessService } from './process.service';
|
||||||
|
|
||||||
export function injectActivatedProcess() {
|
|
||||||
return inject(ProcessService).activatedProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function injectActivatedProcessId() {
|
export function injectActivatedProcessId() {
|
||||||
return inject(ProcessService).activatedProcessId;
|
return inject(ProcessService).activatedProcessId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function injectActivatedProcess() {
|
||||||
|
return inject(ProcessService).activatedProcess;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<h1 class="isa-typo-subtitle-1-regualr">Rückgabe starten</h1>
|
|
||||||
<p class="isa-typo-body-regular text-center">
|
|
||||||
Scannen Sie den QR-Code auf der Rechnung oder suchen Sie die Bestellung <br />
|
|
||||||
via Rechnungsnummer, E-Mail-Adresse oder Kundennamen
|
|
||||||
</p>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { FeatureReturnPagesComponent } from './feature-return-pages.component';
|
|
||||||
|
|
||||||
describe('FeatureReturnPagesComponent', () => {
|
|
||||||
let component: FeatureReturnPagesComponent;
|
|
||||||
let fixture: ComponentFixture<FeatureReturnPagesComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [FeatureReturnPagesComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(FeatureReturnPagesComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'lib-feature-return-pages',
|
|
||||||
imports: [CommonModule],
|
|
||||||
templateUrl: './feature-return-pages.component.html',
|
|
||||||
styleUrl: './feature-return-pages.component.css',
|
|
||||||
})
|
|
||||||
export class FeatureReturnPagesComponent {}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<h1 class="isa-text-subtitle-1-regular">Rückgabe starten</h1>
|
||||||
|
<p class="isa-text-body-1-regular text-center">
|
||||||
|
Scannen Sie den QR-Code auf der Rechnung oder suchen Sie die Bestellung <br />
|
||||||
|
via Rechnungsnummer, E-Mail-Adresse oder Kundennamen
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<filter-search-bar-input
|
||||||
|
groupName="main"
|
||||||
|
inputKey="qs"
|
||||||
|
(search)="onSearch()"
|
||||||
|
></filter-search-bar-input>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
padding: 3rem 1.5rem 0rem 1.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||||
|
import { ReturnSearchService } from '@feature/return/services';
|
||||||
|
import { injectActivatedProcessId } from '@isa/core/process';
|
||||||
|
import { FilterService, SearchBarInputComponent } from '@isa/shared/filter';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-main-page',
|
||||||
|
templateUrl: './main-page.component.html',
|
||||||
|
styleUrls: ['./main-page.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
standalone: true,
|
||||||
|
imports: [SearchBarInputComponent],
|
||||||
|
})
|
||||||
|
export class MainPageComponent {
|
||||||
|
processId = injectActivatedProcessId();
|
||||||
|
|
||||||
|
filterService = inject(FilterService);
|
||||||
|
|
||||||
|
returnSearchService = inject(ReturnSearchService);
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
this.returnSearchService
|
||||||
|
.search({
|
||||||
|
filter: this.filterService.toParams(),
|
||||||
|
})
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { inject } from '@angular/core';
|
||||||
|
import { ResolveFn } from '@angular/router';
|
||||||
|
import { ReturnSearchService } from '@feature/return/services';
|
||||||
|
import { QuerySettingsDTO } from '@generated/swagger/oms-api';
|
||||||
|
|
||||||
|
export const querySettingsResolverFn: ResolveFn<QuerySettingsDTO> = () =>
|
||||||
|
inject(ReturnSearchService).querySettings();
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<router-outlet></router-outlet>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
padding: 3rem 1.5rem 0rem 1.5rem;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
12
libs/feature/return/pages/src/lib/return-pages.component.ts
Normal file
12
libs/feature/return/pages/src/lib/return-pages.component.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { ActivatedRoute, RouterOutlet } from '@angular/router';
|
||||||
|
import { provideQuerySettings } from '@isa/shared/filter';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-return-pages',
|
||||||
|
imports: [RouterOutlet],
|
||||||
|
templateUrl: './return-pages.component.html',
|
||||||
|
styleUrl: './return-pages.component.scss',
|
||||||
|
providers: [provideQuerySettings(() => inject(ActivatedRoute).snapshot.data['querySettings'])],
|
||||||
|
})
|
||||||
|
export class ReturnPagesComponent {}
|
||||||
@@ -1,4 +1,13 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
import { FeatureReturnPagesComponent } from './feature-return-pages.component';
|
import { ReturnPagesComponent } from './return-pages.component';
|
||||||
|
import { querySettingsResolverFn } from './resolvers/query-settings.resolver-fn';
|
||||||
|
import { MainPageComponent } from './main/main-page.component';
|
||||||
|
|
||||||
export const routes: Routes = [{ path: '', component: FeatureReturnPagesComponent }];
|
export const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: ReturnPagesComponent,
|
||||||
|
resolve: { querySettings: querySettingsResolverFn },
|
||||||
|
children: [{ path: '', component: MainPageComponent }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from './lib/feature-return-services.component';
|
export * from './lib/return-search.service';
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<p>FeatureReturnServices works!</p>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { FeatureReturnServicesComponent } from './feature-return-services.component';
|
|
||||||
|
|
||||||
describe('FeatureReturnServicesComponent', () => {
|
|
||||||
let component: FeatureReturnServicesComponent;
|
|
||||||
let fixture: ComponentFixture<FeatureReturnServicesComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [FeatureReturnServicesComponent],
|
|
||||||
}).compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(FeatureReturnServicesComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { Component } from '@angular/core';
|
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'lib-feature-return-services',
|
|
||||||
imports: [CommonModule],
|
|
||||||
templateUrl: './feature-return-services.component.html',
|
|
||||||
styleUrl: './feature-return-services.component.css',
|
|
||||||
})
|
|
||||||
export class FeatureReturnServicesComponent {}
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const QueryTokenSchema = z.object({
|
||||||
|
filter: z.object({
|
||||||
|
qs: z.string().optional(),
|
||||||
|
}),
|
||||||
|
skip: z.number().default(0),
|
||||||
|
take: z.number().default(25),
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { QuerySettingsDTO, QueryTokenDTO, ReceiptService } from '@generated/swagger/oms-api';
|
||||||
|
import { map, Observable, throwError } from 'rxjs';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import * as Schemas from './return-search.schemas';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class ReturnSearchService {
|
||||||
|
#receiptService = inject(ReceiptService);
|
||||||
|
|
||||||
|
querySettings(): Observable<QuerySettingsDTO> {
|
||||||
|
return this.#receiptService.ReceiptQueryReceiptSettings().pipe(
|
||||||
|
map((res) => {
|
||||||
|
if (res.error || !res.result) {
|
||||||
|
throw new Error('Failed to fetch query settings');
|
||||||
|
}
|
||||||
|
return res.result;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(queryToken: z.input<typeof Schemas.QueryTokenSchema>): Observable<any> {
|
||||||
|
try {
|
||||||
|
queryToken = Schemas.QueryTokenSchema.parse(queryToken);
|
||||||
|
} catch (error) {
|
||||||
|
return throwError(() => error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#receiptService.ReceiptQueryReceipt({
|
||||||
|
queryToken,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
22
libs/feature/return/services/src/lib/return-search.store.ts
Normal file
22
libs/feature/return/services/src/lib/return-search.store.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { signalStore, withMethods } from '@ngrx/signals';
|
||||||
|
import {} from '@ngrx/operators';
|
||||||
|
import { withEntities } from '@ngrx/signals/entities';
|
||||||
|
import { pipe } from 'rxjs';
|
||||||
|
|
||||||
|
type ReturnSearuchState = {
|
||||||
|
id: number;
|
||||||
|
params: Record<string, string>;
|
||||||
|
results: string[];
|
||||||
|
hits: number;
|
||||||
|
status: 'idle' | 'pending' | 'success' | 'error';
|
||||||
|
error: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ReturnSearchStore = signalStore(
|
||||||
|
{ providedIn: 'root' },
|
||||||
|
withEntities<ReturnSearuchState>(),
|
||||||
|
// withMethods((store) => ({
|
||||||
|
// search: rxMethod<{ id: number; params: Record<string, string> }>(pipe()),
|
||||||
|
// paging: rxMethod<{ id: number }>(pipe()),
|
||||||
|
// })),
|
||||||
|
);
|
||||||
7
libs/shared/filter/README.md
Normal file
7
libs/shared/filter/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# shared-filter
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test shared-filter` to execute the unit tests.
|
||||||
34
libs/shared/filter/eslint.config.mjs
Normal file
34
libs/shared/filter/eslint.config.mjs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import nx from '@nx/eslint-plugin';
|
||||||
|
import baseConfig from '../../../eslint.config.mjs';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...baseConfig,
|
||||||
|
...nx.configs['flat/angular'],
|
||||||
|
...nx.configs['flat/angular-template'],
|
||||||
|
{
|
||||||
|
files: ['**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'@angular-eslint/directive-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'attribute',
|
||||||
|
prefix: 'filter',
|
||||||
|
style: 'camelCase',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@angular-eslint/component-selector': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
type: 'element',
|
||||||
|
prefix: 'filter',
|
||||||
|
style: 'kebab-case',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.html'],
|
||||||
|
// Override or add rules here
|
||||||
|
rules: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
21
libs/shared/filter/jest.config.ts
Normal file
21
libs/shared/filter/jest.config.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export default {
|
||||||
|
displayName: 'shared-filter',
|
||||||
|
preset: '../../../jest.preset.js',
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||||
|
coverageDirectory: '../../../coverage/libs/shared/filter',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.(ts|mjs|js|html)$': [
|
||||||
|
'jest-preset-angular',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||||
|
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||||
|
snapshotSerializers: [
|
||||||
|
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||||
|
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||||
|
'jest-preset-angular/build/serializers/html-comment',
|
||||||
|
],
|
||||||
|
};
|
||||||
20
libs/shared/filter/project.json
Normal file
20
libs/shared/filter/project.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-filter",
|
||||||
|
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "libs/shared/filter/src",
|
||||||
|
"prefix": "shared",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "libs/shared/filter/jest.config.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
libs/shared/filter/src/index.ts
Normal file
3
libs/shared/filter/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './lib/core';
|
||||||
|
export * from './lib/inputs';
|
||||||
|
export * from './lib/types';
|
||||||
57
libs/shared/filter/src/lib/core/filter.service.ts
Normal file
57
libs/shared/filter/src/lib/core/filter.service.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { inject, Injectable, InjectionToken, Provider } from '@angular/core';
|
||||||
|
import { InputType, QuerySettingsDTO } from '../types';
|
||||||
|
import { patchState, signalState } from '@ngrx/signals';
|
||||||
|
import { mapToFilter } from './mappings';
|
||||||
|
|
||||||
|
export const QUERY_SETTINGS = new InjectionToken<QuerySettingsDTO>('QuerySettings');
|
||||||
|
|
||||||
|
export function provideQuerySettings(factory: () => QuerySettingsDTO): Provider[] {
|
||||||
|
return [{ provide: QUERY_SETTINGS, useFactory: factory }, FilterService];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FilterService {
|
||||||
|
readonly settings = inject(QUERY_SETTINGS);
|
||||||
|
|
||||||
|
#state = signalState(mapToFilter(this.settings));
|
||||||
|
|
||||||
|
groups = this.#state.groups;
|
||||||
|
|
||||||
|
inputs = this.#state.inputs;
|
||||||
|
|
||||||
|
setInputValue(key: string, value: string | undefined): void {
|
||||||
|
const inputs = this.inputs().map((input) => {
|
||||||
|
if (input.key !== key) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.type === InputType.Text) {
|
||||||
|
return { ...input, value };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Input type not supported: ${input.type}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
patchState(this.#state, { inputs });
|
||||||
|
}
|
||||||
|
|
||||||
|
toParams(): Record<string, string> {
|
||||||
|
const params: Record<string, string> = {};
|
||||||
|
|
||||||
|
for (const input of this.inputs()) {
|
||||||
|
switch (input.type) {
|
||||||
|
case InputType.Text:
|
||||||
|
if (input.value) {
|
||||||
|
params[input.key] = input.value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseParams(params: Record<string, string>): void {
|
||||||
|
throw new Error('Not implemented');
|
||||||
|
}
|
||||||
|
}
|
||||||
3
libs/shared/filter/src/lib/core/index.ts
Normal file
3
libs/shared/filter/src/lib/core/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export * from './filter.service';
|
||||||
|
export * from './mappings';
|
||||||
|
export * from './schemas';
|
||||||
102
libs/shared/filter/src/lib/core/mappings.ts
Normal file
102
libs/shared/filter/src/lib/core/mappings.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { InputDTO, InputGroupDTO, InputType, OptionDTO, QuerySettingsDTO } from '../types';
|
||||||
|
import {
|
||||||
|
CheckboxFilterInput,
|
||||||
|
CheckboxFilterInputOption,
|
||||||
|
CheckboxFilterInputOptionSchema,
|
||||||
|
CheckboxFilterInputSchema,
|
||||||
|
DateRangeFilterInput,
|
||||||
|
DateRangeFilterInputSchema,
|
||||||
|
Filter,
|
||||||
|
FilterGroup,
|
||||||
|
FilterGroupSchema,
|
||||||
|
FilterInput,
|
||||||
|
TextFilterInput,
|
||||||
|
TextFilterInputSchema,
|
||||||
|
} from './schemas';
|
||||||
|
|
||||||
|
export function mapToFilter(settings: QuerySettingsDTO): Filter {
|
||||||
|
const filter: Filter = {
|
||||||
|
groups: [],
|
||||||
|
inputs: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const groups = [...settings.filter, ...settings.input];
|
||||||
|
|
||||||
|
for (const group of groups) {
|
||||||
|
filter.groups.push(mapToFilterGroup(group));
|
||||||
|
|
||||||
|
for (const input of group.input) {
|
||||||
|
filter.inputs.push(mapToFilterInput(group.group, input));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToFilterGroup(group: InputGroupDTO): FilterGroup {
|
||||||
|
return FilterGroupSchema.parse({
|
||||||
|
group: group.group,
|
||||||
|
label: group.label,
|
||||||
|
description: group.description,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToFilterInput(group: string, input: InputDTO): FilterInput {
|
||||||
|
switch (input.type) {
|
||||||
|
case InputType.Text:
|
||||||
|
return mapToTextFilterInput(group, input);
|
||||||
|
case InputType.Checkbox:
|
||||||
|
return mapToCheckboxFilterInput(group, input);
|
||||||
|
case InputType.DateRange:
|
||||||
|
return mapToDateRangeFilterInput(group, input);
|
||||||
|
}
|
||||||
|
throw new Error(`Unknown input type: ${input.type}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToTextFilterInput(group: string, input: InputDTO): TextFilterInput {
|
||||||
|
return TextFilterInputSchema.parse({
|
||||||
|
group,
|
||||||
|
key: input.key,
|
||||||
|
label: input.label,
|
||||||
|
description: input.description,
|
||||||
|
type: InputType.Text,
|
||||||
|
defaultValue: input.value,
|
||||||
|
value: input.value,
|
||||||
|
placeholder: input.placeholder,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToCheckboxFilterInput(group: string, input: InputDTO): CheckboxFilterInput {
|
||||||
|
return CheckboxFilterInputSchema.parse({
|
||||||
|
group,
|
||||||
|
key: input.key,
|
||||||
|
label: input.label,
|
||||||
|
description: input.description,
|
||||||
|
type: InputType.Checkbox,
|
||||||
|
defaultValue: input.value,
|
||||||
|
maxOptions: input.options?.max,
|
||||||
|
options: input.options?.values?.map(mapToCheckboxOption),
|
||||||
|
selected:
|
||||||
|
input.options?.values?.filter((option) => option.selected).map((option) => option.value) ||
|
||||||
|
[],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToCheckboxOption(option: OptionDTO): CheckboxFilterInputOption {
|
||||||
|
return CheckboxFilterInputOptionSchema.parse({
|
||||||
|
label: option.label,
|
||||||
|
value: option.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToDateRangeFilterInput(group: string, input: InputDTO): DateRangeFilterInput {
|
||||||
|
return DateRangeFilterInputSchema.parse({
|
||||||
|
group,
|
||||||
|
key: input.key,
|
||||||
|
label: input.label,
|
||||||
|
description: input.description,
|
||||||
|
type: InputType.DateRange,
|
||||||
|
start: input.options?.values?.[0].value,
|
||||||
|
stop: input.options?.values?.[1].value,
|
||||||
|
});
|
||||||
|
}
|
||||||
74
libs/shared/filter/src/lib/core/schemas.ts
Normal file
74
libs/shared/filter/src/lib/core/schemas.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import { InputType } from '../types';
|
||||||
|
|
||||||
|
export const FilterGroupSchema = z
|
||||||
|
.object({
|
||||||
|
group: z.string(),
|
||||||
|
label: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
})
|
||||||
|
.describe('FilterGroup');
|
||||||
|
|
||||||
|
export const CheckboxFilterInputOptionSchema = z
|
||||||
|
.object({
|
||||||
|
label: z.string(),
|
||||||
|
value: z.string(),
|
||||||
|
})
|
||||||
|
.describe('CheckboxFilterInputOption');
|
||||||
|
|
||||||
|
const BaseFilterInputSchema = z
|
||||||
|
.object({
|
||||||
|
group: z.string(),
|
||||||
|
key: z.string(),
|
||||||
|
label: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
type: z.nativeEnum(InputType),
|
||||||
|
})
|
||||||
|
.describe('BaseFilterInput');
|
||||||
|
|
||||||
|
export const TextFilterInputSchema = BaseFilterInputSchema.extend({
|
||||||
|
type: z.literal(InputType.Text),
|
||||||
|
placeholder: z.string().optional(),
|
||||||
|
defaultValue: z.string().optional(),
|
||||||
|
value: z.string().optional(),
|
||||||
|
}).describe('TextFilterInput');
|
||||||
|
|
||||||
|
export const CheckboxFilterInputSchema = BaseFilterInputSchema.extend({
|
||||||
|
type: z.literal(InputType.Checkbox),
|
||||||
|
maxOptions: z.number().optional(),
|
||||||
|
options: z.array(CheckboxFilterInputOptionSchema),
|
||||||
|
selected: z.array(z.string()),
|
||||||
|
}).describe('CheckboxFilterInput');
|
||||||
|
|
||||||
|
export const DateRangeFilterInputSchema = BaseFilterInputSchema.extend({
|
||||||
|
type: z.literal(InputType.DateRange),
|
||||||
|
start: z.string().optional(),
|
||||||
|
stop: z.string().optional(),
|
||||||
|
}).describe('DateRangeFilterInput');
|
||||||
|
|
||||||
|
export const FilterInputSchema = z.union([
|
||||||
|
TextFilterInputSchema,
|
||||||
|
CheckboxFilterInputSchema,
|
||||||
|
DateRangeFilterInputSchema,
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const FilterSchema = z
|
||||||
|
.object({
|
||||||
|
groups: z.array(FilterGroupSchema),
|
||||||
|
inputs: z.array(FilterInputSchema),
|
||||||
|
})
|
||||||
|
.describe('Filter');
|
||||||
|
|
||||||
|
export type Filter = z.infer<typeof FilterSchema>;
|
||||||
|
|
||||||
|
export type FilterGroup = z.infer<typeof FilterGroupSchema>;
|
||||||
|
|
||||||
|
export type TextFilterInput = z.infer<typeof TextFilterInputSchema>;
|
||||||
|
|
||||||
|
export type CheckboxFilterInput = z.infer<typeof CheckboxFilterInputSchema>;
|
||||||
|
|
||||||
|
export type FilterInput = z.infer<typeof FilterInputSchema>;
|
||||||
|
|
||||||
|
export type CheckboxFilterInputOption = z.infer<typeof CheckboxFilterInputOptionSchema>;
|
||||||
|
|
||||||
|
export type DateRangeFilterInput = z.infer<typeof DateRangeFilterInputSchema>;
|
||||||
1
libs/shared/filter/src/lib/inputs/index.ts
Normal file
1
libs/shared/filter/src/lib/inputs/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './search-bar-input';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './search-bar-input.component';
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
@let inp = input();
|
||||||
|
@if (inp) {
|
||||||
|
<ui-search-bar>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
[formControl]="control"
|
||||||
|
[placeholder]="inp.placeholder"
|
||||||
|
(keydown.enter)="onSearch()"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
uiIconButton
|
||||||
|
color="brand"
|
||||||
|
[disabled]="control.invalid"
|
||||||
|
(click)="onSearch()"
|
||||||
|
>
|
||||||
|
<ng-icon name="isaActionSearch"></ng-icon>
|
||||||
|
</button>
|
||||||
|
</ui-search-bar>
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
|
||||||
|
import { UiSearchBarComponent } from '@isa/ui/search-bar';
|
||||||
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { UiIconButtonComponent } from '@isa/ui/buttons';
|
||||||
|
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||||
|
import { isaActionSearch } from '@isa/icons';
|
||||||
|
import { FilterService, TextFilterInput } from '../../core';
|
||||||
|
import { InputType } from '../../types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'filter-search-bar-input',
|
||||||
|
templateUrl: './search-bar-input.component.html',
|
||||||
|
styleUrls: ['./search-bar-input.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
standalone: true,
|
||||||
|
imports: [UiSearchBarComponent, UiIconButtonComponent, NgIconComponent, ReactiveFormsModule],
|
||||||
|
providers: [provideIcons({ isaActionSearch })],
|
||||||
|
})
|
||||||
|
export class SearchBarInputComponent {
|
||||||
|
readonly filterService = inject(FilterService);
|
||||||
|
|
||||||
|
control = new FormControl();
|
||||||
|
|
||||||
|
inputKey = input.required<string>();
|
||||||
|
|
||||||
|
input = computed<TextFilterInput>(() => {
|
||||||
|
const inputs = this.filterService.inputs();
|
||||||
|
const input = inputs.find(
|
||||||
|
(input) => input.key === this.inputKey() && input.type === InputType.Text,
|
||||||
|
) as TextFilterInput;
|
||||||
|
|
||||||
|
if (!input) {
|
||||||
|
throw new Error(`Input not found for key: ${this.inputKey()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.control.setValue(input.value);
|
||||||
|
|
||||||
|
return input;
|
||||||
|
});
|
||||||
|
|
||||||
|
search = output();
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
this.filterService.setInputValue(this.inputKey(), this.control.value);
|
||||||
|
this.search.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
194
libs/shared/filter/src/lib/types.ts
Normal file
194
libs/shared/filter/src/lib/types.ts
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
export enum InputType {
|
||||||
|
Text = 1,
|
||||||
|
Checkbox = 2,
|
||||||
|
DateRange = 128,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuerySettingsDTO {
|
||||||
|
/**
|
||||||
|
* Filter
|
||||||
|
*/
|
||||||
|
filter: Array<InputGroupDTO>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eingabefelder
|
||||||
|
*/
|
||||||
|
input: Array<InputGroupDTO>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sortierung
|
||||||
|
*/
|
||||||
|
orderBy: Array<OrderByDTO>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InputGroupDTO {
|
||||||
|
/**
|
||||||
|
* Beschreibung
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group / ID
|
||||||
|
*/
|
||||||
|
group: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eingabefelder
|
||||||
|
*/
|
||||||
|
input: Array<InputDTO>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sortierwert
|
||||||
|
*/
|
||||||
|
export interface OrderByDTO {
|
||||||
|
/**
|
||||||
|
* Wert
|
||||||
|
*/
|
||||||
|
by?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absteigend
|
||||||
|
*/
|
||||||
|
desc?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eingabeelement
|
||||||
|
*/
|
||||||
|
export interface InputDTO {
|
||||||
|
/**
|
||||||
|
* Regex-Überprüfung
|
||||||
|
*/
|
||||||
|
constraint?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beschreibung
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key / ID
|
||||||
|
*/
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
label?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max-Wert (optional)
|
||||||
|
*/
|
||||||
|
maxValue?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Min-Wert (optional)
|
||||||
|
*/
|
||||||
|
minValue?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auswahl
|
||||||
|
*/
|
||||||
|
options?: InputOptionsDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wasserzeichen
|
||||||
|
*/
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anwendungsziel
|
||||||
|
*/
|
||||||
|
target?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Art des Werts
|
||||||
|
*/
|
||||||
|
type: InputType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wert
|
||||||
|
*/
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auswahl
|
||||||
|
*/
|
||||||
|
export interface InputOptionsDTO {
|
||||||
|
/**
|
||||||
|
* Maximale Anzahl auswählbarer Elemente (null => alle, 1 = single select)
|
||||||
|
*/
|
||||||
|
max?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Werte
|
||||||
|
*/
|
||||||
|
values?: Array<OptionDTO>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auswahlelement
|
||||||
|
*/
|
||||||
|
export interface OptionDTO {
|
||||||
|
/**
|
||||||
|
* Beschreibung
|
||||||
|
*/
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aktiv
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key / ID
|
||||||
|
*/
|
||||||
|
key?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label
|
||||||
|
*/
|
||||||
|
label?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max-Wert (optional)
|
||||||
|
*/
|
||||||
|
maxValue?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Min-Wert (optional)
|
||||||
|
*/
|
||||||
|
minValue?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wasserzeichen
|
||||||
|
*/
|
||||||
|
placeholder?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ausgewählt / Default
|
||||||
|
*/
|
||||||
|
selected?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wert
|
||||||
|
*/
|
||||||
|
value?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unter-Optionen
|
||||||
|
*/
|
||||||
|
values?: Array<OptionDTO>;
|
||||||
|
}
|
||||||
6
libs/shared/filter/src/test-setup.ts
Normal file
6
libs/shared/filter/src/test-setup.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
|
||||||
|
|
||||||
|
setupZoneTestEnv({
|
||||||
|
errorOnUnknownElements: true,
|
||||||
|
errorOnUnknownProperties: true,
|
||||||
|
});
|
||||||
28
libs/shared/filter/tsconfig.json
Normal file
28
libs/shared/filter/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2022",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../../tsconfig.base.json",
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
17
libs/shared/filter/tsconfig.lib.json
Normal file
17
libs/shared/filter/tsconfig.lib.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../dist/out-tsc",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/test-setup.ts",
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.test.ts"
|
||||||
|
],
|
||||||
|
"include": ["src/**/*.ts"]
|
||||||
|
}
|
||||||
16
libs/shared/filter/tsconfig.spec.json
Normal file
16
libs/shared/filter/tsconfig.spec.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../dist/out-tsc",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es2016",
|
||||||
|
"types": ["jest", "node"]
|
||||||
|
},
|
||||||
|
"files": ["src/test-setup.ts"],
|
||||||
|
"include": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
<ng-content select="[uiSearchBarInput]"></ng-content>
|
<ng-content select="input[type=text]"></ng-content>
|
||||||
|
|
||||||
@let control = inputControl();
|
|
||||||
|
|
||||||
<div class="ui-search-bar__actions">
|
<div class="ui-search-bar__actions">
|
||||||
<ng-content select="ui-search-bar-clear"></ng-content>
|
<ng-content select="ui-search-bar-clear"></ng-content>
|
||||||
|
|||||||
@@ -5,18 +5,14 @@ import {
|
|||||||
ElementRef,
|
ElementRef,
|
||||||
ViewEncapsulation,
|
ViewEncapsulation,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { isaActionClose } from '@isa/icons';
|
|
||||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
|
||||||
import { NgControl } from '@angular/forms';
|
import { NgControl } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ui-search-bar',
|
selector: 'ui-search-bar',
|
||||||
imports: [NgIconComponent],
|
|
||||||
templateUrl: './search-bar.component.html',
|
templateUrl: './search-bar.component.html',
|
||||||
styleUrl: './search-bar.component.scss',
|
styleUrl: './search-bar.component.scss',
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
providers: [provideIcons({ isaActionClose })],
|
|
||||||
host: {
|
host: {
|
||||||
'[class]': '["ui-search-bar"]',
|
'[class]': '["ui-search-bar"]',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,209 +1,209 @@
|
|||||||
const plugin = require("tailwindcss/plugin");
|
const plugin = require('tailwindcss/plugin');
|
||||||
|
|
||||||
module.exports = plugin(function ({ addBase, addUtilities }) {
|
module.exports = plugin(function ({ addBase, addUtilities }) {
|
||||||
addBase({
|
addBase({
|
||||||
".text-h1": { fontSize: "3.375rem", lineHeight: "4.5rem" },
|
'.text-h1': { fontSize: '3.375rem', lineHeight: '4.5rem' },
|
||||||
".text-h2": { fontSize: "1.625rem", lineHeight: "2.25rem" },
|
'.text-h2': { fontSize: '1.625rem', lineHeight: '2.25rem' },
|
||||||
".text-h3": { fontSize: "1.375rem", lineHeight: "1.75rem" },
|
'.text-h3': { fontSize: '1.375rem', lineHeight: '1.75rem' },
|
||||||
".text-p1": { fontSize: "1.125rem", lineHeight: "1.5rem" },
|
'.text-p1': { fontSize: '1.125rem', lineHeight: '1.5rem' },
|
||||||
".text-p2": { fontSize: "1rem", lineHeight: "1.313rem" },
|
'.text-p2': { fontSize: '1rem', lineHeight: '1.313rem' },
|
||||||
".text-p3": { fontSize: "0.875rem", lineHeight: "1.188rem" },
|
'.text-p3': { fontSize: '0.875rem', lineHeight: '1.188rem' },
|
||||||
".text-p4": { fontSize: "0.75rem", lineHeight: "1rem" },
|
'.text-p4': { fontSize: '0.75rem', lineHeight: '1rem' },
|
||||||
});
|
});
|
||||||
|
|
||||||
addUtilities({
|
addUtilities({
|
||||||
".isa-text-heading-1-bold": {
|
'.isa-text-heading-1-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "3.75rem",
|
fontSize: '3.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "4.5rem",
|
lineHeight: '4.5rem',
|
||||||
letterSpacing: "0.02813rem",
|
letterSpacing: '0.02813rem',
|
||||||
},
|
},
|
||||||
".isa-text-heading-2-bold": {
|
'.isa-text-heading-2-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "3rem",
|
fontSize: '3rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "4rem",
|
lineHeight: '4rem',
|
||||||
},
|
},
|
||||||
".isa-text-heading-3-bold": {
|
'.isa-text-heading-3-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "2.5rem",
|
fontSize: '2.5rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "3rem",
|
lineHeight: '3rem',
|
||||||
},
|
},
|
||||||
".isa-text-subtitle-1-regular": {
|
'.isa-text-subtitle-1-regular': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.75rem",
|
fontSize: '1.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "2.5rem",
|
lineHeight: '2.5rem',
|
||||||
},
|
},
|
||||||
".isa-text-subtitle-1-bold": {
|
'.isa-text-subtitle-1-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.75rem",
|
fontSize: '1.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "2.5rem",
|
lineHeight: '2.5rem',
|
||||||
},
|
},
|
||||||
".isa-text-subtitle-2-bold": {
|
'.isa-text-subtitle-2-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1rem",
|
fontSize: '1rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.5rem",
|
lineHeight: '1.5rem',
|
||||||
letterSpacing: "0.025rem",
|
letterSpacing: '0.025rem',
|
||||||
textTransform: "uppercase",
|
textTransform: 'uppercase',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-bold": {
|
'.isa-text-body-1-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1rem",
|
fontSize: '1rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.5rem",
|
lineHeight: '1.5rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-bold-big": {
|
'.isa-text-body-1-bold-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.25rem",
|
fontSize: '1.25rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.75rem",
|
lineHeight: '1.75rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-bold-xl": {
|
'.isa-text-body-1-bold-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.375rem",
|
fontSize: '1.375rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "2.125rem",
|
lineHeight: '2.125rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-semibold": {
|
'.isa-text-body-1-semibold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1rem",
|
fontSize: '1rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "600",
|
fontWeight: '600',
|
||||||
lineHeight: "1.5rem",
|
lineHeight: '1.5rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-regular": {
|
'.isa-text-body-1-regular': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1rem",
|
fontSize: '1rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.5rem",
|
lineHeight: '1.5rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-regular-big": {
|
'.isa-text-body-1-regular-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.25rem",
|
fontSize: '1.25rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.75rem",
|
lineHeight: '1.75rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-1-regular-xl": {
|
'.isa-text-body-1-regular-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.375rem",
|
fontSize: '1.375rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "2.125rem",
|
lineHeight: '2.125rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-bold": {
|
'.isa-text-body-2-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-bold-big": {
|
'.isa-text-body-2-bold-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.125rem",
|
fontSize: '1.125rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.625rem",
|
lineHeight: '1.625rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-bold-xl": {
|
'.isa-text-body-2-bold-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.25rem",
|
fontSize: '1.25rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.75rem",
|
lineHeight: '1.75rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-semibold": {
|
'.isa-text-body-2-semibold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "600",
|
fontWeight: '600',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-regular": {
|
'.isa-text-body-2-regular': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-regular-big": {
|
'.isa-text-body-2-regular-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.125rem",
|
fontSize: '1.125rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.625rem",
|
lineHeight: '1.625rem',
|
||||||
},
|
},
|
||||||
".isa-text-body-2-regular-xl": {
|
'.isa-text-body-2-regular-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "1.125rem",
|
fontSize: '1.125rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.75rem",
|
lineHeight: '1.75rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-bold": {
|
'.isa-text-caption-bold': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.75rem",
|
fontSize: '0.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1rem",
|
lineHeight: '1rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-bold-big": {
|
'.isa-text-caption-bold-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-bold-xl": {
|
'.isa-text-caption-bold-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-caps": {
|
'.isa-text-caption-caps': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.75rem",
|
fontSize: '0.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "700",
|
fontWeight: '700',
|
||||||
lineHeight: "1rem",
|
lineHeight: '1rem',
|
||||||
textTransform: "uppercase",
|
textTransform: 'uppercase',
|
||||||
},
|
},
|
||||||
".isa-text-caption-regular": {
|
'.isa-text-caption-regular': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.75rem",
|
fontSize: '0.75rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1rem",
|
lineHeight: '1rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-regular-big": {
|
'.isa-text-caption-regular-big': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
".isa-text-caption-regular-xl": {
|
'.isa-text-caption-regular-xl': {
|
||||||
fontFamily: "Open Sans",
|
fontFamily: 'Open Sans',
|
||||||
fontSize: "0.875rem",
|
fontSize: '0.875rem',
|
||||||
fontStyle: "normal",
|
fontStyle: 'normal',
|
||||||
fontWeight: "400",
|
fontWeight: '400',
|
||||||
lineHeight: "1.25rem",
|
lineHeight: '1.25rem',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const plugin = require('tailwindcss/plugin');
|
|||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ['./apps/**/*.{html,ts}'],
|
content: ['./apps/**/*.{html,ts}', './libs/**/*.{html,ts}'],
|
||||||
darkMode: 'media', // or 'media' or 'class',
|
darkMode: 'media', // or 'media' or 'class',
|
||||||
theme: {
|
theme: {
|
||||||
screens: {
|
screens: {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"@hub/*": ["apps/isa-app/src/hub/*/index.ts"],
|
"@hub/*": ["apps/isa-app/src/hub/*/index.ts"],
|
||||||
"@isa/core/process": ["libs/core/process/src/index.ts"],
|
"@isa/core/process": ["libs/core/process/src/index.ts"],
|
||||||
"@isa/icons": ["libs/icons/src/index.ts"],
|
"@isa/icons": ["libs/icons/src/index.ts"],
|
||||||
|
"@isa/shared/filter": ["libs/shared/filter/src/index.ts"],
|
||||||
"@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"],
|
"@isa/ui/buttons": ["libs/ui/buttons/src/index.ts"],
|
||||||
"@isa/ui/input-controls": ["libs/ui/input-controls/src/index.ts"],
|
"@isa/ui/input-controls": ["libs/ui/input-controls/src/index.ts"],
|
||||||
"@isa/ui/search-bar": ["libs/ui/search-bar/src/index.ts"],
|
"@isa/ui/search-bar": ["libs/ui/search-bar/src/index.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user