Add edit renderer for Assets

This commit is contained in:
Urban Rotnik 2019-12-04 14:52:52 +01:00
parent 3ab1967703
commit ee5c2ac93d
7 changed files with 276 additions and 22 deletions

View file

@ -0,0 +1,54 @@
/*
global ActiveStorage Promise
*/
/* eslint-disable no-unused-vars */
var Asset = (function() {
function uploadFiles($fileInputs, directUploadUrl) {
let filesToUploadCntr = 0;
let filesUploadedCntr = 0;
let filesForUpload = [];
$fileInputs.each(function(_, f) {
let $f = $(f);
if ($f.val()) {
filesToUploadCntr += 1;
filesForUpload.push($f);
}
});
return new Promise((resolve, reject) => {
if (filesToUploadCntr === 0) {
resolve('done');
return;
}
$(filesForUpload).each(function(_, $el) {
let upload = new ActiveStorage.DirectUpload($el[0].files[0], directUploadUrl);
upload.create(function(error, blob) {
if (error) {
reject(error);
} else {
$el
.prev('.file-hidden-field-container')
.html(`<input type="hidden"
form="${$el.attr('form')}"
name="repository_cells[${$el.data('col-id')}]"
value="${blob.signed_id}"/>`);
filesUploadedCntr += 1;
if (filesUploadedCntr === filesToUploadCntr) {
resolve('done');
}
}
});
return true;
});
});
}
return {
uploadFiles: uploadFiles
};
}());

View file

@ -17,7 +17,27 @@ $.fn.dataTable.render.editRowName = function(formId, cell) {
};
$.fn.dataTable.render.editRepositoryAssetValue = function(formId, columnId, cell) {
return '';
let $cell = $(cell.node());
let empty = $cell.is(':empty');
let fileName = $cell.find('a.file-preview-link').text();
$cell.html(`
<div class="file-editing">
<div class="file-hidden-field-container hidden"></div>
<input class=""
id="repository_file_${columnId}"
form="${formId}"
type="file"
data-col-id="${columnId}"
data-is-empty="${empty}"
value=""
data-type="RepositoryAssetValue">
<div class="file-upload-button ${empty ? 'new-file' : ''}">
<label for="repository_file_${columnId}">Select File (Max 300 MB)...</label>
<span class="icon"><i class="fas fa-paperclip"></i></span><span class="label-asset">${fileName}</span>
<span class="delete-action fas fa-trash"> </span>
</div>
</div>`);
};
$.fn.dataTable.render.editRepositoryTextValue = function(formId, columnId, cell) {

View file

@ -250,7 +250,8 @@ var RepositoryDatatable = (function(global) {
function initSaveButton() {
TABLE_WRAPPER.on('click', '#saveRecord', function() {
$(TABLE_ID).find('.repository-row-edit-form').submit();
var $table = $(TABLE_ID);
RepositoryDatatableRowEditor.validateAndSubmit($table);
});
}

View file

@ -1,6 +1,7 @@
/*
globals HelperModule animateSpinner SmartAnnotation
globals HelperModule animateSpinner SmartAnnotation Asset
*/
/* eslint-disable no-unused-vars */
var RepositoryDatatableRowEditor = (function() {
const NAME_COLUMN_ID = 'row-name';
@ -18,27 +19,80 @@ var RepositoryDatatableRowEditor = (function() {
});
}
function validateAndSubmit($table) {
let $form = $table.find('.repository-row-edit-form');
let $row = $form.closest('tr');
let valid = true;
let directUrl = $table.data('direct-upload-url');
let $files = $row.find('input[type=file]');
$row.find('.has-error').removeClass('has-error').find('span').remove();
// Validations here
$row.find('input').each(function() {
let dataType = $(this).data('type');
if (!dataType) return;
valid = $.fn.dataTable.render[dataType + 'Validator']($(this));
if (!valid) return false;
});
if (!valid) return false;
// DirectUpload here
let uploadPromise = Asset.uploadFiles($files, directUrl);
// Submission here
uploadPromise
.then(function() {
animateSpinner(null, true);
$form.submit();
return false;
}).catch((reason) => {
alert(reason);
return false;
});
return null;
}
function initAssetCellActions($row) {
let fileInputs = $row.find('input[type=file]');
let deleteButtons = $row.find('.file-upload-button>span.delete-action');
fileInputs.on('change', function() {
let $input = $(this);
let $fileBtn = $input.next('.file-upload-button');
let $label = $fileBtn.find('.label-asset');
$label.text($input[0].files[0].name);
$fileBtn.removeClass('new-file');
});
deleteButtons.on('click', function() {
let $fileBtn = $(this).parent();
let $input = $fileBtn.prev('input[type=file]');
let $label = $fileBtn.find('.label-asset');
$fileBtn.addClass('new-file');
$label.text('');
$input.val('');
if (!$input.data('is-empty')) { // set hidden field for deletion only if original value has been set on rendering
$input
.prev('.file-hidden-field-container')
.html(`<input type="hidden"
form="${$input.attr('form')}"
name="repository_cells[${$input.data('col-id')}]"
value="-1"/>`);
}
});
}
function initFormSubmitAction(table) {
TABLE = table;
let $table = $(TABLE.table().node());
$table.on('ajax:beforeSend', '.repository-row-edit-form', function() {
let $row = $(this).closest('tr');
let valid = true;
$row.find('.has-error').removeClass('has-error').find('span').remove();
$row.find('input').each(function() {
let dataType = $(this).data('type');
if (!dataType) return;
valid = $.fn.dataTable.render[dataType + 'Validator']($(this));
});
if (!valid) return false;
animateSpinner(null, true);
});
$table.on('ajax:success', '.repository-row-edit-form', function(ev, data) {
TABLE.ajax.reload();
HelperModule.flashAlertMsg(data.flash, 'success');
@ -139,13 +193,16 @@ var RepositoryDatatableRowEditor = (function() {
});
initSmartAnnotation($row);
initAssetCellActions($row);
TABLE.columns.adjust();
}
return Object.freeze({
initFormSubmitAction: initFormSubmitAction,
validateAndSubmit: validateAndSubmit,
switchRowToEditMode: switchRowToEditMode,
addNewRow: addNewRow
});
}());

View file

@ -1,4 +1,4 @@
/* global GLOBAL_CONSTANTS textValidator */
/* global GLOBAL_CONSTANTS textValidator I18n */
$.fn.dataTable.render.RowNameValidator = function($input) {
return textValidator(undefined, $input, 1, GLOBAL_CONSTANTS.NAME_MAX_LENGTH);
@ -15,3 +15,17 @@ $.fn.dataTable.render.RepositoryListValueValidator = function() {
$.fn.dataTable.render.RepositoryStatusValueValidator = function() {
return true;
};
$.fn.dataTable.render.RepositoryAssetValueValidator = function($input) {
let file = $input[0].files[0];
if (!file) return true;
let valid = (file.size < GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB * 1024 * 1024);
if (valid) return true;
let errorMessage = I18n.t('general.file.size_exceeded', { file_size: GLOBAL_CONSTANTS.FILE_MAX_SIZE_MB });
let $btn = $input.next('.file-upload-button');
$btn.addClass('error');
$btn.attr('data-error-text', errorMessage);
return false;
};

View file

@ -65,6 +65,10 @@
.repository-status-value-icon {
margin-right: 5px;
}
.dropdown-selector-container {
width: 150px;
}
}
.repository-cog {
@ -158,10 +162,114 @@
}
.file-preview-link {
min-width: 140px;
padding-left: 5px;
}
}
.file-editing {
width: 200px;
.file-upload-button {
background-color: $color-white;
border: solid 1px;
border-radius: 3px;
height: 34px;
line-height: 32px;
position: relative;
&.new-file {
.icon {
display: none;
}
label {
display: inline-block;
}
&:hover {
.fa-trash {
display: none;
}
}
}
.icon {
display: inline-block;
text-align: center;
width: 34px;
}
.label-asset {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: calc(100% - 44px);
}
.fa-trash {
background-color: $color-white;
cursor: pointer;
display: none;
line-height: 32px;
position: absolute;
right: 0;
text-align: center;
top: 0;
width: 34px;
z-index: 3;
}
&:hover {
.fa-trash {
display: inline-block;
}
}
&.error {
border-color: $brand-danger;
margin-bottom: 10px;
&::after {
background-color: $color-white;
bottom: 0;
color: $brand-danger;
content: "\f071";
font-family: "Font Awesome 5 Free";
font-weight: 501;
line-height: 32px;
position: absolute;
right: 0;
text-align: center;
width: 34px;
}
&::before {
bottom: -15px;
color: $brand-danger;
content: attr(data-error-text);
left: 0;
line-height: 15px;
position: absolute;
width: 100%;
}
}
}
input[type=file] {
display: none;
}
label {
display: none;
font-weight: normal;
margin-left: 10px;
}
}
.toolbarButtonsDatatable {
.view-only-label {
opacity: .6;

View file

@ -158,7 +158,7 @@ class RepositoryRowsController < ApplicationController
existing.delete
end
elsif existing.value_type == 'RepositoryAssetValue'
existing.value.destroy && next if remove_file_columns_params.include?(key)
existing.value.destroy && next if value == '-1'
if existing.value.asset.update(file: value)
existing.value.asset.created_by = current_user
existing.value.asset.last_modified_by = current_user