Monetization::Issue -> Monetization::Task
This commit is contained in:
parent
40b4553dc3
commit
ccff99fb94
32 changed files with 254 additions and 254 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Twenty::Issue < Twenty::Model
|
||||
class Twenty::Task < Twenty::Model
|
||||
self.table_name = 'issues'
|
||||
|
||||
##
|
|
@ -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)
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
class Twenty::Servlet::Issues < Twenty::Servlet
|
||||
##
|
||||
# GET /servlet/issues/
|
||||
# GET /servlet/issues/<id>/
|
||||
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/<id>/
|
||||
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
|
60
twenty-backend/lib/twenty-backend/servlet/tasks.rb
Normal file
60
twenty-backend/lib/twenty-backend/servlet/tasks.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
class Twenty::Servlet::Tasks < Twenty::Servlet
|
||||
##
|
||||
# GET /servlet/tasks/
|
||||
# GET /servlet/tasks/<id>/
|
||||
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/<id>/
|
||||
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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
48
twenty-frontend/nanoc/rules/tasks.rules
Normal file
48
twenty-frontend/nanoc/rules/tasks.rules
Normal file
|
@ -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
|
|
@ -36,7 +36,7 @@ body header {
|
|||
|
||||
.root {
|
||||
color: $black;
|
||||
.issue {
|
||||
.task {
|
||||
.content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount edit-issue"></div>
|
||||
<script src="/js/main/issue/edit.js"></script>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount issues"></div>
|
||||
<script src="/js/main/issues.js"></script>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount new-issue"></div>
|
||||
<script src="/js/main/issue/new.js"></script>
|
||||
</div>
|
4
twenty-frontend/src/html/tasks/edit/index.html.erb
Normal file
4
twenty-frontend/src/html/tasks/edit/index.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount edit-task"></div>
|
||||
<script src="/js/main/task/edit.js"></script>
|
||||
</div>
|
4
twenty-frontend/src/html/tasks/index.html.erb
Normal file
4
twenty-frontend/src/html/tasks/index.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount tasks"></div>
|
||||
<script src="/js/main/tasks.js"></script>
|
||||
</div>
|
4
twenty-frontend/src/html/tasks/new/index.html.erb
Normal file
4
twenty-frontend/src/html/tasks/new/index.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<div class="root align-center max-width">
|
||||
<div class="react-mount new-task"></div>
|
||||
<script src="/js/main/task/new.js"></script>
|
||||
</div>
|
|
@ -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 (
|
||||
<div className="table">
|
||||
<div className="table div">
|
||||
<span>Tasks</span>
|
||||
<a href="/issues/new">New task</a>
|
||||
</div>
|
||||
<div className="table content">
|
||||
<ul className="items">
|
||||
{issues.map((issue: Issue, key: number) => {
|
||||
const { updated_at: updatedAt } = issue;
|
||||
const datetime = DateTime.fromISO(updatedAt);
|
||||
return (
|
||||
<li className="item" key={key}>
|
||||
<div className="top">
|
||||
<a href={`/issues/edit#id=${issue.id}`}>
|
||||
<span className="item title">{issue.title}</span>
|
||||
</a>
|
||||
<div className="actions">
|
||||
<DoneIcon onClick={() => onDone(issue)} />
|
||||
<TrashIcon onClick={() => onDestroy(issue)}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bottom">
|
||||
<span>
|
||||
{datetime.toFormat("dd LLL, yyyy")} at{" "}
|
||||
{datetime.toFormat("HH:mm")}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -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<Inputs>();
|
||||
const [isEditable, setIsEditable] = useState<boolean>(!issue);
|
||||
const [isEditable, setIsEditable] = useState<boolean>(!task);
|
||||
const selectRef = useRef<HTMLSelectElement>(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 (
|
||||
<form className="issue" onSubmit={handleSubmit(onSave)}>
|
||||
<input type="hidden" value={issue?.id} {...register("id")} />
|
||||
<form className="task" onSubmit={handleSubmit(onSave)}>
|
||||
<input type="hidden" value={task?.id} {...register("id")} />
|
||||
<div className="table">
|
||||
<div className="table tabbed div">
|
||||
<ul className="tabs">
|
||||
|
@ -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 })}
|
||||
/>
|
||||
</div>
|
||||
|
@ -72,7 +72,7 @@ export function Issue({ issue }: { issue?: Issue }) {
|
|||
<textarea
|
||||
className="form"
|
||||
placeholder="Add your description heren"
|
||||
defaultValue={issue?.content}
|
||||
defaultValue={task?.content}
|
||||
{...register("content", { required: true })}
|
||||
/>
|
||||
</div>
|
||||
|
@ -82,9 +82,9 @@ export function Issue({ issue }: { issue?: Issue }) {
|
|||
</>
|
||||
) : (
|
||||
<div
|
||||
className="issue content"
|
||||
className="task content"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: c.makeHtml(content || issue?.content),
|
||||
__html: c.makeHtml(content || task?.content),
|
||||
}}
|
||||
/>
|
||||
)}
|
58
twenty-frontend/src/js/components/Tasks.tsx
Normal file
58
twenty-frontend/src/js/components/Tasks.tsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
import React from "react";
|
||||
import { useTasks } from "/hooks/useTasks";
|
||||
import { useDestroyTask } from "/hooks/useDestroyTask";
|
||||
import { TrashIcon, DoneIcon } from "/components/Icons";
|
||||
import { DateTime } from "luxon";
|
||||
import { Task } from "/types/schema";
|
||||
import { useUpsertTask } from "/hooks/useUpsertTask";
|
||||
|
||||
export function Tasks() {
|
||||
const { tasks, setTasks } = useTasks();
|
||||
const upsertTask = useUpsertTask();
|
||||
const destroyTask = useDestroyTask();
|
||||
const onDestroy = (task: Task) => {
|
||||
destroyTask({id: task.id})
|
||||
.then(() => tasks.filter((t: Task) => t.id !== task.id))
|
||||
.then((tasks: Task[]) => setTasks(tasks));
|
||||
}
|
||||
const onDone = (task: Task) => {
|
||||
upsertTask({input: {id: task.id, state: "closed"}})
|
||||
.then(() => tasks.filter((t: Task) => t.id !== task.id))
|
||||
.then((tasks) => setTasks(tasks));
|
||||
}
|
||||
return (
|
||||
<div className="table">
|
||||
<div className="table div">
|
||||
<span>Tasks</span>
|
||||
<a href="/tasks/new">New task</a>
|
||||
</div>
|
||||
<div className="table content">
|
||||
<ul className="items">
|
||||
{tasks.map((task: Task, key: number) => {
|
||||
const { updated_at: updatedAt } = task;
|
||||
const datetime = DateTime.fromISO(updatedAt);
|
||||
return (
|
||||
<li className="item" key={key}>
|
||||
<div className="top">
|
||||
<a href={`/tasks/edit#id=${task.id}`}>
|
||||
<span className="item title">{task.title}</span>
|
||||
</a>
|
||||
<div className="actions">
|
||||
<DoneIcon onClick={() => onDone(task)} />
|
||||
<TrashIcon onClick={() => onDestroy(task)}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bottom">
|
||||
<span>
|
||||
{datetime.toFormat("dd LLL, yyyy")} at{" "}
|
||||
{datetime.toFormat("HH:mm")}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -2,11 +2,11 @@ type Params = {
|
|||
id: number;
|
||||
};
|
||||
|
||||
export function useDestroyIssue() {
|
||||
export function useDestroyTask() {
|
||||
return function ({ id }: Params) {
|
||||
return new Promise((accept, reject) => {
|
||||
const req = { method: "DELETE" };
|
||||
return fetch(`/servlet/issues/${id}`, req)
|
||||
return fetch(`/servlet/tasks/${id}`, req)
|
||||
.then(res => res.json())
|
||||
.then(accept)
|
||||
.catch(reject);
|
|
@ -1,27 +0,0 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { Issue } from "/types/schema";
|
||||
|
||||
type Result = {
|
||||
setIssues: (issues: Issue[]) => unknown;
|
||||
issues: Issue[];
|
||||
req: () => Promise<Issue[]>;
|
||||
};
|
||||
|
||||
export function useIssues(): Result {
|
||||
const [issues, setIssues] = useState<Issue[]>([]);
|
||||
const set = (ary: Issue[]) => {
|
||||
setIssues(ary);
|
||||
return ary;
|
||||
};
|
||||
const req = async function (): Promise<Issue[]> {
|
||||
return await fetch("/servlet/issues")
|
||||
.then((res: Response) => res.json())
|
||||
.then((res: { issues: Issue[] }) => set(res.issues))
|
||||
.catch(() => null);
|
||||
};
|
||||
useEffect(() => {
|
||||
req();
|
||||
}, []);
|
||||
|
||||
return { issues, setIssues: set, req };
|
||||
}
|
27
twenty-frontend/src/js/hooks/useTasks.ts
Normal file
27
twenty-frontend/src/js/hooks/useTasks.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { Task } from "/types/schema";
|
||||
|
||||
type Result = {
|
||||
setTasks: (tasks: Task[]) => unknown;
|
||||
tasks: Task[];
|
||||
req: () => Promise<Task[]>;
|
||||
};
|
||||
|
||||
export function useTasks(): Result {
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const set = (ary: Task[]) => {
|
||||
setTasks(ary);
|
||||
return ary;
|
||||
};
|
||||
const req = async function (): Promise<Task[]> {
|
||||
return await fetch("/servlet/tasks")
|
||||
.then((res: Response) => res.json())
|
||||
.then((res: { tasks: Task[] }) => set(res.tasks))
|
||||
.catch(() => null);
|
||||
};
|
||||
useEffect(() => {
|
||||
req();
|
||||
}, []);
|
||||
|
||||
return { tasks, setTasks: set, req };
|
||||
}
|
|
@ -6,7 +6,7 @@ type Params = {
|
|||
connectionId?: number;
|
||||
};
|
||||
|
||||
export function useUpsertIssue() {
|
||||
export function useUpsertTask() {
|
||||
const normalize = (input: Params) => {
|
||||
const { id, title, content, state, connectionId } = input;
|
||||
return { id, title, content, state, connection_id: connectionId };
|
||||
|
@ -17,7 +17,7 @@ export function useUpsertIssue() {
|
|||
method: input.id ? "PUT" : "POST",
|
||||
body: JSON.stringify(normalize(input)),
|
||||
};
|
||||
return fetch("/servlet/issues", req)
|
||||
return fetch("/servlet/tasks", req)
|
||||
.then(res => res.json())
|
||||
.then(accept)
|
||||
.catch(reject);
|
|
@ -1,8 +0,0 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { ReadIssue } from "/components/ReadIssue";
|
||||
|
||||
(function () {
|
||||
const root = document.querySelector(".react-mount.edit-issue")!;
|
||||
ReactDOM.createRoot(root).render(<ReadIssue />);
|
||||
})();
|
|
@ -1,8 +0,0 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Issue } from "/components/Issue";
|
||||
|
||||
(function () {
|
||||
const root = document.querySelector(".react-mount.new-issue")!;
|
||||
ReactDOM.createRoot(root).render(<Issue />);
|
||||
})();
|
|
@ -1,8 +0,0 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Issues } from "/components/Issues";
|
||||
|
||||
(function () {
|
||||
const n1 = document.querySelector(".react-mount.issues")!;
|
||||
ReactDOM.createRoot(n1).render(<Issues />);
|
||||
})();
|
8
twenty-frontend/src/js/main/task/edit.tsx
Normal file
8
twenty-frontend/src/js/main/task/edit.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Task } from "/components/Task";
|
||||
|
||||
(function () {
|
||||
const root = document.querySelector(".react-mount.edit-task")!;
|
||||
ReactDOM.createRoot(root).render(<Task/>);
|
||||
})();
|
8
twenty-frontend/src/js/main/task/new.tsx
Normal file
8
twenty-frontend/src/js/main/task/new.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Task } from "/components/Task";
|
||||
|
||||
(function () {
|
||||
const root = document.querySelector(".react-mount.new-task")!;
|
||||
ReactDOM.createRoot(root).render(<Task />);
|
||||
})();
|
8
twenty-frontend/src/js/main/tasks.tsx
Normal file
8
twenty-frontend/src/js/main/tasks.tsx
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { Tasks } from "/components/Tasks";
|
||||
|
||||
(function () {
|
||||
const n1 = document.querySelector(".react-mount.tasks")!;
|
||||
ReactDOM.createRoot(n1).render(<Tasks />);
|
||||
})();
|
|
@ -4,7 +4,7 @@ export type Connection = {
|
|||
path: string;
|
||||
};
|
||||
|
||||
export type Issue = {
|
||||
export type Task = {
|
||||
id: number;
|
||||
title: string;
|
||||
content: string;
|
||||
|
|
|
@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
|
|||
gem.version = "0.1.0"
|
||||
gem.licenses = ["0BSD"]
|
||||
gem.files = []
|
||||
gem.summary = "Simple task management for hobby projects"
|
||||
gem.summary = "twenty provides simple task management on http://localhost"
|
||||
gem.description = gem.summary
|
||||
gem.add_runtime_dependency "twenty-backend", "~> 0.1"
|
||||
gem.add_runtime_dependency "twenty-frontend", "~> 0.1"
|
||||
|
|
Loading…
Reference in a new issue