+
+
+
Active
@@ -13,54 +13,175 @@
-
+
-
-
diff --git a/src/app/project/board/board.component.scss b/src/app/project/board/board.component.scss
index 178c18acf5..00d5eae078 100644
--- a/src/app/project/board/board.component.scss
+++ b/src/app/project/board/board.component.scss
@@ -1,4 +1,5 @@
@import "../../../assets/style/responsive";
+@import "../../../assets/style/config";
section {
margin: 24px auto;
@@ -6,7 +7,7 @@ section {
// phone devices
@media (max-width: map-get($grid-breakpoints, phone)) {
-
+
.fill-remaining-space {
display: none;
}
@@ -40,8 +41,180 @@ section {
// desktop and tablet devices
@media (min-width: map-get($grid-breakpoints, phone)) {
-
+
+ .more-space-bottom {
+ margin-bottom: 15px !important;
+ }
+
.app-toolbar-mobile {
display: none;
}
}
+
+.project-info-container {
+ width: 98vw;
+ max-width: 1280px;
+ position: relative;
+ margin: 0 auto 60px auto;
+
+ .left-info {
+ flex: 70%;
+ }
+
+ .right-info {
+ flex: 30%;
+ max-width: 400px;
+ }
+
+ .column {
+ padding: 15px;
+ }
+
+ .metadata-box {
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: whitesmoke;
+ border: 1px solid $primary_100;
+ border-radius: $border-radius;
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
+ }
+
+ .tab-contents {
+ margin-top: 20px;
+ }
+
+ .display-inline-block {
+ display: inline-block;
+ }
+
+ .copy-to-clipboard {
+ display: inline-block;
+ float: right;
+
+ button {
+ cursor: pointer;
+ border: none;
+ }
+ }
+
+ .mat-radio-button {
+ margin-bottom: 5px;
+ display: block;
+ }
+
+ /*
+ .mat-radio-container{
+ height: 15px;
+ width: 15px;
+ }
+ .mat-radio-outer-circle{
+ height: 15px;
+ width: 15px;
+ }
+ .mat-radio-inner-circle{
+ height: 15px;
+ width: 15px;
+ }
+ .mat-radio-button .mat-radio-ripple{
+ height: 15px;
+ width: 15px;
+ left: calc(50% - 15px);
+ top: calc(50% - 15px);
+ }
+ */
+
+ .download-metadata {
+ margin-right: 10px;
+ }
+
+ .sidenav-prop-text {
+ text-align: left;
+ overflow-wrap: break-word;
+ font-weight: inherit;
+ color: #434242;
+ }
+
+ .sidenav-properties-container {
+
+ .property {
+
+ .property-label {
+ font-weight: bold;
+ font-size: 16px;
+ margin-bottom: 8px;
+ text-align: left;
+ overflow-wrap: break-word;
+ }
+
+ .property-value {
+ margin-left: 20px;
+ }
+ }
+
+ .property:not(:last-child) {
+ margin-bottom: 13px;
+ }
+ }
+
+ // grid
+ ::ng-deep .properties-container {
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ gap: 16px;
+
+ .properties {
+ grid-column: 1 / span 6;
+ margin-top: 16px;
+
+ .property {
+ grid-row: 1 / 1;
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 16px;
+ margin-top: 5px;
+
+ .property-label,
+ .property-value {
+ overflow-wrap: break-word;
+ }
+
+ .property-label {
+ grid-column: 1 / span 1;
+ padding: 2px;
+
+ .label {
+ text-align: right;
+ color: rgba(0,0,0,.54);
+ }
+ }
+
+ .property-value {
+ grid-column: 2 / span 3;
+ padding: 5px 2px 8px;
+ }
+ }
+ }
+ }
+
+ ::ng-deep .person {
+
+ h4 {
+ margin-bottom: 6px;
+ margin-top: 6px;
+ display: inline-block;
+ }
+
+ p {
+ margin-top: 0px;
+ margin-bottom: 8px;
+ }
+
+ .sub-details {
+ margin-top: 10px;
+ .contents {
+ margin-left: 35px;
+ }
+ }
+ }
+
+}
diff --git a/src/app/project/board/board.component.spec.ts b/src/app/project/board/board.component.spec.ts
index e3b7d67f8f..d0be5e4144 100644
--- a/src/app/project/board/board.component.spec.ts
+++ b/src/app/project/board/board.component.spec.ts
@@ -6,16 +6,15 @@ import { MatIconModule } from '@angular/material/icon';
import { ActivatedRoute } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { KnoraApiConnection } from '@dasch-swiss/dsp-js';
-import {
- AppInitService,
- DspActionModule,
- DspApiConfigToken,
- DspApiConnectionToken,
- DspCoreModule
-} from '@dasch-swiss/dsp-ui';
+import { AppInitService, DspActionModule, DspApiConfigToken, DspApiConnectionToken, DspCoreModule } from '@dasch-swiss/dsp-ui';
import { of } from 'rxjs';
import { TestConfig } from 'test.config';
import { BoardComponent } from './board.component';
+import { AttributionTabViewComponent } from './attribution-tab-view/attribution-tab-view.component';
+import { ContactsTabViewComponent } from './contacts-tab-view/contacts-tab-view.component';
+import { DatasetTabViewComponent } from './dataset-tab-view/dataset-tab-view.component';
+import { ProjectTabViewComponent } from './project-tab-view/project-tab-view.component';
+import { TermsTabViewComponent } from './terms-tab-view/terms-tab-view.component';
describe('BoardComponent', () => {
let component: BoardComponent;
@@ -23,7 +22,14 @@ describe('BoardComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [BoardComponent],
+ declarations: [
+ BoardComponent,
+ AttributionTabViewComponent,
+ ContactsTabViewComponent,
+ DatasetTabViewComponent,
+ ProjectTabViewComponent,
+ TermsTabViewComponent
+ ],
imports: [
DspActionModule,
DspCoreModule,
diff --git a/src/app/project/board/board.component.ts b/src/app/project/board/board.component.ts
index 39aef68226..4fe406ca00 100644
--- a/src/app/project/board/board.component.ts
+++ b/src/app/project/board/board.component.ts
@@ -2,10 +2,12 @@ import { Component, Inject, OnInit } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Params } from '@angular/router';
-import { ApiResponseData, ApiResponseError, KnoraApiConnection, ProjectResponse, ReadProject, ReadUser } from '@dasch-swiss/dsp-js';
+import { ApiResponseData, ApiResponseError, KnoraApiConnection, ProjectResponse, ReadProject } from '@dasch-swiss/dsp-js';
import { DspApiConnectionToken, Session, SessionService } from '@dasch-swiss/dsp-ui';
import { DialogComponent } from 'src/app/main/dialog/dialog.component';
import { CacheService } from '../../main/cache/cache.service';
+import { MatRadioChange } from '@angular/material/radio';
+import { ClipboardService } from 'ngx-clipboard';
@Component({
selector: 'app-board',
@@ -14,7 +16,7 @@ import { CacheService } from '../../main/cache/cache.service';
})
export class BoardComponent implements OnInit {
- // loading for progess indicator
+ // loading for progress indicator
loading: boolean;
// permissions of logged-in user
@@ -28,23 +30,26 @@ export class BoardComponent implements OnInit {
// project data
project: ReadProject;
- projectMembers: ReadUser[] = [];
-
- // i18n setup
- itemPluralMapping = {
- member: {
- '=1': '1 User',
- other: '# Users'
- },
- ontology: {
- '=1': '1 Ontology',
- other: '# Ontologies'
- },
- keyword: {
- '=1': '1 Keyword',
- other: '# Keywords'
- }
- };
+ color: string = 'primary';
+
+ // variables to store metadata information
+ metadata: object;
+ datasetMetadata: object;
+ projectMetadata: object;
+ attribution: object;
+ conditionsOfAccess: string;
+ license: object;
+ contactDetails: object;
+ projectDescription: string;
+ datasetOptions: object[];
+ howToCite: string;
+ datasetIdentifier: string;
+ publicationDate: string;
+ keywords: object;
+ selectedDataset: string;
+
+ // different metadata download formats
+ metadataDownloadFormats = ['XML', 'JSON', 'JSON-LD', 'Triplestore'];
constructor(
@Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection,
@@ -52,7 +57,8 @@ export class BoardComponent implements OnInit {
private _session: SessionService,
private _dialog: MatDialog,
private _route: ActivatedRoute,
- private _titleService: Title
+ private _titleService: Title,
+ private _clipboardService: ClipboardService
) {
// get the shortcode of the current project
this._route.parent.paramMap.subscribe((params: Params) => {
@@ -73,7 +79,11 @@ export class BoardComponent implements OnInit {
this.sysAdmin = this.session.user.sysAdmin;
}
+ // get project info from backend
this.getProject();
+
+ // get project and dataset metadata from backend
+ this.getProjectMetadata();
}
getProject() {
@@ -90,6 +100,8 @@ export class BoardComponent implements OnInit {
this.projectAdmin = this.sysAdmin ? this.sysAdmin : this.session.user.projectAdmin.some(e => e === this.project.id);
}
+ this.datasetIdentifier = this.project['id'];
+
this.loading = false;
},
(error: ApiResponseError) => {
@@ -100,13 +112,174 @@ export class BoardComponent implements OnInit {
this.loading = false;
}
+ getProjectMetadata() {
+ // get project metadata from backend
+ // note: for now to complete functionality we have used hard-coded metadata.
+ // in next iteration, it will be replace with ajax request to get
+ // metadata from backend
+ this.metadata = {
+ 'projectsMetadata': [{
+ 'abstract': 'Dies ist ein Testprojekt.',
+ 'alternativeTitle': 'test',
+ 'conditionsOfAccess': 'Open Access',
+ 'dateCreated': '2001-09-26',
+ 'dateModified': '2020-04-26',
+ 'datePublished': '2002-09-24',
+ 'distribution': {'type': 'https://schema.org/DataDownload', 'value': 'https://test.dasch.swiss'},
+ 'documentation': 'Work in progress',
+ 'howToCite': 'Testprojekt (test), 2002, https://test.dasch.swiss',
+ 'language': ['EN', 'DE', 'FR'],
+ 'license': {'type': 'https://schema.org/URL', 'value': 'https://creativecommons.org/licenses/by/3.0'},
+ 'qualifiedAttribution': [{'role': 'contributor', 'agent': 'http://ns.dasch.swiss/test-berry'}, {'role': 'contributor', 'agent': 'http://ns.dasch.swiss/test-hart'}, {
+ 'role': 'editor',
+ 'agent': 'http://ns.dasch.swiss/test-abraham'
+ }, {'role': 'editor', 'agent': 'http://ns.dasch.swiss/test-coleman'}, {'role': 'editor', 'agent': 'http://ns.dasch.swiss/test-jones'}],
+ 'status': 'ongoing',
+ 'title': 'Testprojekt',
+ 'typeOfData': ['image', 'text'],
+ 'project': {
+ 'alternateName': 'test',
+ 'contactPoint': {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'stewart.abraham@test.ch',
+ 'familyName': 'Abraham',
+ 'givenName': 'Stewart',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch',
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://orcid.org/0000-0002-1825-0097'},
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ }
+ },
+ 'dataManagementPlan': {'url': {'type': 'https://schema.org/URL', 'value': 'https://snf.ch'}, 'isAvailable': true},
+ 'description': 'Dies ist ein Testprojekt...alle Properties wurden verwendet, um diese zu testen',
+ 'discipline': {'name': 'SKOS UNESCO Nomenclature', 'url': 'http://skos.um.es/unesco6/11'},
+ 'endDate': '2001-01-26',
+ 'funder': 'http://ns.dasch.swiss/test-funder',
+ 'grant': {
+ 'funder': [
+ {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ },
+ {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'lauren.berry@unibas.ch',
+ 'familyName': 'Berry',
+ 'givenName': 'Lauren',
+ 'jobTitle': 'Dr.',
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': 'info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': 'http://www.utoronto.ca/'
+ }
+ }], 'name': 'Test Grant Name', 'number': '0123456789', 'url': {'type': 'https://schema.org/URL', 'value': 'http://p3.snf.ch/testproject'}
+ },
+ 'keywords': ['science', 'mathematics', 'history of science', 'history of mathematics'],
+ 'name': 'Testprojektname (test)',
+ 'publication': 'testpublication',
+ 'shortcode': '0000',
+ 'spatialCoverage': [
+ {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/2017370/russian-federation.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2658434/switzerland.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3175395/italian-republic.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2921044/federal-republic-of-germany.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3017382/republic-of-france.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/6269131/england.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/6255148/europe.html'}}],
+ 'startDate': '2000-07-26',
+ 'temporalCoverage': {'name': 'Chronontology Dainst', 'url': 'http://chronontology.dainst.org/period/Ef9SyESSafJ1'},
+ 'url': {'type': 'https://schema.org/URL', 'value': 'https://test.dasch.swiss/'}
+ },
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://test.dasch.swiss/'}
+ }, {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': '/benjamin.jones@test.ch',
+ 'familyName': 'Jones',
+ 'givenName': 'Benjamin',
+ 'jobTitle': 'Dr. des.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch'
+ }, {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': '/james.coleman@dasch.swiss',
+ 'familyName': 'Coleman',
+ 'givenName': 'James',
+ 'jobTitle': 'Dr. des.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch'
+ }, {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': '/lauren.berry@unibas.ch',
+ 'familyName': 'Berry',
+ 'givenName': 'Lauren',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch'
+ }, {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': '/leonhard.hart@test.ch',
+ 'familyName': 'Hart',
+ 'givenName': 'Leonhard',
+ 'jobTitle': 'Prof.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch'
+ }]
+ };
+
+ this.datasetMetadata = this.metadata['projectsMetadata'][0];
+
+ // dataset options to display radio buttons for selection in right column
+ this.datasetOptions = [
+ {'name': this.datasetMetadata['title'], 'id': 0, 'checked': true}
+ ];
+
+ // initialise metadata
+ this.initialiseMetadataVariables();
+ }
+
+ // initialise metadata variables required to display in template
+ initialiseMetadataVariables() {
+ this.projectMetadata = this.datasetMetadata['project'];
+ this.attribution = this.datasetMetadata['qualifiedAttribution'];
+ this.conditionsOfAccess = this.datasetMetadata['conditionsOfAccess'];
+ this.license = this.datasetMetadata['license'];
+ this.contactDetails = this.projectMetadata['contactPoint'];
+ this.projectDescription = this.projectMetadata['description'];
+ this.howToCite = this.datasetMetadata['howToCite'];
+ this.publicationDate = this.datasetMetadata['datePublished'];
+ this.keywords = this.projectMetadata['keywords'];
+ }
+
+ updateDataset(event: MatRadioChange) {
+ this.datasetMetadata = this.metadata['projectsMetadata'][event.value];
+
+ // initialise metadata variables again
+ this.initialiseMetadataVariables();
+ }
+
+ copyHowToCiteToClipboard() {
+ this._clipboardService.copyFromContent(this.howToCite);
+ }
+
openDialog(mode: string, name: string, id?: string): void {
const dialogConfig: MatDialogConfig = {
width: '560px',
position: {
top: '112px'
},
- data: { mode: mode, title: name, project: id }
+ data: {mode: mode, title: name, project: id}
};
const dialogRef = this._dialog.open(DialogComponent, dialogConfig);
diff --git a/src/app/project/board/contacts-tab-view/contacts-tab-view.component.html b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.html
new file mode 100644
index 0000000000..e2a6a19b98
--- /dev/null
+++ b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.html
@@ -0,0 +1,5 @@
+
Contact
+
+
diff --git a/src/app/project/board/contacts-tab-view/contacts-tab-view.component.scss b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.scss
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.scss
@@ -0,0 +1 @@
+
diff --git a/src/app/project/board/contacts-tab-view/contacts-tab-view.component.spec.ts b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.spec.ts
new file mode 100644
index 0000000000..cdc11b081c
--- /dev/null
+++ b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.spec.ts
@@ -0,0 +1,51 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { ContactsTabViewComponent } from './contacts-tab-view.component';
+import { Component, ViewChild } from '@angular/core';
+
+/**
+ * Test host component to simulate parent component.
+ */
+@Component({
+ selector: 'app-board-host-component',
+ template: '
'
+})
+class TestHostBoardComponent {
+
+ @ViewChild('contactsTabView') contactsTabView: ContactsTabViewComponent;
+
+ // input parameters
+ contactDetails = {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'stewart.abraham@test.ch',
+ 'familyName': 'Abraham',
+ 'givenName': 'Stewart',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch',
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://orcid.org/0000-0002-1825-0097'}
+ };
+}
+
+describe('ContactsTabViewComponent', () => {
+ let testHostComponent: TestHostBoardComponent;
+ let testHostFixture: ComponentFixture
;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestHostBoardComponent,
+ ContactsTabViewComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostBoardComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+});
diff --git a/src/app/project/board/contacts-tab-view/contacts-tab-view.component.ts b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.ts
new file mode 100644
index 0000000000..78b45cd77a
--- /dev/null
+++ b/src/app/project/board/contacts-tab-view/contacts-tab-view.component.ts
@@ -0,0 +1,26 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-contacts-tab-view',
+ templateUrl: './contacts-tab-view.component.html',
+ styleUrls: ['./contacts-tab-view.component.scss']
+})
+export class ContactsTabViewComponent implements OnInit {
+
+ // contact details
+ @Input() contactDetails: object;
+
+ ngOnInit(): void {
+ // reformat data
+ if (this.contactDetails['sameAs']) {
+ this.contactDetails['sameAs'] = this.contactDetails['sameAs']['value'];
+ }
+
+ if (this.contactDetails['organisation']) {
+ if (this.contactDetails['organisation']['url']) {
+ this.contactDetails['organisation']['url'] = this.contactDetails['organisation']['url']['value'];
+ }
+ }
+ }
+
+}
diff --git a/src/app/project/board/dataset-tab-view/dataset-tab-view.component.html b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.html
new file mode 100644
index 0000000000..00aedc1abb
--- /dev/null
+++ b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.html
@@ -0,0 +1,35 @@
+ 1">
+
Selected dataset: {{ metadata['title'] }}
+
Click on the radio button in the right side panel to change the dataset.
+
+
+
+
Default dataset is displayed, to change it click on the radio button in the right side panel.
+
+
+
+
+
+
+
+
+
+
+ {{ prop.key }}
+
+
+
+ {{ prop.value }}
+
+
-1;" class="property-value">
+
+
-1;">
+ {{ prop.value | date:'MMMM d, yyyy' }}
+
+
+
+
+
+
diff --git a/src/app/project/board/dataset-tab-view/dataset-tab-view.component.scss b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.scss
new file mode 100644
index 0000000000..e5780ee921
--- /dev/null
+++ b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.scss
@@ -0,0 +1,7 @@
+@import "../../../../assets/style/config";
+
+.note {
+ font-style: italic;
+ color: $warn;
+ padding-left: 0px;
+}
diff --git a/src/app/project/board/dataset-tab-view/dataset-tab-view.component.spec.ts b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.spec.ts
new file mode 100644
index 0000000000..e3ea70e03c
--- /dev/null
+++ b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.spec.ts
@@ -0,0 +1,133 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatasetTabViewComponent } from './dataset-tab-view.component';
+import { Component, ViewChild } from '@angular/core';
+
+
+/**
+ * Test host component to simulate parent component.
+ */
+@Component({
+ selector: 'app-board-host-component',
+ template: ''
+})
+class TestHostBoardComponent {
+
+ @ViewChild('datasetTabView') datasetTabView: DatasetTabViewComponent;
+
+ // metadata object
+ datasetMetadata = {
+ 'abstract': 'Dies ist ein Testprojekt.',
+ 'alternativeTitle': 'test',
+ 'conditionsOfAccess': 'Open Access',
+ 'dateCreated': '2001-09-26',
+ 'dateModified': '2020-04-26',
+ 'datePublished': '2002-09-24',
+ 'distribution': {'type': 'https://schema.org/DataDownload', 'value': 'https://test.dasch.swiss'},
+ 'documentation': 'Work in progress',
+ 'howToCite': 'Testprojekt (test), 2002, https://test.dasch.swiss',
+ 'language': ['EN', 'DE', 'FR'],
+ 'license': {'type': 'https://schema.org/URL', 'value': 'https://creativecommons.org/licenses/by/3.0'},
+ 'qualifiedAttribution': [{'role': 'contributor', 'agent': 'http://ns.dasch.swiss/test-berry'}, {'role': 'contributor', 'agent': 'http://ns.dasch.swiss/test-hart'}, {
+ 'role': 'editor',
+ 'agent': 'http://ns.dasch.swiss/test-abraham'
+ }, {'role': 'editor', 'agent': 'http://ns.dasch.swiss/test-coleman'}, {'role': 'editor', 'agent': 'http://ns.dasch.swiss/test-jones'}],
+ 'status': 'ongoing',
+ 'title': 'Testprojekt',
+ 'typeOfData': ['image', 'text'],
+ 'project': {
+ 'alternateName': 'test',
+ 'contactPoint': {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'stewart.abraham@test.ch',
+ 'familyName': 'Abraham',
+ 'givenName': 'Stewart',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch',
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://orcid.org/0000-0002-1825-0097'},
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ }
+ },
+ 'dataManagementPlan': {'url': {'type': 'https://schema.org/URL', 'value': 'https://snf.ch'}, 'isAvailable': false},
+ 'description': 'Dies ist ein Testprojekt...alle Properties wurden verwendet, um diese zu testen',
+ 'discipline': {'name': 'SKOS UNESCO Nomenclature', 'url': 'http://skos.um.es/unesco6/11'},
+ 'endDate': '2001-01-26',
+ 'funder': 'http://ns.dasch.swiss/test-funder',
+ 'grant': {
+ 'funder': [
+ {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ },
+ {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'lauren.berry@unibas.ch',
+ 'familyName': 'Berry',
+ 'givenName': 'Lauren',
+ 'jobTitle': 'Dr.',
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': 'info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': 'http://www.utoronto.ca/'
+ }
+ }], 'name': 'Test Grant Name', 'number': '0123456789', 'url': {'type': 'https://schema.org/URL', 'value': 'http://p3.snf.ch/testproject'}
+ },
+ 'keywords': ['science', 'mathematics', 'history of science', 'history of mathematics'],
+ 'name': 'Testprojektname (test)',
+ 'publication': 'testpublication',
+ 'shortcode': '0000',
+ 'spatialCoverage': [
+ {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/2017370/russian-federation.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2658434/switzerland.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3175395/italian-republic.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2921044/federal-republic-of-germany.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3017382/republic-of-france.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/6269131/england.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/6255148/europe.html'}}],
+ 'startDate': '2000-07-26',
+ 'temporalCoverage': {'name': 'Chronontology Dainst', 'url': 'http://chronontology.dainst.org/period/Ef9SyESSafJ1'},
+ 'url': {'type': 'https://schema.org/URL', 'value': 'https://test.dasch.swiss/'}
+ },
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://test.dasch.swiss/'}
+ };
+}
+
+describe('DatasetTabViewComponent', () => {
+ let testHostComponent: TestHostBoardComponent;
+ let testHostFixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestHostBoardComponent,
+ DatasetTabViewComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostBoardComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+});
diff --git a/src/app/project/board/dataset-tab-view/dataset-tab-view.component.ts b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.ts
new file mode 100644
index 0000000000..cbc12020d0
--- /dev/null
+++ b/src/app/project/board/dataset-tab-view/dataset-tab-view.component.ts
@@ -0,0 +1,25 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-dataset-tab-view',
+ templateUrl: './dataset-tab-view.component.html',
+ styleUrls: ['./dataset-tab-view.component.scss']
+})
+export class DatasetTabViewComponent {
+
+ // metadata input object
+ @Input() metadata: object;
+
+ // number of datasets available for this project
+ @Input() noOfDatasets: number;
+
+ // metadata keys that we do not want to display
+ excludeKeys = ['project', 'qualifiedAttribution'];
+
+ // metadata keys that require specific format to display
+ templateKeys = ['distribution', 'license', 'sameAs', 'dateCreated', 'dateModified', 'datePublished'];
+
+ // date keys from metadata object for formatting
+ dateKeys = ['dateCreated', 'dateModified', 'datePublished'];
+
+}
diff --git a/src/app/project/board/organisation-template/organisation-template.component.ts b/src/app/project/board/organisation-template/organisation-template.component.ts
new file mode 100644
index 0000000000..05d9cffe4a
--- /dev/null
+++ b/src/app/project/board/organisation-template/organisation-template.component.ts
@@ -0,0 +1,32 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-organisation-template',
+ template: `
+
+
+
+
+ {{ organisation['name'] }}
+
+
+
+
+
+
+
+
+ `,
+ styles: ['.metadata-title { font-size: 95%; }']
+})
+export class OrganisationTemplateComponent {
+
+ // input parameter
+ @Input() organisation: object;
+}
diff --git a/src/app/project/board/person-template/person-template.component.html b/src/app/project/board/person-template/person-template.component.html
new file mode 100644
index 0000000000..1c38f1342c
--- /dev/null
+++ b/src/app/project/board/person-template/person-template.component.html
@@ -0,0 +1,28 @@
+
+
{{ person['givenName'] }} {{person['familyName'] }}
+
+
+
Job title:
+ {{ person['jobTitle'] }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/project/board/person-template/person-template.component.scss b/src/app/project/board/person-template/person-template.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/app/project/board/person-template/person-template.component.spec.ts b/src/app/project/board/person-template/person-template.component.spec.ts
new file mode 100644
index 0000000000..ddfcdaaad7
--- /dev/null
+++ b/src/app/project/board/person-template/person-template.component.spec.ts
@@ -0,0 +1,52 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { PersonTemplateComponent } from './person-template.component';
+import { Component, ViewChild } from '@angular/core';
+
+
+/**
+ * Test host component to simulate parent component.
+ */
+@Component({
+ selector: 'app-contact-host-component',
+ template: ''
+})
+class TestHostContactComponent {
+
+ @ViewChild('personView') personView: PersonTemplateComponent;
+
+ // input parameters
+ contactDetails = {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'stewart.abraham@test.ch',
+ 'familyName': 'Abraham',
+ 'givenName': 'Stewart',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch',
+ 'sameAs': 'https://orcid.org/0000-0002-1825-0097'
+ };
+}
+
+describe('PersonTemplateComponent', () => {
+ let testHostComponent: TestHostContactComponent;
+ let testHostFixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestHostContactComponent,
+ PersonTemplateComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostContactComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+});
diff --git a/src/app/project/board/person-template/person-template.component.ts b/src/app/project/board/person-template/person-template.component.ts
new file mode 100644
index 0000000000..f250e5e372
--- /dev/null
+++ b/src/app/project/board/person-template/person-template.component.ts
@@ -0,0 +1,25 @@
+import {Component, Input} from '@angular/core';
+
+@Component({
+ selector: 'app-person-template',
+ templateUrl: './person-template.component.html',
+ styleUrls: ['./person-template.component.scss']
+})
+export class PersonTemplateComponent {
+
+ /*
+ Format for person object:
+ person = {
+ jobTitle: '',
+ givenName: '',
+ familyName: '',
+ email: ''.
+ sameAs: '',
+ address: '',
+ organisation: ''
+ }
+ */
+ // input parameter
+ @Input() person: object;
+
+}
diff --git a/src/app/project/board/project-tab-view/project-tab-view.component.html b/src/app/project/board/project-tab-view/project-tab-view.component.html
new file mode 100644
index 0000000000..1715b03af0
--- /dev/null
+++ b/src/app/project/board/project-tab-view/project-tab-view.component.html
@@ -0,0 +1,94 @@
+Metadata for selected project is listed below.
+
+
+
+
+
+
+
+ {{ prop.key }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ k }}
+
+
+
+
+
+
+
+
+
+
+
{{ metadata['grant']['name'] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ prop.value }}
+
+
-1;">
+ {{ prop.value | date:'MMMM d, yyyy' }}
+
+
+
+
+
+
+
diff --git a/src/app/project/board/project-tab-view/project-tab-view.component.scss b/src/app/project/board/project-tab-view/project-tab-view.component.scss
new file mode 100644
index 0000000000..74bc5dadf0
--- /dev/null
+++ b/src/app/project/board/project-tab-view/project-tab-view.component.scss
@@ -0,0 +1,17 @@
+.mat-icon-text {
+ display: flex;
+ align-items: center;
+
+ .mat-icon {
+ margin-right: 8px;
+ }
+}
+
+.funder-entry {
+ margin-bottom: 15px;
+ margin-left: 35px;
+}
+
+.remove-top-margin {
+ margin-top: 0px;
+}
diff --git a/src/app/project/board/project-tab-view/project-tab-view.component.spec.ts b/src/app/project/board/project-tab-view/project-tab-view.component.spec.ts
new file mode 100644
index 0000000000..0434d3504d
--- /dev/null
+++ b/src/app/project/board/project-tab-view/project-tab-view.component.spec.ts
@@ -0,0 +1,112 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { ProjectTabViewComponent } from './project-tab-view.component';
+import { Component, ViewChild } from '@angular/core';
+
+/**
+ * Test host component to simulate parent component.
+ */
+@Component({
+ selector: 'app-board-host-component',
+ template: ''
+})
+class TestHostBoardComponent {
+
+ @ViewChild('projectTabView') projectTabView: ProjectTabViewComponent;
+
+ // input parameters
+ projectMetadata = {
+ 'alternateName': 'test',
+ 'contactPoint': {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'stewart.abraham@test.ch',
+ 'familyName': 'Abraham',
+ 'givenName': 'Stewart',
+ 'jobTitle': 'Dr.',
+ 'memberOf': 'http://ns.dasch.swiss/test-dasch',
+ 'sameAs': {'type': 'https://schema.org/URL', 'value': 'https://orcid.org/0000-0002-1825-0097'},
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ }
+ },
+ 'dataManagementPlan': {'url': {'type': 'https://schema.org/URL', 'value': 'https://snf.ch'}, 'isAvailable': false},
+ 'description': 'Dies ist ein Testprojekt...alle Properties wurden verwendet, um diese zu testen',
+ 'discipline': {'name': 'SKOS UNESCO Nomenclature', 'url': 'http://skos.um.es/unesco6/11'},
+ 'endDate': '2001-01-26',
+ 'funder': 'http://ns.dasch.swiss/test-funder',
+ 'grant': {
+ 'funder': [
+ {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': '/info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': {'type': 'https://schema.org/URL', 'value': 'http://www.utoronto.ca/'}
+ },
+ {
+ 'address': {'addressLocality': 'Basel', 'postalCode': '4000', 'streetAddress': 'Teststrasse'},
+ 'email': 'lauren.berry@unibas.ch',
+ 'familyName': 'Berry',
+ 'givenName': 'Lauren',
+ 'jobTitle': 'Dr.',
+ 'organisation': {
+ 'address': {'addressLocality': 'Toronto', 'postalCode': '40000', 'streetAddress': 'University of Toronto Street'},
+ 'email': 'info@universityoftoronto.ca',
+ 'name': 'University of Toronto',
+ 'url': 'http://www.utoronto.ca/'
+ }
+ }], 'name': 'Test Grant Name', 'number': '0123456789', 'url': {'type': 'https://schema.org/URL', 'value': 'http://p3.snf.ch/testproject'}
+ },
+ 'keywords': ['science', 'mathematics', 'history of science', 'history of mathematics'],
+ 'name': 'Testprojektname (test)',
+ 'publication': 'testpublication',
+ 'shortcode': '0000',
+ 'spatialCoverage': [
+ {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/2017370/russian-federation.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2658434/switzerland.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3175395/italian-republic.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/2921044/federal-republic-of-germany.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/3017382/republic-of-france.html'}}, {
+ 'place': {
+ 'name': 'Geonames',
+ 'url': 'https://www.geonames.org/6269131/england.html'
+ }
+ }, {'place': {'name': 'Geonames', 'url': 'https://www.geonames.org/6255148/europe.html'}}],
+ 'startDate': '2000-07-26',
+ 'temporalCoverage': {'name': 'Chronontology Dainst', 'url': 'http://chronontology.dainst.org/period/Ef9SyESSafJ1'},
+ 'url': {'type': 'https://schema.org/URL', 'value': 'https://test.dasch.swiss/'}
+ };
+
+}
+
+describe('ProjectTabViewComponent', () => {
+ let testHostComponent: TestHostBoardComponent;
+ let testHostFixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestHostBoardComponent,
+ ProjectTabViewComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostBoardComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+});
diff --git a/src/app/project/board/project-tab-view/project-tab-view.component.ts b/src/app/project/board/project-tab-view/project-tab-view.component.ts
new file mode 100644
index 0000000000..874aeea674
--- /dev/null
+++ b/src/app/project/board/project-tab-view/project-tab-view.component.ts
@@ -0,0 +1,20 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-project-tab-view',
+ templateUrl: './project-tab-view.component.html',
+ styleUrls: ['./project-tab-view.component.scss']
+})
+export class ProjectTabViewComponent {
+
+ // metadata object
+ @Input() metadata: object;
+
+ // metadata keys that we do not want to display in template
+ excludeKeys = ['contactPoint'];
+
+ // list of date keys from metadata object
+ // used for formatting
+ dateKeys = ['startDate', 'endDate'];
+
+}
diff --git a/src/app/project/board/terms-tab-view/terms-tab-view.component.html b/src/app/project/board/terms-tab-view/terms-tab-view.component.html
new file mode 100644
index 0000000000..4079e2cdf5
--- /dev/null
+++ b/src/app/project/board/terms-tab-view/terms-tab-view.component.html
@@ -0,0 +1,15 @@
+Terms & Conditions
+
+
+
+
+ Conditions of access:
+ {{ conditions }}
+
+
+
+
diff --git a/src/app/project/board/terms-tab-view/terms-tab-view.component.scss b/src/app/project/board/terms-tab-view/terms-tab-view.component.scss
new file mode 100644
index 0000000000..149aa78f30
--- /dev/null
+++ b/src/app/project/board/terms-tab-view/terms-tab-view.component.scss
@@ -0,0 +1,14 @@
+.license-image {
+ max-width: 200px;
+ object-fit: contain;
+ margin: 24px 0px;
+ display: block;
+}
+
+.display-inline-block {
+ display: inline-block;
+}
+
+.add-left-margin {
+ margin-left: 8px;
+}
diff --git a/src/app/project/board/terms-tab-view/terms-tab-view.component.spec.ts b/src/app/project/board/terms-tab-view/terms-tab-view.component.spec.ts
new file mode 100644
index 0000000000..7783c273a5
--- /dev/null
+++ b/src/app/project/board/terms-tab-view/terms-tab-view.component.spec.ts
@@ -0,0 +1,45 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { TermsTabViewComponent } from './terms-tab-view.component';
+import { Component, ViewChild } from '@angular/core';
+
+/**
+ * Test host component to simulate parent component.
+ */
+@Component({
+ selector: 'app-board-host-component',
+ template: ''
+})
+class TestHostBoardComponent {
+
+ @ViewChild('termsTabView') termsTabView: TermsTabViewComponent;
+
+ // input parameters
+ conditionsOfAccess = 'Open Access';
+ license = {'type': 'https://schema.org/URL', 'value': 'https://creativecommons.org/licenses/by/3.0'};
+}
+
+describe('TermsTabViewComponent', () => {
+ let testHostComponent: TestHostBoardComponent;
+ let testHostFixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestHostBoardComponent,
+ TermsTabViewComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostBoardComponent);
+ testHostComponent = testHostFixture.componentInstance;
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ });
+});
+
diff --git a/src/app/project/board/terms-tab-view/terms-tab-view.component.ts b/src/app/project/board/terms-tab-view/terms-tab-view.component.ts
new file mode 100644
index 0000000000..cf9ea8661a
--- /dev/null
+++ b/src/app/project/board/terms-tab-view/terms-tab-view.component.ts
@@ -0,0 +1,16 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-terms-tab-view',
+ templateUrl: './terms-tab-view.component.html',
+ styleUrls: ['./terms-tab-view.component.scss']
+})
+export class TermsTabViewComponent {
+
+ // conditions input from parent component to display it in template
+ @Input() conditions: string;
+
+ // license from parent component to display it in template
+ @Input() license: object;
+
+}
diff --git a/src/assets/images/cc-license.png b/src/assets/images/cc-license.png
new file mode 100644
index 0000000000..5c71d21fff
Binary files /dev/null and b/src/assets/images/cc-license.png differ
diff --git a/src/assets/style/_config.scss b/src/assets/style/_config.scss
index 3cd5a4b4b9..29afb876ce 100644
--- a/src/assets/style/_config.scss
+++ b/src/assets/style/_config.scss
@@ -1,6 +1,6 @@
$primary_50: #eceff1;
$primary_100: #cfd8dc;
-$primary_200: #b0bec5;
+$primary_200: #d4d3d3;
$primary_300: #90a4ae;
$primary_400: #78909c;
$primary_500: #607d8b;