diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 8372844224..0000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,10 +0,0 @@
-# copied from @angular/material
-# Ignore miscellaneous folders
-.github/
-.idea/
-node_modules/
-dist/
-tmp/
-
-# Ignore certain project files
-docs/assets/js/
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 17e748d646..0000000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,335 +0,0 @@
-{
- "extends": "eslint:recommended",
- "parserOptions": {
- "ecmaVersion": 8
- },
- "rules": {
- "accessor-pairs": "error",
- "array-bracket-newline": "off",
- "array-bracket-spacing": [
- "error",
- "never"
- ],
- "array-callback-return": "error",
- "array-element-newline": "off",
- "arrow-body-style": "error",
- "arrow-parens": [
- "error",
- "as-needed"
- ],
- "arrow-spacing": "error",
- "block-scoped-var": "off",
- "block-spacing": "off",
- "brace-style": "off",
- "callback-return": "off",
- "camelcase": "off",
- "capitalized-comments": "off",
- "class-methods-use-this": "error",
- "comma-dangle": "off",
- "comma-spacing": "off",
- "comma-style": [
- "error",
- "last"
- ],
- "complexity": "off",
- "computed-property-spacing": "off",
- "consistent-return": "off",
- "consistent-this": "off",
- "curly": "off",
- "default-case": "off",
- "dot-location": "off",
- "dot-notation": "off",
- "eol-last": "off",
- "eqeqeq": "off",
- "for-direction": "error",
- "func-call-spacing": "off",
- "func-name-matching": "off",
- "func-names": "off",
- "func-style": "off",
- "generator-star-spacing": "error",
- "getter-return": "error",
- "global-require": "off",
- "guard-for-in": "off",
- "handle-callback-err": "error",
- "id-blacklist": "error",
- "id-length": "off",
- "id-match": "error",
- "indent": "off",
- "indent-legacy": "off",
- "init-declarations": "off",
- "jsx-quotes": "error",
- "key-spacing": "off",
- "keyword-spacing": [
- "error",
- {
- "before": true,
- "after": true
- }
- ],
- "line-comment-position": "off",
- "linebreak-style": "off",
- "lines-around-comment": "off",
- "lines-around-directive": "off",
- "max-depth": "error",
- "max-len": "off",
- "max-lines": "off",
- "max-nested-callbacks": "error",
- "max-params": "off",
- "max-statements": "off",
- "max-statements-per-line": "off",
- "multiline-ternary": "off",
- "new-parens": "error",
- "newline-after-var": "off",
- "newline-before-return": "off",
- "newline-per-chained-call": "off",
- "no-alert": "off",
- "no-array-constructor": "error",
- "no-await-in-loop": "error",
- "no-bitwise": "off",
- "no-buffer-constructor": "error",
- "no-caller": "error",
- "no-catch-shadow": "error",
- "no-confusing-arrow": "error",
- "no-console": [
- "off"
- ],
- "no-constant-condition": [
- "error",
- {
- "checkLoops": false
- }
- ],
- "no-continue": "off",
- "no-div-regex": "off",
- "no-duplicate-imports": "error",
- "no-else-return": "off",
- "no-empty-function": "off",
- "no-eq-null": "off",
- "no-eval": "error",
- "no-extend-native": "off",
- "no-extra-bind": "off",
- "no-extra-label": "error",
- "no-extra-parens": "off",
- "no-floating-decimal": "error",
- "no-implicit-coercion": [
- "error",
- {
- "boolean": false,
- "number": false,
- "string": false
- }
- ],
- "no-implicit-globals": "off",
- "no-implied-eval": "error",
- "no-inline-comments": "off",
- "no-inner-declarations": [
- "error",
- "functions"
- ],
- "no-invalid-this": "off",
- "no-iterator": "error",
- "no-label-var": "error",
- "no-labels": "error",
- "no-lone-blocks": "error",
- "no-lonely-if": "off",
- "no-loop-func": "error",
- "no-magic-numbers": "off",
- "no-mixed-operators": "off",
- "no-mixed-requires": "error",
- "no-multi-assign": "off",
- "no-multi-spaces": "off",
- "no-multi-str": "off",
- "no-multiple-empty-lines": "off",
- "no-native-reassign": "error",
- "no-negated-condition": "off",
- "no-negated-in-lhs": "error",
- "no-nested-ternary": "off",
- "no-new": "error",
- "no-new-func": "error",
- "no-new-object": "error",
- "no-new-require": "error",
- "no-new-wrappers": "error",
- "no-octal-escape": "error",
- "no-param-reassign": "off",
- "no-path-concat": "error",
- "no-plusplus": "off",
- "no-process-env": "off",
- "no-process-exit": "error",
- "no-proto": "error",
- "no-prototype-builtins": "off",
- "no-restricted-globals": "error",
- "no-restricted-imports": "error",
- "no-restricted-modules": "error",
- "no-restricted-properties": "error",
- "no-restricted-syntax": "error",
- "no-return-assign": "off",
- "no-return-await": "error",
- "no-script-url": "error",
- "no-self-compare": "error",
- "no-sequences": "off",
- "no-shadow": "off",
- "no-shadow-restricted-names": "error",
- "no-spaced-func": "off",
- "no-sync": "off",
- "no-tabs": "off",
- "no-template-curly-in-string": "error",
- "no-ternary": "off",
- "no-throw-literal": "off",
- "no-trailing-spaces": [
- "error"
- ],
- "no-undef-init": "error",
- "no-undefined": "off",
- "no-underscore-dangle": "off",
- "no-unmodified-loop-condition": "error",
- "no-unneeded-ternary": "off",
- "no-unused-expressions": "off",
- "no-use-before-define": "off",
- "no-useless-call": "error",
- "no-useless-computed-key": "error",
- "no-useless-concat": "off",
- "no-useless-constructor": "error",
- "no-useless-rename": "error",
- "no-useless-return": "error",
- "no-var": "off",
- "no-void": "off",
- "no-warning-comments": "off",
- "no-whitespace-before-property": "error",
- "no-with": "error",
- "nonblock-statement-body-position": [
- "error",
- "any"
- ],
- "object-curly-newline": "off",
- "object-curly-spacing": "off",
- "object-property-newline": "off",
- "object-shorthand": "off",
- "one-var": "off",
- "one-var-declaration-per-line": "off",
- "operator-assignment": "off",
- "operator-linebreak": "off",
- "padded-blocks": "off",
- "padding-line-between-statements": "error",
- "prefer-arrow-callback": "off",
- "prefer-const": "error",
- "prefer-destructuring": "off",
- "prefer-numeric-literals": "error",
- "prefer-promise-reject-errors": "error",
- "prefer-reflect": "off",
- "prefer-rest-params": "off",
- "prefer-spread": "off",
- "prefer-template": "off",
- "quote-props": "off",
- "quotes": "off",
- "radix": "off",
- "require-await": "error",
- "require-jsdoc": "off",
- "rest-spread-spacing": "error",
- "semi": "off",
- "semi-spacing": "off",
- "semi-style": "off",
- "sort-imports": "error",
- "sort-keys": "off",
- "sort-vars": "off",
- "space-before-blocks": "off",
- "space-before-function-paren": "off",
- "space-in-parens": [
- "error",
- "never"
- ],
- "space-infix-ops": "off",
- "space-unary-ops": "off",
- "spaced-comment": [
- "error",
- "always",
- {
- "exceptions": [
- "*"
- ]
- }
- ],
- "strict": "off",
- "switch-colon-spacing": "off",
- "symbol-description": "error",
- "template-curly-spacing": "error",
- "template-tag-spacing": "error",
- "unicode-bom": [
- "error",
- "never"
- ],
- "valid-jsdoc": "off",
- "vars-on-top": "off",
- "wrap-iife": "off",
- "wrap-regex": "off",
- "yield-star-spacing": "error",
- "yoda": "off",
- "no-unused-vars": "off",
- "no-cond-assign": "off",
- "no-unexpected-multiline": "off"
- },
- "env": {
- "node": true
- },
- "globals": {
- "angular": true,
- "moment": true
- },
- "overrides": [
- {
- "files": [
- "docs/app/js/**/*",
- "src/**/*"
- ],
- "parserOptions": {
- "ecmaVersion": 5
- },
- "env": {
- "browser": true
- },
- "rules": {
- "arrow-parens": "error",
- "global-require": "error",
- "no-console": [
- "error"
- ],
- "no-process-env": "error",
- "no-sync": "error"
- },
- "globals": {
- "angular": true,
- "CryptoJS": true,
- "hljs": true
- }
- },
- {
- "files": [
- "scripts/**/*"
- ],
- "rules": {
- "no-process-env": "off"
- }
- },
- {
- "files": [
- "**/*.spec.js"
- ],
- "env": {
- "jasmine": true
- },
- "rules": {
- "no-native-reassign": "off",
- "no-global-assign": "off"
- },
- "globals": {
- "module": true,
- "inject": true,
- "disableAnimations": true,
- "createMockStyleSheet": true,
- "$mdUtil": false,
- "$timeout": false,
- "$animate": false,
- "$material": false
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 5437945c29..0a5f5604f8 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -91,6 +91,7 @@ import { AddressTemplateComponent } from './project/board/address-template/addre
import { OrganisationTemplateComponent } from './project/board/organisation-template/organisation-template.component';
import { EditListItemComponent } from './project/list/list-item-form/edit-list-item/edit-list-item.component';
import { PropertyInfoComponent } from './project/ontology/property-info/property-info.component';
+import { ResourceClassInfoComponent } from './project/ontology/resource-class-info/resource-class-info.component';
// translate: AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
@@ -164,7 +165,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
AddressTemplateComponent,
OrganisationTemplateComponent,
EditListItemComponent,
- PropertyInfoComponent
+ PropertyInfoComponent,
+ ResourceClassInfoComponent
],
imports: [
AppRoutingModule,
diff --git a/src/app/project/ontology/default-data/default-properties.ts b/src/app/project/ontology/default-data/default-properties.ts
index ad81a63276..301ff1ba93 100644
--- a/src/app/project/ontology/default-data/default-properties.ts
+++ b/src/app/project/ontology/default-data/default-properties.ts
@@ -160,7 +160,7 @@ export class DefaultProperties {
// group: 'Link'
// },
{
- icon: 'http',
+ icon: 'language',
label: 'External URL',
subPropOf: Constants.HasValue,
objectType: Constants.UriValue,
diff --git a/src/app/project/ontology/default-data/default-resource-classes.ts b/src/app/project/ontology/default-data/default-resource-classes.ts
index 3963d9e078..704bc7e5c2 100644
--- a/src/app/project/ontology/default-data/default-resource-classes.ts
+++ b/src/app/project/ontology/default-data/default-resource-classes.ts
@@ -1,41 +1,153 @@
import { Constants } from '@dasch-swiss/dsp-js';
-export interface DefaultClass {
+export interface DefaultInfo {
iri: string;
label: string;
- icons?: string[];
+ icons?: string[]; // icons can be used to be selected in the resource class form
}
export class DefaultResourceClasses {
- public static data: DefaultClass[] = [
+ public static data: DefaultInfo[] = [
{
iri: Constants.Resource,
- label: 'Object without file representation (metadata only)'
+ label: 'Object without file representation (metadata only)',
+ icons: [
+ 'person',
+ 'person_outline',
+ 'group',
+ 'groups',
+ 'people_alt',
+ 'note',
+ 'notes',
+ 'text_snippet',
+ 'short_text',
+ 'comment',
+ 'event_note',
+ 'emoji_symbols',
+ 'calculate',
+ 'functions',
+ 'house',
+ 'location_city',
+ 'science',
+ 'school',
+ 'emoji_transportation',
+ 'local_bar',
+ 'fastfood',
+ 'restaurant',
+ 'collections',
+ 'portrait',
+ 'auto_stories',
+ 'book',
+ 'import_contacts',
+ 'menu_book',
+ 'commute',
+ 'map',
+ 'satellite',
+ 'public',
+ 'language',
+ 'devices',
+ 'devices_other',
+ 'important_devices',
+ 'source'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'StillImageRepresentation',
- label: 'Still Image'
+ label: 'Still Image',
+ icons: [
+ 'photo',
+ 'panorama',
+ 'photo_library',
+ 'camera_roll',
+ 'camera',
+ 'camera_alt',
+ 'camera_enhance',
+ 'portrait',
+ 'auto_stories',
+ 'book',
+ 'import_contacts',
+ 'menu_book',
+ 'note',
+ 'sticky_note_2',
+ 'account_balance',
+ 'museum',
+ 'theater_comedy',
+ 'landscape',
+ 'nature_people',
+ 'screenshot',
+ 'wallpaper'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'MovingImageRepresentation',
- label: 'Moving Image'
+ label: 'Moving Image',
+ icons: [
+ 'movie',
+ 'theaters',
+ 'slideshow',
+ 'live_tv',
+ 'animation',
+ 'music_video',
+ 'play_circle_filled',
+ 'play_circle_outline',
+ 'videocam',
+ 'video_library',
+ 'duo',
+ 'subtitles'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'AudioRepresentation',
- label: 'Audio'
+ label: 'Audio',
+ icons: [
+ 'audiotrack',
+ 'music_note',
+ 'graphiq_eq',
+ 'headphones',
+ 'volume_up',
+ 'mic',
+ 'equalizer',
+ 'speaker',
+ 'album',
+ 'voicemail',
+ 'music_video',
+ 'library_music',
+ 'radio'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'TextRepresentation',
- label: 'Text'
+ label: 'Text',
+ icons: [
+ 'rtt',
+ 'notes',
+ 'subject',
+ 'chrome_reader_mode'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'DocumentRepresentation',
- label: 'Document (Word, PDF, etc.)'
+ label: 'Document (Word, PDF, etc.)',
+ icons: [
+ 'description',
+ 'article',
+ 'text_snippet',
+ 'picture_as_pdf',
+ 'mark_as_unread',
+ 'history_edu',
+ 'mail',
+ 'drafts',
+ 'library_books'
+ ]
},
{
iri: Constants.KnoraApiV2 + Constants.HashDelimiter + 'DDDRepresentation',
- label: 'RTI Image'
+ label: 'RTI Image',
+ icons: [
+ 'view_in_ar',
+ 'layers'
+ ]
}
];
diff --git a/src/app/project/ontology/ontology-form/ontology-form.component.spec.ts b/src/app/project/ontology/ontology-form/ontology-form.component.spec.ts
index 21f901f728..37ea33a733 100644
--- a/src/app/project/ontology/ontology-form/ontology-form.component.spec.ts
+++ b/src/app/project/ontology/ontology-form/ontology-form.component.spec.ts
@@ -70,7 +70,6 @@ describe('OntologyFormComponent', () => {
label: null
});
-
fixture.detectChanges();
});
diff --git a/src/app/project/ontology/ontology-form/ontology-form.component.ts b/src/app/project/ontology/ontology-form/ontology-form.component.ts
index f01c2fd448..5a2266deb6 100644
--- a/src/app/project/ontology/ontology-form/ontology-form.component.ts
+++ b/src/app/project/ontology/ontology-form/ontology-form.component.ts
@@ -211,6 +211,4 @@ export class OntologyFormComponent implements OnInit {
}
-
-
}
diff --git a/src/app/project/ontology/ontology.component.html b/src/app/project/ontology/ontology.component.html
index 62042189e9..b1aa9a2b16 100644
--- a/src/app/project/ontology/ontology.component.html
+++ b/src/app/project/ontology/ontology.component.html
@@ -104,7 +104,7 @@
{{ontology?.label
@@ -129,9 +129,9 @@ {{ontology?.label
Add class
-
@@ -145,46 +145,12 @@ {{ontology?.label
-
diff --git a/src/app/project/ontology/ontology.component.scss b/src/app/project/ontology/ontology.component.scss
index b385f4c099..a3f7f20337 100644
--- a/src/app/project/ontology/ontology.component.scss
+++ b/src/app/project/ontology/ontology.component.scss
@@ -29,6 +29,12 @@ $width: 340px;
border: 1px dotted $primary_200;
position: relative;
margin: 0 auto 60px auto;
+ z-index: 0;
+
+ .ontology-editor-header {
+ z-index: 2;
+ top: 121px;
+ }
}
.ontology-viewer {
width: 98vw;
@@ -69,39 +75,6 @@ $width: 340px;
}
}
-.resource-class {
- min-height: 120px;
- height: auto;
- position: relative;
- @include mat-elevation-transition;
- @include mat-elevation(2);
- padding: 12px;
- margin: 6px;
- background-color: #fff;
-
- .resource-class-header {
- margin: -12px -12px 0 -12px;
- width: calc(100% + 24px);
- min-height: 48px !important;
- height: 48px;
- cursor: move;
- }
-
- .resource-class-properties {
- li.property-info {
- list-style-type: none;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- margin-left: -24px;
- list-style-position: inside;
- }
- }
-
- &:active {
- @include mat-elevation(8);
- }
-}
.ontology-editor-header {
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
position: sticky !important;
diff --git a/src/app/project/ontology/ontology.component.ts b/src/app/project/ontology/ontology.component.ts
index 6f325f6b0b..55b2e6502d 100644
--- a/src/app/project/ontology/ontology.component.ts
+++ b/src/app/project/ontology/ontology.component.ts
@@ -25,7 +25,7 @@ import { DspApiConnectionToken, Session, SessionService, SortingService } from '
import { CacheService } from 'src/app/main/cache/cache.service';
import { DialogComponent } from 'src/app/main/dialog/dialog.component';
import { ErrorHandlerService } from 'src/app/main/error/error-handler.service';
-import { DefaultClass, DefaultResourceClasses } from './default-data/default-resource-classes';
+import { DefaultInfo, DefaultResourceClasses } from './default-data/default-resource-classes';
import { ResourceClassFormService } from './resource-class-form/resource-class-form.service';
export interface OntologyInfo {
@@ -90,7 +90,7 @@ export class OntologyComponent implements OnInit {
/**
* list of all default resource classes (sub class of)
*/
- resourceClass: DefaultClass[] = DefaultResourceClasses.data;
+ defaultClasses: DefaultInfo[] = DefaultResourceClasses.data;
@ViewChild('ontologyEditor', { read: ViewContainerRef }) ontologyEditor: ViewContainerRef;
@@ -202,7 +202,7 @@ export class OntologyComponent implements OnInit {
this.ontologyIri = response.ontologies[0].id;
}
- response.ontologies.forEach((ontoMeta, index, array) => {
+ response.ontologies.forEach(ontoMeta => {
// set list of already existing ontology names
// it will be used in ontology form
// because ontology name has to be unique
@@ -212,6 +212,7 @@ export class OntologyComponent implements OnInit {
// get each ontology
this._dspApiConnection.v2.onto.getOntology(ontoMeta.id, true).subscribe(
(readOnto: ReadOntology) => {
+
this.ontologies.push(readOnto);
if (ontoMeta.id === this.ontologyIri) {
@@ -261,6 +262,7 @@ export class OntologyComponent implements OnInit {
this.loadOntology = false;
}
if (response.ontologies.length === this.ontologies.length) {
+ this.ontologies = this._sortingService.keySortByAlphabetical(this.ontologies, 'label');
this._cache.set('currentProjectOntologies', this.ontologies);
this.setCache();
}
@@ -357,7 +359,7 @@ export class OntologyComponent implements OnInit {
* @param mode
* @param resClassInfo (could be subClassOf (create mode) or resource class itself (edit mode))
*/
- openResourceClassForm(mode: 'createResourceClass' | 'editResourceClass', resClassInfo: DefaultClass): void {
+ openResourceClassForm(mode: 'createResourceClass' | 'editResourceClass', resClassInfo: DefaultInfo): void {
const dialogConfig: MatDialogConfig = {
disableClose: true,
@@ -380,7 +382,6 @@ export class OntologyComponent implements OnInit {
});
}
-
/**
* Updates cardinality
* @param subClassOf resource class
@@ -409,20 +410,20 @@ export class OntologyComponent implements OnInit {
}
/**
- * Delete either ontology or sourcetype
+ * Delete either ontology or resource class
*
- * @param id
* @param mode Can be 'Ontology' or 'ResourceClass'
+ * @param id
* @param title
*/
- delete(id: string, mode: 'Ontology' | 'ResourceClass', title: string) {
+ delete(mode: 'Ontology' | 'ResourceClass', info: DefaultInfo) {
const dialogConfig: MatDialogConfig = {
width: '560px',
maxHeight: '80vh',
position: {
top: '112px'
},
- data: { mode: 'delete' + mode, title: title }
+ data: { mode: 'delete' + mode, title: info.label }
};
const dialogRef = this._dialog.open(
@@ -462,7 +463,7 @@ export class OntologyComponent implements OnInit {
// delete resource class and refresh the view
this.loadOntology = true;
const resClass: DeleteResourceClass = new DeleteResourceClass();
- resClass.id = id;
+ resClass.id = info.iri;
resClass.lastModificationDate = this.ontology.lastModificationDate;
this._dspApiConnection.v2.onto.deleteResourceClass(resClass).subscribe(
(response: OntologyMetadata) => {
diff --git a/src/app/project/ontology/property-form/property-form.component.ts b/src/app/project/ontology/property-form/property-form.component.ts
index c00a32099d..49dbefa972 100644
--- a/src/app/project/ontology/property-form/property-form.component.ts
+++ b/src/app/project/ontology/property-form/property-form.component.ts
@@ -18,8 +18,7 @@ import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { CacheService } from 'src/app/main/cache/cache.service';
import { ErrorHandlerService } from 'src/app/main/error/error-handler.service';
-import { DefaultProperties, Category, PropertyType } from '../default-data/default-properties';
-
+import { Category, DefaultProperties, PropertyType } from '../default-data/default-properties';
// TODO: should be removed and replaced by AutocompleteItem from dsp-ui
/**
diff --git a/src/app/project/ontology/property-info/property-info.component.scss b/src/app/project/ontology/property-info/property-info.component.scss
index 160e1defdd..2edc608115 100644
--- a/src/app/project/ontology/property-info/property-info.component.scss
+++ b/src/app/project/ontology/property-info/property-info.component.scss
@@ -27,7 +27,6 @@
}
}
-
.mat-line.info {
font-size: small;
diff --git a/src/app/project/ontology/property-info/property-info.component.ts b/src/app/project/ontology/property-info/property-info.component.ts
index 3af7aac457..ee8ff5b447 100644
--- a/src/app/project/ontology/property-info/property-info.component.ts
+++ b/src/app/project/ontology/property-info/property-info.component.ts
@@ -152,9 +152,6 @@ export class PropertyInfoComponent implements OnInit, AfterContentInit {
}
}
);
-
-
-
}
}
diff --git a/src/app/project/ontology/resource-class-form/resource-class-form.component.ts b/src/app/project/ontology/resource-class-form/resource-class-form.component.ts
index 62308fcb2f..d02d80e011 100644
--- a/src/app/project/ontology/resource-class-form/resource-class-form.component.ts
+++ b/src/app/project/ontology/resource-class-form/resource-class-form.component.ts
@@ -145,7 +145,6 @@ export class ResourceClassFormComponent implements OnInit, OnDestroy, AfterViewC
selectedLanguage = 'en';
languages: StringLiteral[] = AppGlobal.languagesList;
-
constructor(
@Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection,
private _cache: CacheService,
@@ -426,7 +425,6 @@ export class ResourceClassFormComponent implements OnInit, OnDestroy, AfterViewC
}
);
-
} else {
// edit mode: res class cardinality
// submit properties and set cardinality
diff --git a/src/app/project/ontology/resource-class-form/resource-class-form.service.ts b/src/app/project/ontology/resource-class-form/resource-class-form.service.ts
index 0a60739ed5..0423b9aacd 100644
--- a/src/app/project/ontology/resource-class-form/resource-class-form.service.ts
+++ b/src/app/project/ontology/resource-class-form/resource-class-form.service.ts
@@ -178,7 +178,6 @@ export class ResourceClassFormService {
}
-
/**
* add new property line
*/
diff --git a/src/app/project/ontology/resource-class-info/resource-class-info.component.html b/src/app/project/ontology/resource-class-info/resource-class-info.component.html
new file mode 100644
index 0000000000..33943ae9be
--- /dev/null
+++ b/src/app/project/ontology/resource-class-info/resource-class-info.component.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/project/ontology/resource-class-info/resource-class-info.component.scss b/src/app/project/ontology/resource-class-info/resource-class-info.component.scss
new file mode 100644
index 0000000000..1478799fb2
--- /dev/null
+++ b/src/app/project/ontology/resource-class-info/resource-class-info.component.scss
@@ -0,0 +1,45 @@
+@import "~@angular/material/theming";
+@import "../../../../assets/style/config";
+
+.resource-class {
+ min-height: 120px;
+ height: auto;
+ position: relative;
+ @include mat-elevation-transition;
+ @include mat-elevation(2);
+ padding: 12px;
+ margin: 6px;
+ background-color: #fff;
+
+ .resource-class-header {
+ cursor: move;
+ margin-left: -12px;
+
+ .resource-class-header-action {
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
+
+ .resource-class-footer {
+ position: absolute;
+ bottom: 14px;
+ right: 14px;
+ }
+
+ .resource-class-properties {
+ li.property-info {
+ list-style-type: none;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-left: -24px;
+ list-style-position: inside;
+ }
+ }
+
+ &:active {
+ @include mat-elevation(8);
+ }
+}
diff --git a/src/app/project/ontology/resource-class-info/resource-class-info.component.spec.ts b/src/app/project/ontology/resource-class-info/resource-class-info.component.spec.ts
new file mode 100644
index 0000000000..b92524ea03
--- /dev/null
+++ b/src/app/project/ontology/resource-class-info/resource-class-info.component.spec.ts
@@ -0,0 +1,133 @@
+import { Component, DebugElement, OnInit, ViewChild } from '@angular/core';
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatCardModule } from '@angular/material/card';
+import { MatIconModule } from '@angular/material/icon';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { By } from '@angular/platform-browser';
+import { ClassDefinition, Constants, MockOntology, ReadOntology } from '@dasch-swiss/dsp-js';
+import { DspActionModule, SortingService } from '@dasch-swiss/dsp-ui';
+import { of } from 'rxjs';
+import { CacheService } from 'src/app/main/cache/cache.service';
+import { ResourceClassInfoComponent } from './resource-class-info.component';
+
+/**
+ * test host component to simulate parent component
+ * Property is of type simple text
+ */
+@Component({
+ template: `
`
+})
+class HostComponent implements OnInit {
+
+ @ViewChild('resClassInfo') resourceClassInfoComponent: ResourceClassInfoComponent;
+
+ // get ontology from DSP-JS-Lib test data
+ ontology: ReadOntology;
+
+ resourceClass: ClassDefinition;
+
+ constructor(
+ private _cache: CacheService,
+ private _sortingService: SortingService
+ ) {
+
+ }
+
+ ngOnInit() {
+
+ this._cache.get('currentOntology').subscribe(
+ (response: ReadOntology) => {
+ this.ontology = response;
+
+ const allOntoClasses = response.getAllClassDefinitions();
+ // reset the ontology classes
+ let classesToDisplay = [];
+
+ // display only the classes which are not a subClass of Standoff
+ allOntoClasses.forEach(resClass => {
+ if (resClass.subClassOf.length) {
+ const splittedSubClass = resClass.subClassOf[0].split('#');
+ if (!splittedSubClass[0].includes(Constants.StandoffOntology) && !splittedSubClass[1].includes('Standoff')) {
+ classesToDisplay.push(resClass);
+ }
+ }
+ });
+ classesToDisplay = this._sortingService.keySortByAlphabetical(classesToDisplay, 'label');
+ this.resourceClass = classesToDisplay[0];
+ }
+ );
+
+ }
+
+}
+
+describe('ResourceClassInfoComponent', () => {
+ let hostComponent: HostComponent;
+ let hostFixture: ComponentFixture
;
+
+ beforeEach(async(() => {
+ const dspConnSpy = {
+ v2: {
+ onto: jasmine.createSpyObj('onto', ['getOntology']),
+ }
+ };
+
+ const cacheServiceSpy = jasmine.createSpyObj('CacheService', ['get']);
+
+ TestBed.configureTestingModule({
+ declarations: [
+ HostComponent,
+ ResourceClassInfoComponent
+ ],
+ imports: [
+ DspActionModule,
+ MatCardModule,
+ MatIconModule,
+ MatMenuModule,
+ MatTooltipModule
+ ],
+ providers: [
+ {
+ provide: CacheService,
+ useValue: cacheServiceSpy
+ }
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ // mock cache service for currentOntology
+ const cacheSpy = TestBed.inject(CacheService);
+
+ (cacheSpy as jasmine.SpyObj).get.and.callFake(
+ () => {
+ const response: ReadOntology = MockOntology.mockReadOntology('http://0.0.0.0:3333/ontology/0001/anything/v2');
+ return of(response);
+ }
+ );
+
+ hostFixture = TestBed.createComponent(HostComponent);
+ hostComponent = hostFixture.componentInstance;
+ hostFixture.detectChanges();
+
+ expect(hostComponent).toBeTruthy();
+
+ });
+
+ it('expect title to be "Blue thing" and subclass of "Thing"', () => {
+ expect(hostComponent.resourceClassInfoComponent).toBeTruthy();
+ expect(hostComponent.resourceClassInfoComponent.resourceClass).toBeDefined();
+
+ const hostCompDe = hostFixture.debugElement;
+
+ const title: DebugElement = hostCompDe.query(By.css('mat-card-title'));
+
+ expect(title.nativeElement.innerText).toEqual('Blue thing');
+
+ const subtitle: DebugElement = hostCompDe.query(By.css('mat-card-subtitle'));
+
+ expect(subtitle.nativeElement.innerText).toEqual('Thing');
+ });
+});
diff --git a/src/app/project/ontology/resource-class-info/resource-class-info.component.ts b/src/app/project/ontology/resource-class-info/resource-class-info.component.ts
new file mode 100644
index 0000000000..4cdc2bf47e
--- /dev/null
+++ b/src/app/project/ontology/resource-class-info/resource-class-info.component.ts
@@ -0,0 +1,90 @@
+import { EventEmitter, Input, Output } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+import { ApiResponseError, ClassDefinition, ReadOntology } from '@dasch-swiss/dsp-js';
+import { CacheService } from 'src/app/main/cache/cache.service';
+import { ErrorHandlerService } from 'src/app/main/error/error-handler.service';
+import { DefaultInfo, DefaultResourceClasses } from '../default-data/default-resource-classes';
+
+@Component({
+ selector: 'app-resource-class-info',
+ templateUrl: './resource-class-info.component.html',
+ styleUrls: ['./resource-class-info.component.scss']
+})
+export class ResourceClassInfoComponent implements OnInit {
+
+ // open / close res class card
+ @Input() expanded = false;
+
+ @Input() resourceClass: ClassDefinition;
+
+ @Output() editResourceClass: EventEmitter = new EventEmitter();
+ @Output() updateCardinality: EventEmitter = new EventEmitter();
+ @Output() deleteResourceClass: EventEmitter = new EventEmitter();
+
+ ontology: ReadOntology;
+
+ subClassOfLabel = '';
+
+ // list of default classes
+ defaultClasses: DefaultInfo[] = DefaultResourceClasses.data;
+
+ constructor(
+ private _cache: CacheService,
+ private _errorHandler: ErrorHandlerService,
+ ) { }
+
+ ngOnInit(): void {
+ this._cache.get('currentOntology').subscribe(
+ (response: ReadOntology) => {
+ this.ontology = response;
+ this.translateSubClassOfIri(this.resourceClass.subClassOf);
+ },
+ (error: ApiResponseError) => {
+ this._errorHandler.showMessage(error);
+ }
+ );
+ }
+
+
+ /**
+ * translates iri from "sub class of" array
+ * - display label from default resource classes (as part of Knora System Project)
+ * - in case the class is a subclass of another class in the same ontology: display this class label
+ * - in none of those cases display the name from the class IRI
+ *
+ * @param classIris
+ */
+ translateSubClassOfIri(classIris: string[]) {
+
+ classIris.forEach((iri, index) => {
+ // get ontology iri from class iri
+ const splittedIri = iri.split('#');
+ const ontologyIri = splittedIri[0];
+ const className = splittedIri[1];
+
+ this.subClassOfLabel += (index > 0 ? ', ' : '');
+
+ // find default class for the current class iri
+ const defaultClass = this.defaultClasses.find(i => i.iri === iri);
+ if (defaultClass) {
+ this.subClassOfLabel += defaultClass.label;
+ } else if (this.ontology.id === ontologyIri) {
+ // the class is not defined in the default classes
+ // but defined in the current ontology
+ // get class label from there
+ this.subClassOfLabel += this.ontology.classes[iri].label;
+ } else {
+ // the ontology iri of the upper class couldn't be found
+ // display the class name
+ if (className) {
+ this.subClassOfLabel += className;
+ } else {
+ // iri is not kind of [ontologyIri]#[className]
+ this.subClassOfLabel += iri.split('/').filter(e => e).slice(-1);
+ }
+ }
+ });
+
+ }
+
+}