Tasks display

This commit is contained in:
2025-07-12 17:50:56 +03:00
parent 42d45853ff
commit 4f5b9dcf89
12 changed files with 120 additions and 7 deletions
+7 -1
View File
@@ -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
+1
View File
@@ -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
+5
View File
@@ -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
+24
View File
@@ -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
+2
View File
@@ -0,0 +1,2 @@
module TasksHelper
end
+26 -2
View File
@@ -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
+20
View File
@@ -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
+5 -1
View File
@@ -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
+14
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
div
em= @task.full_number
h1= @task.title
section= @task.description
+6 -1
View File
@@ -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
+4 -1
View File
@@ -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
@@ -15,4 +17,5 @@ Rails.application.routes.draw do
# root "posts#index" # root "posts#index"
resources :projects resources :projects
resources :tasks
end end