diff --git a/twenty-backend/lib/twenty-backend/model.rb b/twenty-backend/lib/twenty-backend/model.rb index ec90679..dd299e0 100644 --- a/twenty-backend/lib/twenty-backend/model.rb +++ b/twenty-backend/lib/twenty-backend/model.rb @@ -42,5 +42,5 @@ class Twenty::Model < ActiveRecord::Base connect Twenty::Migration.run! require_relative "model/connection" - require_relative "model/issue" + require_relative "model/task" end diff --git a/twenty-backend/lib/twenty-backend/model/connection.rb b/twenty-backend/lib/twenty-backend/model/connection.rb index 71d8561..ea8f943 100644 --- a/twenty-backend/lib/twenty-backend/model/connection.rb +++ b/twenty-backend/lib/twenty-backend/model/connection.rb @@ -8,7 +8,7 @@ class Twenty::Connection < Twenty::Model ## # Associations - has_many :issues, class_name: 'Twenty::Issue' + has_many :tasks, class_name: 'Twenty::Task' def to_json(options = {}) {id:, name:, path:}.to_json(options) diff --git a/twenty-backend/lib/twenty-backend/model/issue.rb b/twenty-backend/lib/twenty-backend/model/task.rb similarity index 93% rename from twenty-backend/lib/twenty-backend/model/issue.rb rename to twenty-backend/lib/twenty-backend/model/task.rb index d32f56c..9608587 100644 --- a/twenty-backend/lib/twenty-backend/model/issue.rb +++ b/twenty-backend/lib/twenty-backend/model/task.rb @@ -1,4 +1,4 @@ -class Twenty::Issue < Twenty::Model +class Twenty::Task < Twenty::Model self.table_name = 'issues' ## diff --git a/twenty-backend/lib/twenty-backend/servlet.rb b/twenty-backend/lib/twenty-backend/servlet.rb index 3fe4d28..c6ba61a 100644 --- a/twenty-backend/lib/twenty-backend/servlet.rb +++ b/twenty-backend/lib/twenty-backend/servlet.rb @@ -1,7 +1,7 @@ class Twenty::Servlet < WEBrick::HTTPServlet::AbstractServlet require_relative "servlet/response" require_relative "servlet/connections" - require_relative "servlet/issues" + require_relative "servlet/tasks" def ok(res, body = {}) Response.new(res) diff --git a/twenty-backend/lib/twenty-backend/servlet/issues.rb b/twenty-backend/lib/twenty-backend/servlet/issues.rb deleted file mode 100644 index 11cea89..0000000 --- a/twenty-backend/lib/twenty-backend/servlet/issues.rb +++ /dev/null @@ -1,60 +0,0 @@ -class Twenty::Servlet::Issues < Twenty::Servlet - ## - # GET /servlet/issues/ - # GET /servlet/issues// - def do_GET(req, res) - case req.path_info - when "" - issues = Twenty::Issue.open.order(updated_at: :desc) - ok(res, issues:) - when %r|^/([\d]+)/?$| - issue = Twenty::Issue.find_by(id: $1) - issue ? ok(res, issue:) : not_found(res) - else - not_found(res) - end - end - - ## - # POST /servlet/issues/ - def do_POST(req, res) - case req.path_info - when "" - issue = Twenty::Issue.new(JSON.parse(req.body)) - if issue.save - ok(res, issue:) - else - errors = issue.errors.full_messages - bad_request(res, errors:) - end - else - not_found(res) - end - end - - ## - # PUT /servlet/issues - def do_PUT(req, res) - case req.path_info - when "" - body = JSON.parse(req.body) - id = body.delete("id") - issue = Twenty::Issue.find_by(id:) - issue.update(body) ? ok(res, issue:) : not_found(res) - else - not_found(res) - end - end - - ## - # DELETE /servlet/issues// - def do_DELETE(req, res) - case req.path_info - when %r|^/([\d]+)/?$| - issue = Twenty::Issue.find_by(id: $1) - issue.destroy ? ok(res) : not_found(res) - else - not_found(res) - end - end -end diff --git a/twenty-backend/lib/twenty-backend/servlet/tasks.rb b/twenty-backend/lib/twenty-backend/servlet/tasks.rb new file mode 100644 index 0000000..2a30df6 --- /dev/null +++ b/twenty-backend/lib/twenty-backend/servlet/tasks.rb @@ -0,0 +1,60 @@ +class Twenty::Servlet::Tasks < Twenty::Servlet + ## + # GET /servlet/tasks/ + # GET /servlet/tasks// + def do_GET(req, res) + case req.path_info + when "" + tasks = Twenty::Task.open.order(updated_at: :desc) + ok(res, tasks:) + when %r|^/([\d]+)/?$| + task = Twenty::Task.find_by(id: $1) + task ? ok(res, task:) : not_found(res) + else + not_found(res) + end + end + + ## + # POST /servlet/tasks/ + def do_POST(req, res) + case req.path_info + when "" + task = Twenty::Task.new(JSON.parse(req.body)) + if task.save + ok(res, task:) + else + errors = task.errors.full_messages + bad_request(res, errors:) + end + else + not_found(res) + end + end + + ## + # PUT /servlet/tasks + def do_PUT(req, res) + case req.path_info + when "" + body = JSON.parse(req.body) + id = body.delete("id") + task = Twenty::Task.find_by(id:) + task.update(body) ? ok(res, task:) : not_found(res) + else + not_found(res) + end + end + + ## + # DELETE /servlet/tasks// + def do_DELETE(req, res) + case req.path_info + when %r|^/([\d]+)/?$| + task = Twenty::Task.find_by(id: $1) + task.destroy ? ok(res) : not_found(res) + else + not_found(res) + end + end +end diff --git a/twenty-cli/lib/twenty-cli/command/up.rb b/twenty-cli/lib/twenty-cli/command/up.rb index d001f6b..fa1937e 100644 --- a/twenty-cli/lib/twenty-cli/command/up.rb +++ b/twenty-cli/lib/twenty-cli/command/up.rb @@ -12,7 +12,7 @@ class Twenty::Command::Up < Twenty::Command def run_command server = WEBrick::HTTPServer.new(server_options) server.mount '/servlet/connections', Twenty::Servlet::Connections - server.mount '/servlet/issues', Twenty::Servlet::Issues + server.mount '/servlet/tasks', Twenty::Servlet::Tasks trap(:SIGINT) { server.shutdown } server.start end diff --git a/twenty-frontend/Rules b/twenty-frontend/Rules index 5b6c624..ccb0a6c 100644 --- a/twenty-frontend/Rules +++ b/twenty-frontend/Rules @@ -19,7 +19,7 @@ end require_rules "nanoc/rules/assets" require_rules "nanoc/rules/connections" -require_rules "nanoc/rules/issues" +require_rules "nanoc/rules/tasks" compile("/**/*") { write(nil) } layout '/**/*', :erb diff --git a/twenty-frontend/nanoc/rules/issues.rules b/twenty-frontend/nanoc/rules/issues.rules deleted file mode 100644 index a67b347..0000000 --- a/twenty-frontend/nanoc/rules/issues.rules +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env ruby - -## -# GET /issues/new/ -compile '/html/issues/new/index.html.erb' do - layout "/default.*" - filter(:erb) - write("/issues/new/index.html") -end - -## -# GET /js/main/issue/new.js -compile("/js/main/issue/new.tsx") do - filter(:webpack, depend_on: %w[/js/components/ /js/hooks/ /js/types/]) - write("/js/main/issue/new.js") -end - -## -# GET / -# GET /issues/ -compile("/html/issues/index.html.erb") do - layout "/default.*" - filter(:erb) - write("/issues/index.html") - write("/index.html") -end - -## -# GET /js/main/issues.js -compile("/js/main/issues.tsx") do - filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types/]) - write("/js/main/issues.js") -end - -## -# GET /issues/edit#id=X -compile("/html/issues/edit/index.html.erb") do - layout "/default.*" - filter(:erb) - write("/issues/edit/index.html") -end - -## -# GET /js/main/issue/edit.js -compile("/js/main/issue/edit.tsx") do - filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types/]) - write("/js/main/issue/edit.js") -end diff --git a/twenty-frontend/nanoc/rules/tasks.rules b/twenty-frontend/nanoc/rules/tasks.rules new file mode 100644 index 0000000..d59fd88 --- /dev/null +++ b/twenty-frontend/nanoc/rules/tasks.rules @@ -0,0 +1,48 @@ +#!/usr/bin/env ruby + +## +# GET /tasks/new/ +compile '/html/tasks/new/index.html.erb' do + layout "/default.*" + filter(:erb) + write("/tasks/new/index.html") +end + +## +# GET /js/main/task/new.js +compile("/js/main/task/new.tsx") do + filter(:webpack, depend_on: %w[/js/components/ /js/hooks/ /js/types/]) + write("/js/main/task/new.js") +end + +## +# GET / +# GET /tasks/ +compile("/html/tasks/index.html.erb") do + layout "/default.*" + filter(:erb) + write("/tasks/index.html") + write("/index.html") +end + +## +# GET /js/main/tasks.js +compile("/js/main/tasks.tsx") do + filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types/]) + write("/js/main/tasks.js") +end + +## +# GET /tasks/edit#id=X +compile("/html/tasks/edit/index.html.erb") do + layout "/default.*" + filter(:erb) + write("/tasks/edit/index.html") +end + +## +# GET /js/main/task/edit.js +compile("/js/main/task/edit.tsx") do + filter(:webpack, depend_on: %w[/js/components /js/hooks/ /js/types/]) + write("/js/main/task/edit.js") +end diff --git a/twenty-frontend/src/css/main.scss b/twenty-frontend/src/css/main.scss index 19ea6d8..96a3be2 100644 --- a/twenty-frontend/src/css/main.scss +++ b/twenty-frontend/src/css/main.scss @@ -36,7 +36,7 @@ body header { .root { color: $black; - .issue { + .task { .content { padding: 10px; } diff --git a/twenty-frontend/src/html/issues/edit/index.html.erb b/twenty-frontend/src/html/issues/edit/index.html.erb deleted file mode 100644 index b019ff6..0000000 --- a/twenty-frontend/src/html/issues/edit/index.html.erb +++ /dev/null @@ -1,4 +0,0 @@ -
-
- -
diff --git a/twenty-frontend/src/html/issues/index.html.erb b/twenty-frontend/src/html/issues/index.html.erb deleted file mode 100644 index 142fff5..0000000 --- a/twenty-frontend/src/html/issues/index.html.erb +++ /dev/null @@ -1,4 +0,0 @@ -
-
- -
diff --git a/twenty-frontend/src/html/issues/new/index.html.erb b/twenty-frontend/src/html/issues/new/index.html.erb deleted file mode 100644 index 1657732..0000000 --- a/twenty-frontend/src/html/issues/new/index.html.erb +++ /dev/null @@ -1,4 +0,0 @@ -
-
- -
diff --git a/twenty-frontend/src/html/tasks/edit/index.html.erb b/twenty-frontend/src/html/tasks/edit/index.html.erb new file mode 100644 index 0000000..0db39ab --- /dev/null +++ b/twenty-frontend/src/html/tasks/edit/index.html.erb @@ -0,0 +1,4 @@ +
+
+ +
diff --git a/twenty-frontend/src/html/tasks/index.html.erb b/twenty-frontend/src/html/tasks/index.html.erb new file mode 100644 index 0000000..a56ec81 --- /dev/null +++ b/twenty-frontend/src/html/tasks/index.html.erb @@ -0,0 +1,4 @@ +
+
+ +
diff --git a/twenty-frontend/src/html/tasks/new/index.html.erb b/twenty-frontend/src/html/tasks/new/index.html.erb new file mode 100644 index 0000000..d17b804 --- /dev/null +++ b/twenty-frontend/src/html/tasks/new/index.html.erb @@ -0,0 +1,4 @@ +
+
+ +
diff --git a/twenty-frontend/src/js/components/Issues.tsx b/twenty-frontend/src/js/components/Issues.tsx deleted file mode 100644 index 7c673bf..0000000 --- a/twenty-frontend/src/js/components/Issues.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from "react"; -import { useIssues } from "/hooks/useIssues"; -import { useDestroyIssue } from "/hooks/useDestroyIssue"; -import { TrashIcon, DoneIcon } from "/components/Icons"; -import { DateTime } from "luxon"; -import { Issue } from "/types/schema"; -import { useUpsertIssue } from "hooks/useUpsertIssue"; - -export function Issues() { - const { issues, setIssues } = useIssues(); - const upsertIssue = useUpsertIssue(); - const destroyIssue = useDestroyIssue(); - const onDestroy = (issue: Issue) => { - destroyIssue({id: issue.id}) - .then(() => issues.filter((i) => i.id !== issue.id)) - .then((issues) => setIssues(issues)); - } - const onDone = (issue: Issue) => { - upsertIssue({input: {id: issue.id, state: "closed"}}) - .then(() => issues.filter((i) => i.id !== issue.id)) - .then((issues) => setIssues(issues)); - } - return ( -
-
- Tasks - New task -
-
-
    - {issues.map((issue: Issue, key: number) => { - const { updated_at: updatedAt } = issue; - const datetime = DateTime.fromISO(updatedAt); - return ( -
  • -
    - - {issue.title} - -
    - onDone(issue)} /> - onDestroy(issue)}/> -
    -
    -
    - - {datetime.toFormat("dd LLL, yyyy")} at{" "} - {datetime.toFormat("HH:mm")} - -
    -
  • - ); - })} -
-
-
- ); -} diff --git a/twenty-frontend/src/js/components/Issue.tsx b/twenty-frontend/src/js/components/Task.tsx similarity index 79% rename from twenty-frontend/src/js/components/Issue.tsx rename to twenty-frontend/src/js/components/Task.tsx index 14515ed..ca9baf9 100644 --- a/twenty-frontend/src/js/components/Issue.tsx +++ b/twenty-frontend/src/js/components/Task.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState, useRef } from "react"; import { useForm } from "react-hook-form"; import { Select } from "/components/forms/Select"; -import { useUpsertIssue } from "/hooks/useUpsertIssue"; +import { useUpsertTask } from "/hooks/useUpsertTask"; import { useConnections } from "/hooks/useConnections"; -import { Issue } from "/types/schema"; +import { Task } from "/types/schema"; import showdown from "showdown"; type Inputs = { @@ -13,17 +13,17 @@ type Inputs = { connectionId: number; }; -export function Issue({ issue }: { issue?: Issue }) { +export function Task({ task }: { task?: Task }) { const { register, handleSubmit, watch, setValue: set } = useForm(); - const [isEditable, setIsEditable] = useState(!issue); + const [isEditable, setIsEditable] = useState(!task); const selectRef = useRef(null); - const upsert = useUpsertIssue(); + const upsert = useUpsertTask(); const [connections] = useConnections(); const c = new showdown.Converter(); const content = watch("content"); const onSave = (input: Inputs) => { upsert({ input }).then(() => { - location.href = "/issues/"; + location.href = "/tasks/"; }); }; @@ -32,8 +32,8 @@ export function Issue({ issue }: { issue?: Issue }) { }, []); return ( -
- + +
    @@ -62,7 +62,7 @@ export function Issue({ issue }: { issue?: Issue }) { className="form" type="text" placeholder="Title" - defaultValue={issue?.title} + defaultValue={task?.title} {...register("title", { required: true })} />
@@ -72,7 +72,7 @@ export function Issue({ issue }: { issue?: Issue }) {