MOBILE-4459 core: Create and use core-sites-list component

main
Dani Palou 2023-11-01 15:52:20 +01:00
parent d27d3ddec3
commit a9bae5937c
15 changed files with 234 additions and 260 deletions

View File

@ -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 {}

View 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>

View File

@ -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;

View 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);
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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">

View File

@ -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();

View File

@ -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.
};

View File

@ -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>

View File

@ -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.
};

View File

@ -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>

View File

@ -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 {

View File

@ -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>

View File

@ -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 {