Merge pull request #2516 from okriuchykhin/ok_SCI_4525

Add versions sidebar to assigned repository rows full view modal [SCI-4525]
This commit is contained in:
Alex Kriuchykhin 2020-04-23 13:18:23 +02:00 committed by GitHub
commit 1802d7cb59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 612 additions and 111 deletions

View file

@ -1,12 +1,13 @@
/* eslint-disable no-param-reassign */
/* global DataTableHelpers PerfectScrollbar FilePreviewModal */
/* global DataTableHelpers PerfectScrollbar FilePreviewModal animateSpinner */
var MyModuleRepositories = (function() {
const FULL_VIEW_MODAL = $('#myModuleRepositoryFullViewModal');
var SIMPLE_TABLE;
var FULL_VIEW_TABLE;
var FULL_VIEW_TABLE_SCROLLBAR;
function tableColumnPreparation(tableContainer, skipCheckbox = false) {
function tableColumns(tableContainer, skipCheckbox = false) {
var columns = $(tableContainer).data('default-table-columns');
var customColumns = $(tableContainer).find('thead th[data-type]');
for (let i = 0; i < columns.length; i += 1) {
@ -25,6 +26,41 @@ var MyModuleRepositories = (function() {
return columns;
}
function fullViewColumnDefs() {
let columnDefs = [{
targets: 0,
visible: false
}];
if (FULL_VIEW_MODAL.find('.table').data('type') === 'live') {
columnDefs.push({
targets: 1,
searchable: false,
className: 'assigned-column',
sWidth: '1%'
}, {
targets: 3,
render: function(data, type, row) {
return "<a href='" + row.recordInfoUrl + "' class='record-info-link'>" + data + '</a>';
}
});
}
columnDefs.push(
{
targets: '_all',
render: function(data) {
if (typeof data === 'object' && $.fn.dataTable.render[data.value_type]) {
return $.fn.dataTable.render[data.value_type](data);
}
return data;
}
}
);
return columnDefs;
}
function renderSimpleTable(tableContainer) {
if (SIMPLE_TABLE) SIMPLE_TABLE.destroy();
SIMPLE_TABLE = $(tableContainer).DataTable({
@ -46,9 +82,9 @@ var MyModuleRepositories = (function() {
d.skip_custom_columns = true;
},
global: false,
type: 'GET'
type: 'POST'
},
columns: tableColumnPreparation(tableContainer),
columns: tableColumns(tableContainer),
columnDefs: [{
targets: 3,
render: function(data, type, row) {
@ -84,38 +120,17 @@ var MyModuleRepositories = (function() {
d.view_mode = true;
},
global: false,
type: 'GET'
type: 'POST'
},
columns: tableColumnPreparation(tableContainer, true),
columnDefs: [{
targets: 0,
visible: false
}, {
targets: 1,
searchable: false,
className: 'assigned-column',
sWidth: '1%'
}, {
targets: 3,
render: function(data, type, row) {
return "<a href='" + row.recordInfoUrl + "'"
+ "class='record-info-link'>" + data + '</a>';
}
}, {
targets: '_all',
render: function(data) {
if (typeof data === 'object' && $.fn.dataTable.render[data.value_type]) {
return $.fn.dataTable.render[data.value_type](data);
}
return data;
}
}],
columns: tableColumns(tableContainer, true),
columnDefs: fullViewColumnDefs(),
fnInitComplete: function() {
var dataTableWrapper = $(tableContainer).closest('.dataTables_wrapper');
DataTableHelpers.initLengthApearance(dataTableWrapper);
DataTableHelpers.initSearchField(dataTableWrapper);
dataTableWrapper.find('.main-actions, .pagination-row').removeClass('hidden');
$('.table-container .toolbar').html($('#repositoryToolbarButtonsTemplate').html());
},
drawCallback: function() {
@ -143,6 +158,41 @@ var MyModuleRepositories = (function() {
});
}
function setSelectedItem() {
let versionsSidebar = FULL_VIEW_MODAL.find('.repository-versions-sidebar');
let currentId = FULL_VIEW_MODAL.find('.table').data('id');
versionsSidebar.find('.list-group-item').removeClass('active');
versionsSidebar.find(`[data-id="${currentId}"]`).addClass('active');
}
function createDestroySnapshot(actionPath, requestType) {
animateSpinner(null, true);
$.ajax({
url: actionPath,
type: requestType,
dataType: 'json',
success: function(data) {
FULL_VIEW_MODAL.find('.repository-versions-sidebar').html(data.html);
setSelectedItem();
animateSpinner(null, false);
},
error: function() {
// TODO
}
});
}
function reloadTable(tableUrl) {
animateSpinner(null, true);
if (FULL_VIEW_TABLE) FULL_VIEW_TABLE.destroy();
$.get(tableUrl, (data) => {
FULL_VIEW_MODAL.find('.table-container').html(data.html);
renderFullViewTable(FULL_VIEW_MODAL.find('.table'));
setSelectedItem();
animateSpinner(null, false);
});
}
function initSimpleTable() {
$('#assigned-items-container').on('show.bs.collapse', '.assigned-repository-container', function() {
var repositoryContainer = $(this);
@ -153,18 +203,59 @@ var MyModuleRepositories = (function() {
});
}
function initVersionsSidebarActions() {
FULL_VIEW_MODAL.on('click', '#showVersionsSidebar', function(e) {
$.get(FULL_VIEW_MODAL.find('.table').data('versions-sidebar-url'), (data) => {
FULL_VIEW_MODAL.find('.repository-versions-sidebar').html(data.html);
setSelectedItem();
FULL_VIEW_MODAL.find('.table-container').addClass('collapsed');
FULL_VIEW_MODAL.find('.repository-versions-sidebar').removeClass('collapsed');
});
e.stopPropagation();
});
FULL_VIEW_MODAL.on('click', '#createRepositorySnapshotButton', function(e) {
createDestroySnapshot($(this).data('action-path'), 'POST');
e.stopPropagation();
});
FULL_VIEW_MODAL.on('click', '.delete-snapshot-button', function(e) {
let snapshotId = $(this).closest('.repository-snapshot-item').data('id');
createDestroySnapshot($(this).data('action-path'), 'DELETE');
if (snapshotId === FULL_VIEW_MODAL.find('.table').data('id')) {
reloadTable(FULL_VIEW_MODAL.find('#selectLiveVersionButton').data('table-url'));
}
e.stopPropagation();
});
FULL_VIEW_MODAL.on('click', '.select-snapshot-button', function(e) {
reloadTable($(this).data('table-url'));
e.stopPropagation();
});
FULL_VIEW_MODAL.on('click', '#selectLiveVersionButton', function(e) {
reloadTable(FULL_VIEW_MODAL.find('#selectLiveVersionButton').data('table-url'));
e.stopPropagation();
});
FULL_VIEW_MODAL.on('click', '#collapseVersionsSidebar', function(e) {
FULL_VIEW_MODAL.find('.repository-versions-sidebar').addClass('collapsed');
FULL_VIEW_MODAL.find('.table-container').removeClass('collapsed');
e.stopPropagation();
});
}
function initRepositoryFullView() {
$('#assigned-items-container').on('click', '.action-buttons .full-screen', function(e) {
var fullViewModal = $('#my-module-repository-full-view-modal');
var repositoryNameObject = $(this).closest('.assigned-repository-caret')
.find('.assigned-repository-title')
.clone();
fullViewModal.find('.repository-name').html(repositoryNameObject);
fullViewModal.modal('show');
FULL_VIEW_MODAL.find('.repository-name').html(repositoryNameObject);
FULL_VIEW_MODAL.modal('show');
$.get($(this).data('table-url'), (data) => {
fullViewModal.find('.modal-body').html(data.html);
renderFullViewTable(fullViewModal.find('.table'));
FULL_VIEW_MODAL.find('.table-container').html(data.html);
renderFullViewTable(FULL_VIEW_MODAL.find('.table'));
});
e.stopPropagation();
});
@ -184,6 +275,7 @@ var MyModuleRepositories = (function() {
initSimpleTable();
initRepositoryFullView();
initRepositoriesDropdown();
initVersionsSidebarActions();
}
};
}());

View file

@ -170,7 +170,7 @@
}
}
#my-module-repository-full-view-modal {
#myModuleRepositoryFullViewModal {
.modal-dialog {
height: 100vh;
margin: 0;
@ -231,30 +231,30 @@
padding: 0;
}
.dataTables_wrapper {
height: 100%;
position: absolute;
width: 100%;
.dataTables_scroll {
height: calc(100% - 146px);
padding: 0 24px;
.dataTables_scrollBody {
height: calc(100% - 44px);
}
}
.main-actions {
padding: 16px 24px 10px;
}
.pagination-row {
border-top: $border-default;
height: 84px;
padding: 0 24px;
}
}
// .dataTables_wrapper {
// height: 100%;
// position: absolute;
// width: 100%;
//
// .dataTables_scroll {
// height: calc(100% - 146px);
// padding: 0 24px;
//
// .dataTables_scrollBody {
// height: calc(100% - 44px);
// }
// }
//
// .main-actions {
// padding: 16px 24px 10px;
// }
//
// .pagination-row {
// border-top: $border-default;
// height: 84px;
// padding: 0 24px;
// }
// }
}
}
@ -283,4 +283,82 @@
}
}
}
.table-container {
padding: 2em;
width: 100%;
&.collapsed {
margin-right: 20%;
width: 80%;
}
}
.repository-versions-sidebar {
background-color: $color-concrete;
bottom: 0;
height: 100%;
overflow-x: hidden;
padding: 0;
position: fixed;
right: 0;
transition: .5s;
width: 20%;
&.collapsed {
margin-right: -20%;
}
.sidebar-collapse-button {
color: $color-volcano;
text-decoration: none;
}
.repository-versions-header {
border-bottom: 1px solid $color-alto;
padding: 0 1em;
}
.list-group-item {
background-color: $color-concrete;
border: 0;
.list-group-item-text {
color: $color-silver-chalice;
}
.version-button {
color: $color-volcano;
text-decoration: none;
}
.delete-snapshot-button {
display: none;
}
&:hover {
background-color: $color-alto;
.delete-snapshot-button {
display: block;
}
}
&.active {
background-color: $brand-primary;
.list-group-item-heading,
.list-group-item-text,
.delete-snapshot-button {
color: $color-white;
}
}
}
.create-snapshot-item {
border-bottom: 1px solid $color-alto;
padding: 15px 10px;
}
}
}

View file

@ -1,14 +1,14 @@
# frozen_string_literal: true
class MyModuleRepositoriesController < ApplicationController
before_action :load_my_module, only: %i(show full_view_table dropdown_list)
before_action :load_repository, only: %i(show full_view_table)
before_action :check_my_module_view_permissions, only: %i(show full_view_table dropdown_list)
before_action :check_repository_view_permissions, only: %i(show full_view_table)
before_action :load_my_module
before_action :load_repository, except: %i(repositories_dropdown_list)
before_action :check_my_module_view_permissions
before_action :check_repository_view_permissions, except: %i(repositories_dropdown_list)
def show
def index_dt
@draw = params[:draw].to_i
per_page = params[:length] == '-1' ? 10 : params[:length].to_i
per_page = params[:length] == '-1' ? Constants::REPOSITORY_DEFAULT_PAGE_SIZE : params[:length].to_i
page = (params[:start].to_i / per_page) + 1
datatable_service = RepositoryDatatableService.new(@repository, params, current_user, @my_module)
@ -29,10 +29,12 @@ class MyModuleRepositoriesController < ApplicationController
end
def full_view_table
render json: { html: render_to_string(partial: 'my_modules/repositories/full_view_table') }
render json: {
html: render_to_string(partial: 'my_modules/repositories/full_view_table')
}
end
def dropdown_list
def repositories_dropdown_list
@repositories = Repository.accessible_by_teams(current_team)
render json: { html: render_to_string(partial: 'my_modules/repositories/repositories_dropdown_list') }

View file

@ -0,0 +1,87 @@
# frozen_string_literal: true
class MyModuleRepositorySnapshotsController < ApplicationController
before_action :load_my_module
before_action :load_repository
before_action :load_repository_snapshot, except: %i(create full_view_versions_sidebar)
before_action :check_view_permissions, except: %i(create destroy)
before_action :check_manage_permissions, only: %i(create destroy)
def index_dt
@draw = params[:draw].to_i
per_page = params[:length] == '-1' ? Constants::REPOSITORY_DEFAULT_PAGE_SIZE : params[:length].to_i
page = (params[:start].to_i / per_page) + 1
datatable_service = RepositorySnapshotDatatableService.new(@repository_snapshot, params, current_user, @my_module)
@datatable_params = {
view_mode: params[:view_mode],
skip_custom_columns: params[:skip_custom_columns]
}
@all_rows_count = datatable_service.all_count
@columns_mappings = datatable_service.mappings
@repository_rows = datatable_service.repository_rows
.preload(:repository_columns,
:created_by,
repository_cells: @repository_snapshot.cell_preload_includes)
.page(page)
.per(per_page)
render 'repository_rows/snapshot_index.json'
end
def create
service = Repositories::MyModuleAssigningSnapshotService.call(repository: @repository,
my_module: @my_module,
user: current_user)
if service.succeed?
@repository_snapshots = @my_module.repository_snapshots.where(original_repository: @repository)
render json: { html: render_to_string(partial: 'my_modules/repositories/full_view_versions_sidebar') }
else
render json: service.errors, status: :unprocessable_entity
end
end
def destroy
@repository_snapshot.destroy!
@repository_snapshots = @my_module.repository_snapshots.where(original_repository: @repository)
render json: { html: render_to_string(partial: 'my_modules/repositories/full_view_versions_sidebar') }
end
def full_view_table
render json: {
html: render_to_string(partial: 'my_modules/repositories/full_view_snapshot_table')
}
end
def full_view_versions_sidebar
@repository_snapshots = @my_module.repository_snapshots.where(original_repository: @repository)
render json: { html: render_to_string(partial: 'my_modules/repositories/full_view_versions_sidebar') }
end
private
def load_my_module
@my_module = MyModule.find_by(id: params[:my_module_id])
render_404 unless @my_module
end
def load_repository
@repository = Repository.find_by(id: params[:repository_id])
render_404 unless @repository
render_403 unless can_read_repository?(@repository)
end
def load_repository_snapshot
@repository_snapshot = @my_module.repository_snapshots.find_by(id: params[:id])
render_404 unless @repository_snapshot
end
def check_view_permissions
render_403 unless can_read_experiment?(@my_module.experiment)
end
def check_manage_permissions
render_403 unless can_read_experiment?(@my_module.experiment)
end
end

View file

@ -30,7 +30,7 @@ class UserRepositoriesController < ApplicationController
private
def load_vars
@repository = Repository.find_by_id(params[:repository_id])
render_403 if @repository.nil? || !can_read_repository?(@repository)
@repository = RepositoryBase.find_by(id: params[:repository_id])
render_403 if @repository.nil? || !can_read_repository?(@repository.becomes(Repository))
end
end

View file

@ -3,14 +3,8 @@
module RepositoryDatatableHelper
include InputSanitizeHelper
def prepare_row_columns(repository_rows,
repository,
columns_mappings,
team,
options = {})
parsed_records = []
repository_rows.each do |record|
def prepare_row_columns(repository_rows, repository, columns_mappings, team, options = {})
repository_rows.map do |record|
row = {
'DT_RowId': record.id,
'1': assigned_row(record),
@ -45,9 +39,29 @@ module RepositoryDatatableHelper
display_cell_value(cell, team)
end
end
parsed_records << row
row
end
end
def prepare_snapshot_row_columns(repository_rows, columns_mappings, team, options = {})
repository_rows.map do |record|
row = {
'DT_RowId': record.id,
'1': record.parent_id,
'2': escape_input(record.name),
'3': I18n.l(record.created_at, format: :full),
'4': escape_input(record.created_by.full_name),
'recordInfoUrl': Rails.application.routes.url_helpers.repository_row_path(record.id)
}
unless options[:skip_custom_columns]
# Add custom columns
record.repository_cells.each do |cell|
row[columns_mappings[cell.repository_column.id]] = display_cell_value(cell, team)
end
end
row
end
parsed_records
end
def assigned_row(record)
@ -79,6 +93,14 @@ module RepositoryDatatableHelper
Constants::REPOSITORY_TABLE_DEFAULT_STATE['columns'].to_json
end
def default_snapshot_table_order_as_js_array
Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['order'].to_json
end
def default_snapshot_table_columns
Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['columns'].to_json
end
def display_cell_value(cell, team)
value_name = cell.repository_column.data_type.demodulize.underscore
serializer_class = "RepositoryDatatable::#{cell.repository_column.data_type}Serializer".constantize

View file

@ -87,6 +87,10 @@ class Repository < RepositoryBase
end
end
def default_columns_count
Constants::REPOSITORY_TABLE_DEFAULT_STATE['length']
end
def i_shared?(team)
shared_with_anybody? && self.team == team
end

View file

@ -100,25 +100,19 @@ class RepositoryColumn < ApplicationRecord
def repository_list_value_deep_dup(new_column)
repository_list_items.each do |item|
new_item = item.deep_dup
new_item.repository_id = nil
new_column.repository_list_items << new_item
new_column.repository_list_items << item.deep_dup
end
end
def repository_checklist_value_deep_dup(new_column)
repository_checklist_items.each do |item|
new_item = item.deep_dup
new_item.repository_id = nil
new_column.repository_checklist_items << new_item
new_column.repository_checklist_items << item.deep_dup
end
end
def repository_status_value_deep_dup(new_column)
repository_status_items.each do |item|
new_item = item.deep_dup
new_item.repository_id = nil
new_column.repository_status_items << new_item
new_column.repository_status_items << item.deep_dup
end
end
end

View file

@ -5,4 +5,8 @@ class RepositorySnapshot < RepositoryBase
belongs_to :my_module, optional: true
validates :name, presence: true, length: { maximum: Constants::NAME_MAX_LENGTH }
def default_columns_count
Constants::REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['length']
end
end

View file

@ -29,6 +29,16 @@ Canaid::Permissions.register_for(Repository) do
user.is_admin_of_team?(repository.team) unless repository.shared_with?(user.current_team)
end
# repository: make a snapshot with assigned rows
can :create_repository_snapshot do |user, repository|
user.is_normal_user_or_admin_of_team?(repository.team)
end
# repository: delete a snapshot with assigned rows
can :delete_repository_snapshot do |user, repository|
user.is_normal_user_or_admin_of_team?(repository.team)
end
# repository: create/import record
can :create_repository_rows do |user, repository|
if repository.shared_with?(user.current_team)

View file

@ -18,7 +18,7 @@ class RepositoryDatatableService
def create_columns_mappings
# Make mappings of custom columns, so we have same id for every
# column
index = 6
index = @repository.default_columns_count
@mappings = {}
@repository.repository_columns.order(:id).each do |column|
@mappings[column.id] = index.to_s

View file

@ -0,0 +1,57 @@
# frozen_string_literal: true
class RepositorySnapshotDatatableService < RepositoryDatatableService
private
def process_query
search_value = build_conditions(@params)[:search_value]
order_obj = build_conditions(@params)[:order_by_column]
repository_rows = fetch_rows(search_value)
repository_rows = repository_rows.preload(Extends::REPOSITORY_ROWS_PRELOAD_RELATIONS)
@repository_rows = sort_rows(order_obj, repository_rows)
end
def fetch_rows(search_value)
repository_rows = @repository.repository_rows
@all_count = repository_rows.count
if search_value.present?
matched_by_user = repository_rows.joins(:created_by).where_attributes_like('users.full_name', search_value)
repository_row_matches = repository_rows
.where_attributes_like(['repository_rows.name', 'repository_rows.id'], search_value)
results = repository_rows.where(id: repository_row_matches)
results = results.or(repository_rows.where(id: matched_by_user))
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |field, include_hash|
custom_cell_matches = repository_rows.joins(repository_cells: include_hash)
.where_attributes_like(field, search_value)
results = results.or(repository_rows.where(id: custom_cell_matches))
end
repository_rows = results
end
repository_rows.left_outer_joins(:created_by)
.select('repository_rows.*')
.select('COUNT("repository_rows"."id") OVER() AS filtered_count')
.group('repository_rows.id')
end
def build_sortable_columns
array = [
'repository_rows.parent_id',
'repository_rows.name',
'repository_rows.created_at',
'users.full_name'
]
@repository.repository_columns.count.times do
array << 'repository_cell.value'
end
array
end
end

View file

@ -49,10 +49,8 @@
</span>
</a>
<div class="actions-block">
<div class="dropdown repositories-assign-container"
data-repositories-url="<%= dropdown_list_my_module_my_module_repositories_path(@my_module) %>"
>
<a href="#" id="repositories-assign-button" class="btn btn-secondary btn-block" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<div class="dropdown repositories-assign-container" data-repositories-url="<%= my_module_repositories_dropdown_list_path(@my_module) %>">
<a href="#" id="repositories-assign-button" class="btn btn-secondary btn-block" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span class="fas fa-file-signature"></span>
<span><%= t('my_modules.assigned_items.assign_from') %></span>
<span class="caret pull-right"></span>

View file

@ -1,4 +1,4 @@
<div class="modal" id="my-module-repository-full-view-modal" tabindex="-1" role="dialog">
<div class="modal" id="myModuleRepositoryFullViewModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -16,6 +16,20 @@
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<template id="repositoryToolbarButtonsTemplate">
<div class="">
<div class="form-group pull-left">
<button id="showVersionsSidebar" type="button" class="btn btn-default">
<span class="fas fa-eye"></span>
<%= t('my_modules.repository.snapshots.full_view.versions_sidebar_button') %>
</button>
</div>
</div>
</template>
<div class="row">
<div class="table-container"></div>
<div class="repository-versions-sidebar collapsed"></div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,31 @@
<table class="table"
data-id="<%= @repository_snapshot.id %>"
data-type="snapshot"
data-source="<%= index_dt_my_module_repository_snapshot_path(@my_module, @repository, @repository_snapshot) %>"
data-default-order="<%= default_snapshot_table_order_as_js_array %>"
data-default-table-columns="<%= default_snapshot_table_columns %>"
data-load-state-url="<%= repository_load_table_state_path(@repository_snapshot) %>"
data-versions-sidebar-url="<%= my_module_repository_full_view_versions_sidebar_path(@my_module, @repository) %>"
>
<thead>
<tr>
<th class="never"></th>
<th id="row-id"><%= t("repositories.table.id") %></th>
<th id="row-name"><%= t("repositories.table.row_name") %></th>
<th id="added-on"><%= t("repositories.table.added_on") %></th>
<th id="added-by"><%= t("repositories.table.added_by") %></th>
<% @repository_snapshot.repository_columns.order(:id).each do |column| %>
<th class="repository-column"
id="<%= column.id %>"
data-type="<%= column.data_type %>"
<% column.metadata.each do |k, v| %>
<%= "data-metadata-#{k}=#{v}" %>
<% end %>
>
<%= display_tooltip(column.name) %>
</th>
<% end %>
</tr>
</thead>
<tbody></tbody>
</table>

View file

@ -1,8 +1,11 @@
<table id="my-module-repository-table-full-view-<%= @repository.id %>" class="table"
data-source="<%= my_module_my_module_repository_path(@my_module, @repository) %>"
data-default-order="<%= default_table_order_as_js_array %>"
data-default-table-columns="<%= default_table_columns %>"
data-load-state-url="<%= repository_load_table_state_path(@repository) %>"
<table class="table"
data-id="<%= @repository.id %>"
data-type="live"
data-source="<%= index_dt_my_module_repository_path(@my_module, @repository) %>"
data-default-order="<%= default_table_order_as_js_array %>"
data-default-table-columns="<%= default_table_columns %>"
data-load-state-url="<%= repository_load_table_state_path(@repository) %>"
data-versions-sidebar-url="<%= my_module_repository_full_view_versions_sidebar_path(@my_module, @repository) %>"
>
<thead>
<tr>

View file

@ -0,0 +1,54 @@
<div class="repository-versions-header">
<h4><%= t('my_modules.repository.snapshots.full_view.header') %>
<a id="collapseVersionsSidebar" class="pull-right sidebar-collapse-button" href="#">
<i class="fas fa-angle-double-right"></i>
</a>
</h4>
</div>
<div class="list-group">
<div class="list-group-item live-version-item" data-id="<%= @repository.id %>">
<a id="selectLiveVersionButton" class="version-button" href="#" data-table-url="<%= full_view_table_my_module_repository_path(@my_module, @repository) %>">
<h2 class="list-group-item-heading">
<%= t('my_modules.repository.snapshots.full_view.live') %>
</h2>
</a>
<p class="list-group-item-text">
<%= t('my_modules.repository.snapshots.full_view.live_description') %>
</p>
</div>
<div class="create-snapshot-item">
<% if @repository_snapshots.blank? %>
<p class="list-group-item-text">
<%= t('my_modules.repository.snapshots.full_view.no_snapshots_label') %>
</p>
<% end %>
<button id="createRepositorySnapshotButton" class="btn btn-default" data-action-path="<%= my_module_repository_snapshots_path(@my_module, @repository) %>">
<i class="fas fa-camera"></i>
<%= t('my_modules.repository.snapshots.full_view.create_button') %>
</button>
</div>
<% @repository_snapshots.each do |repository_snapshot| %>
<div class="list-group-item repository-snapshot-item" data-id="<%= repository_snapshot.id %>">
<div class="row">
<div class="col-sm-10">
<a class="version-button select-snapshot-button" href="#" data-table-url="<%= full_view_table_my_module_repository_snapshot_path(@my_module, @repository, repository_snapshot) %>">
<h4 class="list-group-item-heading">
<%= l(repository_snapshot.created_at, format: :full) %>
</h4>
<p class="list-group-item-text">
<%= t('my_modules.repository.snapshots.full_view.created_by', full_name: repository_snapshot.created_by.full_name) %>
</p>
</a>
</div>
<div class="col-sm-2">
<a class="pull-right btn version-button delete-snapshot-button" href="#" data-action-path="<%= my_module_repository_snapshot_path(@my_module, @repository, repository_snapshot) %>">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</div>
<% end %>
</div>

View file

@ -11,23 +11,21 @@
<%= repository.name %>
</span>
<div class="action-buttons">
<i class="fas fa-expand full-screen"
data-table-url="<%= full_view_table_my_module_my_module_repository_path(@my_module, repository) %>"></i>
<i class="fas fa-expand full-screen" data-table-url="<%= full_view_table_my_module_repository_path(@my_module, repository) %>">
</i>
<i class="fas fa-trash unassign-repository"></i>
</div>
</a>
<div class="collapse assigned-repository-container"
id="assigned-repository-items-container-<%= repository.id %>"
data-repository-url="<%= my_module_my_module_repository_path(@my_module, repository) %>"
data-repository-url="<%= index_dt_my_module_repository_path(@my_module, repository) %>"
>
</div>
</div>
<% end %>
<template id="my-module-repository-simple-template">
<table class="table hidden"
data-default-table-columns="<%= default_table_columns %>"
>
<table class="table hidden" data-default-table-columns="<%= default_table_columns %>">
<thead>
<tr>
<th class="never"></th>
@ -44,4 +42,4 @@
<%= render partial: "my_modules/repositories/full_view_modal" %>
<%= javascript_include_tag("my_modules/repositories") %>
<%= javascript_include_tag("my_modules/repositories") %>

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
json.draw @draw
json.data do
json.array! prepare_snapshot_row_columns(@repository_rows,
@columns_mappings,
@repository.team,
defined?(@datatable_params) ? @datatable_params : {})
end
json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0
json.recordsTotal @all_rows_count

View file

@ -963,6 +963,26 @@ class Constants
}
end
REPOSITORY_TABLE_DEFAULT_STATE.freeze
# Repository default table state
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE = {
'time' => 0,
'start' => 0,
'length' => 5,
'order' => [[1, 'asc']], # Default sorting by 'ID' column
'search' => { 'search' => '',
'smart' => true,
'regex' => false,
'caseInsensitive' => true },
'columns' => [],
'assigned' => 'assigned',
'ColReorder' => [*0..4]
}
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['columns'] = REPOSITORY_TABLE_DEFAULT_STATE['columns'][0..4]
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE.freeze
# For default custom column template, any searchable default
# column can be reused
REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE =
@ -971,6 +991,7 @@ class Constants
EXPORTABLE_ZIP_EXPIRATION_DAYS = 7
REPOSITORY_DEFAULT_PAGE_SIZE = 10
REPOSITORY_LIST_ITEMS_PER_COLUMN = 500
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN = 50
REPOSITORY_NUMBER_TYPE_DEFAULT_DECIMALS = 2

View file

@ -794,6 +794,15 @@ en:
repository:
head_title: "%{project} | %{module} | Inventory %{repository}"
export: 'Export'
snapshots:
full_view:
header: 'Versions'
live: 'Live version'
live_description: 'Regularly updated from the inventory'
no_snapshots_label: 'You have not created any snapshots yet. To do so click the button bellow.'
versions_sidebar_button: 'View versions'
create_button: 'Create snapshot'
created_by: 'by %{full_name}'
modals:
assign_repository_record:
title: 'Assign %{repository_name} items to task %{my_module_name}'

View file

@ -384,13 +384,25 @@ Rails.application.routes.draw do
path: '/comments',
only: [:index, :create, :edit, :update, :destroy]
resources :my_module_repositories, path: '/repositories', only: :show do
get :repositories_dropdown_list, to: 'my_module_repositories#repositories_dropdown_list'
resources :repositories, only: [] do
member do
get :full_view_table
get :full_view_table, to: 'my_module_repositories#full_view_table', as: :full_view_table
post :index_dt, to: 'my_module_repositories#index_dt', as: :index_dt
end
collection do
get :dropdown_list
resources :repository_snapshots, controller: 'my_module_repository_snapshots',
as: :snapshots,
only: %i(create destroy) do
member do
get :full_view_table, to: 'my_module_repository_snapshots#full_view_table'
post :index_dt, to: 'my_module_repository_snapshots#index_dt'
end
end
get :full_view_versions_sidebar, to: 'my_module_repository_snapshots#full_view_versions_sidebar',
as: :full_view_versions_sidebar
end
# resources :sample_my_modules, path: '/samples_index', only: [:index]