diff --git a/alfa-client/libs/design-system/src/index.ts b/alfa-client/libs/design-system/src/index.ts index dae1c087a831f7b46b22c93f751404403aef90bd..66c369f9faedc02ba57a5e2bba78287ee563ea42 100644 --- a/alfa-client/libs/design-system/src/index.ts +++ b/alfa-client/libs/design-system/src/index.ts @@ -20,6 +20,7 @@ export * from './lib/icons/bescheid-generate-icon/bescheid-generate-icon.compone export * from './lib/icons/bescheid-upload-icon/bescheid-upload-icon.component'; export * from './lib/icons/close-icon/close-icon.component'; export * from './lib/icons/edit-icon/edit-icon.component'; +export * from './lib/icons/error-icon/error-icon.component'; export * from './lib/icons/exclamation-icon/exclamation-icon.component'; export * from './lib/icons/external-unit-icon/external-unit-icon.component'; export * from './lib/icons/file-icon/file-icon.component'; @@ -35,6 +36,7 @@ export * from './lib/icons/search-icon/search-icon.component'; export * from './lib/icons/send-icon/send-icon.component'; export * from './lib/icons/spinner-icon/spinner-icon.component'; export * from './lib/icons/stamp-icon/stamp-icon.component'; +export * from './lib/icons/user-icon/user-icon.component'; export * from './lib/icons/users-icon/users-icon.component'; export * from './lib/instant-search/instant-search/instant-search.component'; export * from './lib/instant-search/instant-search/instant-search.model'; diff --git a/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6f909f03ce2d522ca5780b5ab4c18ec1af12591 --- /dev/null +++ b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ErrorIconComponent } from './error-icon.component'; + +describe('ErrorIconComponent', () => { + let component: ErrorIconComponent; + let fixture: ComponentFixture<ErrorIconComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ErrorIconComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(ErrorIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..efe33c3a26a3008fb27082027312eb71f5082764 --- /dev/null +++ b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.component.ts @@ -0,0 +1,28 @@ +import { NgClass } from '@angular/common'; +import { Component, Input } from '@angular/core'; +import { twMerge } from 'tailwind-merge'; +import { IconVariants, iconVariants } from '../iconVariants'; + +@Component({ + selector: 'ods-error-icon', + standalone: true, + imports: [NgClass], + template: `<svg + viewBox="0 0 24 24" + [ngClass]="[twMerge(iconVariants({ size }), 'fill-error', class)]" + aria-hidden="true" + fill="inherit" + xmlns="http://www.w3.org/2000/svg" + > + <path + d="M12 17C12.2833 17 12.5208 16.9042 12.7125 16.7125C12.9042 16.5208 13 16.2833 13 16C13 15.7167 12.9042 15.4792 12.7125 15.2875C12.5208 15.0958 12.2833 15 12 15C11.7167 15 11.4792 15.0958 11.2875 15.2875C11.0958 15.4792 11 15.7167 11 16C11 16.2833 11.0958 16.5208 11.2875 16.7125C11.4792 16.9042 11.7167 17 12 17ZM11 13H13V7H11V13ZM12 22C10.6167 22 9.31667 21.7375 8.1 21.2125C6.88333 20.6875 5.825 19.975 4.925 19.075C4.025 18.175 3.3125 17.1167 2.7875 15.9C2.2625 14.6833 2 13.3833 2 12C2 10.6167 2.2625 9.31667 2.7875 8.1C3.3125 6.88333 4.025 5.825 4.925 4.925C5.825 4.025 6.88333 3.3125 8.1 2.7875C9.31667 2.2625 10.6167 2 12 2C13.3833 2 14.6833 2.2625 15.9 2.7875C17.1167 3.3125 18.175 4.025 19.075 4.925C19.975 5.825 20.6875 6.88333 21.2125 8.1C21.7375 9.31667 22 10.6167 22 12C22 13.3833 21.7375 14.6833 21.2125 15.9C20.6875 17.1167 19.975 18.175 19.075 19.075C18.175 19.975 17.1167 20.6875 15.9 21.2125C14.6833 21.7375 13.3833 22 12 22ZM12 20C14.2333 20 16.125 19.225 17.675 17.675C19.225 16.125 20 14.2333 20 12C20 9.76667 19.225 7.875 17.675 6.325C16.125 4.775 14.2333 4 12 4C9.76667 4 7.875 4.775 6.325 6.325C4.775 7.875 4 9.76667 4 12C4 14.2333 4.775 16.125 6.325 17.675C7.875 19.225 9.76667 20 12 20Z" + /> + </svg>`, +}) +export class ErrorIconComponent { + @Input() size: IconVariants['size'] = 'medium'; + @Input() class: string = undefined; + + readonly iconVariants = iconVariants; + readonly twMerge = twMerge; +} diff --git a/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.stories.ts new file mode 100644 index 0000000000000000000000000000000000000000..5f77738047aac37b720323278ea04d31ecf3772e --- /dev/null +++ b/alfa-client/libs/design-system/src/lib/icons/error-icon/error-icon.stories.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/angular'; + +import { ErrorIconComponent } from './error-icon.component'; + +const meta: Meta<ErrorIconComponent> = { + title: 'Icons/Error icon', + component: ErrorIconComponent, + excludeStories: /.*Data$/, + tags: ['autodocs'], +}; + +export default meta; +type Story = StoryObj<ErrorIconComponent>; + +export const Default: Story = { + args: { size: 'medium' }, + argTypes: { + size: { + control: 'select', + options: ['small', 'medium', 'large', 'extra-large', 'full'], + description: 'Size of icon. Property "full" means 100%', + table: { + defaultValue: { summary: 'medium' }, + }, + }, + }, +}; diff --git a/alfa-client/libs/design-system/src/lib/icons/user-icon/user-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/user-icon/user-icon.component.ts index 90c01e353f6029d459584e6fcdafa425c6e6d9be..a3a53a9097b2984aea8449cf1671b5f860ac5da4 100644 --- a/alfa-client/libs/design-system/src/lib/icons/user-icon/user-icon.component.ts +++ b/alfa-client/libs/design-system/src/lib/icons/user-icon/user-icon.component.ts @@ -10,13 +10,13 @@ import { IconVariants, iconVariants } from '../iconVariants'; imports: [CommonModule, ExclamationIconComponent], template: ` <svg - viewBox="0 0 47 47" + viewBox="0 0 112 112" fill="none" xmlns="http://www.w3.org/2000/svg" [ngClass]="[twMerge(iconVariants({ size }), 'fill-ozggray-300', class)]" > <path - d="M23.5 3.91663C12.69 3.91663 3.91669 12.69 3.91669 23.5C3.91669 34.31 12.69 43.0833 23.5 43.0833C34.31 43.0833 43.0834 34.31 43.0834 23.5C43.0834 12.69 34.31 3.91663 23.5 3.91663ZM23.5 9.79163C26.7509 9.79163 29.375 12.4158 29.375 15.6666C29.375 18.9175 26.7509 21.5416 23.5 21.5416C20.2492 21.5416 17.625 18.9175 17.625 15.6666C17.625 12.4158 20.2492 9.79163 23.5 9.79163ZM23.5 37.6C18.6042 37.6 14.2763 35.0933 11.75 31.2941C11.8088 27.397 19.5834 25.2625 23.5 25.2625C27.3971 25.2625 35.1913 27.397 35.25 31.2941C32.7238 35.0933 28.3959 37.6 23.5 37.6Z" + d="M56 0.970734C25.6239 0.970734 0.970886 25.6239 0.970886 56C0.970886 86.3761 25.6239 111.029 56 111.029C86.3761 111.029 111.029 86.3761 111.029 56C111.029 25.6239 86.3761 0.970734 56 0.970734ZM56 17.4795C65.135 17.4795 72.5087 24.8534 72.5087 33.9881C72.5087 43.1232 65.135 50.4969 56 50.4969C46.8652 50.4969 39.4912 43.1232 39.4912 33.9881C39.4912 24.8534 46.8652 17.4795 56 17.4795ZM56 95.621C42.2428 95.621 30.0814 88.5772 22.9825 77.9014C23.1477 66.9506 44.9943 60.9526 56 60.9526C66.9508 60.9526 88.8525 66.9506 89.0175 77.9014C81.9189 88.5772 69.7575 95.621 56 95.621Z" /> </svg> `, diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html index 7c3ff6344729ceebe6372394587f6d6e09370a5d..e74237977c9aa085b67f137d7c2de0d3e3c70712 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html @@ -27,29 +27,26 @@ <div [matTooltipDisabled]="disableTooltip" data-test-class="user-profile-icon" - [class.initials]="!!userProfileStateResource.resource || userProfileStateResource.error" - class="user-profile" + class="relative flex size-9 items-center justify-center overflow-hidden rounded-full text-lg text-whitetext" + [class.bg-ozggray-900]="userProfileStateResource.resource || errorMessageCode === messageCode.RESOURCE_NOT_FOUND" [matTooltip]="tooltip" > <ng-container *ngIf="userProfileStateResource.resource; else noUser"> <span data-test-class="user-profile-assigned">{{ initials }}</span> </ng-container> <ng-template #noUser> - <mat-icon *ngIf="!userProfileStateResource.error" data-test-class="user-profile-unassigned" - >account_circle_outline</mat-icon - > - <span - *ngIf="errorMessageCode === messageCode.RESOURCE_NOT_FOUND" - data-test-class="user-profile-user-not-found" - >!</span - > - <mat-icon + <ods-user-icon + *ngIf="!userProfileStateResource.error" + data-test-class="user-profile-unassigned" + class="size-9 fill-ozggray-800" + style="--mdc-icon-button-icon-size: 36px" + /> + <span *ngIf="errorMessageCode === messageCode.RESOURCE_NOT_FOUND" data-test-class="user-profile-user-not-found">!</span> + <ods-error-icon *ngIf="errorMessageCode === messageCode.SERVICE_UNAVAILABLE" - class="unavailable" data-test-class="user-profile-service-unavailable" - >error_outline</mat-icon - > + style="--mdc-icon-button-icon-size: 42px" + /> </ng-template> - <div class="picture"></div> </div> </ozgcloud-spinner> diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss deleted file mode 100644 index dda9a87b9b1c6fb2dd5bca49aba7183be674d65c..0000000000000000000000000000000000000000 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (C) 2022 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. - */ -@use 'sass:map'; -@use '@angular/material' as mat; -@import 'variables'; - -.user-profile { - width: 36px; - height: 36px; - border-radius: 50%; - position: relative; - overflow: hidden; - - &.initials { - background-color: #3e3e3e; - color: #fff; - display: flex; - justify-content: center; - align-items: center; - font-size: 18px; - } -} - -mat-icon { - color: $grey; - position: absolute; - left: 50%; - top: 50%; - transform: scale(1.78) translate(-50%, -50%); - transform-origin: left top; -} - -span { - line-height: 1; -} - -mat-icon.unavailable { - background-color: #fff; - color: mat.get-color-from-palette($warnPalette); -} diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts index c2c4f8ef4539fc85530fc656c9733dd514894cf4..7c3850d8e871fe553f7073f01e853aab80d1c5e4 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts @@ -31,15 +31,12 @@ import { } from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { SpinnerComponent } from '@alfa-client/ui'; -import { - NO_NAME_MESSAGE, - UserProfileResource, - userProfileMessage, -} from '@alfa-client/user-profile-shared'; +import { NO_NAME_MESSAGE, UserProfileResource, userProfileMessage } from '@alfa-client/user-profile-shared'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; import { MatTooltipModule } from '@angular/material/tooltip'; import { faker } from '@faker-js/faker'; +import { ErrorIconComponent, UserIconComponent as OdsUserIconComponent } from '@ods/system'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; import { MockComponent, MockModule } from 'ng-mocks'; @@ -64,6 +61,8 @@ describe('UserIconComponent', () => { MatIcon, MockComponent(SpinnerComponent), MockModule(MatTooltipModule), + MockComponent(ErrorIconComponent), + MockComponent(OdsUserIconComponent), ], }); }); @@ -183,9 +182,7 @@ describe('UserIconComponent', () => { describe('on unexpected error', () => { it('should return empty string on non existing messageCode issue', () => { - component.userProfileStateResource = createErrorStateResource( - createApiErrorWithMessageCode(faker.random.word()), - ); + component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(faker.random.word())); const tooltip = component.getErrorTooltip(); diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts index 2a5c2244d1530041467669e723103a3f8925df02..1ee555b5938fecb134728e2af33df7bd911f326d 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts @@ -21,30 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { ApiError, MessageCode, StateResource, createEmptyStateResource, hasStateResourceError } from '@alfa-client/tech-shared'; +import { UserProfileResource, getUserName, getUserNameInitials, userProfileMessage } from '@alfa-client/user-profile-shared'; import { Component, Input, SimpleChanges } from '@angular/core'; -import { - ApiError, - createEmptyStateResource, - hasStateResourceError, - MessageCode, - StateResource, -} from '@alfa-client/tech-shared'; -import { - getUserName, - getUserNameInitials, - userProfileMessage, - UserProfileResource, -} from '@alfa-client/user-profile-shared'; import { isUndefined } from 'lodash-es'; @Component({ selector: 'alfa-user-icon', templateUrl: './user-icon.component.html', - styleUrls: ['./user-icon.component.scss'], }) export class UserIconComponent { - @Input() userProfileStateResource: StateResource<UserProfileResource> = - createEmptyStateResource<UserProfileResource>(); + @Input() userProfileStateResource: StateResource<UserProfileResource> = createEmptyStateResource<UserProfileResource>(); @Input() disableTooltip: boolean = false; readonly messageCode = MessageCode; diff --git a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts index fe2547f6551c42cbb2da5564357dddd5b6c56ae0..c6cdcd1a5af3d8b040e7e48cc333c62dfcfe3abd 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts @@ -21,12 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; import { TechSharedModule } from '@alfa-client/tech-shared'; import { UiModule } from '@alfa-client/ui'; import { UserProfileSharedModule } from '@alfa-client/user-profile-shared'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { ErrorIconComponent, UserIconComponent as OdsUserIconComponent } from '@ods/system'; import { AssignUserProfileButtonContainerComponent } from './assign-user-profile-button-container/assign-user-profile-button-container.component'; import { LinkWithUserNameTooltipContainerComponent } from './link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component'; import { LinkWithUserNameTooltipComponent } from './link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component'; @@ -48,7 +49,15 @@ import { UserProfileSearchComponent } from './user-profile-search-container/user import { UserProfileComponent } from './user-profile/user-profile.component'; @NgModule({ - imports: [CommonModule, TechSharedModule, UiModule, UserProfileSharedModule, RouterModule], + imports: [ + CommonModule, + TechSharedModule, + UiModule, + UserProfileSharedModule, + RouterModule, + OdsUserIconComponent, + ErrorIconComponent, + ], declarations: [ UserIconComponent, UserProfileInVorgangContainerComponent,