Projects selector

This commit is contained in:
2025-07-15 22:46:28 +03:00
parent 434b5b184e
commit 991ff51aae
11 changed files with 202 additions and 4 deletions
+13
View File
@@ -1,5 +1,18 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
include Authentication
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
allow_browser versions: :modern
helper_method :all_projects, :current_project
private
# Needed in projects selector (and can be used anywhere else)
def all_projects
Project.order(:name)
end
attr_accessor :current_project
end
+1
View File
@@ -38,6 +38,7 @@ class ProjectsController < ApplicationController
def fetch_project!
@project = Project.find_by!(code: params[:id])
self.current_project = @project
end
def project_params
+4 -3
View File
@@ -4,9 +4,9 @@ class TasksController < ApplicationController
before_action :fetch_task, only: %w[show edit update delete]
def index
@project = fetch_project
@tasks = if @project
@project.tasks
self.current_project = fetch_project
@tasks = if current_project
current_project.tasks
else
Task.all
end
@@ -58,5 +58,6 @@ class TasksController < ApplicationController
def fetch_task
@task = Task.includes(:project).find_by_full_number_or_id!(params[:id])
self.current_project = @task.project
end
end
+2
View File
@@ -1,2 +1,4 @@
# frozen_string_literal: true
module ApplicationHelper
end
+4
View File
@@ -4,3 +4,7 @@ import "controllers"
import "trix"
import "@rails/actiontext"
import {ProjectsSelector} from 'elements/project_selector'
customElements.define('projects-selector', ProjectsSelector)
@@ -0,0 +1,40 @@
import {html, css, LitElement} from 'lit'
export class ProjectsSelector extends LitElement {
static style=css`
slot {
display: none;
}
`
static properties = {
frame: {type: String},
_options: {type: Array, state: true}
}
render() {
return html`
<slot @slotchange=${this._handleUpdatedElements} style="display: none"></slot>
<select @change=${this._handleSelect}>
${(this._options || []).map(option => this._renderOption(option))}
</select>
`
}
_handleUpdatedElements(e) {
const childNodes = e.target.assignedElements({flatten: true})
this._options = childNodes.map(e => {
return {name: e.innerText, href: e.getAttribute('href'), selected: !!e.getAttribute('selected')}
})
}
_renderOption(option) {
const {name, href, selected} = option
return html`<option value="${href}" ?selected="${selected}">${name}</option>`
}
_handleSelect(e) {
const href = e.target.value
Turbo.visit(href, {action: 'advance', frame: this.frame})
}
}
@@ -0,0 +1,7 @@
<% if current_project %>
<projects-selector>
<% all_projects.each do |project| %>
<%= tag.option(project.name, href: project_path(project), selected: current_project == project) %>
<% end %>
</projects-selector>
<% end %>
+6 -1
View File
@@ -23,6 +23,11 @@
</head>
<body>
<%= yield %>
<aside>
<%= render partial: 'projects_selector' %>
</aside>
<main>
<%= yield %>
</main>
</body>
</html>