aboutsummaryrefslogtreecommitdiff
path: root/client/src/Component/Table.hs
blob: a02eaa76d6572771395fe822e24dfee34e14cab8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module Component.Table
  ( view
  , In(..)
  , Out(..)
  ) where

import           Data.Text        (Text)
import           Reflex.Dom       (Dynamic, Event, MonadWidget)
import qualified Reflex.Dom       as R

import qualified Component.Button as Button
import qualified Component.Modal  as Modal
import qualified Component.Pages  as Pages
import qualified Util.Reflex      as ReflexUtil
import qualified View.Icon        as Icon

data In m t h r a = In
  { _in_headerLabel :: h -> Text
  , _in_rows        :: Dynamic t [r]
  , _in_cell        :: h -> r -> Text
  , _in_perPage     :: Int
  , _in_resetPage   :: Event t ()
  , _in_cloneModal  :: r -> Modal.Content t m a
  , _in_editModal   :: r -> Modal.Content t m a
  , _in_deleteModal :: r -> Modal.Content t m a
  , _in_isOwner     :: r -> Bool
  }

data Out t a = Out
  { _out_add    :: Event t a
  , _out_edit   :: Event t a
  , _out_delete :: Event t a
  }

view :: forall t m h r a. (MonadWidget t m, Bounded h, Enum h)  => In m t h r a -> m (Out t a)
view input =
  R.divClass "table" $ do
    rec
      result <- R.divClass "lines" $ do

        R.divClass "header" $ do
          flip mapM_ [minBound..] $ \header ->
            R.divClass "cell" . R.text $
              _in_headerLabel input header

          R.divClass "cell" $ R.blank
          R.divClass "cell" $ R.blank
          R.divClass "cell" $ R.blank

        let rows = getRange
              (_in_perPage input)
                <$> (Pages._out_currentPage pages)
                <*> (_in_rows input)

        R.simpleList rows $ \r ->
          R.divClass "row" $ do
            flip mapM_ [minBound..] $ \h ->
              R.divClass "cell" $
                R.dynText $
                  R.ffor r (_in_cell input h)

            clone <-
              R.divClass "cell button" $
                Button._out_clic <$> (Button.view $
                  Button.defaultIn Icon.clone)

            cloned <-
              Modal.view $ Modal.In
                { Modal._in_show    = clone
                , Modal._in_content = \curtainClick ->
                  (R.dyn . R.ffor r $ \r2 -> _in_cloneModal input r2 curtainClick)
                    >>= ReflexUtil.flattenTuple
                }

            let isOwner = R.ffor r (_in_isOwner input)

            edit <-
              R.divClass "cell button" $
                ReflexUtil.divVisibleIf isOwner $
                  Button._out_clic <$> (Button.view $
                    Button.defaultIn Icon.edit)

            edited <-
              Modal.view $ Modal.In
                { Modal._in_show    = edit
                , Modal._in_content = \curtainClick ->
                  (R.dyn . R.ffor r $ \r2 -> _in_editModal input r2 curtainClick)
                    >>= ReflexUtil.flattenTuple
                }

            delete <-
              R.divClass "cell button" $
                ReflexUtil.divVisibleIf isOwner $
                  Button._out_clic <$> (Button.view $
                    Button.defaultIn Icon.delete)

            deleted <-
              Modal.view $ Modal.In
                { Modal._in_show    = delete
                , Modal._in_content = \curtainClick ->
                  (R.dyn . R.ffor r $ \r2 -> _in_deleteModal input r2 curtainClick)
                    >>= ReflexUtil.flattenTuple
                }

            return (cloned, edited, deleted)

      pages <- Pages.view $ Pages.In
        { Pages._in_total = length <$> _in_rows input
        , Pages._in_perPage = _in_perPage input
        , Pages._in_reset = _in_resetPage input
        }

    let add = R.switch . R.current . fmap (R.leftmost . map (\(a, _, _) -> a)) $ result
        edit = R.switch . R.current . fmap (R.leftmost . map (\(_, a, _) -> a)) $ result
        delete = R.switch . R.current . fmap (R.leftmost . map (\(_, _, a) -> a)) $ result

    return $ Out
      { _out_add = add
      , _out_edit = edit
      , _out_delete = delete
      }

getRange :: forall a. Int -> Int -> [a] -> [a]
getRange perPage currentPage =
  take perPage . drop ((currentPage - 1) * perPage)