diff --git a/src/app/admin/admin-sidebar/admin-sidebar.component.scss b/src/app/admin/admin-sidebar/admin-sidebar.component.scss
index 5ed0142c7f9..dbf0faaac8d 100644
--- a/src/app/admin/admin-sidebar/admin-sidebar.component.scss
+++ b/src/app/admin/admin-sidebar/admin-sidebar.component.scss
@@ -1,3 +1,8 @@
+.clarin-logo {
+ height: var(--ds-login-logo-height);
+ width: var(--ds-login-logo-width);
+}
+
:host {
--ds-icon-z-index: 10;
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 1fb5798c068..598f775d9eb 100755
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -59,6 +59,12 @@ import { PageInternalServerErrorComponent } from './page-internal-server-error/p
import { DtqTestExampleComponent } from './dtq-test-example/dtq-test-example.component';
import { APP_CONFIG, AppConfig } from '../config/app-config.interface';
+import { DevTableComponent } from './dev-table/dev-table.component';
+import {MatTableModule} from '@angular/material/table';
+import {MatTreeModule} from '@angular/material/tree';
+import {MatIconModule} from '@angular/material/icon';
+import {MatButtonModule} from '@angular/material/button';
+import {ScrollingModule} from '@angular/cdk/scrolling';
export function getConfig() {
return environment;
@@ -187,7 +193,7 @@ const DECLARATIONS = [
IdleModalComponent,
ThemedPageInternalServerErrorComponent,
PageInternalServerErrorComponent,
- DtqTestExampleComponent
+ DtqTestExampleComponent,
];
const EXPORTS = [
@@ -195,8 +201,8 @@ const EXPORTS = [
@NgModule({
imports: [
- BrowserModule.withServerTransition({ appId: 'dspace-angular' }),
- ...IMPORTS
+ BrowserModule.withServerTransition({appId: 'dspace-angular'}),
+ ...IMPORTS,
],
providers: [
...PROVIDERS
@@ -204,10 +210,10 @@ const EXPORTS = [
declarations: [
...DECLARATIONS,
],
- exports: [
- ...EXPORTS,
- ...DECLARATIONS,
- ]
+ exports: [
+ ...EXPORTS,
+ ...DECLARATIONS,
+ ]
})
export class AppModule {
diff --git a/src/app/dev-table/dev-progress.json b/src/app/dev-table/dev-progress.json
new file mode 100644
index 00000000000..6b43903934c
--- /dev/null
+++ b/src/app/dev-table/dev-progress.json
@@ -0,0 +1,210 @@
+{
+ "Submission extensions": {
+ "percentage": "100",
+ "status": "done",
+ "Different fields for different types of submission": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Retrieve information on complex fields": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Hints, examples, suggestions": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Handling of the unknown date or date range of an item": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "OpenAIRE": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Sanity checks": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Admin only fields": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Upload CMDI file": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "User friendly settings": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Support files over 2GB": {
+ "percentage": 100,
+ "status": "done"
+ }
+ },
+ "Dissemination extensions": {
+ "status": "done",
+ "percentage": 100,
+ "Harvestable metadata via OAI-PMH": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "TombStone": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Item is hidden from search, harvestable only for oai": {
+ "percentage": 65,
+ "status": "done"
+ },
+ "Harvest CMDI metadata format": {
+ "percentage": 70,
+ "status": "done"
+ },
+ "Harvest OLAC metadata format": {
+ "percentage": 70,
+ "status": "done"
+ },
+ "Google scholar mapping metadata": {
+ "percentage": 70,
+ "status": "done"
+ }
+ },
+ "PIDs": {
+ "status": "done",
+ "percentage": 100,
+ "PIDs associat. to metadata records": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "HTTP-accept header for content negotiation": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Return directly cmdi": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Config handle prefix for communities": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Manage handle table": {
+ "percentage": 100,
+ "status": "done"
+ },
+ "Support DOIs": {
+ "percentage": 100,
+ "status": "done"
+ }
+ },
+ "Licensing Framework": {
+ "percentage": 60,
+ "status": "waiting",
+ "License administrator": {
+ "percentage": 0,
+ "status": "done"
+ },
+ "Choose license in submission process": {
+ "percentage": 0,
+ "status": "waiting"
+ },
+ "Item view - show item license": {
+ "percentage": 30,
+ "status": "waiting"
+ },
+ "Technical support for restricted items": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Attach/dettach license to/from item": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "New search filter option in search page - Licenses": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ },
+ "Statistics": {
+ "percentage": 0,
+ "status": "not-done",
+ "Bitstream downloads": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Stat based on Matomo Analytics": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ },
+ "Look&Feel": {
+ "percentage": 0,
+ "status": "not-done",
+ "Support Ref Table citations - CMDI, bib": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "After DB update, OAI gets updated": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Item view shows versioning": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Create new version of item": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ },
+ "Data downloads": {
+ "percentage": 0,
+ "status": "not-done",
+ "Resumable downloads, restrictive": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ },
+ "AAI using Shibboleth": {
+ "percentage": 0,
+ "status": "not-done",
+ "Federated SSO, authorization via Shibboleth": {
+ "percentage": 11,
+ "status": "not-done"
+ },
+ "Page with a list of released attributes (from IdP)": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Item deposit by registered users only": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Is it possible to hide item?": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Implement GÉANT.. - DP-CoC": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Login - select federated login": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ },
+ "Unicode Support": {
+ "percentage": 0,
+ "status": "not-done",
+ "DSpace should support UTF-8": {
+ "percentage": 0,
+ "status": "not-done"
+ },
+ "Multilingual Support": {
+ "percentage": 0,
+ "status": "not-done"
+ }
+ }
+}
diff --git a/src/app/dev-table/dev-table.component.html b/src/app/dev-table/dev-table.component.html
new file mode 100644
index 00000000000..1bfb5962007
--- /dev/null
+++ b/src/app/dev-table/dev-table.component.html
@@ -0,0 +1,47 @@
+
Modifications being done:
+
+
+
+
+
+
+
diff --git a/src/app/dev-table/dev-table.component.scss b/src/app/dev-table/dev-table.component.scss
new file mode 100644
index 00000000000..44e6f9210cc
--- /dev/null
+++ b/src/app/dev-table/dev-table.component.scss
@@ -0,0 +1,147 @@
+table {
+ border: 1px solid black;
+ width: 100%;
+}
+
+$clr: rgb(235 228 228 / 33%);
+$clr-unspecified: $clr;
+
+$clr-done: $clr;
+$clr-not-done: $clr;
+$clr-waiting: $clr;
+//$clr-done: rgba(0, 128, 55, 0.3);
+//$clr-not-done: rgba(255, 0, 0, 0.3);
+//$clr-waiting: rgba(243, 156, 18, 0.3);
+
+
+ul {
+ margin-bottom: 1px;
+}
+
+mat-tree {
+ padding: 1px;
+ //margin: 1px;
+ margin: auto;
+}
+
+.material-icons {
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+div.unspecified, li.mat-tree-node.unspecified {
+ padding: 1px 5px 1px 1px;
+ margin: 1px;
+ border-radius: 5px;
+ background: $clr-unspecified;
+ display:inline-flex;
+}
+
+div.done, li.mat-tree-node.done {
+ padding: 1px 5px 1px 1px;
+ display: inline-flex;
+ margin: 1px;
+ border-radius: 5px;
+ background: $clr-done;
+}
+
+div.waiting, li.mat-tree-node.waiting {
+ padding: 1px 5px 1px 1px;
+ margin: 1px;
+ background: $clr-waiting;
+ border-radius: 5px;
+ display: inline-flex;
+}
+
+div.not-done, li.mat-tree-node.not-done {
+ padding: 1px 5px 1px 1px;
+ margin: 1px;
+ background: $clr-not-done;
+ border-radius: 5px;
+ display: inline-flex;
+}
+mat-tree-node {
+ padding-right: 5px;
+ display: inline;
+}
+
+.done.mat-tree-node, .waiting.mat-tree-node, .not-done.mat-tree-node {
+ background-color: #f2f2f2 !important;
+}
+
+
+ul {
+ display: grid;
+}
+
+::-webkit-scrollbar {
+ width: 1px;
+ background: transparent;
+}
+
+#scroll-dev-table {
+
+ height: 45vh;
+ //height: 100%;
+ margin:auto;
+ width: 100%;
+ overflow: hidden;
+ //overflow-y: auto;
+ background: #f2f2f2;
+ border-radius: 5px;
+ padding: 1px;
+}
+
+.example-tree {
+ width: 100%;
+ height: 100%;
+ overflow-y: scroll;
+ padding-right: 50px;
+ box-sizing: content-box;
+}
+
+.example-tree-invisible {
+ display: none;
+}
+
+
+span.done {
+ color: rgb(0, 128, 55);
+}
+
+span.waiting {
+color: rgb(243, 156, 18);
+}
+
+span.not-done {
+color: rgb(255, 0, 0);
+}
+
+.example-tree ul,
+.example-tree li {
+ //margin-top: 0;
+ //margin-bottom: 0;
+ list-style-type: none;
+}
+
+.mat-icon-button {
+ background: #ffff0000;
+}
+
+
+
+tr {
+ border: 1px solid black;
+}
+
+td {
+ border: 1px solid black;
+}
+
+th {
+ border: 1px solid black;
+}
+
+button:focus {
+ outline: none;
+}
diff --git a/src/app/dev-table/dev-table.component.spec.ts b/src/app/dev-table/dev-table.component.spec.ts
new file mode 100644
index 00000000000..a7023f7463d
--- /dev/null
+++ b/src/app/dev-table/dev-table.component.spec.ts
@@ -0,0 +1,26 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+
+import { DevTableComponent } from './dev-table.component';
+
+describe('DevTableComponent', () => {
+ let component: DevTableComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ DevTableComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DevTableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/dev-table/dev-table.component.ts b/src/app/dev-table/dev-table.component.ts
new file mode 100644
index 00000000000..3f967c4c25a
--- /dev/null
+++ b/src/app/dev-table/dev-table.component.ts
@@ -0,0 +1,38 @@
+import {Component, Injectable, OnInit} from '@angular/core';
+import {NestedTreeControl} from '@angular/cdk/tree';
+import {MatTreeNestedDataSource} from '@angular/material/tree';
+import {BehaviorSubject} from 'rxjs';
+
+import doc from './dev-progress.json';
+import { FileNode } from './file-node';
+import { FileDatabase } from './file-database';
+
+
+
+@Component({
+ selector: 'ds-dev-table',
+ templateUrl: './dev-table.component.html',
+ styleUrls: ['./dev-table.component.scss'],
+ providers: [FileDatabase]
+})
+
+export class DevTableComponent implements OnInit {
+ nestedTreeControl: NestedTreeControl;
+ nestedDataSource: MatTreeNestedDataSource;
+
+ constructor(database: FileDatabase) {
+ this.nestedTreeControl = new NestedTreeControl(this._getChildren);
+ this.nestedDataSource = new MatTreeNestedDataSource();
+
+ database.dataChange.subscribe(data => this.nestedDataSource.data = data);
+ }
+
+ hasNestedChild = (_: number, nodeData: FileNode) => nodeData.children != null && nodeData.children.length > 0;
+
+ private _getChildren = (node: FileNode) => node.children;
+
+ ngOnInit(): void {
+ // nop
+ }
+
+}
diff --git a/src/app/dev-table/file-database.ts b/src/app/dev-table/file-database.ts
new file mode 100644
index 00000000000..ccf926503d6
--- /dev/null
+++ b/src/app/dev-table/file-database.ts
@@ -0,0 +1,84 @@
+/**
+ * Json node data with nested structure. Each node has a filename and a value or a list of children
+ */
+
+
+import doc from './dev-progress.json';
+import {Injectable} from '@angular/core';
+import {BehaviorSubject} from 'rxjs';
+import {FileNode} from './file-node';
+
+/**
+ * The Json tree data in string. The data could be parsed into Json object
+ */
+const TREE_DATA = JSON.stringify(doc);
+
+/**
+ * File database, it can build a tree structured Json object from string.
+ * Each node in Json object represents a file or a directory. For a file, it has filename and type.
+ * For a directory, it has filename and children (a list of files or directories).
+ * The input will be a json object string, and the output is a list of `FileNode` with nested
+ * structure.
+ */
+@Injectable()
+export class FileDatabase {
+ reserved = ['name', 'percentage', 'status'];
+ dataChange = new BehaviorSubject([]);
+
+ get data(): FileNode[] {
+ return this.dataChange.value;
+ }
+
+ constructor() {
+ this.initialize();
+ }
+
+ initialize() {
+ // Parse the string to json object.
+ const dataObject = JSON.parse(TREE_DATA);
+
+ // Build the tree nodes from Json object. The result is a list of `FileNode` with nested
+ // file node as children.
+ const data = this.buildFileTree(dataObject);
+
+ // Notify the change.
+ this.dataChange.next(data);
+ }
+
+
+ /**
+ * Build the file structure tree. The `value` is the Json object, or a sub-tree of a Json object.
+ * The return value is the list of `FileNode`.
+ */
+ buildFileTree(obj: { [key: string]: any }, level: number = 0): FileNode[] {
+ return Object.keys(obj).reduce((accumulator, key) => {
+ const value = obj[key];
+ const node = new FileNode();
+ node.taskName = key;
+ if (this.reserved.includes(key)) {
+ return accumulator;
+ }
+
+
+ if (value != null) {
+ if (typeof value === 'object') {
+ node.children = this.buildFileTree(value, level + 1);
+ if (value.name != null) {
+ node.taskName = value.name;
+ }
+ if (value.status != null) {
+ node.status = value.status;
+ }
+ if (value.percentage != null) {
+ node.donePercentage = value.percentage;
+ }
+ } else {
+ node.donePercentage = value;
+ }
+ }
+
+ return accumulator.concat(node);
+ }, []);
+ }
+}
+
diff --git a/src/app/dev-table/file-node.ts b/src/app/dev-table/file-node.ts
new file mode 100644
index 00000000000..553a12f00b4
--- /dev/null
+++ b/src/app/dev-table/file-node.ts
@@ -0,0 +1,14 @@
+export class FileNode {
+ children: FileNode[];
+ taskName: string;
+ donePercentage: any;
+ status: any = 'unspecified';
+
+ getParsedPercentage() {
+ let ret = '';
+ if (this.donePercentage != null) {
+ ret = ': ' + this.donePercentage + '%';
+ }
+ return ret;
+ }
+}
diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html
index 2c1a34ccaef..c3251b077fe 100644
--- a/src/app/footer/footer.component.html
+++ b/src/app/footer/footer.component.html
@@ -1,86 +1,171 @@
+
+