diff --git a/app/javascript/application.js b/app/javascript/application.js index d834182a..647378b0 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -56,6 +56,7 @@ import OpenModal from './elements/open_modal' import BarChart from './elements/bar_chart' import FieldCondition from './elements/field_condition' import ConfirmUpload from './elements/confirm_upload' +import ScrollFade from './elements/scroll_fade' import * as TurboInstantClick from './lib/turbo_instant_click' @@ -150,6 +151,7 @@ safeRegisterElement('open-modal', OpenModal) safeRegisterElement('bar-chart', BarChart) safeRegisterElement('field-condition', FieldCondition) safeRegisterElement('confirm-upload', ConfirmUpload) +safeRegisterElement('scroll-fade', ScrollFade) safeRegisterElement('template-builder', class extends HTMLElement { connectedCallback () { diff --git a/app/javascript/elements/scroll_fade.js b/app/javascript/elements/scroll_fade.js new file mode 100644 index 00000000..20c4906a --- /dev/null +++ b/app/javascript/elements/scroll_fade.js @@ -0,0 +1,40 @@ +export default class extends HTMLElement { + connectedCallback () { + this.addEventListener('scroll', this.updateFade, { passive: true }) + window.addEventListener('resize', this.updateFade) + + this.updateFade() + } + + disconnectedCallback () { + window.removeEventListener('resize', this.updateFade) + } + + updateFade = () => { + const maxScroll = this.scrollWidth - this.clientWidth + const fadeGradient = { + right: 'linear-gradient(to right, black calc(100% - 24px), transparent)', + left: 'linear-gradient(to right, transparent, black 24px)', + both: 'linear-gradient(to right, transparent, black 24px, black calc(100% - 24px), transparent)' + } + + let state = 'none' + + if (maxScroll > 4) { + if (this.scrollLeft <= 4) { + state = 'right' + } else if (this.scrollLeft >= maxScroll - 4) { + state = 'left' + } else { + state = 'both' + } + } + + this.applyFade(fadeGradient[state] || '') + } + + applyFade (gradient) { + this.style.maskImage = gradient + this.style.webkitMaskImage = gradient + } +} diff --git a/app/views/shared/_classes.html.erb b/app/views/shared/_classes.html.erb index 7069b153..f4858dca 100644 --- a/app/views/shared/_classes.html.erb +++ b/app/views/shared/_classes.html.erb @@ -1 +1 @@ -<% 'stats stat stat-figure stat-title stat-value text-accent w-fit hover:bg-white dropdown-open border-base-content/30 before:border-base-content/30' %> +<% 'stats stat stat-figure stat-title stat-value text-accent w-fit hover:bg-white dropdown-open border-base-content/30 before:border-base-content/30 order-none order-1 order-2 order-3 order-4 order-5' %> diff --git a/app/views/submissions_archived/index.html.erb b/app/views/submissions_archived/index.html.erb index 73bb402b..67380d50 100644 --- a/app/views/submissions_archived/index.html.erb +++ b/app/views/submissions_archived/index.html.erb @@ -16,7 +16,7 @@ <% end %> -
+
<%= render 'submissions_filters/applied_filters', filter_params: %> <%= render 'submissions_filters/filter_button', filter_params: %>
diff --git a/app/views/submissions_dashboard/index.html.erb b/app/views/submissions_dashboard/index.html.erb index 43d5cfd4..dc7580c2 100644 --- a/app/views/submissions_dashboard/index.html.erb +++ b/app/views/submissions_dashboard/index.html.erb @@ -34,7 +34,7 @@ <% end %> <% if is_show_tabs %>
-
+ -
- <%= render 'submissions_filters/applied_filters', filter_params: %> +
+ <%= render 'submissions_filters/applied_filters', filter_params:, with_status: true %> <%= render 'submissions_filters/filter_button', filter_params: %> <%= render 'submissions_filters/actions', filter_params: %>
diff --git a/app/views/submissions_filters/_applied_filters.html.erb b/app/views/submissions_filters/_applied_filters.html.erb index 773b111e..07cc0049 100644 --- a/app/views/submissions_filters/_applied_filters.html.erb +++ b/app/views/submissions_filters/_applied_filters.html.erb @@ -1,72 +1,85 @@ <% query_params = params.permit(:q).merge(filter_params) %> -<% if icon = { 'declined' => 'x_circle', 'expired' => 'clock_cancel', 'partially_completed' => 'clock_edit', 'sent' => 'send', 'opened' => 'mail_opened' }[params[:status]] %> -
- <%= link_to submissions_filter_path('status', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> - <%= svg_icon(icon, class: 'w-5 h-5 shrink-0') %> - <%= t(params[:status]) %> - <% end %> - <%= link_to url_for(params: request.query_parameters.except('status')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> -<% if params[:folder].present? %> -
- <%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> - <%= svg_icon('folder', class: 'w-5 h-5 shrink-0') %> - <%= params[:folder] %> - <% end %> - <%= link_to url_for(params: request.query_parameters.except('folder')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> -<% if params[:author].present? %> -
- <%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> - <%= svg_icon('user', class: 'w-5 h-5 shrink-0') %> - <%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %> - <% end %> - <%= link_to url_for(params: request.query_parameters.except('author')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> -<% if query_params[:completed_at_from].present? || query_params[:completed_at_to].present? %> -
- <%= link_to submissions_filter_path('completed_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> - <%= svg_icon('calendar_check', class: 'w-5 h-5 shrink-0') %> - - <% if query_params[:completed_at_from] == query_params[:completed_at_to] %> - <%= l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) %> - <% else %> - <%= query_params[:completed_at_from].present? ? l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) : '∞' %> - - - <%= query_params[:completed_at_to].present? ? l(Date.parse(query_params[:completed_at_to]), locale: current_account.locale) : t('today') %> - <% end %> - - <% end %> - <%= link_to url_for(params: request.query_parameters.except('completed_at_from', 'completed_at_to')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> -<% if query_params[:created_at_from].present? || query_params[:created_at_to].present? %> -
- <%= link_to submissions_filter_path('created_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> - <%= svg_icon('calendar', class: 'w-5 h-5 shrink-0') %> - - <% if query_params[:created_at_from] == query_params[:created_at_to] %> - <%= l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) %> - <% else %> - <%= query_params[:created_at_from].present? ? l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) : '∞' %> - - - <%= query_params[:created_at_to].present? ? l(Date.parse(query_params[:created_at_to]), locale: current_account.locale) : t('today') %> - <% end %> - - <% end %> - <%= link_to url_for(params: request.query_parameters.except('created_at_to', 'created_at_from')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> +<% filter_names = %w[status folder author completed_at created_at] %> +<% ordered_filters = request.query_parameters.keys.filter_map { |key| filter_names.find { |name| key.start_with?(name) } }.uniq %> +<% chip_order = ordered_filters.reverse.each_with_index.to_h { |name, index| [name, index + 1] } %> +<% chip_order.default = ordered_filters.size + 1 %> + + <% if local_assigns[:with_status] %> + <% status_icons = { 'all' => 'list', 'pending' => 'clock', 'completed' => 'circle_check', 'partially_completed' => 'clock_edit', 'sent' => 'send', 'opened' => 'mail_opened', 'declined' => 'x_circle', 'expired' => 'clock_cancel' } %> + <% current_status = status_icons.key?(params[:status].to_s) ? params[:status] : 'all' %> + + <%= svg_icon(status_icons[current_status], class: 'w-5 h-5 shrink-0') %> + <%= t(current_status) %> + <%= svg_icon('chevron_down', class: 'w-4 h-4 shrink-0') %> + + <% end %> + <% if icon = { 'declined' => 'x_circle', 'expired' => 'clock_cancel', 'partially_completed' => 'clock_edit', 'sent' => 'send', 'opened' => 'mail_opened' }[params[:status]] %> +
+ <%= link_to submissions_filter_path('status', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> + <%= svg_icon(icon, class: 'w-5 h-5 shrink-0') %> + <%= t(params[:status]) %> + <% end %> + <%= link_to url_for(params: request.query_parameters.except('status')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> + <% if params[:folder].present? %> +
+ <%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> + <%= svg_icon('folder', class: 'w-5 h-5 shrink-0') %> + <%= params[:folder] %> + <% end %> + <%= link_to url_for(params: request.query_parameters.except('folder')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> + <% if params[:author].present? %> +
+ <%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> + <%= svg_icon('user', class: 'w-5 h-5 shrink-0') %> + <%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %> + <% end %> + <%= link_to url_for(params: request.query_parameters.except('author')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> + <% if query_params[:completed_at_from].present? || query_params[:completed_at_to].present? %> +
+ <%= link_to submissions_filter_path('completed_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> + <%= svg_icon('calendar_check', class: 'w-5 h-5 shrink-0') %> + + <% if query_params[:completed_at_from] == query_params[:completed_at_to] %> + <%= l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) %> + <% else %> + <%= query_params[:completed_at_from].present? ? l(Date.parse(query_params[:completed_at_from]), locale: current_account.locale) : '∞' %> + <%= query_params[:completed_at_to].present? ? l(Date.parse(query_params[:completed_at_to]), locale: current_account.locale) : t('today') %> + <% end %> + + <% end %> + <%= link_to url_for(params: request.query_parameters.except('completed_at_from', 'completed_at_to')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> + <% if query_params[:created_at_from].present? || query_params[:created_at_to].present? %> +
+ <%= link_to submissions_filter_path('created_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> + <%= svg_icon('calendar', class: 'w-5 h-5 shrink-0') %> + + <% if query_params[:created_at_from] == query_params[:created_at_to] %> + <%= l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) %> + <% else %> + <%= query_params[:created_at_from].present? ? l(Date.parse(query_params[:created_at_from]), locale: current_account.locale) : '∞' %> + <%= query_params[:created_at_to].present? ? l(Date.parse(query_params[:created_at_to]), locale: current_account.locale) : t('today') %> + <% end %> + + <% end %> + <%= link_to url_for(params: request.query_parameters.except('created_at_to', 'created_at_from')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> +
diff --git a/app/views/submissions_filters/_filter_button.html.erb b/app/views/submissions_filters/_filter_button.html.erb index 2e65f0ed..ec20c1ee 100644 --- a/app/views/submissions_filters/_filter_button.html.erb +++ b/app/views/submissions_filters/_filter_button.html.erb @@ -1,8 +1,9 @@ <% query_params = params.permit(:q).merge(filter_params) %> -