From 1a84c60c74343cf757a15257313a45a38ead4f35 Mon Sep 17 00:00:00 2001 From: Giga Chubinidze Date: Mon, 19 Dec 2022 14:55:38 +0400 Subject: [PATCH] FE | BE Add new task modal field for Tags [SCI-7449] --- app/assets/javascripts/experiments/show.js | 84 +++++++++++++++++++ app/assets/stylesheets/experiment/show.scss | 29 +++++++ app/controllers/experiments_controller.rb | 17 ++++ app/controllers/projects_controller.rb | 27 +++++- .../my_modules/modals/_new_modal.html.erb | 22 ++++- config/locales/en.yml | 2 + config/routes.rb | 3 + 7 files changed, 179 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/experiments/show.js b/app/assets/javascripts/experiments/show.js index 9de3cd6a1..e8cad83d9 100644 --- a/app/assets/javascripts/experiments/show.js +++ b/app/assets/javascripts/experiments/show.js @@ -5,6 +5,8 @@ let experimentWrapper = '.experiment-new-my_module'; let newMyModuleModal = '#new-my-module-modal'; let myModuleUserSelector = '#my_module_user_ids'; + var myModuleTagsSelector = '#my_module_tag_ids'; + // Modal's submit handler function $(experimentWrapper) @@ -22,6 +24,16 @@ $.map(dropdownSelector.getValues(myModuleUserSelector), function(val) { $(`${myModuleUserSelector} option[value=${val}]`).prop('selected', true); }); + // For submitting correct id values of the chosen tags + $.map(dropdownSelector.getValues(myModuleTagsSelector), function(val) { + if ($(`${myModuleTagsSelector} option[value=${val}]`).length === 0) { + $(myModuleTagsSelector).append( + $(``) + ); + } else { + $(`${myModuleTagsSelector} option[value=${val}]`).prop('selected', true); + } + }); }) .on('ajax:success', '.new-my-module-button', function(ev, result) { // Add and show modal @@ -55,6 +67,78 @@ }); dropdownSelector.selectValues(myModuleUserSelector, $('#new-my-module-modal').data('user-id')); + + dropdownSelector.init($(myModuleTagsSelector), { + closeOnSelect: true, + tagClass: 'my-module-white-tags', + tagStyle: (data) => { + return `background: ${data.params.color}`; + }, + customDropdownIcon: () => { + return ''; + }, + optionLabel: (data) => { + if (data.value > 0) { + return ` + ${data.label}`; + } + return ` + ${data.label + ' '} + (${I18n.t('my_modules.details.create_new_tag')})`; + }, + onOpen: function() { + $('.select-container .edit-button-container').removeClass('hidden'); + }, + onClose: function() { + $('.select-container .edit-button-container').addClass('hidden'); + }, + onSelect: function() { + var selectElement = $(myModuleTagsSelector); + var lastTag = selectElement.next().find('.ds-tags').last(); + var lastTagId = lastTag.find('.tag-label').data('ds-tag-id'); + var newTag; + + if (lastTagId > 0) { + newTag = { my_module_tag: { tag_id: lastTagId } }; + (function() { + dropdownSelector.removeValue(myModuleTagsSelector, lastTagId, '', true); + }); + } else { + newTag = { + tag: { + name: lastTag.find('.tag-label').html(), + project_id: selectElement.data('project-id'), + color: null + }, + my_module_id: selectElement.data('module-id'), + simple_creation: true + }; + $.post(selectElement.data('tags-create-url'), newTag, function(result) { + dropdownSelector.removeValue(myModuleTagsSelector, 0, '', true); + dropdownSelector.addValue(myModuleTagsSelector, { + value: result.tag.id, + label: result.tag.name, + params: { + color: result.tag.color + } + }, true); + }).fail(function() { + dropdownSelector.removeValue(myModuleTagsSelector, lastTagId, '', true); + }); + } + }, + onUnSelect: (id) => { + $.post(`${$(myModuleTagsSelector).data('update-module-tags-url')}/${id}/destroy_by_tag_id`) + .success(function() { + dropdownSelector.closeDropdown(myModuleTagsSelector); + }) + .fail(function(r) { + if (r.status === 403) { + HelperModule.flashAlertMsg(I18n.t('general.no_permissions'), 'danger'); + } + }); + } + }) }); } diff --git a/app/assets/stylesheets/experiment/show.scss b/app/assets/stylesheets/experiment/show.scss index 5da5c4285..1a4f426d9 100644 --- a/app/assets/stylesheets/experiment/show.scss +++ b/app/assets/stylesheets/experiment/show.scss @@ -36,6 +36,35 @@ max-width: 20px; } } + .dropdown-selector-container { + .my-module-white-tags { + color: $color-white; + } + + .my-module-tags-color { + border-radius: 8px; + display: inline-block; + height: 16px; + margin-right: 5px; + width: 16px; + } + + .my-module-tags-create-new { + opacity: .6; + } + + &.open { + .input-field { + border: 1px solid $color-alto; + } + } + + &:not(.view-mode):hover { + .input-field { + border: 1px solid $color-alto; + } + } + } .datetime-picker-container { width: 45%; diff --git a/app/controllers/experiments_controller.rb b/app/controllers/experiments_controller.rb index 6f68f4f8c..bbf8dc0a0 100644 --- a/app/controllers/experiments_controller.rb +++ b/app/controllers/experiments_controller.rb @@ -265,6 +265,23 @@ class ExperimentsController < ApplicationController end end + def search_tags + assigned_tags = [] + all_tags = @experiment.project.tags + tags = all_tags.where.not(id: assigned_tags) + .where_attributes_like(:name, params[:query]) + .select(:id, :name, :color) + + tags = tags.map do |tag| + { value: tag.id, label: sanitize_input(tag.name), params: { color: sanitize_input(tag.color) } } + end + + if params[:query].present? && tags.select { |tag| tag[:label] == params[:query] }.blank? + tags << { value: 0, label: sanitize_input(params[:query]), params: { color: nil } } + end + render json: tags + end + # POST: move_experiment(id) def move service = Experiments::MoveToProjectService diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 126f6f0a7..d85d9effe 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -13,7 +13,7 @@ class ProjectsController < ApplicationController before_action :switch_team_with_param, only: :index before_action :load_vars, only: %i(show permissions edit update notifications - sidebar experiments_cards view_type actions_dropdown) + sidebar experiments_cards view_type actions_dropdown create_tag) before_action :load_current_folder, only: %i(index cards new show) before_action :check_view_permissions, except: %i(index cards new create edit update archive_group restore_group users_filter actions_dropdown) @@ -264,6 +264,25 @@ class ProjectsController < ApplicationController end end + + def create_tag + render_403 unless can_manage_project_tags?(@project) + + @tag = @project.tags.create(tag_params.merge({ + created_by: current_user, + last_modified_by: current_user, + color: Constants::TAG_COLORS.sample + })) + + render json: { + tag: { + id: @tag.id, + name: @tag.name, + color: @tag.color + } + } + end + def restore_group projects = current_team.projects.archived.where(id: params[:projects_ids]) counter = 0 @@ -372,11 +391,15 @@ class ProjectsController < ApplicationController end def load_vars - @project = Project.find_by(id: params[:id]) + @project = Project.find_by(id: params[:id] || params[:project_id]) render_404 unless @project end + def tag_params + params.require(:tag).permit(:name) + end + def load_current_folder if current_team && params[:project_folder_id].present? @current_folder = current_team.project_folders.find_by(id: params[:project_folder_id]) diff --git a/app/views/my_modules/modals/_new_modal.html.erb b/app/views/my_modules/modals/_new_modal.html.erb index d17753e89..69ff7a282 100644 --- a/app/views/my_modules/modals/_new_modal.html.erb +++ b/app/views/my_modules/modals/_new_modal.html.erb @@ -1,4 +1,4 @@ - - + +
+
+ <%= f.select 'tag_ids', options_for_select([]), + { + id: 'module-tags-selector', + label: t('experiments.canvas.new_my_module_modal.assigned_tags_label') + }, + data: { + 'tags-create-url': project_create_tag_path(project_id: @experiment.project_id), + 'ajax-url': search_tags_experiment_path, + 'placeholder': t('experiments.canvas.new_my_module_modal.assigned_tags_placeholder') + }, + multiple: true %> +
+
+
<%= f.select 'user_ids', @@ -49,7 +65,7 @@ }), { id: 'new-modal-assigned-users-selector', - label: t('experiments.canvas.new_my_module_modal.assigned_users') + label: t('experiments.canvas.new_my_module_modal.assigned_users') }, { :multiple => true } %> diff --git a/config/locales/en.yml b/config/locales/en.yml index af2d77584..afc4c0f13 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1377,6 +1377,8 @@ en: name_placeholder: "e.g. My task" due_date: "Due date (optional)" due_date_placeholder: "+ Add due date" + assigned_tags_label: "Add tags (optional)" + assigned_tags_placeholder: "Select tags for your task" assigned_users: "Assign task to (optional)" tags: "Add tags (optional)" create: "Create" diff --git a/config/routes.rb b/config/routes.rb index 3822c30c9..72725344f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -296,6 +296,8 @@ Rails.application.routes.draw do # as well as all activities page for single project (HTML) resources :project_activities, path: '/activities', only: [:index] resources :tags, only: [:create, :update, :destroy] + post :create_tag + resources :reports, path: '/reports', only: %i(edit update create) do @@ -382,6 +384,7 @@ Rails.application.routes.draw do get :assigned_users_to_tasks post :archive_my_modules post :batch_clone_my_modules + get :search_tags end end