todoro 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +18 -23
- data/app/constraints/taskable_models_constraint.rb +6 -0
- data/app/controllers/todoro/application_controller.rb +23 -1
- data/app/controllers/todoro/task_lists_controller.rb +5 -15
- data/app/controllers/todoro/tasks_controller.rb +11 -10
- data/app/models/todoro/task.rb +0 -1
- data/app/views/todoro/task_lists/_form.html.erb +1 -4
- data/app/views/todoro/task_lists/edit.html.erb +1 -1
- data/app/views/todoro/task_lists/index.html.erb +5 -5
- data/app/views/todoro/task_lists/new.html.erb +1 -1
- data/app/views/todoro/task_lists/show.html.erb +11 -8
- data/app/views/todoro/tasks/_form.html.erb +2 -2
- data/app/views/todoro/tasks/edit.html.erb +1 -1
- data/app/views/todoro/tasks/new.html.erb +1 -1
- data/config/routes.rb +8 -4
- data/lib/todoro/version.rb +1 -1
- data/lib/todoro.rb +7 -0
- metadata +3 -3
- data/app/models/concerns/taskable.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fdd815954054219782d8b2281bced824aca47cb6c7add82408cf6d1fdad3f4d
|
|
4
|
+
data.tar.gz: aa21ff161a69f8d9ae91cc5634871fdb354aeead527c92b8798b6526e576812b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5c69c6f569090184889b7536ea4d380c5a616be36155a70941e7f2cae1095a73780b4844013539d3ff536da18db1f34b48ce62e5dd9d5bcce37e00239c1d1d6
|
|
7
|
+
data.tar.gz: ee5361a8bc6904bba93619563a6b4d504a5e2b359c8c75ad25b44fda556b8b2d79349011a50b6ad32c1af5613459eec36320317584cec7ff753345d68216fe2d
|
data/README.md
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
To enhance the **Todoro** gem's documentation, here's an updated version of the `README.md` file that includes instructions on mounting the engine and customizing the mount path:
|
|
2
|
-
|
|
3
|
-
```markdown
|
|
4
1
|
# Todoro
|
|
5
2
|
|
|
6
3
|
A lightweight Rails engine that lets any model manage task lists and tasks with a simple, flexible API.
|
|
@@ -54,6 +51,22 @@ task = project.add_task_to_list(task_list, "Build homepage", "Implement UI compo
|
|
|
54
51
|
puts project.tasks # Lists all tasks in all its task lists
|
|
55
52
|
```
|
|
56
53
|
|
|
54
|
+
## Automatic Route Generation
|
|
55
|
+
|
|
56
|
+
Todoro automatically generates routes for any model that includes `acts_as_taskable`. For example, if `Project` includes `acts_as_taskable`, the following routes are created:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
GET /projects/:project_id/task_lists(.:format)
|
|
60
|
+
POST /projects/:project_id/task_lists(.:format)
|
|
61
|
+
GET /projects/:project_id/task_lists/:id(.:format)
|
|
62
|
+
PATCH /projects/:project_id/task_lists/:id(.:format)
|
|
63
|
+
DELETE /projects/:project_id/task_lists/:id(.:format)
|
|
64
|
+
GET /projects/:project_id/task_lists/:task_list_id/tasks(.:format)
|
|
65
|
+
POST /projects/:project_id/task_lists/:task_list_id/tasks(.:format)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
These routes are automatically configured, so no additional setup is needed.
|
|
69
|
+
|
|
57
70
|
## Mounting the Engine
|
|
58
71
|
|
|
59
72
|
To access Todoro's routes, mount the engine in your application's routes file:
|
|
@@ -61,31 +74,13 @@ To access Todoro's routes, mount the engine in your application's routes file:
|
|
|
61
74
|
```ruby
|
|
62
75
|
# config/routes.rb
|
|
63
76
|
Rails.application.routes.draw do
|
|
64
|
-
mount Todoro::Engine, at:
|
|
77
|
+
mount Todoro::Engine, at: "/"
|
|
65
78
|
# Other routes...
|
|
66
79
|
end
|
|
67
80
|
```
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
### Customizing the Mount Path
|
|
72
|
-
|
|
73
|
-
You can mount Todoro at any path that fits your application's structure:
|
|
74
|
-
|
|
75
|
-
- To mount at the root:
|
|
76
|
-
|
|
77
|
-
```ruby
|
|
78
|
-
Rails.application.routes.draw do
|
|
79
|
-
mount Todoro::Engine, at: '/'
|
|
80
|
-
# Other routes...
|
|
81
|
-
end
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Now, Todoro's routes are available at the root URL (e.g., `http://yourdomain.com/`).
|
|
85
|
-
|
|
82
|
+
Since Todoro dynamically registers routes for `acts_as_taskable` models, no further route configuration is required.
|
|
86
83
|
|
|
87
84
|
## License
|
|
88
85
|
|
|
89
86
|
The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
|
|
90
|
-
|
|
91
|
-
```
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
module Todoro
|
|
2
|
-
class ApplicationController <
|
|
2
|
+
class ApplicationController < ::ApplicationController
|
|
3
|
+
before_action :set_taskable
|
|
4
|
+
before_action :validate_taskable!
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def set_taskable
|
|
9
|
+
taskable_type = params[:taskable_type]&.classify
|
|
10
|
+
taskable_id_param = "#{params[:taskable_type]}_id"
|
|
11
|
+
taskable_id = params[taskable_id_param]
|
|
12
|
+
|
|
13
|
+
if taskable_type.present? && taskable_id.present? && Todoro.taskable_models.include?(taskable_type)
|
|
14
|
+
@taskable = taskable_type.safe_constantize&.find_by(id: taskable_id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
render json: { error: "Taskable not found" }, status: :not_found unless @taskable
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def validate_taskable!
|
|
21
|
+
unless @taskable && Todoro.taskable_models.include?(@taskable.class.name)
|
|
22
|
+
render json: { error: "Unauthorized taskable model" }, status: :forbidden
|
|
23
|
+
end
|
|
24
|
+
end
|
|
3
25
|
end
|
|
4
26
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
module Todoro
|
|
2
2
|
class TaskListsController < ApplicationController
|
|
3
3
|
before_action :set_task_list, only: %i[show edit update destroy]
|
|
4
|
-
before_action :set_taskable, only: %i[index new create]
|
|
5
4
|
|
|
6
5
|
def index
|
|
7
6
|
@task_lists = @taskable.task_lists
|
|
@@ -16,7 +15,7 @@ module Todoro
|
|
|
16
15
|
def create
|
|
17
16
|
@task_list = @taskable.task_lists.new(task_list_params)
|
|
18
17
|
if @task_list.save
|
|
19
|
-
redirect_to
|
|
18
|
+
redirect_to [ @taskable, @task_list ], notice: "Task list created successfully."
|
|
20
19
|
else
|
|
21
20
|
render :new
|
|
22
21
|
end
|
|
@@ -26,7 +25,7 @@ module Todoro
|
|
|
26
25
|
|
|
27
26
|
def update
|
|
28
27
|
if @task_list.update(task_list_params)
|
|
29
|
-
redirect_to
|
|
28
|
+
redirect_to [ @taskable, @task_list ], notice: "Task list updated successfully."
|
|
30
29
|
else
|
|
31
30
|
render :edit
|
|
32
31
|
end
|
|
@@ -35,23 +34,14 @@ module Todoro
|
|
|
35
34
|
def destroy
|
|
36
35
|
taskable = @task_list.taskable
|
|
37
36
|
@task_list.destroy
|
|
38
|
-
|
|
37
|
+
|
|
38
|
+
redirect_to [ @taskable, :task_list ], notice: "Task list deleted."
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
private
|
|
42
42
|
|
|
43
43
|
def set_task_list
|
|
44
|
-
@task_list =
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def set_taskable
|
|
48
|
-
@taskable = find_taskable
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def find_taskable
|
|
52
|
-
return unless params[:taskable] && params[:taskable_id]
|
|
53
|
-
|
|
54
|
-
params[:taskable].constantize.find(params[:taskable_id])
|
|
44
|
+
@task_list = @taskable.task_lists.find(params[:id])
|
|
55
45
|
end
|
|
56
46
|
|
|
57
47
|
def task_list_params
|
|
@@ -8,9 +8,10 @@ module Todoro
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def create
|
|
11
|
-
@task = @task_list.tasks.
|
|
11
|
+
@task = @task_list.tasks.build(task_params)
|
|
12
|
+
|
|
12
13
|
if @task.save
|
|
13
|
-
redirect_to
|
|
14
|
+
redirect_to [ @taskable, @task_list ], notice: "Task created successfully."
|
|
14
15
|
else
|
|
15
16
|
render :new
|
|
16
17
|
end
|
|
@@ -20,7 +21,7 @@ module Todoro
|
|
|
20
21
|
|
|
21
22
|
def update
|
|
22
23
|
if @task.update(task_params)
|
|
23
|
-
redirect_to @task_list, notice: "Task updated successfully."
|
|
24
|
+
redirect_to [ @taskable, @task_list ], notice: "Task updated successfully."
|
|
24
25
|
else
|
|
25
26
|
render :edit
|
|
26
27
|
end
|
|
@@ -28,26 +29,26 @@ module Todoro
|
|
|
28
29
|
|
|
29
30
|
def destroy
|
|
30
31
|
@task.destroy
|
|
31
|
-
redirect_to @task_list, notice: "Task deleted."
|
|
32
|
+
redirect_to [ @taskable, @task_list ], notice: "Task deleted."
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def complete
|
|
35
36
|
@task.update(status: "completed")
|
|
36
|
-
redirect_to
|
|
37
|
+
redirect_to [ @taskable, @task_list ], notice: "Task marked as completed."
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
private
|
|
40
41
|
|
|
41
|
-
def set_task_list
|
|
42
|
-
@task_list = Todoro::TaskList.find(params[:task_list_id])
|
|
43
|
-
end
|
|
44
|
-
|
|
45
42
|
def set_task
|
|
46
43
|
@task = @task_list.tasks.find(params[:id])
|
|
47
44
|
end
|
|
48
45
|
|
|
46
|
+
def set_task_list
|
|
47
|
+
@task_list = @taskable.task_lists.find(params[:task_list_id])
|
|
48
|
+
end
|
|
49
|
+
|
|
49
50
|
def task_params
|
|
50
|
-
params.require(:task).permit(:title, :description, :
|
|
51
|
+
params.require(:task).permit(:title, :description, :status, :expiry_date)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
end
|
data/app/models/todoro/task.rb
CHANGED
|
@@ -4,7 +4,6 @@ module Todoro
|
|
|
4
4
|
has_many :reminders, dependent: :destroy
|
|
5
5
|
|
|
6
6
|
validates :title, presence: true
|
|
7
|
-
validates :description, presence: true
|
|
8
7
|
validates :status, presence: true, inclusion: { in: %w[pending completed] }
|
|
9
8
|
|
|
10
9
|
enum :status, { pending: "pending", completed: "completed" }
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
<%= form_with model: [taskable, task_list], local: true do |form| %>
|
|
1
|
+
<%= form_with model: task_list, url: polymorphic_path([@taskable, task_list]), local: true do |form| %>
|
|
2
2
|
<div class="form-group">
|
|
3
3
|
<%= form.label :name %>
|
|
4
4
|
<%= form.text_field :name, class: "form-control", required: true %>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
|
-
<%= form.hidden_field :taskable_id, value: taskable.id %>
|
|
8
|
-
<%= form.hidden_field :taskable_type, value: taskable.class.name %>
|
|
9
7
|
|
|
10
8
|
<%= form.submit class: "btn btn-success" %>
|
|
11
9
|
<% end %>
|
|
12
|
-
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<h1>Task Lists for <%= @taskable.class.name %>: <%= @taskable.try(:name) || "Unknown" %></h1>
|
|
2
2
|
|
|
3
|
-
<%= link_to "Create New Task List",
|
|
3
|
+
<%= link_to "Create New Task List", new_polymorphic_path([@taskable, :task_list]), class: "btn btn-primary" %>
|
|
4
4
|
|
|
5
5
|
<ul>
|
|
6
6
|
<% @task_lists.each do |task_list| %>
|
|
7
7
|
<li>
|
|
8
|
-
<%= link_to task_list.name,
|
|
9
|
-
(<%= link_to "Edit",
|
|
10
|
-
<%= link_to "Delete",
|
|
8
|
+
<%= link_to task_list.name, polymorphic_path([ @taskable, task_list]) %>
|
|
9
|
+
(<%= link_to "Edit", edit_polymorphic_path([@taskable, task_list ])%> |
|
|
10
|
+
<%= link_to "Delete", polymorphic_path([ @taskable, task_list ]), method: :delete, data: { confirm: "Are you sure?" } %>)
|
|
11
11
|
</li>
|
|
12
12
|
<% end %>
|
|
13
13
|
</ul>
|
|
14
14
|
|
|
15
|
-
<%= link_to "Back",
|
|
15
|
+
<%= link_to "Back", polymorphic_path(@taskable), class: "btn btn-secondary" %>
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
<h1><%= @task_list.name %></h1>
|
|
2
2
|
|
|
3
|
-
<%= link_to "Edit",
|
|
4
|
-
|
|
3
|
+
<%= link_to "Edit", edit_polymorphic_path([@task_list.taskable, @task_list]), class: "btn btn-warning" %>
|
|
4
|
+
|
|
5
|
+
<%= button_to "Delete", polymorphic_path([@task_list.taskable, @task_list]), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-danger btn-link" %>
|
|
5
6
|
|
|
6
7
|
<h2>Tasks</h2>
|
|
7
|
-
<%= link_to "Add Task",
|
|
8
|
+
<%= link_to "Add Task", new_polymorphic_path([@task_list.taskable, @task_list, :task]), class: "btn btn-primary" %>
|
|
8
9
|
|
|
9
10
|
<ul>
|
|
10
11
|
<% @task_list.tasks.each do |task| %>
|
|
11
12
|
<li>
|
|
12
13
|
<%= task.title %> - <%= task.status %>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<%=
|
|
14
|
+
<%= link_to "Edit", edit_polymorphic_path([@task_list.taskable, @task_list, task]) %> |
|
|
15
|
+
|
|
16
|
+
<%= button_to "Complete", polymorphic_path([@task_list.taskable, @task_list, task], action: :complete), method: :patch, class: "btn btn-success btn-link", data: { turbo: true } if task.status == "pending" %>
|
|
17
|
+
|
|
18
|
+
<%= button_to "Delete", polymorphic_path([@task_list.taskable, @task_list, task]), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-danger btn-link" %>
|
|
19
|
+
|
|
16
20
|
</li>
|
|
17
21
|
<% end %>
|
|
18
22
|
</ul>
|
|
19
23
|
|
|
20
|
-
<%= link_to "Back to Task Lists",
|
|
21
|
-
|
|
24
|
+
<%= link_to "Back to Task Lists", polymorphic_path([@task_list.taskable, :task_lists]), class: "btn btn-secondary" %>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%= form_with model: [
|
|
1
|
+
<%= form_with model: task, url: polymorphic_path([@taskable, @task_list, @task]), local: true do |form| %>
|
|
2
2
|
<div class="form-group">
|
|
3
3
|
<%= form.label :title %>
|
|
4
4
|
<%= form.text_field :title, class: "form-control", required: true %>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<div class="form-group">
|
|
8
8
|
<%= form.label :description %>
|
|
9
|
-
<%= form.text_area :description, class: "form-control"
|
|
9
|
+
<%= form.text_area :description, class: "form-control" %>
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
<div class="form-group">
|
data/config/routes.rb
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
Todoro::Engine.routes.draw do
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
Todoro.taskable_models.each do |model|
|
|
3
|
+
resource_name = model.underscore.pluralize.to_sym
|
|
4
|
+
|
|
5
|
+
resources resource_name, defaults: { taskable_type: model.downcase }, constraints: TaskableModelsConstraint.new do
|
|
6
|
+
resources :task_lists do
|
|
7
|
+
resources :tasks, only: [ :new, :edit, :create, :update, :destroy ] do
|
|
8
|
+
patch :complete, on: :member
|
|
9
|
+
end
|
|
6
10
|
end
|
|
7
11
|
end
|
|
8
12
|
end
|
data/lib/todoro/version.rb
CHANGED
data/lib/todoro.rb
CHANGED
|
@@ -3,4 +3,11 @@ require "todoro/engine"
|
|
|
3
3
|
require "todoro/taskable"
|
|
4
4
|
|
|
5
5
|
module Todoro
|
|
6
|
+
def self.taskable_models
|
|
7
|
+
Rails.application.eager_load!
|
|
8
|
+
|
|
9
|
+
ActiveRecord::Base.descendants.select do |model|
|
|
10
|
+
model.included_modules.include?(Todoro::Taskable)
|
|
11
|
+
end.map(&:name)
|
|
12
|
+
end
|
|
6
13
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: todoro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Despo Pentara
|
|
8
8
|
- Evangelos Giataganas
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-02-
|
|
11
|
+
date: 2025-02-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -37,6 +37,7 @@ files:
|
|
|
37
37
|
- README.md
|
|
38
38
|
- Rakefile
|
|
39
39
|
- app/assets/stylesheets/todoro/application.css
|
|
40
|
+
- app/constraints/taskable_models_constraint.rb
|
|
40
41
|
- app/controllers/todoro/application_controller.rb
|
|
41
42
|
- app/controllers/todoro/task_lists_controller.rb
|
|
42
43
|
- app/controllers/todoro/tasks_controller.rb
|
|
@@ -45,7 +46,6 @@ files:
|
|
|
45
46
|
- app/helpers/todoro/tasks_helper.rb
|
|
46
47
|
- app/jobs/todoro/application_job.rb
|
|
47
48
|
- app/mailers/todoro/application_mailer.rb
|
|
48
|
-
- app/models/concerns/taskable.rb
|
|
49
49
|
- app/models/todoro/application_record.rb
|
|
50
50
|
- app/models/todoro/reminder.rb
|
|
51
51
|
- app/models/todoro/task.rb
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module Todoro
|
|
2
|
-
module Taskable
|
|
3
|
-
extend ActiveSupport::Concern
|
|
4
|
-
|
|
5
|
-
included do
|
|
6
|
-
has_many :task_lists, as: :taskable, class_name: "Todoro::TaskList", dependent: :destroy
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def tasks
|
|
10
|
-
Todoro::Task.joins(:task_list).where(task_lists: { taskable_id: id, taskable_type: self.class.name })
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def create_task_list(name)
|
|
14
|
-
task_lists.create(name: name)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def add_task_to_list(task_list, title, description, expiry_date = nil)
|
|
18
|
-
task_list.tasks.create(title: title, description: description, expiry_date: expiry_date, status: "pending")
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|