From aea2f10e0fc17efbd30c0538ec8ce849d1a6480e Mon Sep 17 00:00:00 2001 From: Steffen Jost Date: Sun, 31 Mar 2019 20:26:09 +0200 Subject: [PATCH 001/519] minor --- src/Handler/Admin.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Handler/Admin.hs b/src/Handler/Admin.hs index 2ee38518b..ad3b77383 100644 --- a/src/Handler/Admin.hs +++ b/src/Handler/Admin.hs @@ -404,7 +404,7 @@ postAdminFeaturesR = do ] dbtSorting = Map.fromList [ ("key" , SortColumn (E.^. StudyTermsKey)) - , ("isnew" , SortColumn (\studyTerm -> studyTerm E.^. StudyTermsKey `E.in_` E.valList (unStudyTermsKey <$> Set.toList newKeys))) + , ("isnew" , SortColumn (\studyTerm -> studyTerm E.^. StudyTermsKey `E.in_` E.valList (unStudyTermsKey <$> Set.toList newKeys))) -- works only once -- Remember: sorting with E.in_ by StudyTermsId instead will produce esqueleto-error "unsafeSqlBinOp: non-id/composite keys not expected here" , ("isbad" , SortColumn (\studyTerm -> studyTerm E.^. StudyTermsKey `E.in_` E.valList (unStudyTermsKey <$> Set.toList badKeys))) , ("name" , SortColumn (E.^. StudyTermsName)) @@ -416,7 +416,7 @@ postAdminFeaturesR = do } psValidator = def -- & defaultSorting [SortAscBy "name", SortAscBy "short", SortAscBy "key"] - & defaultSorting [SortDescBy "isbad", SortDescBy "isnew", SortAscBy "key"] + & defaultSorting [SortDescBy "isnew", SortDescBy "isbad", SortAscBy "key"] in dbTable psValidator DBTable{..} mkCandidateTable = From 97800303438a361a73bb6573b506490af29940d0 Mon Sep 17 00:00:00 2001 From: Steffen Jost Date: Sun, 31 Mar 2019 21:15:46 +0200 Subject: [PATCH 002/519] Session: newness for StudyTerms lasts longer --- messages/uniworx/de.msg | 2 ++ src/Foundation.hs | 2 +- src/Handler/Admin.hs | 29 ++++++++++++++++++----------- src/Utils.hs | 4 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/messages/uniworx/de.msg b/messages/uniworx/de.msg index 2c90d5524..7d51240f3 100644 --- a/messages/uniworx/de.msg +++ b/messages/uniworx/de.msg @@ -1,3 +1,5 @@ +PrintDebugForStupid name@Text: Debug message "#{name}" + BtnSubmit: Senden BtnAbort: Abbrechen BtnDelete: Löschen diff --git a/src/Foundation.hs b/src/Foundation.hs index b2ed47c49..0d8e5d909 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -1001,7 +1001,7 @@ siteLayout' headingOverride widget = do | isModal -> getMessages | otherwise -> do applySystemMessages - authTagPivots <- fromMaybe Set.empty <$> getSessionJson SessionInactiveAuthTags + authTagPivots <- fromMaybe Set.empty <$> takeSessionJson SessionInactiveAuthTags forM_ authTagPivots $ \authTag -> addMessageWidget Info $ modal [whamlet|_{MsgUnauthorizedDisabledTag authTag}|] (Left $ SomeRoute (AuthPredsR, catMaybes [(toPathPiece GetReferer, ) . toPathPiece <$> mcurrentRoute])) getMessages diff --git a/src/Handler/Admin.hs b/src/Handler/Admin.hs index ad3b77383..19b84adf3 100644 --- a/src/Handler/Admin.hs +++ b/src/Handler/Admin.hs @@ -286,6 +286,9 @@ instance Button UniWorX ButtonAdminStudyTerms where btnClasses BtnCandidatesDeleteAll = [BCIsButton, BCDanger] -- END Button needed only here +sessionKeyNewStudyTerms :: Text +sessionKeyNewStudyTerms = "key-new-study-terms" + getAdminFeaturesR, postAdminFeaturesR :: Handler Html getAdminFeaturesR = postAdminFeaturesR postAdminFeaturesR = do @@ -295,34 +298,38 @@ postAdminFeaturesR = do , formEncoding = btnEnctype , formSubmit = FormNoSubmit } - (infConflicts,infAccepted) <- case btnResult of + infConflicts <- case btnResult of FormSuccess BtnCandidatesInfer -> do (infConflicts, infAmbiguous, infRedundant, infAccepted) <- Candidates.inferHandler unless (null infAmbiguous) . addMessageI Info . MsgAmbiguousCandidatesRemoved $ length infAmbiguous unless (null infRedundant) . addMessageI Info . MsgRedundantCandidatesRemoved $ length infRedundant - if - | null infAccepted - -> addMessageI Info MsgNoCandidatesInferred - | otherwise - -> addMessageI Success . MsgCandidatesInferred $ length infAccepted - return (infConflicts, infAccepted) + let newKeys = map (StudyTermsKey' . fst) infAccepted + setSessionJson sessionKeyNewStudyTerms newKeys + -- addMessageI Error $ MsgPrintDebugForStupid $ tshow newKeys + if | null infAccepted + -> addMessageI Info MsgNoCandidatesInferred + | otherwise + -> addMessageI Success . MsgCandidatesInferred $ length infAccepted + return infConflicts FormSuccess BtnCandidatesDeleteConflicts -> runDB $ do confs <- Candidates.conflicts incis <- Candidates.getIncidencesFor (entityKey <$> confs) deleteWhere [StudyTermCandidateIncidence <-. (E.unValue <$> incis)] addMessageI Success $ MsgIncidencesDeleted $ length incis - return ([],[]) + return [] FormSuccess BtnCandidatesDeleteAll -> runDB $ do deleteWhere ([] :: [Filter StudyTermCandidate]) addMessageI Success MsgAllIncidencesDeleted - (, []) <$> Candidates.conflicts - _other -> (, []) <$> runDB Candidates.conflicts + Candidates.conflicts + _other -> runDB Candidates.conflicts + newStudyTermKeys <- fromMaybe [] <$> lookupSessionJson sessionKeyNewStudyTerms + -- addMessageI Error $ MsgPrintDebugForStupid $ tshow newStudyTermKeys ( (degreeResult,degreeTable) , (studyTermsResult,studytermsTable) , ((), candidateTable)) <- runDB $ (,,) <$> mkDegreeTable - <*> mkStudytermsTable (Set.fromList $ map (StudyTermsKey' . fst) infAccepted) + <*> mkStudytermsTable (Set.fromList newStudyTermKeys) (Set.fromList $ map entityKey infConflicts) <*> mkCandidateTable diff --git a/src/Utils.hs b/src/Utils.hs index f6ebd76d6..bd0998561 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -610,9 +610,9 @@ modifySessionJson (toPathPiece -> key) f = lookupSessionJson key >>= maybe (dele tellSessionJson :: (PathPiece k, FromJSON v, ToJSON v, MonadHandler m, Monoid v) => k -> v -> m () tellSessionJson key val = modifySessionJson key $ Just . (`mappend` val) . fromMaybe mempty -getSessionJson :: (PathPiece k, FromJSON v, MonadHandler m) => k -> m (Maybe v) +takeSessionJson :: (PathPiece k, FromJSON v, MonadHandler m) => k -> m (Maybe v) -- ^ `lookupSessionJson` followed by `deleteSession` -getSessionJson key = lookupSessionJson key <* deleteSession (toPathPiece key) +takeSessionJson key = lookupSessionJson key <* deleteSession (toPathPiece key) -------------------- -- GET Parameters -- From b84032d0b9ac7b506bef42688a8fd3d8b411853d Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Sun, 31 Mar 2019 20:31:07 +0200 Subject: [PATCH 003/519] dont initialize forms inside modals wihout modal headers --- static/js/utils/form.js | 9 ++++++++- static/js/utils/modal.js | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/static/js/utils/form.js b/static/js/utils/form.js index e45fd56c0..2e9bbc92b 100644 --- a/static/js/utils/form.js +++ b/static/js/utils/form.js @@ -20,8 +20,15 @@ } window.utils.form = function(form, options) { + options = options || {}; - if (form.classList.contains(JS_INITIALIZED)) { + // dont initialize form if it is in a modal and is not forced + if (form.closest('.modal') && !options.force) { + return false; + } + + // dont initialize form if already initialized and should not be force-initialized + if (form.classList.contains(JS_INITIALIZED) && !options.force) { return false; } diff --git a/static/js/utils/modal.js b/static/js/utils/modal.js index 5c6c1ec43..a5971edf7 100644 --- a/static/js/utils/modal.js +++ b/static/js/utils/modal.js @@ -75,7 +75,7 @@ function setupForm() { var form = modalElement.querySelector('form'); if (form) { - utilInstances.push(window.utils.setup('form', form, { headers: MODAL_HEADERS })); + utilInstances.push(window.utils.setup('form', form, { headers: MODAL_HEADERS, force: true })); } } From 44684f39985a250c8756d2ac613c026a2d1330e4 Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Mon, 1 Apr 2019 22:17:43 +0200 Subject: [PATCH 004/519] clean inputs javascript --- static/js/utils/inputs.js | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/static/js/utils/inputs.js b/static/js/utils/inputs.js index fd4ad906e..3a9f7ebc4 100644 --- a/static/js/utils/inputs.js +++ b/static/js/utils/inputs.js @@ -3,37 +3,37 @@ window.utils = window.utils || {}; - var JS_INITIALIZED_CLASS = 'js-initialized'; - - function isNotInitialized(element) { - return !element.classList.contains(JS_INITIALIZED_CLASS); - } + var JS_INITIALIZED_CLASS = 'js-inputs-initialized'; window.utils.inputs = function(wrapper, options) { - + options = options || {}; var utilInstances = []; + if (wrapper.classList.contains(JS_INITIALIZED_CLASS) && !options.force) { + return false; + } + // checkboxes var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"]')); - checkboxes.filter(isNotInitialized).forEach(function(checkbox) { + checkboxes.forEach(function(checkbox) { utilInstances.push(window.utils.setup('checkbox', checkbox)); }); // radios var radios = Array.from(wrapper.querySelectorAll('input[type="radio"]')); - radios.filter(isNotInitialized).forEach(function(radio) { + radios.forEach(function(radio) { utilInstances.push(window.utils.setup('radio', radio)); }); // file-uploads var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]')); - fileUploads.filter(isNotInitialized).forEach(function(input) { + fileUploads.forEach(function(input) { utilInstances.push(window.utils.setup('fileUpload', input, options)); }); // file-checkboxes var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox')); - fileCheckboxes.filter(isNotInitialized).forEach(function(input) { + fileCheckboxes.forEach(function(input) { utilInstances.push(window.utils.setup('fileCheckbox', input, options)); }); @@ -45,6 +45,8 @@ }); } + wrapper.classList.add(JS_INITIALIZED_CLASS); + return { scope: wrapper, destroy: destroyUtils, @@ -74,7 +76,6 @@ if (!i18n) { throw new Error('window.utils.fileUpload(input, options) needs to be passed i18n object via options'); } - input.classList.add(JS_INITIALIZED_CLASS); function renderFileList(files) { fileList.innerHTML = ''; @@ -166,8 +167,6 @@ cont = cont.parentNode; } addListener(cont); - input.classList.add(JS_INITIALIZED_CLASS); - cont.classList.add(JS_INITIALIZED_CLASS); } setup(); @@ -190,7 +189,6 @@ labelEl.setAttribute('for', input.id); wrapperEl.appendChild(input); wrapperEl.appendChild(labelEl); - input.classList.add(JS_INITIALIZED_CLASS); if (siblingEl) { parentEl.insertBefore(wrapperEl, siblingEl); @@ -219,7 +217,6 @@ wrapperEl.appendChild(siblingEl); } - input.classList.add(JS_INITIALIZED_CLASS); parentEl.appendChild(wrapperEl); } @@ -233,8 +230,6 @@ window.utils.implicitSubmit = function(input, options) { var submit = options.submit; - console.log('implicitSubmit', input, submit); - if (!submit) { throw new Error('window.utils.implicitSubmit(input, options) needs to be passed a submit element via options'); } @@ -247,7 +242,7 @@ }; input.addEventListener('keypress', doSubmit); - + return { scope: input, destroy: function() { From ec50d27bd7dfa346e4e6d10cf5c9fd56d616ccc3 Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Mon, 1 Apr 2019 22:32:22 +0200 Subject: [PATCH 005/519] refinement of section spacing --- templates/adminTest.hamlet | 11 ++++------- templates/default-layout.lucius | 6 ++---- templates/table/layout-filter-default.lucius | 1 - 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/templates/adminTest.hamlet b/templates/adminTest.hamlet index 75622355e..7e59d9599 100644 --- a/templates/adminTest.hamlet +++ b/templates/adminTest.hamlet @@ -1,17 +1,14 @@ -
-

Uni2work - Admin Demopage - +

Diese interne Seite dient lediglich zum Testen diverser Funktionalitäten und zur Demonstration der verschiedenen Hilfsfunktionen/Module. Der Handler sollte jeweils aktuelle Beispiele für alle möglichen Funktionalitäten enthalten, so dass man immer weiß, wo man nachschlagen kann. - -

+

Teilweise funktionierende Abschnitte -