Tasks display
This commit is contained in:
+7
-1
@@ -17,7 +17,9 @@ AllCops:
|
|||||||
|
|
||||||
Style/StringLiterals:
|
Style/StringLiterals:
|
||||||
Exclude:
|
Exclude:
|
||||||
- Gemfile # Mostly because of auto-generated files
|
# Mostly because of auto-generated files
|
||||||
|
- Gemfile
|
||||||
|
- config/application.rb
|
||||||
|
|
||||||
Bundler/OrderedGems:
|
Bundler/OrderedGems:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
@@ -28,6 +30,10 @@ Style/Documentation:
|
|||||||
Rails/ActionOrder:
|
Rails/ActionOrder:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
Rails/DynamicFindBy:
|
||||||
|
AllowedMethods:
|
||||||
|
- find_by_full_number_or_id!
|
||||||
|
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Exclude:
|
Exclude:
|
||||||
- db/migrate/*.rb
|
- db/migrate/*.rb
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ gem "thruster", require: false
|
|||||||
gem "image_processing", "~> 1.2"
|
gem "image_processing", "~> 1.2"
|
||||||
|
|
||||||
gem 'slim'
|
gem 'slim'
|
||||||
|
gem 'slim-rails'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
||||||
|
|||||||
@@ -263,6 +263,10 @@ GEM
|
|||||||
slim (5.2.1)
|
slim (5.2.1)
|
||||||
temple (~> 0.10.0)
|
temple (~> 0.10.0)
|
||||||
tilt (>= 2.1.0)
|
tilt (>= 2.1.0)
|
||||||
|
slim-rails (3.7.0)
|
||||||
|
actionpack (>= 3.1)
|
||||||
|
railties (>= 3.1)
|
||||||
|
slim (>= 3.0, < 6.0, != 5.0.0)
|
||||||
solid_cable (3.0.8)
|
solid_cable (3.0.8)
|
||||||
actioncable (>= 7.2)
|
actioncable (>= 7.2)
|
||||||
activejob (>= 7.2)
|
activejob (>= 7.2)
|
||||||
@@ -338,6 +342,7 @@ DEPENDENCIES
|
|||||||
rubocop
|
rubocop
|
||||||
rubocop-rails
|
rubocop-rails
|
||||||
slim
|
slim
|
||||||
|
slim-rails
|
||||||
solid_cable
|
solid_cable
|
||||||
solid_cache
|
solid_cache
|
||||||
solid_queue
|
solid_queue
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TasksController < ApplicationController
|
||||||
|
before_action :fetch_task, only: %w[show edit update delete]
|
||||||
|
|
||||||
|
def index
|
||||||
|
if params[:project]
|
||||||
|
@project = Project.find_by!(code: params[:project])
|
||||||
|
@tasks = @project.tasks
|
||||||
|
else
|
||||||
|
@tasks = Task.all
|
||||||
|
end
|
||||||
|
|
||||||
|
@tasks = @tasks.includes(:project)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show; end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def fetch_task
|
||||||
|
@task = Task.find_by_full_number_or_id!(params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
module TasksHelper
|
||||||
|
end
|
||||||
+26
-2
@@ -2,17 +2,41 @@
|
|||||||
|
|
||||||
class Project < ApplicationRecord
|
class Project < ApplicationRecord
|
||||||
validates :name, :code, presence: true
|
validates :name, :code, presence: true
|
||||||
validates :code, exclusion: { in: %w[new] }, uniqueness: true
|
validates :code, exclusion: { in: %w[new] }, uniqueness: true, format: { with: /\A[a-z]{2,}\z/ }
|
||||||
|
|
||||||
has_many :tasks, dependent: :restrict_with_exception
|
has_many :tasks, dependent: :restrict_with_exception
|
||||||
|
|
||||||
has_rich_text :description
|
has_rich_text :description
|
||||||
|
|
||||||
normalizes :code, with: ->(code) { code.strip.downcase }
|
normalizes :code, with: ->(code) { code.strip.downcase.gsub(/\W+/, '') }
|
||||||
|
|
||||||
|
after_commit :create_tasks_number_sequence, on: :create
|
||||||
|
after_destroy_commit :drop_tasks_number_sequence
|
||||||
|
|
||||||
def to_param
|
def to_param
|
||||||
return unless id
|
return unless id
|
||||||
|
|
||||||
code
|
code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tasks_number_sequence_name
|
||||||
|
"_seq_projects__#{code}_tasks_number"
|
||||||
|
end
|
||||||
|
|
||||||
|
def next_task_number
|
||||||
|
result = self.class.connection.exec_query "SELECT NEXT VALUE FOR #{tasks_number_sequence_name} AS task_number"
|
||||||
|
raise "Expected one result, got #{result.count}" unless result.one?
|
||||||
|
|
||||||
|
result.first['task_number']
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_tasks_number_sequence
|
||||||
|
self.class.connection.execute "CREATE SEQUENCE IF NOT EXISTS #{tasks_number_sequence_name} AS INT UNSIGNED"
|
||||||
|
end
|
||||||
|
|
||||||
|
def drop_tasks_number_sequence
|
||||||
|
self.class.connection.execute "DROP SEQUENCE IF EXISTS #{tasks_number_sequence_name}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Task < ApplicationRecord
|
class Task < ApplicationRecord
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
|
|
||||||
@@ -5,4 +7,22 @@ class Task < ApplicationRecord
|
|||||||
validates :number, numericality: { greater_than: 0 }
|
validates :number, numericality: { greater_than: 0 }
|
||||||
|
|
||||||
has_rich_text :description
|
has_rich_text :description
|
||||||
|
|
||||||
|
def to_param
|
||||||
|
return full_number if association(:project).loaded?
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_number
|
||||||
|
"#{project.code.upcase}-#{number}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_by_full_number_or_id!(number_or_id)
|
||||||
|
return find!(number_or_id) if number_or_id.is_a?(Numeric) || number_or_id =~ /\A\d+\z/
|
||||||
|
|
||||||
|
project_code, number = number_or_id.split('-')
|
||||||
|
project = Project.find_by!(code: project_code.downcase)
|
||||||
|
find_by!(project:, number:)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
.row
|
||||||
|
= link_to 'New', new_project_path
|
||||||
|
|
||||||
ul
|
ul
|
||||||
- @projects.each do |project|
|
- @projects.each do |project|
|
||||||
li= link_to project.name, project
|
li
|
||||||
|
= link_to project.name, project
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
.row
|
||||||
|
= link_to 'New', new_task_path(project: @project&.code)
|
||||||
|
|
||||||
|
- if @tasks.exists?
|
||||||
|
table
|
||||||
|
thead
|
||||||
|
tbody
|
||||||
|
- @tasks.each do |task|
|
||||||
|
- cache task do
|
||||||
|
tr
|
||||||
|
td= link_to task.full_number, task_path(task)
|
||||||
|
td= task.title
|
||||||
|
- else
|
||||||
|
p No tasks
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
div
|
||||||
|
em= @task.full_number
|
||||||
|
h1= @task.title
|
||||||
|
|
||||||
|
section= @task.description
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "boot"
|
require_relative "boot"
|
||||||
|
|
||||||
require "rails"
|
require "rails"
|
||||||
@@ -37,6 +39,9 @@ module SubtleStorm
|
|||||||
# config.eager_load_paths << Rails.root.join("extras")
|
# config.eager_load_paths << Rails.root.join("extras")
|
||||||
|
|
||||||
# Don't generate system test files.
|
# Don't generate system test files.
|
||||||
config.generators.system_tests = nil
|
config.generators do |g|
|
||||||
|
g.system_tests nil
|
||||||
|
g.template_engine :slim
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+5
-2
@@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
resource :session
|
resource :session
|
||||||
resources :passwords, param: :token
|
resources :passwords, param: :token
|
||||||
@@ -5,7 +7,7 @@ Rails.application.routes.draw do
|
|||||||
|
|
||||||
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
|
||||||
# Can be used by load balancers and uptime monitors to verify that the app is live.
|
# Can be used by load balancers and uptime monitors to verify that the app is live.
|
||||||
get "up" => "rails/health#show", as: :rails_health_check
|
get 'up' => 'rails/health#show', as: :rails_health_check
|
||||||
|
|
||||||
# Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb)
|
# Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb)
|
||||||
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
|
# get "manifest" => "rails/pwa#manifest", as: :pwa_manifest
|
||||||
@@ -13,6 +15,7 @@ Rails.application.routes.draw do
|
|||||||
|
|
||||||
# Defines the root path route ("/")
|
# Defines the root path route ("/")
|
||||||
# root "posts#index"
|
# root "posts#index"
|
||||||
|
|
||||||
resources :projects
|
resources :projects
|
||||||
|
resources :tasks
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user