Merge pull request #5364 from dannon/history_multipanel_fixes

History multipanel fixes
This commit is contained in:
Martin Cech
2018-01-25 10:51:27 -05:00
committed by GitHub
5 changed files with 142 additions and 154 deletions
+3 -1
View File
@@ -27,6 +27,9 @@ import LegacyGridView from "legacy/grid/grid-view";
import * as run_stats from "reports/run_stats";
import ToolshedGroups from "toolshed/toolshed.groups";
/* global Galaxy */
/* global $ */
if (window.Galaxy && window.Galaxy.debug === undefined) {
//TODO: (kind of a temporary hack?) Must have Galaxy.logging for some of the imports
//here; remove when imports are all fixed.
@@ -155,7 +158,6 @@ export function multiHistoryEntry(options) {
limitPerFetch: options.limit,
currentHistoryId: options.current_history_id
});
let multipanel = new MultiPanel.MultiPanelColumns({
el: $("#center").get(0),
histories: histories
@@ -2,6 +2,9 @@ import * as _ from "libs/underscore";
import * as Backbone from "libs/backbone";
import BASE_MVC from "mvc/base-mvc";
/* global Galaxy */
/* global jQuery */
//=============================================================================
/**
* A Collection that can be limited/offset/re-ordered/filtered.
@@ -35,7 +38,6 @@ var ControlledFetchCollection = Backbone.Collection.extend({
// note: we normally want options passed in to override the defaults built here
// so most of these fns will generate defaults
options = _.clone(options) || {};
var self = this;
// jquery ajax option; allows multiple q/qv for filters (instead of 'q[]')
options.traditional = true;
@@ -47,7 +49,7 @@ var ControlledFetchCollection = Backbone.Collection.extend({
// to the pagination options too
// (i.e. this.on( 'sync', function( options ){ if( options.limit ){ ... } }))
// however, when we send to xhr/jquery we copy them to data also so that they become API query params
options.data = options.data || self._buildFetchData(options);
options.data = options.data || this._buildFetchData(options);
Galaxy.debug("data:", options.data);
// options.data.filters --> options.data.q, options.data.qv
@@ -1,9 +1,13 @@
import HISTORY_CONTENTS from "mvc/history/history-contents";
import HISTORY_PREFS from "mvc/history/history-preferences";
import CONTROLLED_FETCH_COLLECTION from "mvc/base/controlled-fetch-collection";
import UTILS from "utils/utils";
import BASE_MVC from "mvc/base-mvc";
import _l from "utils/localization";
import * as _ from "libs/underscore";
import * as Backbone from "libs/backbone";
/* global jQuery */
/* global Galaxy */
//==============================================================================
/** @class Model for a Galaxy history resource - both a record of user
@@ -161,7 +165,7 @@ var History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(
_fetchContentRelatedAttributes: function() {
var contentRelatedAttrs = ["size", "non_ready_jobs", "contents_active", "hid_counter"];
return this.fetch({
data: $.param({
data: jQuery.param({
keys: contentRelatedAttrs.join(",")
})
});
@@ -185,7 +189,9 @@ var History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(
var serverResponseDatetime;
try {
serverResponseDatetime = new Date(xhr.getResponseHeader("Date"));
} catch (err) {}
} catch (err) {
console.error(err);
}
this.lastUpdateTime = serverResponseDatetime || new Date();
this.checkForUpdates(options);
});
@@ -277,11 +283,10 @@ var History = Backbone.Model.extend(BASE_MVC.LoggableMixin).extend(
/** fetch this histories contents, adjusting options based on the stored history preferences */
fetchContents: function(options) {
options = options || {};
var self = this;
// we're updating, reset the update time
self.lastUpdateTime = new Date();
return self.contents.fetchCurrentPage(options);
this.lastUpdateTime = new Date();
return this.contents.fetchCurrentPage(options);
},
/** save this history, _Mark_ing it as deleted (just a flag) */
@@ -438,7 +443,7 @@ var HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({
_buildFetchFilters: function(options) {
var superFilters = _collectionSuper.prototype._buildFetchFilters.call(this, options) || {};
var filters = {};
if (!this.includeDeleted) {
if (this.includeDeleted !== true) {
filters.deleted = false;
filters.purged = false;
} else {
@@ -451,25 +456,24 @@ var HistoryCollection = _collectionSuper.extend(BASE_MVC.LoggableMixin).extend({
/** override to fetch current as well (as it may be outside the first 10, etc.) */
fetchFirst: function(options) {
var self = this;
// TODO: batch?
var xhr = $.when();
var xhr = jQuery.when();
if (this.currentHistoryId) {
xhr = _collectionSuper.prototype.fetchFirst.call(self, {
xhr = _collectionSuper.prototype.fetchFirst.call(this, {
silent: true,
limit: 1,
filters: {
"encoded_id-in": this.currentHistoryId,
// without these a deleted current history will return [] here and block the other xhr
purged: "",
deleted: "",
"encoded_id-in": this.currentHistoryId
deleted: null,
purged: ""
}
});
}
return xhr.then(() => {
options = options || {};
options.offset = 0;
return self.fetchMore(options);
return this.fetchMore(options);
});
},
+114 -136
View File
@@ -1,4 +1,6 @@
import _l from "utils/localization";
import * as _ from "libs/underscore";
import * as Backbone from "libs/backbone";
import HISTORY_MODEL from "mvc/history/history-model";
import HISTORY_VIEW_EDIT from "mvc/history/history-view-edit";
import JOB_STATES_MODEL from "mvc/history/job-states-model";
@@ -9,6 +11,9 @@ import ajaxQueue from "utils/ajax-queue";
import "ui/mode-button";
import "ui/search-input";
/* global $ */
/* global Galaxy */
var logNamespace = "history";
/* ==============================================================================
TODO:
@@ -54,25 +59,23 @@ var HistoryViewColumn = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** set up reflexive listeners */
setUpListeners: function setUpListeners() {
var column = this;
//this.log( 'setUpListeners', this );
this.once("rendered", () => {
column.trigger("rendered:initial", column);
this.trigger("rendered:initial", this);
});
this.setUpPanelListeners();
},
/** set listeners needed for panel */
setUpPanelListeners: function setUpPanelListeners() {
var column = this;
this.listenTo(
this.panel,
{
//'all': function(){ console.info( 'panel of ' + this, arguments ); },
// assumes panel will take the longest to render
rendered: function() {
column.trigger("rendered", column);
rendered: () => {
this.trigger("rendered", this);
},
// when a panel's view expands turn off the click handler on the rerun button so that it uses it's href
// this allows the button to open the tool rerun form in a new tab (instead of erroring)
@@ -125,7 +128,6 @@ var HistoryViewColumn = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** set up plugins */
setUpBehaviors: function setUpBehaviors() {
//this.log( 'setUpBehaviors:', this );
//var column = this;
// on panel size change, ...
},
@@ -175,22 +177,19 @@ var HistoryViewColumn = Backbone.View.extend(baseMVC.LoggableMixin).extend({
},
//TODO: remove boiler plate from next 3
"click .delete-history": function() {
var column = this;
this.model._delete().done(data => {
column.render();
this.render();
});
},
"click .undelete-history": function() {
var column = this;
this.model.undelete().done(data => {
column.render();
this.render();
});
},
"click .purge-history": function() {
if (confirm(_l("This will permanently remove the data. Are you sure?"))) {
var column = this;
this.model.purge().done(data => {
column.render();
this.render();
});
}
},
@@ -321,10 +320,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Set up reflexive listeners */
setUpListeners: function setUpListeners() {
var multipanel = this;
//multipanel.log( 'setUpListeners', multipanel );
this.on("end-of-scroll", () => {
multipanel.collection.fetchMore();
this.collection.fetchMore();
});
},
@@ -352,10 +350,9 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
addModels: function addModels(models, collection, options) {
// console.log( 'addModels:', models, collection, options );
options = options || {};
var multipanel = this;
models = _.isArray(models) ? models : [models];
models.forEach(model => {
multipanel.addColumn(model, false);
this.addColumn(model, false);
// if this is from a fetch, sort will be called and it will call render
});
return this;
@@ -363,23 +360,22 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Set up listeners for the collection - handling: added histories, change of current, deletion, and sorting */
setUpCollectionListeners: function() {
var multipanel = this;
multipanel.listenTo(multipanel.collection, {
this.listenTo(this.collection, {
// handle ajax errors from the collection
error: multipanel.errorHandler,
error: this.errorHandler,
// add multiple models
add: multipanel.addModels,
add: this.addModels,
// when all the histories a user has have been fetched
"all-fetched": multipanel._postFetchAll,
"all-fetched": this._postFetchAll,
// handle addition of histories, triggered by column copy and create new
"new-current": multipanel.addAsCurrentColumn,
"new-current": this.addAsCurrentColumn,
// handle setting a history as current, triggered by history.setAsCurrent
"set-as-current": multipanel.setCurrentHistory,
"set-as-current": this.setCurrentHistory,
// handle deleting a history (depends on whether panels is including deleted or not)
"change:deleted change:purged": multipanel.handleDeletedHistory,
"change:deleted change:purged": this.handleDeletedHistory,
// re-render columns after a sort
sort: function() {
multipanel.renderColumns(0);
this.renderColumns(0);
}
});
},
@@ -420,8 +416,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
handleDeletedHistory: function handleDeletedHistory(history) {
if (history.get("deleted") || history.get("purged")) {
this.log("handleDeletedHistory", this.collection.includeDeleted, history);
var multipanel = this;
var column = multipanel.columnMap[history.id];
var column = this.columnMap[history.id];
if (!column) {
return;
}
@@ -433,8 +428,8 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
//multipanel.collection.create().done( function(){
// if( !multipanel.collection.includeDeleted ){ multipanel.removeColumn( column, false ); }
//});
} else if (!multipanel.collection.includeDeleted) {
multipanel.removeColumn(column);
} else if (!this.collection.includeDeleted) {
this.removeColumn(column);
}
}
},
@@ -485,13 +480,11 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** create columns from collection */
createColumns: function createColumns(models, columnOptions) {
columnOptions = columnOptions || this.options.columnOptions;
var multipanel = this;
// clear column map
// TODO: make cummulative
multipanel.columnMap = {};
multipanel.collection.each((model, i) => {
var column = multipanel.createColumn(model, columnOptions);
multipanel.columnMap[model.id] = column;
this.columnMap = {};
this.collection.each((model, i) => {
this.columnMap[model.id] = this.createColumn(model, columnOptions);
});
},
@@ -516,7 +509,6 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** add a new column for history and render all columns if render is true */
addColumn: function add(history, render) {
// console.debug( 'adding column for:', history, render );
render = render !== undefined ? render : true;
var newColumn = this.createColumn(history);
this.columnMap[history.id] = newColumn;
@@ -528,13 +520,10 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** add a new column for history and make it the current history/column */
addAsCurrentColumn: function add(history, collection, options) {
//this.log( 'adding current column for:', history );
var multipanel = this;
var newColumn = this.addColumn(history, false);
this.setCurrentHistory(history);
newColumn.once("rendered", () => {
multipanel.queueHdaFetch(newColumn);
this.queueHdaFetch(newColumn);
});
return newColumn;
},
@@ -546,47 +535,45 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
if (!column) {
return;
}
var multipanel = this;
var widthToRemove = this.options.columnWidth + this.options.columnGap;
column.$el.fadeOut("fast", function() {
column.$el.fadeOut("fast", () => {
if (render) {
$(this).remove();
multipanel.$(".middle").width(multipanel.$(".middle").width() - widthToRemove);
multipanel.checkColumnsInView();
multipanel._recalcFirstColumnHeight();
this.$(".middle").width(this.$(".middle").width() - widthToRemove);
this.checkColumnsInView();
this._recalcFirstColumnHeight();
}
//TODO: to freeColumn (where Columns have freePanel)
multipanel.stopListening(column.panel);
multipanel.stopListening(column);
delete multipanel.columnMap[column.model.id];
this.stopListening(column.panel);
this.stopListening(column);
delete this.columnMap[column.model.id];
column.remove();
});
},
/** set up listeners for a column and it's panel - handling: hda lazy-loading, drag and drop */
setUpColumnListeners: function setUpColumnListeners(column) {
var multipanel = this;
multipanel.listenTo(column, {
this.listenTo(column, {
//'all': function(){ console.info( 'column ' + column + ':', arguments ) },
"in-view": multipanel.queueHdaFetch
"in-view": this.queueHdaFetch
});
multipanel.listenTo(column.panel, {
this.listenTo(column.panel, {
//'all': function(){ console.info( 'panel ' + column.panel + ':', arguments ) },
"view:draggable:dragstart": function(ev, view, panel, column) {
multipanel._dropData = JSON.parse(ev.dataTransfer.getData("text"));
multipanel.currentColumnDropTargetOn();
"view:draggable:dragstart": (ev, view, panel, column) => {
this._dropData = JSON.parse(ev.dataTransfer.getData("text"));
this.currentColumnDropTargetOn();
},
"view:draggable:dragend": function(ev, view, panel, column) {
multipanel._dropData = null;
multipanel.currentColumnDropTargetOff();
"view:draggable:dragend": (ev, view, panel, column) => {
this._dropData = null;
this.currentColumnDropTargetOff();
},
"droptarget:drop": function(ev, data, panel) {
"droptarget:drop": (ev, data, panel) => {
//note: bad copy sources fail silently
var toCopy = multipanel._dropData.filter(json => panel.model.contents.isCopyable(json));
multipanel._dropData = null;
var toCopy = this._dropData.filter(json => panel.model.contents.isCopyable(json));
this._dropData = null;
var queue = new ajaxQueue.NamedAjaxQueue();
if (panel.model.contents.currentPage !== 0) {
@@ -628,8 +615,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
if (!filters || !filters.length) {
return this.sortedColumns();
}
var multipanel = this;
return multipanel.sortedColumns().filter((column, index) => {
return this.sortedColumns().filter((column, index) => {
var filtered = column.currentHistory || _.every(filters.map(filter => filter.call(column)));
return filtered;
});
@@ -637,8 +623,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** return array of Columns sorted to match the collection */
sortedColumns: function() {
var multipanel = this;
var sorted = this.collection.map((history, index) => multipanel.columnMap[history.id]);
var sorted = this.collection.map((history, index) => this.columnMap[history.id]);
return sorted;
},
@@ -646,18 +631,17 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Render this view, columns, and set up view plugins */
render: function render(speed) {
speed = speed !== undefined ? speed : this.fxSpeed;
var multipanel = this;
multipanel.log(`${multipanel}.render`);
multipanel.$el.html(multipanel.mainTemplate(multipanel));
multipanel.renderColumns(speed);
this.log(`${this}.render`);
this.$el.html(this.mainTemplate(this));
this.renderColumns(speed);
// set the columns to full height allowed and set up behaviors for thie multipanel
multipanel.setUpBehaviors();
this.setUpBehaviors();
//TODO: wrong - has to wait for columns to render
// - create a column listener that fires this when all columns are rendered
multipanel.trigger("rendered", multipanel);
return multipanel;
this.trigger("rendered", this);
return this;
},
/** Render the columns and panels */
@@ -665,24 +649,22 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
speed = _.isNumber(speed) ? speed : this.fxSpeed;
// console.log( 'renderColumns:', speed );
// render columns and track the total number rendered, firing an event when all are rendered
var self = this;
var sortedAndFiltered = self.sortedFilteredColumns();
var sortedAndFiltered = this.sortedFilteredColumns();
// console.log( '\t sortedAndFiltered:', sortedAndFiltered );
var $middle = self.$(".middle").empty();
var $middle = this.$(".middle").empty();
self._addColumns(sortedAndFiltered, speed);
if (!self.collection.allFetched) {
$middle.append(self.loadingIndicatorTemplate(self));
this._addColumns(sortedAndFiltered, speed);
if (!this.collection.allFetched) {
$middle.append(this.loadingIndicatorTemplate(this));
}
//TODO: sorta - at least their fx queue has started the re-rendering
self.trigger("columns-rendered", sortedAndFiltered, self);
this.trigger("columns-rendered", sortedAndFiltered, this);
if (self.datasetSearch && sortedAndFiltered.length <= 1) {
} else {
if (!this.datasetSearch || sortedAndFiltered.length > 1) {
// check for in-view, hda lazy-loading if so
self.checkColumnsInView();
this.checkColumnsInView();
// the first, current column has position: fixed and flex css will not apply - adjust height manually
self._recalcFirstColumnHeight();
this._recalcFirstColumnHeight();
}
return sortedAndFiltered;
},
@@ -817,8 +799,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
},
toggleDeletedDatasets: function(show) {
show = show !== undefined ? show : false;
var multipanel = this;
multipanel.sortedFilteredColumns().forEach((column, i) => {
this.sortedFilteredColumns().forEach((column, i) => {
_.delay(() => {
column.panel.toggleShowDeleted(show, false);
}, i * 200);
@@ -831,8 +812,7 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
},
toggleHiddenDatasets: function(show) {
show = show !== undefined ? show : false;
var multipanel = this;
multipanel.sortedFilteredColumns().forEach((column, i) => {
this.sortedFilteredColumns().forEach((column, i) => {
_.delay(() => {
column.panel.toggleShowHidden(show, false);
}, i * 200);
@@ -841,12 +821,11 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** change the collection order and re-fetch when the drop down in the options menu is changed */
_chooseOrder: function(ev) {
var multipanel = this;
var collection = multipanel.collection;
var collection = this.collection;
var orderKey = $(ev.currentTarget).data("order");
// set the sort order text also
multipanel.$(".current-order").text(multipanel.orderDescriptions[orderKey]);
multipanel.toggleOptionsPopover();
this.$(".current-order").text(this.orderDescriptions[orderKey]);
this.toggleOptionsPopover();
// set the order and re-fetch using the new order, saving the current history as the first
collection.setOrder(orderKey);
var currentHistoryModel = collection.slice(0, 1);
@@ -854,12 +833,12 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
collection.unshift(currentHistoryModel, {
silent: true
});
multipanel.createColumns();
this.createColumns();
// need to clear this or previously fetched contents won't refetch now (bc of named queue)
multipanel.hdaQueue.clear();
multipanel.render();
this.hdaQueue.clear();
this.render();
});
multipanel.once("columns-rendered", multipanel._scrollLeft);
this.once("columns-rendered", this._scrollLeft);
//TODO: check allFetched and do not reset if so - just sort instead
},
@@ -871,70 +850,69 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
/** Set up any view plugins */
setUpBehaviors: function() {
var multipanel = this;
multipanel._moreOptionsPopover();
this._moreOptionsPopover();
// input to search histories
multipanel.$("#search-histories").searchInput({
this.$("#search-histories").searchInput({
name: "search-histories",
placeholder: _l("search histories"),
onfirstsearch: function(searchFor) {
multipanel.$("#search-histories").searchInput("toggle-loading");
multipanel.renderInfo(_l("loading all histories for search"));
multipanel.collection.fetchAll().done(() => {
multipanel.$("#search-histories").searchInput("toggle-loading");
multipanel.renderInfo("");
onfirstsearch: searchFor => {
this.$("#search-histories").searchInput("toggle-loading");
this.renderInfo(_l("loading all histories for search"));
this.collection.fetchAll().done(() => {
this.$("#search-histories").searchInput("toggle-loading");
this.renderInfo("");
});
},
onsearch: function(searchFor) {
multipanel.historySearch = searchFor;
multipanel.filters = [
function() {
return this.model.matchesAll(multipanel.historySearch);
onsearch: searchFor => {
this.historySearch = searchFor;
this.filters = [
() => {
return this.model.matchesAll(this.historySearch);
}
];
multipanel.renderColumns(0);
this.renderColumns(0);
},
onclear: function(searchFor) {
multipanel.historySearch = null;
onclear: searchFor => {
this.historySearch = null;
//TODO: remove specifically not just reset
multipanel.filters = [];
multipanel.renderColumns(0);
this.filters = [];
this.renderColumns(0);
}
});
// input to search datasets
multipanel.$("#search-datasets").searchInput({
this.$("#search-datasets").searchInput({
name: "search-datasets",
placeholder: _l("search all datasets"),
onfirstsearch: function(searchFor) {
multipanel.hdaQueue.clear();
multipanel.$("#search-datasets").searchInput("toggle-loading");
multipanel.datasetSearch = searchFor;
multipanel.sortedFilteredColumns().forEach(column => {
onfirstsearch: searchFor => {
this.hdaQueue.clear();
this.$("#search-datasets").searchInput("toggle-loading");
this.datasetSearch = searchFor;
this.sortedFilteredColumns().forEach(column => {
column.panel.searchItems(searchFor);
// load details for them that need
multipanel.queueHdaFetchDetails(column);
this.queueHdaFetchDetails(column);
});
multipanel.hdaQueue.progress(progress => {
multipanel.renderInfo([_l("searching"), progress.curr + 1, _l("of"), progress.total].join(" "));
this.hdaQueue.progress(progress => {
this.renderInfo([_l("searching"), progress.curr + 1, _l("of"), progress.total].join(" "));
});
multipanel.hdaQueue.deferred.done(() => {
multipanel.renderInfo("");
multipanel.$("#search-datasets").searchInput("toggle-loading");
this.hdaQueue.deferred.done(() => {
this.renderInfo("");
this.$("#search-datasets").searchInput("toggle-loading");
});
},
onsearch: function(searchFor) {
multipanel.datasetSearch = searchFor;
multipanel.sortedFilteredColumns().forEach(column => {
onsearch: searchFor => {
this.datasetSearch = searchFor;
this.sortedFilteredColumns().forEach(column => {
column.panel.searchItems(searchFor);
});
},
onclear: function(searchFor) {
multipanel.datasetSearch = null;
multipanel.sortedFilteredColumns().forEach(column => {
onclear: searchFor => {
this.datasetSearch = null;
this.sortedFilteredColumns().forEach(column => {
column.panel.clearSearch();
});
}
@@ -942,15 +920,15 @@ var MultiPanelColumns = Backbone.View.extend(baseMVC.LoggableMixin).extend({
// resize first (fixed position) column on page resize
$(window).resize(() => {
multipanel._recalcFirstColumnHeight();
this._recalcFirstColumnHeight();
});
// when scrolling - check for histories now in view: they will fire 'in-view' and queueHdaLoading if necc.
//TODO:?? might be able to simplify and not use pub-sub
var debouncedInView = _.debounce(function _debouncedInner() {
var viewport = multipanel._viewport();
multipanel.checkColumnsInView(viewport);
multipanel.checkForEndOfScroll(viewport);
var debouncedInView = _.debounce(() => {
var viewport = this._viewport();
this.checkColumnsInView(viewport);
this.checkForEndOfScroll(viewport);
}, 100);
this.$(".middle")
.parent()
+3 -1
View File
@@ -507,7 +507,7 @@ class HistoriesController(BaseAPIController, ExportsHistoryMixin, ImportsHistory
return self.serve_ready_history_export(trans, jeha)
@expose_api
def get_custom_builds_metadata(self, trans, id, payload={}, **kwd):
def get_custom_builds_metadata(self, trans, id, payload=None, **kwd):
"""
GET /api/histories/{id}/custom_builds_metadata
Returns meta data for custom builds.
@@ -515,6 +515,8 @@ class HistoriesController(BaseAPIController, ExportsHistoryMixin, ImportsHistory
:param id: the encoded history id
:type id: str
"""
if payload is None:
payload = {}
history = self.history_manager.get_accessible(self.decode_id(id), trans.user, current_history=trans.history)
installed_builds = []
for build in glob.glob(os.path.join(trans.app.config.len_file_path, "*.len")):