feat(core-tabs): Changes due to Renaming from Process to Tab and Unit Test Fixes

This commit is contained in:
Nino
2025-06-16 16:37:48 +02:00
parent e41dbc2870
commit befdc9fa4d
30 changed files with 139 additions and 207 deletions

View File

@@ -30,7 +30,7 @@ import {
ActivateProcessIdWithConfigKeyGuard, ActivateProcessIdWithConfigKeyGuard,
} from './guards/activate-process-id.guard'; } from './guards/activate-process-id.guard';
import { MatomoRouteData } from 'ngx-matomo-client'; import { MatomoRouteData } from 'ngx-matomo-client';
import { processResolverFn } from '@isa/core/tabs'; import { tabResolverFn } from '@isa/core/tabs';
import { provideScrollPositionRestoration } from '@isa/utils/scroll-position'; import { provideScrollPositionRestoration } from '@isa/utils/scroll-position';
const routes: Routes = [ const routes: Routes = [
@@ -180,9 +180,9 @@ const routes: Routes = [
], ],
}, },
{ {
path: ':processId', path: ':tabId',
component: MainComponent, component: MainComponent,
resolve: { process: processResolverFn }, resolve: { process: tabResolverFn, tab: tabResolverFn },
canActivate: [IsAuthenticatedGuard], canActivate: [IsAuthenticatedGuard],
children: [ children: [
{ {

View File

@@ -8,7 +8,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/product" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/product"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<div class="side-menu-group-item-icon"> <div class="side-menu-group-item-icon">
<shared-icon icon="import-contacts"></shared-icon> <shared-icon icon="import-contacts"></shared-icon>
</div> </div>
@@ -25,7 +25,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer"
(isActiveChange)="customerActive($event); focusSearchBox()" (isActiveChange)="customerActive($event); focusSearchBox()"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="person"></shared-icon> <shared-icon icon="person"></shared-icon>
</span> </span>
@@ -33,10 +33,12 @@
<button <button
class="side-menu-group-arrow" class="side-menu-group-arrow"
[class.side-menu-item-rotate]="customerExpanded" [class.side-menu-item-rotate]="customerExpanded"
(click)=" (click)="
$event.stopPropagation(); $event.preventDefault(); customerExpanded = !customerExpanded $event.stopPropagation();
" $event.preventDefault();
> customerExpanded = !customerExpanded
"
>
<shared-icon icon="keyboard-arrow-down"></shared-icon> <shared-icon icon="keyboard-arrow-down"></shared-icon>
</button> </button>
</a> </a>
@@ -52,7 +54,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer\/(\(search|search)" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer\/(\(search|search)"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Suchen</span> <span class="side-menu-group-item-label">Suchen</span>
</a> </a>
@@ -65,7 +67,7 @@
[queryParams]="customerCreateRoute.queryParams" [queryParams]="customerCreateRoute.queryParams"
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer\/(\(create|create)" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/customer\/(\(create|create)"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Erfassen</span> <span class="side-menu-group-item-label">Erfassen</span>
</a> </a>
@@ -81,7 +83,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/pickup-shelf" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/pickup-shelf"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="unarchive"></shared-icon> <shared-icon icon="unarchive"></shared-icon>
</span> </span>
@@ -93,11 +95,11 @@
(click)="closeSideMenu(); focusSearchBox()" (click)="closeSideMenu(); focusSearchBox()"
[routerLink]="[ [routerLink]="[
'/', '/',
processService.activatedProcess()?.id || processService.nextId(), processService.activatedTab()?.id || processService.nextId(),
'return', 'return',
]" ]"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<span class="side-menu-group-item-icon w-[2.375rem] h-12"> <span class="side-menu-group-item-icon w-[2.375rem] h-12">
<ng-icon name="isaNavigationReturn"></ng-icon> <ng-icon name="isaNavigationReturn"></ng-icon>
</span> </span>
@@ -112,7 +114,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/order" sharedRegexRouterLinkActiveTest="^\/kunde\/\d*\/order"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="deployed-code"></shared-icon> <shared-icon icon="deployed-code"></shared-icon>
</span> </span>
@@ -132,7 +134,7 @@
[queryParams]="taskCalenderNavigation.queryParams" [queryParams]="taskCalenderNavigation.queryParams"
routerLinkActive="active" routerLinkActive="active"
(isActiveChange)="focusSearchBox()" (isActiveChange)="focusSearchBox()"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="event-available"></shared-icon> <shared-icon icon="event-available"></shared-icon>
</span> </span>
@@ -146,7 +148,7 @@
[routerLink]="assortmentNavigation.path" [routerLink]="assortmentNavigation.path"
[queryParams]="assortmentNavigation.queryParams" [queryParams]="assortmentNavigation.queryParams"
routerLinkActive="active" routerLinkActive="active"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="shape-outline"></shared-icon> <shared-icon icon="shape-outline"></shared-icon>
</span> </span>
@@ -164,7 +166,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
sharedRegexRouterLinkActiveTest="^\/filiale\/(pickup-shelf|goods\/in)" sharedRegexRouterLinkActiveTest="^\/filiale\/(pickup-shelf|goods\/in)"
(isActiveChange)="shelfActive($event); focusSearchBox()" (isActiveChange)="shelfActive($event); focusSearchBox()"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="isa-abholfach"></shared-icon> <shared-icon icon="isa-abholfach"></shared-icon>
</span> </span>
@@ -172,10 +174,12 @@
<button <button
class="side-menu-group-arrow" class="side-menu-group-arrow"
[class.side-menu-item-rotate]="shelfExpanded" [class.side-menu-item-rotate]="shelfExpanded"
(click)=" (click)="
$event.stopPropagation(); $event.preventDefault(); shelfExpanded = !shelfExpanded $event.stopPropagation();
" $event.preventDefault();
> shelfExpanded = !shelfExpanded
"
>
<shared-icon icon="keyboard-arrow-down"></shared-icon> <shared-icon icon="keyboard-arrow-down"></shared-icon>
</button> </button>
</a> </a>
@@ -192,7 +196,7 @@
sharedRegexRouterLinkActive="active" sharedRegexRouterLinkActive="active"
[sharedRegexRouterLinkActiveTest]="'^\/filiale\/pickup-shelf'" [sharedRegexRouterLinkActiveTest]="'^\/filiale\/pickup-shelf'"
(isActiveChange)="shelfActive($event); focusSearchBox()" (isActiveChange)="shelfActive($event); focusSearchBox()"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Einbuchen</span> <span class="side-menu-group-item-label">Einbuchen</span>
</a> </a>
@@ -205,7 +209,7 @@
[class.active-child]="(currentShelfView$ | async) === 'reservation'" [class.active-child]="(currentShelfView$ | async) === 'reservation'"
routerLinkActive="active" routerLinkActive="active"
(isActiveChange)="shelfActive($event)" (isActiveChange)="shelfActive($event)"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Reservierung</span> <span class="side-menu-group-item-label">Reservierung</span>
</a> </a>
@@ -217,7 +221,7 @@
[class.active-child]="(currentShelfView$ | async) === 'cleanup'" [class.active-child]="(currentShelfView$ | async) === 'cleanup'"
routerLinkActive="active" routerLinkActive="active"
(isActiveChange)="shelfActive($event)" (isActiveChange)="shelfActive($event)"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Ausräumen</span> <span class="side-menu-group-item-label">Ausräumen</span>
</a> </a>
@@ -229,7 +233,7 @@
[class.active-child]="(currentShelfView$ | async) === 'remission'" [class.active-child]="(currentShelfView$ | async) === 'remission'"
routerLinkActive="active" routerLinkActive="active"
(isActiveChange)="shelfActive($event)" (isActiveChange)="shelfActive($event)"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Remi-Vorschau</span> <span class="side-menu-group-item-label">Remi-Vorschau</span>
</a> </a>
@@ -238,10 +242,12 @@
(click)="closeSideMenu()" (click)="closeSideMenu()"
[routerLink]="['/filiale', 'goods', 'in', 'list']" [routerLink]="['/filiale', 'goods', 'in', 'list']"
[queryParams]="{ view: 'wareneingangsliste' }" [queryParams]="{ view: 'wareneingangsliste' }"
[class.active-child]="(currentShelfView$ | async) === 'wareneingangsliste'" [class.active-child]="
(currentShelfView$ | async) === 'wareneingangsliste'
"
routerLinkActive="active" routerLinkActive="active"
(isActiveChange)="shelfActive($event)" (isActiveChange)="shelfActive($event)"
> >
<span class="side-menu-group-item-icon"></span> <span class="side-menu-group-item-icon"></span>
<span class="side-menu-group-item-label">Fehlende</span> <span class="side-menu-group-item-label">Fehlende</span>
</a> </a>
@@ -255,7 +261,7 @@
[routerLink]="remissionNavigation.path" [routerLink]="remissionNavigation.path"
[queryParams]="remissionNavigation.queryParams" [queryParams]="remissionNavigation.queryParams"
routerLinkActive="active" routerLinkActive="active"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="assignment-return"></shared-icon> <shared-icon icon="assignment-return"></shared-icon>
</span> </span>
@@ -270,7 +276,7 @@
[routerLink]="packageInspectionNavigation.path" [routerLink]="packageInspectionNavigation.path"
[queryParams]="packageInspectionNavigation.queryParams" [queryParams]="packageInspectionNavigation.queryParams"
routerLinkActive="active" routerLinkActive="active"
> >
<span class="side-menu-group-item-icon"> <span class="side-menu-group-item-icon">
<shared-icon icon="clipboard-check-outline"></shared-icon> <shared-icon icon="clipboard-check-outline"></shared-icon>
</span> </span>

View File

@@ -29,7 +29,7 @@ import {
ProductCatalogNavigationService, ProductCatalogNavigationService,
} from '@shared/services/navigation'; } from '@shared/services/navigation';
import { ProcessService } from '@isa/core/tabs'; import { TabService } from '@isa/core/tabs';
import { NgIconComponent, provideIcons } from '@ng-icons/core'; import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { isaNavigationReturn } from '@isa/icons'; import { isaNavigationReturn } from '@isa/icons';
@@ -49,7 +49,7 @@ import { isaNavigationReturn } from '@isa/icons';
providers: [provideIcons({ isaNavigationReturn })], providers: [provideIcons({ isaNavigationReturn })],
}) })
export class ShellSideMenuComponent { export class ShellSideMenuComponent {
processService = inject(ProcessService); processService = inject(TabService);
branchKey$ = this._stockService.StockCurrentBranch().pipe( branchKey$ = this._stockService.StockCurrentBranch().pipe(
retry(3), retry(3),

View File

@@ -1,89 +0,0 @@
const nx = require('@nx/eslint-plugin');
module.exports = [
...nx.configs['flat/base'],
...nx.configs['flat/typescript'],
...nx.configs['flat/javascript'],
{
ignores: ['**/dist'],
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
},
],
},
],
},
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
// Override or add rules here
rules: {},
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
];

View File

@@ -1,6 +1,7 @@
import nx from '@nx/eslint-plugin'; import nx from '@nx/eslint-plugin';
import eslintConfigPrettier from 'eslint-config-prettier/flat'; import eslintConfigPrettier from 'eslint-config-prettier/flat';
import prettierPlugin from 'eslint-plugin-prettier'; import prettierPlugin from 'eslint-plugin-prettier';
import jsoncEslintParser from 'jsonc-eslint-parser';
export default [ export default [
...nx.configs['flat/base'], ...nx.configs['flat/base'],
@@ -46,4 +47,18 @@ export default [
'prettier/prettier': 'error', 'prettier/prettier': 'error',
}, },
}, },
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: jsoncEslintParser,
},
},
]; ];

View File

@@ -1,5 +1,5 @@
export * from './lib/process'; export * from './lib/tab';
export * from './lib/process.injector'; export * from './lib/tab.injector';
export * from './lib/process.resolver-fn'; export * from './lib/tab.resolver-fn';
export * from './lib/process.schemas'; export * from './lib/tab.schemas';
export * from './lib/process.service'; export * from './lib/tab.service';

View File

@@ -1,6 +0,0 @@
import { inject } from '@angular/core';
import { ProcessService } from './process.service';
export function injectActivatedProcessId() {
return inject(ProcessService).activatedProcessId;
}

View File

@@ -1,20 +0,0 @@
import { ResolveFn } from '@angular/router';
import { ProcessService } from './process.service';
import { Process } from './process';
import { inject } from '@angular/core';
export const processResolverFn: ResolveFn<Process> = (route) => {
const id = parseInt(route.params['processId']);
const processService = inject(ProcessService);
let process = processService.entityMap()[id];
if (!process) {
process = processService.addProcess({
name: 'New Process',
tags: ['return'],
});
}
processService.activateProcess(process.id);
return process;
};

View File

View File

@@ -0,0 +1,6 @@
import { inject } from '@angular/core';
import { TabService } from './tab.service';
export function injectActivatedTabId() {
return inject(TabService).activatedTabId;
}

View File

@@ -0,0 +1,20 @@
import { ResolveFn } from '@angular/router';
import { TabService } from './tab.service';
import { Tab } from './tab';
import { inject } from '@angular/core';
export const tabResolverFn: ResolveFn<Tab> = (route) => {
const id = parseInt(route.params['tabId']);
const tabService = inject(TabService);
let tab = tabService.entityMap()[id];
if (!tab) {
tab = tabService.addTab({
name: 'Neuer Vorgang',
tags: [],
});
}
tabService.activateTab(tab.id);
return tab;
};

View File

@@ -1,11 +1,11 @@
import { z } from 'zod'; import { z } from 'zod';
export const AddProcessSchema = z.object({ export const AddTabSchema = z.object({
name: z.string().nonempty(), name: z.string().nonempty(),
tags: z.array(z.string()), tags: z.array(z.string()),
}); });
export const PatchProcessSchema = z.object({ export const PatchTabSchema = z.object({
name: z.string().nonempty().optional(), name: z.string().nonempty().optional(),
tags: z.array(z.string()).optional(), tags: z.array(z.string()).optional(),
}); });

View File

@@ -13,60 +13,60 @@ import {
updateEntity, updateEntity,
withEntities, withEntities,
} from '@ngrx/signals/entities'; } from '@ngrx/signals/entities';
import { Process } from './process'; import { Tab } from './tab';
import { z } from 'zod'; import { z } from 'zod';
import { AddProcessSchema, PatchProcessSchema } from './process.schemas'; import { AddTabSchema, PatchTabSchema } from './tab.schemas';
import { computed, effect } from '@angular/core'; import { computed, effect } from '@angular/core';
export const ProcessService = signalStore( export const TabService = signalStore(
{ providedIn: 'root' }, { providedIn: 'root' },
withState<{ activatedProcessId: number | null }>({ withState<{ activatedTabId: number | null }>({
activatedProcessId: null, activatedTabId: null,
}), }),
withEntities<Process>(), withEntities<Tab>(),
withComputed((store) => ({ withComputed((store) => ({
nextId: computed( nextId: computed(
() => Math.max(0, ...store.entities().map((e) => e.id)) + 1, () => Math.max(0, ...store.entities().map((e) => e.id)) + 1,
), ),
activatedProcess: computed<Process | null>(() => { activatedTab: computed<Tab | null>(() => {
const activeProcessId = store.activatedProcessId(); const activeTabId = store.activatedTabId();
if (activeProcessId === null) { if (activeTabId === null) {
return null; return null;
} }
return store.entities().find((e) => e.id === activeProcessId) ?? null; return store.entities().find((e) => e.id === activeTabId) ?? null;
}), }),
})), })),
withMethods((store) => ({ withMethods((store) => ({
addProcess(add: z.infer<typeof AddProcessSchema>) { addTab(add: z.infer<typeof AddTabSchema>) {
const parsed = AddProcessSchema.parse(add); const parsed = AddTabSchema.parse(add);
const process: Process = { const tab: Tab = {
name: parsed.name, name: parsed.name,
id: store.nextId(), id: store.nextId(),
createdAt: Date.now(), createdAt: Date.now(),
tags: parsed.tags, tags: parsed.tags,
}; };
patchState(store, addEntity(process)); patchState(store, addEntity(tab));
return process; return tab;
}, },
activateProcess(id: number) { activateTab(id: number) {
patchState(store, { patchState(store, {
...updateEntity({ id, changes: { activatedAt: Date.now() } }), ...updateEntity({ id, changes: { activatedAt: Date.now() } }),
activatedProcessId: id, activatedTabId: id,
}); });
}, },
patchProcess(id: number, changes: z.infer<typeof PatchProcessSchema>) { patchTab(id: number, changes: z.infer<typeof PatchTabSchema>) {
patchState( patchState(
store, store,
updateEntity({ id, changes: PatchProcessSchema.parse(changes) }), updateEntity({ id, changes: PatchTabSchema.parse(changes) }),
); );
}, },
removeProcess(id: number) { removeTab(id: number) {
patchState(store, removeEntity(id)); patchState(store, removeEntity(id));
}, },
})), })),
withHooks((store) => ({ withHooks((store) => ({
onInit() { onInit() {
const entitiesStr = localStorage.getItem('ProcessEntities'); const entitiesStr = localStorage.getItem('TabEntities');
if (entitiesStr) { if (entitiesStr) {
const entities = JSON.parse(entitiesStr); const entities = JSON.parse(entitiesStr);
patchState(store, addEntities(entities)); patchState(store, addEntities(entities));
@@ -74,7 +74,7 @@ export const ProcessService = signalStore(
effect(() => { effect(() => {
const state = store.entities(); const state = store.entities();
localStorage.setItem('ProcessEntities', JSON.stringify(state)); localStorage.setItem('TabEntities', JSON.stringify(state));
}); });
}, },
})), })),

View File

@@ -1,4 +1,4 @@
export interface Process { export interface Tab {
id: number; id: number;
name: string; name: string;
tags: string[]; tags: string[];

View File

@@ -1,7 +1,7 @@
import { createServiceFactory } from '@ngneat/spectator/jest'; import { createServiceFactory } from '@ngneat/spectator/jest';
import { ReturnProcessStore } from './return-process.store'; import { ReturnProcessStore } from './return-process.store';
import { IDBStorageProvider } from '@isa/core/storage'; import { IDBStorageProvider } from '@isa/core/storage';
import { ProcessService } from '@isa/core/tabs'; import { TabService } from '@isa/core/tabs';
import { patchState } from '@ngrx/signals'; import { patchState } from '@ngrx/signals';
import { setAllEntities, setEntity } from '@ngrx/signals/entities'; import { setAllEntities, setEntity } from '@ngrx/signals/entities';
import { unprotected } from '@ngrx/signals/testing'; import { unprotected } from '@ngrx/signals/testing';
@@ -47,7 +47,7 @@ const TEST_ITEMS: Record<number, ReturnProcess['receiptItem']> = {
describe('ReturnProcessStore', () => { describe('ReturnProcessStore', () => {
const createService = createServiceFactory({ const createService = createServiceFactory({
service: ReturnProcessStore, service: ReturnProcessStore,
mocks: [IDBStorageProvider, ProcessService], mocks: [IDBStorageProvider, TabService],
}); });
describe('Initialization', () => { describe('Initialization', () => {

View File

@@ -13,7 +13,7 @@ import {
} from '@ngrx/signals/entities'; } from '@ngrx/signals/entities';
import { IDBStorageProvider, withStorage } from '@isa/core/storage'; import { IDBStorageProvider, withStorage } from '@isa/core/storage';
import { computed, effect, inject } from '@angular/core'; import { computed, effect, inject } from '@angular/core';
import { ProcessService } from '@isa/core/tabs'; import { TabService } from '@isa/core/tabs';
import { Receipt, ReceiptItem, ReturnProcess } from '../models'; import { Receipt, ReceiptItem, ReturnProcess } from '../models';
import { import {
CreateReturnProcessError, CreateReturnProcessError,
@@ -194,17 +194,17 @@ export const ReturnProcessStore = signalStore(
}, },
})), })),
withHooks((store, processService = inject(ProcessService)) => ({ withHooks((store, tabService = inject(TabService)) => ({
/** /**
* Lifecycle hook that runs when the store is initialized. * Lifecycle hook that runs when the store is initialized.
* Sets up an effect to clean up orphaned entities that are no longer associated with active processes. * Sets up an effect to clean up orphaned entities that are no longer associated with active processes.
*/ */
onInit() { onInit() {
effect(() => { effect(() => {
const processIds = processService.ids(); const tabIds = tabService.ids();
const orphanedEntity = store const orphanedEntity = store
.entities() .entities()
.find((entity) => !processIds.includes(entity.processId)); .find((entity) => !tabIds.includes(entity.processId));
if (orphanedEntity) { if (orphanedEntity) {
store.removeAllEntitiesByProcessId(orphanedEntity.processId); store.removeAllEntitiesByProcessId(orphanedEntity.processId);
} }

View File

@@ -26,7 +26,7 @@ import {
import { ReceiptListItem } from '../models'; import { ReceiptListItem } from '../models';
import { Query } from '@isa/shared/filter'; import { Query } from '@isa/shared/filter';
import { SessionStorageProvider, withStorage } from '@isa/core/storage'; import { SessionStorageProvider, withStorage } from '@isa/core/storage';
import { ProcessService } from '@isa/core/tabs'; import { TabService } from '@isa/core/tabs';
/** /**
* Enum representing the status of a return search process. * Enum representing the status of a return search process.
@@ -262,13 +262,13 @@ export const ReturnSearchStore = signalStore(
), ),
), ),
})), })),
withHooks((store, processService = inject(ProcessService)) => ({ withHooks((store, tabService = inject(TabService)) => ({
onInit() { onInit() {
effect(() => { effect(() => {
const processIds = processService.ids(); const tabIds = tabService.ids();
const orphanedEntity = store const orphanedEntity = store
.entities() .entities()
.find((entity) => !processIds.includes(entity.processId)); .find((entity) => !tabIds.includes(entity.processId));
if (orphanedEntity) { if (orphanedEntity) {
store.removeAllEntitiesByProcessId(orphanedEntity.processId); store.removeAllEntitiesByProcessId(orphanedEntity.processId);
} }

View File

@@ -13,7 +13,7 @@ import { z } from 'zod';
import { NgIconComponent, provideIcons } from '@ng-icons/core'; import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { isaActionChevronLeft } from '@isa/icons'; import { isaActionChevronLeft } from '@isa/icons';
import { ButtonComponent } from '@isa/ui/buttons'; import { ButtonComponent } from '@isa/ui/buttons';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { ExpandableDirectives } from '@isa/ui/expandable'; import { ExpandableDirectives } from '@isa/ui/expandable';
import { ProgressBarComponent } from '@isa/ui/progress-bar'; import { ProgressBarComponent } from '@isa/ui/progress-bar';
@@ -53,7 +53,7 @@ export class ReturnDetailsComponent {
#returnDetailsService = inject(ReturnDetailsService); #returnDetailsService = inject(ReturnDetailsService);
#returnProcessStore = inject(ReturnProcessStore); #returnProcessStore = inject(ReturnProcessStore);
private processId = injectActivatedProcessId(); private processId = injectActivatedTabId();
private _router = inject(Router); private _router = inject(Router);

View File

@@ -20,8 +20,8 @@ import { ReturnProcessItemComponent } from './return-process-item/return-process
import { ReturnProcessComponent } from './return-process.component'; import { ReturnProcessComponent } from './return-process.component';
const mockActivatedProcessIdSignal = signal<number | null>(123); const mockActivatedProcessIdSignal = signal<number | null>(123);
jest.mock('@isa/core/process', () => ({ jest.mock('@isa/core/tabs', () => ({
injectActivatedProcessId: jest.fn(() => mockActivatedProcessIdSignal), injectActivatedTabId: jest.fn(() => mockActivatedProcessIdSignal),
})); }));
jest.mock('scandit-web-datacapture-core', () => ({})); jest.mock('scandit-web-datacapture-core', () => ({}));

View File

@@ -18,7 +18,7 @@ import {
ReturnProcessService, ReturnProcessService,
ReturnProcessStore, ReturnProcessStore,
} from '@isa/oms/data-access'; } from '@isa/oms/data-access';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { ReturnProcessItemComponent } from './return-process-item/return-process-item.component'; import { ReturnProcessItemComponent } from './return-process-item/return-process-item.component';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { RouterLink } from '@angular/router'; import { RouterLink } from '@angular/router';
@@ -58,7 +58,7 @@ export class ReturnProcessComponent {
#logger = logger(); #logger = logger();
/** Signal emitting the numeric ID of the currently active return process, derived from the route parameters. Null if no ID is present. */ /** Signal emitting the numeric ID of the currently active return process, derived from the route parameters. Null if no ID is present. */
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
#returnCanReturnService = inject(ReturnCanReturnService); #returnCanReturnService = inject(ReturnCanReturnService);

View File

@@ -1,7 +1,7 @@
import { computed, inject, Injectable } from '@angular/core'; import { computed, inject, Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router'; import { CanDeactivate } from '@angular/router';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { ReturnTaskListStore } from '@isa/oms/data-access'; import { ReturnTaskListStore } from '@isa/oms/data-access';
import { ReturnReviewComponent } from '../return-review.component'; import { ReturnReviewComponent } from '../return-review.component';
import { ConfirmationDialogComponent, injectDialog } from '@isa/ui/dialog'; import { ConfirmationDialogComponent, injectDialog } from '@isa/ui/dialog';
@@ -16,7 +16,7 @@ export class UncompletedTasksGuard
'Aufgaben erledigen', 'Aufgaben erledigen',
); );
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
uncompletedTaskListItems = computed(() => { uncompletedTaskListItems = computed(() => {
const processId = this.processId(); const processId = this.processId();

View File

@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { PrintReceiptsService, ReturnProcessStore } from '@isa/oms/data-access'; import { PrintReceiptsService, ReturnProcessStore } from '@isa/oms/data-access';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { ReturnTaskListComponent } from '@isa/oms/shared/task-list'; import { ReturnTaskListComponent } from '@isa/oms/shared/task-list';
import { ReturnReviewHeaderComponent } from './return-review-header/return-review-header.component'; import { ReturnReviewHeaderComponent } from './return-review-header/return-review-header.component';
@@ -15,7 +15,7 @@ import { ReturnReviewHeaderComponent } from './return-review-header/return-revie
export class ReturnReviewComponent { export class ReturnReviewComponent {
#printReceiptsService = inject(PrintReceiptsService); #printReceiptsService = inject(PrintReceiptsService);
#returnProcessStore = inject(ReturnProcessStore); #returnProcessStore = inject(ReturnProcessStore);
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
async printReceipt() { async printReceipt() {
const processId = this.processId(); const processId = this.processId();

View File

@@ -6,7 +6,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { CallbackResult, ListResponseArgs } from '@isa/common/data-access'; import { CallbackResult, ListResponseArgs } from '@isa/common/data-access';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { import {
ReceiptListItem, ReceiptListItem,
ReturnSearchStatus, ReturnSearchStatus,
@@ -38,7 +38,7 @@ export class ReturnSearchMainComponent {
#route = inject(ActivatedRoute); #route = inject(ActivatedRoute);
#router = inject(Router); #router = inject(Router);
private _processId = injectActivatedProcessId(); private _processId = injectActivatedTabId();
private _filterService = inject(FilterService); private _filterService = inject(FilterService);
private _returnSearchStore = inject(ReturnSearchStore); private _returnSearchStore = inject(ReturnSearchStore);

View File

@@ -6,7 +6,7 @@ import {
inject, inject,
linkedSignal, linkedSignal,
} from '@angular/core'; } from '@angular/core';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { import {
@@ -72,7 +72,7 @@ export class ReturnSearchResultComponent implements AfterViewInit {
restoreScrollPosition = injectRestoreScrollPosition(); restoreScrollPosition = injectRestoreScrollPosition();
/** Current process ID from the activated route */ /** Current process ID from the activated route */
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
/** Store for managing return search data and operations */ /** Store for managing return search data and operations */
returnSearchStore = inject(ReturnSearchStore); returnSearchStore = inject(ReturnSearchStore);

View File

@@ -9,8 +9,8 @@ import {
import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component'; import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
jest.mock('@isa/core/process', () => ({ jest.mock('@isa/core/tabs', () => ({
injectActivatedProcessId: () => jest.fn(() => 1), injectActivatedTabId: () => jest.fn(() => 1),
})); }));
const MOCK_RETURN_PROCESSES: ReturnProcess[] = [ const MOCK_RETURN_PROCESSES: ReturnProcess[] = [

View File

@@ -6,7 +6,7 @@ import {
signal, signal,
} from '@angular/core'; } from '@angular/core';
import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component'; import { ReturnSummaryItemComponent } from './return-summary-item/return-summary-item.component';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { import {
ReturnProcess, ReturnProcess,
ReturnProcessService, ReturnProcessService,
@@ -55,7 +55,7 @@ export class ReturnSummaryComponent {
location = inject(Location); location = inject(Location);
/** The active process ID from the current route */ /** The active process ID from the current route */
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
/** Filtered list of return processes for the current process ID */ /** Filtered list of return processes for the current process ID */
returnProcesses = computed<ReturnProcess[]>(() => { returnProcesses = computed<ReturnProcess[]>(() => {

View File

@@ -20,7 +20,7 @@ import {
} from '@isa/oms/data-access'; } from '@isa/oms/data-access';
import { IconButtonComponent } from '@isa/ui/buttons'; import { IconButtonComponent } from '@isa/ui/buttons';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { injectActivatedProcessId } from '@isa/core/tabs'; import { injectActivatedTabId } from '@isa/core/tabs';
import { logger, provideLoggerContext } from '@isa/core/logging'; import { logger, provideLoggerContext } from '@isa/core/logging';
// TODO: Komponente und logik benötigt review // TODO: Komponente und logik benötigt review
@@ -45,7 +45,7 @@ export class ReturnTaskListComponent {
#returnTaskListStore = inject(ReturnTaskListStore); #returnTaskListStore = inject(ReturnTaskListStore);
#logger = logger(); #logger = logger();
processId = injectActivatedProcessId(); processId = injectActivatedTabId();
appearanceClass = computed( appearanceClass = computed(
() => `oms-shared-return-task-list__${this.appearance()}`, () => `oms-shared-return-task-list__${this.appearance()}`,