Refactored pagination/sorting/filtering of gcode files into own configurable listHelper now used to provide pagination etc to both gcode and timelapse file list.
parent
dae1c0367a
commit
1fbb73e448
|
@ -286,7 +286,6 @@ def getTimelapseData():
|
||||||
|
|
||||||
files = timelapse.getFinishedTimelapses()
|
files = timelapse.getFinishedTimelapses()
|
||||||
for file in files:
|
for file in files:
|
||||||
file["size"] = util.getFormattedSize(file["size"])
|
|
||||||
file["url"] = url_for("downloadTimelapse", filename=file["name"])
|
file["url"] = url_for("downloadTimelapse", filename=file["name"])
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -679,64 +679,38 @@ function TerminalViewModel() {
|
||||||
function GcodeFilesViewModel() {
|
function GcodeFilesViewModel() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.allFiles = [];
|
// initialize list helper
|
||||||
|
self.listHelper = new ItemListHelper(
|
||||||
self.files = ko.observableArray([]);
|
"gcodeFiles",
|
||||||
self.pageSize = ko.observable(CONFIG_FILESPERPAGE);
|
{
|
||||||
self.currentPage = ko.observable(0);
|
"name": function(a, b) {
|
||||||
self.currentSorting = ko.observable("name");
|
// sorts ascending
|
||||||
self.currentFilters = ko.observableArray([]);
|
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
|
||||||
|
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
|
||||||
if( localStorage["currentSorting"] )
|
return 0;
|
||||||
self.currentSorting( localStorage["currentSorting"] );
|
},
|
||||||
|
"upload": function(a, b) {
|
||||||
if( localStorage["filterPrinted"] == 1 ) {
|
// sorts descending
|
||||||
var filters = self.currentFilters();
|
if (a["date"] > b["date"]) return -1;
|
||||||
filters.push("printed");
|
if (a["date"] < b["date"]) return 1;
|
||||||
self.currentFilters(_.uniq(filters));
|
return 0;
|
||||||
|
},
|
||||||
|
"size": function(a, b) {
|
||||||
|
// sorts descending
|
||||||
|
if (a["bytes"] > b["bytes"]) return -1;
|
||||||
|
if (a["bytes"] < b["bytes"]) return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
self.paginatedFiles = ko.dependentObservable(function() {
|
{
|
||||||
if (self.files() == undefined) {
|
"printed": function(file) {
|
||||||
return [];
|
return !(file["prints"] && file["prints"]["success"] && file["prints"]["success"] > 0);
|
||||||
} else {
|
|
||||||
var from = Math.max(self.currentPage() * self.pageSize(), 0);
|
|
||||||
var to = Math.min(from + self.pageSize(), self.files().length);
|
|
||||||
return self.files().slice(from, to);
|
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
self.lastPage = ko.dependentObservable(function() {
|
"name",
|
||||||
return Math.ceil(self.files().length / self.pageSize()) - 1;
|
[],
|
||||||
})
|
CONFIG_GCODEFILESPERPAGE
|
||||||
self.pages = ko.dependentObservable(function() {
|
)
|
||||||
var pages = [];
|
|
||||||
if (self.lastPage() < 7) {
|
|
||||||
for (var i = 0; i < self.lastPage() + 1; i++) {
|
|
||||||
pages.push({ number: i, text: i+1 });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pages.push({ number: 0, text: 1 });
|
|
||||||
if (self.currentPage() < 5) {
|
|
||||||
for (var i = 1; i < 5; i++) {
|
|
||||||
pages.push({ number: i, text: i+1 });
|
|
||||||
}
|
|
||||||
pages.push({ number: -1, text: "…"});
|
|
||||||
} else if (self.currentPage() > self.lastPage() - 5) {
|
|
||||||
pages.push({ number: -1, text: "…"});
|
|
||||||
for (var i = self.lastPage() - 4; i < self.lastPage(); i++) {
|
|
||||||
pages.push({ number: i, text: i+1 });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pages.push({ number: -1, text: "…"});
|
|
||||||
for (var i = self.currentPage() - 1; i <= self.currentPage() + 1; i++) {
|
|
||||||
pages.push({ number: i, text: i+1 });
|
|
||||||
}
|
|
||||||
pages.push({ number: -1, text: "…"});
|
|
||||||
}
|
|
||||||
pages.push({ number: self.lastPage(), text: self.lastPage() + 1})
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
})
|
|
||||||
|
|
||||||
self.requestData = function() {
|
self.requestData = function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -750,12 +724,11 @@ function GcodeFilesViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fromResponse = function(response) {
|
self.fromResponse = function(response) {
|
||||||
self.allFiles = response.files;
|
self.listHelper.updateItems(response.files);
|
||||||
self._updateFiles();
|
|
||||||
|
|
||||||
if (response.filename) {
|
if (response.filename) {
|
||||||
// got a file to scroll to
|
// got a file to scroll to
|
||||||
self.switchToFile(response.filename);
|
self.listHelper.switchToItem(function(item) {return item.name == response.filename});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,131 +751,6 @@ function GcodeFilesViewModel() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.switchToFile = function(filename) {
|
|
||||||
var pos = -1;
|
|
||||||
var filelist = self.files();
|
|
||||||
for (var i = 0; i < filelist.length; i++) {
|
|
||||||
if (filelist[i].name == filename) {
|
|
||||||
pos = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > -1) {
|
|
||||||
var page = Math.floor(pos / self.pageSize());
|
|
||||||
self.changePage(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.changePage = function(newPage) {
|
|
||||||
if (newPage < 0 || newPage > self.lastPage())
|
|
||||||
return;
|
|
||||||
self.currentPage(newPage);
|
|
||||||
}
|
|
||||||
self.prevPage = function() {
|
|
||||||
if (self.currentPage() > 0) {
|
|
||||||
self.currentPage(self.currentPage() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.nextPage = function() {
|
|
||||||
if (self.currentPage() < self.lastPage()) {
|
|
||||||
self.currentPage(self.currentPage() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.changeSorting = function(sorting) {
|
|
||||||
if (sorting != "name" && sorting != "upload" && sorting != "size")
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.currentSorting(sorting);
|
|
||||||
localStorage["currentSorting"] = self.currentSorting(); //store setting in local storage
|
|
||||||
self.changePage(0);
|
|
||||||
self._updateFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.toggleFilter = function(filter) {
|
|
||||||
if (_.contains(self.currentFilters(), filter)) {
|
|
||||||
self.removeFilter(filter);
|
|
||||||
} else {
|
|
||||||
self.addFilter(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.addFilter = function(filter) {
|
|
||||||
if (filter != "printed")
|
|
||||||
return;
|
|
||||||
|
|
||||||
var filters = self.currentFilters();
|
|
||||||
filters.push(filter);
|
|
||||||
self.currentFilters(_.uniq(filters));
|
|
||||||
localStorage["filterPrinted"] = 1;
|
|
||||||
self._updateFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.removeFilter = function(filter) {
|
|
||||||
if (filter != "printed")
|
|
||||||
return;
|
|
||||||
|
|
||||||
self.currentFilters(_.without(self.currentFilters(), filter));
|
|
||||||
localStorage["filterPrinted"] = 0;
|
|
||||||
self._updateFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
self._updateFiles = function() {
|
|
||||||
// determine comparator
|
|
||||||
var comparator = undefined;
|
|
||||||
if (self.currentSorting() == "name") {
|
|
||||||
comparator = function(a, b) {
|
|
||||||
// sorts ascending
|
|
||||||
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
|
|
||||||
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else if (self.currentSorting() == "upload") {
|
|
||||||
comparator = function(a, b) {
|
|
||||||
// sorts descending
|
|
||||||
if (a["date"] > b["date"]) return -1;
|
|
||||||
if (a["date"] < b["date"]) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else if (self.currentSorting() == "size") {
|
|
||||||
comparator = function(a, b) {
|
|
||||||
// sorts descending
|
|
||||||
if (a["bytes"] > b["bytes"]) return -1;
|
|
||||||
if (a["bytes"] < b["bytes"]) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// work on all files
|
|
||||||
var result = self.allFiles;
|
|
||||||
|
|
||||||
// filter if necessary
|
|
||||||
var filters = self.currentFilters();
|
|
||||||
for (var i = 0; i < filters.length; i++) {
|
|
||||||
var filterFunction = undefined;
|
|
||||||
var filter = filters[i];
|
|
||||||
switch (filter) {
|
|
||||||
case "printed": {
|
|
||||||
filterFunction = function(file) {
|
|
||||||
return !(file["prints"] && file["prints"]["success"] && file["prints"]["success"] > 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof filterFunction !== undefined)
|
|
||||||
result = _.filter(result, filterFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort if necessary
|
|
||||||
if (typeof comparator !== undefined)
|
|
||||||
result.sort(comparator);
|
|
||||||
|
|
||||||
// set result list
|
|
||||||
self.files(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.getPopoverContent = function(data) {
|
self.getPopoverContent = function(data) {
|
||||||
var output = "<p><strong>Uploaded:</strong> " + data["date"] + "</p>";
|
var output = "<p><strong>Uploaded:</strong> " + data["date"] + "</p>";
|
||||||
if (data["gcodeAnalysis"]) {
|
if (data["gcodeAnalysis"]) {
|
||||||
|
@ -933,7 +781,6 @@ function WebcamViewModel() {
|
||||||
|
|
||||||
self.timelapseType = ko.observable(undefined);
|
self.timelapseType = ko.observable(undefined);
|
||||||
self.timelapseTimedInterval = ko.observable(undefined);
|
self.timelapseTimedInterval = ko.observable(undefined);
|
||||||
self.files = ko.observableArray([]);
|
|
||||||
|
|
||||||
self.isErrorOrClosed = ko.observable(undefined);
|
self.isErrorOrClosed = ko.observable(undefined);
|
||||||
self.isOperational = ko.observable(undefined);
|
self.isOperational = ko.observable(undefined);
|
||||||
|
@ -951,6 +798,36 @@ function WebcamViewModel() {
|
||||||
self.requestData();
|
self.requestData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// initialize list helper
|
||||||
|
self.listHelper = new ItemListHelper(
|
||||||
|
"timelapseFiles",
|
||||||
|
{
|
||||||
|
"name": function(a, b) {
|
||||||
|
// sorts ascending
|
||||||
|
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1;
|
||||||
|
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1;
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
"creation": function(a, b) {
|
||||||
|
// sorts descending
|
||||||
|
if (a["date"] > b["date"]) return -1;
|
||||||
|
if (a["date"] < b["date"]) return 1;
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
"size": function(a, b) {
|
||||||
|
// sorts descending
|
||||||
|
if (a["bytes"] > b["bytes"]) return -1;
|
||||||
|
if (a["bytes"] < b["bytes"]) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
"name",
|
||||||
|
[],
|
||||||
|
CONFIG_TIMELAPSEFILESPERPAGE
|
||||||
|
)
|
||||||
|
|
||||||
self.requestData = function() {
|
self.requestData = function() {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: AJAX_BASEURL + "timelapse",
|
url: AJAX_BASEURL + "timelapse",
|
||||||
|
@ -962,8 +839,8 @@ function WebcamViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fromResponse = function(response) {
|
self.fromResponse = function(response) {
|
||||||
self.timelapseType(response.type)
|
self.timelapseType(response.type);
|
||||||
self.files(response.files)
|
self.listHelper.updateItems(response.files);
|
||||||
|
|
||||||
if (response.type == "timed" && response.config && response.config.interval) {
|
if (response.type == "timed" && response.config && response.config.interval) {
|
||||||
self.timelapseTimedInterval(response.config.interval)
|
self.timelapseTimedInterval(response.config.interval)
|
||||||
|
@ -1089,7 +966,7 @@ function SettingsViewModel() {
|
||||||
self.appearance_color = ko.observable(undefined);
|
self.appearance_color = ko.observable(undefined);
|
||||||
|
|
||||||
/* I did attempt to allow arbitrary gradients but cross browser support via knockout or jquery was going to be horrible */
|
/* I did attempt to allow arbitrary gradients but cross browser support via knockout or jquery was going to be horrible */
|
||||||
self.appearance_available_colors = ko.observable(["white", "red", "orange", "yellow", "green", "blue", "violet"]);
|
self.appearance_available_colors = ko.observable(["default", "red", "orange", "yellow", "green", "blue", "violet"]);
|
||||||
|
|
||||||
self.printer_movementSpeedX = ko.observable(undefined);
|
self.printer_movementSpeedX = ko.observable(undefined);
|
||||||
self.printer_movementSpeedY = ko.observable(undefined);
|
self.printer_movementSpeedY = ko.observable(undefined);
|
||||||
|
@ -1265,6 +1142,231 @@ function DataUpdater(connectionViewModel, printerStateViewModel, temperatureView
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ItemListHelper(listType, supportedSorting, supportedFilters, defaultSorting, defaultFilters, filesPerPage) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.listType = listType;
|
||||||
|
self.supportedSorting = supportedSorting;
|
||||||
|
self.supportedFilters = supportedFilters;
|
||||||
|
self.defaultSorting = defaultSorting;
|
||||||
|
self.defaultFilters = defaultFilters;
|
||||||
|
|
||||||
|
self.allItems = [];
|
||||||
|
self.items = ko.observableArray([]);
|
||||||
|
self.pageSize = ko.observable(filesPerPage);
|
||||||
|
self.currentPage = ko.observable(0);
|
||||||
|
self.currentSorting = ko.observable(self.defaultSorting);
|
||||||
|
self.currentFilters = ko.observableArray(self.defaultFilters);
|
||||||
|
|
||||||
|
//~~ item handling
|
||||||
|
|
||||||
|
self.updateItems = function(items) {
|
||||||
|
self.allItems = items;
|
||||||
|
self._updateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
//~~ pagination
|
||||||
|
|
||||||
|
self.paginatedItems = ko.dependentObservable(function() {
|
||||||
|
if (self.items() == undefined) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
var from = Math.max(self.currentPage() * self.pageSize(), 0);
|
||||||
|
var to = Math.min(from + self.pageSize(), self.items().length);
|
||||||
|
return self.items().slice(from, to);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.lastPage = ko.dependentObservable(function() {
|
||||||
|
return Math.ceil(self.items().length / self.pageSize()) - 1;
|
||||||
|
})
|
||||||
|
self.pages = ko.dependentObservable(function() {
|
||||||
|
var pages = [];
|
||||||
|
if (self.lastPage() < 7) {
|
||||||
|
for (var i = 0; i < self.lastPage() + 1; i++) {
|
||||||
|
pages.push({ number: i, text: i+1 });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pages.push({ number: 0, text: 1 });
|
||||||
|
if (self.currentPage() < 5) {
|
||||||
|
for (var i = 1; i < 5; i++) {
|
||||||
|
pages.push({ number: i, text: i+1 });
|
||||||
|
}
|
||||||
|
pages.push({ number: -1, text: "…"});
|
||||||
|
} else if (self.currentPage() > self.lastPage() - 5) {
|
||||||
|
pages.push({ number: -1, text: "…"});
|
||||||
|
for (var i = self.lastPage() - 4; i < self.lastPage(); i++) {
|
||||||
|
pages.push({ number: i, text: i+1 });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pages.push({ number: -1, text: "…"});
|
||||||
|
for (var i = self.currentPage() - 1; i <= self.currentPage() + 1; i++) {
|
||||||
|
pages.push({ number: i, text: i+1 });
|
||||||
|
}
|
||||||
|
pages.push({ number: -1, text: "…"});
|
||||||
|
}
|
||||||
|
pages.push({ number: self.lastPage(), text: self.lastPage() + 1})
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
})
|
||||||
|
|
||||||
|
self.switchToItem = function(matcher) {
|
||||||
|
var pos = -1;
|
||||||
|
var itemList = self.items();
|
||||||
|
for (var i = 0; i < itemList.length; i++) {
|
||||||
|
if (matcher(itemList[i])) {
|
||||||
|
pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos > -1) {
|
||||||
|
var page = Math.floor(pos / self.pageSize());
|
||||||
|
self.changePage(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.changePage = function(newPage) {
|
||||||
|
if (newPage < 0 || newPage > self.lastPage())
|
||||||
|
return;
|
||||||
|
self.currentPage(newPage);
|
||||||
|
}
|
||||||
|
self.prevPage = function() {
|
||||||
|
if (self.currentPage() > 0) {
|
||||||
|
self.currentPage(self.currentPage() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.nextPage = function() {
|
||||||
|
if (self.currentPage() < self.lastPage()) {
|
||||||
|
self.currentPage(self.currentPage() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//~~ sorting
|
||||||
|
|
||||||
|
self.changeSorting = function(sorting) {
|
||||||
|
if (!_.contains(_.keys(self.supportedSorting), sorting))
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.currentSorting(sorting);
|
||||||
|
self._saveCurrentSortingToLocalStorage();
|
||||||
|
|
||||||
|
self.changePage(0);
|
||||||
|
self._updateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
//~~ filtering
|
||||||
|
|
||||||
|
self.toggleFilter = function(filter) {
|
||||||
|
if (!_.contains(_.keys(self.supportedFilters), filter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_.contains(self.currentFilters(), filter)) {
|
||||||
|
self.removeFilter(filter);
|
||||||
|
} else {
|
||||||
|
self.addFilter(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addFilter = function(filter) {
|
||||||
|
if (!_.contains(_.keys(self.supportedFilters), filter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var filters = self.currentFilters();
|
||||||
|
filters.push(filter);
|
||||||
|
self.currentFilters(filters);
|
||||||
|
self._saveCurrentFiltersToLocalStorage();
|
||||||
|
|
||||||
|
self._updateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.removeFilter = function(filter) {
|
||||||
|
if (filter != "printed")
|
||||||
|
return;
|
||||||
|
|
||||||
|
var filters = self.currentFilters();
|
||||||
|
filters.pop(filter);
|
||||||
|
self.currentFilters(filters);
|
||||||
|
self._saveCurrentFiltersToLocalStorage();
|
||||||
|
|
||||||
|
self._updateItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
//~~ update for sorted and filtered view
|
||||||
|
|
||||||
|
self._updateItems = function() {
|
||||||
|
// determine comparator
|
||||||
|
var comparator = undefined;
|
||||||
|
var currentSorting = self.currentSorting();
|
||||||
|
if (typeof currentSorting !== undefined && typeof self.supportedSorting[currentSorting] !== undefined) {
|
||||||
|
comparator = self.supportedSorting[currentSorting];
|
||||||
|
}
|
||||||
|
|
||||||
|
// work on all items
|
||||||
|
var result = self.allItems;
|
||||||
|
|
||||||
|
// filter if necessary
|
||||||
|
var filters = self.currentFilters();
|
||||||
|
_.each(filters, function(filter) {
|
||||||
|
if (typeof filter !== undefined && typeof supportedFilters[filter] !== undefined)
|
||||||
|
result = _.filter(result, supportedFilters[filter]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// sort if necessary
|
||||||
|
if (typeof comparator !== undefined)
|
||||||
|
result.sort(comparator);
|
||||||
|
|
||||||
|
// set result list
|
||||||
|
self.items(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~~ local storage
|
||||||
|
|
||||||
|
self._saveCurrentSortingToLocalStorage = function() {
|
||||||
|
self._initializeLocalStorage();
|
||||||
|
|
||||||
|
var currentSorting = self.currentSorting();
|
||||||
|
if (currentSorting !== undefined)
|
||||||
|
localStorage[self.listType]["currentSorting"] = currentSorting;
|
||||||
|
else
|
||||||
|
localStorage[self.listType]["currentSorting"] = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
self._loadCurrentSortingFromLocalStorage = function() {
|
||||||
|
self._initializeLocalStorage();
|
||||||
|
|
||||||
|
if (_.contains(_.keys(supportedSorting), localStorage[self.listType]["currentSorting"]))
|
||||||
|
self.currentSorting(localStorage[self.listType]["currentSorting"]);
|
||||||
|
else
|
||||||
|
self.currentSorting(defaultSorting);
|
||||||
|
}
|
||||||
|
|
||||||
|
self._saveCurrentFiltersToLocalStorage = function() {
|
||||||
|
self._initializeLocalStorage();
|
||||||
|
|
||||||
|
var filters = _.intersection(_.keys(self.supportedFilters), self.currentFilters());
|
||||||
|
localStorage[self.listType]["currentFilters"] = filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
self._loadCurrentFiltersFromLocalStorage = function() {
|
||||||
|
self._initializeLocalStorage();
|
||||||
|
|
||||||
|
self.currentFilters(_.intersection(_.keys(self.supportedFilters), localStorage[self.listType, "currentFilters"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
self._initializeLocalStorage = function() {
|
||||||
|
if (localStorage[self.listType] !== undefined)
|
||||||
|
return;
|
||||||
|
|
||||||
|
localStorage[self.listType] = {
|
||||||
|
"currentSorting": self.defaultSorting,
|
||||||
|
"currentFilters": self.defaultFilters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self._loadCurrentFiltersFromLocalStorage();
|
||||||
|
self._loadCurrentSortingFromLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
//~~ View models
|
//~~ View models
|
||||||
|
@ -1398,10 +1500,17 @@ $(function() {
|
||||||
done: function (e, data) {
|
done: function (e, data) {
|
||||||
gcodeFilesViewModel.fromResponse(data.result);
|
gcodeFilesViewModel.fromResponse(data.result);
|
||||||
$("#gcode_upload_progress .bar").css("width", "0%");
|
$("#gcode_upload_progress .bar").css("width", "0%");
|
||||||
|
$("#gcode_upload_progress").removeClass("progress-striped").removeClass("active");
|
||||||
|
$("#gcode_upload_progress .bar").text("");
|
||||||
},
|
},
|
||||||
progressall: function (e, data) {
|
progressall: function (e, data) {
|
||||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||||
$("#gcode_upload_progress .bar").css("width", progress + "%");
|
$("#gcode_upload_progress .bar").css("width", progress + "%");
|
||||||
|
$("#gcode_upload_progress .bar").text("Uploading ...");
|
||||||
|
if (progress >= 100) {
|
||||||
|
$("#gcode_upload_progress").addClass("progress-striped").addClass("active");
|
||||||
|
$("#gcode_upload_progress .bar").text("Saving ...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,20 @@
|
||||||
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet" media="screen">
|
||||||
<link href="{{ url_for('static', filename='css/jquery.fileupload-ui.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/jquery.fileupload-ui.css') }}" rel="stylesheet" media="screen">
|
||||||
<link href="{{ url_for('static', filename='css/ui.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/ui.css') }}" rel="stylesheet" media="screen">
|
||||||
|
<!--link href="{{ url_for('static', filename='css/octoprint.css') }}" rel="stylesheet" type="stylesheet/less" media="screen"-->
|
||||||
<link href="{{ url_for('static', filename='gcodeviewer/css/cupertino/jquery-ui-1.9.0.custom.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='gcodeviewer/css/cupertino/jquery-ui-1.9.0.custom.css') }}" rel="stylesheet" media="screen">
|
||||||
<link href="{{ url_for('static', filename='gcodeviewer/css/style.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='gcodeviewer/css/style.css') }}" rel="stylesheet" media="screen">
|
||||||
|
|
||||||
<script lang="javascript">
|
<script lang="javascript">
|
||||||
var AJAX_BASEURL = "/ajax/";
|
var AJAX_BASEURL = "/ajax/";
|
||||||
var CONFIG_FILESPERPAGE = 5;
|
var CONFIG_GCODEFILESPERPAGE = 5;
|
||||||
|
var CONFIG_TIMELAPSEFILESPERPAGE = 10;
|
||||||
var CONFIG_WEBCAM_STREAM = "{{ webcamStream }}";
|
var CONFIG_WEBCAM_STREAM = "{{ webcamStream }}";
|
||||||
|
|
||||||
var WEB_SOCKET_SWF_LOCATION = "{{ url_for('static', filename='js/WebSocketMain.swf') }}";
|
var WEB_SOCKET_SWF_LOCATION = "{{ url_for('static', filename='js/WebSocketMain.swf') }}";
|
||||||
var WEB_SOCKET_DEBUG = true;
|
var WEB_SOCKET_DEBUG = true;
|
||||||
</script>
|
</script>
|
||||||
|
<script src="{{ url_for('static', filename='js/less-1.3.3.min.js') }}" type="text/javascript"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="navbar" class="navbar navbar-fixed-top">
|
<div id="navbar" class="navbar navbar-fixed-top">
|
||||||
|
@ -91,11 +94,11 @@
|
||||||
<i class="icon-wrench"></i>
|
<i class="icon-wrench"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#" data-bind="click: function() { $root.changeSorting('name'); }"><i class="icon-ok" data-bind="style: {visibility: currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> Sort by name (ascending)</a></li>
|
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('name'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> Sort by name (ascending)</a></li>
|
||||||
<li><a href="#" data-bind="click: function() { $root.changeSorting('upload'); }"><i class="icon-ok" data-bind="style: {visibility: currentSorting() == 'upload' ? 'visible' : 'hidden'}"></i> Sort by upload date (descending)</a></li>
|
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('upload'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'upload' ? 'visible' : 'hidden'}"></i> Sort by upload date (descending)</a></li>
|
||||||
<li><a href="#" data-bind="click: function() { $root.changeSorting('size'); }"><i class="icon-ok" data-bind="style: {visibility: currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> Sort by file size (descending)</a></li>
|
<li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('size'); }"><i class="icon-ok" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> Sort by file size (descending)</a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="#" data-bind="click: function() { $root.toggleFilter('printed'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(currentFilters(), 'printed') ? 'visible' : 'hidden'}"></i> Hide successfully printed files</a></li>
|
<li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('printed'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'printed') ? 'visible' : 'hidden'}"></i> Hide successfully printed files</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,7 +112,7 @@
|
||||||
<th class="gcode_files_action">Action</th>
|
<th class="gcode_files_action">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-bind="foreach: paginatedFiles">
|
<tbody data-bind="foreach: listHelper.paginatedItems">
|
||||||
<tr data-bind="css: $root.getSuccessClass($data), popover: { title: name, animation: true, html: true, placement: 'right', trigger: 'hover', delay: 0, content: $root.getPopoverContent($data), html: true }">
|
<tr data-bind="css: $root.getSuccessClass($data), popover: { title: name, animation: true, html: true, placement: 'right', trigger: 'hover', delay: 0, content: $root.getPopoverContent($data), html: true }">
|
||||||
<td class="gcode_files_name" data-bind="text: name"></td>
|
<td class="gcode_files_name" data-bind="text: name"></td>
|
||||||
<td class="gcode_files_size" data-bind="text: size"></td>
|
<td class="gcode_files_size" data-bind="text: size"></td>
|
||||||
|
@ -119,13 +122,13 @@
|
||||||
</table>
|
</table>
|
||||||
<div class="pagination pagination-mini pagination-centered">
|
<div class="pagination pagination-mini pagination-centered">
|
||||||
<ul>
|
<ul>
|
||||||
<li data-bind="css: {disabled: currentPage() === 0}"><a href="#" data-bind="click: prevPage">«</a></li>
|
<li data-bind="css: {disabled: listHelper.currentPage() === 0}"><a href="#" data-bind="click: listHelper.prevPage">«</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul data-bind="foreach: pages">
|
<ul data-bind="foreach: listHelper.pages">
|
||||||
<li data-bind="css: { active: $data.number === $root.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.changePage($data.number); }"></a></li>
|
<li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li data-bind="css: {disabled: currentPage() === lastPage()}"><a href="#" data-bind="click: nextPage">»</a></li>
|
<li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}"><a href="#" data-bind="click: listHelper.nextPage">»</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<span class="btn btn-primary btn-block fileinput-button" style="margin-bottom: 10px">
|
<span class="btn btn-primary btn-block fileinput-button" style="margin-bottom: 10px">
|
||||||
|
@ -134,7 +137,7 @@
|
||||||
<input id="gcode_upload" type="file" name="gcode_file" class="fileinput-button" data-url="/ajax/gcodefiles/upload">
|
<input id="gcode_upload" type="file" name="gcode_file" class="fileinput-button" data-url="/ajax/gcodefiles/upload">
|
||||||
</span>
|
</span>
|
||||||
<div id="gcode_upload_progress" class="progress" style="width: 100%;">
|
<div id="gcode_upload_progress" class="progress" style="width: 100%;">
|
||||||
<div class="bar" style="width: 0%"></div>
|
<div class="bar" style="width: 0%">Loading ...</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<small>Hint: You can also drag and drop files on this page to upload them.</small>
|
<small>Hint: You can also drag and drop files on this page to upload them.</small>
|
||||||
|
@ -469,6 +472,9 @@
|
||||||
|
|
||||||
<h1>Finished Timelapses</h1>
|
<h1>Finished Timelapses</h1>
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<small>Sort by: <a href="#" data-bind="click: function() { listHelper.changeSorting('name'); }">Name (ascending)</a> | <a href="#" data-bind="click: function() { listHelper.changeSorting('creation'); }">Creation date (descending)</a> | <a href="#" data-bind="click: function() { listHelper.changeSorting('size'); }">Size (descending)</a></small>
|
||||||
|
</div>
|
||||||
<table class="table table-striped table-hover table-condensed table-hover" id="timelapse_files">
|
<table class="table table-striped table-hover table-condensed table-hover" id="timelapse_files">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -477,7 +483,7 @@
|
||||||
<th class="timelapse_files_action">Action</th>
|
<th class="timelapse_files_action">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody data-bind="foreach: files">
|
<tbody data-bind="foreach: listHelper.items">
|
||||||
<tr data-bind="attr: {title: name}">
|
<tr data-bind="attr: {title: name}">
|
||||||
<td class="timelapse_files_name" data-bind="text: name"></td>
|
<td class="timelapse_files_name" data-bind="text: name"></td>
|
||||||
<td class="timelapse_files_size" data-bind="text: size"></td>
|
<td class="timelapse_files_size" data-bind="text: size"></td>
|
||||||
|
@ -485,6 +491,17 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<div class="pagination pagination-mini pagination-centered">
|
||||||
|
<ul>
|
||||||
|
<li data-bind="css: {disabled: listHelper.currentPage() === 0}"><a href="#" data-bind="click: listHelper.prevPage">«</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul data-bind="foreach: listHelper.pages">
|
||||||
|
<li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a></li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}"><a href="#" data-bind="click: listHelper.nextPage">»</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -3,6 +3,7 @@ __author__ = "Gina Häußge <osd@foosel.net>"
|
||||||
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||||||
|
|
||||||
from octoprint.settings import settings
|
from octoprint.settings import settings
|
||||||
|
import octoprint.util as util
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
@ -10,6 +11,7 @@ import urllib
|
||||||
import time
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import datetime
|
||||||
|
|
||||||
def getFinishedTimelapses():
|
def getFinishedTimelapses():
|
||||||
files = []
|
files = []
|
||||||
|
@ -17,9 +19,12 @@ def getFinishedTimelapses():
|
||||||
for osFile in os.listdir(basedir):
|
for osFile in os.listdir(basedir):
|
||||||
if not fnmatch.fnmatch(osFile, "*.mpg"):
|
if not fnmatch.fnmatch(osFile, "*.mpg"):
|
||||||
continue
|
continue
|
||||||
|
statResult = os.stat(os.path.join(basedir, osFile))
|
||||||
files.append({
|
files.append({
|
||||||
"name": osFile,
|
"name": osFile,
|
||||||
"size": os.stat(os.path.join(basedir, osFile)).st_size
|
"size": util.getFormattedSize(statResult.st_size),
|
||||||
|
"bytes": statResult.st_size,
|
||||||
|
"date": util.getFormattedDateTime(datetime.datetime.fromtimestamp(statResult.st_ctime))
|
||||||
})
|
})
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue