diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 94e7183..b2e8b65 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,13 @@ 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 + + def current_provider + @current_provider ||= begin + Current.user.providers.find(cookies.signed[:current_provider_id]) + rescue ActiveRecord::RecordNotFound + Current.user.providers.first + end + end + helper_method :current_provider end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb new file mode 100644 index 0000000..106248e --- /dev/null +++ b/app/controllers/settings_controller.rb @@ -0,0 +1,21 @@ +class SettingsController < ApplicationController + def provider + provider = provider_scope.find(provider_params[:id]) + cookies.signed[:current_provider_id] = provider.id if provider + redirect_to request.referer || root_path + end + + private + + def provider_params + params.expect(provider: :id) + end + + def provider_scope + @provider_scope ||= if Current.user.is_admin? + Provider.all + else + Current.user.providers + end + end +end diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index 27e1d8b..a3b96aa 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -3,7 +3,7 @@ class TopicsController < ApplicationController def index @topics = scope.search_with_params(search_params) - @providers = scope.map(&:provider).uniq.sort_by(&:name) + @available_providers = other_available_providers @languages = scope.map(&:language).uniq.sort_by(&:name) end @@ -45,16 +45,22 @@ def archive private + def other_available_providers + return [] unless Current.user.providers.any? + + Current.user.providers.where.not(id: current_provider.id) + end + def topic_params params.require(:topic).permit(:title, :description, :uid, :language_id, :provider_id, documents: []) end - helper_method :search_params def search_params return {} unless params[:search].present? params.require(:search).permit(:query, :state, :provider_id, :language_id, :year, :month, :order) end + helper_method :search_params def set_topic @topic = Topic.find(params[:id]) @@ -63,8 +69,15 @@ def set_topic def scope @scope ||= if Current.user.is_admin? Topic.all + elsif current_provider.present? + current_provider.topics else Current.user.topics end.includes(:language, :provider) end + + def topics_title + current_provider.present? ? "#{current_provider.name}/topics" : "Topics" + end + helper_method :topics_title end diff --git a/app/javascript/controllers/topics_controller.js b/app/javascript/controllers/topics_controller.js index a52693a..8670f60 100644 --- a/app/javascript/controllers/topics_controller.js +++ b/app/javascript/controllers/topics_controller.js @@ -2,14 +2,18 @@ import { Controller } from "@hotwired/stimulus" import { useDebounce } from "stimulus-use" export default class extends Controller { - static targets = [ "form" ] + static targets = [ "searchForm", "chooseForm" ] static debounces = [ "search" ] connect() { useDebounce(this, { wait: 300 }) } - search() { - this.formTarget.requestSubmit() + searchTopics() { + this.searchFormTarget.requestSubmit() + } + + chooseProvider() { + this.chooseFormTarget.requestSubmit() } } diff --git a/app/models/provider.rb b/app/models/provider.rb index aaa6488..7137874 100644 --- a/app/models/provider.rb +++ b/app/models/provider.rb @@ -18,6 +18,7 @@ class Provider < ApplicationRecord has_many :regions, through: :branches has_many :contributors has_many :users, through: :contributors + has_many :topics validates :name, :provider_type, presence: true validates :name, uniqueness: true diff --git a/app/views/topics/_choose_provider.html.erb b/app/views/topics/_choose_provider.html.erb new file mode 100644 index 0000000..24dbd92 --- /dev/null +++ b/app/views/topics/_choose_provider.html.erb @@ -0,0 +1,12 @@ +<%= form_for :provider , url: provider_settings_path, method: :put, data: { controller: "topics", topics_target: "chooseForm", turbo_frame: "topics", turbo_action: "advance" } do |f| %> +
+
+
+
+ <%= f.label :provider %> + <%= f.select :id, options_from_collection_for_select(providers, :id, :name), { prompt: "Change provider" }, class: "form-select", data: { action: "change->topics#chooseProvider" } %> +
+
+
+
+<% end %> diff --git a/app/views/topics/_search.html.erb b/app/views/topics/_search.html.erb index d5a7359..2e7369e 100644 --- a/app/views/topics/_search.html.erb +++ b/app/views/topics/_search.html.erb @@ -4,49 +4,43 @@
- <%= form_for :search, url: topics_path, method: :get, data: { controller: "topics", topics_target: "form", turbo_frame: "topic-list", turbo_action: "advance" } do |f| %> + <%= form_for :search, url: topics_path, method: :get, data: { controller: "topics", topics_target: "searchForm", turbo_frame: "topic-list", turbo_action: "advance" } do |f| %>
-
+
- <%= f.label :provider %> - <%= f.select :provider_id, options_from_collection_for_select(providers, :id, :name, params[:provider_id]), { prompt: "Select provider" }, class: "form-select", data: { action: "change->topics#search" } %> + <%= f.label :query %> + <%= f.text_field :query, value: params[:query], class: "form-control", data: { action: "input->topics#searchTopics" } %>
<%= f.label :language %> - <%= f.select :language_id, options_from_collection_for_select(languages, :id, :name, params[:provider_id]), { prompt: "Select language" }, class: "form-select", data: { action: "change->topics#search" } %> -
-
-
-
- <%= f.label :query %> - <%= f.text_field :query, value: params[:query], class: "form-control", data: { action: "input->topics#search" } %> + <%= f.select :language_id, options_from_collection_for_select(languages, :id, :name, params[:provider_id]), { prompt: "Select language" }, class: "form-select", data: { action: "change->topics#searchTopics" } %>
<%= f.label :year %> - <%= f.select :year, options_for_select((Date.today.year-10..Date.today.year).to_a, params[:year]), { prompt: "Select year" }, class: "form-select", data: { action: "change->topics#search" } %> + <%= f.select :year, options_for_select((Date.today.year-10..Date.today.year).to_a, params[:year]), { prompt: "Select year" }, class: "form-select", data: { action: "change->topics#searchTopics" } %>
<%= f.label :month %> - <%= f.select :month, options_for_select((1..12).to_a, params[:month]), { prompt: "Select month" }, class: "form-select", data: { action: "change->topics#search" } %> + <%= f.select :month, options_for_select((1..12).to_a, params[:month]), { prompt: "Select month" }, class: "form-select", data: { action: "change->topics#searchTopics" } %>
<%= f.label :state %> - <%= f.select :state, options_for_select(Topic::STATES.index_with(&:itself), params[:state]), { prompt: "Select state" }, class: "form-select", data: { action: "change->topics#search" } %> + <%= f.select :state, options_for_select(Topic::STATES.index_with(&:itself), params[:state]), { prompt: "Select state" }, class: "form-select", data: { action: "change->topics#searchTopics" } %>
<%= f.label :order %> - <%= f.select :order, options_for_select(Topic::SORTS.reverse.index_with(&:itself), params[:order]), {}, class: "form-select", data: { action: "change->topics#search" } %> + <%= f.select :order, options_for_select(Topic::SORTS.reverse.index_with(&:itself), params[:order]), {}, class: "form-select", data: { action: "change->topics#searchTopics" } %>
diff --git a/app/views/topics/index.html.erb b/app/views/topics/index.html.erb index 86ade81..4dcf4d0 100644 --- a/app/views/topics/index.html.erb +++ b/app/views/topics/index.html.erb @@ -4,37 +4,42 @@
<%= render "search", providers: @providers, languages: @languages, params: search_params %> -
-
-

Topics

- <%= link_to new_topic_path, class: "btn btn-primary" do %> - Add New Topic - <% end %> -
-
-
-

Some important information or instruction can be placed here.

- <%= turbo_frame_tag "topic-list" do %> -
- - - - - - - - - - - - - <%= render "list", topics: @topics %> -
TitleDescriptionUIDLanguageProviderStateActions
-
+ <%= turbo_frame_tag "topics" do %> +
+
+

<%= topics_title %>

+ <%= link_to new_topic_path, class: "btn btn-primary" do %> + Add New Topic <% end %>
+
+
+ <% if @available_providers.any? %> + <%= render "choose_provider", providers: @available_providers %> + <% end %> +

Some important information or instruction can be placed here.

+ <%= turbo_frame_tag "topic-list" do %> +
+ + + + + + + + + + + + + <%= render "list", topics: @topics %> +
TitleDescriptionUIDLanguageProviderStateActions
+
+ <% end %> +
+
-
+ <% end %>
diff --git a/config/routes.rb b/config/routes.rb index f74514b..7b2f354 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,9 @@ resources :topics do put :archive, on: :member end + resource :settings, only: [] do + put :provider, on: :collection + end # Render dynamic PWA files from app/views/pwa/* (remember to link manifest in application.html.erb) # get "manifest" => "rails/pwa#manifest", as: :pwa_manifest diff --git a/spec/requests/settings/provider_spec.rb b/spec/requests/settings/provider_spec.rb new file mode 100644 index 0000000..4e88529 --- /dev/null +++ b/spec/requests/settings/provider_spec.rb @@ -0,0 +1,33 @@ +require "rails_helper" + +describe "Settings", type: :request do + describe "PUT /settings/provider" do + let(:user) { create(:user) } + let(:provider) { create(:provider) } + + before { sign_in(user) } + + context "when provider cannot be found" do + it "does not update current provider" do + put provider_settings_url, params: { provider: { id: provider.id } } + + expect(response).to have_http_status(:not_found) + end + end + + context "when user has access to provider" do + before do + user.providers << provider + end + + it "updates current provider" do + put provider_settings_url, params: { provider: { id: provider.id } } + + signed_cookies = ActionDispatch::Request.new(Rails.application.env_config).cookie_jar + + expect(response).to redirect_to(root_url) + expect(signed_cookies.signed[:current_provider_id]).to eq(provider.id) + end + end + end +end