MOBILE-3814 module: Add completion basic mode to use it bellow title
parent
59b1d37f8b
commit
926f2508d1
|
@ -1,38 +1,63 @@
|
|||
<div *ngIf="showCompletionConditions && completion && completion.isautomatic" class="core-module-automatic-completion-conditions"
|
||||
role="list" [attr.aria-label]="'core.course.completionrequirements' | translate:{ $a: moduleName }">
|
||||
<ng-container *ngIf="completion">
|
||||
<ng-container *ngIf="showCompletionConditions && completion.isautomatic">
|
||||
<div *ngIf="mode == 'full'" class="core-module-automatic-completion-conditions" role="list"
|
||||
[attr.aria-label]="'core.course.completionrequirements' | translate:{ $a: moduleName }">
|
||||
|
||||
<ng-container *ngIf="completion.istrackeduser">
|
||||
<ng-container *ngFor="let rule of details">
|
||||
<ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
||||
<ion-label><strong>{{ 'core.course.completion_automatic:done' | translate }}</strong> {{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
<ng-container *ngIf="completion.istrackeduser">
|
||||
<ng-container *ngFor="let rule of details">
|
||||
<ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-icon name="fas-check" [attr.aria-label]="'core.course.completion_automatic:done' | translate "></ion-icon>
|
||||
<ion-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
|
||||
<ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
||||
<ion-label><strong>{{ 'core.course.completion_automatic:failed' | translate }}</strong> {{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
<ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-icon name="fas-times" [attr.aria-label]="'core.course.completion_automatic:failed' | translate "></ion-icon>
|
||||
<ion-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
|
||||
<ion-chip *ngIf="rule.statusincomplete" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-chip *ngIf="rule.statusincomplete" color="dark" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||
<ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon>
|
||||
<ion-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!completion.istrackeduser">
|
||||
<ion-chip *ngFor="let rule of details" role="listitem">
|
||||
<ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon>
|
||||
<ion-label>
|
||||
{{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="mode == 'basic' && completion.istrackeduser">
|
||||
<ion-chip class="completioninfo completion_incomplete" *ngIf="completionStatus === 0" color="dark">
|
||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
||||
<ion-label><strong>{{ 'core.course.completion_automatic:todo' | translate }}</strong> {{ rule.rulevalue.description }}
|
||||
<ion-label>
|
||||
{{ 'core.course.todo' | translate }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
<ion-chip class="completioninfo completion_complete" *ngIf="completionStatus === 1 || completionStatus === 2" color="success">
|
||||
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{'core.course.done' | translate }}</ion-label>
|
||||
</ion-chip>
|
||||
<ion-chip class="completioninfo completion_fail" *ngIf="completionStatus === 3" color="danger">
|
||||
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{'core.course.failed' | translate }}</ion-label>
|
||||
</ion-chip>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!completion.istrackeduser">
|
||||
<ion-chip *ngFor="let rule of details" role="listitem">
|
||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<strong>{{ 'core.course.completion_automatic:todo' | translate }}</strong> {{ rule.rulevalue.description }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<core-course-module-manual-completion *ngIf="showManualCompletion" [completion]="completion" [moduleName]="moduleName"
|
||||
(completionChanged)="completionChanged.emit($event)">
|
||||
</core-course-module-manual-completion>
|
||||
<core-course-module-manual-completion *ngIf="showManualCompletion" [completion]="completion" [moduleName]="moduleName"
|
||||
(completionChanged)="completionChanged.emit($event)" [mode]="mode">
|
||||
</core-course-module-manual-completion>
|
||||
</ng-container>
|
||||
|
|
|
@ -15,7 +15,12 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
|
||||
import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion';
|
||||
import { CoreCourseModuleCompletionStatus, CoreCourseModuleWSRuleDetails } from '@features/course/services/course';
|
||||
import {
|
||||
CoreCourseCompletionMode,
|
||||
CoreCourseModuleCompletionStatus,
|
||||
CoreCourseModuleCompletionTracking,
|
||||
CoreCourseModuleWSRuleDetails,
|
||||
} from '@features/course/services/course';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
|
@ -37,9 +42,11 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
|||
|
||||
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
||||
@Input() showManualCompletion = false; // Whether to show manual completion.
|
||||
@Input() mode: CoreCourseCompletionMode = CoreCourseCompletionMode.FULL; // Show full completion status or a basic mode.
|
||||
|
||||
details?: CompletionRule[];
|
||||
accessibleDescription: string | null = null;
|
||||
completionStatus?: CoreCourseModuleCompletionStatus;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -49,6 +56,11 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
|||
return;
|
||||
}
|
||||
|
||||
this.completionStatus = !this.completion?.istrackeduser ||
|
||||
this.completion.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE
|
||||
? undefined
|
||||
: this.completion.state;
|
||||
|
||||
// Format rules.
|
||||
this.details = await Promise.all(this.completion.details.map(async (rule: CompletionRule) => {
|
||||
rule.statuscomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
|
||||
|
@ -57,8 +69,8 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
|||
rule.statusincomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE;
|
||||
rule.accessibleDescription = null;
|
||||
|
||||
if (this.completion!.overrideby) {
|
||||
const fullName = await CoreUser.getUserFullNameWithDefault(this.completion!.overrideby, this.completion!.courseId);
|
||||
if (this.completion?.overrideby) {
|
||||
const fullName = await CoreUser.getUserFullNameWithDefault(this.completion.overrideby, this.completion.courseId);
|
||||
|
||||
const setByData = {
|
||||
$a: {
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
<div *ngIf="completion && !completion.isautomatic" class="core-module-manual-completion">
|
||||
|
||||
<ng-container *ngIf="completion && !completion.isautomatic">
|
||||
<ng-container *ngIf="completion.istrackeduser">
|
||||
<ng-container *ngIf="completion.state">
|
||||
<ion-button color="success" fill="outline" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
||||
class="ion-text-wrap">
|
||||
<ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.course.completion_manual:done' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!completion.state">
|
||||
<ion-button color="dark" fill="outline" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
||||
class="ion-text-wrap">
|
||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!completion.istrackeduser">
|
||||
<ion-button disabled="true" color="dark" fill="outline" class="ion-text-wrap">
|
||||
<ion-button *ngIf="completion.state" color="success" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
||||
class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||
<ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.course.completion_manual:done' | translate }}
|
||||
</ion-button>
|
||||
<ion-button *ngIf="!completion.state" color="dark" fill="outline" [attr.aria-label]="accessibleDescription"
|
||||
(click)="completionClicked($event)" class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!completion.istrackeduser">
|
||||
<ion-button disabled="true" color="dark" fill="outline" class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChange } from '@angular/core';
|
||||
import { CoreCourseCompletionType } from '@features/course/services/course';
|
||||
|
||||
import { CoreCourseCompletionMode, CoreCourseCompletionType } from '@features/course/services/course';
|
||||
import { CoreCourseHelper, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { Translate } from '@singletons';
|
||||
|
@ -31,6 +30,7 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
|
|||
|
||||
@Input() completion?: CoreCourseModuleCompletionData; // The completion status.
|
||||
@Input() moduleName?: string; // The name of the module this completion affects.
|
||||
@Input() mode: CoreCourseCompletionMode = CoreCourseCompletionMode.FULL; // Show full completion status or a basic mode.
|
||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when completion changes.
|
||||
|
||||
accessibleDescription: string | null = null;
|
||||
|
@ -97,6 +97,9 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
|
|||
return;
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
await CoreCourseHelper.changeManualCompletion(this.completion, event);
|
||||
|
||||
// @deprecated MANUAL_COMPLETION_CHANGED is deprecated since 4.0 use COMPLETION_CHANGED instead.
|
||||
|
|
|
@ -18,21 +18,12 @@
|
|||
[courseId]="module.course" [attr.aria-label]="module.handlerData.a11yTitle + ', ' + modNameTranslated">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<ion-chip class="completioninfo completion_incomplete" *ngIf="completionStatus === 0">
|
||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
{{ 'core.course.todo' | translate }}
|
||||
</ion-label>
|
||||
</ion-chip>
|
||||
<ion-chip class="completioninfo completion_complete" *ngIf="completionStatus === 1 || completionStatus === 2"
|
||||
color="success">
|
||||
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{'core.course.done' | translate }}</ion-label>
|
||||
</ion-chip>
|
||||
<ion-chip class="completioninfo completion_fail" *ngIf="completionStatus === 3" color="danger">
|
||||
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{'core.course.failed' | translate }}</ion-label>
|
||||
</ion-chip>
|
||||
|
||||
<!-- Basic module completion. -->
|
||||
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
||||
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)" mode="basic">
|
||||
</core-course-module-completion>
|
||||
|
||||
<ion-chip *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor"
|
||||
class="ion-text-wrap ion-text-start" [outline]="true">
|
||||
|
@ -76,10 +67,9 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Module completion. -->
|
||||
<!-- Module completion. Only auto conditions-->
|
||||
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
||||
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)">
|
||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions">
|
||||
</core-course-module-completion>
|
||||
|
||||
<div *ngIf="module.completiondata?.offline">
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
}
|
||||
|
||||
.core-course-module-info {
|
||||
ion-badge {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.core-module-availabilityinfo {
|
||||
font-size: 90%;
|
||||
ul {
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
CoreCourseModuleCompletionData,
|
||||
CoreCourseSection,
|
||||
} from '@features/course/services/course-helper';
|
||||
import { CoreCourse, CoreCourseModuleCompletionStatus, CoreCourseModuleCompletionTracking } from '@features/course/services/course';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,6 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
hasInfo = false;
|
||||
showLegacyCompletion = false; // Whether to show module completion in the old format.
|
||||
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
||||
completionStatus?: CoreCourseModuleCompletionStatus;
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
|
@ -62,19 +61,11 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
||||
this.completionStatus = this.module.completiondata === undefined ||
|
||||
!this.module.completiondata?.istrackeduser ||
|
||||
this.module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE
|
||||
? undefined
|
||||
: this.module.completiondata.state;
|
||||
|
||||
this.hasInfo = !!(
|
||||
this.module.description ||
|
||||
(this.showActivityDates && this.module.dates && this.module.dates.length) ||
|
||||
(this.module.completiondata &&
|
||||
((this.showManualCompletion && !this.module.completiondata.isautomatic) ||
|
||||
(this.showCompletionConditions && this.module.completiondata.isautomatic))
|
||||
) ||
|
||||
(this.module.completiondata && this.showCompletionConditions && this.module.completiondata.isautomatic) ||
|
||||
this.module.completiondata?.offline ||
|
||||
(this.module.visible === 0 && (!this.section || this.section.visible)) ||
|
||||
(this.module.visible !== 0 && this.module.isStealth) ||
|
||||
|
|
|
@ -76,6 +76,11 @@ export enum CoreCourseCompletionType {
|
|||
AUTO = 1,
|
||||
}
|
||||
|
||||
export enum CoreCourseCompletionMode {
|
||||
FULL = 'full',
|
||||
BASIC = 'basic',
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion tracking valid values.
|
||||
*/
|
||||
|
|
|
@ -184,44 +184,6 @@ ion-app.ios ion-header ion-title {
|
|||
white-space: normal !important;
|
||||
}
|
||||
|
||||
ion-button core-format-text .core-format-text-content {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ion-button > * {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
ion-button.ion-text-wrap {
|
||||
white-space: normal;
|
||||
core-format-text .core-format-text-content {
|
||||
white-space: normal;
|
||||
display: contents;
|
||||
}
|
||||
|
||||
& > * {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
ion-button.button-outline {
|
||||
--background: var(--contrast-background);
|
||||
}
|
||||
|
||||
ion-button ion-spinner {
|
||||
--color: inherit !important;
|
||||
}
|
||||
|
||||
ion-button:not(.button-has-icon-only) > ion-icon {
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
@each $color-name, $unused in $colors {
|
||||
.text-#{$color-name},
|
||||
p.text-#{$color-name} {
|
||||
|
@ -293,10 +255,6 @@ ion-icon {
|
|||
}
|
||||
}
|
||||
|
||||
ion-button.button-small ion-icon.faicon[slot] {
|
||||
font-size: 1.5em !important;
|
||||
}
|
||||
|
||||
// Buttons.
|
||||
ion-button,
|
||||
ion-fab-button,
|
||||
|
@ -306,10 +264,58 @@ button,
|
|||
min-width: var(--a11y-min-target-size);
|
||||
}
|
||||
|
||||
ion-button.button-outline {
|
||||
--border-width: 1px;
|
||||
--background: var(--contrast-background);
|
||||
}
|
||||
|
||||
ion-button.button-solid {
|
||||
--box-shadow: none;
|
||||
}
|
||||
|
||||
ion-button core-format-text .core-format-text-content {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
ion-button > * {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
ion-button.ion-text-wrap {
|
||||
white-space: normal;
|
||||
core-format-text .core-format-text-content {
|
||||
white-space: normal;
|
||||
display: contents;
|
||||
}
|
||||
|
||||
& > * {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
ion-button ion-spinner {
|
||||
--color: inherit !important;
|
||||
}
|
||||
|
||||
ion-button:not(.button-has-icon-only):not(.button-small) > ion-icon {
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
ion-button.button.button-clear.button-has-icon-only {
|
||||
--border-radius: var(--huge-radius);
|
||||
}
|
||||
|
||||
ion-button.button.button-solid,
|
||||
ion-button.button.button-outline {
|
||||
--border-radius: var(--small-radius);
|
||||
}
|
||||
|
||||
// Clear buttons will be black.
|
||||
ion-button.button-clear {
|
||||
--primary: var(--primary);
|
||||
|
@ -877,12 +883,14 @@ ion-badge {
|
|||
border-radius: var(--big-radius);
|
||||
}
|
||||
|
||||
ion-chip {
|
||||
ion-chip,
|
||||
ion-button.chip {
|
||||
line-height: 1.1;
|
||||
font-size: 12px;
|
||||
padding: 4px 8px;
|
||||
min-height: 24px;
|
||||
height: auto;
|
||||
text-transform: none;
|
||||
margin: 4px;
|
||||
font-weight: normal;
|
||||
|
||||
ion-icon {
|
||||
font-size: 16px;
|
||||
|
@ -890,6 +898,18 @@ ion-chip {
|
|||
@include margin(0, 8px, 0, 0);
|
||||
}
|
||||
|
||||
ion-label {
|
||||
white-space: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
ion-chip {
|
||||
line-height: 1.1;
|
||||
font-size: 12px;
|
||||
padding: 4px 8px;
|
||||
min-height: 24px;
|
||||
height: auto;
|
||||
|
||||
&.ion-color {
|
||||
background: var(--ion-color-tint);
|
||||
&.chip-outline {
|
||||
|
@ -899,9 +919,7 @@ ion-chip {
|
|||
}
|
||||
}
|
||||
|
||||
ion-label {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ion-searchbar {
|
||||
|
|
Loading…
Reference in New Issue