diff --git a/.github/stale.yml b/.github/stale.yml index d1d5ed0b..07cd9424 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -8,7 +8,6 @@ exemptLabels: - "status: inNextRelease" - "status: inProgress" - "status: wontfix" - - "type: enhancement" # Label to use when marking an issue as stale staleLabel: "status: markedForAutoClose" # Comment to post when marking an issue as stale. Set to `false` to disable diff --git a/octoprint_SpoolManager/DatabaseManager.py b/octoprint_SpoolManager/DatabaseManager.py index a9befad0..86162c2a 100644 --- a/octoprint_SpoolManager/DatabaseManager.py +++ b/octoprint_SpoolManager/DatabaseManager.py @@ -24,8 +24,24 @@ # List all Models MODELS = [PluginMetaDataModel, SpoolModel] + + class DatabaseManager(object): + class DatabaseSettings: + useExternal = False + # Internal stuff + fileLocation = "" + backupFileLocation = "" + # External stuff + dialect = "postgresql" # sqlite, mysql, postgresql + host = "" + port = 0 + user = 0 + password = 0 + + + def __init__(self, parentLogger, sqlLoggingEnabled): self.sqlLoggingEnabled = sqlLoggingEnabled self._logger = logging.getLogger(parentLogger.name + "." + self.__class__.__name__) @@ -168,6 +184,25 @@ def _createDatabaseTables(self): ################################################################################################### public functions + + def buildDatabaseSettings(self, pluginSettings): + + databaseSettings = self.DatabaseSettings() + + # "databaseSettings"] = { + # "useExternal": "true", + # "type": "postgres", + # "host": "localhost", + # "port": 5432, + # "databaseName": "PrintJobDatabase", + # "user": "Olli", + # "password": "illO" + + + + return databaseSettings + pass + def getDatabaseFileLocation(self): return self._databaseFileLocation @@ -301,6 +336,12 @@ def loadAllSpoolsByQuery(self, tableQuery): myQuery = myQuery.order_by(SpoolModel.remainingWeight.desc()) else: myQuery = myQuery.order_by(SpoolModel.remainingWeight) + if ("material" == sortColumn): + if ("desc" == sortOrder): + myQuery = myQuery.order_by(SpoolModel.material.desc()) + else: + myQuery = myQuery.order_by(SpoolModel.material) + return myQuery diff --git a/octoprint_SpoolManager/__init__.py b/octoprint_SpoolManager/__init__.py index ddc6e1b9..8dbf1491 100644 --- a/octoprint_SpoolManager/__init__.py +++ b/octoprint_SpoolManager/__init__.py @@ -311,7 +311,7 @@ def _on_printJobFinished(self, printStatus, payload): self._databaseManager.saveModel(spoolModel) self._sendDataToClient(dict( - action="reloadTable" + action="reloadTable and sidebarSpools" )) pass @@ -448,13 +448,24 @@ def get_settings_defaults(self): ## Debugging settings[SettingsKeys.SETTINGS_KEY_SQL_LOGGING_ENABLED] = False + ## Database + settings["databaseSettings"] = { + "useExternal": "true", + "type": "postgres", + "host": "localhost", + "port": 5432, + "databaseName": "PrintJobDatabase", + "user": "Olli", + "password": "illO" + } + return settings ##~~ TemplatePlugin mixin def get_template_configs(self): return [ dict(type="tab", name="Spools"), - dict(type="settings", custom_bindings=True) + dict(type="settings", custom_bindings=True, name="Spool Manager") ] ##~~ AssetPlugin mixin @@ -498,7 +509,7 @@ def get_update_information(self): # version check: github repository type="github_release", - user="you", + user="OllisGit", repo="OctoPrint-SpoolManager", current=self._plugin_version, diff --git a/octoprint_SpoolManager/models/SpoolModel.py b/octoprint_SpoolManager/models/SpoolModel.py index ff195f98..e0cc347d 100644 --- a/octoprint_SpoolManager/models/SpoolModel.py +++ b/octoprint_SpoolManager/models/SpoolModel.py @@ -37,7 +37,7 @@ class SpoolModel(BaseModel): purchasedFrom = CharField(null=True) purchasedOn = DateField(null=True) cost = FloatField(null=True) - costUnit = CharField(null=True) + costUnit = CharField(null=True) # deprecated needs to be removed, value should be used from pluginSettings labels = TextField(null=True) diff --git a/octoprint_SpoolManager/static/js/ComponentFactory.js b/octoprint_SpoolManager/static/js/ComponentFactory.js index fb8e9fb5..a8192210 100644 --- a/octoprint_SpoolManager/static/js/ComponentFactory.js +++ b/octoprint_SpoolManager/static/js/ComponentFactory.js @@ -45,7 +45,8 @@ function ComponentFactory(pluginId) { } var componentViewModel = { - currentDateTime: ko.observable() + currentDateTime: ko.observable(), + isEnabled: ko.observable(true) } var elementSelector = "#" + elementId ; @@ -59,7 +60,9 @@ function ComponentFactory(pluginId) { }); $($(elementSelector).parent().find('span[class=add-on]')[0]).on('click', function () { - $(elementSelector).datetimepicker('show'); + if (componentViewModel.isEnabled() == true){ + $(elementSelector).datetimepicker('show'); + } }); diff --git a/octoprint_SpoolManager/static/js/SpoolManager-EditSpoolDialog.js b/octoprint_SpoolManager/static/js/SpoolManager-EditSpoolDialog.js index cad5e748..5a9a1302 100644 --- a/octoprint_SpoolManager/static/js/SpoolManager-EditSpoolDialog.js +++ b/octoprint_SpoolManager/static/js/SpoolManager-EditSpoolDialog.js @@ -157,7 +157,6 @@ function SpoolManagerEditSpoolDialog(){ if (editable == true){ - var colorViewModel = self.componentFactory.createColorPicker("filament-color-picker"); this.color = colorViewModel.selectedColor; this.color(DEFAULT_COLOR); // needed @@ -168,7 +167,6 @@ function SpoolManagerEditSpoolDialog(){ this.firstUse = firstUseViewModel.currentDateTime; this.lastUse = lastUseViewModel.currentDateTime; this.purchasedOn = purchasedOnViewModel.currentDateTime; - } self.labelsViewModel = self.componentFactory.createLabels("spool-labels-select", $('#spool-form')); @@ -534,6 +532,9 @@ function SpoolManagerEditSpoolDialog(){ alert("Displayname not entered!"); return; } + // workaround + self.spoolItemForEditing.costUnit(self.pluginSettings.currencySymbol()) + var noteText = self.noteEditor.getText(); var noteDeltaFormat = self.noteEditor.getContents(); var noteHtml = self.noteEditor.getHtml(); diff --git a/octoprint_SpoolManager/static/js/SpoolManager.js b/octoprint_SpoolManager/static/js/SpoolManager.js index bb1c70b1..69f28546 100644 --- a/octoprint_SpoolManager/static/js/SpoolManager.js +++ b/octoprint_SpoolManager/static/js/SpoolManager.js @@ -64,6 +64,7 @@ $(function() { self.loginState = parameters[0]; self.settingsViewModel = parameters[1]; self.printerStateViewModel = parameters[2]; + self.filesViewModel = parameters[3]; self.pluginSettings = null; @@ -92,6 +93,22 @@ $(function() { }; ///////////////////////////////////////////////////// START: SETTINGS + + self.showLocalBusyIndicator = ko.observable(false); + self.showExternalBusyIndicator = ko.observable(false); + $("#spoolmanger-settings-tab").find('a[data-toggle="tab"]').on('shown', function (e) { + var activatedTab = e.target.hash; // activated tab + var prevTab = e.relatedTarget.hash; // previous tab + console.info("PrevTab:" + prevTab + " ActiveTab:"+activatedTab); + + if ("#tab-spool-Storage" == activatedTab){ +// self.showLocalBusyIndicator(true); +// self.showExternalBusyIndicator(true); + } + }); + + + self.isFilamentManagerPluginAvailable = ko.observable(false); self.databaseFileLocation = ko.observable("hello"); @@ -268,6 +285,46 @@ $(function() { self.spoolDialog.showDialog(null, closeDialogHandler); } + + var TableAttributeVisibility = function (){ + this.displayName = ko.observable(true); + this.material = ko.observable(true); + this.lastFirstUse = ko.observable(true); + this.weight = ko.observable(true); + this.used = ko.observable(true); + this.note = ko.observable(true); + } + self.tableAttributeVisibility = new TableAttributeVisibility(); + + self.initTableVisibilities = function(){ + // load all settings from browser storage + if (!Modernizr.localstorage) { + // damn!!! + return false; + } + + assignVisibility = function(attributeName){ + var storageKey = "spoolmanager.table.visible." + attributeName; + if (localStorage[storageKey] == null){ + localStorage[storageKey] = true + } else { + self.tableAttributeVisibility[attributeName]( "true" == localStorage[storageKey]); + } + self.tableAttributeVisibility[attributeName].subscribe(function(newValue){ + localStorage[storageKey] = newValue; + }); + } + + assignVisibility("displayName"); + assignVisibility("material"); + assignVisibility("lastFirstUse"); + assignVisibility("weight"); + assignVisibility("used"); + assignVisibility("note"); + } + + + ///////////////////////////////////////////////////////////////////////////////////////////////// TABLE BEHAVIOR self.spoolItemTableHelper = new TableItemHelper(function(tableQuery, observableTableModel, observableTotalItemCount){ // api-call @@ -308,19 +365,18 @@ $(function() { ///////////////////////////////////////////////////////////////////////////////////////// OCTOPRINT PRINT-BUTTON - const startPrint = self.printerStateViewModel.print; - self.printerStateViewModel.print = function confirmSpoolSelectionBeforeStartPrint() { - + const origStartPrintFunction = self.printerStateViewModel.print; + const newStartPrintFunction = function confirmSpoolSelectionBeforeStartPrint() { // api-call self.apiClient.allowedToPrint(function(responseData){ var result = responseData.result; if ("startPrint" == result){ - startPrint(); + origStartPrintFunction(); } else { if ("noSpoolSelected" == result){ var check = confirm('Do you want to start the print without a selected spool?'); if (check == true) { - startPrint(); + origStartPrintFunction(); } return; } @@ -332,7 +388,7 @@ $(function() { if ("filamentNotEnough" == result){ var check = confirm('Not enough filament. Do you want to start the print anyway?'); if (check == true) { - startPrint(); + origStartPrintFunction(); } return; } @@ -340,19 +396,64 @@ $(function() { var question = "Please verify your selected Spool '"+responseData.spoolName+"'. Do you want to start the print anyway?"; var check = confirm(question); if (check == true) { - startPrint(); + origStartPrintFunction(); } } } }); }; + self.filesViewModel.loadFile = function confirmSpoolSelectionOnLoadAndPrint(data, printAfterLoad) { + // orig. SourceCode + if (!self.filesViewModel.loginState.hasPermission(self.filesViewModel.access.permissions.FILES_SELECT)) return; + + if (!data) { + return; + } + + if (printAfterLoad && self.filesViewModel.listHelper.isSelected(data) && self.filesViewModel.enablePrint(data)) { + // file was already selected, just start the print job + // SPOOLMANAGER-CHANGE changed OctoPrint.job.start(); + startPrintFunction(); + } else { + // select file, start print job (if requested and within dimensions) + var withinPrintDimensions = self.filesViewModel.evaluatePrintDimensions(data, true); + var print = printAfterLoad && withinPrintDimensions; + + if (print && self.filesViewModel.settingsViewModel.feature_printStartConfirmation()) { + showConfirmationDialog({ + message: gettext("This will start a new print job. Please check that the print bed is clear."), + question: gettext("Do you want to start the print job now?"), + cancel: gettext("No"), + proceed: gettext("Yes"), + onproceed: function() { + OctoPrint.files.select(data.origin, data.path, false).done(function () { + if (print){ + newStartPrintFunction(); + } + }); + }, + nofade: true + }); + } else { + OctoPrint.files.select(data.origin, data.path, false).done(function () { + if (print){ + newStartPrintFunction(); + } + }); + } + } + }; + + + self.printerStateViewModel.print = newStartPrintFunction; //////////////////////////////////////////////////////////////////////////////////////////////// OCTOPRINT HOOKS self.onBeforeBinding = function() { // assign current pluginSettings self.pluginSettings = self.settingsViewModel.settings.plugins[PLUGIN_ID]; - + // Table visibility + self. initTableVisibilities(); // resetSettings-Stuff new ResetSettingsUtilV2(self.pluginSettings).assignResetSettingsFeature(PLUGIN_ID, function(data){ // no additional reset function needed in V2 @@ -417,6 +518,12 @@ $(function() { return; } + if ("reloadTable and sidebarSpools" == data.action){ + self.spoolItemTableHelper.reloadItems(); + self.loadSpoolsForSidebar(); + return; + } + if ("csvImportStatus" == data.action){ self.csvImportDialog.updateText(data); return; @@ -454,7 +561,8 @@ $(function() { dependencies: [ "loginStateViewModel", "settingsViewModel", - "printerStateViewModel" + "printerStateViewModel", + "filesViewModel" ], // Elements to bind to, e.g. #settings_plugin_SpoolManager, #tab_plugin_SpoolManager, ... elements: [ diff --git a/octoprint_SpoolManager/static/js/pick-a-color.js b/octoprint_SpoolManager/static/js/pick-a-color.js index e70dc3b1..57c0316e 100755 --- a/octoprint_SpoolManager/static/js/pick-a-color.js +++ b/octoprint_SpoolManager/static/js/pick-a-color.js @@ -295,6 +295,67 @@ "#" + myColorVars.typedColor); } } + + +/////////////////////////////////////////////// + if (settings.showAdvanced) { + var newColor = $thisEl.val(); + var hsl = tinycolor(newColor).toHsl(); + var $advancedContainer = $thisEl.parent().find(".advanced-list"); + var spectrumWidth = parseInt($advancedContainer.find(".color-box").first().width(),10); + + //Set Hue + var $hueSpectrum = $advancedContainer.find(".spectrum-hue"); + var $hueBand = $hueSpectrum.find(".highlight-band"); + var $hueValue = $advancedContainer.find(".hue-value"); + var hbWidth = $hueBand.outerWidth(); + var halfHBWidth = hbWidth / 2; + //inverse of hsl equation in getHighlightedHue + var position = hsl.h/360*spectrumWidth; + $hueBand.css("left", position - halfHBWidth); + + //Set Saturation + var $satSpectrum = $advancedContainer.find(".spectrum-saturation"); + var $satBand = $satSpectrum.find(".highlight-band"); + var $saturationValue = $advancedContainer.find(".saturation-value"); + var sbWidth = $satBand.outerWidth(); + var halfSBWidth = sbWidth / 2; + //inverse of hsl equation in getHighlightedSaturation + var position = hsl.s*spectrumWidth; + $satBand.css("left", position - halfSBWidth); + + //Set Lightness + var $lightSpectrum = $advancedContainer.find(".spectrum-lightness"); + var $lightBand = $lightSpectrum.find(".highlight-band"); + var $lightnessValue = $advancedContainer.find(".lightness-value"); + var lbWidth = $lightBand.outerWidth(); + var halfLBWidth = lbWidth / 2; + //I made this up. It looks like hsl.l += multiplier, which is + //calculated in getColorMultiplier. This is just tweaking lightness + //but I want to just set it. So taking an educated guess. + var position = (1.0-hsl.l)*spectrumWidth; + $lightBand.css("left", position - halfLBWidth); + + //Make sure all variables are updated correctly + methods.updateSaturationStyles($satSpectrum,hsl.h,hsl.l); + methods.updateHueStyles($hueSpectrum,hsl.s,hsl.l); + methods.updateLightnessStyles($lightSpectrum,hsl.h,hsl.s); + var $advancedPreview = $advancedContainer.find(".color-preview"); + $advancedPreview.css("background-color","#" + newColor); + + //Update lookup values (code looks up current values instead of + //calculating each time based on band position) + $hueValue.text(Math.floor( hsl.h )); + $lightnessValue.text(Math.floor(hsl.l * 100) + "%"); + $saturationValue.text(Math.floor(hsl.s * 100) + "%"); + $hueSpectrum.attr('data-value', hsl.h); + $satSpectrum.attr('data-value', hsl.s); + $lightSpectrum.attr('data-value', hsl.l); + } + + + + }, // must be called with apply and an arguments array like [{thisEvent}] @@ -872,7 +933,6 @@ var hue = Math.floor((position/spectrumWidth) * 360), color = "hsl(" + hue + "," + saturationString + "," + lightnessString + ")"; color = "#" + tinycolor(color).toHex(); - $advancedPreview.css("background-color",color); $hueValue.text(hue); methods.updateLightnessStyles($lightnessSpectrum,hue,currentSaturation); @@ -981,11 +1041,14 @@ } } if (settings.showAdvanced) { - advancedStatus = { - h: 0, - s: 1, - l: 0.5 - }; + + + +// advancedStatus = { +// h: 0, +// s: 1, +// l: 0.5 +// }; myElements.advancedSpectrums = myElements.thisWrapper.find(".advanced-list").find(".color-box"); myElements.advancedHighlightBands = myElements.thisWrapper.find(".advanced-list").find(".highlight-band"); @@ -1080,23 +1143,38 @@ if (settings.showAdvanced) { - // for dragging advanced sliders - + function getAdvancedStatus() { + var hslObj = { + h: $(myElements.hueSpectrum).attr('data-value'), + s: $(myElements.saturationSpectrum).attr('data-value'), + l: $(myElements.lightnessSpectrum).attr('data-value') + } + return hslObj; + } + // for dragging advanced sliders $(myElements.hueHighlightBand).on(dragEvent, function(event) { - advancedStatus.h = methods.getHighlightedHue.apply(this, [advancedStatus]); +// advancedStatus.h = methods.getHighlightedHue.apply(this, [advancedStatus]); + var newH = methods.getHighlightedHue.apply(this, [getAdvancedStatus()]); + $(myElements.hueSpectrum).attr('data-value', newH); }); $(myElements.lightnessHighlightBand).on(dragEvent, function() { - methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": advancedStatus}]); +// methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": advancedStatus}]); + methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": getAdvancedStatus()}]); }).on(endEvent, function () { - advancedStatus.l = methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": advancedStatus}]); +// advancedStatus.l = methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": advancedStatus}]); + var newL = methods.calculateHighlightedColor.apply(this, [{"type": "advanced", "hsl": getAdvancedStatus()}]); + $(myElements.lightnessSpectrum).attr('data-value', newL); }); $(myElements.saturationHighlightBand).on(dragEvent, function() { - methods.getHighlightedSaturation.apply(this, [advancedStatus]); +// methods.getHighlightedSaturation.apply(this, [advancedStatus]); + methods.getHighlightedSaturation.apply(this, [getAdvancedStatus()]); }).on(endDragEvent, function () { - advancedStatus.s = methods.getHighlightedSaturation.apply(this, [advancedStatus]); +// advancedStatus.s = methods.getHighlightedSaturation.apply(this, [advancedStatus]); + var newS = methods.getHighlightedSaturation.apply(this, [getAdvancedStatus()]); + $(myElements.saturationSpectrum).attr('data-value', newS); }); $(myElements.advancedHighlightBand).on(endDragEvent, function () { @@ -1104,13 +1182,14 @@ }); // for clicking/tapping advanced sliders - $(myElements.lightnessSpectrum).click( function (event) { event.stopPropagation(); // stop this click from closing the dropdown var $highlightBand = $(this).find(".highlight-band"), dimensions = methods.getMoveableArea($highlightBand); methods.moveHighlightBand($highlightBand, dimensions, event); - advancedStatus.l = methods.calculateHighlightedColor.apply($highlightBand, [{"type": "advanced", "hsl": advancedStatus}]); +// advancedStatus.l = methods.calculateHighlightedColor.apply($highlightBand, [{"type": "advanced", "hsl": advancedStatus}]); + var newL = methods.calculateHighlightedColor.apply($highlightBand, [{"type": "advanced", "hsl": getAdvancedStatus()}]); + $(myElements.lightnessSpectrum).attr('data-value', newL); }); $(myElements.hueSpectrum).click( function (event) { @@ -1118,7 +1197,9 @@ var $highlightBand = $(this).find(".highlight-band"), dimensions = methods.getMoveableArea($highlightBand); methods.moveHighlightBand($highlightBand, dimensions, event); - advancedStatus.h = methods.getHighlightedHue.apply($highlightBand, [advancedStatus]); +// advancedStatus.h = methods.getHighlightedHue.apply($highlightBand, [advancedStatus]); + var newH = methods.getHighlightedHue.apply($highlightBand, [getAdvancedStatus()]); + $(myElements.hueSpectrum).attr('data-value', newH); }); $(myElements.saturationSpectrum).click( function (event) { @@ -1126,7 +1207,9 @@ var $highlightBand = $(this).find(".highlight-band"), dimensions = methods.getMoveableArea($highlightBand); methods.moveHighlightBand($highlightBand, dimensions, event); - advancedStatus.s = methods.getHighlightedSaturation.apply($highlightBand, [advancedStatus]); +// advancedStatus.s = methods.getHighlightedSaturation.apply($highlightBand, [advancedStatus]); + var newS = methods.getHighlightedSaturation.apply($highlightBand, [getAdvancedStatus()]); + $(myElements.saturationSpectrum).attr('data-value', newS); }); $(myElements.advancedSpectrums).click( function () { @@ -1134,8 +1217,8 @@ }); //for clicking advanced color preview - $(myElements.advancedPreview).click( function () { + var selectedColor = tinycolor($(this).css("background-color")).toHex(); $(myElements.thisEl).val(selectedColor); $(myElements.thisEl).trigger("change"); diff --git a/octoprint_SpoolManager/templates/SpoolManager_settings.jinja2 b/octoprint_SpoolManager/templates/SpoolManager_settings.jinja2 index 4139ec69..7886a8c9 100644 --- a/octoprint_SpoolManager/templates/SpoolManager_settings.jinja2 +++ b/octoprint_SpoolManager/templates/SpoolManager_settings.jinja2 @@ -3,7 +3,7 @@
-
diff --git a/octoprint_SpoolManager/templates/SpoolManager_tab.jinja2 b/octoprint_SpoolManager/templates/SpoolManager_tab.jinja2 index 70a2ce66..455bb243 100644 --- a/octoprint_SpoolManager/templates/SpoolManager_tab.jinja2 +++ b/octoprint_SpoolManager/templates/SpoolManager_tab.jinja2 @@ -24,10 +24,11 @@
Sort by: - Displayname | + Name | Last use | First use | - Remaining + Remaining | + Material
@@ -42,6 +43,93 @@
+ + + + @@ -49,27 +137,27 @@ - - - - - - + + + + + + - - + - - - - + + + +
NameMaterialLast / First useWeightUsedNoteNameMaterialLast / First useWeightUsedNote

+


g
g
%
mm

g
g
%
mm
diff --git a/octoprint_SpoolManager/templates/SpoolManager_tab_dialogs.jinja2 b/octoprint_SpoolManager/templates/SpoolManager_tab_dialogs.jinja2 index 3443d031..e0d20a45 100644 --- a/octoprint_SpoolManager/templates/SpoolManager_tab_dialogs.jinja2 +++ b/octoprint_SpoolManager/templates/SpoolManager_tab_dialogs.jinja2 @@ -201,13 +201,21 @@
- -
+ +
+
+ + °C +
+ +  Bed
- + °C
+
+
@@ -271,6 +279,7 @@
1Mandatory field
2Needed for filament usage prediction
3See https://bitfab.io/blog/3d-printing-materials-densities/ (without warranty)
+
4Not send to the printer
@@ -309,7 +318,7 @@
- +
diff --git a/setup.py b/setup.py index 30a2b5fa..13fe3d42 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ # The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module # -plugin_version = "1.0.0" +plugin_version = "1.1.0" # The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin # module