Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Paragraphs Re order to own page #58

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 46 additions & 36 deletions Web/Controller/LandingPages.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Web.Controller.Prelude
import Web.View.LandingPages.Index
import Web.View.LandingPages.New
import Web.View.LandingPages.Edit
import Web.View.LandingPages.Order
import Web.View.LandingPages.Show

instance Controller LandingPagesController where
Expand Down Expand Up @@ -51,42 +52,6 @@ instance Controller LandingPagesController where
Right landingPage -> do
landingPage <- landingPage |> updateRecord

-- After we update the Landing page, we can set the order of the paragraphs.
let params = paramListOrNothing @UUID "paragraphId"

case catMaybes params of
[] -> do
-- No paragraphs to update.
pure ()

uuids -> do
-- We need to update the weight of the paragraphs,
-- So load them.
landingPageWithRecords <- fetchLandingPageWithRecords landingPageId

-- Iterate over all paragraphs, and update the weight.
forEach landingPageWithRecords.paragraphCtas updateParagraph
forEach landingPageWithRecords.paragraphQuotes updateParagraph

where
updateParagraph :: forall record.
( HasField "id" record (Id record)
, SetField "weight" record Int
, CanUpdate record
, PrimaryKey (GetTableName record) ~ UUID
, ?modelContext :: ModelContext
) => record -> IO ()
updateParagraph paragraph = do
let uuid :: UUID = unpackId paragraph.id
let weight = elemIndex uuid uuids |> fromMaybe 0

paragraph
|> set #weight weight
|> updateRecord


pure ()

setSuccessMessage "LandingPage updated"
setFormStatus FormStatusSuccess
redirectTo EditLandingPageAction { .. }
Expand All @@ -112,6 +77,51 @@ instance Controller LandingPagesController where
setSuccessMessage "LandingPage deleted"
redirectTo LandingPagesAction

action ShowOrderLandingPageParagraphsAction { .. } = do
landingPageWithRecords <- fetchLandingPageWithRecords landingPageId

render OrderParagraphsView { .. }

action UpdateOrderLandingPageParagraphsAction { .. } = do
landingPageWithRecords <- fetchLandingPageWithRecords landingPageId

let params = paramListOrNothing @UUID "paragraphId"

case catMaybes params of
[] -> do
-- No paragraphs to update.
pure ()

uuids -> do
-- We need to update the weight of the paragraphs,
-- So load them.
landingPageWithRecords <- fetchLandingPageWithRecords landingPageId

-- Iterate over all paragraphs, and update the weight.
forEach landingPageWithRecords.paragraphCtas updateParagraph
forEach landingPageWithRecords.paragraphQuotes updateParagraph

setSuccessMessage "Paragraphs updated"
redirectTo ShowOrderLandingPageParagraphsAction { .. }

where
updateParagraph :: forall record.
( HasField "id" record (Id record)
, SetField "weight" record Int
, CanUpdate record
, PrimaryKey (GetTableName record) ~ UUID
, ?modelContext :: ModelContext
) => record -> IO ()
updateParagraph paragraph = do
let uuid :: UUID = unpackId paragraph.id
let weight = elemIndex uuid uuids |> fromMaybe 0

paragraph
|> set #weight weight
|> updateRecord

pure ()

buildLandingPage landingPage = landingPage
|> fill @'["title"]
|> validateField #title nonEmpty
Expand Down
4 changes: 2 additions & 2 deletions Web/Element/SubmitButton.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import Application.Helper.Icons
import Web.Element.ElementWrap
import Web.Element.Types

renderSubmitButtonwithFormStatus :: SubmitButton -> FormStatus -> Html
renderSubmitButtonwithFormStatus submitButton formStatus = [hsx|
renderSubmitButtonWithFormStatus :: SubmitButton -> FormStatus -> Html
renderSubmitButtonWithFormStatus submitButton formStatus = [hsx|
{submitButton}

{- We show only one of these messages -}
Expand Down
4 changes: 4 additions & 0 deletions Web/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ data LandingPagesController
| EditLandingPageAction { landingPageId :: !(Id LandingPage) }
| UpdateLandingPageAction { landingPageId :: !(Id LandingPage) }
| DeleteLandingPageAction { landingPageId :: !(Id LandingPage) }
-- Order of paragraphs, and update of it.
| ShowOrderLandingPageParagraphsAction { landingPageId :: !(Id LandingPage) }
| UpdateOrderLandingPageParagraphsAction { landingPageId :: !(Id LandingPage) }
deriving (Eq, Show, Data)

data ParagraphCtasController
Expand Down Expand Up @@ -80,6 +83,7 @@ data SessionsController
| CreateSessionAction
| DeleteSessionAction
deriving (Eq, Show, Data)

data UsersController
= UsersAction
| NewUserAction
Expand Down
67 changes: 27 additions & 40 deletions Web/View/LandingPages/Edit.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ data EditView = EditView
instance View EditView where
html EditView { .. } =
[ header
, renderForm landingPage paragraphCtas paragraphQuotes formStatus
, renderForm landingPageWithRecords formStatus
]
|> mconcat
|> wrapVerticalSpacing AlignNone
|> wrapContainerWide
where
landingPage = landingPageWithRecords.landingPage
paragraphCtas = landingPageWithRecords.paragraphCtas
paragraphQuotes = landingPageWithRecords.paragraphQuotes

breadcrumb = renderBreadcrumb
[ breadcrumbLink "Landing Pages" LandingPagesAction
Expand All @@ -46,36 +44,33 @@ instance View EditView where
|> mconcat
|> wrapHorizontalSpacingTiny AlignBaseline

renderForm :: LandingPage -> [ParagraphCta] -> [ParagraphQuote] -> FormStatus -> Html
renderForm landingPage paragraphCtas paragraphQuotes formStatus = formFor landingPage body
renderForm :: LandingPageWithRecords -> FormStatus -> Html
renderForm landingPageWithRecords formStatus = formFor landingPage body
where
body :: (?formContext :: FormContext LandingPage) => Html
body = [hsx|
{(textField #title)}
landingPage = landingPageWithRecords.landingPage
paragraphCtas = landingPageWithRecords.paragraphCtas
paragraphQuotes = landingPageWithRecords.paragraphQuotes

<div class="border p-4">
{paragraphs}
</div>
body :: (?formContext :: FormContext LandingPage) => Html
body =
[ [hsx|{(textField #title)}|]
, paragraphs |> wrapHorizontalPadding |> wrapBorder RoundedCornerNone

{ renderSubmitButtonwithFormStatus
, renderSubmitButtonWithFormStatus
(submitButton {label = "Save Landing page"})
formStatus
}
|]
]
|> mconcat
|> wrapVerticalSpacing AlignNone

paragraphs =
[ addParagraphs
, [hsx|
<ul class="js-sortable">
{orderAndRenderParagraphs paragraphCtas paragraphQuotes}
</ul>
|]
, orderAndRenderParagraphs paragraphCtas paragraphQuotes |> wrapListOl
, reOrderLink
]
|> mconcat
|> wrapVerticalSpacing AlignNone


addParagraphs =
[ cs ("Paragraphs" :: Text) |> wrapHeaderTag 3
, paragraphButtons
Expand All @@ -90,6 +85,16 @@ renderForm landingPage paragraphCtas paragraphQuotes formStatus = formFor landin
|> mconcat
|> wrapHorizontalSpacing AlignCenter

reOrderLink = if countParagraphs landingPageWithRecords > 1
then renderLinkAction (ShowOrderLandingPageParagraphsAction landingPage.id) "Re-Order"
else ""


countParagraphs :: LandingPageWithRecords -> Int
countParagraphs LandingPageWithRecords { paragraphCtas, paragraphQuotes } =
length paragraphCtas + length paragraphQuotes


orderAndRenderParagraphs :: [ParagraphCta] -> [ParagraphQuote] -> Html
orderAndRenderParagraphs paragraphCtas paragraphQuotes =
ctas
Expand All @@ -111,15 +116,11 @@ orderAndRenderParagraphs paragraphCtas paragraphQuotes =
paragraphTitleAndOps :: (Show (PrimaryKey record), HasPath controller) => (Id' record -> controller) -> (Id' record -> controller) -> Id' record -> Text -> Text -> Html
paragraphTitleAndOps editAction deleteAction id title type_ =
[hsx|
<li>{body}</li>
<li class="">{body}</li>
|]
where
body =
[hsx|
{sortableHandle}

<input type="hidden" name="paragraphId" value={show id} />

{title} <span class="text-sm text-gray-600">({type_})</span>
{operations}
|]
Expand All @@ -134,18 +135,4 @@ orderAndRenderParagraphs paragraphCtas paragraphQuotes =



sortableHandle =
if
length ctas + length quotes > 1
then
[hsx|
<div class="sortable-handle">
<div class="sortable-handle">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-gray-200 hover:text-gray-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 7.5L7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5" />
</svg>
</div>
</div>
|]
else
mempty

70 changes: 70 additions & 0 deletions Web/View/LandingPages/Order.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module Web.View.LandingPages.Order where

import Web.Element.Cta
import Web.Element.ElementWrap
import Web.Element.Link
import Web.Element.Types
import Web.Element.Quote
import Web.Element.ElementWrap
import Web.Types
import Web.View.Prelude

data OrderParagraphsView = OrderParagraphsView { landingPageWithRecords :: LandingPageWithRecords }

instance View OrderParagraphsView where
html OrderParagraphsView { .. } =
[ header
, orderAndRenderParagraphs landingPageWithRecords
]
|> mconcat
|> wrapVerticalSpacing AlignNone
|> wrapContainerWide
where
landingPage = landingPageWithRecords.landingPage

breadcrumb = renderBreadcrumb
[ breadcrumbLink "LandingPages" LandingPagesAction
, breadcrumbText "Show LandingPage"
]

header =
[ breadcrumb
, titleAndEdit
]
|> mconcat
|> wrapVerticalSpacing AlignNone
|> wrapContainerWide


titleAndEdit =
[ cs ("Re-Order Paragraphs" :: Text) |> wrapHeaderTag 1
, renderLinkAction (EditLandingPageAction landingPage.id) "back"
]
|> mconcat
|> wrapHorizontalSpacingTiny AlignBaseline


orderAndRenderParagraphs :: (?context::ControllerContext) => LandingPageWithRecords -> Html
orderAndRenderParagraphs landingPageWithRecords =
ctas ++ quotes
-- Order by weight.
|> sortOn fst
|> fmap snd
|> fmap wrapSortableListLi
|> mconcat
|> wrapSortableList
where

ctas = landingPageWithRecords.paragraphCtas
|> fmap (\paragraph ->
( paragraph.weight
, cs paragraph.title
)
)

quotes = landingPageWithRecords.paragraphQuotes
|> fmap (\paragraph ->
( paragraph.weight
, cs paragraph.body
)
)
2 changes: 1 addition & 1 deletion Web/View/ParagraphQuotes/Form.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ renderForm paragraphQuote isImageRequired formStatus = formFor paragraphQuote [h
<img id="imageUrlPreview" src={paragraphQuote.imageUrl} class="w-20 h-20" />
</div>

{renderSubmitButtonwithFormStatus submitButton formStatus}
{renderSubmitButtonWithFormStatus submitButton formStatus}
|]
|> wrapVerticalSpacing AlignNone
|> wrapContainerWide
Expand Down
1 change: 1 addition & 0 deletions tailwind/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
content: [
"Web/Element/**/*.hs",
"Web/View/**/*.hs",
"Application/Helper/Icons.hs",
],
safelist: [
// Add custom class names.
Expand Down
Loading