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

WIP: Query by pairs of values #30

Closed
wants to merge 4 commits into from
Closed
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
55 changes: 55 additions & 0 deletions Application/Fixtures.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@


SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;


SET SESSION AUTHORIZATION DEFAULT;

ALTER TABLE public.landing_pages DISABLE TRIGGER ALL;



ALTER TABLE public.landing_pages ENABLE TRIGGER ALL;


ALTER TABLE public.paragraph_ctas DISABLE TRIGGER ALL;



ALTER TABLE public.paragraph_ctas ENABLE TRIGGER ALL;


ALTER TABLE public.paragraph_quotes DISABLE TRIGGER ALL;



ALTER TABLE public.paragraph_quotes ENABLE TRIGGER ALL;


ALTER TABLE public.projects DISABLE TRIGGER ALL;

INSERT INTO public.projects (id, project_type, participants) VALUES ('e767f087-d1b9-42ea-898e-c2a2bf39999e', 'project_type_ongoing', '2');
INSERT INTO public.projects (id, project_type, participants) VALUES ('429177d7-f425-4c5e-b379-5e1a0f72bfb5', 'project_type_not_started', '3');
INSERT INTO public.projects (id, project_type, participants) VALUES ('84825fa3-2cce-4b4a-872b-81fe554e2076', 'project_type_not_started', '2');
INSERT INTO public.projects (id, project_type, participants) VALUES ('687e32f5-8e8b-4a6d-b4a7-ead9d8a39f91', 'project_type_finished', '2');


ALTER TABLE public.projects ENABLE TRIGGER ALL;


ALTER TABLE public.users DISABLE TRIGGER ALL;



ALTER TABLE public.users ENABLE TRIGGER ALL;


8 changes: 6 additions & 2 deletions Application/Schema.sql
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
CREATE TYPE project_type AS ENUM ('project_type_ongoing', 'project_type_not_started', 'project_type_finished');
CREATE FUNCTION set_updated_at_to_now() RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language plpgsql;
-- Your database schema. Use the Schema Designer at http://localhost:8001/ to add some tables.

CREATE TABLE users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
email TEXT NOT NULL,
password_hash TEXT NOT NULL,
locked_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
failed_login_attempts INT DEFAULT 0 NOT NULL
);

CREATE TABLE landing_pages (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
Expand All @@ -40,6 +39,11 @@ CREATE TABLE paragraph_ctas (
);
CREATE INDEX paragraph_quotes_landing_page_id_index ON paragraph_quotes (landing_page_id);
CREATE INDEX paragraph_ctas_landing_page_id_index ON paragraph_ctas (landing_page_id);
CREATE TABLE projects (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
project_type project_type NOT NULL,
participants TEXT NOT NULL
);
ALTER TABLE paragraph_ctas ADD CONSTRAINT paragraph_ctas_ref_landing_page_id FOREIGN KEY (landing_page_id) REFERENCES landing_pages (id) ON DELETE NO ACTION;
ALTER TABLE paragraph_ctas ADD CONSTRAINT paragraph_ctas_ref_ref_landing_page_id FOREIGN KEY (ref_landing_page_id) REFERENCES landing_pages (id) ON DELETE NO ACTION;
ALTER TABLE paragraph_quotes ADD CONSTRAINT paragraph_quotes_ref_landing_page_id FOREIGN KEY (landing_page_id) REFERENCES landing_pages (id) ON DELETE NO ACTION;
37 changes: 37 additions & 0 deletions Web/Controller/Projects.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Web.Controller.Projects where

import Web.Controller.Prelude
import Web.View.Projects.Index
import Web.View.Projects.New

instance Controller ProjectsController where
action ProjectsAction = do
projects <- query @Project |> fetch

-- Fetch only specific projects by a pair of values.
-- In this case we really fetch all, but show how we pair the values we want to
-- query by.
let pairs = projects
|> fmap (\project -> "(" ++ show project.projectType ++ ", " ++ project.participants ++ ")")

projectsQuery :: [Project] <- sqlQuery "SELECT * FROM projects WHERE (project_type, participants) IN (VALUES ?)" (Only (In pairs))
Comment on lines +11 to +17
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the query. It compiles, but isn't right:

image

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to implement ToField:

instance ToField (ProjectType, Text) where
    toField (projectType, participants) = Many [toField projectType, toField participants]


instance Controller ProjectsController where
    action ProjectsAction = do
        projects <- query @Project |> fetch

        -- Fetch only specific projects by a pair of values.
        -- In this case we really fetch all, but show how we pair the values we want to
        -- query by.
        let pairs = projects |> fmap (\project -> (project.projectType, project.participants))

        -- Use a parameterized query to handle list of tuples
        projectsQuery :: [Project] <- sqlQuery "SELECT * FROM projects WHERE (project_type, participants) IN ?" (Only $ In pairs)


        render IndexView { .. }

But this now has this error

image


render IndexView { .. }

action NewProjectAction = do
let project = newRecord
render NewView { .. }

action CreateProjectAction = do
let project = newRecord @Project
project
|> buildProject
|> ifValid \case
Left project -> render NewView { .. }
Right project -> do
project <- project |> createRecord
setSuccessMessage "Project created"
redirectTo ProjectsAction

buildProject project = project
|> fill @'["projectType", "participants"]
2 changes: 2 additions & 0 deletions Web/FrontController.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Web.View.Layout (defaultLayout)


-- Controller Imports
import Web.Controller.Projects
import Web.Controller.Users
import Web.Controller.ImageStyle
import Web.Controller.LandingPages
Expand All @@ -19,6 +20,7 @@ instance FrontController WebApplication where
controllers =
[ startPage LandingPagesAction
-- Generator Marker
, parseRoute @ProjectsController
, parseRoute @UsersController
, parseRoute @ImageStyleController
, parseRoute @LandingPagesController
Expand Down
3 changes: 3 additions & 0 deletions Web/Routes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ instance AutoRoute SessionsController

instance AutoRoute UsersController


instance AutoRoute ProjectsController

15 changes: 15 additions & 0 deletions Web/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import IHP.Prelude
import IHP.ModelSupport
import Generated.Types
import IHP.LoginSupport.Types
import IHP.View.Form

-- Custom types

Expand Down Expand Up @@ -77,3 +78,17 @@ data UsersController
| UpdateUserAction { userId :: !(Id User) }
| DeleteUserAction { userId :: !(Id User) }
deriving (Eq, Show, Data)

data ProjectsController
= ProjectsAction
| NewProjectAction
| CreateProjectAction
deriving (Eq, Show, Data)

instance CanSelect ProjectType where
type SelectValue ProjectType = ProjectType
selectValue value = value
selectLabel value = case value of
ProjectTypeNotStarted -> "Not started"
ProjectTypeOngoing -> "Ongoing"
ProjectTypeFinished -> "Finished"
36 changes: 36 additions & 0 deletions Web/View/Projects/Index.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Web.View.Projects.Index where
import Web.View.Prelude

data IndexView = IndexView { projects :: [Project] }

instance View IndexView where
html IndexView { .. } = [hsx|
{breadcrumb}

<h1>Index<a href={pathTo NewProjectAction} class="btn btn-primary ms-4">+ New</a></h1>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Project</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>{forEach projects renderProject}</tbody>
</table>

</div>
|]
where
breadcrumb = renderBreadcrumb
[ breadcrumbLink "Projects" ProjectsAction
]

renderProject :: Project -> Html
renderProject project = [hsx|
<tr>
<td>{project.projectType} {project.participants}</td>
</tr>
|]
24 changes: 24 additions & 0 deletions Web/View/Projects/New.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Web.View.Projects.New where
import Web.View.Prelude

data NewView = NewView { project :: Project }

instance View NewView where
html NewView { .. } = [hsx|
{breadcrumb}
<h1>New Project</h1>
{renderForm project}
|]
where
breadcrumb = renderBreadcrumb
[ breadcrumbLink "Projects" ProjectsAction
, breadcrumbText "New Project"
]

renderForm :: Project -> Html
renderForm project = formFor project [hsx|
{(selectField #projectType allProjectTypes)}
{(numberField #participants)}
{submitButton}
|]
where allProjectTypes = allEnumValues @ProjectType