From 4102386ecd742d6482ffa4d0c205a4833c29f910 Mon Sep 17 00:00:00 2001 From: Diamantis Tziotzios Date: Tue, 22 Oct 2019 15:46:48 +0300 Subject: [PATCH] toc style changes --- dmp-frontend/package.json | 1 + .../dataset-wizard.component.html | 143 +---------- .../dataset-wizard.component.scss | 230 ++++++++++-------- .../dataset-wizard.component.ts | 18 +- .../src/app/ui/dataset/dataset.module.ts | 10 +- .../dataset-description-form.component.html | 13 +- .../dataset-description-form.component.scss | 100 +------- .../dataset-description-form.component.ts | 102 +------- .../dataset-description-form.module.ts | 7 +- .../table-of-contents.html | 19 +- .../table-of-contents.scss | 76 +++--- .../table-of-contents.ts | 223 +++++------------ 12 files changed, 283 insertions(+), 659 deletions(-) diff --git a/dmp-frontend/package.json b/dmp-frontend/package.json index 2a69526d8..7c9527007 100644 --- a/dmp-frontend/package.json +++ b/dmp-frontend/package.json @@ -22,6 +22,7 @@ "@ngx-translate/core": "^11.0.1", "@ngx-translate/http-loader": "^4.0.0", "@swimlane/ngx-datatable": "^16.0.2", + "@w11k/angular-sticky-things": "^1.1.2", "bootstrap": "^4.3.1", "core-js": "^2.5.5", "file-saver": "^2.0.2", diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html index 85a808e23..4e9dccee1 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.html @@ -91,8 +91,16 @@ {{'DATASET-PROFILE-EDITOR.STEPS.PAGES.DESCRIPTION' | translate}} - - +
+
+ + +
+
+
+ +
+
@@ -112,134 +120,3 @@ - - - - - - - - - - diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss index 70bf9f022..49e23b07c 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.scss @@ -1,125 +1,155 @@ @media (max-width: 768px) { - .main-content { - padding: 30px 0px; - } + .main-content { + padding: 30px 0px; + } - ::ng-deep .mat-expansion-panel-header { - min-height: 48px; - height: auto !important; - } + ::ng-deep .mat-expansion-panel-header { + min-height: 48px; + height: auto !important; + } - ::ng-deep .mat-expansion-panel-body { - padding: 0 0px 16px !important; - } + ::ng-deep .mat-expansion-panel-body { + padding: 0 0px 16px !important; + } - ::ng-deep .mat-vertical-content { - padding: 0 14px 24px 14px !important; - } + ::ng-deep .mat-vertical-content { + padding: 0 14px 24px 14px !important; + } } .dataset-wizard { - .step-container { - margin-top: 1em; - } - .external-item-card { - margin-top: 1em; - } - .external-item-action-row, - .description-action-row { - margin-top: 1em; - } - .deleteButton, - .reverseButton { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - text-transform: uppercase; - } - .cancelButton { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - text-transform: uppercase; - } - .saveButton { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - text-transform: uppercase; - } - .saveAndFinalizeButton { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - } - .finalizeButton { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - text-transform: uppercase; - } - .export-btn { - padding-right: 6px; - } - .downloadPDF { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - } - .downloadXML { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - } - .downloadDOCX { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - } - .updateDatasetProfile { - margin-top: 15px; - margin-bottom: 15px; - margin-right: 15px; - } + .toc-pane-container { + &.is-sticky~.nav-spacer { + height: 500px; // the container size } + // height: calc(100vh - 100px); // the container size } + } + } - .actions { - display: flex; - justify-content: flex-end; - } + .step-container { + margin-top: 1em; + } - // .actions > button { - // background-color: #0070c0; - // color: #ffffff; - // text-transform: uppercase; - // } + .external-item-card { + margin-top: 1em; + } - .more-horiz { - font-size: 28px; - color: #aaaaaa; - } + .external-item-action-row, + .description-action-row { + margin-top: 1em; + } - .more-icon :hover { - color: #00b29f; - } + .deleteButton, + .reverseButton { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + text-transform: uppercase; + } - .new-dataset { - height: 3.5em; - } + .cancelButton { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + text-transform: uppercase; + } + + .saveButton { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + text-transform: uppercase; + } + + .saveAndFinalizeButton { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + } + + .finalizeButton { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + text-transform: uppercase; + } + + .export-btn { + padding-right: 6px; + } + + .downloadPDF { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + } + + .downloadXML { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + } + + .downloadDOCX { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + } + + .updateDatasetProfile { + margin-top: 15px; + margin-bottom: 15px; + margin-right: 15px; + } + + .actions { + display: flex; + justify-content: flex-end; + } + + // .actions > button { + // background-color: #0070c0; + // color: #ffffff; + // text-transform: uppercase; + // } + + .more-horiz { + font-size: 28px; + color: #aaaaaa; + } + + .more-icon :hover { + color: #00b29f; + } + + .new-dataset { + height: 3.5em; + } } .menu-item { - width: 248px; + width: 248px; } ::ng-deep .mat-tab-labels { - justify-content: space-between; + justify-content: space-between; } ::ng-deep .mat-tab-label-content { - text-transform: uppercase; + text-transform: uppercase; } ::ng-deep .mat-ink-bar { - background-color: #00b29f !important; - // background-color: #0070c0 !important; + background-color: #00b29f !important; + // background-color: #0070c0 !important; +} + +.toc-pane-container { + &.is-sticky~.nav-spacer { + height: 500px; // the container size } + // height: calc(100vh - 100px); // the container size } + } +} + +.is-sticky { + margin-top: 70px !important; } diff --git a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts index 9cf8fc488..b7e5a3980 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts +++ b/dmp-frontend/src/app/ui/dataset/dataset-wizard/dataset-wizard.component.ts @@ -1,5 +1,3 @@ -import { of as observableOf, Observable } from 'rxjs'; -import { map, catchError, takeUntil } from 'rxjs/operators'; import { Component, OnInit, ViewChild } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; @@ -8,9 +6,12 @@ import { MatStepper } from '@angular/material/stepper'; import { ActivatedRoute, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; +import { Observable, of as observableOf } from 'rxjs'; +import { catchError, map, takeUntil } from 'rxjs/operators'; import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model'; import { BaseComponent } from '../../../core/common/base/base.component'; import { DatasetStatus } from '../../../core/common/enum/dataset-status'; +import { DmpStatus } from '../../../core/common/enum/dmp-status'; import { DataTableRequest } from '../../../core/model/data-table/data-table-request'; import { DatasetProfileModel } from '../../../core/model/dataset/dataset-profile'; import { DmpModel } from '../../../core/model/dmp/dmp'; @@ -25,13 +26,12 @@ import { ExternalSourcesService } from '../../../core/services/external-sources/ import { SnackBarNotificationLevel, UiNotificationService } from '../../../core/services/notification/ui-notification-service'; import { SingleAutoCompleteConfiguration } from '../../../library/auto-complete/single/single-auto-complete-configuration'; import { ConfirmationDialogComponent } from '../../../library/confirmation-dialog/confirmation-dialog.component'; -import { ExportMethodDialogComponent } from '../../../library/export-method-dialog/export-method-dialog.component'; import { BreadcrumbItem } from '../../misc/breadcrumb/definition/breadcrumb-item'; import { IBreadCrumbComponent } from '../../misc/breadcrumb/definition/IBreadCrumbComponent'; import { DatasetDescriptionFormEditorModel } from '../../misc/dataset-description-form/dataset-description-form.model'; +import { LinkToScroll } from '../../misc/dataset-description-form/tableOfContentsMaterial/table-of-contents'; import { DatasetCopyDialogueComponent } from './dataset-copy-dialogue/dataset-copy-dialogue.component'; import { DatasetWizardEditorModel } from './dataset-wizard-editor.model'; -import { DmpStatus } from '../../../core/common/enum/dmp-status'; @Component({ selector: 'app-dataset-wizard-component', @@ -42,7 +42,6 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr breadCrumbs: Observable; viewOnly = false; - @ViewChild('stepper', { static: false }) stepper: MatStepper; editMode = false; publicMode = false; @@ -600,10 +599,6 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr this.formGroup.disable(); } - isActiveStep(index: number) { - return this.stepper.selectedIndex === index; - } - openConfirm(dmpLabel, id): void { const dialogRef = this.dialog.open(ConfirmationDialogComponent, { maxWidth: '300px', @@ -678,4 +673,9 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr } }); } + + linkToScroll: LinkToScroll; + onStepFound(linkToScroll: LinkToScroll) { + this.linkToScroll = linkToScroll; + } } diff --git a/dmp-frontend/src/app/ui/dataset/dataset.module.ts b/dmp-frontend/src/app/ui/dataset/dataset.module.ts index 1296235b4..c2a467d1e 100644 --- a/dmp-frontend/src/app/ui/dataset/dataset.module.ts +++ b/dmp-frontend/src/app/ui/dataset/dataset.module.ts @@ -1,11 +1,15 @@ import { NgModule } from '@angular/core'; +import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; import { CommonFormsModule } from '../../common/forms/common-forms.module'; import { CommonUiModule } from '../../common/ui/common-ui.module'; import { AutoCompleteModule } from '../../library/auto-complete/auto-complete.module'; import { ConfirmationDialogModule } from '../../library/confirmation-dialog/confirmation-dialog.module'; +import { ExportMethodDialogModule } from '../../library/export-method-dialog/export-method-dialog.module'; import { UrlListingModule } from '../../library/url-listing/url-listing.module'; import { DatasetDescriptionFormModule } from '../misc/dataset-description-form/dataset-description-form.module'; +import { TableOfContentsModule } from '../misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.module'; import { ExternalSourcesModule } from '../misc/external-sources/external-sources.module'; +import { DatasetCopyDialogueComponent } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component'; import { DatasetEditorComponent } from './dataset-wizard/dataset-editor/dataset-editor.component'; import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.component'; import { DatasetExternalReferencesEditorComponent } from './dataset-wizard/external-references/dataset-external-references-editor.component'; @@ -15,11 +19,9 @@ import { DatasetExternalRegistryDialogEditorComponent } from './dataset-wizard/e import { DatasetExternalServiceDialogEditorComponent } from './dataset-wizard/external-references/editors/service/dataset-external-service-dialog-editor.component'; import { DatasetRoutingModule } from './dataset.routing'; import { DatasetCriteriaComponent } from './listing/criteria/dataset-criteria.component'; -import { DatasetListingComponent } from './listing/dataset-listing.component'; -import { DatasetCopyDialogueComponent } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component'; import { DatasetUploadDialogue } from './listing/criteria/dataset-upload-dialogue/dataset-upload-dialogue.component'; +import { DatasetListingComponent } from './listing/dataset-listing.component'; import { DatasetListingItemComponent } from './listing/listing-item/dataset-listing-item.component'; -import { ExportMethodDialogModule } from '../../library/export-method-dialog/export-method-dialog.module'; @NgModule({ imports: [ @@ -31,6 +33,8 @@ import { ExportMethodDialogModule } from '../../library/export-method-dialog/exp ExternalSourcesModule, ExportMethodDialogModule, DatasetDescriptionFormModule, + TableOfContentsModule, + AngularStickyThingsModule, DatasetRoutingModule ], declarations: [ diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html index dfc20db71..810d19280 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.html @@ -1,8 +1,8 @@ -
+
-
-
+
+
@@ -17,13 +17,6 @@
- -
-
-
- diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss index 372eb669e..65de16db2 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.scss @@ -1,94 +1,16 @@ @media (max-width: 768px) { - .dynamic-form-editor { - .form-container { - padding: 0px; - } - } + .dynamic-form-editor { + .form-container { + padding: 0px; + } + } +} + +.form-container { } .dynamic-form-editor { - mat-vertical-stepper { - background-color: #ffffff; - } + mat-vertical-stepper { + background-color: #ffffff; + } } - -.toc-and-content { - display: flex; - align-items: flex-start; - text-align: left; - max-width: 940px; - margin: 0 auto; -} - -// table-of-contents { -// top: 0px; -// position: sticky; - -// Reposition on top of content on small screens and remove -// sticky positioning -// @media (max-width: 720px) { -// order: -1; -// position: inherit; -// width: auto; -// padding-left: 0; -// } -// } - -// .ng-sidebar { -// width: 40%; -// } - -// /* .toc-container { -// background: #f9f9f9 none repeat scroll 0 0; -// border: 1px solid #aaa; -// display: table; -// font-size: 95%; -// margin-bottom: 1em; -// padding: 20px; -// width: 100%; -// } */ - -// .ui-steps .ui-steps-item { -// min-width: 10%; -// } - -// .dynamic-form-editor { -// // background-color: #e0e0e0; -// // min-height: 80vh; -// mat-vertical-stepper { -// background-color: #e0e0e0; -// } -// } - -// .ng-sidebar-container { -// overflow: inherit !important; - -// } - -// /* .ng-sidebar__content { -// overflow: inherit !important; -// } */ - -// .alignment-center{ -// text-align: center; -// } - -// .demo-progress-bar-container { - -// width: 100%; - -// } - -// .form-progress-bar { - -// margin: 20px 0; - -// } - -// .full-width{ -// width:100%; -// } - -// .full-height{ -// height:100%; -// } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts index af61f5406..a41d23d57 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.component.ts @@ -1,10 +1,8 @@ import { AfterViewInit, Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { MatHorizontalStepper } from '@angular/material/stepper'; -import { ActivatedRoute, Router } from '@angular/router'; import { BaseComponent } from '../../../core/common/base/base.component'; import { Rule } from '../../../core/model/dataset-profile-definition/rule'; -import { FormFocusService } from './form-focus/form-focus.service'; import { LinkToScroll } from './tableOfContentsMaterial/table-of-contents'; import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; @@ -15,64 +13,21 @@ import { VisibilityRulesService } from './visibility-rules/visibility-rules.serv }) export class DatasetDescriptionFormComponent extends BaseComponent implements OnInit, AfterViewInit, OnChanges { - // pathName: string; - // pages: Array; - // activeStepperIndex = 1; - // visibleSidebar = false; - // datasetProfileDefinitionModel: DatasetDescriptionFormEditorModel; - // private currentPageIndex = 0; @ViewChild('stepper', { static: false }) stepper: MatHorizontalStepper; - - // //@Input() dataModel: DatasetProfileDefinitionModel; @Input() path: string; @Input() form: FormGroup; @Input() visibilityRules: Rule[] = []; - // id: string; - // trackByFn = (index, item) => item ? item['id'] : null; - // pageTrackByFn = (index, item) => item['id']; @Input() datasetProfileId: String; - - linkToScroll: LinkToScroll; - - // uniqueId = Math.random().toString(36).substr(2, 9); + @Input() linkToScroll: LinkToScroll; constructor( - private router: Router, - private route: ActivatedRoute, private visibilityRulesService: VisibilityRulesService, - private formFocusService: FormFocusService ) { super(); - //this.datasetId = route.snapshot.params['id']; } - // getSubForm(subformName) { - // return this.form.controls[subformName]; - // } - ngOnInit() { - - // this.visibilityRulesService.formGroup = this.form; this.visibilityRulesService.buildVisibilityRules(this.visibilityRules, this.form); - // this.datasetProfileDefinitionModel = new DatasetDescriptionFormEditorModel().fromModel(this.dataModel); - // this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel); - - // this.createPagination(); - - // const sections: Pair[] = this.datasetProfileDefinitionModel.pages.map(page => new Pair(page.sections, page.ordinal)).filter(x => x); - // const compositeFields: Pair[] = sections.map(section => new Pair(section.left.flatMap(sec => sec.compositeFields), section.right)).filter(x => x); - // const nestedSections: Pair[] = sections.map(section => new Pair(section.left.flatMap(x => x.sections), section.right)).filter(x => x); - // const nestedCompositeFields: Pair[] = nestedSections.map(section => new Pair(section.left.flatMap(x => x.compositeFields), section.right)).filter(x => x); - // const compositeFieldsUnion: Pair[] = compositeFields.concat(nestedCompositeFields); - - //const fields = compositeFieldsUnion.flatJoinOn(x => x.right); - //this.formFocusService.setFields(compositeFieldsUnion); - // this.route.fragment - // .pipe(takeUntil(this._destroyed)) - // .subscribe((fragment: string) => { - // const self = this; - // setTimeout(function () { self.scrollTo(fragment); }); - // }); } ngOnChanges(changes: SimpleChanges) { @@ -80,59 +35,14 @@ export class DatasetDescriptionFormComponent extends BaseComponent implements On // When the form is changed set stepper index to 0. if (changes['form'] && !changes['form'].isFirstChange()) { this.stepper.selectedIndex = 0; + } else if (changes['linkToScroll'] && changes['linkToScroll'].currentValue) { + if (changes['linkToScroll'].currentValue.page >= 0) { + this.stepper.selectedIndex = changes['linkToScroll'].currentValue.page; + } } } - onStepFound(linkToScroll: LinkToScroll) { - - if (linkToScroll.page >= 0) { - this.stepper.selectedIndex = linkToScroll.page; - } - this.linkToScroll = linkToScroll; - } - ngAfterViewInit() { - //this.visibilityRulesService.triggerVisibilityEvaluation(); - // this.route.queryParams - // .pipe(takeUntil(this._destroyed)) - // .subscribe((params) => { - // if (params && 'page' in params) { - // this.changeCurrentPage(params['page']); - // } - // }); + } - - - // toggleSidebar() { - // this.visibleSidebar = !this.visibleSidebar; - // } - - // shouldDisplaySection(section: Section): Boolean { - // return (section.page) === this.currentPageIndex; - // } - - // createPagination() { - - // } - - // changePageIndex(index: any) { - // this.router.navigate([this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { queryParams: { page: this.pages[index - 1] } }); - // } - - // scrollTo(sectionID: string) { - // if (!sectionID) { return; } - // const element = document.querySelector('#' + sectionID); - // if (!element) { return; } - // element.scrollIntoView(); - // this.visibleSidebar = true; - // } - - // changeCurrentPage(pageString: string) { - // //if (!pageString) { return; } - // const page = parseInt(pageString); - // /*if (isNaN(page)) { return; } - // const pageIndex = this.pages.indexOf(page); - // if (pageIndex === -1) { return; }*/ - // this.stepper.selectedIndex = page; - // } } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts index 5ce506604..ef078ce38 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts @@ -1,4 +1,5 @@ import { NgModule } from '@angular/core'; +import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; import { CommonFormsModule } from '../../../common/forms/common-forms.module'; import { CommonUiModule } from '../../../common/ui/common-ui.module'; import { AutoCompleteModule } from '../../../library/auto-complete/auto-complete.module'; @@ -8,16 +9,16 @@ import { FormProgressIndicationComponent } from './components/form-progress-indi import { FormSectionComponent } from './components/form-section/form-section.component'; import { DatasetDescriptionFormComponent } from './dataset-description-form.component'; import { FormFocusService } from './form-focus/form-focus.service'; -import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; import { TableOfContentsModule } from './tableOfContentsMaterial/table-of-contents.module'; -import { TableOfContents } from './tableOfContentsMaterial/table-of-contents'; +import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; @NgModule({ imports: [ CommonUiModule, CommonFormsModule, AutoCompleteModule, - TableOfContentsModule + // TableOfContentsModule, + // AngularStickyThingsModule ], declarations: [ DatasetDescriptionFormComponent, diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.html index a2bb11d99..fa0ce0a4a 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.html +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.html @@ -1,12 +1,11 @@ -
-
Contents
- +
+
Contents
+ - - {{link.name}} - - +
+ + {{link.name}} + + +
diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.scss index be241f387..b3c4e796e 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.scss +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.scss @@ -1,58 +1,50 @@ -:host { - font-size: 13px; - // Width is container width minus content width - width: 19%; - height: fit-content; - position: -webkit-sticky; - position: sticky; - // display: inline-flex; - align-self: flex-start; - top: 0; - padding-left: 25px; - box-sizing: border-box; -} - .docs-toc-container { - width: 100%; - padding: 5px 0 10px 10px; - cursor: pointer; - border-left: solid 4px #0c7489; + width: 100%; + padding: 5px 0 10px 10px; + cursor: pointer; + border-left: solid 4px #0c7489; - .docs-link { - color: rgba(0, 0, 0, 0.54); - // color: mat-color($app-blue-theme-foreground, secondary-text); - transition: color 100ms; + .scroll-container { + overflow-y: auto; + // calc(100vh - 250px) + height: calc(100vh - 250px); + } - &:hover, - &.docs-active { - color: #0c7489; - // color: mat-color($primary, if($is-dark-theme, 200, default)); - } - } + .docs-link { + color: rgba(0, 0, 0, 0.54); + // color: mat-color($app-blue-theme-foreground, secondary-text); + transition: color 100ms; + + &:hover, + &.docs-active { + 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; + margin: 0; + padding: 0; + font-size: 13px; + font-weight: bold; } span { - line-height: 16px; - margin: 8px 0 0; - position: relative; - text-decoration: none; - display: block; - text-overflow: ellipsis !important; - overflow: hidden; - color: rgba(0, 0, 0, 0.54); + line-height: 16px; + margin: 8px 0 0; + position: relative; + text-decoration: none; + display: block; + text-overflow: ellipsis !important; + overflow: hidden; + color: rgba(0, 0, 0, 0.54); } .docs-level-mat-expansion-panel { - margin-left: 12px; + margin-left: 12px; } .docs-level-h5 { - margin-left: 24px; + margin-left: 24px; } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.ts index 682fffcb1..4c399bee2 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.ts @@ -1,29 +1,22 @@ import { DOCUMENT } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, OnDestroy, OnInit, Output } from '@angular/core'; -import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; -import { fromEvent, Subject } from 'rxjs'; -import { debounceTime, takeUntil } from 'rxjs/operators'; -import { link } from 'fs'; - +import { Component, ElementRef, EventEmitter, Inject, OnInit, Output } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { interval, Subject, Subscription } from 'rxjs'; +import { distinctUntilChanged } from 'rxjs/operators'; +import { BaseComponent } from '../../../../core/common/base/base.component'; 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; } @@ -32,171 +25,73 @@ interface Link { styleUrls: ['./table-of-contents.scss'], templateUrl: './table-of-contents.html' }) -export class TableOfContents implements OnInit, AfterViewInit, OnDestroy { - - @Input() links: Link[] = []; - @Input() container: string; - @Input() headerSelectors = '.toc-page-header, .toc-section-header, .toc-copositeField-header'; +export class TableOfContents extends BaseComponent implements OnInit { + links: Link[] = []; + container: string; + headerSelectors = '.toc-page-header, .toc-section-header, .toc-copositeField-header'; @Output() stepFound = new EventEmitter(); + subscription: Subscription; + linksSubject: Subject = new Subject(); - _rootUrl = this._router.url.split('#')[0]; - private _scrollContainer: any; - private _destroyed = new Subject(); - private _urlFragment = ''; - private selectedLinkId: string; - - constructor(private _router: Router, - private _route: ActivatedRoute, - private _element: ElementRef, + constructor( @Inject(DOCUMENT) private _document: Document) { - - this._router.events.pipe(takeUntil(this._destroyed)).subscribe((event) => { - if (event instanceof NavigationEnd) { - const rootUrl = _router.url.split('#')[0]; - if (rootUrl !== this._rootUrl) { - this.links = this.createLinks(); - this._rootUrl = rootUrl; - } - } - }); - - this._route.fragment.pipe(takeUntil(this._destroyed)).subscribe(fragment => { - this._urlFragment = fragment; - - const target = document.getElementById(this._urlFragment); - if (target) { - target.scrollIntoView(); - } - }); + super(); } + ngOnInit(): void { - // On init, the sidenav content element doesn't yet exist, so it's not possible - // to subscribe to its scroll event until next tick (when it does exist). - Promise.resolve().then(() => { - this._scrollContainer = this.container ? - this._document.querySelectorAll(this.container)[0] : window; - - if (this._scrollContainer) { - fromEvent(this._scrollContainer, 'scroll').pipe( - takeUntil(this._destroyed), - debounceTime(10)) - .subscribe(() => this.onScroll()); - } + //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); }); - } - ngAfterViewInit() { - this.updateScrollPosition(); - } + this.linksSubject.asObservable() + .pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q))) + .subscribe(headers => { + const links: Array = []; - ngOnDestroy(): void { - this._destroyed.next(); - } - - updateScrollPosition(): void { - this.links = this.createLinks(); - - const target = document.getElementById(this._urlFragment); - if (target) { - target.scrollIntoView(); - } - } - - /** Gets the scroll offset of the scroll container */ - private getScrollOffset(): number | void { - const { top } = this._element.nativeElement.getBoundingClientRect(); - if (typeof this._scrollContainer.scrollTop !== 'undefined') { - return this._scrollContainer.scrollTop + top; - } else if (typeof this._scrollContainer.pageYOffset !== 'undefined') { - return this._scrollContainer.pageYOffset + top; - } - } - - private createLinks(): Link[] { - const links: Array = []; - const headers = - Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[]; - - if (headers.length) { - for (const header of headers) { - // const step = 0; - // remove the 'link' icon name from the inner text - const name = header.innerText.trim().replace(/^link/, ''); - const { top } = header.getBoundingClientRect(); - // links.push({ - // name, - // // step, - // type: header.tagName.toLowerCase(), - // top: top, - // id: header.id, - // active: false, - // section: section - // }); - } - } - - return links; - } - - private onScroll(): void { - // for (let i = 0; i < this.links.length; i++) { - // this.links[i].active = this.isLinkActive(this.links[i], this.links[i + 1]); - // } - } - - // private isLinkActive(currentLink: any, nextLink: any): boolean { - // A link is considered active if the page is scrolled passed the anchor without also - // being scrolled passed the next link - // const scrollOffset = this.getScrollOffset(); - // return scrollOffset >= currentLink.top && !(nextLink && nextLink.top < scrollOffset); - // } - - getLinks() { - const links: Array = []; - const headers = - Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[]; - - if (headers.length) { - let page; - let section; - for (const header of headers) { - let name; - let id; - if (header.classList.contains('toc-page-header')) { - name = header.innerText.trim().replace(/^link/, ''); - id = header.id; - page = header.id.split('_')[1]; - section = undefined; - } 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; - } else if (header.classList.contains('toc-copositeField-header')) { - name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, ''); - id = header.id; - // id = header.parentElement.parentElement.parentElement.id; + if (headers.length) { + let page; + let section; + for (const header of headers) { + let name; + let id; + if (header.classList.contains('toc-page-header')) { + name = header.innerText.trim().replace(/^link/, ''); + id = header.id; + page = header.id.split('_')[1]; + section = undefined; + } 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; + } else if (header.classList.contains('toc-copositeField-header')) { + name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, ''); + id = header.id; + // id = header.parentElement.parentElement.parentElement.id; + } + const { top } = header.getBoundingClientRect(); + links.push({ + name, + id, + type: header.tagName.toLowerCase(), + top: top, + active: false, + page: page, + section: section + }); + } } - const { top } = header.getBoundingClientRect(); - links.push({ - name, - id, - type: header.tagName.toLowerCase(), - top: top, - active: this.selectedLinkId == id ? true : false, - page: page, - section: section - }); - } - } - this.links = links; - return links; + this.links = links; + }) } goToStep(link: Link) { - this.selectedLinkId = link.id; + // this.selectedLinkId = link.id; this.stepFound.emit({ page: link.page, section: link.section @@ -210,7 +105,7 @@ export class TableOfContents implements OnInit, AfterViewInit, OnDestroy { if (scrolledY) { window.scroll(0, scrolledY - 70); } - }, 200); + }, 500); } }