Tasks creation (mostly)
This commit is contained in:
@@ -11,7 +11,7 @@ class TasksController < ApplicationController
|
||||
Task.all
|
||||
end
|
||||
|
||||
@tasks = @tasks.includes(:status, project: :task_statuses)
|
||||
@tasks = @tasks.includes(:status, :workflow, project: :task_statuses)
|
||||
end
|
||||
|
||||
def show; end
|
||||
@@ -22,7 +22,7 @@ class TasksController < ApplicationController
|
||||
end
|
||||
|
||||
def create
|
||||
@form = Tasks::Create.new(params.expect(task: %i[project_id title description status_id]))
|
||||
@form = Tasks::Create.new(params.expect(task: %i[project_id title description status_id workflow_id]))
|
||||
if @form.perform
|
||||
redirect_to tasks_path(project: @form.project)
|
||||
else
|
||||
|
||||
@@ -2,20 +2,14 @@ import { Controller } from '@hotwired/stimulus'
|
||||
|
||||
// TODO: unite with ProjectsSelectorController?
|
||||
class FormProjectsSelectorController extends Controller {
|
||||
static values = {
|
||||
frame: String
|
||||
}
|
||||
|
||||
connect() {
|
||||
console.log("Connected", this.element)
|
||||
}
|
||||
static targets = ['frame']
|
||||
|
||||
changeProject(event) {
|
||||
const loc = new URL(location)
|
||||
const selected = event.target.selectedOptions[0]
|
||||
const code = selected.dataset.code
|
||||
loc.searchParams.set('project', code)
|
||||
Turbo.visit(loc.toString(), {frame: this.frameValue})
|
||||
Turbo.visit(loc.toString(), {frame: this.frameTarget})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,15 @@ module Projects
|
||||
class PostInitJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
include Projects::CreateDefaultTaskStatuses
|
||||
include Projects::CreateDefaults
|
||||
|
||||
def perform(project_id)
|
||||
project = Project.preparing.find(project_id)
|
||||
|
||||
project.transaction do
|
||||
workflow = create_default_workflow(project)
|
||||
create_tasks_number_sequence(project)
|
||||
create_default_task_statuses(project)
|
||||
create_default_task_statuses(project, workflow)
|
||||
project.update!(status: :ready)
|
||||
end
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ class Project < ApplicationRecord
|
||||
|
||||
has_many :tasks, dependent: :restrict_with_exception
|
||||
has_many :task_statuses, dependent: :destroy
|
||||
has_many :workflows, dependent: :destroy
|
||||
|
||||
has_rich_text :description
|
||||
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ class Task < ApplicationRecord
|
||||
private
|
||||
|
||||
def associations_should_have_same_project
|
||||
return if status&.project == project
|
||||
return if [project, status.project, workflow.project].uniq == [project]
|
||||
|
||||
errors.add(:status, "Doesn't belong in the same project")
|
||||
errors.add(:base, "Project isn't the same across associations")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,15 @@ class TaskStatus < ApplicationRecord
|
||||
|
||||
validates :name, presence: true, uniqueness: { scope: :project }
|
||||
validates :category, presence: true
|
||||
validate :associations_should_have_same_project
|
||||
|
||||
scope :default_order, -> { order(:category, :name) }
|
||||
|
||||
private
|
||||
|
||||
def associations_should_have_same_project
|
||||
return if workflow.project == project
|
||||
|
||||
errors.add(:workflow, "Doesn't belong in the same project")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Workflow < ApplicationRecord
|
||||
belongs_to :project
|
||||
|
||||
has_many :tasks, dependent: :restrict_with_exception
|
||||
has_mnay :statuses, dependent: :restrict_with_error
|
||||
has_many :statuses, dependent: :restrict_with_error
|
||||
|
||||
enum :icon, { task: 'task', warning: 'warning' }, default: 'task', scopes: false
|
||||
enum :color, { blue: 'blue', gray: 'gray', yellow: 'yellow', red: 'red' }, default: 'gray', scopes: false
|
||||
|
||||
@@ -6,8 +6,9 @@ module Tasks
|
||||
attribute :title, :string
|
||||
attribute :description, :string
|
||||
attribute :status_id, :integer
|
||||
attribute :workflow_id, :integer
|
||||
|
||||
validates :project_id, :title, :status_id, presence: true
|
||||
validates :project_id, :title, :status_id, :workflow_id, presence: true
|
||||
|
||||
delegate :model_name, to: Task
|
||||
|
||||
@@ -18,7 +19,7 @@ module Tasks
|
||||
end
|
||||
|
||||
def perform
|
||||
@task = project.tasks.build(title:, description:, status_id:, number: @project.next_task_number)
|
||||
@task = project.tasks.build(title:, description:, status_id:, workflow_id:, number: @project.next_task_number)
|
||||
save @task
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
- cache task do
|
||||
tr id="task_#{task.id}"
|
||||
td
|
||||
/ TODO: extract into a presenter (and especially add color)
|
||||
= image_tag('mingcute/task_line.svg', title: task.workflow.name)
|
||||
td= link_to task.full_number, task_path(task)
|
||||
td
|
||||
= task_status_selector task, with_form: true
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
h1 New task
|
||||
|
||||
= form_with model: @form, data: {controller: 'form-projects-selector', 'form-projects-selector-frame-value' => 'status_select'} do |form|
|
||||
= form_with model: @form, data: {controller: 'form-projects-selector'} do |form|
|
||||
.field
|
||||
= form.label :project_id
|
||||
= form.select :project_id, Project.order(:name).map { |p| [p.name, p.id, {'data-code': p.code}] }, {}, data: {action: 'form-projects-selector#changeProject'}
|
||||
= turbo_frame_tag :status_select do
|
||||
= turbo_frame_tag :project_field_selects, data: {'form-projects-selector-target': 'frame'} do
|
||||
.field
|
||||
= form.label :workflow
|
||||
= form.select :workflow_id, Workflow.where(project: @form.project).map { |w| [w.name, w.id] }
|
||||
|
||||
.field
|
||||
= form.label :status_id
|
||||
= form.select :status_id, TaskStatus.where(project: @form.project).default_order.map { |ts| [ts.name, ts.id] }
|
||||
|
||||
Reference in New Issue
Block a user