Merge pull request #3827 from crazyserver/MOBILE-4362-2

Mobile 4362 2
main
Dani Palou 2023-10-19 17:48:51 +02:00 committed by GitHub
commit 32055bd8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 110 additions and 49 deletions

View File

@ -18,7 +18,7 @@
<core-loading [hideUntil]="loaded">
<ion-item *ngIf="showMyEntriesToggle">
<ion-label>{{ 'addon.blog.showonlyyourentries' | translate }}</ion-label>
<ion-toggle [(ngModel)]="onlyMyEntries" (ionChange)="onlyMyEntriesToggleChanged(onlyMyEntries)"></ion-toggle>
<ion-toggle [(ngModel)]="onlyMyEntries" (ionChange)="onlyMyEntriesToggleChanged(onlyMyEntries)" slot="end"></ion-toggle>
</ion-item>
<core-empty-box *ngIf="entries && entries.length == 0" icon="far-newspaper" [message]="'addon.blog.noentriesyet' | translate">
</core-empty-box>

View File

@ -363,7 +363,7 @@
<p class="item-heading">{{ 'addon.mod_assign.groupsubmissionsettings' | translate }}</p>
<p>{{ 'addon.mod_assign.applytoteam' | translate }}</p>
</ion-label>
<ion-toggle [(ngModel)]="grade.applyToAll"></ion-toggle>
<ion-toggle [(ngModel)]="grade.applyToAll" slot="end"></ion-toggle>
</ion-item>
<!-- Attempt status. -->
@ -387,7 +387,7 @@
</ion-item>
<ion-item *ngIf="canSaveGrades && allowAddAttempt">
<ion-label>{{ 'addon.mod_assign.addattempt' | translate }}</ion-label>
<ion-toggle [(ngModel)]="grade.addAttempt"></ion-toggle>
<ion-toggle [(ngModel)]="grade.addAttempt" slot="end"></ion-toggle>
</ion-item>
</ng-container>

View File

@ -19,7 +19,7 @@
<ion-item>
<ion-label>{{ 'addon.mod_chat.showincompletesessions' | translate }}</ion-label>
<ion-toggle [(ngModel)]="showAll" (ionChange)="reloadSessions()"></ion-toggle>
<ion-toggle [(ngModel)]="showAll" (ionChange)="reloadSessions()" slot="end"></ion-toggle>
</ion-item>
<ion-card *ngFor="let session of sessions.items" (click)="sessions.select(session)" button

View File

@ -13,7 +13,7 @@
<ion-content>
<ion-item>
<ion-label>{{ 'addon.mod_data.advancedsearch' | translate }}</ion-label>
<ion-toggle [(ngModel)]="search.searchingAdvanced"></ion-toggle>
<ion-toggle [(ngModel)]="search.searchingAdvanced" slot="end"></ion-toggle>
</ion-item>
<form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm" #searchFormEl>
<ion-list class="ion-no-margin">

View File

@ -43,7 +43,7 @@
<div *ngIf="advanced" id="addon-mod-forum-new-discussion-advanced">
<ion-item *ngIf="showGroups && groupIds.length > 1 && accessInfo.cancanposttomygroups">
<ion-label>{{ 'addon.mod_forum.posttomygroups' | translate }}</ion-label>
<ion-toggle [(ngModel)]="newDiscussion.postToAllGroups" name="postallgroups"></ion-toggle>
<ion-toggle [(ngModel)]="newDiscussion.postToAllGroups" name="postallgroups" slot="end"></ion-toggle>
</ion-item>
<ion-item *ngIf="showGroups" class="core-edit-set-group">
<ion-label>{{ 'addon.mod_forum.group' | translate }}</ion-label>
@ -58,11 +58,11 @@
</ion-item>
<ion-item>
<ion-label>{{ 'addon.mod_forum.discussionsubscription' | translate }}</ion-label>
<ion-toggle [(ngModel)]="newDiscussion.subscribe" name="subscribe"></ion-toggle>
<ion-toggle [(ngModel)]="newDiscussion.subscribe" name="subscribe" slot="end"></ion-toggle>
</ion-item>
<ion-item *ngIf="canPin">
<ion-label>{{ 'addon.mod_forum.discussionpinned' | translate }}</ion-label>
<ion-toggle [(ngModel)]="newDiscussion.pin" name="pin"></ion-toggle>
<ion-toggle [(ngModel)]="newDiscussion.pin" name="pin" slot="end"></ion-toggle>
</ion-item>
<core-attachments *ngIf="canCreateAttachments && forum && forum.maxattachments > 0" [files]="newDiscussion.files"
[maxSize]="forum.maxbytes" [maxSubmissions]="forum.maxattachments" [component]="component" [componentId]="forum.cmid"

View File

@ -62,16 +62,16 @@
</ion-item-divider>
<ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.entryusedynalink' | translate }}</ion-label>
<ion-toggle [(ngModel)]="data.usedynalink" name="usedynalink"></ion-toggle>
<ion-toggle [(ngModel)]="data.usedynalink" name="usedynalink" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.casesensitive' | translate }}</ion-label>
<ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.casesensitive" name="casesensitive">
<ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.casesensitive" name="casesensitive" slot="end">
</ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-label>{{ 'addon.mod_glossary.fullmatch' | translate }}</ion-label>
<ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.fullmatch" name="fullmatch"></ion-toggle>
<ion-toggle [disabled]="!data.usedynalink" [(ngModel)]="data.fullmatch" name="fullmatch" slot="end"></ion-toggle>
</ion-item>
</ng-container>
<ion-button class="ion-margin" expand="block" [disabled]="!data.concept || !data.definition" (click)="save()">

View File

@ -56,6 +56,7 @@ export class AddonModLabelModuleHandlerService extends CoreModuleHandlerBase imp
title,
a11yTitle: '',
class: 'addon-mod-label-handler',
hasCustomCmListItem: true,
};
}

View File

@ -105,9 +105,11 @@
</ion-label>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="access.canpublishsubmissions">
<ion-label>{{ 'addon.mod_workshop.publishsubmission' | translate }}</ion-label>
<ion-toggle formControlName="published"></ion-toggle>
<p class="item-help">{{ 'addon.mod_workshop.publishsubmission_help' | translate }}</p>
<ion-label>
<p class="item-heading">{{ 'addon.mod_workshop.publishsubmission' | translate }}</p>
<p>{{ 'addon.mod_workshop.publishsubmission_help' | translate }}</p>
</ion-label>
<ion-toggle formControlName="published" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap">

View File

@ -449,7 +449,14 @@ export class AddonModWorkshopHelperProvider {
* @returns Promise resolved with the files.
*/
async applyOfflineData(
submission: AddonModWorkshopSubmissionDataWithOfflineData = {
submission?: AddonModWorkshopSubmissionDataWithOfflineData,
actions: AddonModWorkshopOfflineSubmission[] = [],
): Promise<AddonModWorkshopSubmissionDataWithOfflineData | undefined> {
if (actions.length === 0) {
return submission;
}
const baseSubmission = submission ?? {
id: 0,
workshopid: 0,
title: '',
@ -462,12 +469,7 @@ export class AddonModWorkshopHelperProvider {
attachment: 0,
published: false,
late: 0,
},
actions: AddonModWorkshopOfflineSubmission[] = [],
): Promise<AddonModWorkshopSubmissionDataWithOfflineData | undefined> {
if (actions.length === 0) {
return submission;
}
};
let attachmentsId: CoreFileUploaderStoreFilesResult | undefined;
const workshopId = actions[0].workshopid;
@ -476,17 +478,17 @@ export class AddonModWorkshopHelperProvider {
switch (action.action) {
case AddonModWorkshopAction.ADD:
case AddonModWorkshopAction.UPDATE:
submission.title = action.title;
submission.content = action.content;
submission.title = action.title;
submission.courseid = action.courseid;
submission.submissionmodified = action.timemodified / 1000;
submission.offline = true;
baseSubmission.title = action.title;
baseSubmission.content = action.content;
baseSubmission.title = action.title;
baseSubmission.courseid = action.courseid;
baseSubmission.submissionmodified = action.timemodified / 1000;
baseSubmission.offline = true;
attachmentsId = action.attachmentsid as CoreFileUploaderStoreFilesResult;
break;
case AddonModWorkshopAction.DELETE:
submission.deleted = true;
submission.submissionmodified = action.timemodified / 1000;
baseSubmission.deleted = true;
baseSubmission.submissionmodified = action.timemodified / 1000;
break;
default:
}
@ -494,13 +496,13 @@ export class AddonModWorkshopHelperProvider {
// Check offline files for latest attachmentsid.
if (attachmentsId) {
submission.attachmentfiles =
baseSubmission.attachmentfiles =
await this.getSubmissionFilesFromOfflineFilesObject(attachmentsId, workshopId);
} else {
submission.attachmentfiles = [];
baseSubmission.attachmentfiles = [];
}
return submission;
return baseSubmission;
}
/**

View File

@ -49,13 +49,14 @@ Feature: Test basic usage of workshop activity in app
Given I entered the workshop activity "workshop" on course "Course 1" as "student1" in the app
Then I should find "Task to do" within "Submit your work" "ion-item" in the app
When I press "Edit submission" in the app
When I press "Add submission" in the app
And I set the field "Title" to "The Answer" in the app
And I set the field "Submission content" to "42" in the app
And I press "Save" in the app
Then I should find "Task done" within "Submit your work" "ion-item" in the app
And I should find "The Answer" in the app
And I should find "42" in the app
And I should find "Edit submission" in the app
Given I entered the workshop activity "workshop" on course "Course 1" as "teacher1" in the app
When I pull to refresh in the app

View File

@ -45,6 +45,7 @@ export class CoreModuleHandlerBase implements Partial<CoreCourseModuleHandler> {
title: module.name,
class: 'addon-mod_' + module.modname + '-handler',
showDownloadButton: true,
hasCustomCmListItem: false,
action: async (
event: Event,
module: CoreCourseModuleData,

View File

@ -1,7 +1,7 @@
<ion-card *ngIf="module.handlerData && module.visibleoncoursepage !== 0"
class="activity-card core-course-module-handler {{module.handlerData.class}}" [class.core-course-module-with-view]="moduleHasView"
[class.item-dimmed]="module.visible === 0 || module.uservisible === false" (click)="moduleClicked($event)"
[button]="module.handlerData.action && module.uservisible"
[class.item-dimmed]="module.visible === 0 || module.uservisible === false" [class.activityinline]="activityInline"
(click)="moduleClicked($event)" [button]="module.handlerData.action && module.uservisible"
[attr.aria-label]="module.handlerData.a11yTitle ? module.handlerData.a11yTitle : null" id="core-course-module-{{module.id}}">
<ng-container *ngIf="!module.handlerData.loading">
<ion-item class="ion-text-wrap">

View File

@ -7,6 +7,10 @@
ion-card {
margin: var(--vertical-margin) var(--horizontal-margin);
&.activityinline {
border: 0px;
}
}
ion-item {
@ -94,7 +98,8 @@
}
}
.core-module-description ::ng-deep img {
.core-module-description ::ng-deep img,
.activity-title .item-heading core-format-text ::ng-deep img {
border-radius: var(--radius-lg);
}
@ -185,4 +190,9 @@
&.indented + ::ng-deep core-course-module.indented ion-card {
border-top: 1px solid var(--border-color);
}
// Hide download folder icon meanwhile MOBILE-4147 is not solved
core-format-text.core-module-description ::ng-deep .description-inner .navitem {
display: none;
}
}

View File

@ -65,6 +65,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
prefetchStatusIcon$ = new BehaviorSubject<string>(''); // Module prefetch status icon.
prefetchStatusText$ = new BehaviorSubject<string>(''); // Module prefetch status text.
moduleHasView = true;
activityInline = false;
protected prefetchHandler?: CoreCourseModulePrefetchHandler;
@ -101,6 +102,18 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
this.moduleHasView = CoreCourse.moduleHasView(this.module);
if (
this.module.handlerData.hasCustomCmListItem &&
(!this.showAvailability || !this.module.availabilityinfo) &&
(!this.showCompletion || !this.hasCompletion) &&
(!this.showActivityDates || !this.module.dates?.length) &&
!this.module.groupmode &&
!(this.module.visible === 0) &&
!(this.module.visible !== 0 && this.module.isStealth)
) {
this.activityInline = true;
}
if (this.showDownloadStatus && this.module.handlerData.showDownloadButton) {
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course);
this.updateModuleStatus(status);

View File

@ -1784,6 +1784,7 @@ export type CoreCourseGetContentsWSModule = {
completion?: CoreCourseModuleCompletionTracking; // Type of completion tracking: 0 means none, 1 manual, 2 automatic.
completiondata?: CoreCourseModuleWSCompletionData; // Module completion data.
contents?: CoreCourseModuleContentFile[];
groupmode?: number; // @since 4.3. Group mode value
downloadcontent?: number; // @since 4.0 The download content value.
dates?: {
label: string;

View File

@ -168,6 +168,14 @@ export interface CoreCourseModuleHandlerData {
*/
showDownloadButton?: boolean;
/**
* Wether activity has the custom cmlist item flag enabled.
*
* Activities like label uses this flag to indicate that it should be
* displayed as a custom course item instead of a tipical activity card.
*/
hasCustomCmListItem?: boolean;
/**
* The buttons to display in the module item.
*

View File

@ -22,19 +22,20 @@
<p class="item-heading">Text direction</p>
<p>{{ direction }}</p>
</ion-label>
<ion-toggle [(ngModel)]="rtl" (ionChange)="RTLChanged()"></ion-toggle>
<ion-toggle [(ngModel)]="rtl" (ionChange)="RTLChanged()" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-label>
<p class="item-heading">Force safe area margins</p>
</ion-label>
<ion-toggle [(ngModel)]="forceSafeAreaMargins" (ionChange)="safeAreaChanged()"></ion-toggle>
<ion-toggle [(ngModel)]="forceSafeAreaMargins" (ionChange)="safeAreaChanged()" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="stagingSitesCount && enableStagingSites !== undefined">
<ion-label>
<h2>Enable staging sites ({{stagingSitesCount}})</h2>
</ion-label>
<ion-toggle [(ngModel)]="enableStagingSites" (ionChange)="setEnabledStagingSites($event.detail.checked)"></ion-toggle>
<ion-toggle [(ngModel)]="enableStagingSites" (ionChange)="setEnabledStagingSites($event.detail.checked)"
slot="end"></ion-toggle>
</ion-item>
<ng-container *ngIf="siteId">
<ion-item class="ion-text-wrap">
@ -42,14 +43,14 @@
<p class="item-heading">Enable remote styles <ion-badge>{{remoteStylesCount}}</ion-badge>
</p>
</ion-label>
<ion-toggle [(ngModel)]="remoteStyles" (ionChange)="remoteStylesChanged()"></ion-toggle>
<ion-toggle [(ngModel)]="remoteStyles" (ionChange)="remoteStylesChanged()" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-label>
<p class="item-heading">Enable site plugin styles <ion-badge>{{pluginStylesCount}}</ion-badge>
</p>
</ion-label>
<ion-toggle [(ngModel)]="pluginStyles" (ionChange)="pluginStylesChanged()"></ion-toggle>
<ion-toggle [(ngModel)]="pluginStyles" (ionChange)="pluginStylesChanged()" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="userToursEnabled">
<ion-label>

View File

@ -57,7 +57,7 @@
<p class="item-heading">{{ 'core.settings.enablerichtexteditor' | translate }}</p>
<p>{{ 'core.settings.enablerichtexteditordescription' | translate }}</p>
</ion-label>
<ion-toggle [(ngModel)]="richTextEditor" (ionChange)="richTextEditorChanged($event)"></ion-toggle>
<ion-toggle [(ngModel)]="richTextEditor" (ionChange)="richTextEditorChanged($event)" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="displayIframeHelp">
<ion-label>
@ -73,14 +73,14 @@
<p class="item-heading">{{ 'core.settings.debugdisplay' | translate }}</p>
<p>{{ 'core.settings.debugdisplaydescription' | translate }}</p>
</ion-label>
<ion-toggle [(ngModel)]="debugDisplay" (ionChange)="debugDisplayChanged($event)"></ion-toggle>
<ion-toggle [(ngModel)]="debugDisplay" (ionChange)="debugDisplayChanged($event)" slot="end"></ion-toggle>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="analyticsSupported">
<ion-label>
<p class="item-heading">{{ 'core.settings.enableanalytics' | translate }}</p>
<p>{{ 'core.settings.enableanalyticsdescription' | translate }}</p>
</ion-label>
<ion-toggle [(ngModel)]="analyticsEnabled" (ionChange)="analyticsEnabledChanged($event)"></ion-toggle>
<ion-toggle [(ngModel)]="analyticsEnabled" (ionChange)="analyticsEnabledChanged($event)" slot="end"></ion-toggle>
</ion-item>
</ion-list>
</ion-content>

View File

@ -26,7 +26,7 @@
<p class="item-heading">{{ handler.title | translate}}</p>
</ion-label>
<ion-toggle *ngIf="handler.toggle" [(ngModel)]="handler.toggleChecked"
(ionChange)="handler.toggle($event.detail.checked)">
(ionChange)="handler.toggle($event.detail.checked)" slot="end">
</ion-toggle>
</ion-item>
</ion-list>

View File

@ -90,6 +90,7 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
icon: CoreCourse.getModuleIconSrc(module.modname, icon),
class: this.handlerSchema.displaydata?.class,
showDownloadButton: showDowloadButton !== undefined ? showDowloadButton : hasOffline,
hasCustomCmListItem: this.handlerSchema.hascustomcmlistitem ?? false,
};
if (this.handlerSchema.method) {

View File

@ -895,6 +895,7 @@ export type CoreSitePluginsCourseModuleHandlerData = CoreSitePluginsHandlerCommo
supportedfeatures?: Record<string, unknown>;
manualcompletionalwaysshown?: boolean;
nolinkhandlers?: boolean;
hascustomcmlistitem?: boolean;
};
/**

View File

@ -113,10 +113,6 @@ core-format-text {
padding: 10px 0;
}
.btn-link {
background: none;
}
}
@keyframes loading {
@ -679,6 +675,29 @@ core-rich-text-editor .core-rte-editor {
background-color: var(--#{$color-name});
}
}
.btn-link {
background: none;
}
button, .btn {
margin: 4px 8px;
padding-left: 12px;
padding-right: 12px;
border-radius: var(--core-input-radius);
a {
color: inherit;
}
}
@each $color-name, $unused in $colors {
.btn.btn-#{$color-name} {
--color-base: var(--#{$color-name});
color: var(--#{$color-name}-shade);
border-color: var(--color-base);
background-color: var(--#{$color-name}-tint);
}
}
}
// h1 is too big and ugly, reduce size when loading.