refactor plan authors into separate component, + remove test project from angular.json
This commit is contained in:
parent
2b39cae424
commit
fad3f394a0
|
@ -129,20 +129,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"frontend-e2e": {
|
||||
"root": "",
|
||||
"sourceRoot": "e2e",
|
||||
"projectType": "application",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "./protractor.conf.js",
|
||||
"devServerTarget": "frontend:serve"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schematics": {
|
||||
|
|
|
@ -188,39 +188,15 @@
|
|||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="frame mb-3 pt-4 pl-3 pr-3 pb-3">
|
||||
<div class="col-12">
|
||||
<p class="header">{{ 'DESCRIPTION-OVERVIEW.DESCRIPTION-AUTHORS' | translate }}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div *ngFor="let planUser of description.plan?.planUsers; let i=index" class="row authors pt-1" [ngClass]="{'author-focused': authorFocus && isFocusedOnUser(planUser.user?.id, i)}" (mouseover)="focusOnAuthor(planUser.user?.id, i)" (mouseout)="resetAuthorFocus()">
|
||||
<div class="col-auto d-flex flex-row pr-0">
|
||||
<button class="account_btn mr-3 pl-0">
|
||||
<mat-icon class="account-icon" [ngClass]="{'author-icon-focused': authorFocus && authorFocus == planUser.user?.id}">account_circle</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col pl-0" style="min-width: 0;">
|
||||
<ng-container *ngIf="!isUserAuthor(planUser.user?.id); else you">
|
||||
<p class="authors-label">{{ planUser.user?.name }}</p>
|
||||
</ng-container>
|
||||
<ng-template #you>
|
||||
<p *ngIf="userName" class="authors-label">{{ userName }}
|
||||
<span>({{ 'DESCRIPTION-OVERVIEW.YOU' | translate }})</span>
|
||||
</p>
|
||||
</ng-template>
|
||||
|
||||
<p class="authors-role">
|
||||
<span>{{ enumUtils.toPlanUserRoleString(planUser.role) }} - </span>
|
||||
<span *ngIf="!planUser.sectionId">{{ 'DESCRIPTION-OVERVIEW.ROLES.ALL-SECTIONS' | translate}}</span>
|
||||
<span *ngIf="planUser.sectionId">{{ getSectionNameById(planUser.sectionId) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-auto" *ngIf="canInvitePlanUsers && description.plan?.status === planStatusEnum.Draft && planUser.role != planUserRoleEnum.Owner">
|
||||
<button (click)="removeUserFromPlan(planUser)" mat-mini-fab matTooltip="{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 header">
|
||||
{{ 'DESCRIPTION-OVERVIEW.DESCRIPTION-AUTHORS' | translate }}
|
||||
</div>
|
||||
<app-plan-authors
|
||||
[planUsers]="description.plan?.planUsers"
|
||||
[username]="userName"
|
||||
[removeUser]="canAssignPlanUsers"
|
||||
(deleteAuthor)="removeUserFromPlan($event)"
|
||||
/>
|
||||
<div *ngIf="canInvitePlanUsers" class="col-12 d-flex justify-content-center mt-2">
|
||||
<button mat-raised-button class="invite-btn" (click)="openShareDialog()">
|
||||
<mat-icon>group_add</mat-icon>
|
||||
|
|
|
@ -161,7 +161,6 @@
|
|||
|
||||
.header {
|
||||
opacity: 0.6;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
|
@ -246,28 +245,6 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.authors {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.authors-label {
|
||||
font-size: 0.875em;
|
||||
color: #212121;
|
||||
height: 1.4em;
|
||||
margin-bottom: 0px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.authors-role {
|
||||
font-size: 0.875em;
|
||||
color: #a8a8a8;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
// ********CENTER ELEMENTS********
|
||||
|
||||
.mat-mini-fab,
|
||||
|
@ -294,16 +271,6 @@
|
|||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.author-focused {
|
||||
background-color: #ececec;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.author-icon-focused {
|
||||
color: #a8a8a8 !important;
|
||||
}
|
||||
|
||||
.deleted-item {
|
||||
color: #cf1407;
|
||||
}
|
|
@ -73,6 +73,11 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
canFinalize = false;
|
||||
canAnnotate = false;
|
||||
canInvitePlanUsers = false;
|
||||
canAssignPlanUsers(): boolean {
|
||||
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
||||
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
||||
!this.isPublicView && this.description?.belongsToCurrentTenant && this.description?.plan?.status === PlanStatusEnum.Draft;
|
||||
}
|
||||
|
||||
authorFocus: string;
|
||||
userName: string;
|
||||
|
|
|
@ -7,6 +7,7 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
|
|||
import { DescriptionCopyDialogModule } from '../description-copy-dialog/description-copy-dialog.module';
|
||||
import { DescriptionOverviewComponent } from './description-overview.component';
|
||||
import { DescriptionOverviewRoutingModule } from './description-overview.routing';
|
||||
import { PlanAuthorsComponent } from '@app/ui/plan/plan-authors/plan-authors.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -16,7 +17,8 @@ import { DescriptionOverviewRoutingModule } from './description-overview.routing
|
|||
FormattingModule,
|
||||
AutoCompleteModule,
|
||||
DescriptionCopyDialogModule,
|
||||
DescriptionOverviewRoutingModule
|
||||
DescriptionOverviewRoutingModule,
|
||||
PlanAuthorsComponent
|
||||
],
|
||||
declarations: [
|
||||
DescriptionOverviewComponent
|
||||
|
|
|
@ -248,39 +248,15 @@
|
|||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="frame mb-3 pt-4 pl-3 pr-3 pb-3">
|
||||
<div class="col-12">
|
||||
<p class="header">{{ 'PLAN-OVERVIEW.PLAN-AUTHORS' | translate }}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div *ngFor="let planUser of plan.planUsers; let i=index;" class="row authors pt-1" [ngClass]="{'author-focused': authorFocus && isFocusedOnUser(planUser.user?.id, i)}" (mouseover)="focusOnAuthor(planUser.user?.id, i)" (mouseout)="resetAuthorFocus()">
|
||||
<div class="col-auto d-flex flex-row pr-0">
|
||||
<button class="account_btn mr-3 pl-0">
|
||||
<mat-icon class="account-icon" [ngClass]="{'author-icon-focused': authorFocus && authorFocus == planUser.user?.id}">account_circle</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col pl-0" style="min-width: 0;">
|
||||
<ng-container *ngIf="!isUserAuthor(planUser.user?.id); else you">
|
||||
<p class="authors-label">{{ planUser.user?.name }}</p>
|
||||
</ng-container>
|
||||
<ng-template #you>
|
||||
<p *ngIf="userName" class="authors-label"> {{ userName }}
|
||||
<span >
|
||||
({{ 'PLAN-OVERVIEW.YOU' | translate }})</span>
|
||||
</p>
|
||||
</ng-template>
|
||||
<p class="authors-role">
|
||||
<span>{{ enumUtils.toPlanUserRoleString(planUser.role) }} - </span>
|
||||
<span *ngIf="!planUser.sectionId">{{ 'PLAN-OVERVIEW.ROLES.ALL-SECTIONS' | translate}}</span>
|
||||
<span *ngIf="planUser.sectionId">{{ getSectionNameById(planUser.sectionId) }}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div *ngIf="canAssignPlanUsers(plan) && plan.status === planStatusEnum.Draft && planUser.role != planUserRoleEnum.Owner" class="col-auto">
|
||||
<button (click)="removeUserFromPlan(planUser)" mat-mini-fab matTooltip="{{ 'PLAN-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 header">
|
||||
{{ 'PLAN-OVERVIEW.PLAN-AUTHORS' | translate }}
|
||||
</div>
|
||||
<app-plan-authors
|
||||
[planUsers]="plan.planUsers"
|
||||
[username]="userName"
|
||||
[removeUser]="canAssignPlanUsers(plan) && plan.status === planStatusEnum.Draft"
|
||||
(deleteAuthor)="removeUserFromPlan($event)"
|
||||
/>
|
||||
<div *ngIf="canInvitePlanUsers()" class="col-12 d-flex align-items-center justify-content-center mt-2">
|
||||
<button mat-raised-button class="invite-btn" (click)="openShareDialog(plan.id,plan.label)">
|
||||
<mat-icon>group_add</mat-icon>
|
||||
|
|
|
@ -93,14 +93,6 @@
|
|||
box-shadow: 0px 2px 6px #00000029;
|
||||
}
|
||||
|
||||
.remove-btn {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
font-size: 0.875em;
|
||||
font-weight: bold;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.invite-btn {
|
||||
width: 9.4em;
|
||||
height: 2.9em;
|
||||
|
@ -109,14 +101,6 @@
|
|||
border: 2px solid #212121;
|
||||
border-radius: 30px;
|
||||
}
|
||||
|
||||
.account_btn {
|
||||
background: transparent;
|
||||
color: #d5d5d5;
|
||||
border: none;
|
||||
height: 2.9em;
|
||||
}
|
||||
|
||||
// ********TEXT********
|
||||
|
||||
.plan-logo {
|
||||
|
@ -160,7 +144,6 @@
|
|||
|
||||
.header {
|
||||
opacity: 0.6;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
|
@ -249,28 +232,6 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.authors {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.authors-label {
|
||||
font-size: 0.875em;
|
||||
color: #212121;
|
||||
height: 1.4em;
|
||||
margin-bottom: 0px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.authors-role {
|
||||
font-size: 0.875em;
|
||||
color: #a8a8a8;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
// ********CENTER ELEMENTS********
|
||||
|
||||
.mat-mini-fab,
|
||||
|
@ -336,15 +297,6 @@
|
|||
border: none;
|
||||
}
|
||||
|
||||
.author-focused {
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.author-icon-focused {
|
||||
color: #a8a8a8 !important;
|
||||
}
|
||||
|
||||
.deleted-item {
|
||||
color: #cf1407;
|
||||
}
|
|
@ -11,6 +11,7 @@ import { PlanOverviewRoutingModule } from './plan-overview.routing';
|
|||
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
|
||||
import { PlanDeleteDialogModule } from '../plan-delete-dialog/plan-delete-dialog.module';
|
||||
import { PlanOverviewComponent } from './plan-overview.component';
|
||||
import { PlanAuthorsComponent } from '../plan-authors/plan-authors.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -22,7 +23,8 @@ import { PlanOverviewComponent } from './plan-overview.component';
|
|||
FormattingModule,
|
||||
AutoCompleteModule,
|
||||
PlanOverviewRoutingModule,
|
||||
PlanFinalizeDialogModule
|
||||
PlanFinalizeDialogModule,
|
||||
PlanAuthorsComponent
|
||||
],
|
||||
declarations: [
|
||||
PlanOverviewComponent,
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
@if(planUsers()){
|
||||
<div *ngFor="let planUser of planUsers(); let i=index;" class="d-flex author">
|
||||
<mat-icon class="author-icon">account_circle</mat-icon>
|
||||
<div style="min-width: 0;">
|
||||
<ng-container *ngIf="!isUserAuthor(planUser.user?.id); else you">
|
||||
<span class="author-label">{{ planUser.user?.name }}</span>
|
||||
</ng-container>
|
||||
<ng-template #you>
|
||||
<div *ngIf="username()" class="author-label"> {{ username() }}
|
||||
<span >
|
||||
({{ 'PLAN-OVERVIEW.YOU' | translate }})
|
||||
</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="author-role">
|
||||
<span>{{ enumUtils.toPlanUserRoleString(planUser.role) }} - </span>
|
||||
<span *ngIf="!planUser.sectionId">{{ 'PLAN-OVERVIEW.ROLES.ALL-SECTIONS' | translate}}</span>
|
||||
<span *ngIf="planUser.sectionId">{{ getSectionNameById(planUser.sectionId) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@if(removeUser() && planUser.role != planUserRoleEnum.Owner){
|
||||
<button (click)="removeUserFromPlan(planUser)" mat-mini-fab class="secondary ml-auto" matTooltip="{{ 'PLAN-OVERVIEW.ACTIONS.REMOVE-AUTHOR' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
.author {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 1rem;
|
||||
font-size: 0.875em;
|
||||
padding: 0.25rem 0.5rem;
|
||||
|
||||
&:hover {
|
||||
background-color: #e0e0e08c;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.author-role {
|
||||
color: #a8a8a8;
|
||||
}
|
||||
|
||||
.author-label {
|
||||
color: #212121;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.author-icon {
|
||||
min-width: 40px;
|
||||
font-size: 40px;
|
||||
height: auto;
|
||||
color: #b7b8bb;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
background-color: var(--primary-color);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { Component, input, output } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { PlanUserRole } from '@app/core/common/enum/plan-user-role';
|
||||
import { PlanBlueprint, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
|
||||
import { PlanUser } from '@app/core/model/plan/plan';
|
||||
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||
import { Guid } from '@common/types/guid';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plan-authors',
|
||||
standalone: true,
|
||||
imports: [TranslateModule, CommonModule, MatIconModule, MatButtonModule, MatTooltipModule],
|
||||
templateUrl: './plan-authors.component.html',
|
||||
styleUrl: './plan-authors.component.scss'
|
||||
})
|
||||
export class PlanAuthorsComponent {
|
||||
planUsers = input.required<PlanUser[]>();
|
||||
username = input.required<string>();
|
||||
planBlueprint = input<PlanBlueprint>(null);
|
||||
removeUser = input<boolean>(false);
|
||||
|
||||
deleteAuthor = output<PlanUser>();
|
||||
|
||||
planUserRoleEnum = PlanUserRole;
|
||||
|
||||
constructor(
|
||||
protected enumUtils: EnumUtils,
|
||||
private authentication: AuthService,
|
||||
){
|
||||
}
|
||||
|
||||
protected isUserAuthor(userId: Guid): boolean {
|
||||
if (this.isAuthenticated()) {
|
||||
const principalId: Guid = this.authentication.userId();
|
||||
return this.username() && userId === principalId;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
protected isAuthenticated(): boolean {
|
||||
return this.authentication.currentAccountIsAuthenticated();
|
||||
}
|
||||
|
||||
protected removeUserFromPlan(author: PlanUser) {
|
||||
this.deleteAuthor.emit(author);
|
||||
}
|
||||
|
||||
getSectionNameById(sectionId: Guid): string {
|
||||
if (sectionId == null || !this.planBlueprint()) return '';
|
||||
let sections: PlanBlueprintDefinitionSection[] = this.planBlueprint()?.definition?.sections?.filter((section: PlanBlueprintDefinitionSection) => sectionId === section.id);
|
||||
|
||||
return sections == null ? '' : sections[0].label;
|
||||
}
|
||||
}
|
|
@ -473,9 +473,35 @@ button,.mdc-button,.mat-mdc-button, .mdc-button:has(.material-icons,mat-icon,[ma
|
|||
border: 0px; //!important
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.mdc-fab.mdc-fab--mini.mat-mdc-mini-fab {
|
||||
.mat-icon {
|
||||
font-size: 1.2em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
&.primary{
|
||||
background-color: var(--primary-color);
|
||||
color: #ffffff;
|
||||
&:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary{
|
||||
background-color: var(--secondary-color);
|
||||
|
||||
color: #000000;
|
||||
&:hover {
|
||||
background-color: var(--primary-color);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-chip {
|
||||
border-radius: 20px;
|
||||
padding-left: 1em;
|
||||
|
@ -509,3 +535,4 @@ button,.mdc-button,.mat-mdc-button, .mdc-button:has(.material-icons,mat-icon,[ma
|
|||
.gap-half-rem {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue