diff --git a/app/assets/stylesheets/collection-items.scss b/app/assets/stylesheets/collection-items.scss new file mode 100644 index 00000000..21e70e5a --- /dev/null +++ b/app/assets/stylesheets/collection-items.scss @@ -0,0 +1,8 @@ +$selected-background: navy; +$selected-text: white; + +.ci-selected { color: $selected-text; background-color: $selected-background; } +.ci-selected a { color: $selected-text; } +.ci-selected .draggable-content { background-color: $selected-background; } +.ci-selected .by-card-v02 { background-color: $selected-background; } +.ci-selected .handle { background-color: $selected-background; border-color: $selected-text; } diff --git a/app/controllers/collection_items_controller.rb b/app/controllers/collection_items_controller.rb index 64ce3072..a7cfe4e0 100644 --- a/app/controllers/collection_items_controller.rb +++ b/app/controllers/collection_items_controller.rb @@ -77,15 +77,8 @@ def update # DELETE /collection_items/1 or /collection_items/1.json def destroy - @collection = @collection_item.collection - @deleted_id = @collection_item.id # used in the js response @collection_item.destroy - @nonce = params[:nonce] - - respond_to do |format| - format.html { redirect_to collection_manage_path(@collection.id), notice: t(:deleted_successfully) } - format.js - end + head :ok end private diff --git a/app/views/collection_items/destroy.js.erb b/app/views/collection_items/destroy.js.erb deleted file mode 100644 index b1b85f41..00000000 --- a/app/views/collection_items/destroy.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -ele = $('div[id*="<%= 'collitem_'+@deleted_id.to_s %>"]'); -ele.find('.by-card-v02').css('background-color', 'orangered'); -ele.fadeOut(1500); diff --git a/app/views/shared/_editable_collection.html.haml b/app/views/shared/_editable_collection.html.haml index 96467bc7..7432c71e 100644 --- a/app/views/shared/_editable_collection.html.haml +++ b/app/views/shared/_editable_collection.html.haml @@ -15,7 +15,7 @@ .container-fluid{ style: 'position:relative;', id: "#{nonce}_coll_container_#{collection.id}" } .collection.connectable.collapse.show{ id: "#{nonce}_coll_#{collection.id}", style: 'min-height:40px;background-color: #e0e0e0;', 'data-nonce': nonce } - collection.collection_items.each do |ci| - .collection_draggable_item{ id: "#{nonce}_collitem_#{ci.id}" } + .collection_draggable_item{ id: "#{nonce}_collitem_#{ci.id}", data: { collection_item_id: ci.id } } .by-card-v02 .drag-handle{ title: t(:coll_drag_tt) } .handle @@ -26,7 +26,6 @@ %br .editable{ id: "#{nonce}_editable_#{ci.id}" } != MultiMarkdown.new(ci.markdown).to_html - = link_to t(:delete), collection_item_path(ci.id), method: :delete, remote: true, data: { confirm: t(:confirm_delete_collection_item) }, class: 'collection-btn', style: 'float: left;top:-40px;left:5px;position:relative;z-index:5;' .editable_edit{ style: 'display:none;' } = form_for ci, url: collection_item_path(ci.id), method: :put, remote: true do |f| = f.label :alt_title, t(:title_only_if_needed) @@ -39,7 +38,6 @@ .editable{ id: "#{nonce}_editable_#{ci.id}", style: 'margin-bottom: 10px;' } %b #{t(:placeholder_item)}: %span{ id: "#{nonce}_ci_title_#{ci.id}" }= ci.alt_title - = link_to t(:delete), collection_item_path(ci.id), method: :delete, remote: true, data: { confirm: t(:confirm_delete_collection_item) }, class: 'collection-btn', style: 'float: left;' .editable_edit{ style: 'display:none;' } = form_for ci, url: collection_item_path(ci.id), method: :put, remote: true do |f| = f.label :alt_title, t(:title) @@ -68,7 +66,6 @@ - @colls_traversed << ci.item.id = render partial: 'shared/editable_collection', locals: { collection: ci.item, focused: false, nonce: nonce } - else - = link_to t(:delete), collection_item_path(ci.id), method: :delete, remote: true, data: { confirm: t(:confirm_delete_collection_item) }, class: 'collection-btn', style: 'float: left;' .headline-3-v02 #{t(:text)}: = link_to collection_item_string(ci), default_link_by_class(ci.item.class, ci.item.id) @@ -123,4 +120,41 @@ event.stopPropagation(); } }); + + $("##{nonce}_coll_#{collection.id} button").click(function(e) { + // We need this to prevent click handler below (used for item selection) from being called when we click + // on buttons inside an item + e.stopPropagation(); + }); + + $("##{nonce}_coll_#{collection.id} > .collection_draggable_item > .by-card-v02 > .draggable-content"). + click(function(e) { + const itemNode = $(this).parent().parent(); + const selected = $(itemNode).hasClass('ci-selected'); // current state of item (before click) + + if (e.ctrlKey) { + // If Ctrl is pressed we're adding/removing additional items to selection + // deselecting all nested collection items (if any) as parent item (this one) has changed status + $(this).find('.collection_draggable_item').removeClass('ci-selected'); + + const selectedParents = $(this).parents('.ci-selected'); + if (selectedParents.length > 0) { + // if we clicked on sub-item of already selected item we should deselect parent item + selectedParents.removeClass('ci-selected'); + } + $(itemNode).toggleClass('ci-selected', !selected); + } else { + // If Ctrl is not pressed we're selecting single element, so we need to deselect all previously selected items + $('.collection_draggable_item').removeClass('ci-selected'); + $(itemNode).toggleClass('ci-selected', !selected); + } + + // Is some items are selected we should display batch editing actions panel + const selectedCount = $('.ci-selected').length; + $('#selected-collection-items-actions').toggle(selectedCount > 0); + $('#selected-collection-items-actions > .actions-label').text( + '#{t('shared.manage_collection.x_items_selected')}'.replace('X', selectedCount) + ); + e.stopPropagation(); // to prevent click handler on parent item (if any) + }); }); diff --git a/app/views/shared/_manage_collection.html.haml b/app/views/shared/_manage_collection.html.haml index 2b4ce3c8..d0179e4d 100644 --- a/app/views/shared/_manage_collection.html.haml +++ b/app/views/shared/_manage_collection.html.haml @@ -37,6 +37,11 @@ %b.white= '+' %div{style: 'margin-right: 10px;'} + .hint= t('.selection_hint') + #selected-collection-items-actions{ style: 'display: none;' } + %span.actions-label= t('.x_items_selected') + %button.btn.btn-sm.btn-danger#remove-selected= t('.remove_selected') + - @colls_traversed = [collection.id] = render partial: 'shared/editable_collection', locals: {collection: collection, focused: true, nonce: nonce} @@ -116,7 +121,7 @@ } }); }); - $('.collection_insert_all_siblings').click(function(){ + $('.collection_insert_all_siblings').click(function(e){ var collection_id = $('#collection_id').val(); $.ajax({ @@ -138,4 +143,23 @@ $('.collection_do_insert').css('background-color', '#660248'); } }); + $('#remove-selected').click(function(e) { + e.preventDefault(); + if (!confirm("#{t('.confirm_remove_selected')}")) { + return; + } + const ids = $('.ci-selected').map(function() { return $(this).data('collectionItemId'); }).get(); + $.each(ids, function(_index, id) { + $.ajax({ + url: '/collection_items/' + id, + type: 'DELETE', + success: function() { + const ele = $('div[id*="collitem_' + id + '"]'); + ele.removeClass('ci-selected'); + ele.find('.by-card-v02').css('background-color', 'orangered'); + ele.fadeOut(1500); + } + }); + }); + }); }); \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 623a463d..71db135a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -13,12 +13,14 @@ en: save: Save update: Update destroy: Destroy + delete: Delete created_successfully: Created Successfully updated_successfully: Updated Successfully deleted_successfully: Deleted Successfully original_works: Original Works translations: Translations edited_works: Edited Works + text: Text alefbet: Alphabetical alefbet_asc: 'Alphabetical: A-Z' alefbet_desc: 'Alphabetical: Z-A' @@ -117,6 +119,11 @@ en: permission_for_all: TBD description for 'permission_for_all' permission_for_selected: TBD description for 'permission_for_selected' unknown: TBD description for 'unknown' + manage_collection: + selection_hint: Click on item to select it. Hold Ctrl to select multiple items. + x_items_selected: "X items selected" + remove_selected: Remove them + confirm_remove_selected: Are you sure you want to remove all selected items from collection? welcome: submit_contact: ziburit_failed: Control question failed diff --git a/config/locales/he.yml b/config/locales/he.yml index 28f16ed0..bb62edde 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -1483,6 +1483,11 @@ he: permission_for_all: על אף שהיצירה עדיין מוגנת בזכויות יוצרים, פרויקט בן־יהודה קיבל *רשות מפורשת לפרסם* את היצירה במאגר היצירה של פרויקט בן־יהודה, לשימוש הקהל הרחב לקריאה ומחקר. שימושים אחרים (כגון המחזה, הלחנה, או ביצוע מסחרי) עדיין *טעונים אישור מפורש* מאת בעלי הזכויות. permission_for_selected: על אף שהיצירה עדיין מוגנת בזכויות יוצרים, פרויקט בן־יהודה קיבל *רשות מפורשת לפרסם* את היצירה במאגר היצירה של פרויקט בן־יהודה, לשימוש הקהל הרחב לקריאה ומחקר. שימושים אחרים (כגון המחזה, הלחנה, או ביצוע מסחרי) עדיין *טעונים אישור מפורש* מאת בעלי הזכויות. unknown: "על אף כל המאמצים, לא ניתן לקבוע מה מצב זכויות היוצרים, בדרך כלל בשל מידע חסר לגבי זהות או מועד פטירת המחבר[ים] או המתרגם[ים]." + manage_collection: + selection_hint: Click on item to select it. Hold Ctrl to select multiple items. + x_items_selected: "X items selected" + remove_selected: Remove them + confirm_remove_selected: Are you sure you want to remove all selected items from collection? welcome: submit_contact: ziburit_failed: לא השתכנענו שאינך רובוט.