diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts index 1ed48c79b..66094e595 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { FormattingModule } from '@app/core/formatting.module'; -import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; import { DatasetProfileRoutingModule } from '@app/ui/admin/dataset-profile/dataset-profile.routing'; import { DatasetProfileEditorCompositeFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component'; import { DatasetProfileEditorDefaultValueComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-profile-editor-default-value/component-profile-editor-default-value.component'; @@ -25,20 +24,27 @@ import { DatasetProfileEditorComponent } from '@app/ui/admin/dataset-profile/edi import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; import { DialogConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; import { DatasetProfileListingComponent } from '@app/ui/admin/dataset-profile/listing/dataset-profile-listing.component'; +import { DatasetModule } from '@app/ui/dataset/dataset.module'; +import { FormProgressIndicationModule } from '@app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; +import { TableOfContentsModule } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.module'; import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; -import { ParseStatus } from './listing/pipe/parse-status.pipe'; -import { DatasetProfileEditorExternalDatasetsFieldComponent } from './editor/components/field-type/external-datasets/dataset-profile-editor-external-datasets-field.component'; +import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; +import { DatasetProfileEditorCurrencyFieldComponent } from './editor/components/field-type/currency/dataset-profile-editor-currency-field.component'; import { DatasetProfileEditorDataRepositoriesFieldComponent } from './editor/components/field-type/data-repositories/dataset-profile-editor-data-repositories-field.component'; +import { DatasetProfileEditorDatasetIdentifierFieldComponent } from './editor/components/field-type/dataset-identifier/dataset-profile-editor-dataset-identifier-field.component'; +import { DatasetProfileEditorExternalDatasetsFieldComponent } from './editor/components/field-type/external-datasets/dataset-profile-editor-external-datasets-field.component'; +import { DatasetProfileEditorOrganizationsFieldComponent } from './editor/components/field-type/organizations/dataset-profile-editor-organizations-field.component'; import { DatasetProfileEditorRegistriesFieldComponent } from './editor/components/field-type/registries/dataset-profile-editor-registries-field.component'; +import { DatasetProfileEditorResearchersFieldComponent } from './editor/components/field-type/researchers/dataset-profile-editor-researchers-field.component'; import { DatasetProfileEditorServicesFieldComponent } from './editor/components/field-type/services/dataset-profile-editor-services-field.component'; import { DatasetProfileEditorTagsFieldComponent } from './editor/components/field-type/tags/dataset-profile-editor-tags-field.component'; -import { DatasetProfileEditorResearchersFieldComponent } from './editor/components/field-type/researchers/dataset-profile-editor-researchers-field.component'; -import { DatasetProfileEditorOrganizationsFieldComponent } from './editor/components/field-type/organizations/dataset-profile-editor-organizations-field.component'; -import { DatasetProfileEditorDatasetIdentifierFieldComponent } from './editor/components/field-type/dataset-identifier/dataset-profile-editor-dataset-identifier-field.component'; -import { DatasetProfileEditorCurrencyFieldComponent } from './editor/components/field-type/currency/dataset-profile-editor-currency-field.component'; import { DatasetProfileEditorValidatorFieldComponent } from './editor/components/field-type/validator/dataset-profile-editor-validator-field.component'; import { NgxDropzoneModule } from 'ngx-dropzone'; +import { ParseStatus } from './listing/pipe/parse-status.pipe'; +import { DatasetProfileTableOfContents } from './table-of-contents/table-of-contents'; + @NgModule({ imports: [ CommonUiModule, @@ -46,7 +52,10 @@ import { NgxDropzoneModule } from 'ngx-dropzone'; FormattingModule, DatasetProfileRoutingModule, ConfirmationDialogModule, - NgxDropzoneModule + NgxDropzoneModule, + FormProgressIndicationModule, + DatasetModule, + AngularStickyThingsModule ], declarations: [ DatasetProfileListingComponent, @@ -82,7 +91,8 @@ import { NgxDropzoneModule } from 'ngx-dropzone'; DatasetProfileEditorOrganizationsFieldComponent, DatasetProfileEditorDatasetIdentifierFieldComponent, DatasetProfileEditorCurrencyFieldComponent, - DatasetProfileEditorValidatorFieldComponent + DatasetProfileEditorValidatorFieldComponent, + DatasetProfileTableOfContents ], entryComponents: [ DialogConfirmationUploadDatasetProfiles diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html index c6d9198aa..d9e634bd7 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html @@ -11,86 +11,118 @@

{{form.get('label').value}}

- - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - - - - - - - {{ lang.name }} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - -
- +
+ + {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate}} + +
+ + + {{'GENERAL.VALIDATION.REQUIRED' | + translate}} + + + + + + {{'GENERAL.VALIDATION.REQUIRED' + | translate}} + + + + + + + + {{ lang.name }} + + + {{'GENERAL.VALIDATION.REQUIRED' | + translate}} + + +
+ +
+
+
{{'DATASET-PROFILE-EDITOR.STEPS.PAGES.TITLE' | translate}}
- +
- +
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}}
- - - - {{i + 1}}. {{form.get('sections').get(''+i).get('title').value}} - - - -
- - -
-
-
+
+ +
+
+ +
- +
- +
- - - + + +
- - + +
@@ -103,4 +135,4 @@
- + \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts index d30180f76..6158679c3 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts @@ -26,6 +26,10 @@ import { LanguageInfo } from '@app/core/model/language-info'; import { LanguageInfoService } from '@app/core/services/culture/language-info-service'; import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; +import { Link, LinkToScroll } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents'; +import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service'; +import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model'; +import { ToCEntry } from '../table-of-contents/table-of-contents-entry'; const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json'); @@ -63,7 +67,9 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn private dialog: MatDialog, private languageInfoService: LanguageInfoService, private httpClient: HttpClient, - private matomoService: MatomoService + private matomoService: MatomoService, + + private datasetWizardService: DatasetWizardService ) { super(); // this.profileID = route.snapshot.params['id']; @@ -174,6 +180,9 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn // }); }); this.form.updateValueAndValidity(); + + //this.getPreview(); + } onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { @@ -403,4 +412,110 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn }, }); } -} + + + + + + + links: Link[] = []; + + getLinks(currentLinks: Link[]) { + this.links = currentLinks; + } + + linkToScroll: LinkToScroll; + onStepFound(linkToScroll: LinkToScroll) { + this.linkToScroll = linkToScroll; + } + + datasetWizardModel: DatasetWizardEditorModel; + formGroup: FormGroup; + getPreview() { + let data = this.form.value; + this.datasetProfileService.preview(data).subscribe(x => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel({ + datasetProfileDefinition: x + }); + this.formGroup = this.datasetWizardModel.buildForm().get('datasetProfileDefinition'); + }); + //this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue())); + + //this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; + // if (this.datasetWizardModel.status === DatasetStatus.Finalized) { + // this.formGroup.disable(); + // this.viewOnly = true; + // } + //if (this.viewOnly) { this.formGroup.disable(); } // For future use, to make Dataset edit like DMP. + // this.registerFormListeners(); + // this.dmpValueChanged(null); + // this.breadCrumbs = observableOf([ + // { + // parentComponentName: null, + // label: this.language.instant('DATASET-LISTING.ACTIONS.CREATE-NEW').toUpperCase(), + // url: '/datasets/new/' + // }]); + + + + // this.datasetWizardService.updateDatasetProfile(this.profileUpdateId) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(data => { + // this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); + // this.formGroupRawValue = JSON.parse(JSON.stringify(this.formGroup.getRawValue())); + + // this.needsUpdate(); + // this.breadCrumbs = observableOf([ + // { + // parentComponentName: null, + // label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'), + // url: '/datasets', + // notFoundResolver: [ + // // { + // // parentComponentName: null, + // // label: this.datasetWizardModel.dmp.grant.label, + // // url: '/grants/edit/' + this.datasetWizardModel.dmp.grant.id + // // }, + // { + // parentComponentName: null, + // label: this.datasetWizardModel.dmp.label, + // url: '/plans/edit/' + this.datasetWizardModel.dmp.id, + // }, + // ] + // }]); + // this.formGroup = this.datasetWizardModel.buildForm(); + // this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft; + // if (this.datasetWizardModel.status === DatasetStatus.Finalized) { + // this.formGroup.disable(); + // this.viewOnly = true; + // } + // // if (this.viewOnly) { this.formGroup.disable(); } // For future use, to make Dataset edit like DMP. + // this.loadDatasetProfiles(); + // }); + } + + getTocEntries(): ToCEntry[] { + if (this.form == null) { return []; } + + const result: ToCEntry[] = []; + (this.form.get('pages') as FormArray).controls.forEach((pageElement, i) => { + result.push({ + id: pageElement.get('id').value, + label: pageElement.get('title').value + } as ToCEntry) + }); + + (this.form.get('sections') as FormArray).controls.forEach((sectionElement, i) => { + const currentSectionPageId = sectionElement.get('page').value; + const pageToAdd = result.filter(x => x.id == currentSectionPageId)[0]; + if (pageToAdd.subEntries == null) pageToAdd.subEntries = []; + + pageToAdd.subEntries.push({ + id: sectionElement.get('id').value, + label: sectionElement.get('title').value + } as ToCEntry) + }); + + return result; + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts new file mode 100644 index 000000000..bf65d0f9c --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts @@ -0,0 +1,5 @@ +export interface ToCEntry { + id: string; + label: string; + subEntries: ToCEntry[]; +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.html b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.html new file mode 100644 index 000000000..c203eaedf --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.html @@ -0,0 +1,15 @@ +
+ + + +
+ + + {{link.label}} + + + +
+
diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.scss new file mode 100644 index 000000000..b346518fa --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.scss @@ -0,0 +1,70 @@ +.docs-toc-container { + width: 100%; + padding: 5px 0 10px 0px; + cursor: pointer; + // border-left: solid 4px #0c7489; + + .scroll-container { + overflow-y: auto; + // calc(100vh - 250px) + // height: calc(100vh - 250px); + } + + .docs-link { + color: rgba(0, 0, 0, 0.54); + // color: mat-color($app-blue-theme-foreground, secondary-text); + transition: color 100ms; + + &:hover, + &.docs-active { + .link-name { + background-color: #ececec; + border-radius: 6px; + // color: #0c7489; + } + // color: mat-color($primary, if($is-dark-theme, 200, default)); + } + } +} + +.docs-toc-heading { + margin: 0; + padding: 0; + font-size: 13px; + font-weight: bold; +} + +span { + line-height: 16px; + margin: 6px 0 0; + position: relative; + text-decoration: none; + display: block; + overflow: hidden; + color: #21212194; + font-weight: 400; + max-width: 290px; + min-width: 290px; + padding: 0rem .4rem; + span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + width: 100%; + } +} + +.selected { + color: #212121 !important; + font-weight: 700 !important; + opacity: 1 !important; +} + +// .docs-level-mat-expansion-panel { +// margin-left: 12px; +// } + +.docs-level-h5 { + margin-left: 24px; +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts new file mode 100644 index 000000000..ec6160e56 --- /dev/null +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts @@ -0,0 +1,167 @@ +import { DOCUMENT } from '@angular/common'; +import { Component, EventEmitter, Inject, OnInit, Output, Input } from '@angular/core'; +import { BaseComponent } from '@common/base/base.component'; +import { interval, Subject, Subscription } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; +import { type } from 'os'; +import { SimpleChanges } from '@angular/core'; +import { ToCEntry } from './table-of-contents-entry'; + +export interface Link { + /* id of the section*/ + id: string; + /* header type h3/h4 */ + type: string; + /* If the anchor is in view of the page */ + active: boolean; + /* name of the anchor */ + name: string; + /* top offset px of the anchor */ + top: number; + page: number; + section: number; + show: boolean; + selected: boolean; +} + +@Component({ + selector: 'dataset-profile-table-of-contents', + styleUrls: ['./table-of-contents.scss'], + templateUrl: './table-of-contents.html' +}) +export class DatasetProfileTableOfContents extends BaseComponent implements OnInit { + + @Input() links: ToCEntry[]; + container: string; + headerSelectors = '.toc-page-header, .toc-section-header, .toc-compositeField-header'; + @Output() stepFound = new EventEmitter(); + @Output() currentLinks = new EventEmitter(); + subscription: Subscription; + linksSubject: Subject = new Subject(); + + @Input() isActive: boolean; + show: boolean = false; + + constructor( + @Inject(DOCUMENT) private _document: Document) { + super(); + } + + + ngOnInit(): void { + //emit value every 500ms + // const source = interval(500); + // this.subscription = source.subscribe(val => { + // const headers = Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[]; + // this.linksSubject.next(headers); + // }); + + // if (!this.links || this.links.length === 0) { + // this.linksSubject.asObservable() + // .pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q))) + // .subscribe(headers => { + // const links: Array = []; + + // if (headers.length) { + // let page; + // let section; + // let show + // for (const header of headers) { + // let name; + // let id; + // if (header.classList.contains('toc-page-header')) { // deprecated after removing stepper + // name = header.innerText.trim().replace(/^link/, ''); + // id = header.id; + // page = header.id.split('_')[1]; + // section = undefined; + // show = true; + // } else if (header.classList.contains('toc-section-header')) { + // name = header.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0].nodeValue.trim().replace(/^link/, ''); + // id = header.id; + // page = header.id.split('.')[1]; + // section = header.id; + // if (header.id.split('.')[4]) { show = false; } + // else { show = true; } + // } else if (header.classList.contains('toc-compositeField-header')) { + // name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, ''); + // id = header.id; + // // id = header.parentElement.parentElement.parentElement.id; + // show = false; + // } + // const { top } = header.getBoundingClientRect(); + // links.push({ + // name, + // id, + // type: header.tagName.toLowerCase(), + // top: top, + // active: false, + // page: page, + // section: section, + // show: show, + // selected: false + // }); + // } + // } + // this.links = links; + // // Initialize selected for button next on dataset wizard component editor + // this.links.length > 0 ? this.links[0].selected = true : null; + // }) + // } + + } + + ngOnChanges(changes: SimpleChanges) { + // if (!this.isActive && this.links && this.links.length > 0) { + // this.links.forEach(link => { + // link.selected = false; + // }) + // this.links[0].selected = true; + // } + } + + goToStep(link: Link) { + // this.stepFound.emit({ + // page: link.page, + // section: link.section + // }); + // this.currentLinks.emit(this.links); + + // setTimeout(() => { + // const target = document.getElementById(link.id); + // target.scrollIntoView(true); + + // var scrolledY = window.scrollY; + // if (scrolledY) { + // window.scroll(0, scrolledY - 70); + // } + // }, 500); + } + + toggle(headerLink: Link) { + // const headerPage = +headerLink.name.split(" ", 1); + // let innerPage; + // for (const link of this.links) { + // link.selected = false; + // if (link.type === 'mat-expansion-panel') { + // innerPage = +link.name.split(".", 1)[0]; + // if (isNaN(innerPage)) { innerPage = +link.name.split(" ", 1) } + // } else if (link.type === 'h5') { + // innerPage = +link.name.split(".", 1)[0]; + // } + // if (headerPage === innerPage && (link.type !== 'mat-expansion-panel' || (link.type === 'mat-expansion-panel' && link.id.split(".")[4]))) { + // link.show = !link.show; + // } + // } + // headerLink.selected = true; + } + + // getIndex(link: Link): number { + // return +link.id.split("_", 2)[1]; + // } + +} + +export interface LinkToScroll { + page: number; + section: number; +} diff --git a/dmp-frontend/src/app/ui/dataset/dataset.module.ts b/dmp-frontend/src/app/ui/dataset/dataset.module.ts index 720e27218..ec553bef5 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset.module.ts +++ b/dmp-frontend/src/app/ui/dataset/dataset.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core'; +import { FormattingModule } from '@app/core/formatting.module'; import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module'; import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; @@ -22,14 +23,10 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation- import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; -import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module'; -import { DatasetOverviewModule } from './overview/dataset-overview.module'; -import { DatasetCriteriaDialogComponent } from './listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component'; -import { DmpEditorComponent } from '../dmp/editor/dmp-editor.component'; -import { DatasetEditorDetailsComponent } from '../dmp/editor/dataset-editor-details/dataset-editor-details.component'; -import { DatasetEditorDetailsModule } from '../dmp/editor/dataset-editor-details/dataset-editor-details.module'; import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; -import { FormattingModule } from '@app/core/formatting.module'; +import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module'; +import { DatasetCriteriaDialogComponent } from './listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component'; +import { DatasetOverviewModule } from './overview/dataset-overview.module'; @NgModule({ imports: [ @@ -77,7 +74,10 @@ import { FormattingModule } from '@app/core/formatting.module'; DatasetExternalDataRepositoryDialogEditorComponent, DatasetExternalDatasetDialogEditorComponent, DatasetExternalRegistryDialogEditorComponent, - DatasetExternalServiceDialogEditorComponent + DatasetExternalServiceDialogEditorComponent, + + DatasetEditorComponent, + DatasetDescriptionFormModule ] }) export class DatasetModule { } diff --git a/dmp-frontend/src/app/ui/dataset/dataset.routing.ts b/dmp-frontend/src/app/ui/dataset/dataset.routing.ts index 7d54ef8b6..b024aa044 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset.routing.ts +++ b/dmp-frontend/src/app/ui/dataset/dataset.routing.ts @@ -4,7 +4,6 @@ import { AuthGuard } from '../../core/auth-guard.service'; import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; import { DatasetListingComponent } from './listing/dataset-listing.component'; import { DatasetOverviewComponent } from './overview/dataset-overview.component'; -import { DmpEditorComponent } from '../dmp/editor/dmp-editor.component'; const routes: Routes = [ {