diff --git a/alfa-client/apps/admin-e2e/docker-compose.yml b/alfa-client/apps/admin-e2e/docker-compose.yml index 11682ebeb086ca5740d4da1b5c3c2feaa34aaee1..4f0c0b6c814346008f80e5aab0c7443933e650b9 100644 --- a/alfa-client/apps/admin-e2e/docker-compose.yml +++ b/alfa-client/apps/admin-e2e/docker-compose.yml @@ -33,7 +33,7 @@ services: volumes: - mongodb:/data/db healthcheck: - test: [ 'CMD', 'mongosh', '--eval', 'db.settings.find()' ] + test: ['CMD', 'mongosh', '--eval', 'db.settings.find()'] interval: 10s timeout: 5s retries: 5 @@ -79,7 +79,7 @@ services: depends_on: - user-manager extra_hosts: - - "host.docker.internal:host-gateway" + - 'host.docker.internal:host-gateway' alfa-cors-proxy: image: alfa-cors-proxy @@ -91,7 +91,6 @@ services: alfa: condition: service_started - user-manager: image: docker.ozg-sh.de/user-manager:${USER_MANAGER_DOCKER_IMAGE:-snapshot-latest} platform: linux/amd64 @@ -132,6 +131,7 @@ services: - SPRING_DATA_MONGODB_URI=mongodb://mongodb:27017/config-db - OZGCLOUD_OAUTH2_REALM=${KEYCLOAK_REALM:-by-e2e-tests-local-dev} - ozgcloud_organisationeinheit_zufisearchuri=http://localhost:8082/api/organisationseinheits + - OZGCLOUD_USER-ASSISTANCE_DOCUMENTATION_URL=http://dummy-leitfaden.url - BPL_DEBUG_ENABLED=true - BPL_DEBUG_PORT=5100 ports: @@ -145,4 +145,4 @@ services: user-manager: condition: service_started extra_hosts: - - "host.docker.internal:host-gateway" + - 'host.docker.internal:host-gateway' diff --git a/alfa-client/apps/admin-e2e/src/components/user-profile/current-user-profile.component.e2e.ts b/alfa-client/apps/admin-e2e/src/components/user-profile/current-user-profile.component.e2e.ts index b96370d68b65cf7848e13b6eb5807473aadb40a3..effa3edb707cf24d98306dc972fefae6770b154e 100644 --- a/alfa-client/apps/admin-e2e/src/components/user-profile/current-user-profile.component.e2e.ts +++ b/alfa-client/apps/admin-e2e/src/components/user-profile/current-user-profile.component.e2e.ts @@ -26,6 +26,7 @@ import { UserProfileE2EComponent } from './user-profile.component.e2e'; export class CurrentUserProfileE2EComponent { private readonly locatorUserIconButton: string = 'popup-button-content'; private readonly locatorLogoutButton: string = 'popup-logout-button'; + private readonly locatorDocumentation: string = 'admin-documentation'; private readonly locatorRoot: string = 'current-user'; @@ -46,7 +47,11 @@ export class CurrentUserProfileE2EComponent { return cy.getTestElement(this.locatorUserIconButton); } - private getLogoutButton() { + public getLogoutButton() { return cy.getTestElement(this.locatorLogoutButton); } + + public getDocumentation() { + return cy.getTestElement(this.locatorDocumentation); + } } diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/user-profile-menu.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/user-profile-menu.cy.ts new file mode 100644 index 0000000000000000000000000000000000000000..80d2884a5bf5889a1a14a1b29970031b7f571144 --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/app/user-profile-menu.cy.ts @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +import { HeaderE2EComponent } from '../../../page-objects/header.po'; +import { MainPage } from '../../../page-objects/main.po'; +import { exist, shouldHaveAttribute } from '../../../support/cypress.util'; +import { loginAsAriane } from '../../../support/user-util'; + +describe('User Profile Menu', () => { + const mainPage: MainPage = new MainPage(); + const header: HeaderE2EComponent = mainPage.getHeader(); + + const documentationLink: string = 'http://dummy-leitfaden.url'; + + before(() => { + loginAsAriane(); + }); + + describe('open user profile menu', () => { + before(() => { + header.getCurrentUserProfile().getUserIconButton().click(); + }); + + it('should show logout button', () => { + exist(header.getCurrentUserProfile().getLogoutButton()); + }); + + it('should show documentation', () => { + exist(header.getCurrentUserProfile().getDocumentation()); + }); + + it('should find documentation link', () => { + shouldHaveAttribute(header.getCurrentUserProfile().getDocumentation().find('a'), 'href', documentationLink); + }); + }); +}); diff --git a/alfa-client/apps/admin/package.json b/alfa-client/apps/admin/package.json index ea02e8712086f17ab1ed610cd07352cd0918d4b0..924f232583709ebf8224d6a8301cd00d84cb1307 100644 --- a/alfa-client/apps/admin/package.json +++ b/alfa-client/apps/admin/package.json @@ -1,4 +1,4 @@ { "name": "admin", - "version": "null" + "version": "1.6.0-SNAPSHOT" } diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html index 8302d53018783e91ffb01539a627b9e5ee7730ff..55e1c8824521c5c846932ee5d648172d86466705 100644 --- a/alfa-client/apps/admin/src/app/app.component.html +++ b/alfa-client/apps/admin/src/app/app.component.html @@ -36,7 +36,10 @@ > <ods-admin-logo-icon /> </a> - <user-profile-button-container data-test-id="user-profile-button"></user-profile-button-container> + <user-profile-button-container + [apiRootStateResource]="apiRootStateResource$ | async" + data-test-id="user-profile-button" + ></user-profile-button-container> </header> <div class="flex h-screen w-full justify-center overflow-y-auto"> <ods-navbar data-test-id="navigation"> diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts index 34bd937efea886d40f3dc6f77df5eb1b3d68bce5..b0a354caa1b666ad9ad15a4527e77f8a632496c6 100644 --- a/alfa-client/apps/admin/src/app/app.component.spec.ts +++ b/alfa-client/apps/admin/src/app/app.component.spec.ts @@ -27,31 +27,18 @@ import { KeycloakTokenService } from '@admin/keycloak-shared'; import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { BuildInfoComponent } from '@alfa-client/common'; import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared'; -import { - existsAsHtmlElement, - getElementComponentFromFixtureByCss, - Mock, - mock, - notExistsAsHtmlElement, -} from '@alfa-client/test-utils'; +import { existsAsHtmlElement, getElementComponentFromFixtureByCss, Mock, mock, notExistsAsHtmlElement, } from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { AuthenticationService } from '@authentication'; -import { - AdminLogoIconComponent, - MailboxIconComponent, - NavbarComponent, - NavItemComponent, - OrgaUnitIconComponent, - UsersIconComponent, -} from '@ods/system'; +import { AdminLogoIconComponent, MailboxIconComponent, NavbarComponent, NavItemComponent, OrgaUnitIconComponent, UsersIconComponent, } from '@ods/system'; import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration'; import { MenuContainerComponent } from 'libs/admin/configuration/src/lib/menu-container/menu-container.component'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent, MockDirective } from 'ng-mocks'; import { of, Subscription } from 'rxjs'; -import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; +import { UserProfileButtonContainerComponent } from '../../../../libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component'; import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component'; import { AppComponent } from './app.component'; diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts index 6de5c0ab4da5fed7ffc763b86cdb18e253c44528..bb5f2013fde365c95ae01525f1b8cb170decddd6 100644 --- a/alfa-client/apps/admin/src/app/app.component.ts +++ b/alfa-client/apps/admin/src/app/app.component.ts @@ -41,7 +41,7 @@ import { UsersIconComponent, } from '@ods/system'; import { filter, Observable, Subscription } from 'rxjs'; -import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; +import { UserProfileButtonContainerComponent } from '../../../../libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component'; import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component'; @Component({ diff --git a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.spec.ts b/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.spec.ts deleted file mode 100644 index b40a661442d6728f6c7819a0548e556d615197a8..0000000000000000000000000000000000000000 --- a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -import { dispatchEventFromFixture, getElementFromFixture, mock, Mock } from '@alfa-client/test-utils'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { DropdownMenuButtonItemComponent, DropdownMenuComponent, LogoutIconComponent } from '@ods/system'; -import { AuthenticationService } from '@authentication'; -import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { MockComponent } from 'ng-mocks'; -import { UserProfileButtonContainerComponent } from './user-profile.button-container.component'; - -describe('UserProfileButtonContainerComponent', () => { - let component: UserProfileButtonContainerComponent; - let fixture: ComponentFixture<UserProfileButtonContainerComponent>; - - const authenticationService: Mock<AuthenticationService> = mock(AuthenticationService); - - const popupButtonContent: string = getDataTestIdOf('popup-button-content'); - const popupLogoutButton: string = getDataTestIdOf('popup-logout-button'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [UserProfileButtonContainerComponent], - imports: [ - RouterTestingModule, - MockComponent(DropdownMenuComponent), - MockComponent(DropdownMenuButtonItemComponent), - MockComponent(LogoutIconComponent), - ], - providers: [ - { - provide: AuthenticationService, - useValue: authenticationService, - }, - ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - it('should call authService to get current user initials', () => { - component.ngOnInit(); - - expect(authenticationService.getCurrentUserInitials).toHaveBeenCalled(); - }); - }); - - describe('popup button', () => { - it('should show initials', () => { - component.currentUserInitials = 'AV'; - fixture.detectChanges(); - - const popupButtonContentElement: HTMLElement = getElementFromFixture(fixture, popupButtonContent); - - expect(popupButtonContentElement.textContent.trim()).toEqual('AV'); - }); - }); - - describe('logout', () => { - it('should call authService logout', () => { - dispatchEventFromFixture(fixture, popupLogoutButton, 'itemClicked'); - - expect(authenticationService.logout).toHaveBeenCalled(); - }); - }); -}); diff --git a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts index 6900b4f81bba5213341add0864bec162856037fb..9bdd8978dbaafbf31aec2301c0a66348be778a6d 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts @@ -1,4 +1,4 @@ -import { shouldHaveAttribute } from "../../support/cypress.util"; +import { shouldHaveAttribute } from '../../support/cypress.util'; /* * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den @@ -26,8 +26,8 @@ import { shouldHaveAttribute } from "../../support/cypress.util"; export class HelpMenuE2EComponent { private readonly root: string = 'help-menu'; private readonly button: string = 'help-menu-button'; - private readonly dropdownButton: string ='dropdown-button'; - private readonly openDocumentationButton: string = 'open-documentation-button'; + private readonly dropdownButton: string = 'dropdown-button'; + private readonly documentation: string = 'documentation'; private readonly openImpressumButton: string = 'impressum'; public getRoot() { @@ -42,15 +42,15 @@ export class HelpMenuE2EComponent { return this.getRoot().getTestElement(this.dropdownButton); } - public getOpenDocumentationButton() { - return this.getRoot().getTestElementWithOid(this.openDocumentationButton); + public getDocumentation() { + return this.getRoot().getTestElementWithOid(this.documentation); } public getImpressumButton(): Cypress.Chainable<Element> { - return cy.getTestElement(this.openImpressumButton) + return cy.getTestElement(this.openImpressumButton); } public impressumLinkIs(link: string): void { - shouldHaveAttribute(this.getImpressumButton().find('a'),'href', link) + shouldHaveAttribute(this.getImpressumButton().find('a'), 'href', link); } } diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts index 4cc001a7f49f79190e8e1f53ef1242c36378d238..f2b5373adae2011b3bd3221041f783d5c8dd9bac 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts @@ -25,7 +25,7 @@ import { HelpMenuE2EComponent } from 'apps/alfa-e2e/src/components/user-assistan import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po'; import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; -import { contains, exist, shouldHaveAttribute } from 'apps/alfa-e2e/src/support/cypress.util'; +import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; import { loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; describe('Help Menu', () => { @@ -33,7 +33,7 @@ describe('Help Menu', () => { const header: HeaderE2EComponent = mainPage.getHeader(); const helpMenu: HelpMenuE2EComponent = header.getHelpMenu(); - const impressumLink: string = 'https://static.dev.sh.ozg-cloud.de/impressum' + const impressumLink: string = 'https://static.dev.sh.ozg-cloud.de/impressum'; before(() => { loginAsSabine(); @@ -50,7 +50,7 @@ describe('Help Menu', () => { it('should show "open documentation"', () => { helpMenu.getRoot().click(); - exist(helpMenu.getOpenDocumentationButton()); + exist(helpMenu.getDocumentation()); }); it('should show Impressum button and find link', () => { @@ -59,13 +59,7 @@ describe('Help Menu', () => { }); it('should open documentation', () => { - helpMenu - .getOpenDocumentationButton() - .find('a') - .invoke('removeAttr', 'target') - .click() - .url() - .should('include', 'benutzerleitfaden'); + helpMenu.getDocumentation().find('a').invoke('removeAttr', 'target').click().url().should('include', 'benutzerleitfaden'); }); }); }); diff --git a/alfa-client/libs/admin/user-profile/.eslintrc.json b/alfa-client/libs/admin/user-profile/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..b10f9813a8f5c59432cf245301dc4d01a8031fd1 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "lib", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "lib", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/alfa-client/libs/admin/user-profile/README.md b/alfa-client/libs/admin/user-profile/README.md new file mode 100644 index 0000000000000000000000000000000000000000..274c5f872b16cc6d084af4624ac985d6def1ab1d --- /dev/null +++ b/alfa-client/libs/admin/user-profile/README.md @@ -0,0 +1,7 @@ +# admin-user-profile + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test admin-user-profile` to execute the unit tests. diff --git a/alfa-client/libs/admin/user-profile/jest.config.ts b/alfa-client/libs/admin/user-profile/jest.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..8670098e4b2ced9d4dc48f74066897f0cde39ff4 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/jest.config.ts @@ -0,0 +1,21 @@ +export default { + displayName: 'admin-user-profile', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + coverageDirectory: '../../../coverage/libs/admin/user-profile', + 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', + ], +}; diff --git a/alfa-client/libs/admin/user-profile/project.json b/alfa-client/libs/admin/user-profile/project.json new file mode 100644 index 0000000000000000000000000000000000000000..fc4e68c48443f646a90034421e184a837300707c --- /dev/null +++ b/alfa-client/libs/admin/user-profile/project.json @@ -0,0 +1,22 @@ +{ + "name": "admin-user-profile", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/admin/user-profile/src", + "prefix": "lib", + "projectType": "library", + "tags": [], + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": [ + "{workspaceRoot}/coverage/{projectRoot}" + ], + "options": { + "jestConfig": "libs/admin/user-profile/jest.config.ts" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/alfa-client/libs/admin/user-profile/src/index.ts b/alfa-client/libs/admin/user-profile/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.html b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c3fe2d2837418f91d393a6de8cb98b20b271a0a5 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.html @@ -0,0 +1,3 @@ +<ods-dropdown-menu-link-item caption="Leitfaden für die Administration" text="PDF öffnen" [url]="url"> + <ods-file-icon icon fileType="pdf" size="medium" /> +</ods-dropdown-menu-link-item> diff --git a/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.scss b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..bcbd245ce7ef1ee60e79e99fce4f19f468a8c145 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.scss @@ -0,0 +1,3 @@ +:host { + white-space: nowrap; +} diff --git a/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.spec.ts b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..174d7d1fddc546ec91902bd0ee6d7a2f4509f561 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { DropdownMenuLinkItemComponent, FileIconComponent } from '@ods/system'; +import { MockComponent } from 'ng-mocks'; +import { DocumentationComponent } from './documentation.component'; + +describe('DocumentationComponent', () => { + let component: DocumentationComponent; + let fixture: ComponentFixture<DocumentationComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DocumentationComponent, MockComponent(DropdownMenuLinkItemComponent), MockComponent(FileIconComponent)], + }).compileComponents(); + + fixture = TestBed.createComponent(DocumentationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.ts b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3efae263c5f161d036cecce326dd636e292ce25 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/documentation/documentation.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; +import { DropdownMenuLinkItemComponent, FileIconComponent } from '@ods/system'; + +@Component({ + selector: 'admin-documentation', + templateUrl: './documentation.component.html', + styleUrls: ['./documentation.component.scss'], + standalone: true, + imports: [DropdownMenuLinkItemComponent, FileIconComponent], +}) +export class DocumentationComponent { + @Input() url: string; +} diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.html b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..9c5b0aa958eaadea5a44ecb92f5cbe45c05b06e6 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.html @@ -0,0 +1,3 @@ +<ods-dropdown-menu-button-item caption="Abmelden" (clickEmitter)="logout.emit()" data-test-id="popup-logout-button"> + <ods-logout-icon icon class="fill-primary" /> +</ods-dropdown-menu-button-item> diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.spec.ts b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..092b7217e8fe78d548dad54ed264c61c4cb0fdcd --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.spec.ts @@ -0,0 +1,42 @@ +import { dispatchEventFromFixture, MockEvent } from '@alfa-client/test-utils'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { expect } from '@jest/globals'; +import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test'; +import { AdminUserLogoutButtonComponent } from './admin-user-logout-button.component'; + +describe('AdminUserLogoutButtonComponent', () => { + let component: AdminUserLogoutButtonComponent; + let fixture: ComponentFixture<AdminUserLogoutButtonComponent>; + + const logoutButtonTestId: string = getDataTestIdOf('popup-logout-button'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AdminUserLogoutButtonComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(AdminUserLogoutButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('template', () => { + describe('menu button item', () => { + describe('output', () => { + describe('clickEmitter', () => { + it('should emit', () => { + component.logout.emit = jest.fn(); + + dispatchEventFromFixture(fixture, logoutButtonTestId, MockEvent.CLICK); + + expect(component.logout.emit).toHaveBeenCalled(); + }); + }); + }); + }); + }); +}); diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.ts b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6e3f4cd7f873a43d3012767e30b5f58738cbee69 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-logout-button/admin-user-logout-button.component.ts @@ -0,0 +1,12 @@ +import { Component, EventEmitter, Output } from '@angular/core'; +import { DropdownMenuButtonItemComponent, LogoutIconComponent } from '@ods/system'; + +@Component({ + selector: 'admin-user-logout-button', + standalone: true, + templateUrl: './admin-user-logout-button.component.html', + imports: [DropdownMenuButtonItemComponent, LogoutIconComponent], +}) +export class AdminUserLogoutButtonComponent { + @Output() logout = new EventEmitter<void>(); +} diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.html b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..78c636770990371bb05b7e6eef2bcca474ca67f0 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.html @@ -0,0 +1,8 @@ +<div + role="img" + class="flex size-9 items-center justify-center rounded-full border-2 border-transparent bg-ozggray-900 hover:border-primary" +> + <p class="font-semibold text-whitetext" data-test-id="popup-button-content"> + {{ currentUserInitials }} + </p> +</div> diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.spec.ts b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d14d9482666d406fa59e7d97856497e2f3ba930b --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AdminUserMenuButtonComponent } from './admin-user-menu-button.component'; + +describe('AdminUserMenuButtonComponent', () => { + let component: AdminUserMenuButtonComponent; + let fixture: ComponentFixture<AdminUserMenuButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AdminUserMenuButtonComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(AdminUserMenuButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.ts b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..02e3f12cef1b770fd4ee46a561d5949a84bc3e92 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu-button/admin-user-menu-button.component.ts @@ -0,0 +1,10 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'admin-user-menu-button', + standalone: true, + templateUrl: './admin-user-menu-button.component.html', +}) +export class AdminUserMenuButtonComponent { + @Input() currentUserInitials: string; +} diff --git a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.html b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.html similarity index 66% rename from alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.html rename to alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.html index 29fc9153463819b76fb30d8f2deef1dd77e7a9c4..7f5574fb4b4a3e18aa19c5a44094644825a59433 100644 --- a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile-button-container.component.html +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.html @@ -24,20 +24,15 @@ --> <ods-dropdown-menu buttonClass="rounded-full"> - <div - button-content - role="img" - class="flex size-9 items-center justify-center rounded-full border-2 border-transparent bg-ozggray-900 hover:border-primary" - > - <p class="font-semibold text-whitetext" data-test-id="popup-button-content"> - {{ currentUserInitials }} - </p> - </div> - <ods-dropdown-menu-button-item - caption="Abmelden" - (itemClicked)="authenticationService.logout()" - data-test-id="popup-logout-button" - > - <ods-logout-icon icon /> - </ods-dropdown-menu-button-item> + <admin-user-menu-button button-content [currentUserInitials]="currentUserInitials"></admin-user-menu-button> + + <admin-user-logout-button (logout)="authenticationService.logout()"></admin-user-logout-button> + + @if (apiRootStateResource.resource | hasLink: ApiRootLinkRel.DOCUMENTATIONS) { + <div class="h-2"></div> + <admin-documentation + [url]="apiRootStateResource.resource | getUrl: ApiRootLinkRel.DOCUMENTATIONS" + data-test-id="admin-documentation" + /> + } </ods-dropdown-menu> diff --git a/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.spec.ts b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb23876d9563a75acb6816a5cc5cca5285b2480a --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile-button-container.component.spec.ts @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; +import { createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { dispatchEventFromFixtureByType, existsAsHtmlElement, getElementComponentFromFixtureByCss, getElementFromFixture, mock, Mock, notExistsAsHtmlElement, } from '@alfa-client/test-utils'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AuthenticationService } from '@authentication'; +import { expect } from '@jest/globals'; +import { getUrl } from '@ngxp/rest'; +import { DropdownMenuButtonItemComponent, DropdownMenuComponent, LogoutIconComponent } from '@ods/system'; +import { MockComponent } from 'ng-mocks'; +import { createApiRootResource } from '../../../../../api-root-shared/test/api-root'; +import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test'; +import { DocumentationComponent } from '../documentation/documentation.component'; +import { AdminUserLogoutButtonComponent } from '../user-logout-button/admin-user-logout-button.component'; +import { UserProfileButtonContainerComponent } from './user-profile.button-container.component'; + +describe('UserProfileButtonContainerComponent', () => { + let component: UserProfileButtonContainerComponent; + let fixture: ComponentFixture<UserProfileButtonContainerComponent>; + + let authenticationService: Mock<AuthenticationService>; + + const popupButtonContent: string = getDataTestIdOf('popup-button-content'); + const popupLogoutButton: string = getDataTestIdOf('popup-logout-button'); + const documentationTestId: string = getDataTestIdOf('admin-documentation'); + + const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); + + beforeEach(() => { + authenticationService = mock(AuthenticationService); + }); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserProfileButtonContainerComponent], + imports: [ + RouterTestingModule, + MockComponent(DropdownMenuComponent), + MockComponent(DropdownMenuButtonItemComponent), + MockComponent(LogoutIconComponent), + ], + providers: [ + { + provide: AuthenticationService, + useValue: authenticationService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileButtonContainerComponent); + component = fixture.componentInstance; + component.apiRootStateResource = apiRootStateResource; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call authService to get current user initials', () => { + component.ngOnInit(); + + expect(authenticationService.getCurrentUserInitials).toHaveBeenCalled(); + }); + }); + + describe('template', () => { + describe('popup button', () => { + it('should show initials', () => { + component.currentUserInitials = 'AV'; + fixture.detectChanges(); + + const popupButtonContentElement: HTMLElement = getElementFromFixture(fixture, popupButtonContent); + + expect(popupButtonContentElement.textContent.trim()).toEqual('AV'); + }); + }); + + describe('logout', () => { + it('should call authService logout', () => { + dispatchEventFromFixtureByType(fixture, AdminUserLogoutButtonComponent, 'logout'); + + expect(authenticationService.logout).toHaveBeenCalled(); + }); + }); + + describe('documentation', () => { + it('should exists', () => { + component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS])); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, documentationTestId); + }); + + it('should NOT exists', () => { + component.apiRootStateResource = createStateResource(createApiRootResource([])); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, documentationTestId); + }); + + it('should have inputs', () => { + component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS])); + + fixture.detectChanges(); + const documentationComponent: DocumentationComponent = getElementComponentFromFixtureByCss(fixture, documentationTestId); + + expect(documentationComponent.url).toEqual( + getUrl(component.apiRootStateResource.resource, ApiRootLinkRel.DOCUMENTATIONS), + ); + }); + }); + }); +}); diff --git a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile.button-container.component.ts b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component.ts similarity index 59% rename from alfa-client/apps/admin/src/common/user-profile-button-container/user-profile.button-container.component.ts rename to alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component.ts index f2f4bd8351b8eb6be525ce81a68c8aec3c081a6e..6a7d7299beab272fc36cd93602f449dd0bff1af7 100644 --- a/alfa-client/apps/admin/src/common/user-profile-button-container/user-profile.button-container.component.ts +++ b/alfa-client/libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component.ts @@ -21,20 +21,36 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, OnInit } from '@angular/core'; -import { DropdownMenuButtonItemComponent, DropdownMenuComponent, LogoutIconComponent } from '@ods/system'; +import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; +import { GetUrlPipe, HasLinkPipe, StateResource } from '@alfa-client/tech-shared'; +import { Component, inject, Input, OnInit } from '@angular/core'; import { AuthenticationService } from '@authentication'; +import { DropdownMenuComponent } from '@ods/system'; +import { DocumentationComponent } from '../documentation/documentation.component'; +import { AdminUserLogoutButtonComponent } from '../user-logout-button/admin-user-logout-button.component'; +import { AdminUserMenuButtonComponent } from '../user-menu-button/admin-user-menu-button.component'; @Component({ selector: 'user-profile-button-container', templateUrl: './user-profile-button-container.component.html', standalone: true, - imports: [DropdownMenuComponent, DropdownMenuButtonItemComponent, LogoutIconComponent], + imports: [ + DropdownMenuComponent, + HasLinkPipe, + GetUrlPipe, + DocumentationComponent, + AdminUserLogoutButtonComponent, + AdminUserMenuButtonComponent, + ], }) export class UserProfileButtonContainerComponent implements OnInit { + @Input() apiRootStateResource: StateResource<ApiRootResource>; + public currentUserInitials: string; - constructor(public authenticationService: AuthenticationService) {} + public readonly authenticationService: AuthenticationService = inject(AuthenticationService); + + public readonly ApiRootLinkRel = ApiRootLinkRel; ngOnInit(): void { this.currentUserInitials = this.authenticationService.getCurrentUserInitials(); diff --git a/alfa-client/libs/admin/user-profile/src/test-setup.ts b/alfa-client/libs/admin/user-profile/src/test-setup.ts new file mode 100644 index 0000000000000000000000000000000000000000..c408668266d2fec3a9803c0ec044bc163fb987fe --- /dev/null +++ b/alfa-client/libs/admin/user-profile/src/test-setup.ts @@ -0,0 +1,12 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; + +import { getTestBed } from '@angular/core/testing'; +import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; + +getTestBed().resetTestEnvironment(); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/admin/user-profile/tsconfig.json b/alfa-client/libs/admin/user-profile/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..8ca9ad312c2bd4dc364383853ddd91a2ed8f86fd --- /dev/null +++ b/alfa-client/libs/admin/user-profile/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2022" + } +} diff --git a/alfa-client/libs/admin/user-profile/tsconfig.lib.json b/alfa-client/libs/admin/user-profile/tsconfig.lib.json new file mode 100644 index 0000000000000000000000000000000000000000..8441346f6e5858b2ef4235cb3c3160eda256f94a --- /dev/null +++ b/alfa-client/libs/admin/user-profile/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "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"] +} diff --git a/alfa-client/libs/admin/user-profile/tsconfig.spec.json b/alfa-client/libs/admin/user-profile/tsconfig.spec.json new file mode 100644 index 0000000000000000000000000000000000000000..e637bf83b59243f9ebc9b37842cfbf3f159bba47 --- /dev/null +++ b/alfa-client/libs/admin/user-profile/tsconfig.spec.json @@ -0,0 +1,11 @@ +{ + "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"] +} diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.spec.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.spec.ts index 0b747f1e0507e5375a8dd0baba6a7ce2733ba89c..1af5235f276bf8afd8787fd155e104f3a8b64040 100644 --- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.spec.ts +++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.spec.ts @@ -43,13 +43,13 @@ describe('DropdownMenuButtonItemComponent', () => { expect(component).toBeTruthy(); }); - describe('itemClicked emitter', () => { - it('should emit itemClicked', () => { - component.itemClicked.emit = jest.fn(); + describe('clickEmitter', () => { + it('should emit', () => { + component.clickEmitter.emit = jest.fn(); dispatchEventFromFixture(fixture, 'button', 'click'); - expect(component.itemClicked.emit).toHaveBeenCalled(); + expect(component.clickEmitter.emit).toHaveBeenCalled(); }); }); }); diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.ts index 2c1b5427927141d6b7ca40515ee64432d9d50e2e..85f7e1f0f6895e6798d6697f3e7e63391be8ca14 100644 --- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.ts +++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component.ts @@ -28,19 +28,21 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; selector: 'ods-dropdown-menu-button-item', standalone: true, imports: [CommonModule], - template: `<button - class="flex min-h-12 w-full items-center gap-4 border-2 border-transparent px-4 py-3 text-start outline-none hover:border-primary focus-visible:border-focus" - role="menuitem" - (click)="itemClicked.emit()" - [attr.data-test-id]="dataTestId" - > - <ng-content select="[icon]" /> - <p class="text-text">{{ caption }}</p> - </button>`, + template: ` <div class="w-full bg-whitetext p-1.5"> + <button + class="flex w-full items-center gap-2 rounded-md border border-transparent px-4 py-2 text-start font-medium outline-none hover:bg-background-150 focus-visible:border-primary dark:hover:bg-neutral-700" + role="menuitem" + (click)="clickEmitter.emit()" + [attr.data-test-id]="dataTestId" + > + <ng-content select="[icon]" /> + <p class="text-sm text-primary">{{ caption }}</p> + </button> + </div>`, }) export class DropdownMenuButtonItemComponent { @Input({ required: true }) caption!: string; @Input() dataTestId: string; - @Output() itemClicked: EventEmitter<MouseEvent> = new EventEmitter(); + @Output() clickEmitter: EventEmitter<MouseEvent> = new EventEmitter(); } diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-item/dropdown-menu-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-item/dropdown-menu-item.component.ts index 301af6719e17a63de18c5141a3bec564265976cd..2314cab202a68e6d276c7d0a3a731ae15df5c239 100644 --- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-item/dropdown-menu-item.component.ts +++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-item/dropdown-menu-item.component.ts @@ -7,6 +7,6 @@ import { Component } from '@angular/core'; imports: [CommonModule], styles: [':host {@apply block min-h-12 px-4 py-3 first:mt-2 last:mb-2}'], - template: ` <ng-content /> `, + template: `<ng-content />`, }) export class DropdownMenuItemComponent {} diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts index 045191b56a76618a85600a82757607f267b4c8e4..24427bb02e4ed24c83d01a0c4c942b474ef7385a 100644 --- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts +++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts @@ -1,3 +1,4 @@ +import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { OpenLinkIconComponent } from '../../icons/open-link-icon/open-link-icon.component'; import { LinkComponent } from '../../link/link.component'; @@ -5,17 +6,27 @@ import { LinkComponent } from '../../link/link.component'; @Component({ selector: 'ods-dropdown-menu-link-item', standalone: true, - imports: [OpenLinkIconComponent, LinkComponent], - styles: [':host {@apply first:mt-2}'], - template: ` <ods-link [url]="url" class="bg-whitetext" [openInNewTab]="true"> - <div class="flex items-center gap-2 px-4 py-3"> - <p class="font-medium text-primary">{{ text }}</p> - <ods-open-link-icon class="size-5" /> - <span class="sr-only">Öffnet in einem neuen Tab</span> - </div> - </ods-link>`, + imports: [LinkComponent, OpenLinkIconComponent, CommonModule], + template: `<div class="w-full bg-whitetext p-1.5"> + <ods-link [url]="url" [openInNewTab]="true"> + <div class="flex min-w-80 gap-3 px-3 py-1.5"> + <ng-content select="[icon]" /> + <div class="flex flex-col gap-1"> + @if (caption) { + <p class="text-sm font-medium text-text">{{ caption }}</p> + } + <div class="flex items-center gap-2"> + <p class="text-sm font-normal text-primary">{{ text }}</p> + <ods-open-link-icon size="small" /> + <span class="sr-only">Öffnet in einem neuen Tab</span> + </div> + </div> + </div> + </ods-link> + </div>`, }) export class DropdownMenuLinkItemComponent { @Input() url: string; + @Input() caption: string; @Input() text: string; } diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts index 04a15c7eec0780ac9b8709224ab54aecaf77ab6f..24c78fceb054182a65572cef755fa379dddca255 100644 --- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts +++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts @@ -46,9 +46,10 @@ import { twMerge } from 'tailwind-merge'; > <ng-content select="[button-content]" /> </button> + <div *ngIf="isPopupOpen" - class="absolute z-50 max-h-120 min-w-44 max-w-96 animate-fadeIn overflow-y-auto rounded bg-dropdownBg shadow-md ring-1 ring-grayborder focus:outline-none" + class="absolute z-50 mt-2 min-w-44 max-w-96 animate-fadeIn rounded-lg bg-background-100 ring-1 ring-grayborder drop-shadow-lg focus:outline-none" [ngClass]="alignTo === 'left' ? 'right-0' : 'left-0'" role="menu" aria-modal="true" diff --git a/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts index 2c084618d209a629d826c35f1397e8ff6c1de6d0..1e3a7ec67b3136e428a177080bd99f7410cb6ae1 100644 --- a/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts +++ b/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts @@ -38,6 +38,7 @@ const fileiconVariants = cva('fill-ozggray-300', { }, size: { small: 'w-4 h-5', + medium: 'w-5 h-6', large: 'w-8 h-10', }, }, diff --git a/alfa-client/libs/design-system/src/lib/link/link.component.ts b/alfa-client/libs/design-system/src/lib/link/link.component.ts index 64830deee7cf6873156013281ec33d7e2a56199e..a7f529ad5ca57b02e72dcb6033b128a9c2e77416 100644 --- a/alfa-client/libs/design-system/src/lib/link/link.component.ts +++ b/alfa-client/libs/design-system/src/lib/link/link.component.ts @@ -11,7 +11,7 @@ import { twMerge } from 'tailwind-merge'; [href]="url" [class]=" twMerge( - 'block rounded-lg border-2 border-transparent text-text hover:bg-ghost-hover focus-visible:border-focus focus-visible:bg-ghost-hover focus-visible:outline-none dark:hover:bg-neutral-700', + 'block rounded-md border border-transparent text-text hover:bg-neutral-100 focus-visible:border-primary focus-visible:outline-none dark:hover:bg-neutral-700', class ) " diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts index e847268dea4139a32915ce071ddd79fb20da4e39..66f33c3579e18d88743d3b23ea96703a2799bb04 100644 --- a/alfa-client/libs/test-utils/src/lib/helper.ts +++ b/alfa-client/libs/test-utils/src/lib/helper.ts @@ -55,6 +55,11 @@ export function dispatchEventFromFixture<T>(fixture: ComponentFixture<T>, elemen element.nativeElement.dispatchEvent(new Event(event)); } +export function dispatchEventFromFixtureByType<T, C>(fixture: ComponentFixture<T>, component: Type<C>, event: string): void { + const element: DebugElement = getDebugElementFromFixtureByType(fixture, component); + element.nativeElement.dispatchEvent(new Event(event)); +} + export function triggerEvent<T>(eventData: EventData<T>) { const element: DebugElement = getDebugElementFromFixtureByCss(eventData.fixture, eventData.elementSelector); element.triggerEventHandler(eventData.name, eventData.data); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html index 9ec99cebdafed843b5ded6af4b56c34fb2b04638..f0b1defde6fba19d8ef6144a37945c05dcbc3735 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html @@ -23,11 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ods-dropdown-menu-text-item - class="border-b border-b-grayborder border-t-grayborder bg-whitetext" - title="Benutzerleitfaden" - description="Alle Funktionen der Allgemeinen Fachanwendung (Alfa) erklärt." -> - <ods-file-icon icon fileType="pdf" size="large"></ods-file-icon> - <alfa-open-documentation-button additionalContent [url]="url" data-test-id="documentations-component" /> -</ods-dropdown-menu-text-item> +<ods-dropdown-menu-link-item caption="Benutzerleitfaden Alfa" text="PDF öffnen" [url]="url"> + <ods-file-icon icon fileType="pdf" size="medium" /> +</ods-dropdown-menu-link-item> diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts index b7307c4a9f800117718ab72571c87289e011907c..fb232797a308c689f244460f103deafbabf9c5f3 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts @@ -22,10 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { DropdownMenuTextItemComponent, FileIconComponent } from '@ods/system'; +import { DropdownMenuLinkItemComponent, FileIconComponent } from '@ods/system'; import { MockComponent } from 'ng-mocks'; import { DocumentationComponent } from './documentation.component'; -import { OpenDocumentationButtonComponent } from './open-documentation-button/open-documentation-button.component'; describe('DocumentationComponent', () => { let component: DocumentationComponent; @@ -33,12 +32,7 @@ describe('DocumentationComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ - DocumentationComponent, - MockComponent(OpenDocumentationButtonComponent), - MockComponent(DropdownMenuTextItemComponent), - MockComponent(FileIconComponent), - ], + declarations: [DocumentationComponent, MockComponent(DropdownMenuLinkItemComponent), MockComponent(FileIconComponent)], }).compileComponents(); fixture = TestBed.createComponent(DocumentationComponent); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html deleted file mode 100644 index d3f460b90b5c7c7232d01e2b4e0674ddee2a8a8c..0000000000000000000000000000000000000000 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - - Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den - Ministerpräsidenten des Landes Schleswig-Holstein - Staatskanzlei - Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - - Lizenziert unter der EUPL, Version 1.2 oder - sobald - diese von der Europäischen Kommission genehmigt wurden - - Folgeversionen der EUPL ("Lizenz"); - Sie dürfen dieses Werk ausschließlich gemäß - dieser Lizenz nutzen. - Eine Kopie der Lizenz finden Sie hier: - - https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - - Sofern nicht durch anwendbare Rechtsvorschriften - gefordert oder in schriftlicher Form vereinbart, wird - die unter der Lizenz verbreitete Software "so wie sie - ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - ausdrücklich oder stillschweigend - verbreitet. - Die sprachspezifischen Genehmigungen und Beschränkungen - unter der Lizenz sind dem Lizenztext zu entnehmen. - ---> -<ozgcloud-open-url-button - text="Öffnen" - [url]="url" - [targetName]="'_blank'" - [tooltip]="'Öffnet in einem neuen Tab'" - data-test-id="open-documentation-button" -/> diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.scss b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.scss deleted file mode 100644 index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.scss +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts deleted file mode 100644 index a57801c4f80be45225f6d78c3789d1cdec31b271..0000000000000000000000000000000000000000 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { OpenDocumentationButtonComponent } from './open-documentation-button.component'; -import { MockComponent } from 'ng-mocks'; -import { OpenUrlButtonComponent } from '@alfa-client/ui'; - -describe('OpenDocumentationButtonComponent', () => { - let component: OpenDocumentationButtonComponent; - let fixture: ComponentFixture<OpenDocumentationButtonComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [OpenDocumentationButtonComponent, MockComponent(OpenUrlButtonComponent)], - }).compileComponents(); - - fixture = TestBed.createComponent(OpenDocumentationButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts deleted file mode 100644 index c0719256cfb74979b4cbe95a7c3e3c451cd08af4..0000000000000000000000000000000000000000 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den - * Ministerpräsidenten des Landes Schleswig-Holstein - * Staatskanzlei - * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung - * - * Lizenziert unter der EUPL, Version 1.2 oder - sobald - * diese von der Europäischen Kommission genehmigt wurden - - * Folgeversionen der EUPL ("Lizenz"); - * Sie dürfen dieses Werk ausschließlich gemäß - * dieser Lizenz nutzen. - * Eine Kopie der Lizenz finden Sie hier: - * - * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 - * - * Sofern nicht durch anwendbare Rechtsvorschriften - * gefordert oder in schriftlicher Form vereinbart, wird - * die unter der Lizenz verbreitete Software "so wie sie - * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - - * ausdrücklich oder stillschweigend - verbreitet. - * Die sprachspezifischen Genehmigungen und Beschränkungen - * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ -import { Component, Input } from '@angular/core'; - -@Component({ - selector: 'alfa-open-documentation-button', - templateUrl: './open-documentation-button.component.html', - styleUrls: ['./open-documentation-button.component.scss'], -}) -export class OpenDocumentationButtonComponent { - @Input() url: string; -} diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html index 24ee1e914732e11ea00e3dad00a7cffea735b000..24583fe97f504dcb3d35279e5a1ab0d932a97ca9 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html @@ -38,6 +38,7 @@ } @if (apiRootStateResource?.resource?.impressumUrl) { + <div class="h-2"></div> <ods-dropdown-menu-link-item [url]="apiRootStateResource.resource.impressumUrl" text="Impressum" data-test-id="impressum" /> } </ods-dropdown-menu> diff --git a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts index 63fc01ce61325ce4935a8292df7314a550e83940..f448be3a653b757112bf18d262ff617fcf3600ab 100644 --- a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts +++ b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts @@ -34,7 +34,6 @@ import { import { MatFabButton } from '@angular/material/button'; import { MatMenuTrigger } from '@angular/material/menu'; import { DocumentationComponent } from './help-menu/documentation/documentation.component'; -import { OpenDocumentationButtonComponent } from './help-menu/documentation/open-documentation-button/open-documentation-button.component'; import { HelpButtonComponent } from './help-menu/help-button/help-button.component'; import { HelpMenuComponent } from './help-menu/help-menu.component'; import { OpenUrlButtonComponent } from '@alfa-client/ui'; @@ -53,7 +52,7 @@ import { OpenUrlButtonComponent } from '@alfa-client/ui'; DropdownMenuLinkItemComponent, OpenUrlButtonComponent, ], - declarations: [HelpMenuComponent, DocumentationComponent, OpenDocumentationButtonComponent, HelpButtonComponent], + declarations: [HelpMenuComponent, DocumentationComponent, HelpButtonComponent], exports: [HelpMenuComponent], }) export class UserAssistanceModule {} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html index a2aac078aaf9d5fc6783864da5b363cf460d9bee..797bf6c78e5323f1914b56376d75b5409c19b3c5 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html @@ -36,7 +36,7 @@ class="user-profile-icon" > </alfa-user-icon> - <ods-dropdown-menu-button-item caption="Abmelden" (itemClicked)="logoutEmitter.emit()" dataTestId="logout-button"> - <ods-logout-icon icon /> + <ods-dropdown-menu-button-item caption="Abmelden" (clickEmitter)="logoutEmitter.emit()" dataTestId="logout-button"> + <ods-logout-icon icon class="fill-primary" /> </ods-dropdown-menu-button-item> </ods-dropdown-menu> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts index ab53c008163ee44d5f785b065da91de6f203363c..2bf68369cdab87155caf1bb0d47489feb1552fc7 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { createStateResource } from '@alfa-client/tech-shared'; -import { dispatchEventFromFixture, getElementComponentFromFixtureByCss, mock, useFromMock } from '@alfa-client/test-utils'; +import { dispatchEventFromFixture, getElementComponentFromFixtureByCss, mock, MockEvent, useFromMock, } from '@alfa-client/test-utils'; import { UserIconComponent } from '@alfa-client/user-profile'; import { getUserName, UserProfileResource } from '@alfa-client/user-profile-shared'; import { EventEmitter } from '@angular/core'; @@ -90,7 +90,7 @@ describe('UserProfileInHeaderComponent', () => { describe('template', () => { describe('click on logout button', () => { it('should emit logout event', () => { - dispatchEventFromFixture(fixture, logoutButton, 'itemClicked'); + dispatchEventFromFixture(fixture, logoutButton, MockEvent.CLICK); expect(component.logoutEmitter.emit).toHaveBeenCalled(); }); diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json index f6bb4c8b2657d8acef026b997d32794971be5656..615131502b18ad4b0d693d9d2baeed734f62c4ce 100644 --- a/alfa-client/tsconfig.base.json +++ b/alfa-client/tsconfig.base.json @@ -78,7 +78,8 @@ "@alfa-client/zustaendige-stelle-shared": ["libs/zustaendige-stelle-shared/src/index.ts"], "@authentication": ["libs/authentication/src/index.ts"], "@ods/component": ["libs/design-component/src/index.ts"], - "@ods/system": ["libs/design-system/src/index.ts"] + "@ods/system": ["libs/design-system/src/index.ts"], + "admin-user-profile": ["libs/admin/admin-user-profile/src/index.ts"] } }, "exclude": ["node_modules", "tmp"]