Skip to content

Commit

Permalink
Merge pull request #3844 from dpalou/MOBILE-4459
Browse files Browse the repository at this point in the history
Mobile 4459
  • Loading branch information
NoelDeMartin authored Nov 15, 2023
2 parents 38303aa + a0f8171 commit ee9daad
Show file tree
Hide file tree
Showing 40 changed files with 735 additions and 322 deletions.
32 changes: 32 additions & 0 deletions src/assets/storybook/sites/companylisa.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// (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 { CoreSiteFixture } from '@/storybook/stubs/classes/site';

export const companyLisaSite: CoreSiteFixture = {
id: 'companylisasite',
info: {
version: '2022041900',
sitename: 'Company',
username: 'lisa',
firstname: 'Lisa',
lastname: 'Díaz',
fullname: 'Lisa Díaz',
lang: 'en',
userid: 1,
siteurl: 'https://company.example.edu',
userpictureurl: 'https://i.pravatar.cc/300?user=companylisa',
functions: [],
},
};
1 change: 0 additions & 1 deletion src/assets/storybook/sites/school.json

This file was deleted.

32 changes: 32 additions & 0 deletions src/assets/storybook/sites/schoolbarbara.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// (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 { CoreSiteFixture } from '@/storybook/stubs/classes/site';

export const schoolBarbaraSite: CoreSiteFixture = {
id: 'schoolbarbarasite',
info: {
version: '2022041900',
sitename: 'School',
username: 'barbara',
firstname: 'Barbara',
lastname: 'Gardner',
fullname: 'Barbara Gardner',
lang: 'en',
userid: 1,
siteurl: 'https://campus.example.edu',
userpictureurl: 'https://i.pravatar.cc/300?user=schoolbarbara',
functions: [],
},
};
32 changes: 32 additions & 0 deletions src/assets/storybook/sites/schooljeffery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// (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 { CoreSiteFixture } from '@/storybook/stubs/classes/site';

export const schoolJefferySite: CoreSiteFixture = {
id: 'schooljefferysite',
info: {
version: '2022041900',
sitename: 'School',
username: 'jeffery',
firstname: 'Jeffery',
lastname: 'Sanders',
fullname: 'Jeffery Sanders',
lang: 'en',
userid: 2,
siteurl: 'https://campus.example.edu',
userpictureurl: 'https://i.pravatar.cc/300?user=schooljeffery',
functions: [],
},
};
19 changes: 17 additions & 2 deletions src/core/classes/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,18 @@ export class CoreSite {
* @returns Site name.
*/
async getSiteName(): Promise<string> {
if (this.isDemoModeSite()) {
return CoreConstants.CONFIG.appname;
}

if (this.infos?.sitename) {
return this.infos?.sitename;
}

// Fallback.
const isSigleFixedSite = await CoreLoginHelper.isSingleFixedSite();
const isSingleFixedSite = await CoreLoginHelper.isSingleFixedSite();

if (isSigleFixedSite) {
if (isSingleFixedSite) {
const sites = await CoreLoginHelper.getAvailableSites();

return sites[0].name;
Expand Down Expand Up @@ -2459,6 +2463,17 @@ export class CoreSite {
});
}

/**
* Check if the site is a demo mode site.
*
* @returns Whether the site is a demo mode site.
*/
isDemoModeSite(): boolean {
const demoSiteData = CoreLoginHelper.getDemoModeSiteInfo();

return this.containsUrl(demoSiteData?.url);
}

}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/core/components/components.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down Expand Up @@ -112,6 +113,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image'
CoreSwipeNavigationTourComponent,
CoreRefreshButtonModalComponent,
CoreSheetModalComponent,
CoreSitesListComponent,
],
imports: [
CommonModule,
Expand Down Expand Up @@ -166,6 +168,7 @@ import { CoreCourseImageComponent } from '@components/course-image/course-image'
CoreSwipeNavigationTourComponent,
CoreRefreshButtonModalComponent,
CoreSheetModalComponent,
CoreSitesListComponent,
],
})
export class CoreComponentsModule {}
56 changes: 56 additions & 0 deletions src/core/components/sites-list/sites-list.html
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
80 changes: 80 additions & 0 deletions src/core/components/sites-list/sites-list.ts
Original file line number Diff line number Diff line change
@@ -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);
}

}
4 changes: 4 additions & 0 deletions src/core/components/stories/components/components.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,21 @@ import { CoreComponentsModule } from '@components/components.module';
import { CommonModule } from '@angular/common';
import { CoreCourseImageCardsPageComponent } from '@components/stories/components/course-image-cards-page/course-image-cards-page';
import { CoreCourseImageListPageComponent } from '@components/stories/components/course-image-list-page/course-image-list-page';
import { CoreSitesListWrapperComponent } from './sites-list-wrapper/sites-list-wrapper';
import { CoreDirectivesModule } from '@directives/directives.module';

@NgModule({
declarations: [
CoreCourseImageCardsPageComponent,
CoreCourseImageListPageComponent,
CoreEmptyBoxPageComponent,
CoreEmptyBoxWrapperComponent,
CoreSitesListWrapperComponent,
],
imports: [
CommonModule,
StorybookModule,
CoreDirectivesModule,
CoreComponentsModule,
CoreSearchComponentsModule,
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<ion-app>
<ion-content class="limited-width">
<core-sites-list *ngIf="accountsList" [accountsList]="accountsList" [sitesClickable]="sitesClickable"
[currentSiteClickable]="currentSiteClickable" (onSiteClicked)="siteClicked($event)">

<ng-template *ngIf="extraText !== 'none'" #siteLabel let-site="site">
<p *ngIf="extraText === 'text'">Extra text for user {{ site.fullname }}</p>
<ion-badge *ngIf="extraText === 'badge'" color="light">{{ site.badge }} MB</ion-badge>
</ng-template>

<ng-template #siteItem let-site="site">
<ion-button *ngIf="extraDetails === 'delete-button'" fill="clear" color="danger" slot="end">
<ion-icon name="fas-trash" slot="icon-only"></ion-icon>
</ion-button>

<ion-badge *ngIf="extraDetails === 'badge'" slot="end">
<span>{{site.badge}}</span>
</ion-badge>
</ng-template>

</core-sites-list>
</ion-content>
</ion-app>
Loading

0 comments on commit ee9daad

Please sign in to comment.