chore(users-add): confirm stub, migrate buttons
This commit is contained in:
parent
e65d38898e
commit
dfc017b10a
@ -121,6 +121,8 @@ CourseParticipantsAlreadyRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Tei
|
|||||||
CourseParticipantsAlreadyTutorialMember n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits in dieser Übungsgruppe angemeldet
|
CourseParticipantsAlreadyTutorialMember n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits in dieser Übungsgruppe angemeldet
|
||||||
CourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich angemeldet
|
CourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich angemeldet
|
||||||
CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Übungsgruppe angemeldet
|
CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Übungsgruppe angemeldet
|
||||||
|
CourseParticipantsRegisterConfirmationHeading: Teilnehmer:innen hinzufügen
|
||||||
|
|
||||||
CourseApplicationText: Text-Bewerbung
|
CourseApplicationText: Text-Bewerbung
|
||||||
CourseApplicationFollowInstructions: Beachten Sie die Anweisungen zur Bewerbung!
|
CourseApplicationFollowInstructions: Beachten Sie die Anweisungen zur Bewerbung!
|
||||||
CourseRegistrationText: Text zur Anmeldung
|
CourseRegistrationText: Text zur Anmeldung
|
||||||
|
|||||||
@ -121,6 +121,8 @@ CourseParticipantsAlreadyRegistered n: #{n} #{pluralEN n "participant is" "parti
|
|||||||
CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "participants are"} already registered for this tutorial
|
CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "participants are"} already registered for this tutorial
|
||||||
CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"}
|
CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"}
|
||||||
CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for tutorial
|
CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for tutorial
|
||||||
|
CourseParticipantsRegisterConfirmationHeading: Register participants
|
||||||
|
|
||||||
CourseApplicationText: Application text
|
CourseApplicationText: Application text
|
||||||
CourseApplicationFollowInstructions: Please follow the instructions for applications!
|
CourseApplicationFollowInstructions: Please follow the instructions for applications!
|
||||||
CourseRegistrationText: Registration text
|
CourseRegistrationText: Registration text
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
|
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
@ -65,4 +65,7 @@ BtnNotifyNewCourseForceOff: Nicht benachrichtigen
|
|||||||
BtnUserAssimilate: Assimilieren
|
BtnUserAssimilate: Assimilieren
|
||||||
BtnCloseExam: Prüfung abschließen
|
BtnCloseExam: Prüfung abschließen
|
||||||
BtnFinishExam: Prüfungsergebnisse sichtbar schalten
|
BtnFinishExam: Prüfungsergebnisse sichtbar schalten
|
||||||
BtnConfirm: Bestätigen
|
BtnConfirm: Bestätigen
|
||||||
|
BtnCourseRegisterAdd: Personen suchen
|
||||||
|
BtnCourseRegisterConfirm: Ausgewählte Personen anmelden
|
||||||
|
BtnCourseRegisterAbort: Abbrechen
|
||||||
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
|
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
@ -65,4 +65,7 @@ BtnNotifyNewCourseForceOff: Do not notify me
|
|||||||
BtnUserAssimilate: Assimilate
|
BtnUserAssimilate: Assimilate
|
||||||
BtnCloseExam: Close exam
|
BtnCloseExam: Close exam
|
||||||
BtnFinishExam: Make results visible
|
BtnFinishExam: Make results visible
|
||||||
BtnConfirm: Confirm
|
BtnConfirm: Confirm
|
||||||
|
BtnCourseRegisterAdd: Search persons
|
||||||
|
BtnCourseRegisterConfirm: Register selected persons
|
||||||
|
BtnCourseRegisterAbort: Abort
|
||||||
@ -13,9 +13,7 @@ import Handler.Utils.Avs
|
|||||||
|
|
||||||
import Jobs.Queue
|
import Jobs.Queue
|
||||||
|
|
||||||
--import Data.Aeson hiding (Result(..))
|
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
--import qualified Data.HashSet as HashSet
|
|
||||||
import Data.List (genericLength)
|
import Data.List (genericLength)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Text as Text
|
import qualified Data.Text as Text
|
||||||
@ -26,6 +24,26 @@ import Control.Monad.Except (MonadError(..))
|
|||||||
import Generics.Deriving.Monoid (memptydefault, mappenddefault)
|
import Generics.Deriving.Monoid (memptydefault, mappenddefault)
|
||||||
|
|
||||||
|
|
||||||
|
data ButtonCourseRegisterMode = BtnCourseRegisterAdd | BtnCourseRegisterConfirm | BtnCourseRegisterAbort
|
||||||
|
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
|
||||||
|
instance Universe ButtonCourseRegisterMode
|
||||||
|
instance Finite ButtonCourseRegisterMode
|
||||||
|
|
||||||
|
embedRenderMessage ''UniWorX ''ButtonCourseRegisterMode id
|
||||||
|
|
||||||
|
nullaryPathPiece ''ButtonCourseRegisterMode $ camelToPathPiece' 1
|
||||||
|
|
||||||
|
instance Button UniWorX ButtonCourseRegisterMode where
|
||||||
|
btnLabel x = [whamlet|_{x}|]
|
||||||
|
|
||||||
|
btnClasses BtnCourseRegisterAdd = [BCIsButton, BCPrimary]
|
||||||
|
btnClasses BtnCourseRegisterConfirm = [BCIsButton, BCPrimary]
|
||||||
|
btnClasses BtnCourseRegisterAbort = [BCIsButton, BCDanger]
|
||||||
|
|
||||||
|
btnValidate _ BtnCourseRegisterAbort = False
|
||||||
|
btnValidate _ _ = True
|
||||||
|
|
||||||
|
|
||||||
data AddUsers = AddUsers
|
data AddUsers = AddUsers
|
||||||
{ auUsers :: Set Text
|
{ auUsers :: Set Text
|
||||||
, auTutorial :: Maybe (CI Text)
|
, auTutorial :: Maybe (CI Text)
|
||||||
@ -120,11 +138,32 @@ postCAddUserR tid ssh csh = do
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--confirmAddUser :: ()
|
confirmAddUser :: Handler Html
|
||||||
--confirmAddUser = do
|
confirmAddUser = do
|
||||||
-- siteLayoutMsg MsgCourseParticipantsRegisterConfirmationHeading $ do
|
siteLayoutMsg MsgCourseParticipantsRegisterConfirmationHeading $ do
|
||||||
-- setTitleI MsgCourseParticipantsRegisterConfirmationHeading
|
setTitleI MsgCourseParticipantsRegisterConfirmationHeading
|
||||||
|
let
|
||||||
|
confirmCheckBox :: Widget
|
||||||
|
confirmCheckBox = do
|
||||||
|
let sJsonField :: Field (HandlerFor UniWorX) a
|
||||||
|
sJsonField = secretJsonField' $ \theId name attrs val _isReq ->
|
||||||
|
[whamlet|
|
||||||
|
$newline never
|
||||||
|
<input id=#{theId} *{attrs} type=checkbox name=#{name} value=#{either id id val} checked>
|
||||||
|
|]
|
||||||
|
fieldView sJsonField act mempty vAttrs (Right act) False
|
||||||
|
availableActs :: Widget
|
||||||
|
availableActs = fieldView (secretJsonField :: Field Handler (Set csvAction)) "" mempty [] (Right . Set.empty) False
|
||||||
|
(confirmForm', confirmEnctype) <- liftHandler . generateFormPost . withButtonForm' [BtnCourseRegisterConfirm, BtnCourseRegisterAbort] . identifyForm FIDCourseRegisterConfirm $ \csrf -> return (error "No meaningful FormResult", $(widgetFile "course/add-user/confirmation"))
|
||||||
|
let confirmForm = wrapForm confirmForm' FormSettings
|
||||||
|
{ formMethod = POST
|
||||||
|
, formAction = Just $ tblLink id
|
||||||
|
, formEncoding = confirmEnctype
|
||||||
|
, formAttrs = []
|
||||||
|
, formSubmit = FormNoSubmit
|
||||||
|
, formAnchor = Nothing :: Maybe Text
|
||||||
|
}
|
||||||
|
$(widgetFile "course/add-user/confirmation-wrapper")
|
||||||
|
|
||||||
|
|
||||||
registerUsers :: CourseId -> Map Text (Maybe UserId) -> WriterT [Message] (YesodJobDB UniWorX) ()
|
registerUsers :: CourseId -> Map Text (Maybe UserId) -> WriterT [Message] (YesodJobDB UniWorX) ()
|
||||||
|
|||||||
@ -283,7 +283,7 @@ data FormIdentifier
|
|||||||
| FIDDBTableCsvImportConfirm Text
|
| FIDDBTableCsvImportConfirm Text
|
||||||
| FIDDelete
|
| FIDDelete
|
||||||
| FIDPrintAcknowledge
|
| FIDPrintAcknowledge
|
||||||
| FIDCourseRegister
|
| FIDCourseRegister | FIDCourseRegisterConfirm
|
||||||
| FIDuserRights
|
| FIDuserRights
|
||||||
| FIDUserSystemFunctions
|
| FIDUserSystemFunctions
|
||||||
| FIDcUserNote
|
| FIDcUserNote
|
||||||
|
|||||||
10
templates/course/add-user/confirmation-wrapper.hamlet
Normal file
10
templates/course/add-user/confirmation-wrapper.hamlet
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
$newline never
|
||||||
|
|
||||||
|
$# SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
||||||
|
$#
|
||||||
|
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>_{MsgCourseAddUserConfirmationTip}
|
||||||
|
<section>
|
||||||
|
^{confirmForm}
|
||||||
27
templates/course/add-user/confirmation.hamlet
Normal file
27
templates/course/add-user/confirmation.hamlet
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
$newline never
|
||||||
|
|
||||||
|
$# SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
||||||
|
$#
|
||||||
|
$# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
#{csrf}
|
||||||
|
^{availableActs}
|
||||||
|
<div .actions>
|
||||||
|
$forall actionClass <- sortOn dbtCsvCoarsenActionClass (Map.keys actionMap)
|
||||||
|
<div .action>
|
||||||
|
<input type=checkbox id=#{actionClassIdent actionClass} .action__checkbox :defaultChecked actionClass:checked>
|
||||||
|
<label .action__label for=#{actionClassIdent actionClass}>
|
||||||
|
^{dbtCsvRenderActionClass actionClass}
|
||||||
|
|
||||||
|
<fieldset .action__fieldset uw-interactive-fieldset .interactive-fieldset__target data-conditional-input=#{actionClassIdent actionClass}>
|
||||||
|
<div .action__checked-counter>
|
||||||
|
<div .action__toggle-all>
|
||||||
|
<input type=checkbox id=#{actionClassIdent actionClass}-toggle-all>
|
||||||
|
<label for=#{actionClassIdent actionClass}-toggle-all .action__option-label>
|
||||||
|
_{MsgDBCsvImportActionToggleAll}
|
||||||
|
<div .action__options>
|
||||||
|
$forall action <- Set.toList (actionMap ! actionClass)
|
||||||
|
<div .action__option>
|
||||||
|
^{csvActionCheckBox [] action}
|
||||||
|
<label .action__option-label for=#{actionIdent action}>
|
||||||
|
^{dbtCsvRenderKey existing action}
|
||||||
85
templates/course/add-user/confirmation.julius
Normal file
85
templates/course/add-user/confirmation.julius
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var IMPORT_ACTIONS_SELECTOR = '.actions';
|
||||||
|
var IMPORT_ACTION_SELECTOR = '.action';
|
||||||
|
var IMPORT_ACTION_CHECKBOX_SELECTOR = '.action__checkbox ';
|
||||||
|
var IMPORT_ACTION_OPTIONS_SELECTOR = '.action__options';
|
||||||
|
var IMPORT_ACTION_TOGGLE_ALL_SELECTOR = '.action__toggle-all [type="checkbox"]';
|
||||||
|
var IMPORT_ACTION_CHECKED_COUNTER_SELECTOR = '.action__checked-counter';
|
||||||
|
|
||||||
|
var importActionsElement;
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
importActionsElement = document.querySelector(IMPORT_ACTIONS_SELECTOR);
|
||||||
|
|
||||||
|
setupActions();
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupActions() {
|
||||||
|
var actionElements = Array.from(importActionsElement.querySelectorAll(IMPORT_ACTION_SELECTOR));
|
||||||
|
|
||||||
|
actionElements.forEach(function(element) {
|
||||||
|
setupAction(element);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupAction(actionElement) {
|
||||||
|
var actionCheckbox = actionElement.querySelector(IMPORT_ACTION_CHECKBOX_SELECTOR);
|
||||||
|
var actionOptions = actionElement.querySelector(IMPORT_ACTION_OPTIONS_SELECTOR);
|
||||||
|
if (actionOptions) {
|
||||||
|
var actionCheckboxes = Array.from(actionOptions.querySelectorAll('[type="checkbox"]'));
|
||||||
|
var toggleAllCheckbox = actionElement.querySelector(IMPORT_ACTION_TOGGLE_ALL_SELECTOR);
|
||||||
|
|
||||||
|
// setup action checkbox to toggle all child checkboxes if changed
|
||||||
|
actionCheckbox.addEventListener('change', function() {
|
||||||
|
actionCheckboxes.forEach(function(checkbox) {
|
||||||
|
checkbox.checked = actionCheckbox.checked;
|
||||||
|
});
|
||||||
|
updateCheckedCounter(actionElement, actionCheckboxes);
|
||||||
|
updateToggleAllCheckbox(toggleAllCheckbox, actionCheckboxes);
|
||||||
|
});
|
||||||
|
|
||||||
|
// update counter and toggle checkbox initially
|
||||||
|
updateCheckedCounter(actionElement, actionCheckboxes);
|
||||||
|
updateToggleAllCheckbox(toggleAllCheckbox, actionCheckboxes);
|
||||||
|
|
||||||
|
// register change listener for individual checkboxes
|
||||||
|
actionCheckboxes.forEach(function(checkbox) {
|
||||||
|
checkbox.addEventListener('change', function() {
|
||||||
|
updateCheckedCounter(actionElement, actionCheckboxes);
|
||||||
|
updateToggleAllCheckbox(toggleAllCheckbox, actionCheckboxes);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// register change listener for toggle all checkbox
|
||||||
|
if (toggleAllCheckbox) {
|
||||||
|
toggleAllCheckbox.addEventListener('change', function() {
|
||||||
|
actionCheckboxes.forEach(function(checkbox) {
|
||||||
|
checkbox.checked = toggleAllCheckbox.checked;
|
||||||
|
});
|
||||||
|
updateCheckedCounter(actionElement, actionCheckboxes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update checked state of toggle all checkbox based on all other checkboxes
|
||||||
|
function updateToggleAllCheckbox(toggleAllCheckbox, actionCheckboxes) {
|
||||||
|
var allChecked = actionCheckboxes.reduce(function(acc, checkbox) {
|
||||||
|
return acc && checkbox.checked;
|
||||||
|
}, true);
|
||||||
|
toggleAllCheckbox.checked = allChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update value of checked counter
|
||||||
|
function updateCheckedCounter(actionElement, actionCheckboxes) {
|
||||||
|
var checkedCounter = actionElement.querySelector(IMPORT_ACTION_CHECKED_COUNTER_SELECTOR);
|
||||||
|
var checkedCheckboxes = actionCheckboxes.reduce(function(acc, checkbox) { return checkbox.checked ? acc + 1 : acc; }, 0);
|
||||||
|
checkedCounter.innerHTML = checkedCheckboxes + '/' + actionCheckboxes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user