MOBILE-4459 core: Create and use core-sites-list component
This commit is contained in:
		
							parent
							
								
									d27d3ddec3
								
							
						
					
					
						commit
						a9bae5937c
					
				| @ -65,6 +65,7 @@ import { CoreGroupSelectorComponent } from './group-selector/group-selector'; | ||||
| import { CoreRefreshButtonModalComponent } from './refresh-button-modal/refresh-button-modal'; | ||||
| import { CoreSheetModalComponent } from '@components/sheet-modal/sheet-modal'; | ||||
| import { CoreCourseImageComponent } from '@components/course-image/course-image'; | ||||
| import { CoreSitesListComponent } from './sites-list/sites-list'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|     declarations: [ | ||||
| @ -112,6 +113,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image' | ||||
|         CoreSwipeNavigationTourComponent, | ||||
|         CoreRefreshButtonModalComponent, | ||||
|         CoreSheetModalComponent, | ||||
|         CoreSitesListComponent, | ||||
|     ], | ||||
|     imports: [ | ||||
|         CommonModule, | ||||
| @ -166,6 +168,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image' | ||||
|         CoreSwipeNavigationTourComponent, | ||||
|         CoreRefreshButtonModalComponent, | ||||
|         CoreSheetModalComponent, | ||||
|         CoreSitesListComponent, | ||||
|     ], | ||||
| }) | ||||
| export class CoreComponentsModule {} | ||||
|  | ||||
							
								
								
									
										56
									
								
								src/core/components/sites-list/sites-list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/core/components/sites-list/sites-list.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| <ion-list class="core-sites-list" *ngIf="accountsList"> | ||||
|     <ion-card *ngIf="accountsList.currentSite"> | ||||
|         <ng-container *ngTemplateOutlet="siteCardHeader; context: {site: accountsList.currentSite, isCurrentSite: true}"></ng-container> | ||||
| 
 | ||||
|         <ng-container *ngTemplateOutlet="siteItem; context: {site: accountsList.currentSite, isCurrentSite: true}"></ng-container> | ||||
| 
 | ||||
|         <ng-container *ngFor="let site of accountsList.sameSite"> | ||||
|             <ng-container *ngTemplateOutlet="siteItem; context: {site: site, isCurrentSite: false}"></ng-container> | ||||
|         </ng-container> | ||||
|     </ion-card> | ||||
| 
 | ||||
|     <ion-card *ngFor="let sites of accountsList.otherSites"> | ||||
|         <ng-container *ngTemplateOutlet="siteCardHeader; context: {site: sites[0], isCurrentSite: false}"></ng-container> | ||||
| 
 | ||||
|         <ng-container *ngFor="let site of sites"> | ||||
|             <ng-container *ngTemplateOutlet="siteItem; context: {site: site, isCurrentSite: false}"></ng-container> | ||||
|         </ng-container> | ||||
|     </ion-card> | ||||
| 
 | ||||
| </ion-list> | ||||
| 
 | ||||
| <!-- Template to render the header of a site card. --> | ||||
| <ng-template #siteCardHeader let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|     <ion-item-divider sticky="true" *ngIf="site" class="core-sites-list-sitename"> | ||||
|         <ion-label> | ||||
|             <h2> | ||||
|                 <core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text> | ||||
|             </h2> | ||||
|             <p *ngIf="!site.isDemoModeSite"> | ||||
|                 <a [href]="site.siteUrl" core-link [autoLogin]="isCurrentSite ? 'yes' : 'no'"> | ||||
|                     {{ site.siteUrlWithoutProtocol }} | ||||
|                 </a> | ||||
|             </p> | ||||
|         </ion-label> | ||||
|     </ion-item-divider> | ||||
| </ng-template> | ||||
| 
 | ||||
| <!-- Template to render a site item. --> | ||||
| <ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|     <ion-item [attr.button]="isSiteClickable(isCurrentSite) ? true : null" (click)="siteClicked($event, site, isCurrentSite)" | ||||
|         [attr.detail]="isSiteClickable(isCurrentSite) ? 'true' : 'false'" [class.item-current]="isCurrentSite"> | ||||
| 
 | ||||
|         <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|         <ion-label> | ||||
|             <p class="item-heading">{{site.fullname}}</p> | ||||
|             <ng-container *ngIf="siteLabelTemplate" [ngTemplateOutlet]="siteLabelTemplate" | ||||
|                 [ngTemplateOutletContext]="{site: site, isCurrentSite: isCurrentSite}"> | ||||
|             </ng-container> | ||||
|         </ion-label> | ||||
| 
 | ||||
|         <ng-container *ngIf="siteItemTemplate" [ngTemplateOutlet]="siteItemTemplate" | ||||
|             [ngTemplateOutletContext]="{site: site, isCurrentSite: isCurrentSite}"> | ||||
|         </ng-container> | ||||
|     </ion-item> | ||||
| </ng-template> | ||||
| @ -1,5 +1,5 @@ | ||||
| ion-list.core-sitelist { | ||||
|     .core-sitelist-sitename { | ||||
| ion-list.core-sites-list { | ||||
|     .core-sites-list-sitename { | ||||
|         ion-label { | ||||
|             margin-top: 8px; | ||||
|             margin-bottom: 8px; | ||||
							
								
								
									
										80
									
								
								src/core/components/sites-list/sites-list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/core/components/sites-list/sites-list.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| // (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, ContentChild, Input, Output, TemplateRef, EventEmitter } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreSiteBasicInfo } from '@services/sites'; | ||||
| import { CoreAccountsList } from '@features/login/services/login-helper'; | ||||
| 
 | ||||
| /** | ||||
|  * Component to display a list of sites (accounts). | ||||
|  * | ||||
|  * By default this component will display the avatar and user fullname for each site, but it allows adding more information | ||||
|  * in the item and in the label for each site, using #siteItem and #siteLabel ng-templates. These templates will receive the | ||||
|  * site being rendered and whether it's the current site or not. Example: | ||||
|  * | ||||
|  * <core-sites-list [accountsList]="accountsList"> | ||||
|  *     <ng-template #siteLabel let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|  *         <!-- Content to be placed in the label, after the user full name.
 | ||||
|  *     </ng-template> | ||||
|  * | ||||
|  *    <ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|  *         <!-- Content to be placed in the item.
 | ||||
|  *     </ng-template> | ||||
|  * </core-sites-list> | ||||
|  */ | ||||
| @Component({ | ||||
|     selector: 'core-sites-list', | ||||
|     templateUrl: 'sites-list.html', | ||||
|     styleUrls: ['sites-list.scss'], | ||||
| }) | ||||
| export class CoreSitesListComponent<T extends CoreSiteBasicInfo> { | ||||
| 
 | ||||
|     @Input() accountsList!: CoreAccountsList<T>; | ||||
|     @Input() sitesClickable = false; // Whether the sites are clickable.
 | ||||
|     @Input() currentSiteClickable?: boolean; // If set, specify a different clickable value for current site.
 | ||||
|     @Output() onSiteClicked = new EventEmitter<T>(); | ||||
| 
 | ||||
|     @ContentChild('siteItem') siteItemTemplate?: TemplateRef<unknown>; | ||||
|     @ContentChild('siteLabel') siteLabelTemplate?: TemplateRef<unknown>; | ||||
| 
 | ||||
|     /** | ||||
|      * Check whether a site is clickable. | ||||
|      * | ||||
|      * @param isCurrentSite Whether the site is current site. | ||||
|      * @returns Whether it's clickable. | ||||
|      */ | ||||
|     isSiteClickable(isCurrentSite: boolean): boolean { | ||||
|         return isCurrentSite ? this.currentSiteClickable ?? this.sitesClickable : this.sitesClickable; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * A site was clicked. | ||||
|      * | ||||
|      * @param ev Event. | ||||
|      * @param site Site clicked. | ||||
|      * @param isCurrentSite Whether the site is current site. | ||||
|      */ | ||||
|     siteClicked(ev: Event, site: T, isCurrentSite: boolean): void { | ||||
|         if (!this.isSiteClickable(isCurrentSite)) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         ev.preventDefault(); | ||||
|         ev.stopPropagation(); | ||||
| 
 | ||||
|         this.onSiteClicked.emit(site); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -20,68 +20,12 @@ | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <ion-list class="core-sitelist"> | ||||
|             <ion-card *ngIf="accountsList.currentSite"> | ||||
|                 <ion-item-divider sticky="true" class="core-sitelist-sitename"> | ||||
|                     <ion-label> | ||||
|                         <h2> | ||||
|                             <core-format-text [text]="accountsList.currentSite.siteName" clean="true" | ||||
|                                 [siteId]="accountsList.currentSite.id"></core-format-text> | ||||
|                         </h2> | ||||
|                         <p *ngIf="!accountsList.currentSite.isDemoModeSite"> | ||||
|                             <a [href]="accountsList.currentSite.siteUrl" core-link autoLogin="yes"> | ||||
|                                 {{ accountsList.currentSite.siteUrlWithoutProtocol }} | ||||
|                             </a> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
|         <core-sites-list [accountsList]="accountsList" [sitesClickable]="true" [currentSiteClickable]="false" | ||||
|             (onSiteClicked)="login($event)"> | ||||
|             <ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|                 <ion-icon *ngIf="isCurrentSite" color="success" name="fas-check"></ion-icon> | ||||
| 
 | ||||
|                 <ion-item detail="false"> | ||||
|                     <core-user-avatar [user]="accountsList.currentSite" slot="start" [linkProfile]="false" | ||||
|                         [siteId]="accountsList.currentSite.id"></core-user-avatar> | ||||
| 
 | ||||
|                     <ion-label> | ||||
|                         <p class="item-heading">{{accountsList.currentSite.fullname}}</p> | ||||
|                     </ion-label> | ||||
|                     <ion-icon color="success" name="fas-check"></ion-icon> | ||||
|                 </ion-item> | ||||
| 
 | ||||
|                 <ng-container *ngTemplateOutlet="siteList; context: {sites: accountsList.sameSite}"></ng-container> | ||||
|             </ion-card> | ||||
| 
 | ||||
|             <ion-card *ngFor="let sites of accountsList.otherSites"> | ||||
|                 <ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename"> | ||||
|                     <ion-label> | ||||
|                         <h2> | ||||
|                             <core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text> | ||||
|                         </h2> | ||||
|                         <p *ngIf="!sites[0].isDemoModeSite"> | ||||
|                             <a [href]="sites[0].siteUrl" core-link autoLogin="no">{{ sites[0].siteUrlWithoutProtocol }}</a> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
| 
 | ||||
|                 <ng-container *ngTemplateOutlet="siteList; context: {sites: sites}"></ng-container> | ||||
|             </ion-card> | ||||
| 
 | ||||
|         </ion-list> | ||||
|     </core-loading> | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end"> | ||||
|         <ion-fab-button (click)="add($event)" [attr.aria-label]="'core.login.add' | translate"> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|             <span class="sr-only">{{ 'core.login.add' | translate }}</span> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </ion-content> | ||||
| 
 | ||||
| <!-- Template to render a list of sites. --> | ||||
| <ng-template #siteList let-sites="sites"> | ||||
|     <ion-item button *ngFor="let site of sites" (click)="login($event, site.id)" detail="true"> | ||||
|         <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|         <ion-label> | ||||
|             <p class="item-heading">{{site.fullname}}</p> | ||||
|         </ion-label> | ||||
|                 <ng-container *ngIf="!isCurrentSite"> | ||||
|                     <ion-badge slot="end" *ngIf="!showDelete && site.badge" @coreShowHideAnimation> | ||||
|                         <span aria-hidden="true">{{site.badge}}</span> | ||||
|                         <span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge } | ||||
| @ -91,5 +35,14 @@ | ||||
|                         [attr.aria-label]="'core.login.removeaccount' | translate" [@coreSlideInOut]="'fromRight'"> | ||||
|                         <ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                     </ion-button> | ||||
|     </ion-item> | ||||
| </ng-template> | ||||
|                 </ng-container> | ||||
|             </ng-template> | ||||
|         </core-sites-list> | ||||
|     </core-loading> | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end"> | ||||
|         <ion-fab-button (click)="add($event)" [attr.aria-label]="'core.login.add' | translate"> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|             <span class="sr-only">{{ 'core.login.add' | translate }}</span> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </ion-content> | ||||
|  | ||||
| @ -28,7 +28,6 @@ import { ModalController } from '@singletons'; | ||||
| @Component({ | ||||
|     selector: 'core-login-sites', | ||||
|     templateUrl: 'sites.html', | ||||
|     styleUrls: ['../../sitelist.scss'], | ||||
|     animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE], | ||||
| }) | ||||
| export class CoreLoginSitesComponent implements OnInit { | ||||
| @ -99,15 +98,14 @@ export class CoreLoginSitesComponent implements OnInit { | ||||
|     /** | ||||
|      * Login in a site. | ||||
|      * | ||||
|      * @param event Click event. | ||||
|      * @param siteId The site ID. | ||||
|      * @param site The site. | ||||
|      * @returns Promise resolved when done. | ||||
|      */ | ||||
|     async login(event: Event, siteId: string): Promise<void> { | ||||
|         await this.close(event, true); | ||||
|     async login(site: CoreSiteBasicInfo): Promise<void> { | ||||
|         await this.close(undefined, true); | ||||
| 
 | ||||
|         // This navigation will logout and navigate to the site home.
 | ||||
|         await CoreNavigator.navigateToSiteHome({ preferCurrentTab: false , siteId }); | ||||
|         await CoreNavigator.navigateToSiteHome({ preferCurrentTab: false , siteId: site.id }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -122,9 +120,9 @@ export class CoreLoginSitesComponent implements OnInit { | ||||
|      * | ||||
|      * @param event Click event. | ||||
|      */ | ||||
|     async close(event: Event, closeAll = false): Promise<void> { | ||||
|         event.preventDefault(); | ||||
|         event.stopPropagation(); | ||||
|     async close(event?: Event, closeAll = false): Promise<void> { | ||||
|         event?.preventDefault(); | ||||
|         event?.stopPropagation(); | ||||
| 
 | ||||
|         await ModalController.dismiss(closeAll); | ||||
|     } | ||||
|  | ||||
| @ -21,25 +21,8 @@ | ||||
| </ion-header> | ||||
| <ion-content class="limited-width"> | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <ion-list class="core-sitelist"> | ||||
|             <ion-card *ngFor="let sites of accountsList.otherSites"> | ||||
|                 <ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename"> | ||||
|                     <ion-label> | ||||
|                         <h2> | ||||
|                             <core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text> | ||||
|                         </h2> | ||||
|                         <p *ngIf="!sites[0].isDemoModeSite"> | ||||
|                             <a [href]="sites[0].siteUrl" core-link autoLogin="no">{{ sites[0].siteUrlWithoutProtocol }}</a> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
| 
 | ||||
|                 <ion-item button *ngFor="let site of sites" (click)="login($event, site.id)" detail="true"> | ||||
|                     <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|                     <ion-label> | ||||
|                         <p class="item-heading">{{site.fullname}}</p> | ||||
|                     </ion-label> | ||||
|         <core-sites-list [accountsList]="accountsList" [sitesClickable]="true" (onSiteClicked)="login($event)"> | ||||
|             <ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite"> | ||||
|                 <ion-badge slot="end" *ngIf="!showDelete && site.badge" @coreShowHideAnimation> | ||||
|                     <span aria-hidden="true">{{site.badge}}</span> | ||||
|                     <span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge } | ||||
| @ -49,9 +32,8 @@ | ||||
|                     [attr.aria-label]="'core.login.removeaccount' | translate" [@coreSlideInOut]="'fromRight'"> | ||||
|                     <ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|                 </ion-item> | ||||
|             </ion-card> | ||||
|         </ion-list> | ||||
|             </ng-template> | ||||
|         </core-sites-list> | ||||
|     </core-loading> | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end"> | ||||
|         <ion-fab-button (click)="add()" [attr.aria-label]="'core.login.add' | translate"> | ||||
|  | ||||
| @ -22,12 +22,11 @@ import { CoreFilter } from '@features/filter/services/filter'; | ||||
| import { CoreAnimations } from '@components/animations'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays a "splash screen" while the app is being initialized. | ||||
|  * Page that displays the list of sites stored in the device. | ||||
|  */ | ||||
| @Component({ | ||||
|     selector: 'page-core-login-sites', | ||||
|     templateUrl: 'sites.html', | ||||
|     styleUrls: ['../../sitelist.scss'], | ||||
|     animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE], | ||||
| }) | ||||
| export class CoreLoginSitesPage implements OnInit { | ||||
| @ -102,18 +101,14 @@ export class CoreLoginSitesPage implements OnInit { | ||||
|     /** | ||||
|      * Login in a site. | ||||
|      * | ||||
|      * @param event Click event. | ||||
|      * @param siteId The site ID. | ||||
|      * @param site The site. | ||||
|      * @returns Promise resolved when done. | ||||
|      */ | ||||
|     async login(event: Event, siteId: string): Promise<void> { | ||||
|         event.preventDefault(); | ||||
|         event.stopPropagation(); | ||||
| 
 | ||||
|     async login(site: CoreSiteBasicInfo): Promise<void> { | ||||
|         const modal = await CoreDomUtils.showModalLoading(); | ||||
| 
 | ||||
|         try { | ||||
|             const loggedIn = await CoreSites.loadSite(siteId); | ||||
|             const loggedIn = await CoreSites.loadSite(site.id); | ||||
| 
 | ||||
|             if (loggedIn) { | ||||
|                 await CoreNavigator.navigateToSiteHome(); | ||||
|  | ||||
| @ -1541,10 +1541,10 @@ export const CoreLoginHelper = makeSingleton(CoreLoginHelperProvider); | ||||
| /** | ||||
|  * Accounts list for selecting sites interfaces. | ||||
|  */ | ||||
| export type CoreAccountsList = { | ||||
|     currentSite?: CoreSiteBasicInfo; // If logged in, current site info.
 | ||||
|     sameSite: CoreSiteBasicInfo[]; // If logged in, accounts info on the same site.
 | ||||
|     otherSites: CoreSiteBasicInfo[][]; // Other accounts in other sites.
 | ||||
| export type CoreAccountsList<T extends CoreSiteBasicInfo = CoreSiteBasicInfo> = { | ||||
|     currentSite?: T; // If logged in, current site info.
 | ||||
|     sameSite: T[]; // If logged in, accounts info on the same site.
 | ||||
|     otherSites: T[][]; // Other accounts in other sites.
 | ||||
|     count: number; // Number of sites.
 | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -17,47 +17,21 @@ | ||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||
|     </ion-refresher> | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <ion-list class="core-sitelist limited-width"> | ||||
|             <ion-card *ngIf="accountsList.currentSite"> | ||||
|                 <ion-item-divider sticky="true" class="core-sitelist-sitename"> | ||||
|                     <ion-label> | ||||
|                         <p class="item-heading"> | ||||
|                             <core-format-text [text]="accountsList.currentSite.siteName" clean="true" | ||||
|                                 [siteId]="accountsList.currentSite.id"></core-format-text> | ||||
|                         </p> | ||||
|                         <p *ngIf="!accountsList.currentSite.isDemoModeSite"> | ||||
|                             <a [href]="accountsList.currentSite.siteUrl" core-link autoLogin="yes"> | ||||
|                                 {{ accountsList.currentSite.siteUrlWithoutProtocol }} | ||||
|                             </a> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
|         <ion-list class="limited-width"> | ||||
|             <core-sites-list [accountsList]="accountsList"> | ||||
|                 <ng-template #siteLabel let-site="site"> | ||||
|                     <ion-badge color="light" *ngIf="site.spaceUsage !== undefined">{{ site.spaceUsage | coreBytesToSize }}</ion-badge> | ||||
|                 </ng-template> | ||||
| 
 | ||||
|                 <ion-item class="item-current"> | ||||
|                     <ng-container *ngTemplateOutlet="siteUsage; context: {site: accountsList.currentSite}"></ng-container> | ||||
|                 </ion-item> | ||||
| 
 | ||||
|                 <ion-item *ngFor="let site of accountsList.sameSite"> | ||||
|                     <ng-container *ngTemplateOutlet="siteUsage; context: {site: site}"></ng-container> | ||||
|                 </ion-item> | ||||
|             </ion-card> | ||||
| 
 | ||||
|             <ion-card *ngFor="let sites of accountsList.otherSites"> | ||||
|                 <ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename"> | ||||
|                     <ion-label> | ||||
|                         <p class="item-heading"> | ||||
|                             <core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text> | ||||
|                         </p> | ||||
|                         <p *ngIf="!sites[0].isDemoModeSite"> | ||||
|                             <a [href]="sites[0].siteUrl" core-link autoLogin="no">{{ sites[0].siteUrlWithoutProtocol }}</a> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
| 
 | ||||
|                 <ion-item *ngFor="let site of sites"> | ||||
|                     <ng-container *ngTemplateOutlet="siteUsage; context: {site: site}"></ng-container> | ||||
|                 </ion-item> | ||||
|             </ion-card> | ||||
|                 <ng-template #siteItem let-site="site"> | ||||
|                     <ion-button fill="clear" color="danger" slot="end" (click)="deleteSiteStorage(site)" | ||||
|                         [hidden]="site.spaceUsage <= 0 && !site.hasCacheEntries"> | ||||
|                         <ion-icon name="fas-trash" slot="icon-only" | ||||
|                             [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: site.siteName }"> | ||||
|                         </ion-icon> | ||||
|                     </ion-button> | ||||
|                 </ng-template> | ||||
|             </core-sites-list> | ||||
| 
 | ||||
|             <ion-item-divider> | ||||
|                 <ion-label> | ||||
| @ -70,19 +44,3 @@ | ||||
|         </ion-list> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
| 
 | ||||
| <!-- Template to render a site space usage. --> | ||||
| <ng-template #siteUsage let-site="site"> | ||||
|     <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|     <ion-label class="ion-text-wrap"> | ||||
|         <p class="item-heading">{{site.fullname}}</p> | ||||
|         <ion-badge color="light" *ngIf="site.spaceUsage !== undefined">{{ site.spaceUsage | coreBytesToSize }}</ion-badge> | ||||
|     </ion-label> | ||||
|     <ion-button fill="clear" color="danger" slot="end" (click)="deleteSiteStorage(site)" | ||||
|         [hidden]="site.spaceUsage <= 0 && !site.hasCacheEntries"> | ||||
|         <ion-icon name="fas-trash" slot="icon-only" | ||||
|             [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: site.siteName }"> | ||||
|         </ion-icon> | ||||
|     </ion-button> | ||||
| </ng-template> | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { CoreUtils } from '@services/utils/utils'; | ||||
| import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||
| 
 | ||||
| import { CoreSettingsHelper } from '../../services/settings-helper'; | ||||
| import { CoreAccountsList } from '@features/login/services/login-helper'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the space usage settings. | ||||
| @ -33,9 +34,10 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy { | ||||
|     loaded = false; | ||||
|     totalSpaceUsage = 0; | ||||
| 
 | ||||
|     accountsList: CoreAccountsListWithUsage = { | ||||
|     accountsList: CoreAccountsList<CoreSiteBasicInfoWithUsage> = { | ||||
|         sameSite: [], | ||||
|         otherSites: [], | ||||
|         count: 0, | ||||
|     }; | ||||
| 
 | ||||
|     protected sitesObserver: CoreEventObserver; | ||||
| @ -128,6 +130,7 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy { | ||||
|         }); | ||||
| 
 | ||||
|         this.accountsList.otherSites = CoreUtils.objectToArray(otherSites); | ||||
|         this.accountsList.count = sites.length; | ||||
| 
 | ||||
|         this.totalSpaceUsage = totalSize; | ||||
|     } | ||||
| @ -192,12 +195,3 @@ interface CoreSiteBasicInfoWithUsage extends CoreSiteBasicInfo { | ||||
|     hasCacheEntries: boolean; // If has cached entries that can be cleared.
 | ||||
|     spaceUsage: number; // Space used in this site.
 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Accounts list for selecting sites interfaces. | ||||
|  */ | ||||
| type CoreAccountsListWithUsage = { | ||||
|     currentSite?: CoreSiteBasicInfoWithUsage; // If logged in, current site info.
 | ||||
|     sameSite: CoreSiteBasicInfoWithUsage[]; // If logged in, accounts info on the same site.
 | ||||
|     otherSites: CoreSiteBasicInfoWithUsage[][]; // Other accounts in other sites.
 | ||||
| }; | ||||
|  | ||||
| @ -17,7 +17,7 @@ | ||||
| </ion-header> | ||||
| <ion-content class="limited-width"> | ||||
|     <core-loading [hideUntil]="sitesLoaded"> | ||||
|         <ion-list class="core-sitelist limited-width"> | ||||
|         <ion-list class="limited-width"> | ||||
|             <ion-item-divider> | ||||
|                 <ion-label> | ||||
|                     <h2>{{ 'core.settings.syncsettings' | translate }}</h2> | ||||
| @ -51,65 +51,25 @@ | ||||
|                     </ion-label> | ||||
|                 </ion-item-divider> | ||||
| 
 | ||||
|                 <ion-card *ngIf="accountsList.currentSite"> | ||||
|                     <ion-item-divider sticky="true" class="core-sitelist-sitename"> | ||||
|                         <ion-label> | ||||
|                             <p class="item-heading"> | ||||
|                                 <core-format-text [text]="accountsList.currentSite.siteName" clean="true" | ||||
|                                     [siteId]="accountsList.currentSite.id"></core-format-text> | ||||
|                             </p> | ||||
|                             <p *ngIf="!accountsList.currentSite.isDemoModeSite"> | ||||
|                                 <a [href]="accountsList.currentSite.siteUrl" core-link autoLogin="yes"> | ||||
|                                     {{ accountsList.currentSite.siteUrlWithoutProtocol }} | ||||
|                                 </a> | ||||
|                             </p> | ||||
|                         </ion-label> | ||||
|                     </ion-item-divider> | ||||
|                 <core-sites-list [accountsList]="accountsList"> | ||||
|                     <ng-template #siteLabel let-site="site"> | ||||
|                         <p class="text-danger" *ngIf="site.loggedOut">{{ 'core.settings.logintosync' | translate }}</p> | ||||
|                     </ng-template> | ||||
| 
 | ||||
|                     <ion-item class="item-current"> | ||||
|                         <ng-container *ngTemplateOutlet="siteSync; context: {site: accountsList.currentSite}"></ng-container> | ||||
|                     </ion-item> | ||||
| 
 | ||||
|                     <ion-item *ngFor="let site of accountsList.sameSite"> | ||||
|                         <ng-container *ngTemplateOutlet="siteSync; context: {site: site}"></ng-container> | ||||
|                     </ion-item> | ||||
|                 </ion-card> | ||||
| 
 | ||||
|                 <ion-card *ngFor="let sites of accountsList.otherSites"> | ||||
|                     <ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename"> | ||||
|                         <ion-label> | ||||
|                             <p class="item-heading"> | ||||
|                                 <core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text> | ||||
|                             </p> | ||||
|                             <p *ngIf="!sites[0].isDemoModeSite"> | ||||
|                                 <a [href]="sites[0].siteUrl" core-link autoLogin="no">{{ sites[0].siteUrlWithoutProtocol }}</a> | ||||
|                             </p> | ||||
|                         </ion-label> | ||||
|                     </ion-item-divider> | ||||
| 
 | ||||
|                     <ion-item *ngFor="let site of sites"> | ||||
|                         <ng-container *ngTemplateOutlet="siteSync; context: {site: site}"></ng-container> | ||||
|                     </ion-item> | ||||
|                 </ion-card> | ||||
|                     <ng-template #siteItem let-site="site"> | ||||
|                         <core-button-with-spinner [loading]="isSynchronizing(site.id)" slot="end" *ngIf="!site.loggedOut"> | ||||
|                             <ion-button fill="clear" (click)="synchronize(site.id)" | ||||
|                                 [attr.aria-label]="'core.settings.synchronizenow' | translate"> | ||||
|                                 <ion-icon name="fas-rotate" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                             </ion-button> | ||||
|                         </core-button-with-spinner> | ||||
|                         <ion-button fill="clear" (click)="login(site.id)" [attr.aria-label]="'core.login.login' | translate" | ||||
|                             *ngIf="site.loggedOut" slot="end"> | ||||
|                             <ion-icon name="fas-right-to-bracket" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                         </ion-button> | ||||
|                     </ng-template> | ||||
|                 </core-sites-list> | ||||
|             </ng-container> | ||||
|         </ion-list> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
| 
 | ||||
| <!-- Template to render a site to sync. --> | ||||
| <ng-template #siteSync let-site="site"> | ||||
|     <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|     <ion-label> | ||||
|         <p class="item-heading">{{site.fullname}}</p> | ||||
|         <p class="text-danger" *ngIf="site.loggedOut">{{ 'core.settings.logintosync' | translate }}</p> | ||||
|     </ion-label> | ||||
|     <core-button-with-spinner [loading]="isSynchronizing(site.id)" slot="end" *ngIf="!site.loggedOut"> | ||||
|         <ion-button fill="clear" (click)="synchronize(site.id)" [attr.aria-label]="'core.settings.synchronizenow' | translate"> | ||||
|             <ion-icon name="fas-rotate" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|         </ion-button> | ||||
|     </core-button-with-spinner> | ||||
|     <ion-button fill="clear" (click)="login(site.id)" [attr.aria-label]="'core.login.login' | translate" *ngIf="site.loggedOut" slot="end"> | ||||
|         <ion-icon name="fas-right-to-bracket" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|     </ion-button> | ||||
| </ng-template> | ||||
|  | ||||
| @ -32,7 +32,6 @@ import { CoreNavigator } from '@services/navigator'; | ||||
| @Component({ | ||||
|     selector: 'page-core-app-settings-synchronization', | ||||
|     templateUrl: 'synchronization.html', | ||||
|     styleUrls: ['../../../login/sitelist.scss'], | ||||
| }) | ||||
| export class CoreSettingsSynchronizationPage implements OnInit, OnDestroy { | ||||
| 
 | ||||
|  | ||||
| @ -17,17 +17,8 @@ | ||||
|                     <p>{{fileName}}</p> | ||||
|                 </ion-label> | ||||
|             </ion-item> | ||||
|             <ion-item *ngFor="let site of sites" (click)="storeInSite(site.id)" detail="false" button> | ||||
|                 <core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar> | ||||
| 
 | ||||
|                 <ion-label> | ||||
|                     <p class="item-heading">{{site.fullname}}</p> | ||||
|                     <p> | ||||
|                         <core-format-text clean="true" [text]="site.siteName" [siteId]="site.id"></core-format-text> | ||||
|                     </p> | ||||
|                     <p *ngIf="!site.isDemoModeSite">{{site.siteUrl}}</p> | ||||
|                 </ion-label> | ||||
|             </ion-item> | ||||
|             <core-sites-list [accountsList]="accountsList" [sitesClickable]="true" (onSiteClicked)="storeInSite($event)"> | ||||
|             </core-sites-list> | ||||
|         </ion-list> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { CoreAccountsList, CoreLoginHelper } from '@features/login/services/login-helper'; | ||||
| import { CoreSharedFilesHelper } from '@features/sharedfiles/services/sharedfiles-helper'; | ||||
| import { FileEntry } from '@ionic-native/file/ngx'; | ||||
| import { CoreFile } from '@services/file'; | ||||
| @ -30,8 +31,12 @@ import { CoreDomUtils } from '@services/utils/dom'; | ||||
| export class CoreSharedFilesChooseSitePage implements OnInit { | ||||
| 
 | ||||
|     fileName?: string; | ||||
|     sites?: CoreSiteBasicInfo[]; | ||||
|     loaded = false; | ||||
|     accountsList: CoreAccountsList = { | ||||
|         sameSite: [], | ||||
|         otherSites: [], | ||||
|         count: 0, | ||||
|     }; | ||||
| 
 | ||||
|     protected filePath?: string; | ||||
|     protected fileEntry?: FileEntry; | ||||
| @ -89,15 +94,15 @@ export class CoreSharedFilesChooseSitePage implements OnInit { | ||||
|      * @returns Promise resolved when done. | ||||
|      */ | ||||
|     protected async loadSites(): Promise<void> { | ||||
|         this.sites = await CoreSites.getSites(); | ||||
|         this.accountsList = await CoreLoginHelper.getAccountsList(CoreSites.getCurrentSiteId()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Store the file in a certain site. | ||||
|      * | ||||
|      * @param siteId Site ID. | ||||
|      * @param site Site. | ||||
|      */ | ||||
|     async storeInSite(siteId: string): Promise<void> { | ||||
|     async storeInSite(site: CoreSiteBasicInfo): Promise<void> { | ||||
|         if (!this.fileEntry) { | ||||
|             return; | ||||
|         } | ||||
| @ -105,7 +110,7 @@ export class CoreSharedFilesChooseSitePage implements OnInit { | ||||
|         this.loaded = false; | ||||
| 
 | ||||
|         try { | ||||
|             await CoreSharedFilesHelper.storeSharedFileInSite(this.fileEntry, siteId, this.isInbox); | ||||
|             await CoreSharedFilesHelper.storeSharedFileInSite(this.fileEntry, site.id, this.isInbox); | ||||
| 
 | ||||
|             CoreNavigator.back(); | ||||
|         } finally { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user