Generic and "safe" deletion widget
This commit is contained in:
parent
45182e5074
commit
c6b7ad0580
@ -74,6 +74,8 @@ CourseRegisterToTip: Anmeldung darf auch ohne Begrenzung möglich sein
|
|||||||
CourseDeregisterUntilTip: Abmeldung darf auch ohne Begrenzung möglich sein
|
CourseDeregisterUntilTip: Abmeldung darf auch ohne Begrenzung möglich sein
|
||||||
CourseFilterSearch: Volltext-Suche
|
CourseFilterSearch: Volltext-Suche
|
||||||
CourseFilterRegistered: Registriert
|
CourseFilterRegistered: Registriert
|
||||||
|
CourseDeleteQuestion: Wollen Sie den unten aufgeführten Kurs wirklich löschen?
|
||||||
|
CourseDeleted: Kurs gelöscht
|
||||||
|
|
||||||
NoSuchTerm tid@TermId: Semester #{display tid} gibt es nicht.
|
NoSuchTerm tid@TermId: Semester #{display tid} gibt es nicht.
|
||||||
NoSuchSchool ssh@SchoolId: Institut #{display ssh} gibt es nicht.
|
NoSuchSchool ssh@SchoolId: Institut #{display ssh} gibt es nicht.
|
||||||
@ -89,10 +91,12 @@ SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand
|
|||||||
SheetEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh} #{sheetName} editieren
|
SheetEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh} #{sheetName} editieren
|
||||||
SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} aus Kurs #{display tid}-#{display ssh}-#{csh} wurde gespeichert.
|
SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} aus Kurs #{display tid}-#{display ssh}-#{csh} wurde gespeichert.
|
||||||
SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{display tid}-#{display ssh}-#{csh}.
|
SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{display tid}-#{display ssh}-#{csh}.
|
||||||
SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kurs #{display tid}-#{display ssh}-#{csh} herauslöschen?
|
SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kurs #{display tid}-#{display ssh}-#{csh} herauslöschen? Alle assoziierten Abgaben und Korrekturen gehen ebenfalls verloren!
|
||||||
SheetDelText submissionNo@Int: Dies kann nicht mehr rückgängig gemacht werden! Alle Einreichungen gehen ebenfalls verloren! Es gibt #{display submissionNo} Abgaben.
|
|
||||||
SheetDelOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh}: #{sheetName} gelöscht.
|
SheetDelOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{display tid}-#{display ssh}-#{csh}: #{sheetName} gelöscht.
|
||||||
|
|
||||||
|
SheetDeleteQuestion: Wollen Sie das unten aufgeführte Übungsblatt und alle zugehörigen Abgaben wirklich löschen?
|
||||||
|
SheetDeleted: Übungsblatt gelöscht
|
||||||
|
|
||||||
SheetUploadMode: Abgabe von Dateien
|
SheetUploadMode: Abgabe von Dateien
|
||||||
SheetSubmissionMode: Abgabe-Modus
|
SheetSubmissionMode: Abgabe-Modus
|
||||||
SheetExercise: Aufgabenstellung
|
SheetExercise: Aufgabenstellung
|
||||||
@ -545,17 +549,19 @@ MenuCorrections: Abgaben
|
|||||||
MenuSheetNew: Neues Übungsblatt anlegen
|
MenuSheetNew: Neues Übungsblatt anlegen
|
||||||
MenuCourseEdit: Kurs editieren
|
MenuCourseEdit: Kurs editieren
|
||||||
MenuCourseNewTemplate: Als neuen Kurs klonen
|
MenuCourseNewTemplate: Als neuen Kurs klonen
|
||||||
|
MenuCourseDelete: Kurs löschen
|
||||||
MenuSubmissionNew: Abgabe anlegen
|
MenuSubmissionNew: Abgabe anlegen
|
||||||
MenuSubmissionOwn: Abgabe
|
MenuSubmissionOwn: Abgabe
|
||||||
MenuCorrectors: Korrektoren
|
MenuCorrectors: Korrektoren
|
||||||
MenuSheetEdit: Übungsblatt editieren
|
MenuSheetEdit: Übungsblatt editieren
|
||||||
|
MenuSheetDelete: Übungsblatt löschen
|
||||||
MenuCorrectionsUpload: Korrekturen hochladen
|
MenuCorrectionsUpload: Korrekturen hochladen
|
||||||
MenuCorrectionsCreate: Abgaben registrieren
|
MenuCorrectionsCreate: Abgaben registrieren
|
||||||
MenuCorrectionsGrade: Abgaben bewerten
|
MenuCorrectionsGrade: Abgaben bewerten
|
||||||
|
|
||||||
AuthPredsActive: Aktive Authorisierungsprädikate
|
AuthPredsActive: Aktive Authorisierungsprädikate
|
||||||
AuthPredsActiveChanged: Authorisierungseinstellungen für aktuelle Sitzung gespeichert
|
AuthPredsActiveChanged: Authorisierungseinstellungen für aktuelle Sitzung gespeichert
|
||||||
AuthTagFree: Seite ist generell zugänglich
|
AuthTagFree: Seite ist universell zugänglich
|
||||||
AuthTagAdmin: Nutzer ist Administrator
|
AuthTagAdmin: Nutzer ist Administrator
|
||||||
AuthTagNoEscalation: Nutzer-Rechte werden nicht erweitert
|
AuthTagNoEscalation: Nutzer-Rechte werden nicht erweitert
|
||||||
AuthTagDeprecated: Seite ist nicht überholt
|
AuthTagDeprecated: Seite ist nicht überholt
|
||||||
@ -573,4 +579,8 @@ AuthTagUserSubmissions: Abgaben erfolgen durch Kursteilnehmer
|
|||||||
AuthTagCorrectorSubmissions: Abgaben erfolgen durch Korrektoren
|
AuthTagCorrectorSubmissions: Abgaben erfolgen durch Korrektoren
|
||||||
AuthTagAuthentication: Authentifizierung erfüllt Anforderungen
|
AuthTagAuthentication: Authentifizierung erfüllt Anforderungen
|
||||||
AuthTagRead: Zugriff ist nur lesend
|
AuthTagRead: Zugriff ist nur lesend
|
||||||
AuthTagWrite: Zugriff ist i.A. schreibend
|
AuthTagWrite: Zugriff ist i.A. schreibend
|
||||||
|
|
||||||
|
DeleteCopyStringIfSure count@Int: Wenn Sie sich sicher sind, dass Sie #{pluralDE count "das obige Objekt" "obige Objekte"} unwiderbringlich löschen möchten, schreiben Sie bitte zunächst den angezeigten Text ab.
|
||||||
|
DeleteConfirmation: Bestätigung
|
||||||
|
DeleteConfirmationWrong: Bestätigung muss genau dem angezeigten Text entsprechen.
|
||||||
@ -13,6 +13,7 @@ import qualified Data.CaseInsensitive as CI
|
|||||||
import Database.Persist.Sql
|
import Database.Persist.Sql
|
||||||
|
|
||||||
import Text.Blaze (ToMarkup(..))
|
import Text.Blaze (ToMarkup(..))
|
||||||
|
import Text.Shakespeare.Text (ToText(..))
|
||||||
|
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text.Encoding as Text
|
import qualified Data.Text.Encoding as Text
|
||||||
@ -63,6 +64,9 @@ instance ToMarkup a => ToMarkup (CI a) where
|
|||||||
toMarkup = toMarkup . CI.original
|
toMarkup = toMarkup . CI.original
|
||||||
preEscapedToMarkup = preEscapedToMarkup . CI.original
|
preEscapedToMarkup = preEscapedToMarkup . CI.original
|
||||||
|
|
||||||
|
instance ToText a => ToText (CI a) where
|
||||||
|
toText = toText . CI.original
|
||||||
|
|
||||||
instance ToWidget site a => ToWidget site (CI a) where
|
instance ToWidget site a => ToWidget site (CI a) where
|
||||||
toWidget = toWidget . CI.original
|
toWidget = toWidget . CI.original
|
||||||
|
|
||||||
|
|||||||
@ -146,6 +146,15 @@ pattern CSubmissionR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Cr
|
|||||||
pattern CSubmissionR tid ssh csh shn cid ptn
|
pattern CSubmissionR tid ssh csh shn cid ptn
|
||||||
= CSheetR tid ssh csh shn (SubmissionR cid ptn)
|
= CSheetR tid ssh csh shn (SubmissionR cid ptn)
|
||||||
|
|
||||||
|
|
||||||
|
pluralDE :: Int -- ^ Count
|
||||||
|
-> Text -- ^ Singular
|
||||||
|
-> Text -- ^ Plural
|
||||||
|
-> Text
|
||||||
|
pluralDE num singularForm pluralForm
|
||||||
|
| num == 1 = singularForm
|
||||||
|
| otherwise = pluralForm
|
||||||
|
|
||||||
-- Messages creates type UniWorXMessage and RenderMessage UniWorX instance
|
-- Messages creates type UniWorXMessage and RenderMessage UniWorX instance
|
||||||
mkMessage "UniWorX" "messages/uniworx" "de"
|
mkMessage "UniWorX" "messages/uniworx" "de"
|
||||||
mkMessageVariant "UniWorX" "Campus" "messages/campus" "de"
|
mkMessageVariant "UniWorX" "Campus" "messages/campus" "de"
|
||||||
@ -1197,6 +1206,14 @@ pageActions (CourseR tid ssh csh CShowR) =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
|
, MenuItem
|
||||||
|
{ menuItemType = PageActionSecondary
|
||||||
|
, menuItemLabel = MsgMenuCourseDelete
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute $ CourseR tid ssh csh CDeleteR
|
||||||
|
, menuItemModal = False
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
]
|
]
|
||||||
pageActions (CourseR tid ssh csh SheetListR) =
|
pageActions (CourseR tid ssh csh SheetListR) =
|
||||||
[ MenuItem
|
[ MenuItem
|
||||||
@ -1257,6 +1274,14 @@ pageActions (CSheetR tid ssh csh shn SShowR) =
|
|||||||
, menuItemModal = False
|
, menuItemModal = False
|
||||||
, menuItemAccessCallback' = return True
|
, menuItemAccessCallback' = return True
|
||||||
}
|
}
|
||||||
|
, MenuItem
|
||||||
|
{ menuItemType = PageActionSecondary
|
||||||
|
, menuItemLabel = MsgMenuSheetDelete
|
||||||
|
, menuItemIcon = Nothing
|
||||||
|
, menuItemRoute = SomeRoute $ CSheetR tid ssh csh shn SDelR
|
||||||
|
, menuItemModal = False
|
||||||
|
, menuItemAccessCallback' = return True
|
||||||
|
}
|
||||||
]
|
]
|
||||||
pageActions (CSheetR tid ssh csh shn SSubsR) =
|
pageActions (CSheetR tid ssh csh shn SSubsR) =
|
||||||
[ MenuItem
|
[ MenuItem
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import Utils.Lens
|
|||||||
-- import Utils.DB
|
-- import Utils.DB
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
|
import Handler.Utils.Delete
|
||||||
|
|
||||||
-- import Data.Time
|
-- import Data.Time
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -386,10 +387,24 @@ pgCEditR isGetReq tid ssh csh = do
|
|||||||
courseEditHandler isGetReq $ courseToForm <$> course
|
courseEditHandler isGetReq $ courseToForm <$> course
|
||||||
|
|
||||||
|
|
||||||
getCDeleteR :: TermId -> SchoolId -> CourseShorthand -> Handler Html
|
getCDeleteR, postCDeleteR :: TermId -> SchoolId -> CourseShorthand -> Handler Html
|
||||||
getCDeleteR = error "TODO: implement getCDeleteR"
|
getCDeleteR = postCDeleteR
|
||||||
postCDeleteR :: TermId -> SchoolId -> CourseShorthand -> Handler Html
|
postCDeleteR tid ssh csh = do
|
||||||
postCDeleteR = error "TODO: implement getCDeleteR"
|
Entity cId _ <- runDB . getBy404 $ TermSchoolCourseShort tid ssh csh
|
||||||
|
deleteR DeleteRoute
|
||||||
|
{ drRecords = Set.singleton cId
|
||||||
|
, drRenderRecord = \(Entity _ Course{courseName, courseTerm, courseSchool}) -> do
|
||||||
|
School{schoolName} <- getJust courseSchool
|
||||||
|
return [whamlet|
|
||||||
|
#{courseName} (_{SomeMessage $ ShortTermIdentifier (unTermKey courseTerm)}, #{schoolName})
|
||||||
|
|]
|
||||||
|
, drRecordConfirmString = \(Entity _ Course{courseShorthand, courseTerm, courseSchool}) ->
|
||||||
|
return [st|#{unSchoolKey courseSchool}/#{termToText (unTermKey courseTerm)}/#{courseShorthand}|]
|
||||||
|
, drCaption = SomeMessage MsgCourseDeleteQuestion
|
||||||
|
, drSuccessMessage = SomeMessage MsgCourseDeleted
|
||||||
|
, drAbort = SomeRoute $ CourseR tid ssh csh CShowR
|
||||||
|
, drSuccess = SomeRoute CourseListR
|
||||||
|
}
|
||||||
{- TODO
|
{- TODO
|
||||||
| False -- DELETE -- TODO: This no longer works that way!!! See new way in Handler.Term.termEditHandler
|
| False -- DELETE -- TODO: This no longer works that way!!! See new way in Handler.Term.termEditHandler
|
||||||
, Just cid <- cfCourseId res -> do
|
, Just cid <- cfCourseId res -> do
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Handler.Utils
|
|||||||
-- import Handler.Utils.Zip
|
-- import Handler.Utils.Zip
|
||||||
import Handler.Utils.Table.Cells
|
import Handler.Utils.Table.Cells
|
||||||
import Handler.Utils.SheetType
|
import Handler.Utils.SheetType
|
||||||
|
import Handler.Utils.Delete
|
||||||
|
|
||||||
-- import Data.Time
|
-- import Data.Time
|
||||||
-- import qualified Data.Text as T
|
-- import qualified Data.Text as T
|
||||||
@ -528,30 +529,26 @@ handleSheetEdit tid ssh csh msId template dbAction = do
|
|||||||
$(widgetFile "formPageI18n")
|
$(widgetFile "formPageI18n")
|
||||||
|
|
||||||
|
|
||||||
|
getSDelR, postSDelR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler Html
|
||||||
getSDelR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler Html
|
getSDelR = postSDelR
|
||||||
getSDelR tid ssh csh shn = do
|
postSDelR tid ssh csh shn = do
|
||||||
((result,formWidget), formEnctype) <- runFormPost (buttonForm :: Form BtnDelete)
|
sid <- runDB $ fetchSheetId tid ssh csh shn
|
||||||
case result of
|
deleteR DeleteRoute
|
||||||
(FormSuccess BtnAbort) -> redirectUltDest $ CSheetR tid ssh csh shn SShowR
|
{ drRecords = Set.singleton sid
|
||||||
(FormSuccess BtnDelete) -> do
|
, drRenderRecord = \(Entity _ Sheet{sheetName, sheetCourse}) -> do
|
||||||
runDB $ fetchSheetId tid ssh csh shn >>= deleteCascade
|
Course{courseTerm, courseSchool, courseName} <- getJust sheetCourse
|
||||||
-- TODO: deleteCascade löscht aber nicht die hochgeladenen Dateien!!!
|
School{schoolName} <- getJust courseSchool
|
||||||
addMessageI Info $ MsgSheetDelOk tid ssh csh shn
|
return [whamlet|
|
||||||
redirect $ CourseR tid ssh csh SheetListR
|
#{sheetName} (_{ShortTermIdentifier (unTermKey courseTerm)}, #{schoolName}, #{courseName})
|
||||||
_other -> do
|
|]
|
||||||
submissionno <- runDB $ do
|
, drRecordConfirmString = \(Entity _ Sheet{sheetName, sheetCourse}) -> do
|
||||||
sid <- fetchSheetId tid ssh csh shn
|
Course{courseTerm, courseSchool, courseShorthand} <- getJust sheetCourse
|
||||||
count [SubmissionSheet ==. sid]
|
return [st|#{termToText (unTermKey courseTerm)}/#{unSchoolKey courseSchool}/#{courseShorthand}/#{sheetName}|]
|
||||||
let formText = Just $ MsgSheetDelText submissionno
|
, drCaption = SomeMessage MsgSheetDeleteQuestion
|
||||||
let actionUrl = CSheetR tid ssh csh shn SDelR
|
, drSuccessMessage = SomeMessage MsgSheetDeleted
|
||||||
defaultLayout $ do
|
, drAbort = SomeRoute $ CSheetR tid ssh csh shn SShowR
|
||||||
setTitleI $ MsgSheetTitle tid ssh csh shn
|
, drSuccess = SomeRoute $ CourseR tid ssh csh SheetListR
|
||||||
$(widgetFile "formPageI18n")
|
}
|
||||||
|
|
||||||
postSDelR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler Html
|
|
||||||
postSDelR = getSDelR
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
insertSheetFile :: SheetId -> SheetFileType -> FileInfo -> YesodDB UniWorX ()
|
insertSheetFile :: SheetId -> SheetFileType -> FileInfo -> YesodDB UniWorX ()
|
||||||
|
|||||||
@ -59,7 +59,7 @@ postMessageR cID = do
|
|||||||
<*> areq htmlField' (fslpI MsgSystemMessageContent "HTML") (Just systemMessageTranslationContent)
|
<*> areq htmlField' (fslpI MsgSystemMessageContent "HTML") (Just systemMessageTranslationContent)
|
||||||
<*> aopt htmlField' (fslpI MsgSystemMessageSummary "HTML") (Just systemMessageTranslationSummary)
|
<*> aopt htmlField' (fslpI MsgSystemMessageSummary "HTML") (Just systemMessageTranslationSummary)
|
||||||
)
|
)
|
||||||
<*> combinedButtonField (universeF :: [BtnSubmitDelete])
|
<*> combinedButtonFieldF ""
|
||||||
|
|
||||||
let modifyTranss = Map.map (view $ _1._1) modifyTranss'
|
let modifyTranss = Map.map (view $ _1._1) modifyTranss'
|
||||||
|
|
||||||
|
|||||||
73
src/Handler/Utils/Delete.hs
Normal file
73
src/Handler/Utils/Delete.hs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
module Handler.Utils.Delete
|
||||||
|
( DeleteRoute(..)
|
||||||
|
, deleteR
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
import Handler.Utils.Form
|
||||||
|
|
||||||
|
import Utils.Lens
|
||||||
|
|
||||||
|
import qualified Data.Text as Text
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
import qualified Data.CaseInsensitive as CI
|
||||||
|
|
||||||
|
import Control.Monad.Trans.Random
|
||||||
|
import System.Random (mkStdGen)
|
||||||
|
import System.Random.Shuffle (shuffleM)
|
||||||
|
import qualified Crypto.Hash as Crypto (hash)
|
||||||
|
import Crypto.Hash (Digest, SHAKE128)
|
||||||
|
|
||||||
|
import qualified Data.ByteArray as ByteArray
|
||||||
|
|
||||||
|
|
||||||
|
data DeleteRoute = forall record. (DeleteCascade record SqlBackend, Hashable (Key record)) => DeleteRoute
|
||||||
|
{ drRecords :: Set (Key record)
|
||||||
|
, drRenderRecord :: Entity record -> ReaderT SqlBackend (HandlerT UniWorX IO) Widget
|
||||||
|
, drRecordConfirmString :: Entity record -> ReaderT SqlBackend (HandlerT UniWorX IO) Text
|
||||||
|
, drCaption
|
||||||
|
, drSuccessMessage :: SomeMessage UniWorX
|
||||||
|
, drAbort
|
||||||
|
, drSuccess :: SomeRoute UniWorX
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
deleteR :: DeleteRoute -> Handler Html
|
||||||
|
deleteR DeleteRoute{..} = do
|
||||||
|
targets <- runDB . mconcatForM drRecords $ \rKey -> do
|
||||||
|
ent <- Entity rKey <$> get404 rKey
|
||||||
|
recordWdgt <- drRenderRecord ent
|
||||||
|
recordConfirmString <- drRecordConfirmString ent
|
||||||
|
return $ pure (recordWdgt, recordConfirmString)
|
||||||
|
|
||||||
|
cIDKey <- hash . (ByteArray.convert :: Digest (SHAKE128 64) -> ByteString) . Crypto.hash <$> getsYesod appCryptoIDKey
|
||||||
|
|
||||||
|
let sTargets = evalRand (shuffleM targets) . mkStdGen . hashWithSalt cIDKey $ Set.toList drRecords
|
||||||
|
confirmString = Text.unlines $ map (Text.strip . view _2) sTargets
|
||||||
|
confirmField
|
||||||
|
| Set.size drRecords <= 1 = textField
|
||||||
|
| otherwise = convertField unTextarea Textarea textareaField
|
||||||
|
|
||||||
|
((deleteFormRes, deleteFormWdgt), deleteFormEnctype) <- runFormPost . identForm FIDDelete . renderAForm FormStandard $ (,)
|
||||||
|
<$> areq confirmField (fslI MsgDeleteConfirmation) Nothing
|
||||||
|
<*> combinedButtonFieldF ""
|
||||||
|
|
||||||
|
formResult deleteFormRes $ \case
|
||||||
|
(_, catMaybes -> [BtnAbort]) ->
|
||||||
|
redirect drAbort
|
||||||
|
(inpConfirmStr, catMaybes -> [BtnDelete])
|
||||||
|
| ((==) `on` map CI.mk . Text.words) confirmString inpConfirmStr
|
||||||
|
-> do
|
||||||
|
runDB $ do
|
||||||
|
forM_ drRecords deleteCascade
|
||||||
|
addMessageI Success drSuccessMessage
|
||||||
|
redirect drSuccess
|
||||||
|
| otherwise
|
||||||
|
-> addMessageI Error MsgDeleteConfirmationWrong
|
||||||
|
_other -> return ()
|
||||||
|
|
||||||
|
Just targetRoute <- getCurrentRoute
|
||||||
|
|
||||||
|
defaultLayout
|
||||||
|
$(widgetFile "widgets/delete-confirmation")
|
||||||
@ -56,6 +56,9 @@ import Data.Aeson.Text (encodeToLazyText)
|
|||||||
data BtnDelete = BtnDelete | BtnAbort
|
data BtnDelete = BtnDelete | BtnAbort
|
||||||
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||||
|
|
||||||
|
instance Universe BtnDelete
|
||||||
|
instance Finite BtnDelete
|
||||||
|
|
||||||
instance PathPiece BtnDelete where -- for displaying the button only, not really for paths
|
instance PathPiece BtnDelete where -- for displaying the button only, not really for paths
|
||||||
toPathPiece = showToPathPiece
|
toPathPiece = showToPathPiece
|
||||||
fromPathPiece = readFromPathPiece
|
fromPathPiece = readFromPathPiece
|
||||||
|
|||||||
@ -498,6 +498,12 @@ partitionM crit = ofoldlM dist mempty
|
|||||||
| okay -> acc `mappend` (opoint x, mempty)
|
| okay -> acc `mappend` (opoint x, mempty)
|
||||||
| otherwise -> acc `mappend` (mempty, opoint x)
|
| otherwise -> acc `mappend` (mempty, opoint x)
|
||||||
|
|
||||||
|
mconcatMapM :: (Monoid b, Monad m, Foldable f) => (a -> m b) -> f a -> m b
|
||||||
|
mconcatMapM f = foldM (\x my -> mappend x <$> my) mempty . map f . Fold.toList
|
||||||
|
|
||||||
|
mconcatForM :: (Monoid b, Monad m, Foldable f) => f a -> (a -> m b) -> m b
|
||||||
|
mconcatForM = flip mconcatMapM
|
||||||
|
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
-- Sessions --
|
-- Sessions --
|
||||||
|
|||||||
@ -172,6 +172,7 @@ data FormIdentifier
|
|||||||
| FIDSystemMessageAddTranslation
|
| FIDSystemMessageAddTranslation
|
||||||
| FIDDBTableFilter
|
| FIDDBTableFilter
|
||||||
| FIDDBTablePagesize
|
| FIDDBTablePagesize
|
||||||
|
| FIDDelete
|
||||||
deriving (Eq, Ord, Read, Show)
|
deriving (Eq, Ord, Read, Show)
|
||||||
|
|
||||||
instance PathPiece FormIdentifier where
|
instance PathPiece FormIdentifier where
|
||||||
@ -230,13 +231,30 @@ buttonField btn = Field {fieldParse, fieldView, fieldEnctype}
|
|||||||
| otherwise = return $ Left "Wrong button value"
|
| otherwise = return $ Left "Wrong button value"
|
||||||
fieldParse _ _ = return $ Left "Multiple button values"
|
fieldParse _ _ = return $ Left "Multiple button values"
|
||||||
|
|
||||||
combinedButtonField :: (Button site a, Show (ButtonCssClass site)) => [a] -> AForm (HandlerT site IO) [Maybe a]
|
combinedButtonField :: (Button site a, Show (ButtonCssClass site)) => [a] -> FieldSettings site -> AForm (HandlerT site IO) [Maybe a]
|
||||||
combinedButtonField = traverse b2f
|
combinedButtonField bs FieldSettings{..} = formToAForm $ do
|
||||||
where
|
mr <- getMessageRender
|
||||||
b2f b = aopt (buttonField b) "" Nothing
|
fvId <- maybe newIdent return fsId
|
||||||
|
name <- maybe newIdent return fsName
|
||||||
|
(ress, fvs) <- fmap unzip . for bs $ \b -> mopt (buttonField b) ("" { fsId = Just $ fvId <> "__" <> toPathPiece b
|
||||||
|
, fsName = Just $ name <> "__" <> toPathPiece b
|
||||||
|
}) Nothing
|
||||||
|
return ( sequenceA ress
|
||||||
|
, pure FieldView
|
||||||
|
{ fvLabel = toHtml $ mr fsLabel
|
||||||
|
, fvTooltip = fmap (toHtml . mr) fsTooltip
|
||||||
|
, fvId
|
||||||
|
, fvInput = foldMap fvInput fvs
|
||||||
|
, fvErrors = bool Nothing (Just $ foldMap (fromMaybe mempty . fvErrors) fvs) $ any (isJust . fvErrors) fvs
|
||||||
|
, fvRequired = False
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
combinedButtonFieldF :: forall site a. (Button site a, Show (ButtonCssClass site), Finite a) => FieldSettings site -> AForm (HandlerT site IO) [Maybe a]
|
||||||
|
combinedButtonFieldF = combinedButtonField (universeF :: [a])
|
||||||
|
|
||||||
submitButton :: (Button site SubmitButton, Show (ButtonCssClass site)) => AForm (HandlerT site IO) ()
|
submitButton :: (Button site SubmitButton, Show (ButtonCssClass site)) => AForm (HandlerT site IO) ()
|
||||||
submitButton = void $ combinedButtonField [BtnSubmit]
|
submitButton = void $ combinedButtonField [BtnSubmit] ""
|
||||||
|
|
||||||
autosubmitButton :: (Button site SubmitButton, Show (ButtonCssClass site)) => AForm (HandlerT site IO) ()
|
autosubmitButton :: (Button site SubmitButton, Show (ButtonCssClass site)) => AForm (HandlerT site IO) ()
|
||||||
autosubmitButton = void $ aopt (buttonField BtnSubmit) ("" & addAutosubmit) Nothing
|
autosubmitButton = void $ aopt (buttonField BtnSubmit) ("" & addAutosubmit) Nothing
|
||||||
|
|||||||
13
templates/widgets/delete-confirmation.hamlet
Normal file
13
templates/widgets/delete-confirmation.hamlet
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<p>_{drCaption}
|
||||||
|
<ul>
|
||||||
|
$forall (wdgt, _) <- sTargets
|
||||||
|
<li>
|
||||||
|
^{wdgt}
|
||||||
|
|
||||||
|
<p>_{SomeMessage $ MsgDeleteCopyStringIfSure (Set.size drRecords)}
|
||||||
|
|
||||||
|
<p .confirmationText>
|
||||||
|
#{confirmString}
|
||||||
|
|
||||||
|
<form method=POST action=@{targetRoute} enctype=#{deleteFormEnctype}>
|
||||||
|
^{deleteFormWdgt}
|
||||||
5
templates/widgets/delete-confirmation.lucius
Normal file
5
templates/widgets/delete-confirmation.lucius
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.confirmationText {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user