diff --git a/app/components/admin/boxes/boxes_list_row_component.html.erb b/app/components/admin/boxes/boxes_list_row_component.html.erb index 385005ce3..4f37b323b 100644 --- a/app/components/admin/boxes/boxes_list_row_component.html.erb +++ b/app/components/admin/boxes/boxes_list_row_component.html.erb @@ -1,8 +1,6 @@
-
-

<%= @box.short_name || @box.name[0] %>

-
+ <%= render Common::BoxLabelComponent.new(@box) %>
@@ -16,7 +14,10 @@ <%= link_to edit_admin_tenant_box_path(@box.tenant, @box), data: { turbo_frame: :modal } do %> <%= render Common::EditButtonComponent.new %> <% end %> - <%= button_to admin_tenant_box_path(@box.tenant, @box), method: :delete do %> + <%= button_to admin_tenant_box_path(@box.tenant, @box), + method: :delete, + disabled: @box == Current.box, + data: { turbo_confirm: "Naozaj odstrániť schránku #{@box.name} ?"} do %> <%= render Common::DeleteButtonComponent.new %> <% end %>
diff --git a/app/components/common/box_label_component.html.erb b/app/components/common/box_label_component.html.erb new file mode 100644 index 000000000..e95421051 --- /dev/null +++ b/app/components/common/box_label_component.html.erb @@ -0,0 +1,33 @@ +<%# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %> +<%# If color values are changed, adjust the color list below !!!!!!!!! %> +<%# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %> +
+

<%= @box.short_name || @box.name[0] %>

+
+<%# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %> +<%# Necessary to generate proper CSS for dynamically generated colors %> +<%# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %> +<%# !!!!!! Change values here, if values in template change !!!!!! %> +<%# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %> +<%# class="bg-slate-100 border border-slate-400 text-slate-600" %> +<%# class="bg-gray-100 border border-gray-400 text-gray-600" %> +<%# class="bg-zinc-100 border border-zinc-400 text-zinc-600" %> +<%# class="bg-neutral-100 border border-neutral-400 text-neutral-600" %> +<%# class="bg-stone-100 border border-stone-400 text-stone-600" %> +<%# class="bg-red-100 border border-red-400 text-red-600" %> +<%# class="bg-orange-100 border border-orange-400 text-orange-600" %> +<%# class="bg-amber-100 border border-amber-400 text-amber-600" %> +<%# class="bg-yellow-100 border border-yellow-400 text-yellow-600" %> +<%# class="bg-lime-100 border border-lime-400 text-lime-600" %> +<%# class="bg-green-100 border border-green-400 text-green-600" %> +<%# class="bg-emerald-100 border border-emerald-400 text-emerald-600" %> +<%# class="bg-teal-100 border border-teal-400 text-teal-600" %> +<%# class="bg-cyan-100 border border-cyan-400 text-cyan-600" %> +<%# class="bg-sky-100 border border-sky-400 text-sky-600" %> +<%# class="bg-blue-100 border border-blue-400 text-blue-600" %> +<%# class="bg-indigo-100 border border-indigo-400 text-indigo-600" %> +<%# class="bg-violet-100 border border-violet-400 text-violet-600" %> +<%# class="bg-purple-100 border border-purple-400 text-purple-600" %> +<%# class="bg-fuchsia-100 border border-fuchsia-400 text-fuchsia-600" %> +<%# class="bg-pink-100 border border-pink-400 text-pink-600" %> +<%# class="bg-rose-100 border border-rose-400 text-rose-600" %> diff --git a/app/components/common/box_label_component.rb b/app/components/common/box_label_component.rb new file mode 100644 index 000000000..391984fa1 --- /dev/null +++ b/app/components/common/box_label_component.rb @@ -0,0 +1,7 @@ +module Common + class BoxLabelComponent < ViewComponent::Base + def initialize(box) + @box = box + end + end +end diff --git a/app/components/layout/box_list_component.html.erb b/app/components/layout/box_list_component.html.erb new file mode 100644 index 000000000..a0e60abf5 --- /dev/null +++ b/app/components/layout/box_list_component.html.erb @@ -0,0 +1,15 @@ +<%= tag.turbo_frame id:'box-list', class:"flex-col self-stretch" do %> + <% @boxes.each do |box| %> + <%= link_to select_box_path(box), class:"flex justify-between items-center self-stretch flex-grow-0 flex-shrink-0 px-4 py-2", data: { turbo_frame: "_top" } do %> +
+
+ <%= render Common::BoxLabelComponent.new(box) %> +
+

<%= box.name %>

+
+
+

<%= box.messages.where(read: false).size %>

+
+ <% end %> + <% end %> +<% end %> diff --git a/app/components/layout/box_list_component.rb b/app/components/layout/box_list_component.rb new file mode 100644 index 000000000..588d2fcff --- /dev/null +++ b/app/components/layout/box_list_component.rb @@ -0,0 +1,5 @@ +class Layout::BoxListComponent < ViewComponent::Base + def initialize(boxes) + @boxes = boxes + end +end \ No newline at end of file diff --git a/app/components/layout/box_selector_component.html.erb b/app/components/layout/box_selector_component.html.erb new file mode 100644 index 000000000..aab74e635 --- /dev/null +++ b/app/components/layout/box_selector_component.html.erb @@ -0,0 +1,29 @@ +
+ + +
diff --git a/app/components/layout/box_selector_component.rb b/app/components/layout/box_selector_component.rb new file mode 100644 index 000000000..cf9dc24a3 --- /dev/null +++ b/app/components/layout/box_selector_component.rb @@ -0,0 +1,2 @@ +class Layout::BoxSelectorComponent < ViewComponent::Base +end diff --git a/app/components/layout/box_selector_popup_component.html.erb b/app/components/layout/box_selector_popup_component.html.erb new file mode 100644 index 000000000..94513ca25 --- /dev/null +++ b/app/components/layout/box_selector_popup_component.html.erb @@ -0,0 +1,28 @@ +
+ <%= link_to select_all_boxes_path, class:"flex justify-between items-center self-stretch flex-grow-0 flex-shrink-0 px-4 py-2" do %> +
+

Všetky schránky

+
+
+

<%= @all_unread_messages&.count %>

+
+ <% end %> +
+ + + +
+ <%= form_with url: search_boxes_path, class:"flex justify-start items-center self-stretch flex-grow-0 flex-shrink-0 gap-2 p-4 border-t-0 border-r-0 border-b border-l-0 border-gray-200" do |form| %> +
+
+ <%= render Icons::SearchComponent.new %> +
+ <%= tag.turbo_frame id:'box-search-results' %> + <%= form.search_field :name_search, value: params[:name_search], placeholder: "Vyhľadaj schránku", + oninput: "this.form.requestSubmit()", + onreset: "this.form.requestSubmit()", + class: "block w-full flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" %> +
+ <% end %> + <%= render Layout::BoxListComponent.new(@boxes) %> +
diff --git a/app/components/layout/box_selector_popup_component.rb b/app/components/layout/box_selector_popup_component.rb new file mode 100644 index 000000000..0d25ba36b --- /dev/null +++ b/app/components/layout/box_selector_popup_component.rb @@ -0,0 +1,6 @@ +class Layout::BoxSelectorPopupComponent < ViewComponent::Base + def initialize + @boxes = Current.tenant.boxes.where.not(boxes: { id: nil }) || [] + @all_unread_messages = Pundit.policy_scope(Current.user, Message).where(read:false) if Current.user + end +end \ No newline at end of file diff --git a/app/components/message_threads_table_row_component.html.erb b/app/components/message_threads_table_row_component.html.erb index 48c33b3fd..9388cd249 100644 --- a/app/components/message_threads_table_row_component.html.erb +++ b/app/components/message_threads_table_row_component.html.erb @@ -2,31 +2,29 @@
<%= check_box_tag('message_thread_ids[]', @message_thread.id) %> > -
-
-

GO

-
+
+ <%= render Common::BoxLabelComponent.new(@message_thread.box) %>
-
- <%= link_to @message_thread, class:"flex justify-stretch overflow-clip items-center grow gap-2" do %> -
-

"><%= @message_thread.title %>

-

<%= @message_thread.with_whom %>

-
- <% @message_thread.tags.each do |tag| %> - <% if tag.visible %> -
-

<%= tag.name %>

-
+ <%= link_to @message_thread, class:"flex justify-stretch overflow-clip items-center grow gap-2" do %> +
+

"><%= @message_thread.title %>

+

<%= @message_thread.with_whom %>

+
+
+ <% @message_thread.tags.each do |tag| %> + <% if tag.visible %> +
+

<%= tag.name %>

+
+ <% end %> <% end %> - <% end %> -
-
-

<%= l @message_thread.last_message_delivered_at, :format => :long %>

-
- - - - <% end %> -
+
+
+

<%= l @message_thread.last_message_delivered_at, :format => :long %>

+
+ + + + <% end %> +
diff --git a/app/components/t_w/top_navigation_component.html.erb b/app/components/t_w/top_navigation_component.html.erb index dff3636b2..cbd210e5d 100644 --- a/app/components/t_w/top_navigation_component.html.erb +++ b/app/components/t_w/top_navigation_component.html.erb @@ -1,12 +1,5 @@
-
-
- - - -

Všetky schránky

-
-
+ <%= render Layout::BoxSelectorComponent.new %> @@ -28,7 +21,6 @@ <% end %> <%= f.search_field :q, value: params[:q], placeholder: 'Vyhľadaj správu', class: 'pl-10 text-base text-left text-gray-900 placeholder-gray-400', style: 'width: 100%' %> <% end %> -
diff --git a/app/controllers/boxes_controller.rb b/app/controllers/boxes_controller.rb index 4cb2ad8ca..aa273b0b0 100644 --- a/app/controllers/boxes_controller.rb +++ b/app/controllers/boxes_controller.rb @@ -1,5 +1,5 @@ class BoxesController < ApplicationController - before_action :load_box, only: [:show, :sync] + before_action :load_box, only: %i[show sync select] def index authorize Box @@ -12,10 +12,31 @@ def show def sync authorize @box, policy_class: BoxPolicy - raise ActionController::MethodNotAllowed.new('Not authorized') unless policy_scope(Box).exists?(@box.id) + raise ActionController::MethodNotAllowed.new("Not authorized") unless policy_scope(Box).exists?(@box.id) Govbox::SyncBoxJob.perform_later(@box) end + def select + authorize @box + session[:box_id] = @box.id + redirect_to request.referrer + end + + def select_all + authorize Box + # TODO: Chceme to takto? nil = vsetky Alebo chceme pridavat inu variablu pre tento stav? + session[:box_id] = nil + redirect_to request.referrer + end + + def search + authorize(Box) + @boxes = policy_scope(Box) + .where(tenant_id: Current.tenant.id) + .where("unaccent(name) ILIKE unaccent(?) OR unaccent(short_name) ILIKE unaccent(?)", "%#{params[:name_search]}%", "%#{params[:name_search]}%") + .order(:name) + end + private def load_box diff --git a/app/controllers/concerns/authentication.rb b/app/controllers/concerns/authentication.rb index 16cfe6ca2..97d251a27 100644 --- a/app/controllers/concerns/authentication.rb +++ b/app/controllers/concerns/authentication.rb @@ -36,12 +36,13 @@ def clean_session session[:user_id] = nil session[:login_expires_at] = nil session[:tenant_id] = nil + session[:box_id] = nil end def load_current_user Current.user = User.find(session[:user_id]) if session[:user_id] Current.tenant = Tenant.find(session[:tenant_id]) if session[:tenant_id] - Current.box ||= Current.tenant&.boxes&.first + Current.box = Current.tenant.boxes.find(session[:box_id]) if session[:box_id] end def valid_session?(session) diff --git a/app/controllers/message_drafts_imports_controller.rb b/app/controllers/message_drafts_imports_controller.rb index 1e0979c66..62566e8fb 100644 --- a/app/controllers/message_drafts_imports_controller.rb +++ b/app/controllers/message_drafts_imports_controller.rb @@ -17,6 +17,8 @@ def create end def upload_new + @box = Current.box if Current.box + @box = Current.tenant.boxes.first if Current.tenant.boxes.count == 1 authorize MessageDraftsImport end diff --git a/app/controllers/message_threads_controller.rb b/app/controllers/message_threads_controller.rb index df11b65c3..b358dd723 100644 --- a/app/controllers/message_threads_controller.rb +++ b/app/controllers/message_threads_controller.rb @@ -22,7 +22,7 @@ def index cursor = MessageThreadCollection.init_cursor(search_params[:cursor]) @message_threads, @next_cursor = MessageThreadCollection.all( - scope: message_thread_policy_scope.includes(:tags), + scope: message_thread_policy_scope.includes(:tags, :box), search_permissions: search_permissions, query: search_params[:q], no_visible_tags: search_params[:no_visible_tags] == '1' && Current.user.admin?, @@ -63,6 +63,7 @@ def message_thread_policy_scope def search_permissions result = { tenant_id: Current.tenant } + result[:box_id] = Current.box if Current.box result[:tag_ids] = policy_scope(Tag).pluck(:id) unless Current.user.admin? result end diff --git a/app/models/box.rb b/app/models/box.rb index 2da8df232..34f4d8f83 100644 --- a/app/models/box.rb +++ b/app/models/box.rb @@ -15,6 +15,7 @@ class Box < ApplicationRecord has_many :folders, dependent: :destroy has_many :message_threads, through: :folders, extend: MessageThreadsExtensions, dependent: :destroy + has_many :messages, through: :message_threads has_many :message_drafts_imports, dependent: :destroy before_destroy ->(box) { EventBus.publish(:box_destroyed, box.id) } diff --git a/app/models/message_thread.rb b/app/models/message_thread.rb index 590bd09f7..2a81083c8 100644 --- a/app/models/message_thread.rb +++ b/app/models/message_thread.rb @@ -13,6 +13,7 @@ class MessageThread < ApplicationRecord has_and_belongs_to_many :tags belongs_to :folder + has_one :box, through: :folder has_many :messages, dependent: :destroy do def find_or_create_by_uuid!(uuid:) end diff --git a/app/models/searchable/message_thread.rb b/app/models/searchable/message_thread.rb index 1407d2b7d..15dc15465 100644 --- a/app/models/searchable/message_thread.rb +++ b/app/models/searchable/message_thread.rb @@ -16,6 +16,7 @@ def self.search_ids(query_filter, search_permissions:, cursor:, per_page:, direc scope = self scope = scope.where(tenant_id: search_permissions.fetch(:tenant_id)) + scope = scope.where(box_id: search_permissions.fetch(:box_id)) if search_permissions[:box_id] if search_permissions.key?(:tag_ids) if search_permissions[:tag_ids].any? diff --git a/app/policies/box_policy.rb b/app/policies/box_policy.rb index 8cd4270fe..9f1ef4dc1 100644 --- a/app/policies/box_policy.rb +++ b/app/policies/box_policy.rb @@ -8,8 +8,6 @@ def initialize(user, box) @box = box end - # TODO: Cely tento policy file je asi na prerabku, kedze vacsina z neho je adminova, a je vlastne kopiou z admina - class Scope < Scope def resolve @user.site_admin? ? scope.all : scope.where(tenant: @user.tenant) @@ -28,23 +26,16 @@ def sync? @user.site_admin? || @user.admin? end - def create? - @user.site_admin? || @user.admin? + def select? + true end - def new? - create? + def select_all? + true end - def update? - @user.site_admin? || @user.admin? + def search? + true end - def edit? - update? - end - - def destroy? - @user.site_admin? || @user.admin? - end end diff --git a/app/views/admin/tenants/show.html.erb b/app/views/admin/tenants/show.html.erb deleted file mode 100644 index ecf912c77..000000000 --- a/app/views/admin/tenants/show.html.erb +++ /dev/null @@ -1,236 +0,0 @@ -
-
-
-
    -
  • -
    -

    Tenant

    -
    -
    -
    - <% if notice.present? %> -

    <%= notice %>

    - <% end %> - <%= render @tenant %> - <%= link_to 'Edit this tenant', edit_admin_tenant_path(@tenant), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %> -
    - <%= button_to 'Destroy this tenant', admin_tenant_path(@tenant), method: :delete, data: { confirm: 'Are you sure?' }, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %> -
    - <%= link_to 'Back to tenants', admin_tenants_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %> -
    -
    -
  • - -
  • -
    -
    -

    Groups

    - <%= link_to 'New group', new_admin_tenant_group_path(@tenant.id), class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %> -
    -
    -
    -
    -
    - - - - - - - - - - <%= render Admin::GroupTableRowComponent.with_collection(@tenant.groups) %> - -
    - - Name - - - - - - Group Type - - - - - Edit -
    -
    -
    -
    -
    -
    -
  • - -
  • -
    -
    -

    Users

    - <%= link_to 'New user', new_admin_tenant_user_path(@tenant.id), class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %> -
    -
    -
    -
    -
    - - - - - - - - - - <%= render(Admin::UserTableRowComponent.with_collection(@tenant.users)) %> - -
    - - Name - - - - - - Email - - - - - Edit -
    -
    -
    -
    -
    -
    -
  • - -
  • -
    -
    -

    Boxes

    - <%= link_to 'New box', new_admin_tenant_box_path(@tenant.id), class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %> -
    -
    -
    -
    -
    - - - - - - - - - - <%= render(Admin::BoxTableRowComponent.with_collection(@tenant.boxes)) %> - -
    - - Name - - - - - - URI - - - - - Edit -
    -
    -
    -
    -
    -
    -
  • - -
  • -
    -
    -

    Tags

    - <%= link_to 'New tag', new_admin_tenant_tag_path(@tenant.id), class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %> -
    -
    -
    -
    -
    - - - - - - - - - - <%= render(Admin::TagTableRowComponent.with_collection(@tenant.tags)) %> - -
    - - Name - - - - - - Visible - - - - - Edit -
    -
    -
    -
    -
    -
    -
  • -
-
-
-
diff --git a/app/views/boxes/search.turbo_stream.erb b/app/views/boxes/search.turbo_stream.erb new file mode 100644 index 000000000..f90921062 --- /dev/null +++ b/app/views/boxes/search.turbo_stream.erb @@ -0,0 +1,3 @@ +<%= turbo_stream.update 'box-list' do %> + <%= render Layout::BoxListComponent.new(@boxes) %> +<% end %> diff --git a/app/views/message_drafts_imports/upload_new.html.erb b/app/views/message_drafts_imports/upload_new.html.erb index 66a4a03d4..9ca840845 100644 --- a/app/views/message_drafts_imports/upload_new.html.erb +++ b/app/views/message_drafts_imports/upload_new.html.erb @@ -1,8 +1,17 @@

Nový import draftov

- -<%= form_tag message_drafts_imports_path, method: :post, multipart: true do %> - <%= label_tag :content, 'Import' %> - <%= file_field_tag :content, accept: "application/zip" %> -

- <%= submit_tag 'Nahrať' %> +<% if !@box %> +

Pre import draftov vyberte v hornej liste schranku, do ktorej sa ma import realizovat

+<% else %> +
+ <%= "Import prebehne do schránky " %> + <%= render Common::BoxLabelComponent.new(@box) %> + <%= @box.name %> +
+ <%= form_tag message_drafts_imports_path, method: :post, multipart: true do %> + <%= label_tag :content, 'Import' %> + <%= file_field_tag :content, accept: "application/zip" %> +
+
+ <%= submit_tag 'Nahrať' %> + <% end %> <% end %> diff --git a/config/routes.rb b/config/routes.rb index 1695867d3..e0a106de0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -43,6 +43,9 @@ resources :boxes, path: 'schranky', only: [:index, :show] do post :sync + get :select, on: :member + get :select_all, on: :collection + post :search, on: :collection end resources :message_threads do