Skip to content

Commit

Permalink
Merge pull request #250 from ael-code/edit-metadata
Browse files Browse the repository at this point in the history
Page to modify metadata of volumes
  • Loading branch information
ael-code committed Mar 12, 2016
2 parents 7daf3a3 + f4504a5 commit 86057a3
Show file tree
Hide file tree
Showing 6 changed files with 471 additions and 3 deletions.
8 changes: 6 additions & 2 deletions webant/api/archivant_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from flask import request, current_app, url_for, jsonify
from archivant import Archivant
from archivant.exceptions import NotFoundException
from util import ApiError, make_success_response
from util import ApiError, on_json_load_error, make_success_response


routes = []
Expand Down Expand Up @@ -55,7 +55,11 @@ def add_volume():

@route('/volumes/<volumeID>', methods=['PUT'])
def update_volume(volumeID):
metadata = receive_volume_metadata()
request.on_json_loading_failed = on_json_load_error
metadata = request.get_json()
# the next two lines should be removed when Flask version is >= 1.0
if not metadata:
raise ApiError("Unsupported media type", 415)
try:
current_app.archivant.update_volume(volumeID, metadata)
except NotFoundException, e:
Expand Down
72 changes: 72 additions & 0 deletions webant/static/edit.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@

.custom-field-form .custom-key{
float: left;
width: 30%;
margin-right: 1.5%;
}

.custom-field-form .custom-value{
float: left;
width: 59%;
margin-right: 0%;
}

.custom-field-form .remove-custom-field{
float: left;
width: 9.5%;
height: 34px;
}

.custom-field-form button{
width: 100%;
height: 100%;
}

@media (min-width: 768px) {

.custom-field-form .custom-value{
width: 65%;
}

.custom-field-form .remove-custom-field{
width: 3.5%;
}
}


#custom-fields-plus-button {
cursor: pointer;
}
.spin {
-webkit-animation: spin 2s infinite linear;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}

@-moz-keyframes spin {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(360deg);
}
}

@-webkit-keyframes spin {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
178 changes: 178 additions & 0 deletions webant/static/js/edit-volume.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
function initializePopover(){
$('[data-toggle="popover"]').popover();
}


/********* custom fields stuff **********/


function clearEmptyInput(e){
if(e.target.value.trim() === '')
e.target.value = '';
}

function validateCustomKeysRepetition() {

var counts = {};

function inc(key){
if(counts.hasOwnProperty(key))
counts[key]++;
else
counts[key] = 1;
}

// collect presets
elements = document.getElementById('mega-form').elements;
for(var i = 0; i < elements.length; i++)
inc(elements[i].name.trim());

customKeys = $('#custom-metadata .custom-field-form .custom-key input');

// collect custom keys
customKeys.each(function(index, elem) {
inc(elem.value.trim());
});

customKeys.each(function(index, elem) {
validityMessage = "";
value = elem.value.trim();
if(value){
if(value.startsWith('_'))
validityMessage = "Key cannot stats with underscore";
if(counts[value] > 1)
validityMessage = "Key used more than once";
}

if(validityMessage == ""){
elem.setCustomValidity("");
$(elem).parent().removeClass('has-error');
} else {
elem.setCustomValidity(validityMessage);
$(elem).parent().addClass('has-error');
}
});
}

function validateCustomField(customField) {
key = customField.find('.custom-key input').get(0);
value = customField.find('.custom-value input').get(0);
if(key.value.trim() != "" || value.value.trim() != ""){
key.setAttribute('required', 'true');
value.setAttribute('required', 'true');
}else{
key.removeAttribute('required');
value.removeAttribute('required');
}
}


function addCustomField(animation) {
newCustomField = $('#templates .custom-field-form').clone();
bindCustomField(newCustomField);

if(animation){
newCustomField.hide();
$('#custom-metadata').append(newCustomField);
newCustomField.slideDown('fast');
}else{
$('#custom-metadata').append(newCustomField);
}
}


function onRemoveCustomField(e) {
customField = $(e.target).parents('.custom-field-form').first();
customField.slideUp('fast', function (){
this.remove();
});
}

function bindCustomField(customField) {
customField.find('.remove-custom-field button').bind('click', onRemoveCustomField);
customField.find('.custom-key input').bind('input', validateCustomKeysRepetition);
customField.find('input').bind('input', function(e){
validateCustomField( $(e.target).parents('.custom-field-form'));
});
customField.find('input').focusout(clearEmptyInput);
}

function bindAllCustomFields() {
$('#custom-metadata .custom-field-form').each(function() {
bindCustomField($(this));
});
}

/********* end custom fields stuff **********/


function submitFormHandler(){
metadata = collectMetadata();
$.ajax({
type: "PUT",
url: $('#mega-form')[0].action,
data: JSON.stringify(metadata),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
exitUpdatingMode();
showSuccessModal();
},
error: function(errMsg) {
exitUpdatingMode();
showErrorModal();
}
});

enterUpdatingMode();
}

function showSuccessModal(){
m = $('#success-modal').modal();
m.modal('toogle');
}

function showErrorModal(){
m = $('#error-modal').modal();
m.modal('toogle');
}

function enterUpdatingMode(){
$('#submit-button').hide();
$('#updating-button').show();
}

function exitUpdatingMode(){
$('#updating-button').hide();
$('#submit-button').show();
}

function collectMetadata(){
metadata = {};
elements = document.getElementById('mega-form').elements;
for(var i = 0; i < elements.length; i++){
elem = elements[i];
kname = elem.name.trim()
if((kname === '') || (elem.tagName === 'button'))
continue;
metadata[kname] = elem.value.trim();
}
// collect custom keys
$('#custom-metadata .custom-field-form').each(function( index ) {
key = $(this).find('.custom-key input')[0].value.trim();
value = $(this).find('.custom-value input')[0].value.trim();
if(key !== "" && value !== "")
metadata[key] = value;
});
return metadata;
}



/********* Initialization *********/

$('[data-toggle="tooltip"]').tooltip();
initializePopover();
bindAllCustomFields();

/******* End Initialization *******/
7 changes: 6 additions & 1 deletion webant/templates/details.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ <h1>{{ title }}
</header>
<div class="btn-toolbar" role="toolbar" aria-label="toolbar">
<div class="btn-group pull-right" role="group" aria-label="action toolbar">
{% if not hide_from_toolbar['edit'] %}
<a href="{{ url_for('edit_volume', volumeID=volume['id']) }}" type="button" class="btn btn-default" aria-label='edit volume metadata' title='edit volume metadata'>
<span class="glyphicon glyphicon glyphicon-pencil"></span>
</a>
{% endif %}
{% if not hide_from_toolbar['delete'] %}
<button data-toggle="modal" data-target="#confirm-deletion-modal"
type="button" class="btn btn-default red-on-hover" aria-label='delete'>
type="button" class="btn btn-default" aria-label='delete volume' title='delete volume'>
<span class="glyphicon glyphicon-trash"></span>
</button>
{% endif %}
Expand Down
Loading

0 comments on commit 86057a3

Please sign in to comment.