diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index d0e5a3098c..a6ca548982 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -8,10 +8,13 @@ import { HelpComponent } from './main/help/help.component'; import { MainComponent } from './main/main.component'; import { StatusComponent } from './main/status/status.component'; import { OntologyClassInstanceComponent } from './project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component'; +import { SettingsComponent } from './project/beta/settings/settings.component'; // project import { BoardComponent } from './project/board/board.component'; import { CollaborationComponent } from './project/collaboration/collaboration.component'; +import { ListInfoFormComponent } from './project/list/list-info-form/list-info-form.component'; import { ListComponent } from './project/list/list.component'; +import { OntologyFormComponent } from './project/ontology/ontology-form/ontology-form.component'; import { OntologyComponent } from './project/ontology/ontology.component'; import { PermissionComponent } from './project/permission/permission.component'; import { ProjectComponent } from './project/project.component'; @@ -111,6 +114,11 @@ const routes: Routes = [ path: 'info', // old path setup to avoid 404 when typing beta in front of project redirectTo: '' }, + { + path: 'add-ontology', + component: OntologyFormComponent, + canActivate: [AuthGuard] + }, { path: 'ontology', component: HintComponent, @@ -135,6 +143,11 @@ const routes: Routes = [ path: 'ontology/:onto/:class/:instance', component: OntologyClassInstanceComponent, }, + { + path: 'add-list', + component: ListInfoFormComponent, + canActivate: [AuthGuard] + }, { path: 'list', component: HintComponent, @@ -147,19 +160,23 @@ const routes: Routes = [ }, { path: 'settings', - component: StatusComponent, - data: { status: 501, comment: 'Here you will be able to configure the project: e.g. setup collaboration and permissions.' }, - canActivate: [AuthGuard] - }, - { - path: 'settings/collaboration', - component: CollaborationComponent, - canActivate: [AuthGuard] - }, - { - path: 'settings/permissions', - component: PermissionComponent, - canActivate: [AuthGuard] + component: SettingsComponent, + canActivate: [AuthGuard], + children: [ + { + path: '', + pathMatch: 'full', + redirectTo: 'collaboration' + }, + { + path: 'collaboration', + component: CollaborationComponent + }, + { + path: 'permissions', + component: PermissionComponent + }, + ] }, { path: '**', diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 6d14d74683..e8f68883b9 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -164,6 +164,7 @@ import { TextComponent } from './workspace/resource/representation/text/text.com import { OntologyClassesComponent } from './project/beta/ontology-classes/ontology-classes.component'; import { OntologyClassItemComponent } from './project/beta/ontology-classes/ontology-class-item/ontology-class-item.component'; import { OntologyClassInstanceComponent } from './project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component'; +import { SettingsComponent } from './project/beta/settings/settings.component'; // translate: AoT requires an exported function for factories export function httpLoaderFactory(httpClient: HttpClient) { @@ -314,7 +315,8 @@ export function httpLoaderFactory(httpClient: HttpClient) { TextComponent, OntologyClassesComponent, OntologyClassItemComponent, - OntologyClassInstanceComponent + OntologyClassInstanceComponent, + SettingsComponent ], imports: [ AngularSplitModule.forRoot(), diff --git a/src/app/main/action/hint/hint.component.html b/src/app/main/action/hint/hint.component.html index 0c90c07091..a186641a09 100644 --- a/src/app/main/action/hint/hint.component.html +++ b/src/app/main/action/hint/hint.component.html @@ -1,5 +1,5 @@
- + Read more in the user guidelaunch diff --git a/src/app/main/dialog/dialog.component.html b/src/app/main/dialog/dialog.component.html index d2682da841..01a77fc374 100644 --- a/src/app/main/dialog/dialog.component.html +++ b/src/app/main/dialog/dialog.component.html @@ -32,12 +32,12 @@ @@ -179,12 +179,12 @@ Do you want to delete this node? @@ -208,12 +208,12 @@ Do you want to delete this list? @@ -237,12 +237,12 @@ Do you want to delete this data model? @@ -268,12 +268,12 @@ Do you want to delete this resource class? @@ -308,12 +308,12 @@ Do you want to delete this property? @@ -347,7 +347,7 @@ diff --git a/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.html b/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.html index 88643b5630..1735a99a8c 100644 --- a/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.html +++ b/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.html @@ -27,7 +27,7 @@
-

Create new {{classId}} instance

+

Create new resource of type: {{resClass?.label}}

@@ -35,3 +35,6 @@

Create new {{classId}} instance

+
+ +
diff --git a/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts b/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts index fe72f6059c..342e90d19f 100644 --- a/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts +++ b/src/app/project/beta/ontology-classes/ontology-class-instance/ontology-class-instance.component.ts @@ -1,6 +1,8 @@ -import { Component } from '@angular/core'; +import { Component, OnChanges } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { ReadOntology, ResourceClassDefinition } from '@dasch-swiss/dsp-js'; import { AppInitService } from 'src/app/app-init.service'; +import { CacheService } from 'src/app/main/cache/cache.service'; import { OntologyService } from 'src/app/project/ontology/ontology.service'; import { FilteredResources, SearchParams } from 'src/app/workspace/results/list-view/list-view.component'; import { SplitSize } from 'src/app/workspace/results/results.component'; @@ -10,13 +12,21 @@ import { SplitSize } from 'src/app/workspace/results/results.component'; templateUrl: './ontology-class-instance.component.html', styleUrls: ['./ontology-class-instance.component.scss'] }) -export class OntologyClassInstanceComponent { +export class OntologyClassInstanceComponent implements OnChanges { projectId: string; + ontoId: string; + + // id (iri) of resource class classId: string; + resClass: ResourceClassDefinition; + + // uuid of resource instance instanceId: string; + // id (iri) or resource instance + resourceIri: string; searchParams: SearchParams; @@ -30,6 +40,7 @@ export class OntologyClassInstanceComponent { constructor( private _ais: AppInitService, + private _cache: CacheService, private _route: ActivatedRoute, private _ontologyService: OntologyService ) { @@ -46,16 +57,22 @@ export class OntologyClassInstanceComponent { const className = params['class']; // get the resource class id from route - this.classId = `${iriBase}/ontology/${projectCode}/${ontologyName}/v2#${className}`; + this.ontoId = `${iriBase}/ontology/${projectCode}/${ontologyName}/v2`; + this.classId = `${this.ontoId}#${className}`; this.instanceId = params['instance']; if (this.instanceId) { - // single instance + // single instance view if (this.instanceId === 'add') { // create new res class instance: display res instance form + this.ngOnChanges(); + } else { + // get the single resource instance + this.resourceIri = `${this._ais.dspAppConfig.iriBase}/${projectCode}/${this.instanceId}`; } } else { + // display all resource instances of this resource class this.searchParams = { query: this._setGravsearch(this.classId), mode: 'gravsearch' @@ -64,6 +81,16 @@ export class OntologyClassInstanceComponent { }); } + ngOnChanges() { + this._cache.get('currentProjectOntologies').subscribe( + (ontologies: ReadOntology[]) => { + // find ontology of current resource class to get the class label + const classes = ontologies[ontologies.findIndex(onto => onto.id === this.ontoId)].getAllClassDefinitions(); + this.resClass = classes[classes.findIndex(res => res.id === this.classId)]; + } + ); + } + openSelectedResources(res: FilteredResources) { this.selectedResources = res; diff --git a/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.html b/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.html index acb38ff276..bfbaf735ca 100644 --- a/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.html +++ b/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.html @@ -1,14 +1,15 @@

{{resClass.label}}

- {{results | i18nPlural: itemPluralMapping['instance']}} + {{results | i18nPlural: itemPluralMapping['resource']}}
- + + diff --git a/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.ts b/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.ts index ea1822c6fb..1f2a28a193 100644 --- a/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.ts +++ b/src/app/project/beta/ontology-classes/ontology-class-item/ontology-class-item.component.ts @@ -14,6 +14,8 @@ export class OntologyClassItemComponent implements OnInit { @Input() resClass: ClassDefinition; + @Input() projectMember: boolean; + gravsearch: string; results: number; @@ -22,9 +24,9 @@ export class OntologyClassItemComponent implements OnInit { // i18n setup itemPluralMapping = { - instance: { - '=1': '1 instance', - other: '# instances' + resource: { + '=1': '1 resource', + other: '# resources' } }; diff --git a/src/app/project/beta/ontology-classes/ontology-classes.component.html b/src/app/project/beta/ontology-classes/ontology-classes.component.html index 6adc248a8e..2a64e1fd60 100644 --- a/src/app/project/beta/ontology-classes/ontology-classes.component.html +++ b/src/app/project/beta/ontology-classes/ontology-classes.component.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/project/beta/ontology-classes/ontology-classes.component.ts b/src/app/project/beta/ontology-classes/ontology-classes.component.ts index 5d2802d8c7..9d46c5499e 100644 --- a/src/app/project/beta/ontology-classes/ontology-classes.component.ts +++ b/src/app/project/beta/ontology-classes/ontology-classes.component.ts @@ -11,6 +11,8 @@ export class OntologyClassesComponent implements OnInit { @Input() resClasses: ClassDefinition[]; + @Input() projectMember: boolean; + classesToDisplay: ClassDefinition[] = []; constructor( diff --git a/src/app/project/beta/settings/settings.component.html b/src/app/project/beta/settings/settings.component.html new file mode 100644 index 0000000000..c8ec54672a --- /dev/null +++ b/src/app/project/beta/settings/settings.component.html @@ -0,0 +1,8 @@ + + diff --git a/src/app/project/beta/settings/settings.component.scss b/src/app/project/beta/settings/settings.component.scss new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/app/project/beta/settings/settings.component.scss @@ -0,0 +1 @@ + diff --git a/src/app/project/beta/settings/settings.component.spec.ts b/src/app/project/beta/settings/settings.component.spec.ts new file mode 100644 index 0000000000..5ff1480f4c --- /dev/null +++ b/src/app/project/beta/settings/settings.component.spec.ts @@ -0,0 +1,29 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { SettingsComponent } from './settings.component'; + +describe('SettingsComponent', () => { + let component: SettingsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ SettingsComponent ], + imports: [ + RouterTestingModule + ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/project/beta/settings/settings.component.ts b/src/app/project/beta/settings/settings.component.ts new file mode 100644 index 0000000000..9da9a128ca --- /dev/null +++ b/src/app/project/beta/settings/settings.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit } from '@angular/core'; +import { AppGlobal } from 'src/app/app-global'; +import { MenuItem } from 'src/app/main/declarations/menu-item'; + +@Component({ + selector: 'app-settings', + templateUrl: './settings.component.html', + styleUrls: ['./settings.component.scss'] +}) +export class SettingsComponent implements OnInit { + + navigation: MenuItem[] = []; + + loading = false; + + constructor() { } + + ngOnInit(): void { + // we need only two items from the old project navigation + // collaboration + this.navigation.push(AppGlobal.projectNav[1]); + // permissions + this.navigation.push(AppGlobal.projectNav[2]); + } + +} diff --git a/src/app/project/board/board.component.html b/src/app/project/board/board.component.html index 45050030c9..432c851a89 100644 --- a/src/app/project/board/board.component.html +++ b/src/app/project/board/board.component.html @@ -1,6 +1,13 @@
+ +
+ This is a preview of a new project view concept! + We are working on a new project view concept. Switch to the beta version. + + Beta Preview +
@@ -10,8 +17,8 @@ - - diff --git a/src/app/project/board/board.component.scss b/src/app/project/board/board.component.scss index 9060f231a4..32251a2cc8 100644 --- a/src/app/project/board/board.component.scss +++ b/src/app/project/board/board.component.scss @@ -6,6 +6,13 @@ section { margin: 24px 16px; } +.note { + border-radius: $border-radius; + width: 100%; + display: inline-flex; + margin-bottom: 16px; +} + // phone devices @media (max-width: map-get($grid-breakpoints, phone)) { diff --git a/src/app/project/board/board.component.spec.ts b/src/app/project/board/board.component.spec.ts index 2959757c42..2a9741403f 100644 --- a/src/app/project/board/board.component.spec.ts +++ b/src/app/project/board/board.component.spec.ts @@ -3,6 +3,7 @@ import { MatChipsModule } from '@angular/material/chips'; import { MatDialogModule } from '@angular/material/dialog'; import { MatDividerModule } from '@angular/material/divider'; import { MatIconModule } from '@angular/material/icon'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { ActivatedRoute } from '@angular/router'; @@ -37,6 +38,7 @@ describe('BoardComponent', () => { MatDialogModule, MatDividerModule, MatIconModule, + MatSlideToggleModule, MatSnackBarModule, RouterTestingModule ], @@ -51,7 +53,12 @@ describe('BoardComponent', () => { return TestConfig.ProjectCode; } } - }) + }), + snapshot: { + url: [ + { path: 'project' } + ] + } } } }, diff --git a/src/app/project/board/board.component.ts b/src/app/project/board/board.component.ts index 795db8451f..8876170e81 100644 --- a/src/app/project/board/board.component.ts +++ b/src/app/project/board/board.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { ApiResponseError, ReadProject @@ -42,20 +42,25 @@ export class BoardComponent implements OnInit { color = 'primary'; + beta = false; + constructor( private _cache: CacheService, private _errorHandler: ErrorHandlerService, private _session: SessionService, private _dialog: MatDialog, private _route: ActivatedRoute, - private _titleService: Title, - private _snackBar: MatSnackBar + private _router: Router, + private _titleService: Title ) { // get the shortcode of the current project this._route.parent.paramMap.subscribe((params: Params) => { this.projectCode = params.get('shortcode'); }); + // get feature toggle information if url contains beta + this.beta = (this._route.parent.snapshot.url[0].path === 'beta'); + // set the page title this._titleService.setTitle('Project ' + this.projectCode); } @@ -95,17 +100,6 @@ export class BoardComponent implements OnInit { this.loading = false; } - // copy link to clipboard - copyToClipboard(msg: string) { - const message = 'Copied to clipboard!'; - const action = msg; - this._snackBar.open(message, action, { - duration: 3000, - horizontalPosition: 'center', - verticalPosition: 'top' - }); - } - openDialog(mode: string, name: string, id?: string): void { const dialogConfig: MatDialogConfig = { width: '560px', @@ -123,4 +117,8 @@ export class BoardComponent implements OnInit { this.getProject(); }); } + + featureToggle() { + this._router.navigate([(this.beta ? 'beta' : ''), 'project', this.projectCode ]); + } } diff --git a/src/app/project/collaboration/collaboration.component.spec.ts b/src/app/project/collaboration/collaboration.component.spec.ts index ed00282e7e..e27a0020d9 100644 --- a/src/app/project/collaboration/collaboration.component.spec.ts +++ b/src/app/project/collaboration/collaboration.component.spec.ts @@ -69,7 +69,12 @@ describe('CollaborationComponent', () => { return TestConfig.ProjectCode; } } - }) + }), + parent: { + snapshot: { + url: [] + } + } } } }, diff --git a/src/app/project/collaboration/collaboration.component.ts b/src/app/project/collaboration/collaboration.component.ts index 4e0c448f93..62bf554ae6 100644 --- a/src/app/project/collaboration/collaboration.component.ts +++ b/src/app/project/collaboration/collaboration.component.ts @@ -60,6 +60,13 @@ export class CollaborationComponent implements OnInit { this.projectCode = params.get('shortcode'); }); + // in case of new beta view, we are in a grand-child route + if (this._route.parent.parent.snapshot.url.length) { + this._route.parent.parent.paramMap.subscribe((params: Params) => { + this.projectCode = params.get('shortcode'); + }); + } + // set the page title this._titleService.setTitle('Project ' + this.projectCode + ' | Collaboration'); diff --git a/src/app/project/list/list-info-form/list-info-form.component.html b/src/app/project/list/list-info-form/list-info-form.component.html index 58bcb4e812..3ad43656c3 100644 --- a/src/app/project/list/list-info-form/list-info-form.component.html +++ b/src/app/project/list/list-info-form/list-info-form.component.html @@ -2,7 +2,7 @@
- +

Create new list

@@ -18,11 +18,9 @@ {{ commentInvalidMessage }}
- - - + - +
-
+
diff --git a/src/app/project/ontology/ontology.component.scss b/src/app/project/ontology/ontology.component.scss index 668a4e6d48..93a3b67153 100644 --- a/src/app/project/ontology/ontology.component.scss +++ b/src/app/project/ontology/ontology.component.scss @@ -30,6 +30,13 @@ $width: 340px; margin: 0 auto 60px auto; z-index: 0; + &.beta { + // resize the with in beta view because of sidenav container + width: auto; + margin: 0; + height: calc(100vh - #{$header-height} - 2px); + } + .ontology-editor-header { z-index: 2; top: 121px; @@ -81,12 +88,15 @@ $width: 340px; } .ontology-editor-container { + height: calc(100% - #{$header-height} - 8px); + .ontology-editor-subheader { height: $sub-header-height; } .ontology-editor-sidenav { width: 200px; + border: none; button { width: 100%; diff --git a/src/app/project/ontology/ontology.component.ts b/src/app/project/ontology/ontology.component.ts index 01e0cb5552..63aedf8f9f 100644 --- a/src/app/project/ontology/ontology.component.ts +++ b/src/app/project/ontology/ontology.component.ts @@ -134,7 +134,6 @@ export class OntologyComponent implements OnInit { private _sortingService: SortingService, private _titleService: Title ) { - // get the shortcode of the current project this._route.parent.paramMap.subscribe((params: Params) => { this.projectCode = params.get('shortcode'); @@ -158,14 +157,11 @@ export class OntologyComponent implements OnInit { const projectCode = this._route.parent.snapshot.params.shortcode; this._route.params.subscribe(params => { const iriBase = this._ontologyService.getIriBaseUrl(); - const ontologyName = params['onto']; this.ontologyIri = `${iriBase}/ontology/${projectCode}/${ontologyName}/v2`; this.ngOnInit(); }); - console.warn('This is a pre-released (beta) project\'s ontology view'); } - } @HostListener('window:resize', ['$event']) onWindwoResize(e: Event) { @@ -183,6 +179,7 @@ export class OntologyComponent implements OnInit { // get information about the logged-in user this.session = this._session.getSession(); + // is the logged-in user system admin? this.sysAdmin = this.session.user.sysAdmin; @@ -469,6 +466,10 @@ export class OntologyComponent implements OnInit { dialogRef.afterClosed().subscribe(result => { // update the view this.initOntologiesList(); + if (this.beta) { + // refresh whole page; todo: would be better to use an event emitter to the parent to update the list of resource classes + window.location.reload(); + } }); } @@ -542,8 +543,14 @@ export class OntologyComponent implements OnInit { // get the ontologies for this project this.initOntologiesList(); // go to project ontology page - const goto = 'project/' + this.projectCode + '/ontologies/'; - this._router.navigateByUrl(goto, { skipLocationChange: false }); + let goto = `/project/${this.projectCode}/ontologies/`; + if (this.beta) { + goto = `/beta/project/${this.projectCode}`; + } + this._router.navigateByUrl(goto, { skipLocationChange: false }).then(() => { + // refresh whole page; todo: would be better to use an event emitter to the parent to update the list of resource classes + window.location.reload(); + }); }, (error: ApiResponseError) => { this._errorHandler.showMessage(error); @@ -563,6 +570,10 @@ export class OntologyComponent implements OnInit { (response: OntologyMetadata) => { this.loading = false; this.resetOntology(this.ontologyIri); + if (this.beta) { + // refresh whole page; todo: would be better to use an event emitter to the parent to update the list of resource classes + window.location.reload(); + } }, (error: ApiResponseError) => { this._errorHandler.showMessage(error); diff --git a/src/app/project/permission/permission.component.spec.ts b/src/app/project/permission/permission.component.spec.ts index cf13fcf122..692fb02fe2 100644 --- a/src/app/project/permission/permission.component.spec.ts +++ b/src/app/project/permission/permission.component.spec.ts @@ -53,7 +53,12 @@ describe('PermissionComponent', () => { return TestConfig.ProjectCode; } } - }) + }), + parent: { + snapshot: { + url: [] + } + } } } }, diff --git a/src/app/project/permission/permission.component.ts b/src/app/project/permission/permission.component.ts index 4ce7686854..ac470f9a78 100644 --- a/src/app/project/permission/permission.component.ts +++ b/src/app/project/permission/permission.component.ts @@ -53,6 +53,13 @@ export class PermissionComponent implements OnInit { this.projectCode = params.get('shortcode'); }); + // in case of new beta view, we are in a grand-child route + if (this._route.parent.parent.snapshot.url.length) { + this._route.parent.parent.paramMap.subscribe((params: Params) => { + this.projectCode = params.get('shortcode'); + }); + } + // set the page title this._titleService.setTitle('Project ' + this.projectCode + ' | Permission Groups'); diff --git a/src/app/project/project.component.html b/src/app/project/project.component.html index a453be4f04..9b708ce64f 100644 --- a/src/app/project/project.component.html +++ b/src/app/project/project.component.html @@ -1,5 +1,4 @@
-
- -
- + @@ -37,9 +34,12 @@

- + - @@ -50,7 +50,7 @@

- + {{onto.label}} @@ -64,12 +64,12 @@ - + @@ -81,9 +81,12 @@ - + - @@ -96,16 +99,18 @@ - + -