cleaned project

This commit is contained in:
Lucio Lelii 2023-03-01 12:06:56 +01:00
parent 795dfe8e63
commit 3b16b16e5c
31 changed files with 597 additions and 134 deletions

View File

@ -3,7 +3,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "io.ionic.starter"
applicationId "org.gcube.workspace"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1

View File

@ -12,6 +12,7 @@ dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-haptics')
implementation project(':capacitor-keyboard')
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar')
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.ionic.starter">
package="gcube.workspace.starter">
<application
android:allowBackup="true"

View File

@ -11,5 +11,8 @@ project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-keyboard'
project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android')
include ':capacitor-splash-screen'
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')
include ':capacitor-status-bar'
project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')

View File

@ -1,5 +1,5 @@
{
"appId": "gcube.workspace.starter",
"appId": "org.gcube.workspace",
"appName": "d4sworkspace",
"webDir": "www",
"bundledWebRuntime": false

View File

@ -14,6 +14,7 @@ def capacitor_pods
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins'
end

121
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "workspace",
"version": "0.0.1",
"dependencies": {
"-": "^0.0.1",
"@angular/common": "^15.0.0",
"@angular/core": "^15.0.0",
"@angular/forms": "^15.0.0",
@ -22,18 +23,20 @@
"@capacitor/haptics": "4.1.0",
"@capacitor/ios": "4.6.3",
"@capacitor/keyboard": "4.1.1",
"@capacitor/splash-screen": "^4.2.0",
"@capacitor/status-bar": "4.1.1",
"@fortawesome/angular-fontawesome": "^0.12.1",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-regular-svg-icons": "^6.3.0",
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@ionic/angular": "^6.5.4",
"angular-oauth2-oidc": "^15.0.1",
"cordova-plugin-file-opener2": "^4.0.0",
"cordova-plugin-preview-any-file": "^0.2.9",
"ionicons": "^6.1.3",
"material-icons": "^1.13.1",
"node-angular-http-client": "^1.1.7",
"rxjs": "~7.5.0",
"save": "^2.9.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
@ -69,6 +72,11 @@
"typescript": "~4.8.4"
}
},
"node_modules/-": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/-/-/--0.0.1.tgz",
"integrity": "sha512-3HfneK3DGAm05fpyj20sT3apkNcvPpCuccOThOPdzz8sY7GgQGe0l93XH9bt+YzibcTIgUAIMoyVJI740RtgyQ=="
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
@ -2565,6 +2573,14 @@
"@capacitor/core": "^4.0.0"
}
},
"node_modules/@capacitor/splash-screen": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-4.2.0.tgz",
"integrity": "sha512-XtGqM7J/yVEl/tKksKa7l1B6IDzhq4JJkadRuT8ohf/N7fD/1z45+id/4twM2Vnsxazh1fur2gq8rma7HaXMEw==",
"peerDependencies": {
"@capacitor/core": "^4.0.0"
}
},
"node_modules/@capacitor/status-bar": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-4.1.1.tgz",
@ -5453,6 +5469,18 @@
"ajv": "^8.8.2"
}
},
"node_modules/angular-oauth2-oidc": {
"version": "15.0.1",
"resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-15.0.1.tgz",
"integrity": "sha512-5gpqO9QL+qFqMItYFHe8F6H5nOIEaowcNUc9iTDs3P1bfVYnoKoVAaijob53PuPTF4YwzdfwKWZi4Mq6P7GENQ==",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": ">=14.0.0",
"@angular/core": ">=14.0.0"
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@ -5627,6 +5655,11 @@
"node": ">=8"
}
},
"node_modules/async": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
@ -6577,11 +6610,6 @@
}
}
},
"node_modules/cordova-plugin-preview-any-file": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/cordova-plugin-preview-any-file/-/cordova-plugin-preview-any-file-0.2.9.tgz",
"integrity": "sha512-OXgbmbfH+jeUme5q4NM7KZMra05E8G2ddolWrAQYt2cBAspikqSCg43a0TfaTQp/dBP94mzG/WA3ea+f7KSoKg=="
},
"node_modules/core-js-compat": {
"version": "3.28.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz",
@ -7101,6 +7129,11 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -8000,6 +8033,20 @@
"node": ">= 0.6"
}
},
"node_modules/event-stream": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
"integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==",
"dependencies": {
"duplexer": "^0.1.1",
"from": "^0.1.7",
"map-stream": "0.0.7",
"pause-stream": "^0.0.11",
"split": "^1.0.1",
"stream-combiner": "^0.2.2",
"through": "^2.3.8"
}
},
"node_modules/eventemitter-asyncresource": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz",
@ -8420,6 +8467,11 @@
"node": ">= 0.6"
}
},
"node_modules/from": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
"integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="
},
"node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@ -10588,6 +10640,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -10915,6 +10972,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/map-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
"integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ=="
},
"node_modules/material-icons": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/material-icons/-/material-icons-1.13.1.tgz",
@ -11026,6 +11088,11 @@
"node": ">=6"
}
},
"node_modules/mingo": {
"version": "6.2.7",
"resolved": "https://registry.npmjs.org/mingo/-/mingo-6.2.7.tgz",
"integrity": "sha512-r+yKmrZ+6SjwGxSot+/3S8sP9+LCxWNueR6xppMx7BzV60OegjbeklWAf/UveyQi8PDW8g/mwrQSHZVY/5jBJQ=="
},
"node_modules/mini-css-extract-plugin": {
"version": "2.7.2",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz",
@ -12303,6 +12370,14 @@
"node": ">=8"
}
},
"node_modules/pause-stream": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
"integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==",
"dependencies": {
"through": "~2.3"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@ -13328,6 +13403,17 @@
}
}
},
"node_modules/save": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/save/-/save-2.9.0.tgz",
"integrity": "sha512-eg8+g8CjvehE/2C6EbLdtK1pINVD27pcJLj4M9PjWWhoeha/y5bWf4dp/0RF+OzbKTcG1bae9qi3PAqiR8CJTg==",
"dependencies": {
"async": "^3.2.2",
"event-stream": "^4.0.1",
"lodash.assign": "^4.2.0",
"mingo": "^6.1.0"
}
},
"node_modules/sax": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz",
@ -13920,6 +14006,17 @@
"wbuf": "^1.7.3"
}
},
"node_modules/split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
"dependencies": {
"through": "2"
},
"engines": {
"node": "*"
}
},
"node_modules/split2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz",
@ -13968,6 +14065,15 @@
"node": ">= 0.4"
}
},
"node_modules/stream-combiner": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
"integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==",
"dependencies": {
"duplexer": "~0.1.1",
"through": "~2.3.4"
}
},
"node_modules/streamroller": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
@ -14386,8 +14492,7 @@
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
"dev": true
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/through2": {
"version": "4.0.2",

View File

@ -13,6 +13,7 @@
},
"private": true,
"dependencies": {
"-": "^0.0.1",
"@angular/common": "^15.0.0",
"@angular/core": "^15.0.0",
"@angular/forms": "^15.0.0",
@ -27,18 +28,20 @@
"@capacitor/haptics": "4.1.0",
"@capacitor/ios": "4.6.3",
"@capacitor/keyboard": "4.1.1",
"@capacitor/splash-screen": "^4.2.0",
"@capacitor/status-bar": "4.1.1",
"@fortawesome/angular-fontawesome": "^0.12.1",
"@fortawesome/fontawesome-svg-core": "^6.3.0",
"@fortawesome/free-regular-svg-icons": "^6.3.0",
"@fortawesome/free-solid-svg-icons": "^6.3.0",
"@ionic/angular": "^6.5.4",
"angular-oauth2-oidc": "^15.0.1",
"cordova-plugin-file-opener2": "^4.0.0",
"cordova-plugin-preview-any-file": "^0.2.9",
"ionicons": "^6.1.3",
"material-icons": "^1.13.1",
"node-angular-http-client": "^1.1.7",
"rxjs": "~7.5.0",
"save": "^2.9.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},

View File

@ -6,5 +6,6 @@ import { Component } from '@angular/core';
styleUrls: ['app.component.scss'],
})
export class AppComponent {
constructor() {}
constructor(){}
}

View File

@ -4,19 +4,19 @@ import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { OAuthModule } from 'angular-oauth2-oidc'
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule, HttpClientModule],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent]
})
export class AppModule {
constructor() {
}
}

View File

@ -0,0 +1,27 @@
<div *ngIf="items">
<ion-text color="medium" *ngIf="items.length == 0 && underUploadItem.length == 0" class="ion-padding ion-text-center">
<p>Empty folder</p>
</ion-text>
<ion-list>
<ion-item disabled *ngFor="let u of underUploadItem">
<mat-icon slot="start">description</mat-icon>
<ion-label text-wrap>{{ u }}</ion-label>
<ion-spinner name="lines-small"></ion-spinner>
</ion-item>
<ion-item *ngFor="let i of items">
<mat-icon slot="start">{{ i.getIconInfo() }}</mat-icon>
<ion-label text-wrap (click)="itemClicked(i)">
{{ i.getTitle() }}
<p *ngIf="i.item.shared; else notShared">{{ i.item.owner }}</p>
<ng-template #notShared>
<p>{{i.item.lastModificationTime | date: 'dd MMM yyyy'}} </p>
</ng-template>
</ion-label>
<mat-icon (click)="actionsSheetClicked(i)" slot="end">more_horiz</mat-icon>
</ion-item>
</ion-list>
</div>

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { ItemsGridComponent } from './items-grid.component';
describe('ItemsGridComponent', () => {
let component: ItemsGridComponent;
let fixture: ComponentFixture<ItemsGridComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ItemsGridComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(ItemsGridComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,33 @@
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { IonicModule } from '@ionic/angular';
import { WSItem } from '../model/ws-item';
@Component({
selector: 'app-items-grid',
templateUrl: './items-grid.component.html',
styleUrls: ['./items-grid.component.scss'],
imports: [CommonModule, IonicModule, MatIconModule]
})
export class ItemsGridComponent implements OnInit {
@Output() actionSheetClickedEvent = new EventEmitter<WSItem>();
@Output() itemClickedEvent = new EventEmitter<WSItem>();
@Input() items: WSItem[] | undefined;
@Input() underUploadItem: string[] = [];
constructor() { }
ngOnInit() {}
itemClicked(item: WSItem){
this.itemClickedEvent.emit(item);
}
actionsSheetClicked(item: WSItem){
this.actionSheetClickedEvent.emit(item);
}
}

View File

@ -0,0 +1,27 @@
<div *ngIf="items">
<ion-text color="medium" *ngIf="items.length == 0 && underUploadItem.length == 0" class="ion-padding ion-text-center">
<p>Empty folder</p>
</ion-text>
<ion-list>
<ion-item disabled *ngFor="let u of underUploadItem">
<mat-icon slot="start">description</mat-icon>
<ion-label text-wrap>{{ u }}</ion-label>
<ion-spinner name="lines-small"></ion-spinner>
</ion-item>
<ion-item *ngFor="let i of items">
<mat-icon slot="start">{{ i.getIconInfo() }}</mat-icon>
<ion-label text-wrap (click)="itemClicked(i)">
{{ i.getTitle() }}
<p *ngIf="i.item.shared; else notShared">{{ i.item.owner }}</p>
<ng-template #notShared>
<p>{{i.item.lastModificationTime | date: 'dd MMM yyyy'}} </p>
</ng-template>
</ion-label>
<mat-icon (click)="actionsSheetClicked(i)" slot="end">more_horiz</mat-icon>
</ion-item>
</ion-list>
</div>

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { ItemsListComponent } from './items-list.component';
describe('ItemsListComponent', () => {
let component: ItemsListComponent;
let fixture: ComponentFixture<ItemsListComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ItemsListComponent ],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(ItemsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,34 @@
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { IonicModule } from '@ionic/angular';
import { WSItem } from '../model/ws-item';
@Component({
standalone: true,
selector: 'app-items-list',
templateUrl: './items-list.component.html',
styleUrls: ['./items-list.component.scss'],
imports: [CommonModule, IonicModule, MatIconModule]
})
export class ItemsListComponent implements OnInit {
@Output() actionSheetClickedEvent = new EventEmitter<WSItem>();
@Output() itemClickedEvent = new EventEmitter<WSItem>();
@Input() items: WSItem[] | undefined;
@Input() underUploadItem: string[] = [];
constructor() { }
ngOnInit() {}
itemClicked(item: WSItem){
this.itemClickedEvent.emit(item);
}
actionsSheetClicked(item: WSItem){
this.actionSheetClickedEvent.emit(item);
}
}

View File

@ -6,22 +6,29 @@ import { RenameAction } from "./rename-item";
export class Actions {
private static actions: Action[] = [new MoveAction(), new CopyAction(),new RenameAction(), new DeleteAction()];
private static mv = new MoveAction();
private static cp = new CopyAction();
private static ren = new RenameAction();
private static del = new DeleteAction();
public static getActionsPerType(type: string): Action[] {
/*switch (type) {
switch (type) {
case 'SharedFolder':
break;
return [];
case 'FolderItem':
break;
return [this.mv, this.ren, this.del];
case 'TrashItem':
return [this.del];
case 'PDFFileItem':
break;
return [this.mv, this.cp, this.ren, this.del];
case 'ImageFile':
break;
return [this.mv, this.cp, this.ren, this.del];
case 'ExternalLink':
break;
return [this.mv, this.cp, this.ren, this.del];
default:
}*/
return Actions.actions;
return [this.mv, this.cp, this.ren, this.del];
}
}
}

49
src/app/model/sorting.ts Normal file
View File

@ -0,0 +1,49 @@
import { WSItem } from "./ws-item";
export enum SortName {
Name = "Name",
LastModificationTime = "Last Modified",
FolderFirst = "Folders First"
}
export enum SortType {
Asc = "arrow_upward",
Desc = "arrow_downward"
}
export class Sorting {
private static sortByNameASC = (item1: WSItem, item2: WSItem) => item1.getTitle().toLowerCase() > item2.getTitle().toLowerCase() ? -1 : 1;
private static sortByNameDESC = (item1: WSItem, item2: WSItem) => item1.getTitle().toLowerCase() > item2.getTitle().toLowerCase() ? 1 : -1;
private static sortByLastModificationASC = (item1: WSItem, item2: WSItem) => item1.item.lastModificationTime > item2.item.lastModificationTime ? 1 : -1;
private static sortByLastModificationDESC = (item1: WSItem, item2: WSItem) => item1.item.lastModificationTime > item2.item.lastModificationTime ? -1 : 1;
private static folderFirst(item1: WSItem, item2: WSItem) {
if (item1.isFolder() && !item2.isFolder()) return -1;
if (!item1.isFolder() && item2.isFolder()) return 1;
if (item1.item.title > item2.item.title) return 1;
if (item1.item.title < item2.item.title) return -1;
return 0;
}
static getSortFunction(name: SortName, type: SortType): (a: WSItem, b: WSItem) => number {
switch (name) {
case SortName.Name:
switch (type) {
case SortType.Asc: return this.sortByNameASC;
case SortType.Desc: return this.sortByNameDESC;
}
case SortName.LastModificationTime:
switch (type) {
case SortType.Asc: return this.sortByLastModificationASC;
case SortType.Desc: return this.sortByLastModificationDESC;
}
case SortName.FolderFirst:
return this.folderFirst;
}
}
}

View File

@ -22,6 +22,9 @@ export class WSItem {
case 'FolderItem':
retrievedName = "folder";
break;
case 'TrashItem':
retrievedName = "delete";
break;
case 'PDFFileItem':
retrievedName = "picture_as_pdf";
break;
@ -47,8 +50,15 @@ export class WSItem {
this.type === 'FolderItem';
}
getTitle(): string | undefined{
return this.item.vreFolder? this.item.displayName: this.item.title;
isFile(): boolean {
return this.type === 'PDFFileItem' ||
this.type === 'ImageFile' ||
this.type === 'GenericFileItem';
}
getTitle(): string{
var title = this.item.vreFolder? this.item.displayName: this.item.title;
return title? title : this.item.name;
}
}

View File

@ -1,42 +1,43 @@
<ion-content class="padding">
<ion-segment mode="ios" value="all">
<ion-segment-button (click)="filterBy('all')" value="all">
All
</ion-segment-button>
<ion-segment-button (click)="filterBy('folders')" value="FolderItem">
Folders
</ion-segment-button>
<ion-segment-button (click)="filterBy('shared')" value="SharedFolderItem">
Shared Folders
</ion-segment-button>
<ion-segment-button (click)="filterBy('files')" value="GenericFileItem">
Files
</ion-segment-button>
</ion-segment>
<ion-toolbar>
<ion-buttons slot="start" *ngIf="!root">
<ion-back-button text="" defaultHref="/">
<ion-buttons slot="start">
<ion-back-button [hidden]="root" text="" defaultHref="/">
<mat-icon>arrow_back_ios_new</mat-icon>
</ion-back-button>
</ion-buttons>
<ion-title> {{ !root && parentItem ? parentItem.getTitle() : tabName }} </ion-title>
<ion-title> {{ title }} </ion-title>
<ion-buttons *ngIf="parentItem" slot="end">
<ion-button (click)="createFolder()"><mat-icon>create_new_folder</mat-icon></ion-button>
<ion-button (click)="addFile()"><mat-icon>upload_file</mat-icon></ion-button>
</ion-buttons>
<ion-progress-bar *ngIf="!filteredItems" type="indeterminate"></ion-progress-bar>
</ion-toolbar>
<input hidden type="file" #filepicker (change)="fileSelected($event)" />
<ion-text color="medium" *ngIf="items.length == 0 && underUploadItem.length == 0" class="ion-padding ion-text-center">
<p>Empty folder</p>
</ion-text>
<ion-list>
<ion-item disabled *ngFor="let u of underUploadItem">
<mat-icon slot="start">description</mat-icon>
<ion-label text-wrap>{{ u }}</ion-label>
<ion-spinner name="lines-small"></ion-spinner>
</ion-item>
<ion-item *ngFor="let i of items">
<mat-icon slot="start">{{ i.getIconInfo() }}</mat-icon>
<ion-label text-wrap (click)="itemClicked(i)">
{{ i.getTitle() }}
<p *ngIf="i.item.shared; else notShared">{{ i.item.owner }}</p>
<ng-template #notShared>
<p>{{i.item.lastModificationTime | date: 'dd MMM yyyy'}} </p>
</ng-template>
</ion-label>
<mat-icon (click)="presentActionSheet(i)" slot="end">more_horiz</mat-icon>
</ion-item>
</ion-list>
<div>
<ion-buttons slot="start">
<ion-item>
<ion-select [interfaceOptions]="customSortAlertOptions" (ionChange)="changeSortName($event)" interface="alert" [value]="currentSortName">
<ion-select-option [value]="sortName.Name"> Name </ion-select-option>
<ion-select-option [value]="sortName.LastModificationTime"> Last Modified </ion-select-option>
</ion-select>
</ion-item>
<ion-button (click)="changeSortType()"><mat-icon>{{ currentSortType }}</mat-icon></ion-button>
</ion-buttons>
</div>
<input hidden type="file" #filepicker (change)="fileSelected($event)" />
<app-items-list [items]="filteredItems" [underUploadItem]="underUploadItem"
(actionSheetClickedEvent)="presentActionSheet($event)" (itemClickedEvent)="itemClicked($event)"></app-items-list>
</ion-content>

View File

@ -10,7 +10,8 @@ import { WSItem } from '../model/ws-item';
import { Action } from '../model/actions/action';
import { CreateFolderAction } from '../model/actions/create-folder';
import { Actions } from '../model/actions/actions';
import { BehaviorSubject } from 'rxjs';
import { ItemsListComponent } from '../items-list/items-list.component';
import { Sorting, SortName, SortType } from '../model/sorting';
@Component({
standalone: true,
@ -20,25 +21,44 @@ import { BehaviorSubject } from 'rxjs';
styleUrls: ['./show-folder.component.scss'],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [
CommonModule, IonicModule, MatIconModule
CommonModule, IonicModule, MatIconModule, ItemsListComponent
]
})
export class ShowFolderComponent implements OnInit {
@Output() folderClickedEvent = new EventEmitter<WSItem>();
@Input() items: WSItem[] = [];
filteredItems: WSItem[] | undefined;
_items: WSItem[] | undefined;
@Input() parentItem: WSItem | undefined;
currentSortName = SortName.Name;
currentSortType = SortType.Asc;
@Input() tabName: string = "";
@Input() set items(items: WSItem[] | undefined) {
this._items = items?.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
this.filteredItems = this._items;
}
@Input() parentItem: WSItem | undefined = undefined;
@Input() title: string | undefined;
@Input() root: boolean = false;
underUploadItem: string[] = [];
selectedSegment = "all";
public get sortName(): typeof SortName {
return SortName;
}
@ViewChild('filepicker') uploader!: ElementRef;
customSortAlertOptions = {
header: 'Sort by',
translucent: true,
};
constructor(
private actionSheetCtrl: ActionSheetController,
@ -46,23 +66,84 @@ export class ShowFolderComponent implements OnInit {
private alertCtrl: AlertController,
private modalCtrl: ModalController,
private toastController: ToastController
) { }
) {
}
ngOnInit(): void {
}
loadDocuments() {
this.filteredItems = undefined;
if (this.parentItem) {
this.storagehub.getChildren(this.parentItem.item.id).subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.items = tmpItems$;
const tmpFiltered$: WSItem[] = []
var segmentFilterFunction = this.getSegmentFilterFunction();
res.forEach(i => {
var localItem = new WSItem(i);
tmpItems$.push(localItem);
if (segmentFilterFunction(localItem))
tmpFiltered$.push(localItem);
});
this._items = tmpItems$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
this.filteredItems = tmpFiltered$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
})
}
}
getSegmentFilterFunction(): (value: WSItem) => unknown {
var filterItemFunction;
switch (this.selectedSegment) {
case "shared":
filterItemFunction = (value: WSItem) => value.type == "SharedFolder";
break;
case "folders":
filterItemFunction = (value: WSItem) => value.isFolder();
break;
case "files":
filterItemFunction = (value: WSItem) => value.isFile();
break;
default:
filterItemFunction = (value: WSItem) => true;
}
return filterItemFunction;
}
filterBy(value: string) {
if (value == this.selectedSegment) return;
this.filteredItems = undefined;
this.selectedSegment = value;
if (this.selectedSegment == "all")
this.filteredItems = this._items;
else {
const tmpFiltered$: WSItem[] = []
this._items?.filter(this.getSegmentFilterFunction()).forEach((i) => tmpFiltered$.push(i));
this.filteredItems = tmpFiltered$;
}
}
changeSortType() {
if (this.currentSortType == SortType.Asc)
this.currentSortType = SortType.Desc;
else this.currentSortType = SortType.Asc;
this.updateSort();
}
changeSortName($event: any) {
var sort : SortName = $event.target.value;
if (this.currentSortName != sort){
this.currentSortName = sort;
this.updateSort();
}
}
updateSort() {
this._items = this._items?.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
this.filteredItems = this.filteredItems?.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
}
itemClicked(item: WSItem) {
if (item.isFolder()) {
this.folderClickedEvent.emit(item);
@ -77,13 +158,13 @@ export class ShowFolderComponent implements OnInit {
const selected = $event.target.files[0];
if (selected && this.parentItem) {
this.underUploadItem= [selected.name];
this.underUploadItem = [selected.name];
const upload$ = this.storagehub.uploadFile(this.parentItem.item.id, selected.name, selected);
upload$.subscribe({
next: () => this.loadDocuments(),
next: () => this.loadDocuments(),
error: () => this.underUploadItem = [],
complete: () => this.underUploadItem = []
});
}

View File

@ -10,6 +10,7 @@ import { ItemWrapper } from './model/item-wrapper.model';
const token = "b7c80297-e4ed-42ab-ab42-fdc0b8b0eabf-98187548";
//const shURL ="https://workspace-repository.dev.d4science.org/storagehub/workspace"
const shURL = "/shub/storagehub/workspace";

View File

@ -13,7 +13,7 @@ const routes: Routes = [
loadChildren: () => import('../ws/ws.module').then(m => m.WsPageModule)
},
{
path: 'ws/:folderid',
path: 'ws/:folderId',
pathMatch: 'full',
loadChildren: () => import('../ws/ws.module').then(m => m.WsPageModule)
},
@ -22,7 +22,7 @@ const routes: Routes = [
loadChildren: () => import('../vres/vres.module').then(m => m.VresPageModule)
},
{
path: 'vres/:folderid',
path: 'vres/:folderId',
pathMatch: 'full',
loadChildren: () => import('../vres/vres.module').then(m => m.VresPageModule)
},

View File

@ -1,4 +1,4 @@
<ion-content [fullscreen]="true">
<show-folder tabName="Trash" [items]="getValues()" [root]="true"></show-folder>
<show-folder title="Trash" [root]="true" [items]="getValues()" ></show-folder>
</ion-content>

View File

@ -1,3 +1,3 @@
<ion-content [fullscreen]="true">
<show-folder [items]="getValues()" tabName="My VREs" [parentItem]="getCurrentItem()" (folderClickedEvent)="openFolder($event)" [root]="root"></show-folder>
<show-folder [root]="root" [title]="getTitle()" [parentItem]="getCurrentItem()" [items]="getValues()" (folderClickedEvent)="openFolder($event)"></show-folder>
</ion-content>

View File

@ -12,60 +12,78 @@ import { StoragehubService } from '../storagehub.service';
})
export class VresPage implements OnInit {
values: WSItem[] = [];
values: WSItem[] | undefined;
item: WSItem | undefined;
folderid: string | undefined;
root: boolean = false;
private static cashItems: WSItem[] = [];
constructor(private storagehub: StoragehubService,
private router: Router,
private route: ActivatedRoute) { }
ngOnInit() {
this.folderid = this.route.snapshot.paramMap.get('folderid') || undefined;
this.root = !this.folderid;
if (!this.folderid)
this.storagehub.getVres().subscribe(
(res) => {
const tmpItems$ : WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
);
else
this.storagehub.getItem(this.folderid).subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res);
}
);
var folderId: string | undefined = this.route.snapshot.paramMap.get('folderId') || undefined;
var tmpItem: WSItem | undefined = undefined;
if (folderId)
tmpItem = VresPage.cashItems.find((value) => value.item.id === folderId);
this.root = !folderId;
if (!tmpItem) {
if (!folderId)
this.storagehub.getVres().subscribe(
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
);
else //folder is not cached
this.storagehub.getItem(folderId).subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
} else {
this.item = tmpItem;
this.onSuccess(tmpItem.item);
}
}
private onSuccess(item: Item) {
this.storagehub.getChildren(item.id, false).subscribe(
(res) => {
const tmpItems$ : WSItem[] = []
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
)
}
public getValues(): WSItem[] {
public getValues(): WSItem[] | undefined {
return this.values;
}
openFolder(item: WSItem) {
if (this.values)
VresPage.cashItems = this.values;
this.router.navigateByUrl(`tabs/vres/${item.item.id}`);
}
public getCurrentItem(): WSItem | undefined{
public getCurrentItem(): WSItem | undefined {
return this.item;
}
getTitle() {
return this.root ? "My VREs" : this.item?.getTitle()
}
}

View File

@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { IonicModule, LoadingController, ModalController, ToastController } from '@ionic/angular';
import { Sorting, SortName, SortType } from '../model/sorting';
import { WSItem } from '../model/ws-item';
import { StoragehubService } from '../storagehub.service';
@ -44,7 +45,7 @@ export class WsViewerComponent implements OnInit {
(res) => {
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.items = tmpItems$.sort(this.sort);
this.items = tmpItems$.sort(Sorting.getSortFunction(SortName.FolderFirst, SortType.Asc));
})
} else
this.storagehub.getWsRoot().subscribe(
@ -99,11 +100,5 @@ export class WsViewerComponent implements OnInit {
return this.modalCtrl.dismiss(null, 'confirm');
}
sort(item1: WSItem, item2: WSItem) {
if (item1.isFolder() && !item2.isFolder()) return -1;
if (!item1.isFolder() && item2.isFolder()) return 1;
if (item1.item.title > item2.item.title) return 1;
if (item1.item.title < item2.item.title) return -1;
return 0;
}
}

View File

@ -1,5 +1,5 @@
<ion-content [fullscreen]="true">
<show-folder tabName="My Workspace" [items]="getValues()" [parentItem]="getCurrentItem()" (folderClickedEvent)="openFolder($event)" [root]="root"></show-folder>
<show-folder [title]="getTitle()" [root]="root" [parentItem]="getCurrentItem()" [items]="getValues()" (folderClickedEvent)="openFolder($event)"></show-folder>
</ion-content>

View File

@ -5,6 +5,7 @@ import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
import { StoragehubService } from '../storagehub.service';
import { WSItem } from '../model/ws-item';
import { Item } from '../model/item.model';
import { concatMap, from } from 'rxjs';
@Component({
selector: 'app-ws',
@ -14,57 +15,74 @@ import { Item } from '../model/item.model';
})
export class WsPage implements OnInit {
values: WSItem[] = [];
values: WSItem[] | undefined = undefined;
folderid: string | undefined;
item : WSItem | undefined ;
item: WSItem | undefined;
root: boolean = false;
private static cashItems: WSItem[] = [];
constructor(private storagehub: StoragehubService,
private router: Router,
private route: ActivatedRoute) { }
ngOnInit() {
this.folderid = this.route.snapshot.paramMap.get('folderid') || undefined;
this.root = !this.folderid;
if (!this.folderid)
this.storagehub.getWsRoot().subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
else
this.storagehub.getItem(this.folderid).subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res);
}
);
var folderId: string | undefined = this.route.snapshot.paramMap.get('folderId') || undefined;
var tmpItem: WSItem | undefined = undefined;
if (folderId)
tmpItem = WsPage.cashItems.find((value) => value.item.id === folderId);
this.root = !folderId;
if (!tmpItem) {
if (!folderId)
this.storagehub.getWsRoot().subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
else //folder is not cached
this.storagehub.getItem(folderId).subscribe(
(res) => {
this.item = new WSItem(res);
this.onSuccess(res)
}
);
} else {
this.item = tmpItem;
this.onSuccess(tmpItem.item);
}
}
private onSuccess(item: Item) {
this.storagehub.getChildren(item.id, false).subscribe(
(res) => {
const tmpItems$ : WSItem[] = []
const tmpItems$: WSItem[] = []
res.forEach(i => tmpItems$.push(new WSItem(i)));
this.values = tmpItems$;
}
)
}
public getValues(): WSItem[] {
return this.values;
public getValues(): WSItem[] | undefined {
return this.values;
}
openFolder(item: WSItem) {
if (this.values)
WsPage.cashItems = this.values;
this.router.navigateByUrl(`tabs/ws/${item.item.id}`);
}
public getCurrentItem() : WSItem | undefined{
return this.item;
public getCurrentItem(): WSItem | undefined {
return this.item;
}
getTitle() {
return this.root ? "My Workspace" : this.item?.getTitle()
}
}