diff --git a/.rubocop.yml b/.rubocop.yml
index 1e980ff..e6fba09 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -20,6 +20,7 @@ Style/StringLiterals:
# Mostly because of auto-generated files
- Gemfile
- config/application.rb
+ - config/importmap.rb
Bundler/OrderedGems:
Enabled: false
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 94e7183..4c45468 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -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
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 25219ed..ef405be 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -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
diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb
index 717cb40..359a4e4 100644
--- a/app/controllers/tasks_controller.rb
+++ b/app/controllers/tasks_controller.rb
@@ -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
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de6be79..15b06f0 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,2 +1,4 @@
+# frozen_string_literal: true
+
module ApplicationHelper
end
diff --git a/app/javascript/application.js b/app/javascript/application.js
index 9ae56c5..696ae3c 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -4,3 +4,7 @@ import "controllers"
import "trix"
import "@rails/actiontext"
+
+import {ProjectsSelector} from 'elements/project_selector'
+
+customElements.define('projects-selector', ProjectsSelector)
diff --git a/app/javascript/elements/project_selector.js b/app/javascript/elements/project_selector.js
new file mode 100644
index 0000000..dba71c4
--- /dev/null
+++ b/app/javascript/elements/project_selector.js
@@ -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`
+
+
+ `
+ }
+
+ _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``
+ }
+
+ _handleSelect(e) {
+ const href = e.target.value
+ Turbo.visit(href, {action: 'advance', frame: this.frame})
+ }
+}
diff --git a/app/views/application/_projects_selector.html.erb b/app/views/application/_projects_selector.html.erb
new file mode 100644
index 0000000..06772e0
--- /dev/null
+++ b/app/views/application/_projects_selector.html.erb
@@ -0,0 +1,7 @@
+<% if current_project %>
+