Vue Attract: Sort/filterable table based on Vue
Initial commit implementing sortable and filterable tables for attract using Vue.
This commit is contained in:
@@ -1,28 +1,3 @@
|
||||
/**
|
||||
* Removes the task from the task list and shot list, and show the 'task-add-link'
|
||||
* when this was the last task in its category.
|
||||
*/
|
||||
function _remove_task_from_list(task_id) {
|
||||
var $task_link = $('#task-' + task_id)
|
||||
var $task_link_parent = $task_link.parent();
|
||||
$task_link.hideAndRemove(300, function() {
|
||||
if ($task_link_parent.children('.task-link').length == 0) {
|
||||
$task_link_parent.find('.task-add-link').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the 'active' class from any element whose ID starts with
|
||||
* shot-, asset-, or task-.
|
||||
*/
|
||||
function deactivateItemLinks()
|
||||
{
|
||||
$('[id^="shot-"]').removeClass('active');
|
||||
$('[id^="asset-"]').removeClass('active');
|
||||
$('[id^="task-"]').removeClass('active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an item such as tasks/shots in the #item-details div
|
||||
*/
|
||||
@@ -39,19 +14,9 @@ function item_open(item_id, item_type, pushState, project_url)
|
||||
}
|
||||
}
|
||||
|
||||
// Style elements starting with item_type and dash, e.g. "#shot-uuid"
|
||||
deactivateItemLinks();
|
||||
var current_item = $('#' + item_type + '-' + item_id);
|
||||
current_item.addClass('processing');
|
||||
|
||||
// Special case to highlight the shot row when opening task in shot or asset context
|
||||
var pu_ctx = ProjectUtils.context();
|
||||
var pc_ctx_shot_asset = (pu_ctx == 'shot' || pu_ctx == 'asset');
|
||||
if (pc_ctx_shot_asset && item_type == 'task'){
|
||||
$('[id^="shot-"]').removeClass('active');
|
||||
$('[id^="asset-"]').removeClass('active');
|
||||
$('#task-' + item_id).closest('.table-row').addClass('active');
|
||||
}
|
||||
|
||||
var item_url = '/attract/' + project_url + '/' + item_type + 's/' + item_id;
|
||||
var push_url = item_url;
|
||||
@@ -60,22 +25,14 @@ function item_open(item_id, item_type, pushState, project_url)
|
||||
}
|
||||
item_url += '?context=' + pu_ctx;
|
||||
|
||||
statusBarSet('default', 'Loading ' + item_type + '…');
|
||||
|
||||
$.get(item_url, function(item_data) {
|
||||
statusBarClear();
|
||||
$('#item-details').html(item_data);
|
||||
$('#col_right .col_header span.header_text').text(item_type + ' details');
|
||||
current_item
|
||||
.removeClass('processing newborn')
|
||||
.addClass('active');
|
||||
|
||||
}).fail(function(xhr) {
|
||||
if (console) {
|
||||
console.log('Error fetching task', item_id, 'from', item_url);
|
||||
console.log('XHR:', xhr);
|
||||
current_item
|
||||
.removeClass('processing')
|
||||
}
|
||||
|
||||
toastr.error('Failed to open ' + item_type);
|
||||
@@ -141,7 +98,9 @@ function asset_create(project_url)
|
||||
};
|
||||
|
||||
$.post(url, data, function(asset_data) {
|
||||
window.location.href = asset_data.asset_id;
|
||||
/* window.location.href = asset_data.asset_id; */
|
||||
pillar.events.Nodes.triggerCreated(asset_data);
|
||||
asset_open(asset_data._id);
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
if (console) {
|
||||
@@ -152,58 +111,6 @@ function asset_create(project_url)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the task item to the shots/tasks list.
|
||||
*
|
||||
* 'shot_id' can be undefined if the task isn't attached to a shot.
|
||||
*/
|
||||
function task_add(shot_id, task_id, task_type)
|
||||
{
|
||||
if (task_id === undefined || task_type === undefined) {
|
||||
throw new ReferenceError("task_add(" + shot_id + ", " + task_id + ", " + task_type + ") called.");
|
||||
}
|
||||
|
||||
var project_url = ProjectUtils.projectUrl();
|
||||
var url = '/attract/' + project_url + '/tasks/' + task_id;
|
||||
var context = ProjectUtils.context();
|
||||
|
||||
if (context == 'task') {
|
||||
/* WARNING: This is a copy of an element of attract/tasks/for_project .item-list.col-list
|
||||
* If that changes, change this too. */
|
||||
$('.item-list.task').append('\
|
||||
<a class="col-list-item task-list-item status-todo task-link active"\
|
||||
href="' + url + '"\
|
||||
data-task-id="' + task_id + '"\
|
||||
id="task-' + task_id + '">\
|
||||
<span class="status-indicator"></span>\
|
||||
<span class="name">-save your task first-</span>\
|
||||
<span class="due_date">-</span>\
|
||||
</a>\
|
||||
');
|
||||
} else if (context == 'shot' || context == 'asset') {
|
||||
if (shot_id === undefined) {
|
||||
throw new ReferenceError("task_add(" + shot_id + ", " + task_id + ", " + task_type + ") called in " + context + " context.");
|
||||
}
|
||||
|
||||
var $list_cell = $('#' + context + '-' + shot_id + ' .table-cell.task-type.' + task_type);
|
||||
var url = '/attract/' + project_url + '/' + context + 's/with-task/' + task_id;
|
||||
|
||||
/* WARNING: This is a copy of an element of attract/shots/for_project .item-list.col-list
|
||||
* If that changes, change this too. */
|
||||
$list_cell.append('\
|
||||
<a class="status-todo task-link active newborn"\
|
||||
title="-save your task first-"\
|
||||
href="' + url + '"\
|
||||
data-task-id="' + task_id + '"\
|
||||
id="task-' + task_id + '">\
|
||||
</a>\
|
||||
');
|
||||
|
||||
$list_cell.find('.task-add.task-add-link').addClass('hidden');
|
||||
} else {
|
||||
if (console) console.log('task_add: not doing much in context', context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task and show it in the #item-details div.
|
||||
@@ -228,8 +135,8 @@ function task_create(shot_id, task_type)
|
||||
|
||||
$.post(url, data, function(task_data) {
|
||||
if (console) console.log('Task created:', task_data);
|
||||
task_open(task_data.task_id);
|
||||
task_add(shot_id, task_data.task_id, task_type);
|
||||
pillar.events.Nodes.triggerCreated(task_data);
|
||||
task_open(task_data._id);
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
if (console) {
|
||||
@@ -257,18 +164,15 @@ function attract_form_save(form_id, item_id, item_save_url, options)
|
||||
var $item = $('#' + item_id);
|
||||
|
||||
$button.attr('disabled', true);
|
||||
$item.addClass('processing');
|
||||
|
||||
statusBarSet('', 'Saving ' + options.type + '…');
|
||||
|
||||
if (console) console.log('Sending:', payload);
|
||||
|
||||
$.post(item_save_url, payload)
|
||||
.done(function(saved_item) {
|
||||
if (console) console.log('Done saving', saved_item);
|
||||
toastr.success('Saved ' + options.type + '. ' + saved_item._updated);
|
||||
|
||||
statusBarSet('success', 'Saved ' + options.type + '. ' + saved_item._updated, 'pi-check');
|
||||
|
||||
pillar.events.Nodes.triggerUpdated(saved_item);
|
||||
$form.find("input[name='_etag']").val(saved_item._etag);
|
||||
|
||||
if (options.done) options.done($item, saved_item);
|
||||
@@ -279,13 +183,12 @@ function attract_form_save(form_id, item_id, item_save_url, options)
|
||||
|
||||
$button.removeClass('btn-outline-success').addClass('btn-danger');
|
||||
|
||||
statusBarSet('error', 'Failed saving. ' + xhr_or_response_data.status, 'pi-warning');
|
||||
toastr.error('Failed saving. ' + xhr_or_response_data.status);
|
||||
|
||||
if (options.fail) options.fail($item, xhr_or_response_data);
|
||||
})
|
||||
.always(function() {
|
||||
$button.attr('disabled', false);
|
||||
$item.removeClass('processing');
|
||||
|
||||
if (options.always) options.always($item);
|
||||
})
|
||||
@@ -297,21 +200,6 @@ function attract_form_save(form_id, item_id, item_save_url, options)
|
||||
function task_save(task_id, task_url) {
|
||||
return attract_form_save('item_form', 'task-' + task_id, task_url, {
|
||||
done: function($task, saved_task) {
|
||||
// Update the task list.
|
||||
// NOTE: this is tightly linked to the HTML of the task list in for_project.jade.
|
||||
$('.task-name-' + saved_task._id).text(saved_task.name).flashOnce();
|
||||
$task.find('span.name').text(saved_task.name);
|
||||
$task.find('span.status').text(saved_task.properties.status.replace('_', ' '));
|
||||
if (saved_task.properties.due_date){
|
||||
$task.find('span.due_date').text(moment().to(saved_task.properties.due_date));
|
||||
}
|
||||
|
||||
$task
|
||||
.removeClassPrefix('status-')
|
||||
.addClass('status-' + saved_task.properties.status)
|
||||
.flashOnce()
|
||||
;
|
||||
|
||||
task_open(task_id);
|
||||
},
|
||||
fail: function($item, xhr_or_response_data) {
|
||||
@@ -329,13 +217,6 @@ function task_save(task_id, task_url) {
|
||||
function shot_save(shot_id, shot_url) {
|
||||
return attract_form_save('item_form', 'shot-' + shot_id, shot_url, {
|
||||
done: function($shot, saved_shot) {
|
||||
// Update the shot list.
|
||||
$('.shot-name-' + saved_shot._id).text(saved_shot.name);
|
||||
$shot
|
||||
.removeClassPrefix('status-')
|
||||
.addClass('status-' + saved_shot.properties.status)
|
||||
.flashOnce()
|
||||
;
|
||||
shot_open(shot_id);
|
||||
},
|
||||
fail: function($item, xhr_or_response_data) {
|
||||
@@ -353,19 +234,6 @@ function shot_save(shot_id, shot_url) {
|
||||
function asset_save(asset_id, asset_url) {
|
||||
return attract_form_save('item_form', 'asset-' + asset_id, asset_url, {
|
||||
done: function($asset, saved_asset) {
|
||||
// Update the asset list.
|
||||
// NOTE: this is tightly linked to the HTML of the asset list in for_project.jade.
|
||||
$('.item-name-' + saved_asset._id).text(saved_asset.name).flashOnce();
|
||||
$asset.find('span.name').text(saved_asset.name);
|
||||
$asset.find('span.due_date').text(moment().to(saved_asset.properties.due_date));
|
||||
$asset.find('span.status').text(saved_asset.properties.status.replace('_', ' '));
|
||||
|
||||
$asset
|
||||
.removeClassPrefix('status-')
|
||||
.addClass('status-' + saved_asset.properties.status)
|
||||
.flashOnce()
|
||||
;
|
||||
|
||||
asset_open(asset_id);
|
||||
},
|
||||
fail: function($item, xhr_or_response_data) {
|
||||
@@ -384,9 +252,6 @@ function task_delete(task_id, task_etag, task_delete_url) {
|
||||
if (task_id === undefined || task_etag === undefined || task_delete_url === undefined) {
|
||||
throw new ReferenceError("task_delete(" + task_id + ", " + task_etag + ", " + task_delete_url + ") called.");
|
||||
}
|
||||
|
||||
$('#task-' + task_id).addClass('processing');
|
||||
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: task_delete_url,
|
||||
@@ -395,13 +260,12 @@ function task_delete(task_id, task_etag, task_delete_url) {
|
||||
.done(function(e) {
|
||||
if (console) console.log('Task', task_id, 'was deleted.');
|
||||
$('#item-details').fadeOutAndClear();
|
||||
_remove_task_from_list(task_id);
|
||||
pillar.events.Nodes.triggerDeleted(task_id);
|
||||
|
||||
statusBarSet('success', 'Task deleted successfully', 'pi-check');
|
||||
toastr.success('Task deleted');
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
|
||||
statusBarSet('error', 'Unable to delete task, code ' + xhr.status, 'pi-warning');
|
||||
toastr.error('Unable to delete task, code ' + xhr.status);
|
||||
|
||||
if (xhr.status == 412) {
|
||||
alert('Someone else edited this task before you deleted it; refresh to try again.');
|
||||
@@ -429,7 +293,7 @@ function loadActivities(url)
|
||||
console.log('XHR:', xhr);
|
||||
}
|
||||
|
||||
statusBarSet('error', 'Opening activity log failed.', 'pi-warning');
|
||||
toastr.error('Opening activity log failed.');
|
||||
|
||||
if (xhr.status) {
|
||||
$('#activities').html(xhr.responseText);
|
||||
@@ -441,31 +305,6 @@ function loadActivities(url)
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$("a.shot-link[data-shot-id]").click(function(e) {
|
||||
e.preventDefault();
|
||||
// delegateTarget is the thing the event hander was attached to,
|
||||
// rather than the thing we clicked on.
|
||||
var shot_id = e.delegateTarget.dataset.shotId;
|
||||
shot_open(shot_id);
|
||||
});
|
||||
|
||||
$("a.asset-link[data-asset-id]").click(function(e) {
|
||||
e.preventDefault();
|
||||
// delegateTarget is the thing the event hander was attached to,
|
||||
// rather than the thing we clicked on.
|
||||
var asset_id = e.delegateTarget.dataset.assetId;
|
||||
asset_open(asset_id);
|
||||
});
|
||||
|
||||
$("a.task-link[data-task-id]").click(function(e) {
|
||||
e.preventDefault();
|
||||
var task_id = e.delegateTarget.dataset.taskId;
|
||||
var project_url = e.delegateTarget.dataset.projectUrl; // fine if undefined
|
||||
task_open(task_id, project_url);
|
||||
});
|
||||
});
|
||||
|
||||
var save_on_ctrl_enter = ['shot', 'asset', 'task'];
|
||||
$(document).on('keyup', function(e){
|
||||
if ($.inArray(save_on_ctrl_enter, ProjectUtils.context())) {
|
||||
|
Reference in New Issue
Block a user