open file added
This commit is contained in:
parent
74e2cb68e7
commit
c1f6010aa5
|
@ -10,6 +10,7 @@ android {
|
|||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-filesystem')
|
||||
implementation project(':capacitor-haptics')
|
||||
implementation project(':capacitor-keyboard')
|
||||
implementation project(':capacitor-splash-screen')
|
||||
|
|
|
@ -39,4 +39,6 @@
|
|||
<!-- Permissions -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
</manifest>
|
||||
|
|
|
@ -5,6 +5,9 @@ project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/
|
|||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
|
||||
|
||||
include ':capacitor-filesystem'
|
||||
project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android')
|
||||
|
||||
include ':capacitor-haptics'
|
||||
project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android')
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationRule</key>
|
||||
|
|
|
@ -12,6 +12,7 @@ def capacitor_pods
|
|||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
|
||||
pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem'
|
||||
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
|
||||
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
|
||||
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
"@capacitor/android": "4.6.3",
|
||||
"@capacitor/app": "^4.1.1",
|
||||
"@capacitor/core": "4.6.3",
|
||||
"@capacitor/filesystem": "^4.1.4",
|
||||
"@capacitor/haptics": "4.1.0",
|
||||
"@capacitor/ios": "4.6.3",
|
||||
"@capacitor/keyboard": "4.1.1",
|
||||
|
@ -33,6 +34,7 @@
|
|||
"@ionic/angular": "^6.5.4",
|
||||
"angular-oauth2-oidc": "^15.0.1",
|
||||
"capacitor-share-extension": "^2.0.0",
|
||||
"cordova-plugin-file-opener2": "^4.0.0",
|
||||
"cordova-plugin-inappbrowser": "^5.0.0",
|
||||
"ionicons": "^6.1.3",
|
||||
"keycloak-angular": "^13.0.0",
|
||||
|
@ -2565,6 +2567,14 @@
|
|||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/filesystem": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/filesystem/-/filesystem-4.1.4.tgz",
|
||||
"integrity": "sha512-ivko1RNK4hq63xhMacq8D6D97N5/SAafTsrmY/pghYrG6Cl2SEY0+IgRu7V9/VWeN3FSplyUPucjUTAFQxXN5g==",
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/haptics": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-4.1.0.tgz",
|
||||
|
@ -6612,6 +6622,24 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cordova-plugin-file-opener2": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-plugin-file-opener2/-/cordova-plugin-file-opener2-4.0.0.tgz",
|
||||
"integrity": "sha512-+O+MMldI2k5Kjoa62KXYxnZQIGE4k5VfoCmmOUmaV5XM6U6euiiKMfCkuMrOrdAFb1C5Jsx+SuBHbWx1NEB5lw==",
|
||||
"engines": {
|
||||
"cordovaDependencies": {
|
||||
"2.0.0": {
|
||||
"cordova": ">=6.0.0"
|
||||
},
|
||||
"3.0.0": {
|
||||
"cordova": ">=7.0.0"
|
||||
},
|
||||
"4.0.0": {
|
||||
"cordova-android": ">=10.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/cordova-plugin-inappbrowser": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-plugin-inappbrowser/-/cordova-plugin-inappbrowser-5.0.0.tgz",
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"@capacitor/android": "4.6.3",
|
||||
"@capacitor/app": "^4.1.1",
|
||||
"@capacitor/core": "4.6.3",
|
||||
"@capacitor/filesystem": "^4.1.4",
|
||||
"@capacitor/haptics": "4.1.0",
|
||||
"@capacitor/ios": "4.6.3",
|
||||
"@capacitor/keyboard": "4.1.1",
|
||||
|
@ -38,6 +39,7 @@
|
|||
"@ionic/angular": "^6.5.4",
|
||||
"angular-oauth2-oidc": "^15.0.1",
|
||||
"capacitor-share-extension": "^2.0.0",
|
||||
"cordova-plugin-file-opener2": "^4.0.0",
|
||||
"cordova-plugin-inappbrowser": "^5.0.0",
|
||||
"ionicons": "^6.1.3",
|
||||
"keycloak-angular": "^13.0.0",
|
||||
|
|
|
@ -11,13 +11,14 @@ import { D4sAuthService } from './d4sauth.service';
|
|||
import { D4sIntentService } from './d4s-intent.service';
|
||||
import {initializeIntent} from './_helper/intent-init.factory'
|
||||
import { StoragehubService } from './storagehub.service';
|
||||
import { EventService } from './event.service';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule, HttpClientModule, KeycloakAngularModule],
|
||||
|
||||
providers: [
|
||||
D4sAuthService, ModalController, StoragehubService, ToastController,
|
||||
D4sAuthService, ModalController, StoragehubService, ToastController, EventService,
|
||||
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
|
|
|
@ -63,12 +63,30 @@ export class D4sAuthService {
|
|||
mustUpdate = true;
|
||||
console.log("token refreshed");
|
||||
}
|
||||
|
||||
if (this.uma && this.isExpired(35)){
|
||||
console.log("uma expires in 35, must update")
|
||||
mustUpdate = true;
|
||||
}
|
||||
|
||||
if (mustUpdate || !this.uma)
|
||||
this.uma = await this.entitlement(this.audience);
|
||||
|
||||
return "Bearer " + this.uma.access_token;
|
||||
}
|
||||
|
||||
isExpired(minValidityInSeconds : number ) {
|
||||
if (!this.uma) return false;
|
||||
const expires: number = this.parseJwt(this.uma.access_token).exp;
|
||||
|
||||
const time: number = Date.now()/1000;
|
||||
|
||||
console.log(`exiperes in ${expires} and now is ${time}`);
|
||||
|
||||
return time+minValidityInSeconds > expires;
|
||||
|
||||
}
|
||||
|
||||
entitlement(resourceServerId: any): Promise<UmaToken> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const keycloak = this.keycloak.getKeycloakInstance();
|
||||
|
|
|
@ -19,7 +19,7 @@ export class CopyAction extends Action {
|
|||
onSelected: (destinationItem: WSItem) => {
|
||||
this.actionHandler({ item: item, destinationItem: destinationItem }, storagehub).then( (obs) => obs.subscribe(
|
||||
() => {
|
||||
reload();
|
||||
reload(destinationItem.item.id)
|
||||
notify(`${item.getTitle()} copied`);
|
||||
}
|
||||
))
|
||||
|
|
|
@ -27,7 +27,7 @@ export class CreateFolderAction extends Action {
|
|||
text: 'Create',
|
||||
handler: (data) => {
|
||||
this.actionHandler({ wsitem: item, name: data.name }, storagehub).then((obs) => obs.subscribe(
|
||||
() => reload()
|
||||
() => reload(item.item.id)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export class DeleteAction extends Action {
|
|||
text: 'Yes',
|
||||
handler: () => {
|
||||
this.actionHandler(item, storagehub).then((obs) => obs.subscribe(
|
||||
() => reload()
|
||||
() => reload(item.item.parentId)
|
||||
));
|
||||
}
|
||||
}]
|
||||
|
|
|
@ -18,7 +18,7 @@ export class MoveAction extends Action {
|
|||
onSelected: (destinationItem:WSItem) =>{
|
||||
this.actionHandler({item: item, destinationItem: destinationItem}, storagehub).then( (obs) => obs.subscribe(
|
||||
() => {
|
||||
reload();
|
||||
reload(destinationItem.item.id);
|
||||
notify(`${item.getTitle()} moved`);
|
||||
}
|
||||
))
|
||||
|
|
|
@ -27,7 +27,7 @@ export class RenameAction extends Action {
|
|||
text: 'Rename',
|
||||
handler: (data) => {
|
||||
this.actionHandler({item: item, newName: data.name}, storagehub).then( (obs) => obs.subscribe(
|
||||
() => reload()
|
||||
() => reload(item.item.parentId)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,6 @@
|
|||
</ion-buttons>
|
||||
</div>
|
||||
<input hidden type="file" #filepicker (change)="fileSelected($event)" />
|
||||
<app-items-list [items]="filteredItems" [underUploadItem]="underUploadItem"
|
||||
<app-items-list [items]="filteredItems" [underUploadItem]="underUpload"
|
||||
(actionSheetClickedEvent)="presentActionSheet($event)" (itemClickedEvent)="itemClicked($event)"></app-items-list>
|
||||
</ion-content>
|
|
@ -12,11 +12,14 @@ import { CreateFolderAction } from '../model/actions/create-folder';
|
|||
import { Actions } from '../model/actions/actions';
|
||||
import { ItemsListComponent } from '../items-list/items-list.component';
|
||||
import { Sorting, SortName, SortType } from '../model/sorting';
|
||||
import { UploaderInfoService } from '../uploader-info.service';
|
||||
import { EventService } from '../event.service';
|
||||
import { OpenFile } from '../model/actions/open-file';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'show-folder',
|
||||
providers: [FileOpener, StoragehubService],
|
||||
providers: [FileOpener, StoragehubService, UploaderInfoService],
|
||||
templateUrl: './show-folder.component.html',
|
||||
styleUrls: ['./show-folder.component.scss'],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
|
@ -45,14 +48,14 @@ export class ShowFolderComponent implements OnInit {
|
|||
|
||||
@Input() root: boolean = false;
|
||||
|
||||
underUploadItem: string[] = [];
|
||||
|
||||
selectedSegment = "all";
|
||||
|
||||
public get sortName(): typeof SortName {
|
||||
return SortName;
|
||||
}
|
||||
|
||||
underUpload: string[];
|
||||
|
||||
@ViewChild('filepicker') uploader!: ElementRef;
|
||||
|
||||
customSortAlertOptions = {
|
||||
|
@ -65,18 +68,31 @@ export class ShowFolderComponent implements OnInit {
|
|||
private storagehub: StoragehubService,
|
||||
private alertCtrl: AlertController,
|
||||
private modalCtrl: ModalController,
|
||||
private toastController: ToastController
|
||||
private toastController: ToastController,
|
||||
private uploaderInfo: UploaderInfoService,
|
||||
private event: EventService,
|
||||
private fileOpener: FileOpener
|
||||
) {
|
||||
this.underUpload = this.getUnderUploadItems();
|
||||
}
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.event.ReloadEvent.subscribe((val) => {
|
||||
console.log(`event received with value ${val} in item ${this.parentItem?.item.id}`);
|
||||
if (val === this.parentItem?.item.id)
|
||||
this.loadDocuments();
|
||||
});
|
||||
}
|
||||
|
||||
getUnderUploadItems(): string[] {
|
||||
const parentId = this.parentItem?.item.id;
|
||||
return parentId ? this.uploaderInfo.getUnderUpload(parentId) : [];
|
||||
}
|
||||
|
||||
loadDocuments() {
|
||||
this.filteredItems = undefined;
|
||||
if (this.parentItem) {
|
||||
this.storagehub.getChildren(this.parentItem.item.id).then( (obs) => obs.subscribe(
|
||||
this.storagehub.getChildren(this.parentItem.item.id).then((obs) => obs.subscribe(
|
||||
(res) => {
|
||||
const tmpItems$: WSItem[] = []
|
||||
const tmpFiltered$: WSItem[] = []
|
||||
|
@ -89,6 +105,7 @@ export class ShowFolderComponent implements OnInit {
|
|||
});
|
||||
this._items = tmpItems$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
|
||||
this.filteredItems = tmpFiltered$.sort(Sorting.getSortFunction(this.currentSortName, this.currentSortType));
|
||||
this.underUpload = this.getUnderUploadItems();
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -133,8 +150,8 @@ export class ShowFolderComponent implements OnInit {
|
|||
}
|
||||
|
||||
changeSortName($event: any) {
|
||||
var sort : SortName = $event.target.value;
|
||||
if (this.currentSortName != sort){
|
||||
var sort: SortName = $event.target.value;
|
||||
if (this.currentSortName != sort) {
|
||||
this.currentSortName = sort;
|
||||
this.updateSort();
|
||||
}
|
||||
|
@ -146,9 +163,13 @@ export class ShowFolderComponent implements OnInit {
|
|||
}
|
||||
|
||||
itemClicked(item: WSItem) {
|
||||
if (item.isFolder()) {
|
||||
if (item.isFolder())
|
||||
this.folderClickedEvent.emit(item);
|
||||
else if (item.isFile()){
|
||||
new OpenFile().open(this.storagehub, this.fileOpener, item);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
addFile() {
|
||||
|
@ -159,12 +180,23 @@ export class ShowFolderComponent implements OnInit {
|
|||
const selected = $event.target.files[0];
|
||||
|
||||
if (selected && this.parentItem) {
|
||||
this.underUploadItem = [selected.name];
|
||||
const upload$ = this.storagehub.uploadFile(this.parentItem.item.id, selected.name, selected);
|
||||
upload$.then( (obs) => obs.subscribe({
|
||||
next: () => this.loadDocuments(),
|
||||
error: () => this.underUploadItem = [],
|
||||
complete: () => this.underUploadItem = []
|
||||
const parentId: string = this.parentItem?.item?.id;
|
||||
this.uploaderInfo.uploadStarted(parentId, selected.name);
|
||||
const upload$ = this.storagehub.uploadFile(parentId, selected.name, selected);
|
||||
var first = true;
|
||||
upload$.then((obs) => obs.subscribe({
|
||||
next: () => {
|
||||
if (first) {
|
||||
this.loadDocuments();
|
||||
first = false;
|
||||
}
|
||||
},
|
||||
error: () => this.uploaderInfo.uploadFinished(parentId, selected.name),
|
||||
complete: () => {
|
||||
console.log
|
||||
this.uploaderInfo.uploadFinished(parentId, selected.name);
|
||||
this.loadDocuments();
|
||||
}
|
||||
|
||||
})
|
||||
);
|
||||
|
@ -233,7 +265,7 @@ export class ShowFolderComponent implements OnInit {
|
|||
await this.presentAlertControl(alertOptions);
|
||||
} else {
|
||||
var modalOptions: undefined | ModalOptions = action.getModalOptions(item, this.storagehub,
|
||||
() => this.loadDocuments(), (text: string) => this.presentToast(text));
|
||||
(itemId: string) => this.event.ReloadEvent.emit(itemId), (text: string) => this.presentToast(text));
|
||||
if (modalOptions)
|
||||
await this.presentModal(modalOptions);
|
||||
else
|
||||
|
|
|
@ -8,6 +8,7 @@ import { Item } from './model/item.model';
|
|||
import { ItemList } from './model/itemlist.model';
|
||||
import { ItemWrapper } from './model/item-wrapper.model';
|
||||
import { D4sAuthService } from './d4sauth.service';
|
||||
import { WSItem } from './model/ws-item';
|
||||
|
||||
|
||||
const shURL ="https://api.dev.d4science.org/workspace"
|
||||
|
@ -87,6 +88,14 @@ export class StoragehubService {
|
|||
);
|
||||
}
|
||||
|
||||
async downloadFile(itemId: string){
|
||||
const bearer = await this.auth.getSecureHeader();
|
||||
let downloadUrl = `${shURL}/items/${itemId}/download`;
|
||||
return this.http.get(downloadUrl, {headers: {"Authorization": bearer }, responseType: 'blob', observe: 'body'}).pipe(
|
||||
catchError(this.error)
|
||||
);
|
||||
}
|
||||
|
||||
async createFolder(parentId: string, name: string, description: string) {
|
||||
const bearer = await this.auth.getSecureHeader();
|
||||
let createFolderURL = `${shURL}/items/${parentId}/create/FOLDER`;
|
||||
|
@ -100,7 +109,7 @@ export class StoragehubService {
|
|||
async deleteItem(itemId: string) : Promise<Observable<any>> {
|
||||
const bearer = await this.auth.getSecureHeader();
|
||||
let deleteItemUrl = `${shURL}/items/${itemId}`;
|
||||
return this.http.delete( deleteItemUrl).pipe(
|
||||
return this.http.delete( deleteItemUrl, {headers: {"Authorization": bearer }}).pipe(
|
||||
catchError(this.error)
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue