summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Omni/Jr/Web.hs46
-rw-r--r--Omni/Jr/Web/Style.hs29
2 files changed, 67 insertions, 8 deletions
diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs
index 49c9ad6..6c30be3 100644
--- a/Omni/Jr/Web.hs
+++ b/Omni/Jr/Web.hs
@@ -58,6 +58,7 @@ type API =
:> Get '[Lucid.HTML] TaskListPage
:<|> "tasks" :> Capture "id" Text :> Get '[Lucid.HTML] TaskDetailPage
:<|> "tasks" :> Capture "id" Text :> "status" :> ReqBody '[FormUrlEncoded] StatusForm :> PostRedirect
+ :<|> "tasks" :> Capture "id" Text :> "description" :> ReqBody '[FormUrlEncoded] DescriptionForm :> PostRedirect
:<|> "tasks" :> Capture "id" Text :> "review" :> Get '[Lucid.HTML] TaskReviewPage
:<|> "tasks" :> Capture "id" Text :> "accept" :> PostRedirect
:<|> "tasks" :> Capture "id" Text :> "reject" :> ReqBody '[FormUrlEncoded] RejectForm :> PostRedirect
@@ -109,6 +110,13 @@ instance FromForm StatusForm where
Just s -> Right (StatusForm s)
Nothing -> Left "Invalid status"
+newtype DescriptionForm = DescriptionForm Text
+
+instance FromForm DescriptionForm where
+ fromForm form = do
+ desc <- parseUnique "description" form
+ Right (DescriptionForm desc)
+
pageHead :: (Monad m) => Text -> Lucid.HtmlT m ()
pageHead title =
Lucid.head_ <| do
@@ -377,15 +385,30 @@ instance Lucid.ToHtml TaskDetailPage where
Lucid.ul_ [Lucid.class_ "dep-list"] <| do
traverse_ renderDependency deps
- case TaskCore.taskDescription task of
- Nothing -> pure ()
- Just desc ->
+ case TaskCore.taskType task of
+ TaskCore.Epic -> do
Lucid.div_ [Lucid.class_ "detail-section"] <| do
- case TaskCore.taskType task of
- TaskCore.Epic -> do
- Lucid.h3_ "Design"
- Lucid.div_ [Lucid.class_ "markdown-content"] (renderMarkdown desc)
- _ -> do
+ Lucid.h3_ "Design"
+ case TaskCore.taskDescription task of
+ Nothing -> Lucid.p_ [Lucid.class_ "empty-msg"] "No design document yet."
+ Just desc -> Lucid.div_ [Lucid.class_ "markdown-content"] (renderMarkdown desc)
+ Lucid.details_ [Lucid.class_ "edit-description"] <| do
+ Lucid.summary_ "Edit Design"
+ Lucid.form_ [Lucid.method_ "POST", Lucid.action_ ("/tasks/" <> TaskCore.taskId task <> "/description")] <| do
+ Lucid.textarea_
+ [ Lucid.name_ "description",
+ Lucid.class_ "description-textarea",
+ Lucid.rows_ "15",
+ Lucid.placeholder_ "Enter design in Markdown format..."
+ ]
+ (Lucid.toHtml (fromMaybe "" (TaskCore.taskDescription task)))
+ Lucid.div_ [Lucid.class_ "form-actions"] <| do
+ Lucid.button_ [Lucid.type_ "submit", Lucid.class_ "submit-btn"] "Save Design"
+ _ ->
+ case TaskCore.taskDescription task of
+ Nothing -> pure ()
+ Just desc ->
+ Lucid.div_ [Lucid.class_ "detail-section"] <| do
Lucid.h3_ "Description"
Lucid.pre_ [Lucid.class_ "description"] (Lucid.toHtml desc)
@@ -790,6 +813,7 @@ server =
:<|> taskListHandler
:<|> taskDetailHandler
:<|> taskStatusHandler
+ :<|> taskDescriptionHandler
:<|> taskReviewHandler
:<|> taskAcceptHandler
:<|> taskRejectHandler
@@ -884,6 +908,12 @@ server =
liftIO <| TaskCore.updateTaskStatus tid newStatus []
pure <| addHeader ("/tasks/" <> tid) NoContent
+ taskDescriptionHandler :: Text -> DescriptionForm -> Servant.Handler (Headers '[Header "Location" Text] NoContent)
+ taskDescriptionHandler tid (DescriptionForm desc) = do
+ let descMaybe = if Text.null (Text.strip desc) then Nothing else Just desc
+ _ <- liftIO <| TaskCore.editTask tid (\t -> t {TaskCore.taskDescription = descMaybe})
+ pure <| addHeader ("/tasks/" <> tid) NoContent
+
taskReviewHandler :: Text -> Servant.Handler TaskReviewPage
taskReviewHandler tid = do
tasks <- liftIO TaskCore.loadTasks
diff --git a/Omni/Jr/Web/Style.hs b/Omni/Jr/Web/Style.hs
index d544e25..dbe1daa 100644
--- a/Omni/Jr/Web/Style.hs
+++ b/Omni/Jr/Web/Style.hs
@@ -473,6 +473,29 @@ formStyles = do
borderRadius (px 2) (px 2) (px 2) (px 2)
fontSize (px 13)
Stylesheet.key "resize" ("vertical" :: Text)
+ ".edit-description" ? do
+ marginTop (px 8)
+ padding (px 8) (px 0) (px 0) (px 0)
+ borderTop (px 1) solid "#e5e7eb"
+ (".edit-description" |> "summary") ? do
+ cursor pointer
+ color "#0066cc"
+ fontSize (px 13)
+ fontWeight (weight 500)
+ (".edit-description" |> "summary") # hover ? textDecoration underline
+ ".description-textarea" ? do
+ width (pct 100)
+ minHeight (px 250)
+ padding (px 8) (px 10) (px 8) (px 10)
+ border (px 1) solid "#d1d5db"
+ borderRadius (px 2) (px 2) (px 2) (px 2)
+ fontSize (px 13)
+ fontFamily ["SF Mono", "Monaco", "Consolas", "monospace"] [monospace]
+ lineHeight (em 1.5)
+ Stylesheet.key "resize" ("vertical" :: Text)
+ marginTop (px 8)
+ ".form-actions" ? do
+ marginTop (px 8)
activityTimelineStyles :: Css
activityTimelineStyles = do
@@ -733,6 +756,12 @@ darkModeStyles =
".md-inline-code" ? do
backgroundColor "#374151"
color "#f3f4f6"
+ ".edit-description" ? borderTopColor "#374151"
+ (".edit-description" |> "summary") ? color "#60a5fa"
+ ".description-textarea" ? do
+ backgroundColor "#374151"
+ borderColor "#4b5563"
+ color "#f3f4f6"
prefersDark :: Stylesheet.Feature
prefersDark =