From 6556b5f2b1cbda41ec924b661dddfd5f0d4311cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Janis=20Daniel=20Da=CC=88hne?=
 <janis.daehne@informatik.uni-halle.de>
Date: Fri, 29 Jan 2021 14:26:26 +0100
Subject: [PATCH] - exercise overviews (all exercises) now allow to sort by
 last updated at and first accessed at

---
 i18n/en.ts                                    |  1 +
 i18n/i18nRoot.ts                              |  1 +
 .../closedExercisesSite/listView.tsx          | 58 +++++++++++++++++
 .../openExercises/listView.tsx                | 63 ++++++++++++++++++-
 .../sites/doExerciseSite/doExerciseSite.tsx   |  1 +
 src/types/exercisePreview.ts                  |  8 +++
 6 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/i18n/en.ts b/i18n/en.ts
index 7ee8aabd..c59190e1 100644
--- a/i18n/en.ts
+++ b/i18n/en.ts
@@ -41,6 +41,7 @@ export const lang_en: LangObj = {
   "Discard": "Discard",
   "Created at": "Created at",
   "Last updated at": "Last updated at",
+  "First accessed at": "First accessed at",
   "Last login at": "Last login at",
   "Information": "Information",
   "Search": "Search",
diff --git a/i18n/i18nRoot.ts b/i18n/i18nRoot.ts
index 0fdaa5e9..23287e23 100644
--- a/i18n/i18nRoot.ts
+++ b/i18n/i18nRoot.ts
@@ -44,6 +44,7 @@ export interface LangObj {
   "Discard": string
   "Created at": string
   "Last updated at": string
+  "First accessed at": string
   "Last login at": string
   "Information": string
   "Search": string
diff --git a/src/components/sites/allAccessibleExercisesSite/closedExercisesSite/listView.tsx b/src/components/sites/allAccessibleExercisesSite/closedExercisesSite/listView.tsx
index a675b14a..a5ea9545 100644
--- a/src/components/sites/allAccessibleExercisesSite/closedExercisesSite/listView.tsx
+++ b/src/components/sites/allAccessibleExercisesSite/closedExercisesSite/listView.tsx
@@ -131,6 +131,50 @@ class AllAccessibleExercisesList extends React.Component<Props, any> {
                   }
                 </span>
               </Table.HeaderCell>
+              <Table.HeaderCell
+                sorted={
+                  isCurrentSortingColumnPaginated<ExercisePreviewFromBackend>(this.props.sortByKey, 'lastUpdatedAt',
+                    this.props.sortDirection)
+                }
+              >
+                <span className="clickable"
+                      onClick={() => {
+                        this.props.setSortByKey('lastUpdatedAt',
+                          rotateSorting<ExercisePreviewFromBackend>(this.props.sortDirection,
+                            this.props.sortByKey,
+                            'lastUpdatedAt',
+                          ),
+                          this.props.displayAsViaCode
+                        )
+                      }}
+                >
+                  {
+                    getI18n(this.props.langId,'Last updated at')
+                  }
+                </span>
+              </Table.HeaderCell>
+              <Table.HeaderCell
+                sorted={
+                  isCurrentSortingColumnPaginated<ExercisePreviewFromBackend>(this.props.sortByKey, 'firstAccessedAt',
+                    this.props.sortDirection)
+                }
+              >
+                <span className="clickable"
+                      onClick={() => {
+                        this.props.setSortByKey('firstAccessedAt',
+                          rotateSorting<ExercisePreviewFromBackend>(this.props.sortDirection,
+                            this.props.sortByKey,
+                            'firstAccessedAt',
+                          ),
+                          this.props.displayAsViaCode
+                        )
+                      }}
+                >
+                  {
+                    getI18n(this.props.langId,'First accessed at')
+                  }
+                </span>
+              </Table.HeaderCell>
               <Table.HeaderCell>
                 <span>
                   <HelpPopup icon="flag outline"
@@ -199,6 +243,20 @@ class AllAccessibleExercisesList extends React.Component<Props, any> {
                       <HelpPopup defaultText={exercisePreview.shortDescription}/>
                       }
                     </Table.Cell>
+                    <Table.Cell>
+                      <span>
+                        {
+                          displayDateAndTime(exercisePreview.lastUpdatedAt, -1)
+                        }
+                      </span>
+                    </Table.Cell>
+                    <Table.Cell>
+                      <span>
+                        {
+                          displayDateAndTime(exercisePreview.firstAccessedAt, -1)
+                        }
+                      </span>
+                    </Table.Cell>
                     <Table.Cell>
                       <div>
                         <Checkbox checked={exercisePreview.shouldNotCount} disabled/>
diff --git a/src/components/sites/allAccessibleExercisesSite/openExercises/listView.tsx b/src/components/sites/allAccessibleExercisesSite/openExercises/listView.tsx
index 2ae023cf..ab2972ae 100644
--- a/src/components/sites/allAccessibleExercisesSite/openExercises/listView.tsx
+++ b/src/components/sites/allAccessibleExercisesSite/openExercises/listView.tsx
@@ -133,6 +133,50 @@ class AllAccessibleExercisesList extends React.Component<Props, any> {
                   }
                 </span>
               </Table.HeaderCell>
+              <Table.HeaderCell
+                sorted={
+                  isCurrentSortingColumnPaginated<ExercisePreviewFromBackend>(this.props.sortByKey, 'lastUpdatedAt',
+                    this.props.sortDirection)
+                }
+              >
+                <span className="clickable"
+                      onClick={() => {
+                        this.props.setSortByKey('lastUpdatedAt',
+                          rotateSorting<ExercisePreviewFromBackend>(this.props.sortDirection,
+                            this.props.sortByKey,
+                            'lastUpdatedAt',
+                          ),
+                          this.props.displayAsViaCode
+                        )
+                      }}
+                >
+                  {
+                    getI18n(this.props.langId,'Last updated at')
+                  }
+                </span>
+              </Table.HeaderCell>
+              <Table.HeaderCell
+                sorted={
+                  isCurrentSortingColumnPaginated<ExercisePreviewFromBackend>(this.props.sortByKey, 'firstAccessedAt',
+                    this.props.sortDirection)
+                }
+              >
+                <span className="clickable"
+                      onClick={() => {
+                        this.props.setSortByKey('firstAccessedAt',
+                          rotateSorting<ExercisePreviewFromBackend>(this.props.sortDirection,
+                            this.props.sortByKey,
+                            'firstAccessedAt',
+                          ),
+                          this.props.displayAsViaCode
+                        )
+                      }}
+                >
+                  {
+                    getI18n(this.props.langId,'First accessed at')
+                  }
+                </span>
+              </Table.HeaderCell>
               {
                 this.props.hideShouldNotCountColumn === false &&
                 <Table.HeaderCell>
@@ -168,9 +212,8 @@ class AllAccessibleExercisesList extends React.Component<Props, any> {
               }
               <Table.HeaderCell>
                 <span>
-                  {
-                    getI18n(this.props.langId,'Working time in min')
-                  }
+                  <HelpPopup icon="wait"
+                             defaultText={getI18n(this.props.langId,'Working time in min')}/>
                 </span>
               </Table.HeaderCell>
               <Table.HeaderCell>
@@ -214,6 +257,20 @@ class AllAccessibleExercisesList extends React.Component<Props, any> {
                       <HelpPopup defaultText={exercisePreview.shortDescription}/>
                       }
                     </Table.Cell>
+                    <Table.Cell>
+                      <span>
+                        {
+                          displayDateAndTime(exercisePreview.lastUpdatedAt, -1)
+                        }
+                      </span>
+                    </Table.Cell>
+                    <Table.Cell>
+                      <span>
+                        {
+                          displayDateAndTime(exercisePreview.firstAccessedAt, -1)
+                        }
+                      </span>
+                    </Table.Cell>
                     {
                       this.props.hideShouldNotCountColumn === false &&
                       <Table.Cell>
diff --git a/src/components/sites/doExerciseSite/doExerciseSite.tsx b/src/components/sites/doExerciseSite/doExerciseSite.tsx
index 3d4e3921..94f0d86d 100644
--- a/src/components/sites/doExerciseSite/doExerciseSite.tsx
+++ b/src/components/sites/doExerciseSite/doExerciseSite.tsx
@@ -911,6 +911,7 @@ class doExerciseSite extends React.Component<Props & RouteComponentProps<Matched
       hasLimitedWorkingTime: this.props.doExercise.exerciseRelease.hasLimitedWorkingTime,
       availableWorkingTimeInMinutes: this.props.doExercise.exerciseRelease.availableWorkingTimeInMinutes,
       firstAccessedAt: this.props.doExercise.firstAccessedAt,
+      lastUpdatedAt: null, //not needed or known here
       shortDescription: '',
       shouldNotCount: false,
       releaseDurationType: this.props.doExercise.exerciseRelease.releaseDurationType,
diff --git a/src/types/exercisePreview.ts b/src/types/exercisePreview.ts
index ac704e8c..114e92fa 100644
--- a/src/types/exercisePreview.ts
+++ b/src/types/exercisePreview.ts
@@ -100,9 +100,17 @@ export interface ExercisePreviewFromBackend {
    * (not actually accessed but could have accessed e.g. wehn he/she enters the release code)
    * used to calculate the left working time...
    * can be null because when accessed without code we know nothing about the (future) participation
+   * e.g. it is displayed in the visible for all area but the user has no participation for it
    */
   readonly firstAccessedAt: Moment | null
 
+  /**
+   * the date time when the user last edited the exercise (e.g. created custom test, changed solution code)
+   * can be null because when accessed without code we know nothing about the (future) participation
+   * e.g. it is displayed in the visible for all area but the user has no participation for it
+   */
+  readonly lastUpdatedAt: Moment | null
+
   /**
    * true: is still released,false: not
    */
-- 
GitLab