Rework recipient UI
This commit is contained in:
parent
45ea84e663
commit
feee06e80a
@ -205,7 +205,7 @@ postAdminTestR = do
|
|||||||
|
|
||||||
-- The actual call to @massInput@ is comparatively simple:
|
-- The actual call to @massInput@ is comparatively simple:
|
||||||
|
|
||||||
((miResult, fvInput -> miForm), miEnc) <- runFormPost . identifyForm ("massinput" :: Text) $ massInput (MassInput mkAddForm mkCellForm deleteCell allowAdd buttonAction defaultMiLayout) "" True Nothing
|
((miResult, fvInput -> miForm), miEnc) <- runFormPost . identifyForm ("massinput" :: Text) $ massInput (MassInput mkAddForm mkCellForm deleteCell allowAdd (\_ _ _ -> Set.empty) buttonAction defaultMiLayout) "" True Nothing
|
||||||
|
|
||||||
|
|
||||||
let locallyDefinedPageHeading = [whamlet|Admin TestPage for Uni2work|]
|
let locallyDefinedPageHeading = [whamlet|Admin TestPage for Uni2work|]
|
||||||
|
|||||||
@ -661,6 +661,9 @@ makeCourseForm miButtonAction template = identifyForm FIDcourse $ \html -> do
|
|||||||
miAllowAdd :: ListPosition -> Natural -> ListLength -> Bool
|
miAllowAdd :: ListPosition -> Natural -> ListLength -> Bool
|
||||||
miAllowAdd _ _ _ = True
|
miAllowAdd _ _ _ = True
|
||||||
|
|
||||||
|
miAddEmpty :: ListPosition -> Natural -> ListLength -> Set ListPosition
|
||||||
|
miAddEmpty _ _ _ = Set.empty
|
||||||
|
|
||||||
miLayout :: ListLength
|
miLayout :: ListLength
|
||||||
-> Map ListPosition (Either UserEmail UserId, FormResult (Maybe LecturerType)) -- ^ massInput state
|
-> Map ListPosition (Either UserEmail UserId, FormResult (Maybe LecturerType)) -- ^ massInput state
|
||||||
-> Map ListPosition Widget -- ^ Cell widgets
|
-> Map ListPosition Widget -- ^ Cell widgets
|
||||||
|
|||||||
@ -139,13 +139,15 @@ commR CommunicationRoute{..} = do
|
|||||||
return (addRes', $(widgetFile "widgets/communication/recipientAdd"))
|
return (addRes', $(widgetFile "widgets/communication/recipientAdd"))
|
||||||
miAdd _ _ _ _ = Nothing
|
miAdd _ _ _ _ = Nothing
|
||||||
miCell _ (Left (CI.original -> email)) initRes nudge csrf = do
|
miCell _ (Left (CI.original -> email)) initRes nudge csrf = do
|
||||||
(tickRes, tickView) <- mpreq checkBoxField ("" & addName (nudge "tick")) initRes
|
(tickRes, tickView) <- mpreq checkBoxField ("" & addName (nudge "tick")) $ initRes <|> Just True
|
||||||
return (tickRes, $(widgetFile "widgets/communication/recipientEmail"))
|
return (tickRes, $(widgetFile "widgets/communication/recipientEmail"))
|
||||||
miCell _ (Right (lookupUser -> User{..})) initRes nudge csrf = do
|
miCell _ (Right (lookupUser -> User{..})) initRes nudge csrf = do
|
||||||
(tickRes, tickView) <- mpreq checkBoxField ("" & addName (nudge "tick")) initRes
|
(tickRes, tickView) <- mpreq checkBoxField ("" & addName (nudge "tick")) $ initRes <|> Just True
|
||||||
return (tickRes, $(widgetFile "widgets/communication/recipientName"))
|
return (tickRes, $(widgetFile "widgets/communication/recipientName"))
|
||||||
miAllowAdd (EnumPosition RecipientCustom, 0) 1 _ = True
|
miAllowAdd (EnumPosition RecipientCustom, 0) 1 _ = True
|
||||||
miAllowAdd _ _ _ = False
|
miAllowAdd _ _ _ = False
|
||||||
|
miAddEmpty _ 0 _ = Set.singleton (EnumPosition RecipientCustom, 0)
|
||||||
|
miAddEmpty _ _ _ = Set.empty
|
||||||
miButtonAction :: forall p . PathPiece p => p -> Maybe (SomeRoute UniWorX)
|
miButtonAction :: forall p . PathPiece p => p -> Maybe (SomeRoute UniWorX)
|
||||||
miButtonAction anchor = SomeRoute . (:#: anchor) <$> mbCurrentRoute
|
miButtonAction anchor = SomeRoute . (:#: anchor) <$> mbCurrentRoute
|
||||||
miLayout :: MapLiveliness (EnumLiveliness RecipientCategory) ListLength
|
miLayout :: MapLiveliness (EnumLiveliness RecipientCategory) ListLength
|
||||||
@ -156,7 +158,7 @@ commR CommunicationRoute{..} = do
|
|||||||
-> Widget
|
-> Widget
|
||||||
miLayout liveliness state cellWdgts _delButtons addWdgts = do
|
miLayout liveliness state cellWdgts _delButtons addWdgts = do
|
||||||
checkedIdentBase <- newIdent
|
checkedIdentBase <- newIdent
|
||||||
let checkedCategories = Set.mapMonotonic (unEnumPosition . fst) . Set.filter (\k' -> Map.foldrWithKey (\k (_, checkState) -> (||) $ k == k' && checkState /= FormSuccess False && checkState /= FormMissing) False state) $ Map.keysSet state
|
let checkedCategories = Set.mapMonotonic (unEnumPosition . fst) . Set.filter (\k' -> Map.foldrWithKey (\k (_, checkState) -> (||) $ k == k' && checkState /= FormSuccess False && (checkState /= FormMissing || fromMaybe True (fmap snd $ chosenRecipients' !? k))) False state) $ Map.keysSet state
|
||||||
checkedIdent c = checkedIdentBase <> "-" <> toPathPiece c
|
checkedIdent c = checkedIdentBase <> "-" <> toPathPiece c
|
||||||
categoryIndices c = Set.filter ((== c) . unEnumPosition . fst) $ review liveCoords liveliness
|
categoryIndices c = Set.filter ((== c) . unEnumPosition . fst) $ review liveCoords liveliness
|
||||||
$(widgetFile "widgets/communication/recipientLayout")
|
$(widgetFile "widgets/communication/recipientLayout")
|
||||||
|
|||||||
@ -249,6 +249,10 @@ data MassInput handler liveliness cellData cellResult = MassInput
|
|||||||
-> Natural
|
-> Natural
|
||||||
-> liveliness
|
-> liveliness
|
||||||
-> Bool -- ^ Decide whether an addition-operation should be permitted
|
-> Bool -- ^ Decide whether an addition-operation should be permitted
|
||||||
|
, miAddEmpty :: BoxCoord liveliness
|
||||||
|
-> Natural
|
||||||
|
-> liveliness
|
||||||
|
-> Set (BoxCoord liveliness) -- ^ Usually addition widgets are only provided for dimension 0 and all _lines_ that have at least one live coordinate. `miAddEmpty` allows specifying when to provide additional widgets
|
||||||
, miButtonAction :: forall p. PathPiece p => p -> Maybe (SomeRoute UniWorX) -- ^ Override form-tag route for `massInput`-Buttons to keep the user closer to the Widget, the `PathPiece` Argument is to be used for constructiong a `Fragment`
|
, miButtonAction :: forall p. PathPiece p => p -> Maybe (SomeRoute UniWorX) -- ^ Override form-tag route for `massInput`-Buttons to keep the user closer to the Widget, the `PathPiece` Argument is to be used for constructiong a `Fragment`
|
||||||
, miLayout :: liveliness
|
, miLayout :: liveliness
|
||||||
-> Map (BoxCoord liveliness) (cellData, FormResult cellResult)
|
-> Map (BoxCoord liveliness) (cellData, FormResult cellResult)
|
||||||
@ -293,10 +297,10 @@ massInput MassInput{..} FieldSettings{..} fvRequired initialResult csrf = do
|
|||||||
sentLiveliness <- maybe (throwM MassInputInvalidShape) return $ Map.keysSet sentShape' ^? liveCoords :: MForm handler liveliness
|
sentLiveliness <- maybe (throwM MassInputInvalidShape) return $ Map.keysSet sentShape' ^? liveCoords :: MForm handler liveliness
|
||||||
|
|
||||||
let addForm :: [BoxDimension (BoxCoord liveliness)] -> MForm handler (Map (Natural, BoxCoord liveliness) (FormResult (Maybe (Map (BoxCoord liveliness) cellData -> FormResult (Map (BoxCoord liveliness) cellData))), Maybe Widget))
|
let addForm :: [BoxDimension (BoxCoord liveliness)] -> MForm handler (Map (Natural, BoxCoord liveliness) (FormResult (Maybe (Map (BoxCoord liveliness) cellData -> FormResult (Map (BoxCoord liveliness) cellData))), Maybe Widget))
|
||||||
addForm = addForm' boxOrigin . zip [0..]
|
addForm = addForm' boxOrigin [] . zip [0..]
|
||||||
where
|
where
|
||||||
addForm' _ [] = return Map.empty
|
addForm' _ _ [] = return Map.empty
|
||||||
addForm' miCoord ((dimIx, _) : remDims) = do
|
addForm' miCoord pDims (dim''@(dimIx, _) : remDims) = do
|
||||||
let nudgeAddWidgetName :: Text -> Text
|
let nudgeAddWidgetName :: Text -> Text
|
||||||
nudgeAddWidgetName miAddWidgetField = toPathPiece MassInputAddWidget{..}
|
nudgeAddWidgetName miAddWidgetField = toPathPiece MassInputAddWidget{..}
|
||||||
(btnRes', btnView) <- mopt (buttonField $ MassInputAddDimension dimIx miCoord) ("" & addName MassInputAddButton{..} & addFormAction) Nothing
|
(btnRes', btnView) <- mopt (buttonField $ MassInputAddDimension dimIx miCoord) ("" & addName MassInputAddButton{..} & addFormAction) Nothing
|
||||||
@ -312,12 +316,12 @@ massInput MassInput{..} FieldSettings{..} fvRequired initialResult csrf = do
|
|||||||
case remDims of
|
case remDims of
|
||||||
[] -> return dimRes'
|
[] -> return dimRes'
|
||||||
((_, BoxDimension dim) : _) -> do
|
((_, BoxDimension dim) : _) -> do
|
||||||
let
|
let miCoords
|
||||||
miCoords
|
= Set.union (miAddEmpty miCoord dimIx sentLiveliness)
|
||||||
= Set.fromList
|
. Set.map (\c -> miCoord & dim .~ (c ^. dim))
|
||||||
. takeWhile (\c -> review (liveCoord c) sentLiveliness)
|
. Set.filter (\c -> and [ ((==) `on` view pDim) miCoord c | (_, BoxDimension pDim) <- pDims `snoc` dim'' ])
|
||||||
$ set dim <$> enumFrom (miCoord ^. dim) <*> pure miCoord
|
$ review liveCoords sentLiveliness
|
||||||
dimRess <- sequence $ Map.fromSet (\c -> addForm' c remDims) miCoords
|
dimRess <- sequence $ Map.fromSet (\c -> addForm' c (pDims `snoc` dim'') remDims) miCoords
|
||||||
return $ dimRes' `Map.union` fold dimRess
|
return $ dimRes' `Map.union` fold dimRess
|
||||||
|
|
||||||
addResults <- addForm boxDimensions
|
addResults <- addForm boxDimensions
|
||||||
@ -458,6 +462,7 @@ massInputList field fieldSettings miButtonAction miSettings miRequired miPrevRes
|
|||||||
over _2 (\FieldView{..} -> $(widgetFile "widgets/massinput/list/cell")) <$> mreq field (fieldSettings pos & addName (nudge "field")) iRes
|
over _2 (\FieldView{..} -> $(widgetFile "widgets/massinput/list/cell")) <$> mreq field (fieldSettings pos & addName (nudge "field")) iRes
|
||||||
, miDelete = miDeleteList
|
, miDelete = miDeleteList
|
||||||
, miAllowAdd = \_ _ _ -> True
|
, miAllowAdd = \_ _ _ -> True
|
||||||
|
, miAddEmpty = \_ _ _ -> Set.empty
|
||||||
, miButtonAction
|
, miButtonAction
|
||||||
, miLayout = \lLength _ cellWdgts delButtons addWdgts
|
, miLayout = \lLength _ cellWdgts delButtons addWdgts
|
||||||
-> $(widgetFile "widgets/massinput/list/layout")
|
-> $(widgetFile "widgets/massinput/list/layout")
|
||||||
|
|||||||
@ -150,13 +150,14 @@
|
|||||||
|
|
||||||
var INTERACTIVE_FIELDSET_UTIL_NAME = 'interactiveFieldset';
|
var INTERACTIVE_FIELDSET_UTIL_NAME = 'interactiveFieldset';
|
||||||
var INTERACTIVE_FIELDSET_UTIL_SELECTOR = '[uw-interactive-fieldset]';
|
var INTERACTIVE_FIELDSET_UTIL_SELECTOR = '[uw-interactive-fieldset]';
|
||||||
|
var INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR = '.interactive-fieldset--target';
|
||||||
|
|
||||||
var INTERACTIVE_FIELDSET_INITIALIZED_CLASS = 'interactive-fieldset--initialized';
|
var INTERACTIVE_FIELDSET_INITIALIZED_CLASS = 'interactive-fieldset--initialized';
|
||||||
|
|
||||||
var interactiveFieldsetUtil = function(element) {
|
var interactiveFieldsetUtil = function(element) {
|
||||||
var conditionalInput;
|
var conditionalInput;
|
||||||
var conditionalValue;
|
var conditionalValue;
|
||||||
var formGroup;
|
var target;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@ -183,9 +184,14 @@
|
|||||||
}
|
}
|
||||||
conditionalValue = element.dataset.conditionalValue;
|
conditionalValue = element.dataset.conditionalValue;
|
||||||
|
|
||||||
formGroup = element.closest(FORM_GROUP_SELECTOR);
|
if (element.matches(INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR)) {
|
||||||
if (!formGroup) {
|
target = element;
|
||||||
throw new Error('Interactive Fieldset needs a .form-group ancestor!');
|
}
|
||||||
|
if (!target) {
|
||||||
|
target = element.closest(INTERACTIVE_FIELDSET_UTIL_TARGET_SELECTOR);
|
||||||
|
}
|
||||||
|
if (!target) {
|
||||||
|
throw new Error('Interactive Fieldset needs to be a target or have a target-ancestor!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// add event listener
|
// add event listener
|
||||||
@ -205,7 +211,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateVisibility() {
|
function updateVisibility() {
|
||||||
element.classList.toggle('hidden', !matchesConditionalValue());
|
target.classList.toggle('hidden', !matchesConditionalValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchesConditionalValue() {
|
function matchesConditionalValue() {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ $case formLayout
|
|||||||
<h3 .form-section-title>
|
<h3 .form-section-title>
|
||||||
^{fvLabel view}
|
^{fvLabel view}
|
||||||
$else
|
$else
|
||||||
<div .form-group :fvRequired view:.form-group--required :not $ fvRequired view:.form-group--optional :isJust $ fvErrors view:.form-group--has-error>
|
<div .form-group .interactive-fieldset--target :fvRequired view:.form-group--required :not $ fvRequired view:.form-group--optional :isJust $ fvErrors view:.form-group--has-error>
|
||||||
$if not (Blaze.null $ fvLabel view)
|
$if not (Blaze.null $ fvLabel view)
|
||||||
<label .form-group-label for=#{fvId view}>
|
<label .form-group-label for=#{fvId view}>
|
||||||
<span .form-group-label__caption>
|
<span .form-group-label__caption>
|
||||||
|
|||||||
@ -5,9 +5,9 @@ $forall category <- activeCategories
|
|||||||
<label for=#{checkedIdent category}>
|
<label for=#{checkedIdent category}>
|
||||||
_{category}
|
_{category}
|
||||||
|
|
||||||
<fieldset uw-interactive-fieldset data-conditional-input=#{checkedIdent category}>
|
<fieldset uw-interactive-fieldset data-conditional-input=#{checkedIdent category} .interactive-fieldset--target>
|
||||||
$forall optIx <- categoryIndices category
|
$forall optIx <- categoryIndices category
|
||||||
^{cellWdgts ! optIx}
|
^{cellWdgts ! optIx}
|
||||||
|
|
||||||
$maybe addWdgt <- addWdgts !? (0, (EnumPosition category, 0))
|
$maybe addWdgt <- addWdgts !? (1, (EnumPosition category, 0))
|
||||||
^{addWdgt}
|
^{addWdgt}
|
||||||
|
|||||||
Reference in New Issue
Block a user