Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(project): proof of new project workflow concept (DEV-985) #760

Merged
merged 14 commits into from Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
90 changes: 78 additions & 12 deletions src/app/app-routing.module.ts
@@ -1,34 +1,31 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { AuthGuard } from './main/guard/auth.guard';
import { HintComponent } from './main/action/hint/hint.component';
import { LoginFormComponent } from './main/action/login-form/login-form.component';
import { CookiePolicyComponent } from './main/cookie-policy/cookie-policy.component';
import { StatusComponent } from './main/status/status.component';
import { AuthGuard } from './main/guard/auth.guard';
import { HelpComponent } from './main/help/help.component';
import { LoginFormComponent } from './main/action/login-form/login-form.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';
// project
import { BoardComponent } from './project/board/board.component';
import { CollaborationComponent } from './project/collaboration/collaboration.component';
import { ListComponent } from './project/list/list.component';
import { OntologyComponent } from './project/ontology/ontology.component';
import { PermissionComponent } from './project/permission/permission.component';
import { ProjectComponent } from './project/project.component';

import { ProjectsComponent } from './system/projects/projects.component';
// system
import { SystemComponent } from './system/system.component';
import { UsersComponent } from './system/users/users.component';
// user
import { DashboardComponent } from './user/dashboard/dashboard.component';
import { UserComponent } from './user/user.component';

// search results and resource viewer
import { ResourceComponent } from './workspace/resource/resource.component';
import { ResultsComponent } from './workspace/results/results.component';

// system
import { SystemComponent } from './system/system.component';
import { ProjectsComponent } from './system/projects/projects.component';
import { UsersComponent } from './system/users/users.component';

const routes: Routes = [
{
path: '',
Expand Down Expand Up @@ -102,6 +99,75 @@ const routes: Routes = [
}
]
},
{
path: 'beta/project/:shortcode',
component: ProjectComponent,
children: [
{
path: '',
component: BoardComponent
},
{
path: 'info', // old path setup to avoid 404 when typing beta in front of project
redirectTo: ''
},
{
path: 'ontology',
component: HintComponent,
data: { topic: 'ontology' }
},
{
path: 'ontology/:onto',
component: OntologyComponent,
canActivate: [AuthGuard]
},
{
path: 'ontology/:onto/:class',
component: OntologyClassInstanceComponent,
},
{
path: 'ontology/:onto/:class/conf',
component: StatusComponent,
data: { status: 501, comment: 'Here you will be able to configure the resource class.' },
canActivate: [AuthGuard]
},
{
path: 'ontology/:onto/:class/:instance',
component: OntologyClassInstanceComponent,
},
{
path: 'list',
component: HintComponent,
data: { topic: 'list' }
},
{
path: 'list/:list',
component: ListComponent,
canActivate: [AuthGuard]
},
{
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]
},
{
path: '**',
component: StatusComponent,
data: { status: 404 }
}
]
},
/*
{
path: 'user/:name',
Expand Down
8 changes: 7 additions & 1 deletion src/app/app.module.ts
Expand Up @@ -161,6 +161,9 @@ import { FulltextSearchComponent } from './workspace/search/fulltext-search/full
import { SearchPanelComponent } from './workspace/search/search-panel/search-panel.component';
import { HintComponent } from './main/action/hint/hint.component';
import { TextComponent } from './workspace/resource/representation/text/text.component';
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';

// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
Expand Down Expand Up @@ -308,7 +311,10 @@ export function httpLoaderFactory(httpClient: HttpClient) {
VideoComponent,
VideoPreviewComponent,
HintComponent,
TextComponent
TextComponent,
OntologyClassesComponent,
OntologyClassItemComponent,
OntologyClassInstanceComponent
],
imports: [
AngularSplitModule.forRoot(),
Expand Down
5 changes: 5 additions & 0 deletions src/app/main/action/hint/hint.component.scss
@@ -1,3 +1,8 @@
:host {
padding: 16px;
display: block;
}

a {
margin: 16px auto;

Expand Down
4 changes: 3 additions & 1 deletion src/app/main/action/hint/hint.component.spec.ts
@@ -1,5 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatIconModule } from '@angular/material/icon';
import { RouterTestingModule } from '@angular/router/testing';

import { HintComponent } from './hint.component';

Expand All @@ -13,7 +14,8 @@ describe('HintComponent', () => {
HintComponent
],
imports: [
MatIconModule
MatIconModule,
RouterTestingModule
]
})
.compileComponents();
Expand Down
31 changes: 30 additions & 1 deletion src/app/main/action/hint/hint.component.ts
@@ -1,4 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
selector: 'app-hint',
Expand All @@ -13,9 +14,18 @@ export class HintComponent implements OnInit {

documentation: string;

constructor() { }
constructor(
private _route: ActivatedRoute
) { }

ngOnInit(): void {
if (!this.topic) {
// but status is defined in app.routing
this._route.data.subscribe(data => {
this.topic = data.topic;
});
}

this.content = this._getHint(this.topic);
}

Expand Down Expand Up @@ -43,6 +53,25 @@ export class HintComponent implements OnInit {
</li>
</ul>`;
break;
case 'ontology':
this.documentation = 'https://docs.dasch.swiss/DSP-APP/user-guide/project/#data-model';
return `<p>Data Model</p>
<p>
The definition of the data model (ontology) is the most important step.
The data model is indispensable for structuring your data. Our platform
provides a tool for an easy creation of one or more project data models.
First, you have to know which data and sources you want to work with.
The data model can be flexible and customizable.
</p>`;
break;
case 'list':
this.documentation = '';
return `<p>List Data</p>
<p>
Lists are very useful if you want to use controlled vocabulary to describe something.
Typical examples are keywords.
</p>`;
break;

default:
return `There's no hint implemented for the topic <strong>${topic}<strong>.`;
Expand Down
2 changes: 2 additions & 0 deletions src/app/main/status/status.component.ts
Expand Up @@ -98,6 +98,8 @@ export class StatusComponent implements OnInit {
// but status is defined in app.routing
this._route.data.subscribe(data => {
this.status = data.status;
this.comment = data.comment;
this.url = data.url;
});
}

Expand Down
@@ -0,0 +1,37 @@
<!-- display all resource instances if instance id does not exist -->
<!-- In case if results present -->
<div class="multiple-instances" *ngIf="searchParams">
<as-split direction="horizontal" (dragEnd)="splitSizeChanged = $event">
<as-split-area [size]="40">
<app-list-view [search]="searchParams" [displayViewSwitch]="true" [withMultipleSelection]="true"
(selectedResources)="openSelectedResources($event)">
</app-list-view>
</as-split-area>
<as-split-area [size]="60" *ngIf="selectedResources?.count > 0" cdkScrollable>
<div [ngSwitch]="viewMode">
<!-- single resource view -->
<app-resource *ngSwitchCase="'single'" [resourceIri]="selectedResources.resInfo[0].id" [splitSizeChanged]="splitSizeChanged"></app-resource>

<!-- intermediate view -->
<app-intermediate *ngSwitchCase="'intermediate'" [resources]="selectedResources" (action)="viewMode=$event"></app-intermediate>

<!-- multiple resources view / comparison viewer -->
<app-comparison *ngSwitchCase="'compare'" [noOfResources]="selectedResources.count"
[resources]="selectedResources.resInfo" [splitSizeChanged]="splitSizeChanged">
</app-comparison>
</div>
</as-split-area>
</as-split>
</div>


<!-- add new resource instance if instance id is called "add" -->
<div class="single-instance-form" *ngIf="instanceId && instanceId === 'add'">
<h3>Create new {{classId}} instance</h3>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done a bit nicer so that only the class name is used in the sentence instead of the entire class id string

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing. This will be done in the next iteration. Because I have only the IRI here and I have to make an API request first etc.

<app-resource-instance-form
[selectedResourceClassIri]="classId"
[selectedProject]="projectId">
</app-resource-instance-form>
</div>

<!-- display single resource instance if instance id exists and is not called "add" -->
@@ -0,0 +1,12 @@
@import "../../../../../assets/style/config";

.multiple-instances {
height: calc(100vh - #{$header-height});
}


.single-instance-form {
max-width: 720px;
display: block;
padding: 16px;
}
@@ -0,0 +1,74 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { ActivatedRoute } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { KnoraApiConnection } from '@dasch-swiss/dsp-js';
import { of } from 'rxjs';
import { AppInitService } from 'src/app/app-init.service';
import { DspApiConfigToken, DspApiConnectionToken } from 'src/app/main/declarations/dsp-api-tokens';
import { TestConfig } from 'test.config';
import { OntologyClassInstanceComponent } from './ontology-class-instance.component';


describe('OntologyClassInstanceComponent', () => {
let component: OntologyClassInstanceComponent;
let fixture: ComponentFixture<OntologyClassInstanceComponent>;

const appInitSpy = {
dspAppConfig: {
iriBase: 'http://rdfh.ch'
}
};

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [OntologyClassInstanceComponent],
imports: [
MatSnackBarModule,
MatDialogModule,
RouterTestingModule
],
providers: [
{
provide: AppInitService,
useValue: appInitSpy
},
{
provide: DspApiConfigToken,
useValue: TestConfig.ApiConfig
},
{
provide: DspApiConnectionToken,
useValue: new KnoraApiConnection(TestConfig.ApiConfig)
},
{
provide: ActivatedRoute,
useValue: {
params: of({
onto: 'anything',
class: 'BlueThing',
}),
parent: {
snapshot: {
params: { shortcode: '0001' }
}
}
}
}

]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(OntologyClassInstanceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});