added copy-link function on description editor fieldsets and annotations

This commit is contained in:
Sofia Papacharalampous 2024-06-28 15:38:46 +03:00
parent ca4f228dba
commit 2f03b563fe
21 changed files with 238 additions and 9 deletions

View File

@ -8,6 +8,11 @@
<mat-dialog-content> <mat-dialog-content>
<div class="row"> <div class="row">
<!-- Create New Thread --> <!-- Create New Thread -->
<div class="ml-auto col-auto">
<button mat-icon-button class="col-auto" type="button" matTooltip="{{ 'DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.COPY-LINK' | translate }}" (click)="copyLink()">
<mat-icon>link</mat-icon>
</button>
</div>
<div class="col-12"> <div class="col-12">
<form [formGroup]="threadFormGroup"> <form [formGroup]="threadFormGroup">
<div class="row mt-2 mb-3"> <div class="row mt-2 mb-3">

View File

@ -217,4 +217,23 @@ export class AnnotationDialogComponent extends BaseComponent {
enableReply(threadId: string): void { enableReply(threadId: string): void {
this.replyEnabledPerThread[threadId] = true; this.replyEnabledPerThread[threadId] = true;
} }
copyLink() {
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;
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
);
}
} }

View File

@ -107,7 +107,22 @@
<div class="row toc-pane-container" #boundary> <div class="row toc-pane-container" #boundary>
<div #spacer></div> <div #spacer></div>
<div class="col-12"> <div class="col-12">
<app-table-of-contents [visibilityRulesService]="visibilityRulesService" #table0fContents [showErrors]="showTocEntriesErrors" [hasFocus]="reachedBase == false" [formGroup]="formGroup.get('properties')" [descriptionTemplate]="item.descriptionTemplate" *ngIf="formGroup" [links]="links" [boundary]="boundary" [spacer]="spacer" stickyThing (entrySelected)="changeStep($event.entry, $event.execute)" [pageToFieldSetMap]="pageToFieldSetMap"></app-table-of-contents> <app-table-of-contents
*ngIf="formGroup"
stickyThing
[visibilityRulesService]="visibilityRulesService"
[showErrors]="showTocEntriesErrors"
[hasFocus]="reachedBase == false"
[formGroup]="formGroup.get('properties')"
[descriptionTemplate]="item.descriptionTemplate"
[links]="links"
[boundary]="boundary" [spacer]="spacer"
[pageToFieldSetMap]="pageToFieldSetMap"
[anchorFieldsetId]="anchorFieldsetId"
(entrySelected)="changeStep($event.entry, $event.execute)"
#table0fContents
></app-table-of-contents>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; import { AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { AbstractControl, UntypedFormArray, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
@ -44,6 +44,7 @@ import { TableOfContentsService } from './table-of-contents/services/table-of-co
import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component'; import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component';
import { RouterUtilsService } from '@app/core/services/router/router-utils.service'; import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
import { DescriptionFormService } from './description-form/components/services/description-form.service'; import { DescriptionFormService } from './description-form/components/services/description-form.service';
import { DescriptionFormAnnotationService } from './description-form/description-form-annotation.service';
@Component({ @Component({
selector: 'app-description-editor-component', selector: 'app-description-editor-component',
@ -51,7 +52,7 @@ import { DescriptionFormService } from './description-form/components/services/d
styleUrls: ['./description-editor.component.scss'], styleUrls: ['./description-editor.component.scss'],
providers: [DescriptionEditorService] providers: [DescriptionEditorService]
}) })
export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorModel, Description> implements OnInit { export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorModel, Description> implements OnInit, AfterViewInit {
isNew = true; isNew = true;
isDeleted = false; isDeleted = false;
@ -72,6 +73,10 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
reachedLast: boolean = false; reachedLast: boolean = false;
reachedFirst: boolean = false; reachedFirst: boolean = false;
anchorFieldsetId: string;
scrollToField: boolean = false;
openAnnotation: boolean = false;
pageToFieldSetMap: Map<string, DescriptionFieldIndicator[]> = new Map<string, DescriptionFieldIndicator[]>(); pageToFieldSetMap: Map<string, DescriptionFieldIndicator[]> = new Map<string, DescriptionFieldIndicator[]>();
private initialTemplateId: string = Guid.EMPTY; private initialTemplateId: string = Guid.EMPTY;
@ -105,6 +110,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
private tableOfContentsService: TableOfContentsService, private tableOfContentsService: TableOfContentsService,
private descriptionFormService: DescriptionFormService, private descriptionFormService: DescriptionFormService,
private descriptionFormAnnotationService: DescriptionFormAnnotationService,
) { ) {
const descriptionLabel: string = route.snapshot.data['entity']?.label; const descriptionLabel: string = route.snapshot.data['entity']?.label;
if (descriptionLabel) { if (descriptionLabel) {
@ -135,8 +141,12 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
const isPublicDescription = params['public']; const isPublicDescription = params['public'];
const newDmpId = params['newDmpId']; const newDmpId = params['newDmpId'];
if (copyDmpId && !dmpId && dmpSectionId) this.isCopy = true;
this.scrollToField = this.route.snapshot.data['scrollToField'] ?? false
this.anchorFieldsetId = params['fieldsetId'] ?? null;
this.openAnnotation = this.route.snapshot.data['openAnnotation'] ?? false;
if (copyDmpId && !dmpId && dmpSectionId) this.isCopy = true;
this.viewOnly = isPublicDescription; this.viewOnly = isPublicDescription;
@ -181,6 +191,12 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
}); });
} }
ngAfterViewInit(): void {
if (this.scrollToField && this.anchorFieldsetId && this.anchorFieldsetId != '') {
if (this.openAnnotation) this.descriptionFormAnnotationService.οpenAnnotationDialog(this.anchorFieldsetId);
}
}
getItem(itemId: Guid, successFunction: (item: Description) => void) { getItem(itemId: Guid, successFunction: (item: Description) => void) {
this.descriptionService.getSingle(itemId, DescriptionEditorEntityResolver.lookupFields()) this.descriptionService.getSingle(itemId, DescriptionEditorEntityResolver.lookupFields())
.pipe(map(data => data as Description), takeUntil(this._destroyed)) .pipe(map(data => data as Description), takeUntil(this._destroyed))

View File

@ -41,6 +41,47 @@ const routes: Routes = [
title: 'DESCRIPTION-EDITOR.TITLE-EDIT-DESCRIPTION', title: 'DESCRIPTION-EDITOR.TITLE-EDIT-DESCRIPTION',
} }
}, },
{
path: ':id/f/:fieldsetId',
canActivate: [AuthGuard],
component: DescriptionEditorComponent,
canDeactivate: [PendingChangesGuard],
resolve: {
'entity': DescriptionEditorEntityResolver,
'permissions': DescriptionEditorPermissionsResolver,
},
data: {
breadcrumbs: true,
getFromTitleService: true,
usePrefix: false,
...BreadcrumbService.generateRouteDataConfiguration({
skipNavigation: true,
}),
title: 'DESCRIPTION-EDITOR.TITLE-EDIT-DESCRIPTION',
scrollToField: true,
}
},
{
path: ':id/f/:fieldsetId/annotation',
canActivate: [AuthGuard],
component: DescriptionEditorComponent,
canDeactivate: [PendingChangesGuard],
resolve: {
'entity': DescriptionEditorEntityResolver,
'permissions': DescriptionEditorPermissionsResolver,
},
data: {
breadcrumbs: true,
getFromTitleService: true,
usePrefix: false,
...BreadcrumbService.generateRouteDataConfiguration({
skipNavigation: true,
}),
title: 'DESCRIPTION-EDITOR.TITLE-EDIT-DESCRIPTION',
scrollToField: true,
openAnnotation: true,
}
},
{ {
path: ':dmpId/:dmpSectionId', path: ':dmpId/:dmpSectionId',
canActivate: [AuthGuard], canActivate: [AuthGuard],

View File

@ -6,8 +6,13 @@
<app-description-form-field-set-title [fieldSet]="fieldSet" [path]="path" [isChild]="isChild"></app-description-form-field-set-title> <app-description-form-field-set-title [fieldSet]="fieldSet" [path]="path" [isChild]="isChild"></app-description-form-field-set-title>
</div> </div>
<div *ngIf="!hideAnnotations" class="col-auto"> <div *ngIf="!hideAnnotations" class="col-auto">
<button mat-icon-button class="col-auto annotation-icon" (click)="showAnnotations(fieldSet.id)" [disabled]="!canReview"> <button mat-icon-button class="col-auto annotation-icon" (click)="showAnnotations(fieldSet.id)" matTooltip="{{ 'DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.ANNOTATIONS' | translate }}" [disabled]="!canReview">
<mat-icon matTooltip="{{'DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.ANNOTATIONS' | translate}}" [matBadge]="annotationsCount" [matBadgeHidden]="annotationsCount <= 0" matBadgeColor="warn">comment</mat-icon> <mat-icon [matBadge]="annotationsCount" [matBadgeHidden]="annotationsCount <= 0" matBadgeColor="warn">comment</mat-icon>
</button>
</div>
<div *ngIf="!hideAnnotations" class="col-auto pl-0">
<button mat-icon-button class="col-auto" type="button" matTooltip="{{ 'DESCRIPTION-EDITOR.QUESTION.EXTENDED-DESCRIPTION.COPY-LINK' | translate }}" (click)="copyLink(fieldSet.id)">
<mat-icon>link</mat-icon>
</button> </button>
</div> </div>
</div> </div>

View File

@ -17,6 +17,9 @@ import { DescriptionFormAnnotationService } from '../../description-form-annotat
import { DescriptionPropertyDefinitionFieldSet } from '@app/core/model/description/description'; import { DescriptionPropertyDefinitionFieldSet } from '@app/core/model/description/description';
import { DescriptionFormService } from '../services/description-form.service'; import { DescriptionFormService } from '../services/description-form.service';
import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type'; import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'app-description-form-field-set', selector: 'app-description-form-field-set',
@ -53,10 +56,13 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
descriptionTemplateFieldType = DescriptionTemplateFieldType; descriptionTemplateFieldType = DescriptionTemplateFieldType;
constructor( constructor(
private routerUtils: RouterUtilsService,
private dialog: MatDialog, private dialog: MatDialog,
private changeDetector: ChangeDetectorRef, private changeDetector: ChangeDetectorRef,
private descriptionFormAnnotationService: DescriptionFormAnnotationService, private descriptionFormAnnotationService: DescriptionFormAnnotationService,
private descriptionFormService: DescriptionFormService, private descriptionFormService: DescriptionFormService,
private uiNotificationService: UiNotificationService,
private language: TranslateService,
) { ) {
super(); super();
} }
@ -71,6 +77,10 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
this.changeDetector.markForCheck(); this.changeDetector.markForCheck();
} }
}); });
this.descriptionFormAnnotationService.getOpenAnnotationSubjectObservable().pipe(takeUntil(this._destroyed)).subscribe( (anchorFieldsetId: string) => {
if (anchorFieldsetId && anchorFieldsetId == this.fieldSet.id) this.showAnnotations(anchorFieldsetId);
});
} }
canAddMultiplicityField(): boolean{ canAddMultiplicityField(): boolean{
@ -135,6 +145,25 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
}); });
} }
copyLink(fieldsetId: string) {
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.descriptionId.toString(), 'f', fieldsetId].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
);
}
// //
// //
// Annotations // Annotations

View File

@ -7,7 +7,7 @@ import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/serv
import { BaseService } from '@common/base/base.service'; import { BaseService } from '@common/base/base.service';
import { Guid } from '@common/types/guid'; import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof'; import { nameof } from 'ts-simple-nameof';
@ -20,6 +20,7 @@ export class DescriptionFormAnnotationService extends BaseService {
private entityId: Guid; private entityId: Guid;
private annotationsPerAnchor: Map<string, number>; private annotationsPerAnchor: Map<string, number>;
private annotationCountSubject: BehaviorSubject<Map<string, number>> = new BehaviorSubject<Map<string, number>>(null); private annotationCountSubject: BehaviorSubject<Map<string, number>> = new BehaviorSubject<Map<string, number>>(null);
private openAnnotationSubject: Subject<any> = new Subject<any>();
constructor( constructor(
private annotationService: AnnotationService, private annotationService: AnnotationService,
@ -38,6 +39,14 @@ export class DescriptionFormAnnotationService extends BaseService {
return this.annotationCountSubject.asObservable(); return this.annotationCountSubject.asObservable();
} }
public getOpenAnnotationSubjectObservable(): Observable<string> {
return this.openAnnotationSubject.asObservable();
}
public οpenAnnotationDialog(next: any): void {
this.openAnnotationSubject.next(next);
}
public refreshAnnotations() { public refreshAnnotations() {
const lookup: AnnotationLookup = new AnnotationLookup(); const lookup: AnnotationLookup = new AnnotationLookup();
lookup.entityIds = [this.entityId]; lookup.entityIds = [this.entityId];

View File

@ -161,8 +161,13 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
const dmpId = route.paramMap.get('dmpId'); const dmpId = route.paramMap.get('dmpId');
const dmpSectionId = route.paramMap.get('dmpSectionId'); const dmpSectionId = route.paramMap.get('dmpSectionId');
const copyDmpId = route.paramMap.get('copyDmpId'); const copyDmpId = route.paramMap.get('copyDmpId');
// const cloneid = route.paramMap.get('cloneid'); const fieldsetId = route.paramMap.get('fieldsetId');
if (id != null && copyDmpId == null && dmpSectionId == null) { if (id != null && copyDmpId == null && dmpSectionId == null) {
if (fieldsetId != null) {
this.breadcrumbService.addExcludedParam(fieldsetId, true);
this.breadcrumbService.addExcludedParam('f', true);
this.breadcrumbService.addExcludedParam('annotation', true);
}
return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(d => this.breadcrumbService.addIdResolvedValue(d.id.toString(), d.label))); return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(d => this.breadcrumbService.addIdResolvedValue(d.id.toString(), d.label)));
} else if (dmpId != null && dmpSectionId != null && copyDmpId == null) { } else if (dmpId != null && dmpSectionId != null && copyDmpId == null) {
return this.dmpService.getSingle(Guid.parse(dmpId), DescriptionEditorEntityResolver.dmpLookupFields()) return this.dmpService.getSingle(Guid.parse(dmpId), DescriptionEditorEntityResolver.dmpLookupFields())

View File

@ -21,6 +21,7 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
@Input() descriptionTemplate: DescriptionTemplate; @Input() descriptionTemplate: DescriptionTemplate;
@Input() hasFocus: boolean = false; @Input() hasFocus: boolean = false;
@Input() visibilityRulesService: VisibilityRulesService; @Input() visibilityRulesService: VisibilityRulesService;
@Input() anchorFieldsetId: string;
tocentries: ToCEntry[] = null; tocentries: ToCEntry[] = null;
@ -29,7 +30,6 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
private _tocentrySelected: ToCEntry = null; private _tocentrySelected: ToCEntry = null;
get tocentrySelected() { get tocentrySelected() {
return this._tocentrySelected; return this._tocentrySelected;
// return this.hasFocus ? this._tocentrySelected : null;
} }
set tocentrySelected(value) { set tocentrySelected(value) {
this._tocentrySelected = value; this._tocentrySelected = value;
@ -47,6 +47,10 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
if (this.descriptionTemplate) { if (this.descriptionTemplate) {
this.tocentries = this.getTocEntries(this.descriptionTemplate); this.tocentries = this.getTocEntries(this.descriptionTemplate);
if (this.anchorFieldsetId) {
const anchorTocentry = TableOfContentsComponent._findTocEntryById(this.anchorFieldsetId, this.tocentries);
if (anchorTocentry) setTimeout(() => { this.onToCentrySelected(anchorTocentry) }, 300);
}
} }
this.tableOfContentsService.getNextClickedEventObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { this.tableOfContentsService.getNextClickedEventObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
@ -105,6 +109,10 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
if (changes['descriptionTemplate'] && changes.descriptionTemplate != null) { if (changes['descriptionTemplate'] && changes.descriptionTemplate != null) {
this.tocentries = this.getTocEntries(this.descriptionTemplate); this.tocentries = this.getTocEntries(this.descriptionTemplate);
} }
if (changes['anchorFieldsetId'] && changes.anchorFieldsetId != null) {
const anchorTocentry = TableOfContentsComponent._findTocEntryById(this.anchorFieldsetId, this.tocentries);
if (anchorTocentry) setTimeout(() => { this.onToCentrySelected(anchorTocentry) }, 300);
}
} }
private _resetObserver() { private _resetObserver() {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {

View File

@ -982,6 +982,13 @@
"CANCEL": "Cancel", "CANCEL": "Cancel",
"UPDATE": "Update" "UPDATE": "Update"
} }
},
"QUESTION": {
"EXTENDED-DESCRIPTION": {
"COPY-LINK": "Copy Link",
"COPY-LINK-SUCCESSFUL": "Link copied",
"ANNOTATIONS": "Comment"
}
} }
}, },
"DESCRIPTION-COPY-DIALOG": { "DESCRIPTION-COPY-DIALOG": {