diff options
Diffstat (limited to 'webgui/src')
-rw-r--r-- | webgui/src/Main.hs | 114 |
1 files changed, 98 insertions, 16 deletions
diff --git a/webgui/src/Main.hs b/webgui/src/Main.hs index cbb1a75..dbf34bc 100644 --- a/webgui/src/Main.hs +++ b/webgui/src/Main.hs | |||
@@ -39,14 +39,19 @@ import Control.Exception | |||
39 | import Control.Monad.Catch | 39 | import Control.Monad.Catch |
40 | 40 | ||
41 | import Control.Applicative | 41 | import Control.Applicative |
42 | import Control.Monad | 42 | import Control.Monad hiding (sequence) |
43 | import Data.Maybe | 43 | import Data.Maybe |
44 | import Data.Monoid | 44 | import Data.Monoid |
45 | import Text.Read hiding (get) | 45 | import Text.Read hiding (get) |
46 | import Data.Either | 46 | import Data.Either |
47 | import Data.List (isPrefixOf) | 47 | import Data.List (isPrefixOf, sortBy) |
48 | import Data.Ord | ||
49 | import qualified Data.Function as F | ||
48 | import Data.Bool | 50 | import Data.Bool |
49 | 51 | ||
52 | import Data.Traversable (sequence) | ||
53 | import Data.Foldable | ||
54 | |||
50 | import Paths_thermoprint_webgui | 55 | import Paths_thermoprint_webgui |
51 | 56 | ||
52 | import Debug.Trace | 57 | import Debug.Trace |
@@ -100,8 +105,10 @@ setup Config{..} window (split -> (socketErr, dataUpdate)) = void $ do | |||
100 | onEvent socketErr handleSocketErr | 105 | onEvent socketErr handleSocketErr |
101 | 106 | ||
102 | getElementById window "javascriptError" >>= maybeM delete | 107 | getElementById window "javascriptError" >>= maybeM delete |
108 | |||
109 | selectedPrinter <- handleJobTable | ||
103 | 110 | ||
104 | changeEditorStatus <- handleEditor | 111 | changeEditorStatus <- handleEditor selectedPrinter |
105 | 112 | ||
106 | handleDraftTable changeEditorStatus | 113 | handleDraftTable changeEditorStatus |
107 | 114 | ||
@@ -136,7 +143,7 @@ setup Config{..} window (split -> (socketErr, dataUpdate)) = void $ do | |||
136 | 143 | ||
137 | Client{..} = mkClient (Nat $ either (fatal . ("Error while communicating to Thermoprint.Server: " ++) . show) return <=< liftIO . runEitherT) server | 144 | Client{..} = mkClient (Nat $ either (fatal . ("Error while communicating to Thermoprint.Server: " ++) . show) return <=< liftIO . runEitherT) server |
138 | 145 | ||
139 | handleEditor = do | 146 | handleEditor selectedPrinter = do |
140 | title <- fatal' "Could not find editor title field" =<< getElementById window "editorTitle" | 147 | title <- fatal' "Could not find editor title field" =<< getElementById window "editorTitle" |
141 | text <- fatal' "Could not find editor text field" =<< getElementById window "editorText" | 148 | text <- fatal' "Could not find editor text field" =<< getElementById window "editorText" |
142 | status <- fatal' "Could not find editor status field" =<< getElementById window "editorStatus" | 149 | status <- fatal' "Could not find editor status field" =<< getElementById window "editorStatus" |
@@ -202,9 +209,9 @@ setup Config{..} window (split -> (socketErr, dataUpdate)) = void $ do | |||
202 | Right po -> case associatedDraft of | 209 | Right po -> case associatedDraft of |
203 | Just dId -> do | 210 | Just dId -> do |
204 | saved <- saveAction False | 211 | saved <- saveAction False |
205 | when saved $ runFunction . focusJob =<< draftPrint dId Nothing -- FIXME | 212 | when saved $ runFunction . focusJob =<< draftPrint dId =<< currentValue selectedPrinter |
206 | Nothing -> do | 213 | Nothing -> do |
207 | runFunction . focusJob =<< jobCreate Nothing po -- FIXME | 214 | runFunction . focusJob =<< flip jobCreate po =<< currentValue selectedPrinter |
208 | Left err -> emitError $ "Could not print draft due to error parsing bbcode: " ++ show err | 215 | Left err -> emitError $ "Could not print draft due to error parsing bbcode: " ++ show err |
209 | 216 | ||
210 | onEvent (whenE saveDraft $ tick autoSaveTimer) (const . void $ saveAction True) | 217 | onEvent (whenE saveDraft $ tick autoSaveTimer) (const . void $ saveAction True) |
@@ -214,6 +221,7 @@ setup Config{..} window (split -> (socketErr, dataUpdate)) = void $ do | |||
214 | return discardButton # sink UI.enabled (discardable <$> editorStatus) | 221 | return discardButton # sink UI.enabled (discardable <$> editorStatus) |
215 | 222 | ||
216 | return discardButton # sink UI.text (bool "Discard" "Save & Clear" <$> saveDraft) | 223 | return discardButton # sink UI.text (bool "Discard" "Save & Clear" <$> saveDraft) |
224 | return printButton # sink UI.text (maybe "Print" (\(PrinterId i) -> "Print on " ++ show i) <$> selectedPrinter) | ||
217 | 225 | ||
218 | on (whenE saveDraft . UI.click) saveButton . const . void $ saveAction False | 226 | on (whenE saveDraft . UI.click) saveButton . const . void $ saveAction False |
219 | on UI.click printButton $ const printAction | 227 | on UI.click printButton $ const printAction |
@@ -268,17 +276,91 @@ setup Config{..} window (split -> (socketErr, dataUpdate)) = void $ do | |||
268 | initialContent <- toTable =<< drafts | 276 | initialContent <- toTable =<< drafts |
269 | return table # set children initialContent | 277 | return table # set children initialContent |
270 | 278 | ||
271 | recheckTimer <- timer | 279 | update <- do |
272 | return recheckTimer # set interval 5000 | 280 | -- recheckTimer <- timer |
273 | start recheckTimer | 281 | -- return recheckTimer # set interval 5000 |
282 | -- start recheckTimer | ||
283 | |||
284 | -- return $ unionWith const (() <$ filterE concernsDrafts dataUpdate) (tick recheckTimer) | ||
285 | return $ filterE concernsDrafts dataUpdate | ||
274 | 286 | ||
275 | onEvent (unionWith const (() <$ filterE concernsDrafts dataUpdate) (tick recheckTimer)) . const $ drafts >>= toTable >>= (\c -> return table # set children c) | 287 | onEvent update . const $ drafts >>= toTable >>= (\c -> return table # set children c) |
276 | where | 288 | |
277 | concernsDrafts :: URI -> Bool | 289 | concernsDrafts :: URI -> Bool |
278 | concernsDrafts (uriPath -> p) | 290 | concernsDrafts (uriPath -> p) |
279 | | p == "drafts" = True | 291 | | p == "drafts" = True |
280 | | "draft/" `isPrefixOf` p = True | 292 | | "draft/" `isPrefixOf` p = True |
281 | | otherwise = False | 293 | | otherwise = False |
294 | |||
295 | concernsPrinters :: URI -> Bool | ||
296 | concernsPrinters (uriPath -> p) | ||
297 | | p == "printers" = True | ||
298 | | "jobs/" `isPrefixOf` p = True | ||
299 | | otherwise = False | ||
300 | |||
301 | handleJobTable = do | ||
302 | allowAbortion <- do | ||
303 | allowAbortion <- fatal' "Could not find abortion switch" =<< getElementById window "allowAbortion" | ||
304 | flip stepper (UI.checkedChange allowAbortion) =<< (allowAbortion # get UI.checked) | ||
305 | |||
306 | (selectedPrinter, updatePrinter) <- do | ||
307 | autoselectPrinter <- fatal' "Could not find printer autoselect switch" =<< getElementById window "autoselectPrinter" | ||
308 | (selectedPrinter, printerSelect) <- stepper' Nothing | ||
309 | return autoselectPrinter # sink UI.checked (isNothing <$> selectedPrinter) | ||
310 | let | ||
311 | -- getSelectedPrinter :: UI (Maybe PrinterId) | ||
312 | getSelectedPrinter = (fmap PrinterId . join . readMaybe) <$> callFunction (ffi "$('input[name=printer]:checked', '#printers').val()") | ||
313 | updatePrinterSelect = getSelectedPrinter >>= liftIO . printerSelect | ||
314 | on (domEvent "change") autoselectPrinter $ const updatePrinterSelect | ||
315 | return (selectedPrinter, updatePrinterSelect) | ||
316 | |||
317 | let | ||
318 | -- getServerState :: UI [(PrinterId, PrinterStatus, [(JobId, UTCTime, JobStatus)])] | ||
319 | getServerState = map mangleTuple . Map.toList <$> (Map.traverseWithKey (\pId status -> (,) status <$> getJobState pId) =<< printers) | ||
320 | -- getJobState :: PrinterId -> UI [(JobId, UTCTime, JobStatus)] | ||
321 | getJobState pId = toList <$> jobs (Just pId) Nothing Nothing | ||
322 | mangleTuple (a, (b, c)) = (a, b, c) | ||
323 | thrd (_, _, c) = c | ||
324 | |||
325 | -- toTable :: [(PrinterId, PrinterStatus, [(JobId, UTCTime, JobStatus)])] -> UI [Element] | ||
326 | toTable = fmap concat . mapM toSubTable | ||
327 | -- toSubTable :: (PrinterId, PrinterStatus, [(JobId, UTCTime, JobStatus)]) -> UI [Element] | ||
328 | toSubTable (rPId@(PrinterId pId), pStatus, (sortBy (queueSort `F.on` thrd) -> jobs)) = do | ||
329 | pId' <- UI.td # set UI.text (show pId) | ||
330 | pStatus' <- UI.td # set UI.text (show pStatus) | ||
331 | let selectId = "printer" ++ show pId | ||
332 | checked <- (== Just rPId) <$> currentValue selectedPrinter | ||
333 | pSelect <- UI.input # set UI.type_ "radio" # set UI.name "printer" # set UI.value (show $ Just pId) # set UI.id_ selectId # set UI.checked checked | ||
334 | on (domEvent "change") pSelect $ const updatePrinter | ||
335 | pSelectL <- UI.label # set UI.for selectId # set UI.text "Use for new jobs" | ||
336 | pSelect' <- UI.td # set children [pSelect, pSelectL] | ||
337 | pFiller <- UI.td # set UI.colspan 2 | ||
338 | let | ||
339 | toLine ((JobId jId), time, status) = do | ||
340 | jPId <- UI.td | ||
341 | jId' <- UI.td # set UI.text (show jId) | ||
342 | jStatus' <- UI.td # set UI.text (show status) | ||
343 | abortButton <- UI.button # sink UI.enabled allowAbortion # set UI.text "Abort" | ||
344 | actions <- UI.td # set children [abortButton] | ||
345 | UI.tr # set UI.id_ ("job" ++ show jId) # set children [jPId, jId', jStatus', actions] | ||
346 | (:) <$> UI.tr # set children [pId', pFiller, pStatus', pSelect'] <*> mapM toLine jobs | ||
347 | |||
348 | update <- do | ||
349 | -- recheckTimer <- timer | ||
350 | -- return recheckTimer # set interval 5000 | ||
351 | -- start recheckTimer | ||
352 | |||
353 | -- return $ unionWith const (() <$ filterE concernsPrinters dataUpdate) (tick recheckTimer) | ||
354 | return $ filterE concernsPrinters dataUpdate | ||
355 | |||
356 | table <- fatal' "Could not find printer table" =<< getElementById window "printerListBody" | ||
357 | initialContent <- toTable =<< getServerState | ||
358 | return table # set children initialContent | ||
359 | |||
360 | onEvent update . const $ getServerState >>= toTable >>= (\c -> return table # set children c) >> updatePrinter | ||
361 | |||
362 | return selectedPrinter | ||
363 | |||
282 | 364 | ||
283 | focusJob :: JobId -> JSFunction () | 365 | focusJob :: JobId -> JSFunction () |
284 | focusJob (JobId (fromInteger -> i)) = ffi "alert(%1)" (i :: Int) -- FIXME | 366 | focusJob (JobId (fromInteger -> i)) = ffi "alert(%1)" (i :: Int) -- FIXME |