forked from EVOgeek/Vmeda.Online
		
	MOBILE-3630 sharedfiled: Implement components and pages
This commit is contained in:
		
							parent
							
								
									92f5742351
								
							
						
					
					
						commit
						2302638702
					
				| @ -137,7 +137,7 @@ export abstract class CorePageItemsListManager<Item> { | |||||||
|         // If this item is already selected, do nothing.
 |         // If this item is already selected, do nothing.
 | ||||||
|         const itemRoute = this.getItemRoute(route); |         const itemRoute = this.getItemRoute(route); | ||||||
|         const itemPath = this.getItemPath(item); |         const itemPath = this.getItemPath(item); | ||||||
|         const selectedItemPath = itemRoute ? this.getSelectedItemPath(itemRoute.snapshot) : null; |         const selectedItemPath = itemRoute?.snapshot ? this.getSelectedItemPath(itemRoute.snapshot) : null; | ||||||
| 
 | 
 | ||||||
|         if (selectedItemPath === itemPath) { |         if (selectedItemPath === itemPath) { | ||||||
|             return; |             return; | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ import { CoreAttachmentsComponent } from './attachments/attachments'; | |||||||
| import { CoreFilesComponent } from './files/files'; | import { CoreFilesComponent } from './files/files'; | ||||||
| import { CoreLocalFileComponent } from './local-file/local-file'; | import { CoreLocalFileComponent } from './local-file/local-file'; | ||||||
| import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; | import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; | ||||||
|  | import { CoreSitePickerComponent } from './site-picker/site-picker'; | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|     declarations: [ |     declarations: [ | ||||||
| @ -86,6 +87,7 @@ import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; | |||||||
|         CoreFilesComponent, |         CoreFilesComponent, | ||||||
|         CoreLocalFileComponent, |         CoreLocalFileComponent, | ||||||
|         CoreBSTooltipComponent, |         CoreBSTooltipComponent, | ||||||
|  |         CoreSitePickerComponent, | ||||||
|     ], |     ], | ||||||
|     imports: [ |     imports: [ | ||||||
|         CommonModule, |         CommonModule, | ||||||
| @ -127,6 +129,7 @@ import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; | |||||||
|         CoreFilesComponent, |         CoreFilesComponent, | ||||||
|         CoreLocalFileComponent, |         CoreLocalFileComponent, | ||||||
|         CoreBSTooltipComponent, |         CoreBSTooltipComponent, | ||||||
|  |         CoreSitePickerComponent, | ||||||
|     ], |     ], | ||||||
| }) | }) | ||||||
| export class CoreComponentsModule {} | export class CoreComponentsModule {} | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								src/core/components/site-picker/core-site-picker.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/core/components/site-picker/core-site-picker.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | <ion-item *ngIf="sites && sites.length"> | ||||||
|  |     <ion-label>{{ 'core.site' | translate }}</ion-label> | ||||||
|  |     <ion-select [(ngModel)]="selectedSite" (ngModelChange)="siteSelected.emit(selectedSite)" interface="action-sheet"> | ||||||
|  |         <ion-select-option *ngFor="let site of sites" [value]="site.id">{{ site.fullNameAndSiteName }}</ion-select-option> | ||||||
|  |     </ion-select> | ||||||
|  | </ion-item> | ||||||
							
								
								
									
										77
									
								
								src/core/components/site-picker/site-picker.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/core/components/site-picker/site-picker.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | import { CoreFilter } from '@features/filter/services/filter'; | ||||||
|  | import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; | ||||||
|  | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | import { Translate } from '@singletons'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Component to display a site selector. It will display a select with the list of sites. If the selected site changes, | ||||||
|  |  * an output will be emitted with the site ID. | ||||||
|  |  * | ||||||
|  |  * Example usage: | ||||||
|  |  * <core-site-picker (siteSelected)="changeSite($event)"></core-site-picker> | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-site-picker', | ||||||
|  |     templateUrl: 'core-site-picker.html', | ||||||
|  | }) | ||||||
|  | export class CoreSitePickerComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |     @Input() initialSite?: string; // Initial site. If not provided, current site.
 | ||||||
|  |     @Output() siteSelected = new EventEmitter<string>(); // Emit an event when a site is selected. Sends the siteId as parameter.
 | ||||||
|  | 
 | ||||||
|  |     selectedSite?: string; | ||||||
|  |     sites?: SiteInfo[]; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     async ngOnInit(): Promise<void> { | ||||||
|  |         this.selectedSite = this.initialSite || CoreSites.getCurrentSiteId(); | ||||||
|  | 
 | ||||||
|  |         // Load the sites.
 | ||||||
|  |         const sites = await CoreSites.getSites(); | ||||||
|  | 
 | ||||||
|  |         if (!this.selectedSite && sites.length) { | ||||||
|  |             // There is no current site, select the first one.
 | ||||||
|  |             this.selectedSite = sites[0].id; | ||||||
|  |             this.siteSelected.emit(this.selectedSite); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         await Promise.all(sites.map(async (site: SiteInfo) => { | ||||||
|  |             // Format the site name.
 | ||||||
|  |             const options = { clean: true, singleLine: true, filter: false }; | ||||||
|  |             const siteName = await CoreUtils.ignoreErrors( | ||||||
|  |                 CoreFilter.formatText(site.siteName || '', options, [], site.id), | ||||||
|  |                 site.siteName || '', | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             site.fullNameAndSiteName = Translate.instant( | ||||||
|  |                 'core.fullnameandsitename', | ||||||
|  |                 { fullname: site.fullName, sitename: siteName }, | ||||||
|  |             ); | ||||||
|  |         })); | ||||||
|  | 
 | ||||||
|  |         this.sites = sites; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type SiteInfo = CoreSiteBasicInfo & { | ||||||
|  |     fullNameAndSiteName?: string; | ||||||
|  | }; | ||||||
| @ -376,16 +376,14 @@ export class CoreFileUploaderHelperProvider { | |||||||
|                     try { |                     try { | ||||||
|                         const data = await handler.action(maxSize, upload, allowOffline, handler.mimetypes); |                         const data = await handler.action(maxSize, upload, allowOffline, handler.mimetypes); | ||||||
| 
 | 
 | ||||||
|  |                         let result: CoreWSUploadFileResult | FileEntry | undefined; | ||||||
|  | 
 | ||||||
|                         if (data.treated) { |                         if (data.treated) { | ||||||
|                             // The handler already treated the file. Return the result.
 |                             // The handler already treated the file. Return the result.
 | ||||||
|                             this.fileUploaded(data.result!); |                             result = data.result; | ||||||
| 
 |  | ||||||
|                             return true; |  | ||||||
|                         } else if (data.fileEntry) { |                         } else if (data.fileEntry) { | ||||||
|                             // The handler provided us a fileEntry, use it.
 |                             // The handler provided us a fileEntry, use it.
 | ||||||
|                             await this.uploadFileEntry(data.fileEntry, !!data.delete, maxSize, upload, allowOffline); |                             result = await this.uploadFileEntry(data.fileEntry, !!data.delete, maxSize, upload, allowOffline); | ||||||
| 
 |  | ||||||
|                             return true; |  | ||||||
|                         } else if (data.path) { |                         } else if (data.path) { | ||||||
|                             let fileEntry: FileEntry; |                             let fileEntry: FileEntry; | ||||||
| 
 | 
 | ||||||
| @ -398,13 +396,17 @@ export class CoreFileUploaderHelperProvider { | |||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
|                             // File found, treat it.
 |                             // File found, treat it.
 | ||||||
|                             await this.uploadFileEntry(fileEntry, !!data.delete, maxSize, upload, allowOffline); |                             result = await this.uploadFileEntry(fileEntry, !!data.delete, maxSize, upload, allowOffline); | ||||||
| 
 |  | ||||||
|                             return true; |  | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         // Nothing received, fail.
 |                         if (!result) { | ||||||
|                         throw new CoreError('No file received'); |                             // Nothing received, fail.
 | ||||||
|  |                             throw new CoreError('No file received'); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         this.fileUploaded(result); | ||||||
|  | 
 | ||||||
|  |                         return true; | ||||||
|                     } catch (error) { |                     } catch (error) { | ||||||
|                         CoreDomUtils.showErrorModalDefault( |                         CoreDomUtils.showErrorModalDefault( | ||||||
|                             error, |                             error, | ||||||
|  | |||||||
| @ -1,55 +0,0 @@ | |||||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| import { CoreConstants } from '@/core/constants'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Settings section. |  | ||||||
|  */ |  | ||||||
| export type CoreSettingsSection = { |  | ||||||
|     name: string; |  | ||||||
|     path: string; |  | ||||||
|     icon: string; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Settings constants. |  | ||||||
|  */ |  | ||||||
| export class CoreSettingsConstants { |  | ||||||
| 
 |  | ||||||
|     static readonly SECTIONS: CoreSettingsSection[] = [ |  | ||||||
|         { |  | ||||||
|             name: 'general', |  | ||||||
|             path: 'general', |  | ||||||
|             icon: 'fas-wrench', |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             name: 'spaceusage', |  | ||||||
|             path: 'spaceusage', |  | ||||||
|             icon: 'fas-tasks', |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             name: 'synchronization', |  | ||||||
|             path: 'sync', |  | ||||||
|             icon: CoreConstants.ICON_SYNC, |  | ||||||
|         }, |  | ||||||
|         // @TODO sharedfiles
 |  | ||||||
|         { |  | ||||||
|             name: 'about', |  | ||||||
|             path: 'about', |  | ||||||
|             icon: 'fas-id-card', |  | ||||||
|         }, |  | ||||||
|     ]; |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -10,15 +10,10 @@ | |||||||
| <ion-content> | <ion-content> | ||||||
|     <core-split-view> |     <core-split-view> | ||||||
|         <ion-list> |         <ion-list> | ||||||
|             <ion-item |             <ion-item *ngFor="let section of sections.items" [class.core-selected-item]="sections.isSelected(section)" button | ||||||
|                 *ngFor="let section of sections.items" |                 detail="true" (click)="sections.select(section)"> | ||||||
|                 [class.core-selected-item]="sections.isSelected(section)" |  | ||||||
|                 button |  | ||||||
|                 detail |  | ||||||
|                 (click)="sections.select(section)" |  | ||||||
|             > |  | ||||||
|                 <ion-icon [name]="section.icon" slot="start"></ion-icon> |                 <ion-icon [name]="section.icon" slot="start"></ion-icon> | ||||||
|                 <ion-label>{{ 'core.settings.' + section.name | translate }}</ion-label> |                 <ion-label>{{ section.name | translate }}</ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
|         </ion-list> |         </ion-list> | ||||||
|     </core-split-view> |     </core-split-view> | ||||||
|  | |||||||
| @ -13,10 +13,14 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core'; | import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core'; | ||||||
| import { CoreSettingsConstants, CoreSettingsSection } from '@features/settings/constants'; | import { ActivatedRouteSnapshot, Params } from '@angular/router'; | ||||||
|  | 
 | ||||||
| import { CorePageItemsListManager } from '@classes/page-items-list-manager'; | import { CorePageItemsListManager } from '@classes/page-items-list-manager'; | ||||||
| import { ActivatedRouteSnapshot } from '@angular/router'; |  | ||||||
| import { CoreSplitViewComponent } from '@components/split-view/split-view'; | import { CoreSplitViewComponent } from '@components/split-view/split-view'; | ||||||
|  | import { CoreSettingsHelper } from '@features/settings/services/settings-helper'; | ||||||
|  | import { CoreConstants } from '@/core/constants'; | ||||||
|  | import { SHAREDFILES_PAGE_NAME } from '@features/sharedfiles/sharedfiles.module'; | ||||||
|  | import { CoreApp } from '@services/app'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|     selector: 'page-core-settings-index', |     selector: 'page-core-settings-index', | ||||||
| @ -32,7 +36,7 @@ export class CoreSettingsIndexPage implements AfterViewInit, OnDestroy { | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngAfterViewInit(): void { |     ngAfterViewInit(): void { | ||||||
|         this.sections.setItems(CoreSettingsConstants.SECTIONS); |         this.sections.setItems(this.getSections()); | ||||||
|         this.sections.start(this.splitView); |         this.sections.start(this.splitView); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -43,6 +47,48 @@ export class CoreSettingsIndexPage implements AfterViewInit, OnDestroy { | |||||||
|         this.sections.destroy(); |         this.sections.destroy(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Get the sections. | ||||||
|  |      * | ||||||
|  |      * @returns Sections. | ||||||
|  |      */ | ||||||
|  |     protected getSections(): CoreSettingsSection[] { | ||||||
|  |         const sections: CoreSettingsSection[] = [ | ||||||
|  |             { | ||||||
|  |                 name: 'core.settings.general', | ||||||
|  |                 path: 'general', | ||||||
|  |                 icon: 'fas-wrench', | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 name: 'core.settings.spaceusage', | ||||||
|  |                 path: 'spaceusage', | ||||||
|  |                 icon: 'fas-tasks', | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 name: 'core.settings.synchronization', | ||||||
|  |                 path: 'sync', | ||||||
|  |                 icon: CoreConstants.ICON_SYNC, | ||||||
|  |             }, | ||||||
|  |         ]; | ||||||
|  | 
 | ||||||
|  |         if (CoreApp.isIOS()) { | ||||||
|  |             sections.push({ | ||||||
|  |                 name: 'core.sharedfiles.sharedfiles', | ||||||
|  |                 path: SHAREDFILES_PAGE_NAME + '/list/root', | ||||||
|  |                 icon: 'fas-folder', | ||||||
|  |                 params: { manage: true }, | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         sections.push({ | ||||||
|  |             name: 'core.settings.about', | ||||||
|  |             path: 'about', | ||||||
|  |             icon: 'fas-id-card', | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return sections; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -57,11 +103,28 @@ class CoreSettingsSectionsManager extends CorePageItemsListManager<CoreSettingsS | |||||||
|         return section.path; |         return section.path; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     protected getItemQueryParams(section: CoreSettingsSection): Params { | ||||||
|  |         return section.params || {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { |     protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { | ||||||
|         return route.parent?.routeConfig?.path ?? null; |         return CoreSettingsHelper.getSelectedItemPath(route); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Settings section. | ||||||
|  |  */ | ||||||
|  | export type CoreSettingsSection = { | ||||||
|  |     name: string; | ||||||
|  |     path: string; | ||||||
|  |     icon: string; | ||||||
|  |     params?: Params; | ||||||
|  | }; | ||||||
|  | |||||||
| @ -26,19 +26,9 @@ | |||||||
|                     </ion-label> |                     </ion-label> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
|                 <ion-item-divider><ion-label></ion-label></ion-item-divider> |                 <ion-item-divider><ion-label></ion-label></ion-item-divider> | ||||||
|                 <!-- <ion-item *ngIf="isIOS" |  | ||||||
|                     (click)="openHandler('CoreSharedFilesListPage', {manage: true, siteId: siteId, hideSitePicker: true})" |  | ||||||
|                     [title]="'core.sharedfiles.sharedfiles' | translate" |  | ||||||
|                     [class.core-selected-item]="'CoreSharedFilesListPage' == selectedPage" detail> |  | ||||||
|                     <ion-icon name="fas-folder" slot="start"></ion-icon> |  | ||||||
|                     <ion-label> |  | ||||||
|                         <h2>{{ 'core.sharedfiles.sharedfiles' | translate }}</h2> |  | ||||||
|                     </ion-label> |  | ||||||
|                     <ion-badge slot="end">{{ iosSharedFiles }}</ion-badge> |  | ||||||
|                 </ion-item> --> |  | ||||||
| 
 | 
 | ||||||
|                 <ion-item *ngFor="let handler of handlers.items" [ngClass]="['core-settings-handler', handler.class]" |                 <ion-item *ngFor="let handler of handlers.items" [ngClass]="['core-settings-handler', handler.class]" | ||||||
|                     [title]="handler.title | translate" detail="true" (click)="handlers.select(handler)" |                     [title]="handler.title | translate" detail="true" (click)="handlers.select(handler)" button | ||||||
|                     [class.core-selected-item]="handlers.isSelected(handler)"> |                     [class.core-selected-item]="handlers.isSelected(handler)"> | ||||||
|                     <ion-icon [name]="handler.icon" slot="start" *ngIf="handler.icon"> |                     <ion-icon [name]="handler.icon" slot="start" *ngIf="handler.icon"> | ||||||
|                     </ion-icon> |                     </ion-icon> | ||||||
|  | |||||||
| @ -20,7 +20,6 @@ import { CoreSettingsDelegate, CoreSettingsHandlerToDisplay } from '../../servic | |||||||
| import { CoreEventObserver, CoreEvents } from '@singletons/events'; | import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||||
| import { CoreSites } from '@services/sites'; | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| // import { CoreSharedFiles } from '@features/sharedfiles/services/sharedfiles';
 |  | ||||||
| import { CoreSettingsHelper, CoreSiteSpaceUsage } from '../../services/settings-helper'; | import { CoreSettingsHelper, CoreSiteSpaceUsage } from '../../services/settings-helper'; | ||||||
| import { CoreApp } from '@services/app'; | import { CoreApp } from '@services/app'; | ||||||
| import { CoreSiteInfo } from '@classes/site'; | import { CoreSiteInfo } from '@classes/site'; | ||||||
| @ -52,7 +51,6 @@ export class CoreSitePreferencesPage implements AfterViewInit, OnDestroy { | |||||||
|         spaceUsage: 0, |         spaceUsage: 0, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     iosSharedFiles = 0; |  | ||||||
|     protected sitesObserver: CoreEventObserver; |     protected sitesObserver: CoreEventObserver; | ||||||
|     protected isDestroyed = false; |     protected isDestroyed = false; | ||||||
| 
 | 
 | ||||||
| @ -101,25 +99,7 @@ export class CoreSitePreferencesPage implements AfterViewInit, OnDestroy { | |||||||
|         this.siteName = currentSite!.getSiteName(); |         this.siteName = currentSite!.getSiteName(); | ||||||
|         this.siteUrl = currentSite!.getURL(); |         this.siteUrl = currentSite!.getURL(); | ||||||
| 
 | 
 | ||||||
|         const promises: Promise<void>[] = []; |         this.spaceUsage = await CoreSettingsHelper.getSiteSpaceUsage(this.siteId); | ||||||
| 
 |  | ||||||
|         promises.push(CoreSettingsHelper.getSiteSpaceUsage(this.siteId) |  | ||||||
|             .then((spaceUsage) => { |  | ||||||
|                 this.spaceUsage = spaceUsage; |  | ||||||
| 
 |  | ||||||
|                 return; |  | ||||||
|             })); |  | ||||||
| 
 |  | ||||||
|         /* if (this.isIOS) { |  | ||||||
|             promises.push(CoreSharedFiles.getSiteSharedFiles(this.siteId) |  | ||||||
|                 .then((files) => { |  | ||||||
|                 this.iosSharedFiles = files.length; |  | ||||||
| 
 |  | ||||||
|                 return; |  | ||||||
|             })); |  | ||||||
|         }*/ |  | ||||||
| 
 |  | ||||||
|         await Promise.all(promises); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -224,9 +204,7 @@ class CoreSettingsSitePreferencesManager extends CorePageItemsListManager<CoreSe | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { |     protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { | ||||||
|         // @todo: routeConfig doesn't have a path after refreshing the app.
 |         return CoreSettingsHelper.getSelectedItemPath(route); | ||||||
|         // route.component is null too, and route.parent.url is empty.
 |  | ||||||
|         return route.parent?.routeConfig?.path ?? null; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,6 +27,9 @@ import { CoreDomUtils } from '@services/utils/dom'; | |||||||
| import { CoreCourse } from '@features/course/services/course'; | import { CoreCourse } from '@features/course/services/course'; | ||||||
| import { makeSingleton, Translate } from '@singletons'; | import { makeSingleton, Translate } from '@singletons'; | ||||||
| import { CoreError } from '@classes/errors/error'; | import { CoreError } from '@classes/errors/error'; | ||||||
|  | import { ActivatedRouteSnapshot } from '@angular/router'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { CoreTextUtils } from '@services/utils/text'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Object with space usage and cache entries that can be erased. |  * Object with space usage and cache entries that can be erased. | ||||||
| @ -438,6 +441,29 @@ export class CoreSettingsHelperProvider { | |||||||
|         document.body.classList.toggle('dark', enable); |         document.body.classList.toggle('dark', enable); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Implementation of getSelectedItemPath for settings items managers. | ||||||
|  |      * | ||||||
|  |      * @param route Current route. | ||||||
|  |      * @return Path of the selected item in the given route. | ||||||
|  |      */ | ||||||
|  |     getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { | ||||||
|  |         // @todo: routeConfig doesn't have a path after refreshing the app.
 | ||||||
|  |         // route.component is null too, and route.parent.url is empty.
 | ||||||
|  |         let routePath = route.routeConfig?.path; | ||||||
|  |         const parentPath = route.parent?.routeConfig?.path; | ||||||
|  | 
 | ||||||
|  |         if (!routePath && !parentPath) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (routePath) { | ||||||
|  |             routePath = CoreNavigator.replaceRoutePathParams(routePath, route.params); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return CoreTextUtils.concatenatePaths(parentPath || '', routePath || ''); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const CoreSettingsHelper = makeSingleton(CoreSettingsHelperProvider); | export const CoreSettingsHelper = makeSingleton(CoreSettingsHelperProvider); | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ import { CoreSharedModule } from '@/core/shared.module'; | |||||||
| import { CoreScreen } from '@services/screen'; | import { CoreScreen } from '@services/screen'; | ||||||
| 
 | 
 | ||||||
| import { CoreSettingsIndexPage } from './pages/index'; | import { CoreSettingsIndexPage } from './pages/index'; | ||||||
|  | import { SHAREDFILES_PAGE_NAME } from '@features/sharedfiles/sharedfiles.module'; | ||||||
| 
 | 
 | ||||||
| const sectionRoutes: Routes = [ | const sectionRoutes: Routes = [ | ||||||
|     { |     { | ||||||
| @ -36,7 +37,10 @@ const sectionRoutes: Routes = [ | |||||||
|             import('./pages/synchronization/synchronization.module') |             import('./pages/synchronization/synchronization.module') | ||||||
|                 .then(m => m.CoreSettingsSynchronizationPageModule), |                 .then(m => m.CoreSettingsSynchronizationPageModule), | ||||||
|     }, |     }, | ||||||
|     // @todo sharedfiles
 |     { | ||||||
|  |         path: SHAREDFILES_PAGE_NAME, | ||||||
|  |         loadChildren: () => import('@features/sharedfiles/sharedfiles-lazy.module').then(m => m.CoreSharedFilesLazyModule), | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|         path: 'about', |         path: 'about', | ||||||
|         loadChildren: () => import('./pages/about/about.module').then(m => m.CoreSettingsAboutPageModule), |         loadChildren: () => import('./pages/about/about.module').then(m => m.CoreSettingsAboutPageModule), | ||||||
|  | |||||||
| @ -0,0 +1,34 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | import { CoreSharedModule } from '@/core/shared.module'; | ||||||
|  | import { CoreSharedFilesListComponent } from './list/list'; | ||||||
|  | import { CoreSharedFilesListModalComponent } from './list-modal/list-modal'; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |     declarations: [ | ||||||
|  |         CoreSharedFilesListComponent, | ||||||
|  |         CoreSharedFilesListModalComponent, | ||||||
|  |     ], | ||||||
|  |     imports: [ | ||||||
|  |         CoreSharedModule, | ||||||
|  |     ], | ||||||
|  |     exports: [ | ||||||
|  |         CoreSharedFilesListComponent, | ||||||
|  |         CoreSharedFilesListModalComponent, | ||||||
|  |     ], | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesComponentsModule {} | ||||||
| @ -0,0 +1,19 @@ | |||||||
|  | <ion-header> | ||||||
|  |     <ion-toolbar> | ||||||
|  |         <ion-buttons slot="start"> | ||||||
|  |             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |         <ion-title>{{ title }}</ion-title> | ||||||
|  | 
 | ||||||
|  |         <ion-buttons slot="end"> | ||||||
|  |             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||||
|  |                 <ion-icon name="fas-times" slot="icon-only"></ion-icon> | ||||||
|  |             </ion-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |     </ion-toolbar> | ||||||
|  | </ion-header> | ||||||
|  | <ion-content> | ||||||
|  |     <core-shared-files-list [siteId]="siteId" [mimetypes]="mimetypes" [isModal]="true" [manage]="manage" [pick]="pick" | ||||||
|  |         [path]="path" [showSitePicker]="showSitePicker" (onPathChanged)="calculateTitle($event)" (onFilePicked)="filePicked($event)"> | ||||||
|  |     </core-shared-files-list> | ||||||
|  | </ion-content> | ||||||
| @ -0,0 +1,75 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, OnInit, Input } from '@angular/core'; | ||||||
|  | import { FileEntry } from '@ionic-native/file'; | ||||||
|  | 
 | ||||||
|  | import { CoreFile } from '@services/file'; | ||||||
|  | import { ModalController, Translate } from '@singletons'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Modal to display the list of shared files. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-shared-files-list-modal', | ||||||
|  |     templateUrl: 'list-modal.html', | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesListModalComponent implements OnInit { | ||||||
|  | 
 | ||||||
|  |     @Input() siteId?: string; | ||||||
|  |     @Input() mimetypes?: string[]; | ||||||
|  |     @Input() manage?: boolean; | ||||||
|  |     @Input() pick?: boolean; // To pick a file you MUST use a modal.
 | ||||||
|  |     @Input() path?: string; | ||||||
|  |     @Input() showSitePicker?: boolean; | ||||||
|  | 
 | ||||||
|  |     title?: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Component being initialized. | ||||||
|  |      */ | ||||||
|  |     ngOnInit(): void { | ||||||
|  |         this.calculateTitle(this.path); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Calculate the title. | ||||||
|  |      * | ||||||
|  |      * @param path Path to use. | ||||||
|  |      */ | ||||||
|  |     calculateTitle(path?: string): void { | ||||||
|  |         if (path) { | ||||||
|  |             this.title = CoreFile.getFileAndDirectoryFromPath(path).name; | ||||||
|  |         } else { | ||||||
|  |             this.title = Translate.instant('core.sharedfiles.sharedfiles'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Close modal. | ||||||
|  |      */ | ||||||
|  |     closeModal(): void { | ||||||
|  |         ModalController.dismiss(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A file was picked. | ||||||
|  |      * | ||||||
|  |      * @param file Picked file. | ||||||
|  |      */ | ||||||
|  |     filePicked(file: FileEntry): void { | ||||||
|  |         ModalController.dismiss(file); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								src/core/features/sharedfiles/components/list/list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/core/features/sharedfiles/components/list/list.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | <ion-refresher slot="fixed" [disabled]="!filesLoaded" (ionRefresh)="refreshFiles($event.target)"> | ||||||
|  |     <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||||
|  | </ion-refresher> | ||||||
|  | 
 | ||||||
|  | <!-- Allow selecting the site to view. --> | ||||||
|  | <core-site-picker *ngIf="showSitePicker" [hidden]="!filesLoaded" [initialSite]="siteId" (siteSelected)="changeSite($event)"> | ||||||
|  | </core-site-picker> | ||||||
|  | 
 | ||||||
|  | <core-loading [hideUntil]="filesLoaded" class="core-loading-center"> | ||||||
|  |     <ion-list *ngIf="files && files.length > 0"> | ||||||
|  |         <ng-container *ngFor="let file of files; let idx = index"> | ||||||
|  |             <core-local-file *ngIf="file.isFile" [file]="file" [manage]="manage" [overrideClick]="pick" | ||||||
|  |                 (onClick)="filePicked(file)" (onDelete)="fileDeleted(idx)" (onRename)="fileRenamed(idx, $event)"> | ||||||
|  |             </core-local-file> | ||||||
|  | 
 | ||||||
|  |             <ion-item button *ngIf="!file.isFile" class="ion-text-wrap item-file" (click)="openFolder(file)"> | ||||||
|  |                 <ion-thumbnail slot="start" aria-hidden="true"> | ||||||
|  |                     <img src="assets/img/files/folder-64.png" alt=""> | ||||||
|  |                 </ion-thumbnail> | ||||||
|  |                 <ion-label>{{ file.name }}</ion-label> | ||||||
|  |             </ion-item> | ||||||
|  |         </ng-container> | ||||||
|  |     </ion-list> | ||||||
|  | 
 | ||||||
|  |     <core-empty-box *ngIf="files && !files.length && manage" icon="fas-folder" | ||||||
|  |         [message]="'core.sharedfiles.nosharedfiles' | translate"> | ||||||
|  |     </core-empty-box> | ||||||
|  | 
 | ||||||
|  |     <core-empty-box *ngIf="files && !files.length && !manage" icon="fas-folder" | ||||||
|  |         [message]="'core.sharedfiles.nosharedfilestoupload' | translate"> | ||||||
|  |     </core-empty-box> | ||||||
|  | </core-loading> | ||||||
							
								
								
									
										170
									
								
								src/core/features/sharedfiles/components/list/list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								src/core/features/sharedfiles/components/list/list.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,170 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core'; | ||||||
|  | import { FileEntry, DirectoryEntry } from '@ionic-native/file'; | ||||||
|  | import { IonRefresher } from '@ionic/angular'; | ||||||
|  | import { Md5 } from 'ts-md5'; | ||||||
|  | 
 | ||||||
|  | import { CoreSharedFiles } from '@features/sharedfiles/services/sharedfiles'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreTextUtils } from '@services/utils/text'; | ||||||
|  | import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Component to display the list of shared files, either as a modal or inside a page. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-shared-files-list', | ||||||
|  |     templateUrl: 'list.html', | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesListComponent implements OnInit, OnDestroy { | ||||||
|  | 
 | ||||||
|  |     @Input() siteId?: string; | ||||||
|  |     @Input() mimetypes?: string[]; | ||||||
|  |     @Input() isModal?: boolean; // Whether the component is loaded in a modal.
 | ||||||
|  |     @Input() manage?: boolean; | ||||||
|  |     @Input() pick?: boolean; // To pick a file you MUST use a modal.
 | ||||||
|  |     @Input() path?: string; | ||||||
|  |     @Input() showSitePicker?: boolean; | ||||||
|  |     @Output() onPathChanged = new EventEmitter<string>(); | ||||||
|  |     @Output() onFilePicked = new EventEmitter<FileEntry>(); | ||||||
|  | 
 | ||||||
|  |     filesLoaded = false; | ||||||
|  |     files?: (FileEntry | DirectoryEntry)[]; | ||||||
|  | 
 | ||||||
|  |     protected shareObserver?: CoreEventObserver; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Component being initialized. | ||||||
|  |      */ | ||||||
|  |     ngOnInit(): void { | ||||||
|  |         this.siteId = this.siteId || CoreSites.getCurrentSiteId(); | ||||||
|  | 
 | ||||||
|  |         this.loadFiles(); | ||||||
|  | 
 | ||||||
|  |         // Listen for new files shared with the app.
 | ||||||
|  |         this.shareObserver = CoreEvents.on(CoreEvents.FILE_SHARED, (data) => { | ||||||
|  |             if (data.siteId == this.siteId) { | ||||||
|  |                 // File was stored in current site, refresh the list.
 | ||||||
|  |                 this.filesLoaded = false; | ||||||
|  |                 this.loadFiles().finally(() => { | ||||||
|  |                     this.filesLoaded = true; | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load the files. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async loadFiles(): Promise<void> { | ||||||
|  |         this.files = await CoreSharedFiles.getSiteSharedFiles(this.siteId, this.path, this.mimetypes); | ||||||
|  |         this.filesLoaded = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Refresh the list of files. | ||||||
|  |      * | ||||||
|  |      * @param refresher Refresher. | ||||||
|  |      */ | ||||||
|  |     refreshFiles(refresher: IonRefresher): void { | ||||||
|  |         this.loadFiles().finally(() => { | ||||||
|  |             refresher.complete(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Called when a file is deleted. Remove the file from the list. | ||||||
|  |      * | ||||||
|  |      * @param index Position of the file. | ||||||
|  |      */ | ||||||
|  |     fileDeleted(index: number): void { | ||||||
|  |         this.files!.splice(index, 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Called when a file is renamed. Update the list. | ||||||
|  |      * | ||||||
|  |      * @param index Position of the file. | ||||||
|  |      * @param data Data containing the new FileEntry. | ||||||
|  |      */ | ||||||
|  |     fileRenamed(index: number, data: { file: FileEntry }): void { | ||||||
|  |         this.files![index] = data.file; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Open a subfolder. | ||||||
|  |      * | ||||||
|  |      * @param folder The folder to open. | ||||||
|  |      */ | ||||||
|  |     openFolder(folder: DirectoryEntry): void { | ||||||
|  |         const path = CoreTextUtils.concatenatePaths(this.path || '', folder.name); | ||||||
|  | 
 | ||||||
|  |         if (this.isModal) { | ||||||
|  |             this.path = path; | ||||||
|  |             this.filesLoaded = false; | ||||||
|  |             this.loadFiles(); | ||||||
|  |             this.onPathChanged.emit(path); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const hash = <string> Md5.hashAsciiStr(path); | ||||||
|  | 
 | ||||||
|  |         CoreNavigator.navigate(`../${hash}`, { | ||||||
|  |             params: { | ||||||
|  |                 path, | ||||||
|  |                 manage: this.manage, | ||||||
|  |                 pick: this.pick, | ||||||
|  |                 siteId: this.siteId, | ||||||
|  |                 mimetypes: this.mimetypes, | ||||||
|  |                 isModal: false, | ||||||
|  |             }, | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Change site loaded. | ||||||
|  |      * | ||||||
|  |      * @param id Site to load. | ||||||
|  |      */ | ||||||
|  |     changeSite(id: string): void { | ||||||
|  |         this.siteId = id; | ||||||
|  |         this.path = ''; | ||||||
|  |         this.filesLoaded = false; | ||||||
|  |         this.loadFiles(); | ||||||
|  |         this.onPathChanged.emit(''); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A file was picked. | ||||||
|  |      * | ||||||
|  |      * @param file Picked file. | ||||||
|  |      */ | ||||||
|  |     filePicked(file: FileEntry): void { | ||||||
|  |         this.onFilePicked.emit(file); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Component destroyed. | ||||||
|  |      */ | ||||||
|  |     ngOnDestroy(): void { | ||||||
|  |         this.shareObserver?.off(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | <ion-header> | ||||||
|  |     <ion-toolbar> | ||||||
|  |         <ion-buttons slot="start"> | ||||||
|  |             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |         <ion-title>{{ 'core.sharedfiles.sharedfiles' | translate }}</ion-title> | ||||||
|  |     </ion-toolbar> | ||||||
|  | </ion-header> | ||||||
|  | <ion-content> | ||||||
|  |     <core-loading [hideUntil]="loaded"> | ||||||
|  |         <ion-list> | ||||||
|  |             <ion-item class="ion-text-wrap"> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <h2>{{ 'core.sharedfiles.chooseaccountstorefile' | translate }}</h2> | ||||||
|  |                     <p>{{fileName}}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  |             <ion-item *ngFor="let site of sites" (click)="storeInSite(site.id)" detail="false"> | ||||||
|  |                 <ion-avatar slot="start" aria-hidden="true"> | ||||||
|  |                     <img [src]="site.avatar" core-external-content [siteId]="site.id" | ||||||
|  |                         alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" | ||||||
|  |                         onError="this.src='assets/img/user-avatar.png'"> | ||||||
|  |                 </ion-avatar> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <h2>{{site.fullName}}</h2> | ||||||
|  |                     <p><core-format-text clean="true" [text]="site.siteName" [siteId]="site.id"></core-format-text></p> | ||||||
|  |                     <p>{{site.siteUrl}}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  |         </ion-list> | ||||||
|  |     </core-loading> | ||||||
|  | </ion-content> | ||||||
							
								
								
									
										108
									
								
								src/core/features/sharedfiles/pages/choose-site/choose-site.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/core/features/sharedfiles/pages/choose-site/choose-site.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, OnInit } from '@angular/core'; | ||||||
|  | import { CoreSharedFilesHelper } from '@features/sharedfiles/services/sharedfiles-helper'; | ||||||
|  | import { FileEntry } from '@ionic-native/file'; | ||||||
|  | import { CoreFile } from '@services/file'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; | ||||||
|  | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
|  | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Page to display the list of sites to choose one to store a shared file. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'page-core-shared-files-choose-site', | ||||||
|  |     templateUrl: 'choose-site.html', | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesChooseSitePage implements OnInit { | ||||||
|  | 
 | ||||||
|  |     fileName?: string; | ||||||
|  |     sites?: CoreSiteBasicInfo[]; | ||||||
|  |     loaded = false; | ||||||
|  | 
 | ||||||
|  |     protected filePath?: string; | ||||||
|  |     protected fileEntry?: FileEntry; | ||||||
|  |     protected isInbox = false; // Whether the file is in the Inbox folder.
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     async ngOnInit(): Promise<void> { | ||||||
|  |         this.filePath = CoreNavigator.getRouteParam('filePath'); | ||||||
|  |         this.isInbox = !!CoreNavigator.getRouteBooleanParam('isInbox'); | ||||||
|  | 
 | ||||||
|  |         if (!this.filePath) { | ||||||
|  |             CoreDomUtils.showErrorModal('Error reading file.'); | ||||||
|  |             await CoreUtils.nextTick(); | ||||||
|  |             CoreNavigator.back(); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const fileAndDir = CoreFile.getFileAndDirectoryFromPath(this.filePath); | ||||||
|  |         this.fileName = fileAndDir.name; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             await Promise.all([ | ||||||
|  |                 this.loadFile(), | ||||||
|  |                 this.loadSites(), | ||||||
|  |             ]); | ||||||
|  |         } catch { | ||||||
|  |             CoreDomUtils.showErrorModal('Error reading file.'); | ||||||
|  |             CoreNavigator.back(); | ||||||
|  |         } finally { | ||||||
|  |             this.loaded = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load the file data. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async loadFile(): Promise<void> { | ||||||
|  |         this.fileEntry = await CoreFile.getExternalFile(this.filePath!); | ||||||
|  |         this.fileName = this.fileEntry.name; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load sites. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async loadSites(): Promise<void> { | ||||||
|  |         this.sites = await CoreSites.getSites(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Store the file in a certain site. | ||||||
|  |      * | ||||||
|  |      * @param siteId Site ID. | ||||||
|  |      */ | ||||||
|  |     async storeInSite(siteId: string): Promise<void> { | ||||||
|  |         this.loaded = false; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             await CoreSharedFilesHelper.storeSharedFileInSite(this.fileEntry!, siteId, this.isInbox); | ||||||
|  | 
 | ||||||
|  |             CoreNavigator.back(); | ||||||
|  |         } finally { | ||||||
|  |             this.loaded = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								src/core/features/sharedfiles/pages/list/list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/core/features/sharedfiles/pages/list/list.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | <ion-header> | ||||||
|  |     <ion-toolbar> | ||||||
|  |         <ion-buttons slot="start"> | ||||||
|  |             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |         <ion-title>{{ title }}</ion-title> | ||||||
|  |     </ion-toolbar> | ||||||
|  | </ion-header> | ||||||
|  | <ion-content> | ||||||
|  |     <core-shared-files-list [siteId]="siteId" [mimetypes]="mimetypes" [isModal]="false" [manage]="manage" [pick]="false" | ||||||
|  |         [path]="path" [showSitePicker]="showSitePicker" (onPathChanged)="calculateTitle($event)"> | ||||||
|  |     </core-shared-files-list> | ||||||
|  | </ion-content> | ||||||
							
								
								
									
										63
									
								
								src/core/features/sharedfiles/pages/list/list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/core/features/sharedfiles/pages/list/list.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, OnInit } from '@angular/core'; | ||||||
|  | 
 | ||||||
|  | import { CoreFile } from '@services/file'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { Translate } from '@singletons'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Page to display the list of shared files. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'page-core-shared-files-list', | ||||||
|  |     templateUrl: 'list.html', | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesListPage implements OnInit { | ||||||
|  | 
 | ||||||
|  |     siteId?: string; | ||||||
|  |     mimetypes?: string[]; | ||||||
|  |     manage = false; | ||||||
|  |     showSitePicker = false; | ||||||
|  |     path = ''; | ||||||
|  |     title?: string; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     ngOnInit(): void { | ||||||
|  |         this.siteId = CoreNavigator.getRouteParam('siteId'); | ||||||
|  |         this.mimetypes = CoreNavigator.getRouteParam('mimetypes'); | ||||||
|  |         this.manage = !!CoreNavigator.getRouteBooleanParam('manage'); | ||||||
|  |         this.path = CoreNavigator.getRouteParam('path') || ''; | ||||||
|  |         this.showSitePicker = !CoreNavigator.getRouteParam('hideSitePicker'); | ||||||
|  | 
 | ||||||
|  |         this.calculateTitle(this.path); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Calculate the title. | ||||||
|  |      * | ||||||
|  |      * @param path Path to use. | ||||||
|  |      */ | ||||||
|  |     calculateTitle(path?: string): void { | ||||||
|  |         if (path) { | ||||||
|  |             this.title = CoreFile.getFileAndDirectoryFromPath(path).name; | ||||||
|  |         } else { | ||||||
|  |             this.title = Translate.instant('core.sharedfiles.sharedfiles'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								src/core/features/sharedfiles/sharedfiles-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/core/features/sharedfiles/sharedfiles-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { NgModule } from '@angular/core'; | ||||||
|  | import { RouterModule, Routes } from '@angular/router'; | ||||||
|  | 
 | ||||||
|  | import { CoreSharedModule } from '@/core/shared.module'; | ||||||
|  | import { CoreSharedFilesComponentsModule } from './components/components.module'; | ||||||
|  | import { CoreSharedFilesListPage } from './pages/list/list'; | ||||||
|  | import { CoreSharedFilesChooseSitePage } from './pages/choose-site/choose-site'; | ||||||
|  | 
 | ||||||
|  | const routes: Routes = [ | ||||||
|  |     { | ||||||
|  |         path: 'choosesite', | ||||||
|  |         component: CoreSharedFilesChooseSitePage, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         path: 'list/:hash', | ||||||
|  |         component: CoreSharedFilesListPage, | ||||||
|  |     }, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |     imports: [ | ||||||
|  |         RouterModule.forChild(routes), | ||||||
|  |         CoreSharedModule, | ||||||
|  |         CoreSharedFilesComponentsModule, | ||||||
|  |     ], | ||||||
|  |     declarations: [ | ||||||
|  |         CoreSharedFilesListPage, | ||||||
|  |         CoreSharedFilesChooseSitePage, | ||||||
|  |     ], | ||||||
|  | }) | ||||||
|  | export class CoreSharedFilesLazyModule {} | ||||||
| @ -465,6 +465,21 @@ export class CoreNavigatorService { | |||||||
|         return 'param-' + (++this.lastParamId); |         return 'param-' + (++this.lastParamId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Replace the route params in a path with the params values. | ||||||
|  |      * | ||||||
|  |      * @param path Path. | ||||||
|  |      * @param params Params. | ||||||
|  |      * @returns Path with params replaced. | ||||||
|  |      */ | ||||||
|  |     replaceRoutePathParams(path: string, params?: Params): string { | ||||||
|  |         for (const name in params) { | ||||||
|  |             path = path.replace(`:${name}`, params[name]); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return path; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const CoreNavigator = makeSingleton(CoreNavigatorService); | export const CoreNavigator = makeSingleton(CoreNavigatorService); | ||||||
|  | |||||||
| @ -373,6 +373,6 @@ export type CoreEventFileSharedData = { | |||||||
| /** | /** | ||||||
|  * Data passed to APP_LAUNCHED_URL event. |  * Data passed to APP_LAUNCHED_URL event. | ||||||
|  */ |  */ | ||||||
|  export type CoreEventAppLaunchedData = { | export type CoreEventAppLaunchedData = { | ||||||
|     url: string; |     url: string; | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user