From 6dae1d1dd2516af644c2c9b4786eb9c8f8625f0c Mon Sep 17 00:00:00 2001 From: Damien Leroy Date: Fri, 13 Sep 2024 11:38:17 +0200 Subject: [PATCH 1/4] convert item-by-id to new control flows --- src/app/items/item-by-id.component.html | 291 ++++++++++++------------ src/app/items/item-by-id.component.ts | 3 +- 2 files changed, 152 insertions(+), 142 deletions(-) diff --git a/src/app/items/item-by-id.component.html b/src/app/items/item-by-id.component.html index 8401954fb..16303fda4 100644 --- a/src/app/items/item-by-id.component.html +++ b/src/app/items/item-by-id.component.html @@ -1,27 +1,30 @@ - - +@if (state$ | async; as state) { + @if (state.isReady && state.data; as itemData) { - - - - - - - + @if (!(fullFrameContent$ | async)) { + + } + @if (showAccessCodeField$ | async) { + + } + @if (observedGroup$ | async; as observedGroup) { + + } + @if (!!(shouldDisplayTabBar$ | async) && !fullFrameContentDisplayed) { + + }
- - - Unable to load the answer - - - Unable to load the answer, back to the regular task page. - - -

{{ errorMessageContactUs }}

-
- - + > + @if (currentTab?.isTaskTab || itemContentComponent?.isTaskLoaded() || currentTab?.tag === 'alg-content' || currentTab?.tag === 'alg-children-edit') { + @if (answerLoadingError$ | async; as error) { + + @if (!error.fallbackLink) { + Unable to load the answer + } @else { + + Unable to load the answer, back to the regular task page. + + } + @if (!error.isForbidden) { +

{{ errorMessageContactUs }}

+ } +
+ } @else { -
- -
+ @if (taskConfig && taskConfig.readOnly && currentTab && ['alg-content', 'task'].includes(currentTab.tag)) { +
+ @if (!!currentTab?.isTaskTab && taskConfig.initialAnswer) { + + } +
+ }
-
- -
- - - - - -
-

- Saving answer before loading submission... - - -

-
- - - - - - - + } + @if (currentTab && [ 'alg-log', 'alg-chapter-progress'].includes(currentTab.tag)) { + @if ((!isObserving && (itemData.item.permissions | allowsViewingContent)) || (itemData.item.permissions | allowsWatchingResults) ) { + @if ((savingAnswer$ | async) ?? false) { +
+

+ Saving answer before loading submission... + + +

+
+ } + @if (currentTab?.tag ==='alg-log') { +
-
- -
- -

+ > + } + @if (currentTab?.tag === 'alg-chapter-progress') { + @if (isObserving) { + + } + @if (!isObserving) { + + } + } + } @else { + @if (isObserving) { +

You are not allowed to view the progress of other users on this content.

-

+ } + @else { +

You are not allowed to view this content.

-
-
- - + } + } + } + @if (currentTab?.tag ==='alg-dependencies') { - - - + } + @if (currentTab?.tag ==='alg-parameters') { - - - - - + } + @if (currentTab?.tag === 'alg-forum') { + @if ((userProfile$ | async)?.tempUser || !showItemThreadWidget) { + + } @else { - - + } + }
-
- - - - -

+ } + @if (state.isFetching) { + + } + @if (state.isError) { + @if (state.error && ($any(state.error).status === 403 || $any(state.error).status === 404)) { +

This content does not exist or you are not allowed to view it.

-

Error while loading the item.

+ } @else { +

Error while loading the item.

+ }

Go back to the + > home page

-
-
- - -

You do not appear to be connected to the Internet, if you leave this task you may loose your progress. Are you sure you want to continue?

- - - - -
+ } +} + +@if (saveBeforeUnloadError$ | async) { + +

You do not appear to be connected to the Internet, if you leave this task you may loose your progress. Are you sure you want to continue?

+ + + + +
+} diff --git a/src/app/items/item-by-id.component.ts b/src/app/items/item-by-id.component.ts index fe366b4e9..97f841b66 100644 --- a/src/app/items/item-by-id.component.ts +++ b/src/app/items/item-by-id.component.ts @@ -57,7 +57,7 @@ import { TabBarComponent } from 'src/app/ui-components/tab-bar/tab-bar.component import { ItemPermissionsComponent } from './containers/item-permissions/item-permissions.component'; import { AccessCodeViewComponent } from 'src/app/containers/access-code-view/access-code-view.component'; import { ItemHeaderComponent } from './containers/item-header/item-header.component'; -import { NgIf, AsyncPipe, NgClass } from '@angular/common'; +import { AsyncPipe, NgClass } from '@angular/common'; import { Store } from '@ngrx/store'; import { fromForum } from '../forum/store'; import { isNotNull } from '../utils/null-undefined-predicates'; @@ -79,7 +79,6 @@ const itemBreadcrumbCat = $localize`Items`; providers: [ InitialAnswerDataSource, ItemTabs ], standalone: true, imports: [ - NgIf, NgClass, ItemHeaderComponent, AccessCodeViewComponent, From b7091793653689b0c6054574685cdfbf19fccc75 Mon Sep 17 00:00:00 2001 From: Damien Leroy Date: Fri, 13 Sep 2024 17:55:16 +0200 Subject: [PATCH 2/4] extra time page (temp while backend service are still missing) --- ...-extra-time-for-descendants.component.html | 56 +++++++++++++++++++ ...-extra-time-for-descendants.component.scss | 0 ...em-extra-time-for-descendants.component.ts | 50 +++++++++++++++++ .../item-extra-time.component.html | 29 ++++++++++ .../item-extra-time.component.scss | 0 .../item-extra-time.component.ts | 36 ++++++++++++ .../items/data-access/extra-time.service.ts | 35 ++++++++++++ src/app/items/item-by-id.component.html | 3 + src/app/items/item-by-id.component.ts | 2 + src/app/items/item-tabs.ts | 4 ++ src/app/items/item.routes.ts | 4 ++ .../models/item-grant-view-permission.ts | 9 +++ src/app/items/models/item-watch-permission.ts | 8 +++ src/app/items/models/time-limited-activity.ts | 46 +++++++++++++++ 14 files changed, 282 insertions(+) create mode 100644 src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html create mode 100644 src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.scss create mode 100644 src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.ts create mode 100644 src/app/items/containers/item-extra-time/item-extra-time.component.html create mode 100644 src/app/items/containers/item-extra-time/item-extra-time.component.scss create mode 100644 src/app/items/containers/item-extra-time/item-extra-time.component.ts create mode 100644 src/app/items/data-access/extra-time.service.ts create mode 100644 src/app/items/models/time-limited-activity.ts diff --git a/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html b/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html new file mode 100644 index 000000000..059159e65 --- /dev/null +++ b/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html @@ -0,0 +1,56 @@ +@let state = stateSignal(); + +

The resulting additional time of all descendants of this group:

+ +@if (state.isError) { + +} +@else if (state.data === undefined) { + +} +@else { + @let data = state.data; + + + @if (data && data.length > 0) { + + Name + Participant-specific + Total + + } + + + + + {{ descendantExtraTime.name }} + {{ descendantExtraTime.additionalTime }}s + {{ descendantExtraTime.totalAdditionalTime }}s + + + + + +
+ This group has no descendants. +
+ + +
+
+} diff --git a/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.scss b/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.ts b/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.ts new file mode 100644 index 000000000..5e382a7a6 --- /dev/null +++ b/src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.ts @@ -0,0 +1,50 @@ +import { ChangeDetectionStrategy, Component, input, OnDestroy } from '@angular/core'; +import { toObservable, toSignal } from '@angular/core/rxjs-interop'; +import { TableModule } from 'primeng/table'; +import { combineLatest, Subject, switchMap } from 'rxjs'; +import { ExtraTimeService } from 'src/app/items/data-access/extra-time.service'; +import { ErrorComponent } from 'src/app/ui-components/error/error.component'; +import { LoadingComponent } from 'src/app/ui-components/loading/loading.component'; +import { mapToFetchState } from 'src/app/utils/operators/state'; + +/** + * Display extra time given to group descendants on the given item. + * This component assumes the parent component has validated that the request is valid. + */ +@Component({ + selector: 'alg-item-extra-time-for-descendants', + standalone: true, + imports: [ + TableModule, + ErrorComponent, + LoadingComponent, + ], + templateUrl: './item-extra-time-for-descendants.component.html', + styleUrl: './item-extra-time-for-descendants.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ItemExtraTimeForDescendantsComponent implements OnDestroy { + itemId = input.required(); + groupId = input.required(); + + private refreshSubject = new Subject(); + + private state$ = combineLatest([ toObservable(this.itemId), toObservable(this.groupId) ]).pipe( + switchMap(([ itemId, groupId ]) => this.extraTimeService.getForGroupDescendant(itemId, groupId)), + mapToFetchState({ resetter: this.refreshSubject }), + ); + stateSignal = toSignal(this.state$, { requireSync: true }); + + constructor( + private extraTimeService: ExtraTimeService, + ){} + + ngOnDestroy(): void { + this.refreshSubject.complete(); + } + + refresh(): void { + this.refreshSubject.next(undefined); + } + +} diff --git a/src/app/items/containers/item-extra-time/item-extra-time.component.html b/src/app/items/containers/item-extra-time/item-extra-time.component.html new file mode 100644 index 000000000..55b87e732 --- /dev/null +++ b/src/app/items/containers/item-extra-time/item-extra-time.component.html @@ -0,0 +1,29 @@ +@let item = itemData().item; +@let observedGroupInfo = observedGroupInfoSignal(); + +@if (!(item | isTimeLimitedActivity) ) { + +} +@else if (!(item | canCurrentUserSetExtraTime)) { + +} +@else if (observedGroupInfo === null) { +

This activity has a duration of {{ item.duration | readable }}. To list and add extra-time to some groups or users, start observation on them.

+} +@else if (observedGroupInfo === undefined || false ) { + +} +@else if (false ) { + +} +@else { +

+ The extra-time given to "{{ observedGroupInfo.name }}" (i.e., including those given to its ancestors) is TODO, + the resulting extra-time (so including its ancestor groups) is TODO. +

+ + + @if (!(observedGroupInfo.route | isUser)) { + + } +} diff --git a/src/app/items/containers/item-extra-time/item-extra-time.component.scss b/src/app/items/containers/item-extra-time/item-extra-time.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/items/containers/item-extra-time/item-extra-time.component.ts b/src/app/items/containers/item-extra-time/item-extra-time.component.ts new file mode 100644 index 000000000..8e25afc98 --- /dev/null +++ b/src/app/items/containers/item-extra-time/item-extra-time.component.ts @@ -0,0 +1,36 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { ItemData } from '../../models/item-data'; +import { CanCurrentUserSetExtraTimePipe, IsTimeLimitedActivityPipe } from '../../models/time-limited-activity'; +import { DurationToReadablePipe } from 'src/app/pipes/duration'; +import { ErrorComponent } from 'src/app/ui-components/error/error.component'; +import { Store } from '@ngrx/store'; +import { fromObservation } from 'src/app/store/observation'; +import { GroupIsUserPipe } from 'src/app/pipes/groupIsUser'; +import { LoadingComponent } from 'src/app/ui-components/loading/loading.component'; +import { ItemExtraTimeForDescendantsComponent } from './item-extra-time-for-descendants/item-extra-time-for-descendants.component'; + +@Component({ + selector: 'alg-item-extra-time', + standalone: true, + imports: [ + IsTimeLimitedActivityPipe, + CanCurrentUserSetExtraTimePipe, + ItemExtraTimeForDescendantsComponent, + DurationToReadablePipe, + GroupIsUserPipe, + ErrorComponent, + LoadingComponent, + ], + templateUrl: './item-extra-time.component.html', + styleUrl: './item-extra-time.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ItemExtraTimeComponent { + itemData = input.required(); + + observedGroupInfoSignal = this.store.selectSignal(fromObservation.selectObservedGroupInfo); + + constructor( + private store: Store, + ) {} +} diff --git a/src/app/items/data-access/extra-time.service.ts b/src/app/items/data-access/extra-time.service.ts new file mode 100644 index 000000000..5706c7805 --- /dev/null +++ b/src/app/items/data-access/extra-time.service.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { appConfig } from 'src/app/utils/config'; +import { z } from 'zod'; +import { decodeSnakeCaseZod } from 'src/app/utils/operators/decode'; + +const groupAdditionalTimesSchema = z.array( + z.object({ + groupId: z.string(), + name: z.string(), + type: z.string(), + additionalTime: z.number(), + totalAdditionalTime: z.number(), + }) +); + +type GroupAdditionalTimes = z.infer; + +@Injectable({ + providedIn: 'root' +}) +export class ExtraTimeService { + + constructor(private http: HttpClient) {} + + getForGroupDescendant(itemId: string, groupId: string): Observable { + return this.http + .get(`${appConfig.apiUrl}/contests/${itemId}/groups/${groupId}/members/additional-times`) + .pipe( + decodeSnakeCaseZod(groupAdditionalTimesSchema), + ); + } + +} diff --git a/src/app/items/item-by-id.component.html b/src/app/items/item-by-id.component.html index 16303fda4..4c017bb64 100644 --- a/src/app/items/item-by-id.component.html +++ b/src/app/items/item-by-id.component.html @@ -140,6 +140,9 @@ @if (currentTab?.tag ==='alg-parameters') { } + @if (currentTab?.tag ==='alg-extra-time') { + + } @if (currentTab?.tag === 'alg-forum') { @if ((userProfile$ | async)?.tempUser || !showItemThreadWidget) { appConfig.featureFlags.hideTaskTabs.includes(v); const filteredTaskTabs = taskTabs.filter(({ view }) => !shouldHideTab(view) && (canViewSolution || view !== solutionTabView)); @@ -86,6 +89,7 @@ export class ItemTabs implements OnDestroy { this.isCurrentTab(historyTab) || showProgress ? historyTab : null, this.isCurrentTab(dependenciesTab) || hasEditionPerm ? dependenciesTab : null, this.isCurrentTab(parametersTab) || hasEditionPerm ? parametersTab : null, + this.isCurrentTab(extraTimeTab) || canSetExtraTime ? extraTimeTab : null, this.isCurrentTab(forumTab) || (!userProfile.tempUser && !!appConfig.forumServerUrl) ? forumTab : null, ] .filter(isNotNull) diff --git a/src/app/items/item.routes.ts b/src/app/items/item.routes.ts index 9bda792d8..39b135054 100644 --- a/src/app/items/item.routes.ts +++ b/src/app/items/item.routes.ts @@ -54,6 +54,10 @@ const routes: Routes = [ path: 'dependencies', children: [], }, + { + path: 'extra-time', + children: [], + }, { path: 'forum', children: [ diff --git a/src/app/items/models/item-grant-view-permission.ts b/src/app/items/models/item-grant-view-permission.ts index b3859b060..526c8c3c4 100644 --- a/src/app/items/models/item-grant-view-permission.ts +++ b/src/app/items/models/item-grant-view-permission.ts @@ -32,6 +32,15 @@ export function allowsGrantingContentView(p: ItemPermWithGrantView): boolean { return [ P.Content, P.ContentWithDescendants, P.Solution, P.SolutionWithGrant ].includes(p.canGrantView); } + +// ******************************************** +// Shortcut/helper functions on items directly +// ******************************************** + +export function canCurrentUserGrantView(i: ItemWithGrantViewPerm): boolean { + return allowsGrantingView(i.permissions); +} + // ******************************************** // Pipes for templates // ******************************************** diff --git a/src/app/items/models/item-watch-permission.ts b/src/app/items/models/item-watch-permission.ts index 796c7019c..2ba2cfb4f 100644 --- a/src/app/items/models/item-watch-permission.ts +++ b/src/app/items/models/item-watch-permission.ts @@ -42,6 +42,14 @@ export function allowsGrantingWatch(p: ItemPermWithWatch): boolean { return p.canWatch === P.AnswerWithGrant; } +// ******************************************** +// Shortcut/helper functions on items directly +// ******************************************** + +export function canCurrentUserWatchResult(i: ItemWithWatchPerm): boolean { + return allowsWatchingResults(i.permissions); +} + // ******************************************** // Pipes for templates // ******************************************** diff --git a/src/app/items/models/time-limited-activity.ts b/src/app/items/models/time-limited-activity.ts new file mode 100644 index 000000000..3bf15fbd1 --- /dev/null +++ b/src/app/items/models/time-limited-activity.ts @@ -0,0 +1,46 @@ +import { Item } from 'src/app/data-access/get-item-by-id.service'; +import { isAChapter, isATask } from './item-type'; +import { canCurrentUserViewContent } from './item-view-permission'; +import { canCurrentUserGrantView } from './item-grant-view-permission'; +import { canCurrentUserWatchResult } from './item-watch-permission'; +import { Pipe, PipeTransform } from '@angular/core'; + +type ItemWithTimeLimitedActivityInfo = Pick; +interface TimeLimitedActivityAssertion { + duration: NonNullable, + requiresExplicitEntry: true, +} +export function isTimeLimitedActivity(item: T): item is T & TimeLimitedActivityAssertion { + if (!isATask(item) && !isAChapter(item)) return false; + if (!item.requiresExplicitEntry) return false; + if (!item.duration) return false; + return item.duration.ms > 0; +} + +export function canCurrentUserSetExtraTime(item: Pick): boolean { + if (item.permissions.isOwner) return true; + return canCurrentUserViewContent(item) && canCurrentUserGrantView(item) && canCurrentUserWatchResult(item); +} + + +// ******************************************** +// Pipes for templates +// ******************************************** + +@Pipe({ + name: 'isTimeLimitedActivity', + pure: true, + standalone: true +}) +export class IsTimeLimitedActivityPipe implements PipeTransform { + transform = isTimeLimitedActivity; +} + +@Pipe({ + name: 'canCurrentUserSetExtraTime', + pure: true, + standalone: true +}) +export class CanCurrentUserSetExtraTimePipe implements PipeTransform { + transform = canCurrentUserSetExtraTime; +} From ce385ff4f2998875c6fc47644d84363f575a70d9 Mon Sep 17 00:00:00 2001 From: Damien Leroy Date: Fri, 20 Sep 2024 16:24:16 +0200 Subject: [PATCH 3/4] new i18n strings --- src/locale/messages.fr.xlf | 177 ++++++++++++++++++++++++++----------- 1 file changed, 123 insertions(+), 54 deletions(-) diff --git a/src/locale/messages.fr.xlf b/src/locale/messages.fr.xlf index 273d5c4b8..a5ef18409 100644 --- a/src/locale/messages.fr.xlf +++ b/src/locale/messages.fr.xlf @@ -24,7 +24,7 @@ - src/app/app.component.html73src/app/items/containers/item-display/item-display.component.ts218src/app/items/containers/permissions-edit-dialog/permissions-edit-dialog.component.html32src/app/items/item-by-id.component.ts319src/app/lti/lti.component.html18 + src/app/app.component.html73src/app/items/containers/item-display/item-display.component.ts218src/app/items/containers/permissions-edit-dialog/permissions-edit-dialog.component.html32src/app/items/item-by-id.component.ts320src/app/lti/lti.component.html18 Language mismatchMauvaise langue src/app/containers/language-mismatch/language-mismatch.component.html4 @@ -136,7 +136,7 @@ src/app/containers/redirect-to-id/redirect-to-id.component.html2 Go back to the Retour à la - src/app/containers/redirect-to-id/redirect-to-id.component.html4src/app/items/item-by-id.component.html159 + src/app/containers/redirect-to-id/redirect-to-id.component.html4src/app/items/item-by-id.component.html172 home pageaccueil src/app/containers/redirect-to-id/redirect-to-id.component.html5 @@ -151,7 +151,7 @@ src/app/containers/path-suggestion/path-suggestion.component.html15 This content does not exist or you are not allowed to view it. Ce contenu n'existe pas ou vous n'êtes pas autorisé à le voir. - src/app/items/item-by-id.component.html155 + src/app/items/item-by-id.component.html166 This page has unsaved changes. Do you want to leave this page and lose its changes?Cette page comporte des changements non sauvegardés. Voulez-vous quitter cette page et perdre les changements ? src/app/guards/pending-changes-guard.ts48 @@ -163,7 +163,7 @@ src/app/guards/pending-changes-guard.ts51 NoNon - src/app/groups/containers/group-edit/group-edit.component.ts65src/app/groups/containers/group-manager-list/group-manager-list.component.ts140src/app/groups/containers/group-remove-button/group-remove-button.component.ts77src/app/groups/containers/joined-group-list/joined-group-list.component.ts74src/app/groups/containers/manager-permission-dialog/manager-permission-dialog.component.ts129src/app/groups/containers/member-list/member-list.component.ts296src/app/groups/containers/member-list/member-list.component.ts310src/app/groups/containers/member-list/member-list.component.ts369src/app/guards/pending-changes-guard.ts56src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts65src/app/items/containers/item-remove-button/item-remove-button.component.ts80src/app/ui-components/collapsible-section/switch-field/switch-field.component.html12 + src/app/groups/containers/group-edit/group-edit.component.ts65src/app/groups/containers/group-manager-list/group-manager-list.component.ts140src/app/groups/containers/group-remove-button/group-remove-button.component.ts77src/app/groups/containers/joined-group-list/joined-group-list.component.ts74src/app/groups/containers/manager-permission-dialog/manager-permission-dialog.component.ts129src/app/groups/containers/member-list/member-list.component.ts296src/app/groups/containers/member-list/member-list.component.ts310src/app/groups/containers/member-list/member-list.component.ts369src/app/guards/pending-changes-guard.ts56src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts66src/app/items/containers/item-remove-button/item-remove-button.component.ts80src/app/ui-components/collapsible-section/switch-field/switch-field.component.html12 Read onlyLecture seule src/app/groups/containers/group-edit/group-edit.component.ts69 @@ -205,7 +205,10 @@ 10 - The managers of this group will be able to the personal info (firstname, lastname, email, grade, ...) you entered in your profile Les gestionnaires de ce groupe pourront les informations personnelles (nom, email, ...) que vous avez entré dans votre profil. + The managers of this group will be able to the personal info (firstname, lastname, email, grade, ...) you entered in your profile Les gestionnaires de ce groupe pourront les informations personnelles (nom, email, ...) que vous avez entré dans votre profil. src/app/groups/containers/join-group-confirmation-dialog/join-group-confirmation-dialog.component.html33 You will not be able to leave this group until Vous ne pourrez pas quitter ce groupe jusqu'au @@ -240,43 +243,43 @@ NeverJamais - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts48 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts49 All children validatedTous les enfants validés - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts51 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts52 All children but one validatedTous les enfants sauf un validés - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts54 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts55 All 'Categories' children validatedTous les enfants 'Catégories' validés - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts57 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts58 One children validatedUn enfant validé - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts60 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts61 Based on typeBasé sur le type - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts68 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts69 Yes mappedOui mappé - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts71 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts72 ListListe - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts76 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts77 GridGrille - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts79 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts80 All the members must be admittedTous les membres doivent être admis - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts86 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts88 Half of the members must be admittedLa moitié des membres doivent être admis - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts89 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts91 One of the members must be admittedUn membre doit être admis - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts92 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts94 None of the members has to be admittedAucun des membres n'a à être admis - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts95 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.ts97 You are not currently observing any group.Vous n'observez actuellement pas de groupe. src/app/items/containers/item-forum/item-forum.component.html11 @@ -393,22 +396,22 @@ src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html157 Latest allowed entering timeHeure d'entrée maximale - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html181 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html178 Participation as a team (only)Participation en tant qu'équipe (uniquement) - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html212 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html209 TeamÉquipe - src/app/groups/containers/managed-group-list/managed-group-list.component.ts61src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html209 + src/app/groups/containers/managed-group-list/managed-group-list.component.ts61src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html206 Freeze team on entryGeler l'équipe à l'entrée - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html221 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html218 Maximum team sizeTaille maximale de l'équipe - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html227 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html224 Minimum admitted membersNombre minimal de membres admis - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html234 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html231 Error while loading the dataErreur lors du chargement des données src/app/items/containers/group-progress-grid/group-progress-grid.component.html11 @@ -471,7 +474,7 @@ src/app/ui-components/collapsible-section/can-enter/can-enter.component.html12 The time is entered in your own timezone () The time is entered in your own timezone () - src/app/ui-components/collapsible-section/can-enter/can-enter.component.html25 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html170src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html195src/app/ui-components/collapsible-section/can-enter/can-enter.component.html25 DaysJours src/app/ui-components/duration/duration.component.html5 @@ -517,32 +520,38 @@ src/app/ui-components/add-content/add-content.component.html107 EditÉditer - src/app/items/item-tabs.ts23 + src/app/items/item-tabs.ts24 StatsStats - src/app/items/item-tabs.ts24 + src/app/items/item-tabs.ts25 HistoryHistorique - src/app/items/item-tabs.ts25 + src/app/items/item-tabs.ts26 DependenciesDépendances - src/app/items/item-tabs.ts26 + src/app/items/item-tabs.ts27 + Extra timeExtra time + + src/app/items/item-tabs.ts + 28 + + ParametersParamètres - src/app/items/item-tabs.ts27 + src/app/items/item-tabs.ts29 Leave unsaved taskNe pas sauvegarder la réponse - src/app/items/item-by-id.component.html179 + src/app/items/item-by-id.component.html192 You do not appear to be connected to the Internet, if you leave this task you may loose your progress. Are you sure you want to continue?Vous ne semblez pas être connecté à Internet, si vous quittez cette tâche, vous perdrez vos changements. Êtes-vous sûr de vouloir continuer ? - src/app/items/item-by-id.component.html181 + src/app/items/item-by-id.component.html194 Loose progress and leave the taskPerdre les changement et quitter la tâche - src/app/items/item-by-id.component.html186 + src/app/items/item-by-id.component.html199 RetryRéessayer - src/app/containers/path-suggestion/path-suggestion.component.html10src/app/items/containers/item-display/item-display.component.html58src/app/items/containers/item-forum/item-forum.component.html24src/app/items/item-by-id.component.html192 + src/app/containers/path-suggestion/path-suggestion.component.html10src/app/items/containers/item-display/item-display.component.html58src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html11src/app/items/containers/item-forum/item-forum.component.html24src/app/items/item-by-id.component.html205 An unknown error occurred. Une erreur est survenue. @@ -561,26 +570,26 @@ src/app/items/containers/item-display/item-display.component.html51 Unable to load the answerErreur lors du chargement de la réponse - src/app/items/item-by-id.component.html37 + src/app/items/item-by-id.component.html42 Unable to load the answer, back to the regular task page. Erreur lors du chargement de la réponse, retour à la tâche brute. - src/app/items/item-by-id.component.html40 + src/app/items/item-by-id.component.html45 Saving answer...Sauvegarde de la réponse ... src/app/items/containers/item-display/item-display.component.html67 SkipPasser - src/app/items/containers/item-display/item-display.component.html69src/app/items/item-by-id.component.html93 + src/app/items/containers/item-display/item-display.component.html69src/app/items/item-by-id.component.html100 You are not allowed to view the progress of other users on this content. Vous n'êtes pas autorisé à suivre la progression d'autres utilisateurs sur ce contenu. - src/app/items/item-by-id.component.html120 + src/app/items/item-by-id.component.html127 You are not allowed to view this content. Vous n'êtes pas autorisé à voir ce contenu. - src/app/items/item-by-id.component.html123 + src/app/items/item-by-id.component.html132 You are not allowed to view this content.Vous n'êtes pas autorisé à voir ce contenu. - src/app/items/item-by-id.component.html139 + src/app/items/item-by-id.component.html150 Your current progress could not have been saved. Are you connected to the internet?Erreur lors de la sauvegarde de votre progression. Êtes-vous connecté à Internet ? src/app/items/containers/item-display/item-display.component.ts148 @@ -607,7 +616,7 @@ src/app/items/containers/item-display/item-display.component.ts265 ForumForum - src/app/items/containers/item-display/item-display.component.ts266src/app/items/item-tabs.ts28 + src/app/items/containers/item-display/item-display.component.ts266src/app/items/item-tabs.ts30 HintsIndices src/app/items/containers/item-display/item-display.component.ts267 @@ -785,7 +794,7 @@ src/app/pipes/threadStatusDisplay.ts9 Saving answer before loading submission...Sauvegarde de la réponse pour charger une soumission... - src/app/items/item-by-id.component.html91 + src/app/items/item-by-id.component.html98 Maformed url: ""URL invalide: "" src/app/items/services/item-task-init.service.ts163 @@ -894,7 +903,7 @@ src/app/groups/containers/member-list/user-removal-response-handling.ts10 Changes successfully saved.Modifications bien enregistrées. - src/app/containers/access-code-view/access-code-view.component.ts79src/app/groups/containers/group-edit/group-edit.component.ts233src/app/groups/containers/platform-settings/platform-settings.component.ts36src/app/items/containers/item-children-edit-form/item-children-edit-form.component.ts127src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.ts335 + src/app/containers/access-code-view/access-code-view.component.ts79src/app/groups/containers/group-edit/group-edit.component.ts233src/app/groups/containers/platform-settings/platform-settings.component.ts36src/app/items/containers/item-children-edit-form/item-children-edit-form.component.ts127src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.ts339 Activity associated to Activité associée à src/app/groups/containers/group-access/group-access.component.html2 @@ -926,7 +935,7 @@ src/app/groups/containers/group-access/group-access.component.html84 Access to activity - Accéder à cette activitésrc/app/items/item-by-id.component.html9 + Accéder à cette activitésrc/app/items/item-by-id.component.html10 src/app/modules/group/pages/group-edit/group-edit.component.ts93src/app/modules/item/pages/item-edit/item-edit-wrapper.component.ts279src/app/modules/shared-components/components/access-code-view/access-code-view.component.ts67 Access to activityAccès à l'activité @@ -942,10 +951,10 @@ src/app/containers/access-code-view/access-code-view.component.ts52 AccessRejoindre - Button label for joining an item by (group) codesrc/app/items/item-by-id.component.html11 + Button label for joining an item by (group) codesrc/app/items/item-by-id.component.html12 ItemsÉlements - src/app/items/item-by-id.component.ts70 + src/app/items/item-by-id.component.ts71 Edit contentEditer le contenu src/app/items/containers/item-content/item-content.component.html61 @@ -980,13 +989,13 @@ - src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html59src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html74src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html112src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html213 + src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html59src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html74src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html112src/app/items/containers/item-edit-advanced-parameters/item-edit-advanced-parameters.component.html210 Your current access rights do not allow you to list the content of this chapter.Vos droits d'accès actuels ne vous permettent pas de lister le contenu de ce chapitre. src/app/containers/left-nav-tree/left-nav-tree.component.html83 home page page d'accueil - src/app/items/item-by-id.component.html167 + src/app/items/item-by-id.component.html180 Go back to the Retour à la src/app/modules/item/pages/item-by-id/item-by-id.component.html @@ -1001,7 +1010,7 @@ Error while loading the item.Erreur lors du chargement du contenu. - src/app/items/item-by-id.component.html157 + src/app/items/item-by-id.component.html169 AddAjouter src/app/ui-components/add-content/add-content.component.ts60 @@ -1099,7 +1108,7 @@ NameNom - src/app/groups/containers/joined-group-list/joined-group-list.component.html23src/app/groups/containers/managed-group-list/managed-group-list.component.html21src/app/groups/containers/member-list/member-list.component.ts41src/app/groups/containers/member-list/member-list.component.ts46src/app/groups/containers/member-list/member-list.component.ts52src/app/groups/containers/member-list/member-list.component.ts57src/app/groups/containers/member-list/member-list.component.ts62 + src/app/groups/containers/joined-group-list/joined-group-list.component.html23src/app/groups/containers/managed-group-list/managed-group-list.component.html21src/app/groups/containers/member-list/member-list.component.ts41src/app/groups/containers/member-list/member-list.component.ts46src/app/groups/containers/member-list/member-list.component.ts52src/app/groups/containers/member-list/member-list.component.ts57src/app/groups/containers/member-list/member-list.component.ts62src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html29 TypeType src/app/groups/containers/joined-group-list/joined-group-list.component.html24src/app/groups/containers/managed-group-list/managed-group-list.component.html22src/app/groups/containers/member-list/member-list.component.ts47src/app/groups/containers/user-group-invitations/user-group-invitations.component.html29 @@ -1267,7 +1276,7 @@ own this item, and get the maximum access in all categories above, and may also delete this item est propriétaire du contenu, il a donc tous les droits maximum dans les catégories ci-dessus et peut également le supprimer src/app/items/containers/permissions-edit-dialog-form/permissions-edit-form.component.html146 - As the group or user has currently "can view >= content" permission, the configured entering times have no effect, the group or user will be able to enter the activity at any time the activity allows it.As the group or user has currently "can view >= content" permission, the configured entering times have no effect, the group or user will be able to enter the activity at any time the activity allows it. + As the group or user has currently "can view >= content" permission, the configured entering times have no effect, the group or user will be able to enter the activity at any time the activity allows it.As the group or user has currently "can view >= content" permission, the configured entering times have no effect, the group or user will be able to enter the activity at any time the activity allows it. src/app/items/containers/permissions-edit-dialog-form/permissions-edit-form.component.ts26 CancelAnnuler @@ -1608,7 +1617,7 @@ ContentContenu - Tab namesrc/app/containers/left-nav/left-nav.component.html12src/app/groups/containers/group-log-view/group-log-view.component.html35src/app/items/containers/chapter-user-progress/chapter-user-progress.component.ts106src/app/items/containers/item-forum/item-forum.component.html45src/app/items/containers/item-log-view/item-log-view.component.ts172src/app/items/item-tabs.ts21src/app/items/item-tabs.ts22src/app/items/models/permissions-string.ts9src/app/items/models/permissions-string.ts17src/app/pipes/groupPermissionCaption.ts9 + Tab namesrc/app/containers/left-nav/left-nav.component.html12src/app/groups/containers/group-log-view/group-log-view.component.html35src/app/items/containers/chapter-user-progress/chapter-user-progress.component.ts106src/app/items/containers/item-forum/item-forum.component.html45src/app/items/containers/item-log-view/item-log-view.component.ts172src/app/items/item-tabs.ts22src/app/items/item-tabs.ts23src/app/items/models/permissions-string.ts9src/app/items/models/permissions-string.ts17src/app/pipes/groupPermissionCaption.ts9 can see the content of this item peut voir le contenu de cet élément src/app/items/models/permissions-texts.ts62 @@ -2175,13 +2184,73 @@ src/app/modules/group/pages/group-edit/group-edit.component.ts70src/app/modules/group/components/pending-request/pending-request-response-handling.ts27src/app/modules/group/components/pending-request/pending-request-response-handling.ts45 You need to solve all the errors displayed in the form to save changes.Vous devez résoudre toutes les erreurs affichées dans le formulaire avant de sauvegarder. - src/app/groups/containers/group-edit/group-edit.component.ts147src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.ts325 + src/app/groups/containers/group-edit/group-edit.component.ts147src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.ts329 Item titleTitre src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.html8 Item subtitleSous-titre - src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.html16 + src/app/items/containers/item-edit-wrapper/item-edit-wrapper.component.html16 + The resulting additional time of all descendants of this group:The resulting additional time of all descendants of this group: + + src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html + 3,5 + + + Unable to extra time informationUnable to extra time information + + src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html + 9,10 + + + Participant-specificParticipant-specific + + src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html + 30,31 + + + TotalTotal + + src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html + 31,32 + + + This group has no descendants. This group has no descendants. + + src/app/items/containers/item-extra-time/item-extra-time-for-descendants/item-extra-time-for-descendants.component.html + 50 + + + This content is not time-limited.This content is not time-limited. + + src/app/items/containers/item-extra-time/item-extra-time.component.html + 5 + + + You do not have the permissions to set extra time on this activity.You do not have the permissions to set extra time on this activity. + + src/app/items/containers/item-extra-time/item-extra-time.component.html + 8 + + + This activity has a duration of . To list and add extra-time to some groups or users, start observation on them.This activity has a duration of . To list and add extra-time to some groups or users, start observation on them. + + src/app/items/containers/item-extra-time/item-extra-time.component.html + 11,13 + + + Unable to load the extra time given to this groupUnable to load the extra time given to this group + + src/app/items/containers/item-extra-time/item-extra-time.component.html + 17 + + + The extra-time given to "" (i.e., including those given to its ancestors) is TODO, the resulting extra-time (so including its ancestor groups) is TODO. The extra-time given to "" (i.e., including those given to its ancestors) is TODO, the resulting extra-time (so including its ancestor groups) is TODO. + + src/app/items/containers/item-extra-time/item-extra-time.component.html + 21,24 + + There is no progress to report for this item.Il n'y a pas de progression sur ce contenu. src/app/items/containers/item-log-view/item-log-view.component.html119 From d7d92fa272aaeef5f3250dfb95a54e4ced7cdb45 Mon Sep 17 00:00:00 2001 From: Damien Leroy Date: Tue, 24 Sep 2024 11:17:52 +0200 Subject: [PATCH 4/4] small improvements (review) --- .../containers/item-extra-time/item-extra-time.component.html | 4 ++-- src/app/items/item-by-id.component.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/items/containers/item-extra-time/item-extra-time.component.html b/src/app/items/containers/item-extra-time/item-extra-time.component.html index 55b87e732..4f72672af 100644 --- a/src/app/items/containers/item-extra-time/item-extra-time.component.html +++ b/src/app/items/containers/item-extra-time/item-extra-time.component.html @@ -10,10 +10,10 @@ @else if (observedGroupInfo === null) {

This activity has a duration of {{ item.duration | readable }}. To list and add extra-time to some groups or users, start observation on them.

} -@else if (observedGroupInfo === undefined || false ) { +@else if (observedGroupInfo === undefined || false) { } -@else if (false ) { +@else if (false) { } @else { diff --git a/src/app/items/item-by-id.component.html b/src/app/items/item-by-id.component.html index 4c017bb64..240d9cb66 100644 --- a/src/app/items/item-by-id.component.html +++ b/src/app/items/item-by-id.component.html @@ -114,7 +114,7 @@ [itemData]="itemData" > } - @if (!isObserving) { + @else {