Merge branch 'features/inventory-archiving' into ml-sci-4689

This commit is contained in:
mlorb 2020-06-08 16:30:24 +02:00 committed by GitHub
commit 75f2a49cc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 247 additions and 74 deletions

View file

@ -4,10 +4,11 @@
var REPOSITORIES_TABLE;
function initRepositoriesDataTable(tableContainer) {
if (REPOSITORIES_TABLE) REPOSITORIES_TABLE.destroy();
$('.content-body').html($('#activeRepositoriesListTable').html());
$.get($(tableContainer).data('source'), function(data) {
function initRepositoriesDataTable(tableContainer, archived = false) {
var tableTemplate = archived ? $('#archivedRepositoriesListTable').html() : $('#activeRepositoriesListTable').html();
$.get($(tableTemplate).data('source'), function(data) {
if (REPOSITORIES_TABLE) REPOSITORIES_TABLE.destroy();
$('.content-body').html(tableTemplate);
REPOSITORIES_TABLE = $(tableContainer).DataTable({
aaData: data,
dom: "R<'main-actions hidden'<'toolbar'><'filter-container'f>>t<'pagination-row hidden'<'pagination-info'li><'pagination-actions'p>>",
@ -39,7 +40,7 @@
var dataTableWrapper = $(tableContainer).closest('.dataTables_wrapper');
DataTableHelpers.initLengthApearance(dataTableWrapper);
DataTableHelpers.initSearchField(dataTableWrapper);
$('.content-body .toolbar').html($('#activeRepositoriesListButtons').html());
$('.content-body .toolbar').html($('#repositoriesListButtons').html());
dataTableWrapper.find('.main-actions, .pagination-row').removeClass('hidden');
$('.create-new-repository').initializeModal('#create-repo-modal');
}
@ -47,5 +48,29 @@
});
}
function reloadSidebar() {
var slidePanel = $('#slide-panel');
var archived;
if ($('.repositories-index').hasClass('archived')) archived = true;
$.get(slidePanel.data('sidebar-url'), { archived: archived }, function(data) {
slidePanel.html(data.html);
});
}
function initRepositoryViewSwitcher() {
var viewSwitch = $('.view-switch');
viewSwitch.on('click', '.view-switch-archived', function() {
$('.repositories-index').toggleClass('archived active');
initRepositoriesDataTable('#repositoriesList', true);
reloadSidebar();
});
viewSwitch.on('click', '.view-switch-active', function() {
$('.repositories-index').toggleClass('archived active');
initRepositoriesDataTable('#repositoriesList');
reloadSidebar();
});
}
initRepositoriesDataTable('#repositoriesList');
initRepositoryViewSwitcher();
}());

View file

@ -0,0 +1,13 @@
.repositories-index {
&.active {
[data-view-mode="archived"] {
display: none
}
}
&.archived {
[data-view-mode="active"] {
display: none
}
}
}

View file

@ -17,6 +17,37 @@
h1 {
margin: 0;
}
.view-switch {
margin-left: auto;
.caret {
margin: 8px 0 8px 8px;
}
&.open {
.caret {
transform: rotateX(180deg)
}
}
.dropdown-menu {
@include font-button;
min-width: 250px;
li {
cursor: pointer;
padding: 1em;
.button-icon {
margin-right: .5em;
}
&:hover {
background: $color-concrete;
}
}
}
}
}
.content-body {

View file

@ -9,10 +9,10 @@ class RepositoriesController < ApplicationController
include RepositoriesDatatableHelper
before_action :switch_team_with_param, only: :show
before_action :load_repository, except: %i(index create create_modal)
before_action :load_repositories, only: %i(index show)
before_action :check_view_all_permissions, only: :index
before_action :check_view_permissions, except: %i(index create_modal create update destroy parse_sheet import_records)
before_action :load_repository, except: %i(index create create_modal sidebar)
before_action :load_repositories, only: %i(index show sidebar)
before_action :check_view_all_permissions, only: %i(index sidebar)
before_action :check_view_permissions, except: %i(index create_modal create update destroy parse_sheet import_records sidebar)
before_action :check_manage_permissions, only: %i(destroy destroy_modal rename_modal update)
before_action :check_share_permissions, only: :share_modal
before_action :check_create_permissions, only: %i(create_modal create)
@ -30,6 +30,15 @@ class RepositoriesController < ApplicationController
end
end
def sidebar
render json: {
html: render_to_string(partial: 'repositories/sidebar_list.html.erb', locals: {
repositories: @repositories,
archived: params[:archived]
})
}
end
def show
@display_edit_button = can_create_repository_rows?(@repository)
@display_delete_button = can_delete_repository_rows?(@repository)
@ -342,6 +351,11 @@ class RepositoriesController < ApplicationController
def load_repositories
@repositories = Repository.accessible_by_teams(current_team).order('repositories.created_at ASC')
@repositories = if params[:archived]
@repositories.archived
else
@repositories.active
end
end
def set_inline_name_editing

View file

@ -5,7 +5,7 @@ module RepositoriesDatatableHelper
def prepare_repositories_datatable(repositories, team, _config)
result = []
repositories = repositories.includes(:repository_rows, :team, :created_by)
repositories = repositories.includes(:repository_rows, :team, :created_by, :archived_by)
repositories.each do |repository|
result.push(
'DT_RepositoryId': repository.id,
@ -15,6 +15,8 @@ module RepositoriesDatatableHelper
'4': escape_input(repository.team.name),
'5': I18n.l(repository.created_at, format: :full),
'6': escape_input(repository.created_by.full_name),
'7': (I18n.l(repository.archived_on, format: :full) if repository.archived_on),
'8': escape_input(repository.archived_by&.full_name),
'repositoryUrl': repository_path(repository)
)
end

View file

@ -9,7 +9,7 @@ class RepositoryBase < ApplicationRecord
belongs_to :team
belongs_to :created_by, foreign_key: :created_by_id, class_name: 'User'
belongs_to :archived_by, foreign_key: :archived_by_id, class_name: 'User', inverse_of: :repository, optional: true
belongs_to :archived_by, foreign_key: :archived_by_id, class_name: 'User', inverse_of: :archived_repositories, optional: true
has_many :repository_columns, foreign_key: :repository_id, inverse_of: :repository, dependent: :destroy
has_many :repository_rows, foreign_key: :repository_id, inverse_of: :repository, dependent: :destroy
has_many :repository_table_states, foreign_key: :repository_id, inverse_of: :repository, dependent: :destroy

View file

@ -1,32 +1,6 @@
<%= content_for :sidebar do %>
<div id="slide-panel" class="visible">
<div id="repo-tree" class="tree">
<ul class="sidebar-root">
<% if can_create_repositories?(current_team) %>
<li class="branch">
<span class="tree-link no-indent">
<a class="btn btn-secondary create-new-repository" data-remote="true"
href="<%= create_modal_team_repositories_path(current_team) %>">
<i class="fas fa-plus"></i>
<%= t('libraries.index.no_libraries.create_new_button') %>
</a>
</span>
</li>
<% end %>
<% repositories.each do |repository| %>
<li class="branch <%= 'active parent_li' if current_page?(repository_path(repository)) %>" >
<span class="tree-link no-indent" title="<%= repository.name %>">
<%= link_to repository_path(repository),
class: current_page?(repository_path(repository)) ? 'disabled line-wrap' : 'line-wrap',
data: { 'no-turbolink' => 'true', type: 'repository', id: repository.id } do %>
<%= repository.name %>
<%= inventory_shared_status_icon(repository, current_team) %>
<% end %>
</span>
</li>
<% end %>
</ul>
</div>
<div id="slide-panel" class="visible" data-sidebar-url="<%= sidebar_repositories_path %>">
<%= render partial: "sidebar_list", locals: { repositories: repositories, archived: false} %>
</div>
<% end %>

View file

@ -0,0 +1,27 @@
<div id="repo-tree" class="tree">
<ul class="sidebar-root">
<% if can_create_repositories?(current_team) && !archived %>
<li class="branch">
<span class="tree-link no-indent">
<a class="btn btn-secondary create-new-repository" data-remote="true"
href="<%= create_modal_team_repositories_path(current_team) %>">
<i class="fas fa-plus"></i>
<%= t('libraries.index.no_libraries.create_new_button') %>
</a>
</span>
</li>
<% end %>
<% repositories.each do |repository| %>
<li class="branch <%= 'active parent_li' if current_page?(repository_path(repository)) %>" >
<span class="tree-link no-indent" title="<%= repository.name %>">
<%= link_to repository_path(repository),
class: current_page?(repository_path(repository)) ? 'disabled line-wrap' : 'line-wrap',
data: { 'no-turbolink' => 'true', type: 'repository', id: repository.id } do %>
<%= repository.name %>
<%= inventory_shared_status_icon(repository, current_team) %>
<% end %>
</span>
</li>
<% end %>
</ul>
</div>

View file

@ -3,46 +3,109 @@
<% if current_team %>
<%= render partial: "sidebar", locals: { repositories: @repositories } %>
<div class="content-pane flexible">
<div class="content-pane flexible active repositories-index">
<div class="content-header">
<h1><%= t('libraries.index.head_title') %></h1>
<h1 data-view-mode="active"><%= t('libraries.index.head_title') %></h1>
<h1 data-view-mode="archived"><%= t('libraries.index.head_title_archived') %></h1>
<%= render layout: "shared/view_switch" do %>
<li class="view-switch-archived" data-view-mode="active">
<i class="fas fa-archive button-icon"></i>
<%= t('libraries.index.switch_view.archived') %>
</li>
<li class="view-switch-active" data-view-mode="archived">
<i class="fas fa-rocket button-icon"></i>
<%= t('libraries.index.switch_view.active') %>
</li>
<% end %>
</div>
<div class="content-body">
</div>
<template id="activeRepositoriesListTable">
<table id="repositoriesList" class="table"
data-source="<%= team_repositories_path(current_team, format: :json) %>"
>
<thead>
<tr>
<th>
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox">
<span class="sci-checkbox-label"></span>
</div>
</th>
<th><%= t('libraries.index.table.name') %></th>
<th><%= t('libraries.index.table.number_of_items') %></th>
<th><%= t('libraries.index.table.shared') %></th>
<th><%= t('libraries.index.table.shared') %></th>
<th>Added on</th>
<th>Added by</th>
</tr>
</thead>
</table>
</template>
<template id="activeRepositoriesListButtons">
<% if can_create_repositories?(current_team) %>
<a class="btn btn-primary btn-lg create-new-repository"
data-remote="true"
href="<%= create_modal_team_repositories_path(current_team) %>">
<span class="fas fa-plus"></span>
<span class="hidden-xs"><%= t('libraries.index.no_libraries.create_new_button') %></span>
</a>
<% end %>
</template>
</div>
<% end %>
<!-- Active table template -->
<template id="activeRepositoriesListTable">
<table id="repositoriesList" class="table"
data-source="<%= team_repositories_path(current_team, format: :json) %>"
>
<thead>
<tr>
<th>
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox">
<span class="sci-checkbox-label"></span>
</div>
</th>
<th><%= t('libraries.index.table.name') %></th>
<th><%= t('libraries.index.table.number_of_items') %></th>
<th><%= t('libraries.index.table.shared') %></th>
<th><%= t('libraries.index.table.ownership') %></th>
<th><%= t('libraries.index.table.added_on') %></th>
<th><%= t('libraries.index.table.added_by') %></th>
</tr>
</thead>
</table>
</template>
<!-- Archived table template -->
<template id="archivedRepositoriesListTable">
<table id="repositoriesList" class="table"
data-source="<%= team_repositories_path(current_team, archived: true, format: :json) %>"
>
<thead>
<tr>
<th>
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox">
<span class="sci-checkbox-label"></span>
</div>
</th>
<th><%= t('libraries.index.table.name') %></th>
<th><%= t('libraries.index.table.number_of_items') %></th>
<th><%= t('libraries.index.table.shared') %></th>
<th><%= t('libraries.index.table.ownership') %></th>
<th><%= t('libraries.index.table.added_on') %></th>
<th><%= t('libraries.index.table.added_by') %></th>
<th><%= t('libraries.index.table.archived_on') %></th>
<th><%= t('libraries.index.table.archived_by') %></th>
</tr>
</thead>
</table>
</template>
<!-- Repositories action buttons -->
<template id="repositoriesListButtons">
<% if can_create_repositories?(current_team) %>
<a class="btn btn-primary btn-lg create-new-repository"
data-remote="true"
data-view-mode="active"
href="<%= create_modal_team_repositories_path(current_team) %>">
<span class="fas fa-plus"></span>
<span class="hidden-xs"><%= t('libraries.index.no_libraries.create_new_button') %></span>
</a>
<% end %>
<a class="btn btn-light" data-view-mode="active" href="#">
<span class="fas fa-pencil-alt"></span>
<%= t('libraries.index.buttons.edit') %>
</a>
<a class="btn btn-light" data-view-mode="active" href="#">
<span class="fas fa-copy"></span>
<%= t('libraries.index.buttons.duplicate') %>
</a>
<a class="btn btn-light" data-view-mode="active" href="#">
<span class="fas fa-archive"></span>
<%= t('libraries.index.buttons.archive') %>
</a>
<a class="btn btn-light" data-view-mode="archived" href="#">
<span class="fas fa-undo"></span>
<%= t('libraries.index.buttons.restore') %>
</a>
<a class="btn btn-light" data-view-mode="archived" href="#">
<span class="fas fa-trash"></span>
<%= t('libraries.index.buttons.delete') %>
</a>
</template>
<%= javascript_include_tag "repositories/index" %>
<%= stylesheet_link_tag 'datatables' %>

View file

@ -0,0 +1,9 @@
<div class="dropdown view-switch">
<a href="#" class="btn btn-light view-switch-button" id="viewSwitchButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span><%= t('general.view') %></span>
<span class="caret pull-right"></span>
</a>
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="viewSwitchButton">
<%= yield %>
</ul>
</div>

View file

@ -1312,6 +1312,7 @@ en:
error_flash: "Something went wrong! Please try again later."
index:
head_title: "Inventories"
head_title_archived: "Archived Inventories"
table:
name: "Name"
number_of_items: "No. of items"
@ -1319,6 +1320,17 @@ en:
ownership: "Ownership"
added_on: "Added on"
added_by: "Added by"
archived_on: "Archived on"
archived_by: "Archived by"
switch_view:
active: Show active inventories
archived: Show archived inventories
buttons:
edit: "Edit"
duplicate: "Duplicate"
archive: "Archive"
restore: "Restore"
delete: "Delete"
no_libraries:
create_new_button: "New Inventory"
show:
@ -2234,6 +2246,7 @@ en:
other: "tasks"
public: "public"
private: "private"
view: "View"
search: "Search"
file:
choose: "Choose File"

View file

@ -643,6 +643,7 @@ Rails.application.routes.draw do
end
collection do
get :sidebar
post 'available_rows', to: 'repository_rows#available_rows', defaults: { format: 'json' }
end

View file

@ -7235,3 +7235,4 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200604210943');

View file

@ -19,7 +19,7 @@ describe RepositoriesController, type: :controller do
action
parsed_response = JSON.parse(response.body)
expect(parsed_response[0].keys).to contain_exactly(
'DT_RepositoryId', '1', '2', '3', '4', '5', '6', 'repositoryUrl'
'DT_RepositoryId', '1', '2', '3', '4', '5', '6', '7', '8', 'repositoryUrl'
)
end
end