feat(changelog): implement changelog like faq
This commit is contained in:
parent
35737902b7
commit
d9d353fcb7
@ -1105,9 +1105,8 @@ th, td
|
|||||||
pointer-events: none
|
pointer-events: none
|
||||||
|
|
||||||
#changelog
|
#changelog
|
||||||
font-size: 14px
|
max-height: 75vh
|
||||||
white-space: pre-wrap
|
overflow: auto
|
||||||
font-family: var(--font-monospace)
|
|
||||||
|
|
||||||
#gitrev
|
#gitrev
|
||||||
font-size: 12px
|
font-size: 12px
|
||||||
|
|||||||
@ -2809,4 +2809,7 @@ CronMatchAsap: ASAP
|
|||||||
CronMatchNone: Nie
|
CronMatchNone: Nie
|
||||||
|
|
||||||
SystemExamOffice: Prüfungsverwaltung
|
SystemExamOffice: Prüfungsverwaltung
|
||||||
SystemFaculty: Fakultätsmitglied
|
SystemFaculty: Fakultätsmitglied
|
||||||
|
|
||||||
|
ChangelogItemFeature: Feature
|
||||||
|
ChangelogItemBugfix: Bugfix
|
||||||
@ -2811,3 +2811,6 @@ CronMatchNone: Never
|
|||||||
|
|
||||||
SystemExamOffice: Exam office
|
SystemExamOffice: Exam office
|
||||||
SystemFaculty: Faculty member
|
SystemFaculty: Faculty member
|
||||||
|
|
||||||
|
ChangelogItemFeature: Feature
|
||||||
|
ChangelogItemBugfix: Bugfix
|
||||||
4
models/changelog.model
Normal file
4
models/changelog.model
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
ChangelogItemFirstSeen
|
||||||
|
item ChangelogItem
|
||||||
|
firstSeen Day
|
||||||
|
Primary item
|
||||||
@ -1,4 +1,3 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
||||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
|
|
||||||
module Data.Time.Calendar.Instances
|
module Data.Time.Calendar.Instances
|
||||||
@ -11,8 +10,13 @@ import Data.Time.Calendar
|
|||||||
|
|
||||||
import Data.Universe
|
import Data.Universe
|
||||||
|
|
||||||
|
import Language.Haskell.TH.Syntax (Lift)
|
||||||
|
import Type.Reflection
|
||||||
|
|
||||||
deriving newtype instance Hashable Day
|
|
||||||
|
deriving instance Lift Day
|
||||||
|
instance Hashable Day where
|
||||||
|
hashWithSalt s (ModifiedJulianDay jDay) = s `hashWithSalt` hash (typeRep @Day) `hashWithSalt` jDay
|
||||||
|
|
||||||
deriving instance Ord DayOfWeek
|
deriving instance Ord DayOfWeek
|
||||||
instance Universe DayOfWeek where
|
instance Universe DayOfWeek where
|
||||||
|
|||||||
@ -225,6 +225,7 @@ embedRenderMessage ''UniWorX ''ExamAidsPreset id
|
|||||||
embedRenderMessage ''UniWorX ''ExamOnlinePreset id
|
embedRenderMessage ''UniWorX ''ExamOnlinePreset id
|
||||||
embedRenderMessage ''UniWorX ''ExamSynchronicityPreset id
|
embedRenderMessage ''UniWorX ''ExamSynchronicityPreset id
|
||||||
embedRenderMessage ''UniWorX ''ExamRequiredEquipmentPreset id
|
embedRenderMessage ''UniWorX ''ExamRequiredEquipmentPreset id
|
||||||
|
embedRenderMessage ''UniWorX ''ChangelogItemKind id
|
||||||
|
|
||||||
embedRenderMessage ''UniWorX ''AuthenticationMode id
|
embedRenderMessage ''UniWorX ''AuthenticationMode id
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,9 @@ import Handler.Utils
|
|||||||
import Handler.Info.TH
|
import Handler.Info.TH
|
||||||
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import Data.Map ((!))
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
import qualified Database.Esqueleto.Utils as E
|
import qualified Database.Esqueleto.Utils as E
|
||||||
@ -34,17 +36,26 @@ getLegalR =
|
|||||||
|
|
||||||
-- | Allgemeine Informationen
|
-- | Allgemeine Informationen
|
||||||
getInfoR :: Handler Html
|
getInfoR :: Handler Html
|
||||||
getInfoR = -- do
|
getInfoR = do
|
||||||
|
changelogEntries' <- runDB $ selectList [] []
|
||||||
|
let changelogEntries = Map.fromListWith Set.union
|
||||||
|
[ (Down changelogItemFirstSeenFirstSeen, Set.singleton changelogItemFirstSeenItem)
|
||||||
|
| Entity _ ChangelogItemFirstSeen{..} <- changelogEntries'
|
||||||
|
]
|
||||||
|
|
||||||
siteLayoutMsg MsgInfoHeading $ do
|
siteLayoutMsg MsgInfoHeading $ do
|
||||||
setTitleI MsgInfoHeading
|
setTitleI MsgInfoHeading
|
||||||
let features = $(i18nWidgetFile "featureList")
|
let features = $(i18nWidgetFile "featureList")
|
||||||
changeLog = $(i18nWidgetFile "changelog")
|
changeLog = $(widgetFile "changelog")
|
||||||
knownBugs = $(i18nWidgetFile "knownBugs")
|
knownBugs = $(i18nWidgetFile "knownBugs")
|
||||||
implementation = $(i18nWidgetFile "implementation")
|
implementation = $(i18nWidgetFile "implementation")
|
||||||
gitInfo :: Text
|
gitInfo :: Text
|
||||||
gitInfo = $gitDescribe <> " (" <> $gitCommitDate <> ")"
|
gitInfo = $gitDescribe <> " (" <> $gitCommitDate <> ")"
|
||||||
$(widgetFile "versionHistory")
|
$(widgetFile "versionHistory")
|
||||||
|
|
||||||
|
where
|
||||||
|
changelogItems = $(i18nWidgetFiles "changelog")
|
||||||
|
|
||||||
|
|
||||||
getInfoLecturerR :: Handler Html
|
getInfoLecturerR :: Handler Html
|
||||||
getInfoLecturerR =
|
getInfoLecturerR =
|
||||||
@ -67,9 +78,9 @@ getInfoLecturerR =
|
|||||||
|
|
||||||
-- new feature with given introduction date
|
-- new feature with given introduction date
|
||||||
newFeat :: Integer -> Int -> Int -> WidgetFor UniWorX ()
|
newFeat :: Integer -> Int -> Int -> WidgetFor UniWorX ()
|
||||||
newFeat year month day = do
|
newFeat y m d = do
|
||||||
currentTime <- liftIO getCurrentTime
|
currentTime <- liftIO getCurrentTime
|
||||||
let expiryTime = UTCTime (addGregorianMonthsRollOver 1 $ fromGregorian year month day) 0
|
let expiryTime = UTCTime (addGregorianMonthsRollOver 1 $ fromGregorian y m d) 0
|
||||||
if currentTime > expiryTime
|
if currentTime > expiryTime
|
||||||
then mempty
|
then mempty
|
||||||
else toWidget [whamlet| ^{iconTooltip tooltipNew (Just IconNew) False} |]
|
else toWidget [whamlet| ^{iconTooltip tooltipNew (Just IconNew) False} |]
|
||||||
|
|||||||
@ -213,9 +213,9 @@ formatDiffDays t
|
|||||||
|
|
||||||
|
|
||||||
setYear :: Integer -> Day -> Day
|
setYear :: Integer -> Day -> Day
|
||||||
setYear year date = fromGregorian year month day
|
setYear year date = fromGregorian year m d
|
||||||
where
|
where
|
||||||
(_,month,day) = toGregorian date
|
(_,m,d) = toGregorian date
|
||||||
|
|
||||||
addOneWeek :: UTCTime -> UTCTime
|
addOneWeek :: UTCTime -> UTCTime
|
||||||
addOneWeek = addWeeks 1
|
addOneWeek = addWeeks 1
|
||||||
@ -295,7 +295,7 @@ formatTimeRangeMail = formatTimeRange' formatTimeMail
|
|||||||
|
|
||||||
|
|
||||||
formatGregorianW :: Integer -> Int -> Int -> Widget
|
formatGregorianW :: Integer -> Int -> Int -> Widget
|
||||||
formatGregorianW year month day = formatTimeW SelFormatDate $ fromGregorian year month day
|
formatGregorianW y m d = formatTimeW SelFormatDate $ fromGregorian y m d
|
||||||
|
|
||||||
instance Csv.ToField ZonedTime where
|
instance Csv.ToField ZonedTime where
|
||||||
toField = Csv.toField . iso8601Show
|
toField = Csv.toField . iso8601Show
|
||||||
|
|||||||
@ -45,6 +45,10 @@ import Web.ServerSession.Backend.Persistent.Memcached (migrateMemcachedSqlStorag
|
|||||||
|
|
||||||
import Data.Conduit.Algorithms.FastCDC (FastCDCParameters(fastCDCMinBlockSize))
|
import Data.Conduit.Algorithms.FastCDC (FastCDCParameters(fastCDCMinBlockSize))
|
||||||
|
|
||||||
|
import Data.Time.Format.ISO8601 (iso8601Show)
|
||||||
|
|
||||||
|
import qualified Data.Time.Zones as TZ
|
||||||
|
|
||||||
-- Database versions must follow https://pvp.haskell.org:
|
-- Database versions must follow https://pvp.haskell.org:
|
||||||
-- - Breaking changes are instances where manual migration is necessary (via customMigrations; i.e. changing a columns format)
|
-- - Breaking changes are instances where manual migration is necessary (via customMigrations; i.e. changing a columns format)
|
||||||
-- - Non-breaking changes are instances where the automatic migration done by persistent is sufficient (i.e. adding a column or table)
|
-- - Non-breaking changes are instances where the automatic migration done by persistent is sufficient (i.e. adding a column or table)
|
||||||
@ -168,6 +172,19 @@ migrateManual = do
|
|||||||
, ("user_ldap_primary_key", "CREATE INDEX user_ldap_primary_key ON \"user\" (ldap_primary_key)" )
|
, ("user_ldap_primary_key", "CREATE INDEX user_ldap_primary_key ON \"user\" (ldap_primary_key)" )
|
||||||
, ("file_content_entry_chunk_hash", "CREATE INDEX file_content_entry_chunk_hash ON \"file_content_entry\" (chunk_hash)" )
|
, ("file_content_entry_chunk_hash", "CREATE INDEX file_content_entry_chunk_hash ON \"file_content_entry\" (chunk_hash)" )
|
||||||
]
|
]
|
||||||
|
|
||||||
|
recordedChangelogItems <- lift . lift $ selectList [] []
|
||||||
|
let missingChangelogItems = Set.toList $ Set.fromList universeF `Set.difference` recordedChangelogItems'
|
||||||
|
where recordedChangelogItems' = Set.fromList [ changelogItemFirstSeenItem | Entity _ ChangelogItemFirstSeen{..} <- recordedChangelogItems ]
|
||||||
|
unless (null missingChangelogItems) $ do
|
||||||
|
now <- iso8601Show . localDay . TZ.utcToLocalTimeTZ appTZ <$> liftIO getCurrentTime
|
||||||
|
addMigration False $
|
||||||
|
let sql = [st|INSERT INTO changelog_item_first_seen (item, first_seen) VALUES #{vals}|]
|
||||||
|
vals = Text.intercalate ", " $ do
|
||||||
|
item <- missingChangelogItems
|
||||||
|
return [st|('#{toPathPiece item}', '#{now}')|]
|
||||||
|
in sql
|
||||||
|
|
||||||
where
|
where
|
||||||
addIndex :: Text -> Sql -> Migration
|
addIndex :: Text -> Sql -> Migration
|
||||||
addIndex ixName ixDef = do
|
addIndex ixName ixDef = do
|
||||||
@ -961,6 +978,15 @@ customMigrations = Map.fromListWith (>>)
|
|||||||
ALTER TABLE school ADD COLUMN "exam_discouraged_modes" jsonb NOT NULL DEFAULT #{ExamModeDNF predDNFFalse};
|
ALTER TABLE school ADD COLUMN "exam_discouraged_modes" jsonb NOT NULL DEFAULT #{ExamModeDNF predDNFFalse};
|
||||||
|]
|
|]
|
||||||
)
|
)
|
||||||
|
, ( AppliedMigrationKey [migrationVersion|42.0.0|] [version|43.0.0|]
|
||||||
|
, unlessM (tableExists "changelog_item_first_seen") $ do
|
||||||
|
[executeQQ|
|
||||||
|
CREATE TABLE "changelog_item_first_seen" (PRIMARY KEY ("item"), "item" VARCHAR NOT NULL, "first_seen" DATE NOT NULL);
|
||||||
|
|]
|
||||||
|
insertMany_ [ ChangelogItemFirstSeen{..}
|
||||||
|
| (changelogItemFirstSeenItem, changelogItemFirstSeenFirstSeen) <- Map.toList changelogItemDays
|
||||||
|
]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -17,3 +17,4 @@ import Model.Types.Allocation as Types
|
|||||||
import Model.Types.Languages as Types
|
import Model.Types.Languages as Types
|
||||||
import Model.Types.File as Types
|
import Model.Types.File as Types
|
||||||
import Model.Types.User as Types
|
import Model.Types.User as Types
|
||||||
|
import Model.Types.Changelog as Types
|
||||||
|
|||||||
145
src/Model/Types/Changelog.hs
Normal file
145
src/Model/Types/Changelog.hs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
module Model.Types.Changelog
|
||||||
|
( ChangelogItem(..)
|
||||||
|
, changelogItemMap
|
||||||
|
, ChangelogItemKind(..), _ChangelogItemFeature, _ChangelogItemBugfix
|
||||||
|
, classifyChangelogItem
|
||||||
|
, changelogItemDays
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import.NoModel
|
||||||
|
|
||||||
|
import Model.Types.TH.PathPiece
|
||||||
|
|
||||||
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
|
|
||||||
|
mkI18nWidgetEnum "Changelog" "changelog"
|
||||||
|
derivePersistFieldPathPiece ''ChangelogItem
|
||||||
|
pathPieceJSONKey ''ChangelogItem
|
||||||
|
pathPieceJSON ''ChangelogItem
|
||||||
|
pathPieceHttpApiData ''ChangelogItem
|
||||||
|
|
||||||
|
data ChangelogItemKind
|
||||||
|
= ChangelogItemFeature
|
||||||
|
| ChangelogItemBugfix
|
||||||
|
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable)
|
||||||
|
deriving anyclass (Universe, Finite)
|
||||||
|
|
||||||
|
makePrisms ''ChangelogItemKind
|
||||||
|
|
||||||
|
classifyChangelogItem :: ChangelogItem -> ChangelogItemKind
|
||||||
|
classifyChangelogItem = \case
|
||||||
|
ChangelogHaskellCampusLogin -> ChangelogItemBugfix
|
||||||
|
ChangelogTooltipsWithoutJavascript -> ChangelogItemBugfix
|
||||||
|
ChangelogButtonsWorkWithoutJavascript -> ChangelogItemBugfix
|
||||||
|
ChangelogTableFormsWorkAfterAjax -> ChangelogItemBugfix
|
||||||
|
ChangelogPassingByPointsWorks -> ChangelogItemBugfix
|
||||||
|
ChangelogErrorMessagesForTableItemVanish -> ChangelogItemBugfix
|
||||||
|
ChangelogExamAchievementParticipantDuplication -> ChangelogItemBugfix
|
||||||
|
ChangelogFormsTimesReset -> ChangelogItemBugfix
|
||||||
|
_other -> ChangelogItemFeature
|
||||||
|
|
||||||
|
changelogItemDays :: Map ChangelogItem Day
|
||||||
|
changelogItemDays = Map.fromListWithKey (\k d1 d2 -> bool (error $ "Duplicate changelog days for " <> show k) d1 $ d1 /= d2)
|
||||||
|
[ (ChangelogConfigurableDatetimeFormat, [day|2018-07-10|])
|
||||||
|
, (ChangelogCourseListOverAllTerms, [day|2018-07-31|])
|
||||||
|
, (ChangelogCorrectionsDisplayImprovements, [day|2018-07-31|])
|
||||||
|
, (ChangelogHaskellCampusLogin, [day|2018-08-01|])
|
||||||
|
, (ChangelogFileDownloadOption, [day|2018-08-06|])
|
||||||
|
, (ChangelogSheetsNoSubmissionAndZipControl, [day|2018-09-18|])
|
||||||
|
, (ChangelogSmartCorrectionDistribution, [day|2018-09-18|])
|
||||||
|
, (ChangelogTableSummaries, [day|2018-09-18|])
|
||||||
|
, (ChangelogPersonalInformation, [day|2018-09-18|])
|
||||||
|
, (ChangelogCourseShorthandsWithinSchools, [day|2018-09-18|])
|
||||||
|
, (ChangelogTooltipsWithoutJavascript, [day|2018-09-18|])
|
||||||
|
, (ChangelogEmailNotifications, [day|2018-10-19|])
|
||||||
|
, (ChangelogSupportWidget, [day|2018-10-19|])
|
||||||
|
, (ChangelogAccountDeletionDuringTesting, [day|2018-10-19|])
|
||||||
|
, (ChangelogImprovementsForCorrectors, [day|2018-11-09|])
|
||||||
|
, (ChangelogButtonsWorkWithoutJavascript, [day|2018-11-09|])
|
||||||
|
, (ChangelogTableFormsWorkAfterAjax, [day|2018-11-29|])
|
||||||
|
, (ChangelogPassingByPointsWorks, [day|2018-11-30|])
|
||||||
|
, (ChangelogErrorMessagesForTableItemVanish, [day|2019-01-16|])
|
||||||
|
, (ChangelogAssignedCorrectionsFilters, [day|2019-01-16|])
|
||||||
|
, (ChangelogCourseConvenienceLinks, [day|2019-01-16|])
|
||||||
|
, (ChangelogAsidenav, [day|2019-01-30|])
|
||||||
|
, (ChangelogCourseAssociatedStudyField, [day|2019-03-20|])
|
||||||
|
, (ChangelogStudyFeatures, [day|2019-03-27|])
|
||||||
|
, (ChangelogCourseAdministratorRoles, [day|2019-03-27|])
|
||||||
|
, (ChangelogCourseAdministratorInvitations, [day|2019-04-20|])
|
||||||
|
, (ChangelogCourseMessages, [day|2019-04-20|])
|
||||||
|
, (ChangelogCorrectorsOnCourseShow, [day|2019-04-29|])
|
||||||
|
, (ChangelogTutorials, [day|2019-04-29|])
|
||||||
|
, (ChangelogCourseMaterials, [day|2019-05-04|])
|
||||||
|
, (ChangelogDownloadAllSheetFiles, [day|2019-05-10|])
|
||||||
|
, (ChangelogImprovedSubmittorUi, [day|2019-05-10|])
|
||||||
|
, (ChangelogCourseRegisterByAdmin, [day|2019-05-13|])
|
||||||
|
, (ChangelogReworkedAutomaticCorrectionDistribution, [day|2019-05-20|])
|
||||||
|
, (ChangelogDownloadAllSheetFilesByType, [day|2019-06-07|])
|
||||||
|
, (ChangelogSheetSpecificFiles, [day|2019-06-07|])
|
||||||
|
, (ChangelogExams, [day|2019-06-26|])
|
||||||
|
, (ChangelogCsvExamParticipants, [day|2019-07-23|])
|
||||||
|
, (ChangelogAllocationCourseRegistration, [day|2019-08-12|])
|
||||||
|
, (ChangelogAllocationApplications, [day|2019-08-19|])
|
||||||
|
, (ChangelogCsvCourseApplications, [day|2019-08-27|])
|
||||||
|
, (ChangelogAllocationsNotifications, [day|2019-09-05|])
|
||||||
|
, (ChangelogConfigurableDisplayEmails, [day|2019-09-12|])
|
||||||
|
, (ChangelogConfigurableDisplayNames, [day|2019-09-12|])
|
||||||
|
, (ChangelogEstimateAllocatedCourseCapacity, [day|2019-09-12|])
|
||||||
|
, (ChangelogNotificationExamRegistration, [day|2019-09-13|])
|
||||||
|
, (ChangelogExamClosure, [day|2019-09-16|])
|
||||||
|
, (ChangelogExamOfficeExamNotification, [day|2019-09-16|])
|
||||||
|
, (ChangelogExamOffices, [day|2019-09-16|])
|
||||||
|
, (ChangelogExamAchievementParticipantDuplication, [day|2019-09-25|])
|
||||||
|
, (ChangelogFormsTimesReset, [day|2019-09-25|])
|
||||||
|
, (ChangelogExamAutomaticResults, [day|2019-09-25|])
|
||||||
|
, (ChangelogExamAutomaticBoni, [day|2019-09-25|])
|
||||||
|
, (ChangelogAutomaticallyAcceptCourseApplications, [day|2019-09-27|])
|
||||||
|
, (ChangelogCourseNews, [day|2019-10-01|])
|
||||||
|
, (ChangelogCsvExportCourseParticipants, [day|2019-10-08|])
|
||||||
|
, (ChangelogNotificationCourseParticipantViaAdmin, [day|2019-10-08|])
|
||||||
|
, (ChangelogCsvExportCourseParticipantsFeatures, [day|2019-10-09|])
|
||||||
|
, (ChangelogCourseOccurences, [day|2019-10-09|])
|
||||||
|
, (ChangelogTutorialRegistrationViaParticipantTable, [day|2019-10-10|])
|
||||||
|
, (ChangelogCsvExportCourseParticipantsRegisteredTutorials, [day|2019-10-10|])
|
||||||
|
, (ChangelogCourseParticipantsSex, [day|2019-10-14|])
|
||||||
|
, (ChangelogTutorialTutorControl, [day|2019-10-14|])
|
||||||
|
, (ChangelogCsvOptionCharacterSet, [day|2019-10-23|])
|
||||||
|
, (ChangelogCsvOptionTimestamp, [day|2019-10-23|])
|
||||||
|
, (ChangelogEnglish, [day|2019-10-31|])
|
||||||
|
, (ChangelogI18n, [day|2019-10-31|])
|
||||||
|
, (ChangelogLmuInternalFields, [day|2019-11-28|])
|
||||||
|
, (ChangelogNotificationSubmissionChanged, [day|2019-12-05|])
|
||||||
|
, (ChangelogExportCourseParticipants, [day|2020-01-17|])
|
||||||
|
, (ChangelogExternalExams, [day|2020-01-17|])
|
||||||
|
, (ChangelogExamAutomaticRoomDistribution, [day|2020-01-29|])
|
||||||
|
, (ChangelogWarningMultipleSemesters, [day|2020-01-30|])
|
||||||
|
, (ChangelogExamAutomaticRoomDistributionBetterRulesDisplay, [day|2020-01-30|])
|
||||||
|
, (ChangelogReworkedNavigation, [day|2020-02-07|])
|
||||||
|
, (ChangelogExamCorrect, [day|2020-02-08|])
|
||||||
|
, (ChangelogExamGradingMode, [day|2020-02-19|])
|
||||||
|
, (ChangelogMarkdownEmails, [day|2020-02-23|])
|
||||||
|
, (ChangelogMarkdownHtmlInput, [day|2020-02-23|])
|
||||||
|
, (ChangelogBetterCsvImport, [day|2020-03-06|])
|
||||||
|
, (ChangelogAdditionalDatetimeFormats, [day|2020-03-16|])
|
||||||
|
, (ChangelogServerSideSessions, [day|2020-03-16|])
|
||||||
|
, (ChangelogWebinterfaceAllocationAllocation, [day|2020-03-16|])
|
||||||
|
, (ChangelogBetterTableCellColourCoding, [day|2020-03-16|])
|
||||||
|
, (ChangelogCourseOccurrenceNotes, [day|2020-03-31|])
|
||||||
|
, (ChangelogHideSystemMessages, [day|2020-04-15|])
|
||||||
|
, (ChangelogNonAnonymisedCorrection, [day|2020-04-17|])
|
||||||
|
, (ChangelogBetterCourseParticipantDetailPage, [day|2020-04-17|])
|
||||||
|
, (ChangelogFaq, [day|2020-04-24|])
|
||||||
|
, (ChangelogRegisteredSubmissionGroups, [day|2020-04-28|])
|
||||||
|
, (ChangelogFormerCourseParticipants, [day|2020-05-05|])
|
||||||
|
, (ChangelogBetterFileUploads, [day|2020-05-05|])
|
||||||
|
, (ChangelogSheetPassAlways, [day|2020-05-23|])
|
||||||
|
, (ChangelogBetterCourseCommunicationTutorials, [day|2020-05-25|])
|
||||||
|
, (ChangelogAdditionalSheetNotifications, [day|2020-05-25|])
|
||||||
|
, (ChangelogCourseParticipantsListAddSheets, [day|2020-06-14|])
|
||||||
|
, (ChangelogYamlRatings, [day|2020-06-17|])
|
||||||
|
, (ChangelogSubmissionOnlyExamRegistered, [day|2020-07-20|])
|
||||||
|
, (ChangelogCourseVisibility, [day|2020-08-10|])
|
||||||
|
, (ChangelogPersonalisedSheetFiles, [day|2020-08-10|])
|
||||||
|
, (ChangelogAbolishCourseAssociatedStudyFeatures, [day|2020-08-28|])
|
||||||
|
]
|
||||||
@ -12,6 +12,7 @@ module Utils.DateTime
|
|||||||
, nominalHour, nominalMinute
|
, nominalHour, nominalMinute
|
||||||
, minNominalYear, avgNominalYear
|
, minNominalYear, avgNominalYear
|
||||||
, module Zones
|
, module Zones
|
||||||
|
, day
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import ClassyPrelude.Yesod hiding (lift)
|
import ClassyPrelude.Yesod hiding (lift)
|
||||||
@ -23,12 +24,14 @@ import Data.Time.Zones.TH as Zones (includeSystemTZ)
|
|||||||
import Data.Time.Zones (localTimeToUTCTZ, timeZoneForUTCTime)
|
import Data.Time.Zones (localTimeToUTCTZ, timeZoneForUTCTime)
|
||||||
import Data.Time.Format (FormatTime)
|
import Data.Time.Format (FormatTime)
|
||||||
import Data.Time.Clock.System (systemEpochDay)
|
import Data.Time.Clock.System (systemEpochDay)
|
||||||
|
import qualified Data.Time.Format.ISO8601 as Time
|
||||||
import qualified Data.Time.Format as Time
|
import qualified Data.Time.Format as Time
|
||||||
|
|
||||||
import qualified Data.List.NonEmpty as NonEmpty
|
import qualified Data.List.NonEmpty as NonEmpty
|
||||||
|
|
||||||
import Language.Haskell.TH
|
import Language.Haskell.TH
|
||||||
import Language.Haskell.TH.Syntax (Lift(..))
|
import Language.Haskell.TH.Syntax (Lift(..))
|
||||||
|
import Language.Haskell.TH.Quote (QuasiQuoter(..))
|
||||||
import Instances.TH.Lift ()
|
import Instances.TH.Lift ()
|
||||||
|
|
||||||
import Data.Data (Data)
|
import Data.Data (Data)
|
||||||
@ -144,3 +147,15 @@ nominalMinute = 60
|
|||||||
minNominalYear, avgNominalYear :: NominalDiffTime
|
minNominalYear, avgNominalYear :: NominalDiffTime
|
||||||
minNominalYear = 365 * nominalDay
|
minNominalYear = 365 * nominalDay
|
||||||
avgNominalYear = fromRational $ 365.2425 * toRational nominalDay
|
avgNominalYear = fromRational $ 365.2425 * toRational nominalDay
|
||||||
|
|
||||||
|
---------
|
||||||
|
-- Day --
|
||||||
|
---------
|
||||||
|
|
||||||
|
day :: QuasiQuoter
|
||||||
|
day = QuasiQuoter{..}
|
||||||
|
where
|
||||||
|
quotePat = error "day used as pattern"
|
||||||
|
quoteType = error "day used as type"
|
||||||
|
quoteDec = error "day used as declaration"
|
||||||
|
quoteExp dStr = maybe (fail $ "Could not parse ISO8601 day: “" <> dStr <> "”") (lift :: Day -> Q Exp) $ Time.iso8601ParseM dStr
|
||||||
|
|||||||
@ -8,6 +8,7 @@ module Utils.PathPiece
|
|||||||
, tuplePathPiece
|
, tuplePathPiece
|
||||||
, pathPieceJSON, pathPieceJSONKey
|
, pathPieceJSON, pathPieceJSONKey
|
||||||
, pathPieceBinary
|
, pathPieceBinary
|
||||||
|
, pathPieceHttpApiData
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import ClassyPrelude.Yesod
|
import ClassyPrelude.Yesod
|
||||||
@ -40,6 +41,8 @@ import qualified Data.Binary as Binary
|
|||||||
import Control.Lens
|
import Control.Lens
|
||||||
import Data.Generics.Product.Types
|
import Data.Generics.Product.Types
|
||||||
|
|
||||||
|
import Web.HttpApiData
|
||||||
|
|
||||||
|
|
||||||
mkFiniteFromPathPiece :: Name -> Q ([Dec], Exp)
|
mkFiniteFromPathPiece :: Name -> Q ([Dec], Exp)
|
||||||
mkFiniteFromPathPiece finiteType = do
|
mkFiniteFromPathPiece finiteType = do
|
||||||
@ -229,3 +232,11 @@ pathPieceBinary tName
|
|||||||
get = Binary.get >>= maybe (fail $ "Could not parse value of " <> $(TH.lift $ nameBase tName) <> " via PathPiece") return . fromPathPiece
|
get = Binary.get >>= maybe (fail $ "Could not parse value of " <> $(TH.lift $ nameBase tName) <> " via PathPiece") return . fromPathPiece
|
||||||
put = Binary.put . toPathPiece
|
put = Binary.put . toPathPiece
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
pathPieceHttpApiData :: Name -> DecsQ
|
||||||
|
pathPieceHttpApiData tName
|
||||||
|
= [d| instance ToHttpApiData $(conT tName) where
|
||||||
|
toUrlPiece = toPathPiece
|
||||||
|
instance FromHttpApiData $(conT tName) where
|
||||||
|
parseUrlPiece = maybe (Left $ "Could not parse value of " <> $(TH.lift $ nameBase tName) <> " via PathPiece") Right . fromPathPiece
|
||||||
|
|]
|
||||||
|
|||||||
14
templates/changelog.hamlet
Normal file
14
templates/changelog.hamlet
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
$newline never
|
||||||
|
<dl .deflist #changelog>
|
||||||
|
$forall (Down d, es) <- Map.toList changelogEntries
|
||||||
|
<dt .deflist__dt ##{"changelog-date--" <> toPathPiece d}>
|
||||||
|
^{formatTimeW SelFormatDate d}
|
||||||
|
<dd .deflist__dd>
|
||||||
|
<ul>
|
||||||
|
$forall e <- Set.toList es
|
||||||
|
<li ##{"changelog-item--" <> toPathPiece e}>
|
||||||
|
$if is _ChangelogItemBugfix $ classifyChangelogItem e
|
||||||
|
<i>
|
||||||
|
_{ChangelogItemBugfix}
|
||||||
|
: #
|
||||||
|
^{changelogItems ! toPathPiece e}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
$newline never
|
||||||
|
Kursassoziierte Studienfächer wurden abgeschafft.
|
||||||
|
<br>
|
||||||
|
Es werden nun an allen kursbezogenen Stellen jene Studiendaten angezeigt, die während des entsprechenden Semesters aktuell waren.
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
$newline never
|
||||||
|
Abolished course-associated features of study.
|
||||||
|
<br>
|
||||||
|
In course-related contexts now all study features which were up to date during the relevant term are displayed.
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Benutzer können sich in der Testphase komplett selbst löschen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
During testing users may completely delete their accounts
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Zusätzliche Uhrzeit- und Datumsformate
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Additional date and time formats
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Zusätzliche Benachrichtigungen für Übungsblätter
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Additional notifications for exercise sheets
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Bewerbungen für Zentralanmeldungen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Applications for central allocations
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kurse zu Zentralanmeldungen eintragen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Registration of courses for central allocation
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Benachrichtigungen für Zentralanmeldungen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Notifications for central allocations
|
||||||
2
templates/i18n/changelog/asidenav.de-de-formal.hamlet
Normal file
2
templates/i18n/changelog/asidenav.de-de-formal.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Designänderungen
|
||||||
2
templates/i18n/changelog/asidenav.en-eu.hamlet
Normal file
2
templates/i18n/changelog/asidenav.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Design changes
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Liste zugewiesener Abgaben lassen sich nun filtern
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Filters for list of assigned corrections
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Automatische Anmeldung von Bewerbern in Kursen, die nicht an einer Zentralanmeldung teilnehmen (nach Bewertung der Bewerbung)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Option to automatically accept applications for courses outside of central allocations
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Besseres Verschicken von Kursmitteilungen an Tutoriumsteilnehmer
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Better sending of course communications to tutorial participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Anzeige von Abgaben, Tutorien und Klausuren auf der Seite für einzelne Kursteilnehmer
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Submissions, tutorials, and exams are now shown on the detail page for course participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Verbesserter Workflow & Fehlerbehandlung für CSV-Import
|
||||||
2
templates/i18n/changelog/better-csv-import.en-eu.hamlet
Normal file
2
templates/i18n/changelog/better-csv-import.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Improved workflow and error-handling for CSV-import
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Verbesserte Handhabung von Datei-Uploads
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Improved handling of file uploads
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Verbesserte Farbkodierung von Tabellenzellen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Improved colour coding of table cells
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Zahlreiche Knöpfe/Formulare funktionieren wieder bei eingeschaltetem Javascript
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Multiple buttons/forms no work again when JavaScript is enabled
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Wählbares Format für Datum
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Configurable date and time formats
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Anpassbare angezeigte E-Mail Adressen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Configulable display emails
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Anpassbare angezeigte Namen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Configurable display names
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Viele Verbesserung zur Anzeige von Korrekturen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Numerous improvements for display of corrections
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Anzeige von Korrektoren auf den Kursseiten
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Display of correctors on course overview pages
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Eintragen von Korrektoren und Kursverwaltern auch ohne bestehenden Account
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Configuration of course correctors and administrators without existing accounts
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kurse Veranstalter können nun mehrere Dozenten und Assistenten selbst eintragen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course administrators can now configure course administrators and assistants themselves
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kursanmeldung benötigen assoziertes Hauptfach (für Studierende mit mehreren Hauptfächern)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course enrollment requires association of a field of study (for students with multiple fields)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Links für Bequemlichkeiten hinzugefügt (z.B. aktuelles Übungsblatt)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Convenience links (i.e. current exercise sheet)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kursliste über alle Semester hinweg (Top-Level-Navigation "Kurse"), wird in Zukunft Filter/Suchfunktion erhalten
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Overall course list for all semesters (see "Courses"), will have filters and search functions in the future
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kursmaterial
|
||||||
2
templates/i18n/changelog/course-materials.en-eu.hamlet
Normal file
2
templates/i18n/changelog/course-materials.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course material
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Versand von Benachrichtigungen an Kursteilnehmer
|
||||||
2
templates/i18n/changelog/course-messages.en-eu.hamlet
Normal file
2
templates/i18n/changelog/course-messages.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Sending of course messages to participants
|
||||||
2
templates/i18n/changelog/course-news.de-de-formal.hamlet
Normal file
2
templates/i18n/changelog/course-news.de-de-formal.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
"Aktuelles" für Kurse
|
||||||
2
templates/i18n/changelog/course-news.en-eu.hamlet
Normal file
2
templates/i18n/changelog/course-news.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course news
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kurstermine
|
||||||
2
templates/i18n/changelog/course-occurences.en-eu.hamlet
Normal file
2
templates/i18n/changelog/course-occurences.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course occurrences
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Spalte für Notizen bei Kursterminen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Column for adding notes to course events
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Auswertung des Übungsbetriebs unter „Kursteilnehmer“
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Inclusion of exercise sheets under “Course participants”
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Optionale Anzeige des Geschlechts in Teilnehmerlisten u.Ä.
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Optionally display sex in (among others) lists of course participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kursverwalter können Teilnehmer hinzufügen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course administrators may enroll participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kurskürzel müssen nur innerhalb eines Instituts eindeutig sein
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Course shorthands now only need to be unique within a department
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Kurse haben nun einen Sichtbarkeitszeitraum.
|
||||||
2
templates/i18n/changelog/course-visibility.en-eu.hamlet
Normal file
2
templates/i18n/changelog/course-visibility.en-eu.hamlet
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Courses now have a visibility period.
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Bewertung von Kurs-Bewerbungen via CSV
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Grading of course applications via CSV
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Import & Export von CSV-Dateien für Klausurteilnehmer
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV import & export of exam participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV-Export für Liste von Kursteilnehmern exportiert nun optional alle Studiengangsdaten der Teilnehmer
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV export of course participants now optionally includes all features of study
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV-Export für Liste von Kursteilnehmern exportiert nun auch die angemeldeten Tutorien
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV export of course participants now includes registered tutorials
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV-Export für Liste von Kursteilnehmern
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV export of course participants
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
CSV-Export-Option um den beim import und export verwendeten Zeichensatz einzustellen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Introduced CSV export option to set the character encoding used
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Option um an die Namen aller heruntergeladenen CSV-Dateien einen Zeitstempel vorne anzuhängen
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
$newline never
|
||||||
|
Introduced option to timestamp all exported CSV files
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user