MOBILE-4459 core: Create and use core-sites-list component
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 { CoreRefreshButtonModalComponent } from './refresh-button-modal/refresh-button-modal';
|
||||||
import { CoreSheetModalComponent } from '@components/sheet-modal/sheet-modal';
|
import { CoreSheetModalComponent } from '@components/sheet-modal/sheet-modal';
|
||||||
import { CoreCourseImageComponent } from '@components/course-image/course-image';
|
import { CoreCourseImageComponent } from '@components/course-image/course-image';
|
||||||
|
import { CoreSitesListComponent } from './sites-list/sites-list';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -112,6 +113,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image'
|
||||||
CoreSwipeNavigationTourComponent,
|
CoreSwipeNavigationTourComponent,
|
||||||
CoreRefreshButtonModalComponent,
|
CoreRefreshButtonModalComponent,
|
||||||
CoreSheetModalComponent,
|
CoreSheetModalComponent,
|
||||||
|
CoreSitesListComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -166,6 +168,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image'
|
||||||
CoreSwipeNavigationTourComponent,
|
CoreSwipeNavigationTourComponent,
|
||||||
CoreRefreshButtonModalComponent,
|
CoreRefreshButtonModalComponent,
|
||||||
CoreSheetModalComponent,
|
CoreSheetModalComponent,
|
||||||
|
CoreSitesListComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreComponentsModule {}
|
export class CoreComponentsModule {}
|
||||||
|
|
|
@ -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 {
|
ion-list.core-sites-list {
|
||||||
.core-sitelist-sitename {
|
.core-sites-list-sitename {
|
||||||
ion-label {
|
ion-label {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
|
@ -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,51 +20,24 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list class="core-sitelist">
|
<core-sites-list [accountsList]="accountsList" [sitesClickable]="true" [currentSiteClickable]="false"
|
||||||
<ion-card *ngIf="accountsList.currentSite">
|
(onSiteClicked)="login($event)">
|
||||||
<ion-item-divider sticky="true" class="core-sitelist-sitename">
|
<ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite">
|
||||||
<ion-label>
|
<ion-icon *ngIf="isCurrentSite" color="success" name="fas-check"></ion-icon>
|
||||||
<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>
|
|
||||||
|
|
||||||
<ion-item detail="false">
|
<ng-container *ngIf="!isCurrentSite">
|
||||||
<core-user-avatar [user]="accountsList.currentSite" slot="start" [linkProfile]="false"
|
<ion-badge slot="end" *ngIf="!showDelete && site.badge" @coreShowHideAnimation>
|
||||||
[siteId]="accountsList.currentSite.id"></core-user-avatar>
|
<span aria-hidden="true">{{site.badge}}</span>
|
||||||
|
<span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge }
|
||||||
<ion-label>
|
}}</span>
|
||||||
<p class="item-heading">{{accountsList.currentSite.fullname}}</p>
|
</ion-badge>
|
||||||
</ion-label>
|
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
||||||
<ion-icon color="success" name="fas-check"></ion-icon>
|
[attr.aria-label]="'core.login.removeaccount' | translate" [@coreSlideInOut]="'fromRight'">
|
||||||
</ion-item>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
<ng-container *ngTemplateOutlet="siteList; context: {sites: accountsList.sameSite}"></ng-container>
|
</ng-container>
|
||||||
</ion-card>
|
</ng-template>
|
||||||
|
</core-sites-list>
|
||||||
<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>
|
</core-loading>
|
||||||
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
||||||
<ion-fab-button (click)="add($event)" [attr.aria-label]="'core.login.add' | translate">
|
<ion-fab-button (click)="add($event)" [attr.aria-label]="'core.login.add' | translate">
|
||||||
|
@ -73,23 +46,3 @@
|
||||||
</ion-fab-button>
|
</ion-fab-button>
|
||||||
</ion-fab>
|
</ion-fab>
|
||||||
</ion-content>
|
</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>
|
|
||||||
<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 }
|
|
||||||
}}</span>
|
|
||||||
</ion-badge>
|
|
||||||
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
|
||||||
[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>
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ import { ModalController } from '@singletons';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'core-login-sites',
|
selector: 'core-login-sites',
|
||||||
templateUrl: 'sites.html',
|
templateUrl: 'sites.html',
|
||||||
styleUrls: ['../../sitelist.scss'],
|
|
||||||
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
||||||
})
|
})
|
||||||
export class CoreLoginSitesComponent implements OnInit {
|
export class CoreLoginSitesComponent implements OnInit {
|
||||||
|
@ -99,15 +98,14 @@ export class CoreLoginSitesComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
* Login in a site.
|
* Login in a site.
|
||||||
*
|
*
|
||||||
* @param event Click event.
|
* @param site The site.
|
||||||
* @param siteId The site ID.
|
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async login(event: Event, siteId: string): Promise<void> {
|
async login(site: CoreSiteBasicInfo): Promise<void> {
|
||||||
await this.close(event, true);
|
await this.close(undefined, true);
|
||||||
|
|
||||||
// This navigation will logout and navigate to the site home.
|
// 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.
|
* @param event Click event.
|
||||||
*/
|
*/
|
||||||
async close(event: Event, closeAll = false): Promise<void> {
|
async close(event?: Event, closeAll = false): Promise<void> {
|
||||||
event.preventDefault();
|
event?.preventDefault();
|
||||||
event.stopPropagation();
|
event?.stopPropagation();
|
||||||
|
|
||||||
await ModalController.dismiss(closeAll);
|
await ModalController.dismiss(closeAll);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,37 +21,19 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content class="limited-width">
|
<ion-content class="limited-width">
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list class="core-sitelist">
|
<core-sites-list [accountsList]="accountsList" [sitesClickable]="true" (onSiteClicked)="login($event)">
|
||||||
<ion-card *ngFor="let sites of accountsList.otherSites">
|
<ng-template #siteItem let-site="site" let-isCurrentSite="isCurrentSite">
|
||||||
<ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename">
|
<ion-badge slot="end" *ngIf="!showDelete && site.badge" @coreShowHideAnimation>
|
||||||
<ion-label>
|
<span aria-hidden="true">{{site.badge}}</span>
|
||||||
<h2>
|
<span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge }
|
||||||
<core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text>
|
}}</span>
|
||||||
</h2>
|
</ion-badge>
|
||||||
<p *ngIf="!sites[0].isDemoModeSite">
|
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
||||||
<a [href]="sites[0].siteUrl" core-link autoLogin="no">{{ sites[0].siteUrlWithoutProtocol }}</a>
|
[attr.aria-label]="'core.login.removeaccount' | translate" [@coreSlideInOut]="'fromRight'">
|
||||||
</p>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-label>
|
</ion-button>
|
||||||
</ion-item-divider>
|
</ng-template>
|
||||||
|
</core-sites-list>
|
||||||
<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>
|
|
||||||
<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 }
|
|
||||||
}}</span>
|
|
||||||
</ion-badge>
|
|
||||||
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
|
||||||
[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>
|
|
||||||
</core-loading>
|
</core-loading>
|
||||||
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
||||||
<ion-fab-button (click)="add()" [attr.aria-label]="'core.login.add' | translate">
|
<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';
|
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({
|
@Component({
|
||||||
selector: 'page-core-login-sites',
|
selector: 'page-core-login-sites',
|
||||||
templateUrl: 'sites.html',
|
templateUrl: 'sites.html',
|
||||||
styleUrls: ['../../sitelist.scss'],
|
|
||||||
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
||||||
})
|
})
|
||||||
export class CoreLoginSitesPage implements OnInit {
|
export class CoreLoginSitesPage implements OnInit {
|
||||||
|
@ -102,18 +101,14 @@ export class CoreLoginSitesPage implements OnInit {
|
||||||
/**
|
/**
|
||||||
* Login in a site.
|
* Login in a site.
|
||||||
*
|
*
|
||||||
* @param event Click event.
|
* @param site The site.
|
||||||
* @param siteId The site ID.
|
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async login(event: Event, siteId: string): Promise<void> {
|
async login(site: CoreSiteBasicInfo): Promise<void> {
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
const modal = await CoreDomUtils.showModalLoading();
|
const modal = await CoreDomUtils.showModalLoading();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const loggedIn = await CoreSites.loadSite(siteId);
|
const loggedIn = await CoreSites.loadSite(site.id);
|
||||||
|
|
||||||
if (loggedIn) {
|
if (loggedIn) {
|
||||||
await CoreNavigator.navigateToSiteHome();
|
await CoreNavigator.navigateToSiteHome();
|
||||||
|
|
|
@ -1541,10 +1541,10 @@ export const CoreLoginHelper = makeSingleton(CoreLoginHelperProvider);
|
||||||
/**
|
/**
|
||||||
* Accounts list for selecting sites interfaces.
|
* Accounts list for selecting sites interfaces.
|
||||||
*/
|
*/
|
||||||
export type CoreAccountsList = {
|
export type CoreAccountsList<T extends CoreSiteBasicInfo = CoreSiteBasicInfo> = {
|
||||||
currentSite?: CoreSiteBasicInfo; // If logged in, current site info.
|
currentSite?: T; // If logged in, current site info.
|
||||||
sameSite: CoreSiteBasicInfo[]; // If logged in, accounts info on the same site.
|
sameSite: T[]; // If logged in, accounts info on the same site.
|
||||||
otherSites: CoreSiteBasicInfo[][]; // Other accounts in other sites.
|
otherSites: T[][]; // Other accounts in other sites.
|
||||||
count: number; // Number of sites.
|
count: number; // Number of sites.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,47 +17,21 @@
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list class="core-sitelist limited-width">
|
<ion-list class="limited-width">
|
||||||
<ion-card *ngIf="accountsList.currentSite">
|
<core-sites-list [accountsList]="accountsList">
|
||||||
<ion-item-divider sticky="true" class="core-sitelist-sitename">
|
<ng-template #siteLabel let-site="site">
|
||||||
<ion-label>
|
<ion-badge color="light" *ngIf="site.spaceUsage !== undefined">{{ site.spaceUsage | coreBytesToSize }}</ion-badge>
|
||||||
<p class="item-heading">
|
</ng-template>
|
||||||
<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-item class="item-current">
|
<ng-template #siteItem let-site="site">
|
||||||
<ng-container *ngTemplateOutlet="siteUsage; context: {site: accountsList.currentSite}"></ng-container>
|
<ion-button fill="clear" color="danger" slot="end" (click)="deleteSiteStorage(site)"
|
||||||
</ion-item>
|
[hidden]="site.spaceUsage <= 0 && !site.hasCacheEntries">
|
||||||
|
<ion-icon name="fas-trash" slot="icon-only"
|
||||||
<ion-item *ngFor="let site of accountsList.sameSite">
|
[attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: site.siteName }">
|
||||||
<ng-container *ngTemplateOutlet="siteUsage; context: {site: site}"></ng-container>
|
</ion-icon>
|
||||||
</ion-item>
|
</ion-button>
|
||||||
</ion-card>
|
</ng-template>
|
||||||
|
</core-sites-list>
|
||||||
<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>
|
|
||||||
|
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
@ -70,19 +44,3 @@
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</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 { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
|
|
||||||
import { CoreSettingsHelper } from '../../services/settings-helper';
|
import { CoreSettingsHelper } from '../../services/settings-helper';
|
||||||
|
import { CoreAccountsList } from '@features/login/services/login-helper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the space usage settings.
|
* Page that displays the space usage settings.
|
||||||
|
@ -33,9 +34,10 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy {
|
||||||
loaded = false;
|
loaded = false;
|
||||||
totalSpaceUsage = 0;
|
totalSpaceUsage = 0;
|
||||||
|
|
||||||
accountsList: CoreAccountsListWithUsage = {
|
accountsList: CoreAccountsList<CoreSiteBasicInfoWithUsage> = {
|
||||||
sameSite: [],
|
sameSite: [],
|
||||||
otherSites: [],
|
otherSites: [],
|
||||||
|
count: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
protected sitesObserver: CoreEventObserver;
|
protected sitesObserver: CoreEventObserver;
|
||||||
|
@ -128,6 +130,7 @@ export class CoreSettingsSpaceUsagePage implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.accountsList.otherSites = CoreUtils.objectToArray(otherSites);
|
this.accountsList.otherSites = CoreUtils.objectToArray(otherSites);
|
||||||
|
this.accountsList.count = sites.length;
|
||||||
|
|
||||||
this.totalSpaceUsage = totalSize;
|
this.totalSpaceUsage = totalSize;
|
||||||
}
|
}
|
||||||
|
@ -192,12 +195,3 @@ interface CoreSiteBasicInfoWithUsage extends CoreSiteBasicInfo {
|
||||||
hasCacheEntries: boolean; // If has cached entries that can be cleared.
|
hasCacheEntries: boolean; // If has cached entries that can be cleared.
|
||||||
spaceUsage: number; // Space used in this site.
|
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-header>
|
||||||
<ion-content class="limited-width">
|
<ion-content class="limited-width">
|
||||||
<core-loading [hideUntil]="sitesLoaded">
|
<core-loading [hideUntil]="sitesLoaded">
|
||||||
<ion-list class="core-sitelist limited-width">
|
<ion-list class="limited-width">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.settings.syncsettings' | translate }}</h2>
|
<h2>{{ 'core.settings.syncsettings' | translate }}</h2>
|
||||||
|
@ -51,65 +51,25 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ion-card *ngIf="accountsList.currentSite">
|
<core-sites-list [accountsList]="accountsList">
|
||||||
<ion-item-divider sticky="true" class="core-sitelist-sitename">
|
<ng-template #siteLabel let-site="site">
|
||||||
<ion-label>
|
<p class="text-danger" *ngIf="site.loggedOut">{{ 'core.settings.logintosync' | translate }}</p>
|
||||||
<p class="item-heading">
|
</ng-template>
|
||||||
<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-item class="item-current">
|
<ng-template #siteItem let-site="site">
|
||||||
<ng-container *ngTemplateOutlet="siteSync; context: {site: accountsList.currentSite}"></ng-container>
|
<core-button-with-spinner [loading]="isSynchronizing(site.id)" slot="end" *ngIf="!site.loggedOut">
|
||||||
</ion-item>
|
<ion-button fill="clear" (click)="synchronize(site.id)"
|
||||||
|
[attr.aria-label]="'core.settings.synchronizenow' | translate">
|
||||||
<ion-item *ngFor="let site of accountsList.sameSite">
|
<ion-icon name="fas-rotate" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
<ng-container *ngTemplateOutlet="siteSync; context: {site: site}"></ng-container>
|
</ion-button>
|
||||||
</ion-item>
|
</core-button-with-spinner>
|
||||||
</ion-card>
|
<ion-button fill="clear" (click)="login(site.id)" [attr.aria-label]="'core.login.login' | translate"
|
||||||
|
*ngIf="site.loggedOut" slot="end">
|
||||||
<ion-card *ngFor="let sites of accountsList.otherSites">
|
<ion-icon name="fas-right-to-bracket" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
<ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename">
|
</ion-button>
|
||||||
<ion-label>
|
</ng-template>
|
||||||
<p class="item-heading">
|
</core-sites-list>
|
||||||
<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-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</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({
|
@Component({
|
||||||
selector: 'page-core-app-settings-synchronization',
|
selector: 'page-core-app-settings-synchronization',
|
||||||
templateUrl: 'synchronization.html',
|
templateUrl: 'synchronization.html',
|
||||||
styleUrls: ['../../../login/sitelist.scss'],
|
|
||||||
})
|
})
|
||||||
export class CoreSettingsSynchronizationPage implements OnInit, OnDestroy {
|
export class CoreSettingsSynchronizationPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,8 @@
|
||||||
<p>{{fileName}}</p>
|
<p>{{fileName}}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngFor="let site of sites" (click)="storeInSite(site.id)" detail="false" button>
|
<core-sites-list [accountsList]="accountsList" [sitesClickable]="true" (onSiteClicked)="storeInSite($event)">
|
||||||
<core-user-avatar [user]="site" slot="start" [linkProfile]="false" [siteId]="site.id"></core-user-avatar>
|
</core-sites-list>
|
||||||
|
|
||||||
<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>
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { CoreAccountsList, CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreSharedFilesHelper } from '@features/sharedfiles/services/sharedfiles-helper';
|
import { CoreSharedFilesHelper } from '@features/sharedfiles/services/sharedfiles-helper';
|
||||||
import { FileEntry } from '@ionic-native/file/ngx';
|
import { FileEntry } from '@ionic-native/file/ngx';
|
||||||
import { CoreFile } from '@services/file';
|
import { CoreFile } from '@services/file';
|
||||||
|
@ -30,8 +31,12 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
export class CoreSharedFilesChooseSitePage implements OnInit {
|
export class CoreSharedFilesChooseSitePage implements OnInit {
|
||||||
|
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
sites?: CoreSiteBasicInfo[];
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
accountsList: CoreAccountsList = {
|
||||||
|
sameSite: [],
|
||||||
|
otherSites: [],
|
||||||
|
count: 0,
|
||||||
|
};
|
||||||
|
|
||||||
protected filePath?: string;
|
protected filePath?: string;
|
||||||
protected fileEntry?: FileEntry;
|
protected fileEntry?: FileEntry;
|
||||||
|
@ -89,15 +94,15 @@ export class CoreSharedFilesChooseSitePage implements OnInit {
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async loadSites(): Promise<void> {
|
protected async loadSites(): Promise<void> {
|
||||||
this.sites = await CoreSites.getSites();
|
this.accountsList = await CoreLoginHelper.getAccountsList(CoreSites.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the file in a certain site.
|
* 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) {
|
if (!this.fileEntry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +110,7 @@ export class CoreSharedFilesChooseSitePage implements OnInit {
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await CoreSharedFilesHelper.storeSharedFileInSite(this.fileEntry, siteId, this.isInbox);
|
await CoreSharedFilesHelper.storeSharedFileInSite(this.fileEntry, site.id, this.isInbox);
|
||||||
|
|
||||||
CoreNavigator.back();
|
CoreNavigator.back();
|
||||||
} finally {
|
} finally {
|
||||||
|
|
Loading…
Reference in New Issue