added plan links
This commit is contained in:
parent
287c016c89
commit
f0c2e9dacc
|
@ -26,7 +26,6 @@ import { ConfigurationService } from '@app/core/services/configuration/configura
|
|||
import { MatSelectionList } from '@angular/material/list';
|
||||
import { PlanUser } from '@app/core/model/plan/plan';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
interface AnnotationPayloadItem {
|
||||
isMention: boolean;
|
||||
|
@ -62,13 +61,15 @@ export class AnnotationDialogComponent extends BaseComponent {
|
|||
public annotationStatusFormGroup: UntypedFormGroup;
|
||||
public listingStatuses: Status[] = [];
|
||||
public planUsers: PlanUser[] = [];
|
||||
|
||||
queryIncludesField: boolean = false;
|
||||
queryIncludesAnnotation: boolean = false;
|
||||
|
||||
@ViewChild('annotationStatus') annotationStatus: MatSelectionList;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<AnnotationDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private uiNotificationService: UiNotificationService,
|
||||
private language: TranslateService,
|
||||
|
@ -78,13 +79,14 @@ export class AnnotationDialogComponent extends BaseComponent {
|
|||
private statusService: StatusService,
|
||||
protected routerUtils: RouterUtilsService,
|
||||
private configurationService: ConfigurationService,
|
||||
private sanitizer: DomSanitizer,
|
||||
) {
|
||||
super();
|
||||
this.entityId = data.entityId;
|
||||
this.anchor = data.anchor;
|
||||
this.entityType = data.entityType;
|
||||
this.planUsers = data.planUsers;
|
||||
this.queryIncludesField = data.queryIncludesField;
|
||||
this.queryIncludesAnnotation = data.queryIncludesAnnotation;
|
||||
dialogRef.backdropClick().pipe(takeUntil(this._destroyed)).subscribe(() => dialogRef.close(this.changesMade));
|
||||
}
|
||||
|
||||
|
@ -279,8 +281,18 @@ export class AnnotationDialogComponent extends BaseComponent {
|
|||
const el = document.createElement('textarea');
|
||||
let domain = `${window.location.protocol}//${window.location.hostname}`;
|
||||
if (window.location.port && window.location.port != '') domain += `:${window.location.port}`
|
||||
const descriptionSectionPath = this.routerUtils.generateUrl(['descriptions/edit', this.entityId, 'f', this.anchor, 'annotation'].join('/'));
|
||||
el.value = domain + descriptionSectionPath;
|
||||
|
||||
let currentPath = window.location.pathname;
|
||||
if (this.queryIncludesAnnotation) {
|
||||
currentPath = currentPath.split('/').slice(0, currentPath.split('/').length-4).join('/')
|
||||
} else if (this.queryIncludesField) {
|
||||
currentPath = currentPath.split('/').slice(0, currentPath.split('/').length-3).join('/')
|
||||
} else {
|
||||
currentPath = currentPath.split('/').slice(0, currentPath.split('/').length-1).join('/')
|
||||
}
|
||||
|
||||
const sectionPath = this.routerUtils.generateUrl([currentPath, this.entityId, 'f', this.anchor, 'annotation'].join('/'));
|
||||
el.value = domain + sectionPath;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
|
@ -374,27 +386,7 @@ export class AnnotationDialogComponent extends BaseComponent {
|
|||
});
|
||||
|
||||
return payloadItems;
|
||||
|
||||
// for (let planUser of this.planUsers) {
|
||||
// payloadItems = payload.split(`@{{userid:${planUser.id}}}`).map({isMention }).join('<span class="highlight-user-mention">'+planUser?.user?.name+'</span>');
|
||||
// }
|
||||
|
||||
// return this.sanitizer.bypassSecurityTrustHtml(payload);
|
||||
}
|
||||
// parsePayload(payload: string): AnnotationPayloadItem[] {
|
||||
|
||||
// if (!this.planUsers) return [{ isMention: false, payload: payload}];
|
||||
// if (this.planUsers.length == 0) [{ isMention: false, payload: payload}];
|
||||
|
||||
// let payloadItems = [];
|
||||
// // let payloadItems = [];
|
||||
|
||||
// for (let planUser of this.planUsers) {
|
||||
// payloadItems = payload.split(`@{{userid:${planUser.id}}}`).map({isMention }).join('<span class="highlight-user-mention">'+planUser?.user?.name+'</span>');
|
||||
// }
|
||||
|
||||
// return this.sanitizer.bypassSecurityTrustHtml(payload);
|
||||
// }
|
||||
|
||||
private onCallbackAnnotationStatusSuccess() {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('ANNOTATION-DIALOG.ANNOTATION-STATUS.SUCCESS'), SnackBarNotificationLevel.Success);
|
||||
|
|
|
@ -141,9 +141,9 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
const isPublicDescription = params['public'];
|
||||
const newPlanId = params['newPlanId'];
|
||||
|
||||
this.scrollToField = this.route.snapshot.data['scrollToField'] ?? false
|
||||
this.scrollToField = this.route.snapshot.data['scrollToField'] ?? false; this.descriptionFormService.queryIncludesField = this.scrollToField;
|
||||
this.anchorFieldsetId = params['fieldsetId'] ?? null;
|
||||
this.openAnnotation = this.route.snapshot.data['openAnnotation'] ?? false;
|
||||
this.openAnnotation = this.route.snapshot.data['openAnnotation'] ?? false; this.descriptionFormService.queryIncludesAnnotation = this.openAnnotation;
|
||||
|
||||
if (copyPlanId && !planId && planSectionId) this.isCopy = true;
|
||||
|
||||
|
|
|
@ -186,7 +186,9 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
|
|||
entityId: this.descriptionId,
|
||||
anchor: fieldSetId,
|
||||
entityType: AnnotationEntityType.Description,
|
||||
planUsers: this.planUsers
|
||||
planUsers: this.planUsers,
|
||||
queryIncludesField: this.descriptionFormService.queryIncludesField,
|
||||
queryIncludesAnnotation: this.descriptionFormService.queryIncludesAnnotation,
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(changesMade => {
|
||||
|
|
|
@ -4,6 +4,9 @@ import { Observable, Subject } from "rxjs";
|
|||
@Injectable()
|
||||
export class DescriptionFormService {
|
||||
|
||||
public queryIncludesField: boolean;
|
||||
public queryIncludesAnnotation: boolean;
|
||||
|
||||
private detectChangesSubject: Subject<any> = new Subject<any>();
|
||||
|
||||
public getDetectChangesObservable(): Observable<any> {
|
||||
|
|
|
@ -198,13 +198,20 @@
|
|||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div *ngFor="let field of section.fields; let j=index">
|
||||
<div class="row align-items-start">
|
||||
<div class="col">
|
||||
{{field.id}}
|
||||
<div class="heading-wrapper row align-items-start" [id]="field.id">
|
||||
<div class="col-auto">
|
||||
<div class="heading" *ngIf="!field.label && field.category === planBlueprintSectionFieldCategoryEnum.System">{{i + 1}}.{{j + 1}} {{enumUtils.toPlanBlueprintSystemFieldTypeString(field.systemFieldType)}}<span *ngIf="field.required">*</span></div>
|
||||
<div class="heading" *ngIf="!field.label && field.category === planBlueprintSectionFieldCategoryEnum.ReferenceType">{{i + 1}}.{{j + 1}} {{field.referenceType.name}}<span *ngIf="field.required">*</span></div>
|
||||
<div class="heading" *ngIf="field.label">{{i + 1}}.{{j + 1}} {{field.label}}<span *ngIf="field.required">*</span></div>
|
||||
</div>
|
||||
<div *ngIf="!isNew" class="col-auto" style="margin-top: 1rem;">
|
||||
<div class="col-auto link-icon" style="margin-top: 1rem;">
|
||||
<button *ngIf="!hildeLink" mat-icon-button type="button" matTooltip="{{ 'DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.COPY-LINK' | translate }}" (click)="copyLink(field?.id)">
|
||||
<mat-icon>link</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isNew" class="ml-auto col-auto" style="margin-top: 1rem;">
|
||||
<button mat-icon-button class="col-auto annotation-icon" (click)="showAnnotations(field.id)" matTooltip="{{ 'PLAN-EDITOR.ACTIONS.ANNOTATIONS' | translate }}" [disabled]="!canAnnotate(section.id)">
|
||||
<mat-icon [matBadge]="annotationsPerAnchor?.get(field.id)" [matBadgeHidden]="annotationsPerAnchor?.get(field.id) <= 0" matBadgeColor="warn">comment</mat-icon>
|
||||
</button>
|
||||
|
|
|
@ -324,6 +324,17 @@ a:hover {
|
|||
opacity: 1;
|
||||
margin: 3rem 0rem 3rem 0rem;
|
||||
}
|
||||
|
||||
.link-icon {
|
||||
margin-top: 1rem;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.heading-wrapper:hover {
|
||||
& > .link-icon {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
text-align: left;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AfterViewInit, Component, OnInit } from '@angular/core';
|
||||
import { FormArray, UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { AnnotationEntityType } from '@app/core/common/enum/annotation-entity-type';
|
||||
import { DescriptionStatus } from '@app/core/common/enum/description-status';
|
||||
import { FileTransformerEntityType } from '@app/core/common/enum/file-transformer-entity-type';
|
||||
|
@ -66,7 +66,7 @@ import { FormAnnotationService } from '@app/ui/annotations/annotation-dialog-com
|
|||
styleUrls: ['./plan-editor.component.scss'],
|
||||
providers: [PlanEditorService]
|
||||
})
|
||||
export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> implements OnInit {
|
||||
export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> implements OnInit, AfterViewInit {
|
||||
|
||||
isNew = true;
|
||||
isDeleted = false;
|
||||
|
@ -89,6 +89,9 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
planUserRoleEnumValues = this.enumUtils.getEnumValues<PlanUserRole>(PlanUserRole);
|
||||
fileTransformerEntityTypeEnum = FileTransformerEntityType;
|
||||
|
||||
scrollToField: boolean = false;
|
||||
openAnnotation: boolean = false;
|
||||
|
||||
permissionPerSection: Map<Guid, string[]>;
|
||||
|
||||
hoveredContact: number = -1;
|
||||
|
@ -214,7 +217,28 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
this.formAnnotationService.getOpenAnnotationSubjectObservable().pipe(takeUntil(this._destroyed)).subscribe((anchorId: string) => {
|
||||
if (anchorId && anchorId == this.item.id?.toString()) this.showAnnotations(anchorId);
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
||||
|
||||
this.route.params
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe((params: Params) => {
|
||||
const fieldId = params['fieldId'];
|
||||
|
||||
this.scrollToField = this.route.snapshot.data['scrollToField'] ?? false
|
||||
this.openAnnotation = this.route.snapshot.data['openAnnotation'] ?? false;
|
||||
|
||||
if (fieldId) {
|
||||
let fieldStep = this.item?.blueprint.definition.sections.find(s => s.fields.filter(f => f.id.toString() == fieldId)?.length > 0)?.ordinal;
|
||||
this.changeStep(fieldStep);
|
||||
setTimeout(() => this.changeStep1(fieldId), 600);
|
||||
|
||||
const openAnnotation = this.route.snapshot.data['openAnnotation'] ?? false;
|
||||
if (openAnnotation) this.showAnnotations(fieldId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getItem(itemId: Guid, successFunction: (item: Plan) => void) {
|
||||
|
@ -491,6 +515,15 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
this.resetScroll();
|
||||
}
|
||||
|
||||
public changeStep1(fieldId: string = null) {
|
||||
if (!fieldId) return;
|
||||
|
||||
const element = document.getElementById(fieldId);
|
||||
if (element) {
|
||||
element.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
nextStep() {
|
||||
this.step = this.step < this.selectedBlueprint.definition.sections.length ? this.step + 1 : this.step;
|
||||
this.resetScroll();
|
||||
|
@ -807,7 +840,9 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
entityId: this.item.id,
|
||||
anchor: anchorId,
|
||||
entityType: AnnotationEntityType.Plan,
|
||||
planUsers: this.item?.planUsers ?? []
|
||||
planUsers: this.item?.planUsers ?? [],
|
||||
queryIncludesField: this.scrollToField,
|
||||
queryIncludesAnnotation: this.openAnnotation,
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(changesMade => {
|
||||
|
@ -829,4 +864,23 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
getLanguageInfos(): LanguageInfo[] {
|
||||
return this.languageInfoService.getLanguageInfoValues();
|
||||
}
|
||||
|
||||
copyLink(fieldId: string): void {
|
||||
const el = document.createElement('textarea');
|
||||
let domain = `${window.location.protocol}//${window.location.hostname}`;
|
||||
if (window.location.port && window.location.port != '') domain += `:${window.location.port}`
|
||||
const descriptionSectionPath = this.routerUtils.generateUrl(['plans/edit', this.item.id.toString(), 'f', fieldId].join('/'));
|
||||
el.value = domain + descriptionSectionPath;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
this.uiNotificationService.snackBarNotification(
|
||||
this.language.instant('DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.COPY-LINK-SUCCESSFUL'),
|
||||
SnackBarNotificationLevel.Success
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { AuthGuard } from '@app/core/auth-guard.service';
|
|||
import { PlanEditorComponent } from './plan-editor.component';
|
||||
import { PlanEditorEntityResolver } from './resolvers/plan-editor-enitity.resolver';
|
||||
import { PlanEditorPermissionsResolver } from './resolvers/plan-editor-permissions.resolver';
|
||||
import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
|
@ -34,8 +35,48 @@ const routes: Routes = [
|
|||
getFromTitleService: true,
|
||||
usePrefix: false
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
path: ':id/f/:fieldId',
|
||||
canActivate: [AuthGuard],
|
||||
component: PlanEditorComponent,
|
||||
canDeactivate: [PendingChangesGuard],
|
||||
resolve: {
|
||||
'entity': PlanEditorEntityResolver,
|
||||
'permissions': PlanEditorPermissionsResolver,
|
||||
},
|
||||
data: {
|
||||
breadcrumbs: true,
|
||||
getFromTitleService: true,
|
||||
usePrefix: false,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
skipNavigation: true,
|
||||
}),
|
||||
title: 'PLAN-EDITOR.TITLE-EDIT',
|
||||
scrollToField: true,
|
||||
}
|
||||
},
|
||||
,
|
||||
{
|
||||
path: ':id/f/:fieldId/annotation',
|
||||
canActivate: [AuthGuard],
|
||||
component: PlanEditorComponent,
|
||||
canDeactivate: [PendingChangesGuard],
|
||||
resolve: {
|
||||
'entity': PlanEditorEntityResolver,
|
||||
'permissions': PlanEditorPermissionsResolver,
|
||||
},
|
||||
data: {
|
||||
breadcrumbs: true,
|
||||
getFromTitleService: true,
|
||||
usePrefix: false,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
skipNavigation: true,
|
||||
}),
|
||||
title: 'DESCRIPTION-EDITOR.TITLE-EDIT-DESCRIPTION',
|
||||
openAnnotation: true,
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -130,8 +130,16 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
|
|||
...PlanEditorEntityResolver.lookupFields()
|
||||
];
|
||||
const id = route.paramMap.get('id');
|
||||
const fieldsetId = route.paramMap.get('fieldsetId');
|
||||
if (id != null) {
|
||||
return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(id, x.label)), takeUntil(this._destroyed));
|
||||
return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(x => {
|
||||
if (fieldsetId) {
|
||||
this.breadcrumbService.addExcludedParam(fieldsetId, true);
|
||||
this.breadcrumbService.addExcludedParam('f', true);
|
||||
this.breadcrumbService.addExcludedParam('annotation', true);
|
||||
}
|
||||
this.breadcrumbService.addIdResolvedValue(id, x.label)
|
||||
}), takeUntil(this._destroyed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue