· 6 years ago · Jan 26, 2020, 04:48 AM
1
2<!DOCTYPE html>
3<html>
4 <head>
5 <title data-bind="text: title">OctoPrint</title>
6
7 <link rel="shortcut icon" href="/static/img/tentacle-32x32.png">
8 <link rel="mask-icon" href="/static/img/mask.svg" color="#56BE37">
9 <link rel="mask-icon-theme" href="/static/img/mask-theme.svg" color="#56BE37">
10 <link rel="apple-touch-icon" sizes="114x114" href="/static/img/apple-touch-icon-114x114.png">
11 <link rel="apple-touch-icon" sizes="144x144" href="/static/img/apple-touch-icon-144x144.png">
12
13 <meta name="robots" content="noindex, nofollow, noimageindex">
14 <meta name="referrer" content="no-referrer">
15 <meta name="theme-color" data-bind="attr: { content: theme_color }">
16
17 <link href="/static/webassets/packed_libs.css?ec88168c" rel="stylesheet" media="screen">
18<link href="/static/webassets/packed_core.css?bb25a3af" rel="stylesheet" media="screen">
19
20
21
22<script src="/static/js/lib/less.min.js" type="text/javascript"></script>
23 <script type="text/javascript">
24 var BASEURL = "/";
25 var API_BASEURL = BASEURL + "api/";
26 var PLUGIN_BASEURL = BASEURL + "plugin/";
27 var GCODE_WORKER = "/static/gcodeviewer/js/Worker.js";
28
29 var CONFIG_DEBUG = false;
30 var CONFIG_LOADINGANIMATION = true;
31
32 var CONFIG_GCODEFILESPERPAGE = 5000;
33 var CONFIG_TIMELAPSEFILESPERPAGE = 10;
34 var CONFIG_LOGFILESPERPAGE = 10;
35 var CONFIG_USERSPERPAGE = 10;
36 var CONFIG_GROUPSPERPAGE = 10;
37 var CONFIG_WEBCAM_STREAM = ""; // deprecated, only left for compatibility reasons
38 var CONFIG_ACCESS_CONTROL = true;
39 var CONFIG_ACCESS_CONTROL_ACTIVE = true;
40 var CONFIG_SD_SUPPORT = true;
41 var CONFIG_FIRST_RUN = false;
42 var CONFIG_TEMPERATURE_GRAPH = true;
43 var CONFIG_GCODE_SIZE_THRESHOLD = 20971520;
44 var CONFIG_GCODE_MOBILE_SIZE_THRESHOLD = 2097152;
45 var CONFIG_WIZARD = false;
46
47 var SOCKJS_URI = "/" + "sockjs";
48 var SOCKJS_DEBUG = CONFIG_DEBUG;
49 // sockjs should define CLOSE_NORMAL for us, but they don't (from ws spec)
50 var SOCKJS_CLOSE_NORMAL = 1000;
51
52 var UI_API_KEY = ""; // deprecated, only left for compatibility reasons
53 var VERSION = "1.4.0rc3";
54 var DISPLAY_VERSION = "1.4.0rc3";
55 var BRANCH = "rc/devel";
56 var LOCALE = "en";
57 var AVAILABLE_LOCALES = {"de": {"display": "Deutsch", "english": "German", "language": "de"}, "en": {"display": "English", "english": "English", "language": "en"}};
58 var SUPPORTED_FILETYPES = ["machinecode"];
59 var SUPPORTED_EXTENSIONS = [".gcode", ".gco", ".g"];
60
61 var PERMISSIONS = [{"dangerous": true, "default_groups": ["admins"], "description": "Admin is allowed to do everything", "key": "ADMIN", "name": "Admin", "needs": {"role": ["admin"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to gather status information, e.g. job progress, printer state, temperatures, ...", "key": "STATUS", "name": "Status", "needs": {"role": ["status"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to connect to and disconnect from a printer", "key": "CONNECTION", "name": "Connection", "needs": {"role": ["connection"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to watch the webcam stream", "key": "WEBCAM", "name": "Webcam", "needs": {"role": ["webcam"]}}, {"dangerous": true, "default_groups": [], "description": "Allows to run system commands, e.g. restart OctoPrint, shutdown or reboot the system", "key": "SYSTEM", "name": "System", "needs": {"role": ["system"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to retrieve a list of all uploaded files, includingtheir metadata (e.g. date, file size, analysis results, ...)", "key": "FILES_LIST", "name": "File List", "needs": {"role": ["files_list"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows users to upload new files", "key": "FILES_UPLOAD", "name": "File Upload", "needs": {"role": ["files_upload"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows users to download files. The GCODE viewer is affected by this as well.", "key": "FILES_DOWNLOAD", "name": "File Download", "needs": {"role": ["files_list", "files_download"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows users to delete files", "key": "FILES_DELETE", "name": "File Delete", "needs": {"role": ["files_list", "files_delete"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to select a file for printing", "key": "FILES_SELECT", "name": "File Select", "needs": {"role": ["files_list", "files_select"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to start, pause and cancel a print job. Includes the \"Select\" permission", "key": "PRINT", "name": "Print", "needs": {"role": ["files_list", "files_select", "print"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows access to the GCODE viewer. Includes the \"File Download\"permission.", "key": "GCODE_VIEWER", "name": "GCODE viewer", "needs": {"role": ["files_list", "gcodeviewer", "files_download"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to watch the terminal tab but not to send commands to the printer from it", "key": "MONITOR_TERMINAL", "name": "Terminal", "needs": {"role": ["monitor_terminal"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to control of the printer by using the temperature controls,the control tab or sending commands through the terminal.", "key": "CONTROL", "name": "Control", "needs": {"role": ["control"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to slice files", "key": "SLICE", "name": "Slice", "needs": {"role": ["slice"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to list timelapse videos", "key": "TIMELAPSE_LIST", "name": "Timelapse List", "needs": {"role": ["timelapse_list"]}}, {"dangerous": false, "default_groups": ["users", "readonly"], "description": "Allows to download timelapse videos", "key": "TIMELAPSE_DOWNLOAD", "name": "Timelapse Download", "needs": {"role": ["timelapse_download"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to delete timelapse videos and unrendered timelapses", "key": "TIMELAPSE_DELETE", "name": "Timelapse Delete", "needs": {"role": ["timelapse_delete"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to change the timelapse settings and delete or render unrendered timelapses. Includes the \"Timelapse List\",\"Timelapse Delete\" and \"Timelapse Download\" permissions", "key": "TIMELAPSE_ADMIN", "name": "Timelapse Admin", "needs": {"role": ["timelapse_download", "timelapse_admin", "timelapse_list"]}}, {"dangerous": true, "default_groups": [], "description": "Allows to manage settings", "key": "SETTINGS", "name": "Settings", "needs": {"role": ["settings"]}}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to see and interact with printer prompts", "key": "PLUGIN_ACTION_COMMAND_PROMPT_INTERACT", "name": "Action Command Prompt Support: Interact with printer prompts", "needs": {"role": ["plugin_action_command_prompt_interact"]}, "plugin": "action_command_prompt"}, {"dangerous": false, "default_groups": ["admins"], "description": "Allows to read announcements", "key": "PLUGIN_ANNOUNCEMENTS_READ", "name": "Announcement Plugin: Read announcements", "needs": {"role": ["plugin_announcements_read"]}, "plugin": "announcements"}, {"dangerous": false, "default_groups": ["admins"], "description": "Allows to manage announcement subscriptions. Includes \"Read announcements\" permission", "key": "PLUGIN_ANNOUNCEMENTS_MANAGE", "name": "Announcement Plugin: Manage announcement subscriptions", "needs": {"role": ["plugin_announcements_read", "plugin_announcements_manage"]}, "plugin": "announcements"}, {"dangerous": true, "default_groups": ["admins"], "description": "Allows administrating all application keys", "key": "PLUGIN_APPKEYS_ADMIN", "name": "Application Keys Plugin: Admin access", "needs": {"role": ["plugin_appkeys_admin"]}, "plugin": "appkeys"}, {"dangerous": true, "default_groups": ["admins"], "description": "Allows access to backups and restores", "key": "PLUGIN_BACKUP_ACCESS", "name": "Backup \u0026 Restore: Backup access", "needs": {"role": ["plugin_backup_access"]}, "plugin": "backup"}, {"dangerous": false, "default_groups": ["admins"], "description": "Allows to download and delete log files and list and set log levels.", "key": "PLUGIN_LOGGING_MANAGE", "name": "Logging: Logging management", "needs": {"role": ["plugin_logging_manage"]}, "plugin": "logging"}, {"dangerous": false, "default_groups": ["admins"], "description": "Allows to enable, disable and uninstall installed plugins.", "key": "PLUGIN_PLUGINMANAGER_MANAGE", "name": "Plugin Manager: Manage plugins", "needs": {"role": ["plugin_pluginmanager_manage"]}, "plugin": "pluginmanager"}, {"dangerous": true, "default_groups": ["admins"], "description": "Allows to install new plugins. Includes the \"Manage plugins\" permission.", "key": "PLUGIN_PLUGINMANAGER_INSTALL", "name": "Plugin Manager: Install new plugins", "needs": {"role": ["plugin_pluginmanager_manage", "plugin_pluginmanager_install"]}, "plugin": "pluginmanager"}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to see printer safety warnings", "key": "PLUGIN_PRINTER_SAFETY_CHECK_DISPLAY", "name": "Printer Safety Check: Display printer safety warnings", "needs": {"role": ["plugin_printer_safety_check_display"]}, "plugin": "printer_safety_check"}, {"dangerous": false, "default_groups": ["users"], "description": "Allows to check for software updates", "key": "PLUGIN_SOFTWAREUPDATE_CHECK", "name": "Software Update: Check", "needs": {"role": ["plugin_softwareupdate_check"]}, "plugin": "softwareupdate"}, {"dangerous": true, "default_groups": ["admins"], "description": "Allows to perform software updates", "key": "PLUGIN_SOFTWAREUPDATE_UPDATE", "name": "Software Update: Update", "needs": {"role": ["plugin_softwareupdate_update"]}, "plugin": "softwareupdate"}];
62
63 var OCTOPRINT_VIEWMODELS = [];
64 var ADDITIONAL_VIEWMODELS = [];
65 var OCTOPRINT_ADDITIONAL_BINDINGS = [];
66
67
68
69
70 var OCTOPRINT_INITIAL_TAB = "#temp";
71
72
73
74 var OCTOPRINT_INITIAL_WIZARD = undefined;
75
76</script>
77 </head>
78 <body>
79 <noscript>
80 <style type="text/css">
81 #page-container-main,
82 #page-container-loading,
83 #page-container-needlogin {
84 display:none;
85 }
86 </style>
87 <div id="page-container-noscript">
88 <div class="wrapper">
89 <div class="outer">
90 <div class="inner">
91 <div class="content">
92 <h1 class="text-error">You don't seem to have JavaScript enabled</h1>
93 OctoPrint's UI requires JavaScript to work. Please enable JavaScript and reload.
94 </div>
95 </div>
96 </div>
97 </div>
98 </div>
99 </noscript>
100
101
102 <div id="page-container-loading" data-bind="visible: loading">
103 <div class="wrapper">
104 <div class="outer">
105 <div class="inner">
106 <div class="content">
107 <h1 id="page-container-loading-header">Loading OctoPrint's UI, please wait...</h1>
108 <i id="page-container-loading-spinner" class="fa fa-spinner fa-spin fa-4x"></i>
109 <p id="page-container-loading-error" style="display: none"></p>
110 </div>
111 </div>
112 </div>
113 </div>
114 </div>
115
116
117 <div class="container" id="page-container-needlogin" style="display: none" data-bind="visible: needlogin">
118 <form class="form-signin">
119 <h2 class="form-signin-heading">Please log in</h2>
120
121 <div class="alert alert-error" style="display: none" data-bind="visible: login_error, text: login_error"></div>
122
123 <input type="text" data-bind="value: login_username" class="input-block-level" placeholder="Username" autofocus>
124 <input type="password" data-bind="value: login_password" class="input-block-level" placeholder="Password">
125 <span class="pull-right"><small><a href="https://faq.octoprint.org/forgotten-password" id="login-forgotpassword" target="_blank" tabindex="-1">Forgot password?</a></small></span>
126 <label class="checkbox">
127 <input type="checkbox" data-bind="value: login_remember"> Remember me
128 </label>
129 <button class="btn btn-block btn-large btn-primary" type="submit" data-bind="click: login">Log in</button>
130 </form>
131 </div>
132
133 <div class="page-container" id="page-container-main" data-bind="visible: visible">
134 <!-- ko allowBindings: false -->
135 <div id="navbar" class="navbar navbar-static-top">
136 <div class="navbar-inner" data-bind="css: appearanceClasses">
137 <div class="container">
138 <a class="brand" href="javascript:void(0)" data-bind="attr: {title: appearance.fullbrand}"><span data-bind="text: appearance.brand">OctoPrint</span></a>
139 <div class="nav-collapse">
140 <!-- Navbar -->
141 <ul class="nav pull-right">
142
143
144 <!-- ko allowBindings: false -->
145 <li id="navbar_plugin_action_command_prompt"
146 data-bind="allowBindings: true"
147
148
149 >
150 <a id="navbar_show_prompt" class="pull-right" style="display: none" href="javascript:void(0)" data-bind="click: function() { showPrompt(); }, visible: active() && !visible()" title="Message from your printer">
151 <i class="fa fa-commenting-o"></i>
152</a>
153 </li>
154 <!-- /ko -->
155
156
157 <!-- ko allowBindings: false -->
158 <li id="navbar_settings"
159 data-bind="visible: loginState.hasPermissionKo(access.permissions.SETTINGS)"
160
161 style="display: none;"
162 >
163 <a id="navbar_show_settings" title="Settings" class="pull-right" href="#settings_dialog" data-bind="click: function() { $root.show(); }">
164 <i class="fa fa-wrench"></i>
165</a>
166 </li>
167 <!-- /ko -->
168
169
170
171 <li id="navbar_systemmenu"
172 data-bind="visible: loginState.hasPermissionKo(access.permissions.SYSTEM)"
173 class="dropdown"
174 style="display: none;"
175 >
176 <a href="javascript:void(0)" title="System" class="dropdown-toggle" data-toggle="dropdown" data-bind="visible: system.systemActions().length > 0">
177 <i class="fa fa-power-off"></i>
178 <b class="caret"></b>
179</a>
180<ul class="dropdown-menu" data-bind="foreach: system.systemActions">
181 <!-- ko if: action == "divider" -->
182 <li class="divider"></li>
183 <!-- /ko -->
184 <!-- ko if: action != "divider" -->
185 <li><a href="javascript:void(0)" data-bind="click: $root.system.triggerCommand, text: name"></a></li>
186 <!-- /ko -->
187</ul>
188 </li>
189
190
191
192 <!-- ko allowBindings: false -->
193 <li id="navbar_plugin_announcements"
194 data-bind="allowBindings: true, visible: loginState.hasPermission(access.permissions.PLUGIN_ANNOUNCEMENTS_ANNOUNCEMENT)"
195
196 style="display: none"
197 >
198 <a id="navbar_show_announcements" class="pull-right" href="javascript:void(0)" data-bind="click: function() { showAnnouncementDialog(); }" title="Announcements">
199 <i class="fa" data-bind="css: {'fa-bell-o': !unread(), 'fa-bell': unread()}"></i>
200</a>
201 </li>
202 <!-- /ko -->
203
204
205
206 <li id="navbar_login"
207
208 class="dropdown"
209
210 >
211 <a href="javascript:void(0)" class="dropdown-toggle">
212 <i class="fa fa-user"></i> <span data-bind="text: loginState.userMenuText, attr: {title: loginState.userMenuTitle}">Login</span>
213 <b class="caret"></b>
214</a>
215<div id="login_dropdown_loggedout" style="padding: 15px" class="dropdown-menu" data-bind="css: {hide: loginState.loggedIn(), 'dropdown-menu': !loginState.loggedIn()}">
216 <form id="loginForm" data-bind="event: {'submit': loginState.prepareLogin }" onsubmit="return false; // this gets overwritten on view model bind">
217 <label for="login_user">Username</label>
218 <input type="text" id="login_user" name="username" data-bind="valueWithInit: loginState.loginUser" placeholder="Username" autocapitalize="none" autocorrect="off">
219 <span class="pull-right"><small><a href="https://faq.octoprint.org/forgotten-password" target="_blank" rel="noreferrer noopener" tabindex="-1">Forgot password?</a></small></span>
220 <label for="login_pass">Password</label>
221 <input type="password" id="login_pass" name="password" data-bind="valueWithInit: loginState.loginPass" placeholder="Password">
222 <label class="checkbox">
223 <input type="checkbox" id="login_remember" data-bind="checked: loginState.loginRemember"> Remember me
224 </label>
225 <button type="submit" class="btn btn-block btn-primary" id="login_button">Login</button>
226 </form>
227</div>
228<ul id="login_dropdown_loggedin" class="hide" data-bind="css: {hide: !loginState.loggedIn(), 'dropdown-menu': loginState.loggedIn()}">
229 <li><a href="#" id="usersettings_button" data-bind="click: function() { usersettings.show(); }">User Settings</a></li>
230 <li><a href="#" id="logout_button" data-bind="click: loginState.logout">Logout</a></li>
231</ul>
232 </li>
233
234
235 </ul>
236 </div>
237 </div>
238 </div>
239 </div>
240 <div class="container octoprint-container">
241 <div class="row">
242 <!-- Sidebar -->
243
244 <div id="sidebar" class="accordion span4">
245
246
247 <!-- ko allowBindings: false -->
248 <div id="sidebar_plugin_printer_safety_check_wrapper"
249 class="accordion-group "
250 data-bind="allowBindings: true, visible: printerState.isOperational() && loginState.isAdmin() && warnings().length > 0"
251 style="display: none"
252 >
253 <div class="accordion-heading">
254 <a class="accordion-toggle" data-toggle="collapse" data-target="#sidebar_plugin_printer_safety_check">
255 <i class="fa icon-black fa-exclamation-triangle"></i> Printer Safety Warning
256 </a>
257
258 </div>
259 <div id="sidebar_plugin_printer_safety_check"
260 class="accordion-body collapse in "
261
262 >
263 <div class="accordion-inner">
264 <p><strong>Warning!</strong></p>
265<!-- ko foreach: warnings -->
266<p class="printer_safety_warning">
267 <span data-bind="text: message"></span><br>
268 <a target="_blank" rel="noreferrer noopener" data-bind="attr: {href: 'https://faq.octoprint.org/warning-' + type}">Learn more...</a>
269</p>
270<!-- /ko -->
271 </div>
272 </div>
273 </div>
274 <!-- /ko -->
275
276
277 <!-- ko allowBindings: false -->
278 <div id="connection_wrapper"
279 class="accordion-group "
280 data-bind="visible: loginState.hasPermissionKo(access.permissions.CONNECTION)"
281 style="display: none;"
282 >
283 <div class="accordion-heading">
284 <a class="accordion-toggle" data-toggle="collapse" data-target="#connection">
285 <i class="fa icon-black fa-signal"></i> Connection
286 </a>
287
288 <div class="refresh-trigger accordion-heading-button btn-group" data-bind="visible: $root.refreshVisible">
289 <a href="#" data-bind="click: function() { $root.requestData(); }" title="Refresh connection options">
290 <i class="fa fa-refresh"></i>
291 </a>
292</div>
293
294 </div>
295 <div id="connection"
296 class="accordion-body collapse in "
297
298 >
299 <div class="accordion-inner">
300 <label for="connection_ports" data-bind="css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()">Serial Port</label>
301<select id="connection_ports" data-bind="options: portOptions, optionsCaption: 'AUTO', value: selectedPort, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()"></select>
302<label for="connection_baudrates" data-bind="css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()">Baudrate</label>
303<select id="connection_baudrates" data-bind="options: baudrateOptions, optionsCaption: 'AUTO', value: selectedBaudrate, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()"></select>
304<label for="connection_printers" data-bind="css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()">Printer Profile</label>
305<select id="connection_printers" data-bind="options: printerOptions, optionsText: 'name', optionsValue: 'id', value: selectedPrinter, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()"></select>
306<label class="checkbox">
307 <input type="checkbox" id="connection_save" data-bind="checked: saveSettings, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()"> Save connection settings
308</label>
309<label class="checkbox">
310 <input type="checkbox" id="connection_autoconnect" data-bind="checked: settings.serial_autoconnect, css: {disabled: !isErrorOrClosed()}, enable: isErrorOrClosed()"> Auto-connect on server startup
311</label>
312<button class="btn btn-block" id="printer_connect" data-bind="click: connect, text: buttonText">Connect</button>
313 </div>
314 </div>
315 </div>
316 <!-- /ko -->
317
318
319 <!-- ko allowBindings: false -->
320 <div id="state_wrapper"
321 class="accordion-group "
322 data-bind="visible: loginState.hasPermissionKo(access.permissions.STATUS)"
323 style="display: none;"
324 >
325 <div class="accordion-heading">
326 <a class="accordion-toggle" data-toggle="collapse" data-target="#state">
327 <i class="fa icon-black fa-info-circle"></i> State
328 </a>
329
330 </div>
331 <div id="state"
332 class="accordion-body collapse in "
333
334 >
335 <div class="accordion-inner">
336 <span title="Current printer state">State</span>: <strong data-bind="text: stateString"></strong><br>
337<hr>
338<span title="Name of file currently selected for printing">File</span>: <strong data-bind="text: filedisplay, attr: {title: filepath}"></strong> <strong data-bind="visible: sd">(SD)</strong><br>
339<span title="Upload date of the file currently selected or printing">Uploaded</span>: <strong data-bind="text: dateString"></strong><br>
340<!-- ko if: userString -->
341<span title="User who selected this file for printing">User</span>: <strong data-bind="text: userString"></strong><br>
342<!-- /ko -->
343<!-- ko if: settings.webcam_timelapseEnabled -->
344<span title="Current timelapse configuration">Timelapse</span>: <strong data-bind="text: timelapseString"></strong><br>
345<!-- /ko -->
346<!-- ko foreach: filament -->
347<span data-bind="text: 'Filament (' + name() + '): ', title: 'Filament usage for ' + name()"></span><strong data-bind="text: formatFilament(data())"></strong><br>
348<!-- /ko -->
349<span title="Estimated total print time based on analysis of the file or past prints">Approx. Total Print Time</span>: <strong data-bind="text: estimatedPrintTimeString, attr: {title: estimatedPrintTimeExactString}"></strong><br>
350<hr>
351<span title="Total print time so far">Print Time</span>: <strong data-bind="text: printTimeString"></strong><br>
352<span title="Estimated time until the print job is done. This is only an estimate and accuracy depends heavily on various factors!">Print Time Left</span>: <strong data-bind="text: printTimeLeftString, attr: {title: printTimeLeftExactString}"></strong> <span id="state_printtimeleft_popover" style="display: none" data-bind="visible: printTimeLeftOrigin, attr: {title: printTimeLeftOriginString}, css: printTimeLeftOriginClass">●</span><br>
353<span title="Bytes printed vs total bytes of file">Printed</span>: <strong data-bind="text: byteString"></strong><br>
354
355
356<div class="progress progress-text-centered">
357 <span class="progress-text-back" data-bind="text: progressBarString()"></span>
358 <div class="bar" id="job_progressBar" data-bind="style: {width: progressString() + '%'}">
359 <span class="progress-text-front" data-bind="copyWidth: ':parent :parent', text: progressBarString()"></span>
360 </div>
361</div>
362
363<div class="row-fluid print-control" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PRINT)">
364 <button class="btn btn-primary span4" data-bind="click: print, enable: enablePrint, css: {'btn-danger': isPaused()}, attr: {title: titlePrintButton}" id="job_print"><i class="fa" data-bind="css: {'fa-print': !isPaused(), 'fa-undo': isPaused()}"></i> <span data-bind="text: (isPaused() ? 'Restart' : 'Print')">Print</span></button>
365 <button class="btn span4" id="job_pause" data-bind="click: function() { isPaused() ? onlyResume() : onlyPause(); }, enable: enablePause, css: {active: isPaused()}, attr: {title: titlePauseButton}"><i class="fa" data-bind="css: {'fa-pause': !isPaused(), 'fa-play': isPaused()}"></i> <span data-bind="visible: !isPaused()">Pause</span><span data-bind="visible: isPaused()">Resume</span></button>
366 <button class="btn span4" id="job_cancel" data-bind="click: cancel, enable: enableCancel" title="Cancels the print job"><i class="fa fa-stop"></i> Cancel</button>
367</div>
368 </div>
369 </div>
370 </div>
371 <!-- /ko -->
372
373
374 <!-- ko allowBindings: false -->
375 <div id="files_wrapper"
376 class="accordion-group "
377 data-bind="visible: loginState.hasPermissionKo(access.permissions.FILES_LIST)"
378 style="display: none;"
379 >
380 <div class="accordion-heading">
381 <a class="accordion-toggle" data-toggle="collapse" data-target="#files">
382 <i class="fa icon-black fa-list"></i> Files
383 </a>
384
385 <div class="settings-trigger accordion-heading-button btn-group" data-bind="visible: $root.filesListVisible">
386 <a class="dropdown-toggle" data-toggle="dropdown" href="#" title="File list settings">
387 <span class="fa fa-wrench"></span>
388 </a>
389 <ul class="dropdown-menu">
390 <li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilterSearch(); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.filterSearch() ? 'visible' : 'hidden'}"></i> Apply filters to search results</a></li>
391 <li class="divider"></li>
392 <li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('name'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> Sort by name (ascending)</a></li>
393 <li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('upload'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'upload' ? 'visible' : 'hidden'}"></i> Sort by upload date (descending)</a></li>
394 <li><a href="#" data-bind="click: function() { $root.listHelper.changeSorting('size'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> Sort by file size (descending)</a></li>
395 <li class="dropdown-submenu">
396 <a href="#"><i class="fa fa-check" style="visibility: hidden"></i> Folders</a>
397 <ul class="dropdown-menu">
398 <li><a href="#" data-bind="click: function() { $root.listStyle('folders_files'); }"><i class="fa fa-check" data-bind="style: {visibility: listStyle() == 'folders_files' ? 'visible' : 'hidden'}"></i> Sort by Folders, Files</a></li>
399 <li><a href="#" data-bind="click: function() { $root.listStyle('files_folders'); }"><i class="fa fa-check" data-bind="style: {visibility: listStyle() == 'files_folders' ? 'visible' : 'hidden'}"></i> Sort by Files, Folders</a></li>
400 <li><a href="#" data-bind="click: function() { $root.listStyle('mixed'); }"><i class="fa fa-check" data-bind="style: {visibility: listStyle() == 'mixed' ? 'visible' : 'hidden'}"></i> Mixed</a></li>
401 </ul>
402 </li>
403 <!-- ko if: availableFiletypes().length > 1 -->
404 <li class="divider"></li>
405 <!-- ko foreach: availableFiletypes -->
406 <li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter($data.key); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains($root.listHelper.currentFilters(), $data.key) ? 'visible' : 'hidden'}"></i> <span data-bind="text: $data.text"></span></a></li>
407 <!-- /ko -->
408 <!-- /ko -->
409
410 <li class="divider"></li>
411 <li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('local'); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'local') ? 'visible' : 'hidden'}"></i> Only show files stored locally</a></li>
412 <li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('sd'); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'sd') ? 'visible' : 'hidden'}"></i> Only show files stored on SD</a></li>
413
414 <li class="divider"></li>
415 <li><a href="#" data-bind="click: function() { $root.listHelper.toggleFilter('printed'); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains(listHelper.currentFilters(), 'printed') ? 'visible' : 'hidden'}"></i> Hide successfully printed files</a></li>
416 </ul>
417</div>
418
419<div class="refresh-trigger accordion-heading-button btn-group" data-bind="visible: $root.filesListVisible">
420 <a href="#" data-bind="click: function() { $root.requestData({force: true}); }" title="Refresh file list">
421 <i class="fa fa-refresh"></i>
422 </a>
423</div>
424
425
426 <div class="sd-trigger accordion-heading-button btn-group" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)() && $root.filesListVisible()">
427 <a class="dropdown-toggle" data-toggle="dropdown" href="#" title="SD Card operations">
428 <span class="icon-sd-black-14"></span>
429 </a>
430 <ul class="dropdown-menu">
431 <li data-bind="visible: !isSdReady()"><a href="#" data-bind="click: function() { $root.initSdCard(); }"><i class="fa fa-flag"></i> Initialize SD card</a></li>
432 <li data-bind="visible: isSdReady()"><a href="#" data-bind="click: function() { $root.refreshSdFiles(); }"><i class="fa fa-refresh"></i> Refresh SD files</a></li>
433 <li data-bind="visible: isSdReady()"><a href="#" data-bind="click: function() { $root.releaseSdCard(); }"><i class="fa fa-eject"></i> Release SD card</a></li>
434 </ul>
435 </div>
436
437
438 </div>
439 <div id="files"
440 class="accordion-body collapse in overflow_visible"
441
442 >
443 <div class="accordion-inner">
444 <form class="form-search" data-bind="submit: performSearch">
445 <div class="search-query-with-clear" data-bind="css: {'active-clear': searchQuery}">
446 <input type="search" class="input-block search-query" data-bind="value: searchQuery, valueUpdate: 'input'" placeholder="Search...">
447 <span class="search-clear" data-bind="click: clearSearchQuery"><i class="fa fa-remove"></i></span>
448 </div>
449</form>
450<div class="gcode_files">
451 <div class="entry back clickable" data-bind="visible: currentPath() != '', click: function() { $root.navigateUp(); }" style="display: none">
452 <div class="back-arrow"><i class="fa fa-arrow-left"></i> Back</div>
453 <div class="back-path"><small class="muted">Currently in <span data-bind="text: currentPath"></span></small></div>
454 </div>
455
456 <div class="scroll-wrapper" data-bind="foreach: filesAndFolders">
457 <div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }, css: $data.type"></div>
458 </div>
459
460 <script type="text/html" id="files_template_machinecode">
461 <div class="title clickable" data-bind="click: function() { if ($root.enableSelect($data)) { $root.loadFile($data, false); } else { return; } }, css: $root.getSuccessClass($data), style: { 'font-weight': $root.listHelper.isSelected($data) ? 'bold' : 'normal' }, text: display"></div>
462 <div class="internal" data-bind="visible: display && name != display">Internal: <span data-bind="text: name"></span></div>
463 <div class="uploaded">Uploaded: <span data-bind="text: formatTimeAgo(date), attr: {title: formatDate(date)}"></span></div>
464 <div class="size">Size: <span data-bind="text: formatSize(size)"></span></div>
465 <div class="additionalInfo hide" data-bind="html: $root.getAdditionalData($data)"></div>
466 <div class="btn-group action-buttons">
467 <div class="btn btn-mini toggleAdditionalData" data-bind="click: function() { if ($root.enableAdditionalData($data)) { $root.toggleAdditionalData($data); } else { return; } }, css: { disabled: !$root.enableAdditionalData($data) }" title="Additional data"><i class="fa fa-chevron-down"></i></div>
468 <a class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_DOWNLOAD), attr: {href: $root.downloadLink($data)}, css: {disabled: !$root.downloadLink($data)}" title="Download"><i class="fa fa-download"></i></a>
469 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_DELETE), click: function(data, event) { if ($root.enableRemove($data)) { $root.removeFile($data, event); } else { return; } }, css: {disabled: !$root.enableRemove($data)}" title="Remove"><i class="fa fa-trash-o"></i></div>
470 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_SELECT), click: function() { if ($root.enableSelect($data)) { $root.loadFile($data, false); } else { return; } }, css: {disabled: !$root.enableSelect($data)}" title="Load"><i class="fa fa-folder-open"></i></div>
471 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.PRINT), click: function() { if ($root.enableSelectAndPrint($data)) { $root.loadFile($data, true); } else { return; } }, css: {disabled: !$root.enableSelectAndPrint($data)}" title="Load and Print"><i class="fa fa-print"></i></div>
472 </div>
473 </script>
474
475 <script type="text/html" id="files_template_model">
476 <div class="title muted" data-bind="text: display"></div>
477 <div class="internal" data-bind="visible: name != display">Internal: <span data-bind="text: name"></span></div>
478 <div class="uploaded">Uploaded: <span data-bind="text: formatTimeAgo(date), attr: {title: formatDate(date)}"></span></div>
479 <div class="size">Size: <span data-bind="text: formatSize(size)"></span></div>
480 <div class="btn-group action-buttons">
481 <a class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_DOWNLOAD), attr: {href: $root.downloadLink($data), css: {disabled: !$root.downloadLink($data)}}" title="Download"><i class="fa fa-download"></i></a>
482 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_DELETE), click: function(data, event) { if ($root.enableRemove($data)) { $root.removeFile($data, event); } else { return; } }, css: {disabled: !$root.enableRemove($data)}" title="Remove"><i class="fa fa-trash-o"></i></div>
483 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.SLICE), click: function() { if ($root.enableSlicing($data)) { $root.sliceFile($data); } else { return; } }, css: {disabled: !$root.enableSlicing($data)}" title="Slice"><i class="fa fa-magic"></i></div>
484 </div>
485 </script>
486
487 <script type="text/html" id="files_template_folder">
488 <div class="title clickable" data-bind="click: $root.changeFolder, style: { 'font-weight': $root.listHelper.isSelected($data) ? 'bold' : 'normal' }"><i class="fa fa-folder-open"></i> <span data-bind="text: display"></span></div>
489 <div class="internal" data-bind="visible: name != display">Internal: <span data-bind="text: name"></span></div>
490 <div class="size">Size: <span data-bind="text: formatSize(size)"></span></div>
491 <div class="btn-group action-buttons">
492 <div class="btn btn-mini" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.FILES_DELETE), click: function(data, event) { if ($root.enableRemove($data)) { $root.removeFolder($data, event); } else { return; } }, css: {disabled: !$root.enableRemove($data)}" title="Remove"><i class="fa fa-trash-o"></i></div>
493 </div>
494 </script>
495</div>
496<div class="text-right muted" data-bind="attr: {title: diskusageString}, css: {'text-error': diskusageCritical}, style: {'font-weight': diskusageCritical() || diskusageWarning() ? 'bold' : 'normal'}">
497 <small>Free: <span data-bind="text: freeSpaceString"></span> / Total: <span data-bind="text: totalSpaceString"></span> <i class="fa fa-exclamation-triangle" data-bind="visible: diskusageWarning" style="display: none"></i></small>
498</div>
499<div style="display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.FILES_UPLOAD)">
500 <div class="row-fluid folder-button">
501 <span class="btn addfolder-button span12" data-bind="click: $root.showAddFolderDialog">
502 <i class="fa fa-folder"></i> Create folder...
503 </span>
504 </div>
505 <div class="row-fluid upload-buttons">
506
507 <span class="btn btn-primary fileinput-button span6" style="margin-bottom: 10px">
508 <i class="fa fa-upload"></i>
509 <span>Upload</span>
510 <input id="gcode_upload" accept=".gcode,.gco,.g" type="file" name="file" class="fileinput-button">
511 </span>
512 <span class="btn btn-primary fileinput-button span6" data-bind="enable: $root.isSdReady() && !$root.isPrinting(), css: {disabled: !$root.isSdReady() || $root.isPrinting()}" style="margin-bottom: 10px">
513 <i class="fa fa-upload"></i>
514 <span>Upload to SD</span>
515 <input id="gcode_upload_sd" accept=".gcode,.gco,.g" type="file" name="file" class="fileinput-button" data-bind="enable: isSdReady()">
516 </span>
517
518 </div>
519 <div id="gcode_upload_progress" class="progress progress-text-centered">
520 <span class="progress-text-back" data-bind="text: uploadProgressText"></span>
521 <div class="bar">
522 <span class="progress-text-front" data-bind="copyWidth: ':parent :parent :parent :parent form', text: uploadProgressText"></span>
523 </div>
524 </div>
525 <div>
526 <small class="muted">Hint: You can also drag and drop files on this page to upload them.</small>
527 </div>
528</div>
529 </div>
530 </div>
531 </div>
532 <!-- /ko -->
533
534 </div>
535
536
537 <!-- Tabs -->
538
539 <div class="tabbable span8">
540 <ul class="nav nav-tabs" id="tabs">
541
542
543 <!-- ko allowBindings: false -->
544 <li id="temp_link"
545 class=""
546 data-bind="visible: loginState.hasAnyPermissionKo(access.permissions.STATUS, access.permissions.CONTROL)() && visible()"
547 style="display: none;"
548 >
549 <a href="#temp" data-toggle="tab">Temperature</a>
550 </li>
551 <!-- /ko -->
552
553
554 <!-- ko allowBindings: false -->
555 <li id="control_link"
556 class=""
557 data-bind="visible: loginState.hasAnyPermissionKo(access.permissions.WEBCAM, access.permissions.CONTROL)"
558 style="display: none;"
559 >
560 <a href="#control" data-toggle="tab">Control</a>
561 </li>
562 <!-- /ko -->
563
564
565 <!-- ko allowBindings: false -->
566 <li id="gcode_link"
567 class=""
568 data-bind="visible: loginState.hasPermissionKo(access.permissions.GCODE_VIEWER)"
569 style="display: none;"
570 >
571 <a href="#gcode" data-toggle="tab">GCode Viewer</a>
572 </li>
573 <!-- /ko -->
574
575
576 <!-- ko allowBindings: false -->
577 <li id="term_link"
578 class=""
579 data-bind="visible: loginState.hasPermissionKo(access.permissions.MONITOR_TERMINAL)"
580 style="display: none;"
581 >
582 <a href="#term" data-toggle="tab">Terminal</a>
583 </li>
584 <!-- /ko -->
585
586
587 <!-- ko allowBindings: false -->
588 <li id="timelapse_link"
589 class=""
590 data-bind="visible: loginState.hasPermissionKo(access.permissions.TIMELAPSE_LIST)"
591 style="display: none;"
592 >
593 <a href="#timelapse" data-toggle="tab">Timelapse</a>
594 </li>
595 <!-- /ko -->
596
597 </ul>
598
599 <div id="tabs_content" class="tab-content">
600
601
602 <!-- ko allowBindings: false -->
603 <div id="temp"
604 class="tab-pane active"
605 data-bind="visible: loginState.hasAnyPermissionKo(access.permissions.STATUS, access.permissions.CONTROL)() && visible()"
606 style="display: none;"
607 >
608
609 <div class="row-fluid">
610 <div id="temperature-graph" style="width: 100%"></div>
611 </div>
612
613<div class="row-fluid">
614
615 <table id="temperature-table" class="table table-bordered table-hover" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL)">
616 <tr>
617 <th class="temperature_tool"></th>
618 <th class="temperature_actual" title="Current actual temperature as reported by your printer">Actual</th>
619 <th class="temperature_target" title="Current target temperature as reported by your printer">Target</th>
620 <th class="temperature_offset" title="Offset to apply to temperature commands sent from files">Offset</th>
621 </tr>
622 <!-- ko foreach: tools -->
623 <tr data-bind="template: { name: 'temprow-template' }"></tr>
624 <!-- /ko -->
625 <tr data-bind="template: { name: 'temprow-template', data: bedTemp }, visible: hasBed"></tr>
626 <tr data-bind="template: { name: 'temprow-template', data: chamberTemp }, visible: hasChamber"></tr>
627 </table>
628
629 <script type="text/html" id="temprow-template">
630 <th class="temperature_tool" data-bind="text: name, attr: {title: name}"></th>
631 <td class="temperature_actual" data-bind="html: formatTemperature(actual()), attr: {title: formatTemperature(actual())}"></td>
632 <td class="temperature_target">
633 <form class="form-inline" style="margin:0" data-bind="submit: function(element) { $root.setTarget($data, element) }">
634 <div class="input-prepend input-append">
635 <button type="button" class="btn btn-input-dec" data-bind="click: $root.decrementTarget, enable: $root.isOperational() && $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)()" title="Fine adjust: -1°C"><i class="fa fa-minus"></i></button>
636 <input type="number" min="0" max="999" class="input-mini input-nospin" style="width: 30px" data-bind="attr: {placeholder: cleanTemperature(target(), 1)}, value: newTarget, valueUpdate: 'input', enable: $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)() && $root.isOperational(), event: { focus: function(d, e) {$root.handleFocus(e, 'target', $data) } }">
637 <span class="add-on">°C</span>
638 <button type="button" class="btn btn-input-inc" data-bind="click: $root.incrementTarget, enable: $root.isOperational() && $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)()" title="Fine adjust: +1°C"><i class="fa fa-plus"></i></button>
639 </div>
640 <div class="btn-group">
641 <button type="submit" data-bind="enable: $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)() && $root.isOperational() && $data.newTargetValid()" class="btn btn-primary" title="Set"><i class="fa fa-check"></i></button>
642 <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" data-bind="enable: $root.isOperational() && $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)()">
643 <span class="caret"></span>
644 </button>
645 <ul class="dropdown-menu">
646 <li>
647 <a href="javascript:void(0)" data-bind="click: $root.setTargetToZero">Off</a>
648 </li>
649 <li class="divider"></li>
650 <!-- ko foreach: $root.temperature_profiles -->
651 <li>
652 <a href="javascript:void(0)" data-bind="click: function() { $root.setTargetFromProfile($parent, $data);}, text: $root.profileText($parent, $data)"></a>
653 </li>
654 <!-- /ko -->
655 </ul>
656 </div>
657 </form>
658 </td>
659 <td class="temperature_offset">
660 <form class="form-inline" style="margin:0">
661 <div class="input-append">
662 <span class="input-mini uneditable-input text-right" style="width: 30px" data-bind="text: offset"></span>
663 <span class="add-on">°C</span>
664 <button class="btn" title="Change Offset" data-bind="click: $root.changeOffset, enable: $root.isOperational() && $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)()"><i class="fa fa-pencil"></i></button>
665 <button class="btn" title="Delete Offset" data-bind="click: $root.setOffsetToZero, enable: $root.isOperational() && $root.loginState.hasPermissionKo($root.access.permissions.CONTROL)()"><i class="fa fa-trash"></i></button>
666 </div>
667 </form>
668 </td>
669 </script>
670</div>
671
672 </div>
673 <!-- /ko -->
674
675
676 <!-- ko allowBindings: false -->
677 <div id="control"
678 class="tab-pane"
679 data-bind="visible: loginState.hasAnyPermissionKo(access.permissions.WEBCAM, access.permissions.CONTROL)"
680 style="display: none;"
681 >
682
683
684<div class="jog-panel" style="display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL)">
685 <!-- XY jogging control panel -->
686 <div id="control-jog-xy" class="jog-panel">
687 <h1>X/Y</h1>
688 <div>
689 <button id="control-yinc" class="btn box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('y',1) }"><i class="fa fa-arrow-up"></i></button>
690 </div>
691 <div>
692 <button id="control-xdec" class="btn box pull-left" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('x',-1) }"><i class="fa fa-arrow-left"></i></button>
693 <button id="control-xyhome" class="btn box pull-left" data-bind="enable: isOperational() && !isPrinting() , click: function() { $root.sendHomeCommand(['x', 'y']) }"><i class="fa fa-home"></i></button>
694 <button id="control-xinc" class="btn box pull-left" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('x',1) }"><i class="fa fa-arrow-right"></i></button>
695 </div>
696 <div>
697 <button id="control-ydec" class="btn box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('y',-1) }"><i class="fa fa-arrow-down"></i></button>
698 </div>
699 </div>
700 <!-- Z jogging control panel -->
701 <div id="control-jog-z" class="jog-panel">
702 <h1>Z</h1>
703 <div>
704 <button id="control-zinc" class="btn box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('z',1) }"><i class="fa fa-arrow-up"></i></button>
705 </div>
706 <div>
707 <button id="control-zhome" class="btn box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendHomeCommand(['z']) }"><i class="fa fa-home"></i></button>
708 </div>
709 <div>
710 <button id="control-zdec" class="btn box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendJogCommand('z',-1) }"><i class="fa fa-arrow-down"></i></button>
711 </div>
712 </div>
713
714 <!-- Jog distance -->
715 <div class="distance">
716 <div class="btn-group" data-toggle="buttons-radio" id="jog_distance">
717 <!-- ko foreach: distances -->
718 <button type="button" class="btn distance" data-bind="enable: $root.isOperational() && !$root.isPrinting(), text: $data, click: function() { $root.distance($data) }, css: { active: $root.distance() === $data }, attr: { id: 'control-distance' + $root.stripDistanceDecimal($data) }"></button>
719 <!-- /ko -->
720 </div>
721 </div>
722
723 <!-- Feed rate -->
724 <div id="control-jog-feedrate" class="jog-panel">
725 <input type="number" style="width: 153px" data-bind="slider: {min: 50, max: 150, step: 1, value: feedRate, tooltip: 'hide'}">
726 <button class="btn btn-block" style="width: 169px" data-bind="enable: isOperational(), click: function() { $root.sendFeedRateCommand() }">Feed rate:<span data-bind="text: feedRate() + '%'"></span></button>
727 </div>
728</div>
729<!-- Extrusion control panel -->
730<div id="control-jog-extrusion" class="jog-panel" style="display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL)() && tools().length > 0">
731 <h1>Tool (E)</h1>
732 <div>
733 <div class="btn-group control-box">
734 <button class="btn dropdown-toggle" data-toggle="dropdown" data-bind="enable: isOperational() && !isPrinting() && !isPaused()">
735 Select Tool...
736 <span class="caret"></span>
737 </button>
738 <ul class="dropdown-menu" data-bind="foreach: tools">
739 <li><a href="#" data-bind="click: $root.sendSelectToolCommand, text: name(), enable: $root.isOperational() && !$root.isPrinting() && !$root.isPaused()"></a></li>
740 </ul>
741 </div>
742 <div class="input-append control-box">
743 <input type="text" class="input-mini text-right" data-bind="value: extrusionAmount, enable: isOperational() && !isPrinting(), attr: {placeholder: settings.printer_defaultExtrusionLength}">
744 <span class="add-on">mm</span>
745 </div>
746 <button class="btn btn-block control-box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendExtrudeCommand() }">Extrude</button>
747 <button class="btn btn-block control-box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendRetractCommand() }">Retract</button>
748
749 <!-- Flow rate -->
750 <input style="width: 100px" type="number" data-bind="slider: {min: 75, max: 125, step: 1, value: flowRate, tooltip: 'hide'}">
751 <button class="btn btn-block control-box" data-bind="enable: isOperational(), click: function() { $root.sendFlowRateCommand() }">Flow rate:<span data-bind="text: flowRate() + '%'"></span></button>
752 </div>
753</div>
754<!-- General control panel -->
755<div id="control-jog-general" class="jog-panel" style="display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL)">
756 <h1>General</h1>
757 <div>
758 <button class="btn btn-block control-box" data-bind="enable: isOperational() && !isPrinting(), click: function() { $root.sendCustomCommand({type:'command',command:'M18'}) }">Motors off</button>
759 <button class="btn btn-block control-box" data-bind="enable: isOperational(), click: function() { $root.sendCustomCommand({type:'command',command:'M106 S255'}) }">Fan on</button>
760 <button class="btn btn-block control-box" data-bind="enable: isOperational(), click: function() { $root.sendCustomCommand({type:'command',command:'M106 S0'}) }">Fan off</button>
761 </div>
762</div>
763
764<!-- Container for custom controls -->
765<div id="control-jog-custom" style="clear: both; display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL), template: { name: $root.displayMode, foreach: controls }"></div>
766
767<!-- Templates for custom controls -->
768<script type="text/html" id="customControls_containerTemplate_nameless">
769 <div class="custom_section">
770 <!-- ko template: { name: 'customControls_containerTemplate', data: $data } --><!-- /ko -->
771 </div>
772</script>
773<script type="text/html" id="customControls_containerTemplate_collapsable">
774 <div class="custom_section">
775 <h1 data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.custom_section', container: '> div' }"><i class="fa" data-bind="css: {'fa-caret-down': !collapsed, 'fa-caret-right': collapsed}"></i> <span data-bind="text: name"></span></h1>
776 <!-- ko template: { name: 'customControls_containerTemplate', data: $data } --><!-- /ko -->
777 </div>
778</script>
779<script type="text/html" id="customControls_containerTemplate">
780 <!-- ko if: layout == 'vertical' -->
781 <div class="custom_section_vertical" data-bind="template: { name: $root.displayMode, foreach: children }, css: {hide: collapsed && name}"></div>
782 <!-- /ko -->
783
784 <!-- ko if: layout == 'horizontal' -->
785 <div class="custom_section_horizontal" data-bind="template: { name: $root.displayMode, foreach: children }, css: {hide: collapsed && name}"></div>
786 <!-- /ko -->
787
788 <!-- ko if: layout == 'horizontal_grid' -->
789 <div class="row-fluid custom_section_horizontal_grid" data-bind="css: {hide: collapsed && name}">
790 <!-- ko foreach: children -->
791 <div data-bind="template: { name: $root.displayMode }, css: $root.rowCss($data)"></div>
792 <!-- /ko -->
793 </div>
794 <!-- /ko -->
795</script>
796<script type="text/html" id="customControls_controlTemplate">
797 <form class="form-inline custom_control">
798 <!-- ko template: { name: 'customControls_controlTemplate_input', data: $data, if: $data.hasOwnProperty('input') } --><!-- /ko -->
799 <!-- ko template: { name: 'customControls_controlTemplate_command', data: $data, if: $data.hasOwnProperty('command') || $data.hasOwnProperty('commands') || $data.hasOwnProperty('script') || $data.hasOwnProperty('javascript') } --><!-- /ko -->
800 <!-- ko template: { name: 'customControls_controlTemplate_output', data: $data, if: $data.hasOwnProperty('output') } --><!-- /ko -->
801 </form>
802</script>
803<script type="text/html" id="customControls_controlTemplate_input">
804 <!-- ko foreach: input -->
805 <label style="cursor: default" data-bind="text: name"></label>
806 <!-- ko if: slider -->
807 <input type="number" style="width: 100px" data-bind="slider: {value: value, min: slider.min, max: slider.max, step: slider.step}">
808 <!-- /ko -->
809 <!-- ko ifnot: slider -->
810 <input type="text" class="input-small" data-bind="attr: {placeholder: name}, value: value">
811 <!-- /ko -->
812 <!-- /ko -->
813</script>
814<script type="text/html" id="customControls_controlTemplate_output">
815 <label style="cursor: default" data-bind="text: output"></label>
816</script>
817<script type="text/html" id="customControls_controlTemplate_command">
818 <button class="btn" data-bind="text: name, css: additionalClasses, enable: $root.isCustomEnabled($data), click: function() { $root.clickCustom($data) }"></button>
819</script>
820<!-- End of templates for custom controls -->
821 </div>
822 <!-- /ko -->
823
824
825 <!-- ko allowBindings: false -->
826 <div id="gcode"
827 class="tab-pane"
828 data-bind="visible: loginState.hasPermissionKo(access.permissions.GCODE_VIEWER)"
829 style="display: none;"
830 >
831 <div data-bind="visible: !waitForApproval()">
832 <div id="canvas_container" class="canvas_container" tabindex="0" data-bind="event: { keydown: onKeyDown, mouseover: onMouseOver, mouseout: onMouseOut }">
833 <input id="gcode_slider_layers" type="text">
834 <canvas id="gcode_canvas" width="568" height="568"></canvas>
835 <input id="gcode_slider_commands" type="text" style="width: 554px">
836 </div>
837
838 <div class="layer-buttons btn-group-toolbar row-fluid">
839 <button type="button" class="btn btn-primary btn-medium span6" data-bind = "click: decrementLayer, enable: layerSelectionEnabled() && layerDownEnabled()">
840 <i class="fa fa-arrow-left"></i>
841 <span>Previous layer</span>
842 </button>
843 <button type="button" class="btn btn-primary btn-medium span6" data-bind = "click: incrementLayer, enable: layerSelectionEnabled() && layerUpEnabled()">
844 <span>Next layer</span>
845 <i class="fa fa-arrow-right"></i>
846 </button>
847 </div>
848
849 <div class="progress progress-text-centered">
850 <span class="progress-text-back" data-bind="text: ui_progress_text"></span>
851 <div class="bar" style="width: 0;" data-bind="style: { width: ui_progress_percentage() + '%' }">
852 <span class="progress-text-front" data-bind="copyWidth: ':parent :parent', text: ui_progress_text"></span>
853 </div>
854 </div>
855
856 <div class="row-fluid">
857 <div class="span7">
858 <h1>Model info</h1>
859 <p data-bind="html: ui_modelInfo"></p>
860
861 <h1>Layer info</h1>
862 <p data-bind="html: ui_layerInfo"></p>
863 </div>
864 <div class="span5">
865 <h1>Renderer options</h1>
866
867 <p>
868 <label class="checkbox">
869 <input type="checkbox" data-bind="checked: renderer_syncProgress">Sync with job progress
870 </label>
871 </p>
872 <p>
873 <label class="checkbox">
874 <input type="checkbox" data-bind="checked: renderer_centerViewport">Center viewport on model
875 </label>
876 <label class="checkbox">
877 <input type="checkbox" data-bind="checked: renderer_zoomOnModel">Zoom in on model
878 </label>
879 </p>
880
881 <p>
882 <label class="checkbox">
883 <input type="checkbox" data-bind="checked: renderer_showMoves">Show moves
884 </label>
885 <label class="checkbox">
886 <input type="checkbox" data-bind="checked: renderer_showRetracts">Show retracts
887 </label>
888 <label class="checkbox">
889 <input type="checkbox" data-bind="checked: renderer_showPrinthead">Show approx. print head position
890 </label>
891 </p>
892
893 <p>
894 <label class="checkbox">
895 <input type="checkbox" data-bind="checked: renderer_showPrevious">Also show previous layer
896 </label>
897 <label class="checkbox">
898 <input type="checkbox" data-bind="checked: renderer_showCurrent">Also show current layer
899 </label>
900 <label class="checkbox">
901 <input type="checkbox" data-bind="checked: renderer_showNext">Also show next layer
902 </label>
903 </p>
904
905 <p>
906 <button class="btn btn-block" data-bind="click: reload, enable: enableReload">Reload</button>
907 </p>
908
909 <div class="advanced_options">
910 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.advanced_options', container: '.hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
911 <div class="hide">
912 <p>
913 <label class="checkbox">
914 <input type="checkbox" data-bind="checked: renderer_showFullSize">Show visited bounding box
915 </label>
916 <label class="checkbox">
917 <input type="checkbox" data-bind="checked: renderer_showBoundingBox">Show printed bounding box
918 </label>
919 </p>
920 <p>
921 <label class="checkbox">
922 <input type="checkbox" data-bind="checked: reader_hideEmptyLayers">Hide empty layers <span class="label">Causes reload</span>
923 </label>
924 <label class="checkbox">
925 <input type="checkbox" data-bind="checked: reader_sortLayers">Sort layers <span class="label">Causes reload</span>
926 </label>
927 </p>
928 <p>
929 <button class="btn btn-block" data-bind="click: resetOptions">Reset options</button>
930 </p>
931 </div>
932 </div>
933 </div>
934 </div>
935
936 <div class="muted">
937 <small>
938 Note that the time and usage values in this tab are <strong>estimated</strong> by the GCODE viewer in your
939 browser and might differ from the values <strong>estimated</strong> by the server that are displayed in the
940 "State" and "Files" panels in the sidebar due to slightly different implementations. Also note that these
941 <strong>estimated</strong> values may be inaccurate since they can also take information present in the
942 GCODE file into account.
943 </small>
944 </div>
945</div>
946<div data-bind="visible: waitForApproval">
947 <h1>Warning</h1>
948 <p>
949 You've selected <strong data-bind="text: selectedFile.name"></strong> for printing which has a size of
950 <strong data-bind="text: formatSize(selectedFile.size())"></strong>. Depending on your machine this
951 might be too large for rendering and cause your browser to become unresponsive or crash.
952 </p>
953
954 <p>
955 Are you sure you want to visualize this file nevertheless?
956 </p>
957
958 <button class="btn btn-warning btn-block" data-bind="click: approveLargeFile">
959 Yes, please visualize <span data-bind="text: selectedFile.name"></span> regardless of its size
960 </button>
961</div>
962 </div>
963 <!-- /ko -->
964
965
966 <!-- ko allowBindings: false -->
967 <div id="term"
968 class="tab-pane"
969 data-bind="visible: loginState.hasPermissionKo(access.permissions.MONITOR_TERMINAL)"
970 style="display: none;"
971 >
972 <div class="terminal">
973 <pre id="terminal-output" class="pre-scrollable pre-output" data-bind="foreach: displayedLines, visible: fancyFunctionality(), click: function(){ gotoTerminalCommand(); }, event: { scroll: terminalScrollEvent }"><span data-bind="text: line + '\n', css: {muted: type == 'filtered' || type == 'cut'}"></span></pre>
974 <pre id="terminal-output-lowfi" style="display: none" class="pre-scrollable" data-bind="text: plainLogOutput, visible: !fancyFunctionality()"></pre>
975 <div id="terminal-sendpanel" style="display: none;" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL)">
976 <div class="input-block-level input-append">
977 <input type="text" id="terminal-command" data-bind="value: command, event: { keyup: function(d,e) { return handleKeyUp(e); }, keydown: function(d,e) { return handleKeyDown(e); } }, enable: isOperational() && loginState.isUser()" autocomplete="off">
978 <a class="btn add-on" id="terminal-send" data-bind="click: sendCommand, enable: isOperational() && loginState.isUser()">Send</a>
979 </div>
980 </div>
981 <small class="pull-left" data-bind="visible: fancyFunctionality()">
982 <button class="btn btn-mini" data-bind="click: toggleAutoscroll, css: {active: autoscrollEnabled}">Autoscroll</button>
983 <span data-bind="text: lineCount, visible: enableFancyFunctionality"></span>
984 <span data-bind="visible: !autoscrollEnabled() && enableFancyFunctionality()" style="display: none">(<a href="javascript:void(0)" data-bind="click: scrollToEnd">Scroll to end</a>)</span>
985 </small>
986 <small class="pull-right">
987 <a href="javascript:void(0)" data-bind="click: copyAll"><i class="fa fa-copy" title="Copy all"></i> Copy all</a><br>
988 <a href="javascript:void(0)" data-bind="click: clearAllLogs"><i class="fa fa-trash-o" title="Clear log window"></i> Clear all</a>
989 </small>
990 <small class="pull-left text-warning" data-bind="visible: !fancyFunctionality()" style="display: none">
991 For performance reasons only a limited amount of terminal functionality is enabled right now.
992 </small>
993</div>
994
995<div class="row-fluid">
996 <div class="span6" id="terminal-filterpanel">
997 <div data-bind="foreach: filters, visible: fancyFunctionality()">
998 <label class="checkbox">
999 <input type="checkbox" data-bind="attr: { value: regex }, checked: $parent.activeFilters"> <span data-bind="text: name"></span>
1000 </label>
1001 </div>
1002 </div>
1003</div>
1004
1005<div>
1006 <div><small><a href="#" class="muted" data-bind="visible: loginState.hasPermissionKo(access.permissions.CONTROL), toggleContent: { class: 'fa-caret-right fa-caret-down', container: '#term .hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
1007 <div class="hide">
1008 <p class="row-fluid">
1009 <button class="btn btn-primary btn-block" type="button" data-bind="click: fakeAck, enable: isOperational()">Fake Acknowledgement</button>
1010 <small class="muted">If acknowledgements ("ok"s) sent by the firmware get lost due to issues with the serial communication to your printer, OctoPrint's communication with it can become stuck. If that happens, this can help. Please be advised that such occurrences hint at general communication issues with your printer which will probably negatively influence your printing results and which you should therefore try to resolve!</small>
1011 </p>
1012 <p class="row-fluid">
1013 <button class="btn btn-danger span6" type="button" data-bind="toggle: forceFancyFunctionality">Force fancy functionality</button>
1014 <button class="btn btn-danger span6" type="button" data-bind="toggle: forceTerminalLogDuringPrinting">Force terminal output during printing</button>
1015 <small class="muted">Some functionality of the terminal will be disabled if OctoPrint detects that your browser is too slow for that. You may force it back on here, but be aware that this might make your browser unresponsive.</small>
1016 </p>
1017 </div>
1018</div>
1019 </div>
1020 <!-- /ko -->
1021
1022
1023 <!-- ko allowBindings: false -->
1024 <div id="timelapse"
1025 class="tab-pane"
1026 data-bind="visible: loginState.hasPermissionKo(access.permissions.TIMELAPSE_LIST)"
1027 style="display: none;"
1028 >
1029 <div data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_ADMIN)">
1030 <div style="display: none;" data-bind="visible: settings.webcam_snapshotUrl() && settings.webcam_ffmpegPath()">
1031 <div class="alert" data-bind="visible: isPrinting()">
1032 Take note that timelapse configuration is disabled while your printer is printing.
1033 </div>
1034
1035 <h1>Timelapse Configuration</h1>
1036
1037 <form class="form-horizontal">
1038 <div class="control-group">
1039 <label class="control-label" for="webcam_timelapse_mode">Timelapse Mode</label>
1040 <div class="controls">
1041 <select id="webcam_timelapse_mode" data-bind="value: timelapseType, enable: !isPrinting()">
1042 <option value="off">Off</option>
1043 <option value="timed">Timed</option>
1044 <option value="zchange">On Z Change</option>
1045 </select>
1046 <span class="help-block" data-bind="visible: timelapseType() == 'zchange'"><span class="label label-info">Note</span> Does not work when printing from the printer's SD Card (no way to detect the change in Z reliably). Use "Timed" mode for those prints instead.</span>
1047 </div>
1048 </div>
1049
1050 <div id="webcam_timelapse_mindelay" class="control-group" data-bind="visible: timelapseType() == 'zchange'">
1051 <label class="control-label" for="webcam_timelapse_minDelay">Minimum interval</label>
1052 <div class="controls">
1053 <div class="input-append">
1054 <input type="number" min="1" class="input-mini" id="webcam_timelapse_minDelay" data-bind="value: timelapseMinDelay, valueUpdate: 'afterkeydown', enable: !isPrinting()">
1055 <span class="add-on">sec</span>
1056 </div>
1057 <span class="help-block">OctoPrint will rate limit snapshots to this minimum interval. This it to prevent against performance issues with vase mode/continuous z prints.</span>
1058 </div>
1059 </div>
1060
1061 <div id="webcam_timelapse_timedsettings" class="control-group" data-bind="visible: intervalInputEnabled">
1062 <label class="control-label" for="webcam_timelapse_interval">Snapshot interval</label>
1063 <div class="controls">
1064 <div class="input-append">
1065 <input type="number" min="1" class="input-mini" id="webcam_timelapse_interval" data-bind="value: timelapseTimedInterval, valueUpdate: 'afterkeydown', enable: !isPrinting()">
1066 <span class="add-on">sec</span>
1067 </div>
1068 </div>
1069 </div>
1070
1071 <div class="control-group">
1072 <label class="control-label" for="webcam_timelapse_fps">Timelapse frame rate</label>
1073 <div class="controls">
1074 <div class="input-append">
1075 <input type="number" min="1" class="input-mini" id="webcam_timelapse_fps" data-bind="value: timelapseFps, valueUpdate: 'afterkeydown', enable: !isPrinting() && timelapseTypeSelected()">
1076 <span class="add-on">fps</span>
1077 </div>
1078 </div>
1079 </div>
1080
1081 <div class="control-group">
1082 <label class="control-label" for="webcam_timelapse_postRoll">Timelapse post roll</label>
1083 <div class="controls">
1084 <div class="input-append">
1085 <input type="number" min="0" class="input-mini" id="webcam_timelapse_postRoll" data-bind="value: timelapsePostRoll, valueUpdate: 'afterkeydown', enable: !isPrinting() && timelapseTypeSelected()">
1086 <span class="add-on">sec</span>
1087 </div>
1088 <span class="help-block">OctoPrint will use the final picture to add this many seconds to the end of your rendered timelapse.</span>
1089 </div>
1090 </div>
1091
1092 <div id="webcam_timelapse_retractionsettings" class="control-group" data-bind="visible: timelapseType() == 'zchange'">
1093 <label class="control-label" for="webcam_timelapse_retractionZHop">Retraction Z-Hop</label>
1094 <div class="controls">
1095 <div class="input-append">
1096 <input type="number" min="0.0" class="input-mini" id="webcam_timelapse_retractionZHop" data-bind="value: timelapseRetractionZHop, valueUpdate: 'afterkeydown', enable: !isPrinting()">
1097 <span class="add-on">mm</span>
1098 </div>
1099 <span class="help-block">Enter the retraction z-hop used in the firmware or the gcode file to trigger snapshots for the timelapse only if a real layer change happens. For this to work properly your retraction z-hop has to be different from your layerheight!</span>
1100 </div>
1101 </div>
1102
1103 <div class="control-group">
1104 <div class="controls">
1105 <label class="checkbox">
1106 <input type="checkbox" data-bind="checked: persist"> Save as default
1107 <span class="help-block">Check this to make your selected timelapse mode and options persist across restarts.</span>
1108 </label>
1109 </div>
1110 </div>
1111
1112 <div class="control-group">
1113 <div class="controls">
1114 <strong class="text-center text-block" data-bind="visible: saveButtonEnabled">You have unsaved changes. Don't forget to save them.</strong>
1115 <button class="btn btn-primary btn-block" data-bind="click: save, enable: saveButtonEnabled">Save changes</button>
1116 <button class="btn btn-block" data-bind="click: reset, enable: resetButtonEnabled">Reset to active configuration</button>
1117 </div>
1118 </div>
1119 </form>
1120 </div>
1121 <div class="alert" style="display: none" data-bind="visible: !settings.webcam_snapshotUrl() || !settings.webcam_ffmpegPath()">
1122 <p><strong>Timelapse not fully configured</strong></p>
1123 <p data-bind="visible: !loginState.isAdmin()">The snapshot URL and/or the path to FFMPEG are missing. To have this fixed, get in touch with an administrator of this OctoPrint instance.</p>
1124 <p data-bind="visible: loginState.isAdmin">The snapshot URL and/or the path to FFMPEG are missing. You can change both under "Settings" > "Webcam & Timelapse" > "Timelapse". If you don't have a webcam or don't want to enable timelapse support you can also just disable it there.</p>
1125 <p data-bind="visible: loginState.isUser"><small>
1126 Currently configured snapshot URL: <span data-bind="text: settings.webcam_snapshotUrl"></span><br/>
1127 Currently configured path to FFMPEG: <span data-bind="text: settings.webcam_ffmpegPath"></span>
1128 </small></p>
1129 </div>
1130</div>
1131
1132<h1 data-bind="visible: renderProgressBarString">Timelapse Render Progress</h1>
1133
1134<div id="render_progress" class="progress progress-text-centered" data-bind="visible: renderProgressBarString, css: { 'progress-striped' : renderAnimation, active : renderAnimation }">
1135 <span class="progress-text-back" data-bind="text: renderProgressBarString"></span>
1136 <div class="bar" data-bind="style: {width: renderProgressString() + '%'}">
1137 <span class="progress-text-front" data-bind="copyWidth: ':parent :parent', text: renderProgressBarString"></span>
1138 </div>
1139</div>
1140
1141<h1>Finished Timelapses</h1>
1142
1143<div class="pull-right">
1144 <div class="btn-group">
1145 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-wrench"></i> <span class="caret"></span></button>
1146 <ul class="dropdown-menu dropdown-menu-right">
1147 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('name'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> Sort by name (ascending)</a></li>
1148 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('date'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'date' ? 'visible' : 'hidden'}"></i> Sort by date (descending)</a></li>
1149 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('size'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> Sort by file size (descending)</a></li>
1150 </ul>
1151 </div>
1152</div>
1153<div class="pull-left" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)">
1154 <div class="btn-group">
1155 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-square-o"></i> <span class="caret"></span></button>
1156 <ul class="dropdown-menu">
1157 <li><a href="javascript:void(0)" data-bind="click: markFilesOnPage">Select all on this page</a></li>
1158 <li><a href="javascript:void(0)" data-bind="click: markAllFiles">Select all</a></li>
1159 <li class="divider"></li>
1160 <li><a href="javascript:void(0)" data-bind="click: clearMarkedFiles">Clear selection</a></li>
1161 </ul>
1162 </div>
1163 <button class="btn btn-small" data-bind="click: removeMarkedFiles, enable: markedForFileDeletion().length > 0">Delete selected</button>
1164</div>
1165<table class="table table-striped table-hover table-condensed table-hover" id="timelapse_files">
1166 <thead>
1167 <tr>
1168 <th class="timelapse_files_checkbox"></th>
1169 <th class="timelapse_files_name">Name</th>
1170 <th class="timelapse_files_size">Size</th>
1171 <th class="timelapse_files_action">Action</th>
1172 </tr>
1173 </thead>
1174 <tbody data-bind="foreach: listHelper.paginatedItems">
1175 <tr data-bind="attr: {title: name}">
1176 <td class="timelapse_files_checkbox"><input type="checkbox" data-bind="value: name, checked: $root.markedForFileDeletion, invisible: !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)()"></td>
1177 <td class="timelapse_files_name" data-bind="text: name"></td>
1178 <td class="timelapse_files_size" data-bind="text: size"></td>
1179 <td class="timelapse_files_action"><a href="javascript:void(0)" class="fa fa-trash-o" data-bind="click: function() { $parent.removeFile($data.name); }, css: {disabled: !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)() }"></a> | <a href="javascript:void(0)" class="fa fa-download" data-bind="css: {disabled: !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DOWNLOAD)()}, attr: { href: ($root.loginState.hasPermission($root.access.permissions.TIMELAPSE_DOWNLOAD)) ? $data.url : 'javascript:void(0)' }"></a></td>
1180 </tr>
1181 </tbody>
1182</table>
1183<div class="pagination pagination-mini pagination-centered">
1184 <ul>
1185 <li data-bind="css: {disabled: listHelper.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: listHelper.prevPage">«</a></li>
1186 </ul>
1187 <ul data-bind="foreach: listHelper.pages">
1188 <li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a></li>
1189 </ul>
1190 <ul>
1191 <li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}"><a href="javascript:void(0)" data-bind="click: listHelper.nextPage">»</a></li>
1192 </ul>
1193</div>
1194
1195
1196<div data-bind="visible: unrenderedListHelper.allSize">
1197 <div><small><a href="javascript:void(0)" class="muted" onclick="$(this).children().toggleClass('fa-caret-right fa-caret-down').parent().parent().parent().next().slideToggle('fast')"><i class="fa fa-caret-right"></i> Unrendered Timelapses</a></small></div>
1198 <div class="hide">
1199 <div class="pull-left" data-bind="visible: $root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)">
1200 <div class="btn-group">
1201 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-square-o"></i> <span class="caret"></span></button>
1202 <ul class="dropdown-menu">
1203 <li><a href="javascript:void(0)" data-bind="click: markUnrenderedOnPage">Select all on this page</a></li>
1204 <li><a href="javascript:void(0)" data-bind="click: markAllUnrendered">Select all</a></li>
1205 <li class="divider"></li>
1206 <li><a href="javascript:void(0)" data-bind="click: clearMarkedUnrendered">Clear selection</a></li>
1207 </ul>
1208 </div>
1209 <button class="btn btn-small" data-bind="click: removeMarkedUnrendered, enable: markedForUnrenderedDeletion().length > 0">Delete selected</button>
1210 </div>
1211 <table class="table table-striped table-hover table-condensed table-hover" id="timelapse_unrendered">
1212 <thead>
1213 <tr>
1214 <th class="timelapse_unrendered_checkbox"></th>
1215 <th class="timelapse_unrendered_name">Name</th>
1216 <th class="timelapse_unrendered_count">Frames</th>
1217 <th class="timelapse_unrendered_size">Size</th>
1218 <th class="timelapse_unrendered_action">Action</th>
1219 </tr>
1220 </thead>
1221 <tbody data-bind="foreach: unrenderedListHelper.paginatedItems">
1222 <tr data-bind="attr: {title: name}">
1223 <td class="timelapse_unrendered_checkbox"><input type="checkbox" data-bind="value: name, checked: $root.markedForUnrenderedDeletion, invisible: !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)()"></td>
1224 <td class="timelapse_unrendered_name" data-bind="text: name"></td>
1225 <td class="timelapse_unrendered_count" data-bind="text: count"></td>
1226 <td class="timelapse_unrendered_size" data-bind="text: size"></td>
1227 <td class="timelapse_unrendered_action">
1228 <span data-bind="visible: processing"><i class="fa fa-refresh fa-spin"></i></span>
1229 <span data-bind="visible: !processing"><a href="javascript:void(0)" title="Delete unrendered timelapse" class="fa fa-trash-o" data-bind="click: function() { $parent.removeUnrendered($data.name); }, css: {disabled: !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_DELETE)()}"></a> | <a href="javascript:void(0)" title="Render timelapse" class="fa fa-video-camera" data-bind="click: function() { if (!$root.isBusy()) { $parent.renderUnrendered($data.name); } else { return; } }, css: {disabled: $root.isBusy() || !$root.loginState.hasPermissionKo($root.access.permissions.TIMELAPSE_ADMIN)()}"></a></span>
1230 </td>
1231 </tr>
1232 </tbody>
1233 </table>
1234 <div class="pagination pagination-mini pagination-centered">
1235 <ul>
1236 <li data-bind="css: {disabled: unrenderedListHelper.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: unrenderedListHelper.prevPage">«</a></li>
1237 </ul>
1238 <ul data-bind="foreach: unrenderedListHelper.pages">
1239 <li data-bind="css: { active: $data.number === $root.unrenderedListHelper.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.unrenderedListHelper.changePage($data.number); }"></a></li>
1240 </ul>
1241 <ul>
1242 <li data-bind="css: {disabled: unrenderedListHelper.currentPage() === unrenderedListHelper.lastPage()}"><a href="javascript:void(0)" data-bind="click: unrenderedListHelper.nextPage">»</a></li>
1243 </ul>
1244 </div>
1245 </div>
1246</div>
1247 </div>
1248 <!-- /ko -->
1249
1250 </div>
1251 </div>
1252
1253 </div>
1254 <div class="footer">
1255 <ul id="footer_version" class="pull-left muted">
1256 <li><small>OctoPrint <span class="version"></span></small></li>
1257 </ul>
1258 <ul id="footer_links" class="pull-right">
1259 <li><a href="https://octoprint.org" target="_blank" rel="noreferrer noopener"><i class="fa fa-home"></i> Homepage</a></li>
1260 <li><a href="https://community.octoprint.org" target="_blank" rel="noreferrer noopener"><i class="fa fa-users"></i> Forum</a></li>
1261 <li><a href="https://faq.octoprint.org" target="_blank" rel="noreferrer noopener"><i class="fa fa-question-circle"></i> FAQ</a></li>
1262 <li><a href="http://docs.octoprint.org" target="_blank" rel="noreferrer noopener"><i class="fa fa-book"></i> Docs</a></li>
1263 <li id="footer_about"><a href="javascript:void(0)" data-bind="click: show"><i class="fa fa-info-circle"></i> About</a></li>
1264 </ul>
1265 </div>
1266 </div>
1267
1268 <!-- Dialogs -->
1269 <div id="settings_dialog" class="modal hide fade large" tabindex="-1" role="dialog" aria-labelledby="settings_dialog_label" aria-hidden="true">
1270 <div class="modal-header">
1271 <button type="button" class="close" data-dismiss="modal">×</button>
1272 <h3 id="settings_dialog_label">OctoPrint Settings <i class="fa fa-spinner fa-spin" data-bind="visible: receiving"></i></h3>
1273 </div>
1274 <div class="modal-body">
1275 <div class="full-sized-box">
1276 <div class="tabbable row-fluid">
1277 <div class="span3 scrollable" id="settings_dialog_menu">
1278 <ul class="nav nav-list" id="settingsTabs">
1279
1280
1281
1282
1283 <li class="nav-header">Printer</li>
1284
1285
1286
1287
1288
1289 <li id="settings_serialConnection_link"
1290
1291 class="active "
1292
1293 >
1294 <a href="#settings_serialConnection" data-toggle="tab">Serial Connection</a>
1295 </li>
1296
1297
1298
1299
1300
1301
1302 <li id="settings_printerProfiles_link"
1303
1304 class=" "
1305
1306 >
1307 <a href="#settings_printerProfiles" data-toggle="tab">Printer Profiles</a>
1308 </li>
1309
1310
1311
1312
1313
1314
1315 <li id="settings_temperature_link"
1316
1317 class=" "
1318
1319 >
1320 <a href="#settings_temperature" data-toggle="tab">Temperatures</a>
1321 </li>
1322
1323
1324
1325
1326
1327
1328 <li id="settings_terminalFilters_link"
1329
1330 class=" "
1331
1332 >
1333 <a href="#settings_terminalFilters" data-toggle="tab">Terminal Filters</a>
1334 </li>
1335
1336
1337
1338
1339
1340
1341 <li id="settings_gcodeScripts_link"
1342
1343 class=" "
1344
1345 >
1346 <a href="#settings_gcodeScripts" data-toggle="tab">GCODE Scripts</a>
1347 </li>
1348
1349
1350
1351
1352
1353 <li class="nav-header">Features</li>
1354
1355
1356
1357
1358
1359 <li id="settings_features_link"
1360
1361 class=" "
1362
1363 >
1364 <a href="#settings_features" data-toggle="tab">Features</a>
1365 </li>
1366
1367
1368
1369
1370
1371
1372 <li id="settings_webcam_link"
1373
1374 class=" "
1375
1376 >
1377 <a href="#settings_webcam" data-toggle="tab">Webcam & Timelapse</a>
1378 </li>
1379
1380
1381
1382
1383
1384
1385 <li id="settings_users_link"
1386
1387 class=" "
1388
1389 >
1390 <a href="#settings_users" data-toggle="tab">Access Control</a>
1391 </li>
1392
1393
1394
1395
1396
1397
1398 <li id="settings_gcodegcodevisualizer_link"
1399
1400 class=" "
1401
1402 >
1403 <a href="#settings_gcodegcodevisualizer" data-toggle="tab">GCODE Visualizer</a>
1404 </li>
1405
1406
1407
1408
1409
1410
1411 <li id="settings_api_link"
1412
1413 class=" "
1414
1415 >
1416 <a href="#settings_api" data-toggle="tab">API</a>
1417 </li>
1418
1419
1420
1421
1422
1423 <!-- ko allowBindings: false -->
1424 <li id="settings_plugin_appkeys_link"
1425 data-bind="allowBindings: true"
1426 class=" "
1427
1428 >
1429 <a href="#settings_plugin_appkeys" data-toggle="tab">Application Keys</a>
1430 </li>
1431 <!-- /ko -->
1432
1433
1434
1435
1436 <li class="nav-header">OctoPrint</li>
1437
1438
1439
1440
1441
1442 <li id="settings_server_link"
1443
1444 class=" "
1445
1446 >
1447 <a href="#settings_server" data-toggle="tab">Server</a>
1448 </li>
1449
1450
1451
1452
1453
1454
1455 <li id="settings_folders_link"
1456
1457 class=" "
1458
1459 >
1460 <a href="#settings_folders" data-toggle="tab">Folders</a>
1461 </li>
1462
1463
1464
1465
1466
1467
1468 <li id="settings_appearance_link"
1469
1470 class=" "
1471
1472 >
1473 <a href="#settings_appearance" data-toggle="tab">Appearance</a>
1474 </li>
1475
1476
1477
1478
1479
1480 <!-- ko allowBindings: false -->
1481 <li id="settings_plugin_logging_link"
1482 data-bind="allowBindings: true"
1483 class=" "
1484
1485 >
1486 <a href="#settings_plugin_logging" data-toggle="tab">Logging</a>
1487 </li>
1488 <!-- /ko -->
1489
1490
1491
1492
1493 <!-- ko allowBindings: false -->
1494 <li id="settings_plugin_pluginmanager_link"
1495 data-bind="allowBindings: true"
1496 class=" "
1497
1498 >
1499 <a href="#settings_plugin_pluginmanager" data-toggle="tab">Plugin Manager</a>
1500 </li>
1501 <!-- /ko -->
1502
1503
1504
1505
1506 <!-- ko allowBindings: false -->
1507 <li id="settings_plugin_softwareupdate_link"
1508 data-bind="allowBindings: true"
1509 class=" "
1510
1511 >
1512 <a href="#settings_plugin_softwareupdate" data-toggle="tab">Software Update</a>
1513 </li>
1514 <!-- /ko -->
1515
1516
1517
1518
1519 <!-- ko allowBindings: false -->
1520 <li id="settings_plugin_announcements_link"
1521 data-bind="allowBindings: true"
1522 class=" "
1523
1524 >
1525 <a href="#settings_plugin_announcements" data-toggle="tab">Announcements</a>
1526 </li>
1527 <!-- /ko -->
1528
1529
1530
1531
1532 <!-- ko allowBindings: false -->
1533 <li id="settings_plugin_backup_link"
1534 data-bind="allowBindings: true"
1535 class=" "
1536
1537 >
1538 <a href="#settings_plugin_backup" data-toggle="tab">Backup & Restore</a>
1539 </li>
1540 <!-- /ko -->
1541
1542
1543
1544
1545
1546 <li id="settings_plugin_tracking_link"
1547
1548 class=" "
1549
1550 >
1551 <a href="#settings_plugin_tracking" data-toggle="tab">Anonymous Usage Tracking</a>
1552 </li>
1553
1554
1555
1556
1557
1558
1559 <li id="settings_plugin_errortracking_link"
1560
1561 class=" "
1562
1563 >
1564 <a href="#settings_plugin_errortracking" data-toggle="tab">Error Tracking</a>
1565 </li>
1566
1567
1568
1569
1570
1571 <li class="nav-header">Plugins</li>
1572
1573
1574
1575
1576
1577 <li id="settings_plugin_action_command_prompt_link"
1578
1579 class=" "
1580
1581 >
1582 <a href="#settings_plugin_action_command_prompt" data-toggle="tab">Action Command Prompt</a>
1583 </li>
1584
1585
1586
1587 </ul>
1588 </div>
1589 <div class="tab-content span9 scrollable" id="settings_dialog_content">
1590
1591
1592
1593
1594
1595
1596
1597
1598 <div id="settings_serialConnection"
1599
1600 class="tab-pane active "
1601
1602 >
1603 <form class="form-horizontal">
1604 <ul class="nav nav-pills">
1605 <li class="active"><a href="#settings_serial_general" data-toggle="tab">General</a></li>
1606 <li><a href="#settings_serial_timeouts" data-toggle="tab">Intervals & timeouts</a></li>
1607 <li><a href="#settings_serial_protocol" data-toggle="tab">Firmware & protocol</a></li>
1608 <li><a href="#settings_serial_behaviour" data-toggle="tab">Behaviour</a></li>
1609 </ul>
1610
1611 <div class="tab-content">
1612 <div id="settings_serial_general" class="tab-pane active">
1613 <fieldset id="settings_serial_general_connection">
1614 <legend>Connection</legend>
1615 <div class="control-group" title="Serial port to connect to, setting this to AUTO will make OctoPrint try to automatically find the right setting">
1616 <label class="control-label" for="settings-serialPort">Serial Port</label>
1617 <div class="controls">
1618 <select id="settings-serialPort" data-bind="options: serial_portOptions, optionsCaption: 'AUTO', value: serial_port"></select>
1619 </div>
1620 </div>
1621 <div class="control-group" title="Serial baud rate to connect with, setting this to AUTO will make OctoPrint try to automatically find the right setting">
1622 <label class="control-label" for="settings-baudrate">Baudrate</label>
1623 <div class="controls">
1624 <select id="settings-baudrate" data-bind="options: serial_baudrateOptions, optionsCaption: 'AUTO', value: serial_baudrate"></select>
1625 </div>
1626 </div>
1627 <div class="control-group" title="Makes OctoPrint try to connect to the printer automatically during start up">
1628 <div class="controls">
1629 <label class="checkbox">
1630 <input type="checkbox" data-bind="checked: serial_autoconnect" id="settings-serialAutoconnect"> Auto-connect to printer on server start
1631 </label>
1632 </div>
1633 </div>
1634 <div class="control-group">
1635 <label class="control-label" for="settings-serialAdditionalPorts">Additional serial ports</label>
1636 <div class="controls">
1637 <textarea rows="4" class="block" id="settings-serialAdditionalPorts" data-bind="value: serial_additionalPorts"></textarea>
1638 <span class="help-inline">Use this to define additional <a href="http://docs.python.org/2/library/glob.html">glob patterns</a> matching serial ports to list for connecting against, e.g. <code>/dev/ttyAMA*</code>. One entry per line. Please note that ports will only be offered to connect to if they get also detected by the <em>operating system</em>. Adding a port here will not make it magically appear in OctoPrint. If the operating system doesn't see your printer you need to solve this first.</span>
1639 </div>
1640 </div>
1641 <div class="control-group">
1642 <label class="control-label" for="settings-serialAdditionalBaudrates">Additional baud rates</label>
1643 <div class="controls">
1644 <input type="text" class="input-block-level" id="settings-serialAdditionalBaudrates" data-bind="value: serial_additionalBaudrates">
1645 <span class="help-inline">Use this to define additional serial port baud rates to list for connecting with, e.g. <code>123456</code>. Comma separated.</span>
1646 </div>
1647 </div>
1648 <div class="control-group">
1649 <div class="controls">
1650 <label class="checkbox">
1651 <input type="checkbox" data-bind="checked: serial_exclusive" id="settings-serialExclusive"> Request exclusive access to the serial port
1652 <span class="help-block">Uncheck this if you are having problems connecting to your printer.</span>
1653 </label>
1654 </div>
1655 </div>
1656 <div class="control-group">
1657 <label class="control-label">Apply parity double open workaround</label>
1658 <div class="controls">
1659 <label class="radio">
1660 <input type="radio" name="useParityWorkaroundGroup" value="always" data-bind="checked: serial_useParityWorkaround" id="settings-serialUseParityWorkaroundAlways"> Always
1661 <span class="help-block">Use this if you are running into <a href="https://forum.arduino.cc/index.php?topic=91291.0" target="_blank" rel="noopener noreferer">this problem</a>.</span>
1662 </label>
1663 <label class="radio">
1664 <input type="radio" name="useParityWorkaroundGroup" value="detect" data-bind="checked: serial_useParityWorkaround" id="settings-serialUseParityWorkaroundPrint"> If detected as potentially needed
1665 </label>
1666 <label class="radio">
1667 <input type="radio" name="useParityWorkaroundGroup" value="never" data-bind="checked: serial_useParityWorkaround" id="settings-serialUseParityWorkaroundNever"> Never
1668 <span class="help-block">Use this if connecting to your printer fails with <code>(22, 'Invalid argument')</code>.</span>
1669 </label>
1670 </div>
1671 </div>
1672 </fieldset>
1673 <fieldset id="settings_serial_general_logging">
1674 <legend>Serial logging</legend>
1675 <div class="control-group">
1676 <div class="controls">
1677 <label class="checkbox">
1678 <input type="checkbox" data-bind="checked: serial_log" id="settings-serialLog"> Log communication to <code>serial.log</code> <span class="label label-important">Warning</span>
1679 <span class="help-block">While this can negatively impact performance, a <code>serial.log</code> can be incredibly useful for debugging any issues observed in the communication between OctoPrint and your printer.</span>
1680 </label>
1681 </div>
1682 </div>
1683 </fieldset>
1684 </div>
1685 <div id="settings_serial_timeouts" class="tab-pane">
1686 <fieldset id="settings_serial_timeouts_intervals">
1687 <legend>Query intervals</legend>
1688 <div class="control-group" title="Interval in which to poll for the temperature information from the printer">
1689 <label class="control-label" for="settings-serialTimeoutTemperature">Temperature interval (polling)</label>
1690 <div class="controls">
1691 <div class="input-append">
1692 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutTemperature" id="settings-serialTimeoutTemperature">
1693 <span class="add-on">s</span>
1694 </div>
1695 <span class="help-inline">When printing or idle</span>
1696 </div>
1697 <div class="controls">
1698 <div class="input-append">
1699 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutTemperatureTargetSet" id="settings-serialTimeoutTemperatureTargetSet">
1700 <span class="add-on">s</span>
1701 </div>
1702 <span class="help-inline">When idle and a target temperature is set</span>
1703 </div>
1704 </div>
1705 <div class="control-group" title="Temperature report interval to request from autoreport capable firmwares. A value of 0 disables autoreporting by the firmware and forces polling.">
1706 <label class="control-label" for="settings-serialTimeoutTemperatureAutoreport">Temperature interval (autoreport)</label>
1707 <div class="controls">
1708 <div class="input-append">
1709 <input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutTemperatureAutoreport" id="settings-serialTimeoutTemperatureAutoreport">
1710 <span class="add-on">s</span>
1711 </div>
1712 <span class="help-inline">Autoreport interval to request from firmware</span>
1713 </div>
1714 </div>
1715 <div class="control-group" title="Interval in which to poll for the SD printing status information from the printer while printing">
1716 <label class="control-label" for="settings-serialTimeoutSdStatus">SD status interval (polling)</label>
1717 <div class="controls">
1718 <div class="input-append">
1719 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutSdStatus" id="settings-serialTimeoutSdStatus">
1720 <span class="add-on">s</span>
1721 </div>
1722 <span class="help-inline">When printing from the printer's SD</span>
1723 </div>
1724 </div>
1725 <div class="control-group" title="SD status interval to request from autoreport capable firmwares. A value of 0 disables autoreporting by the firmware and forces polling.">
1726 <label class="control-label" for="settings-serialTimeoutSdStatusAutoreport">SD status interval (autoreport)</label>
1727 <div class="controls">
1728 <div class="input-append">
1729 <input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutSdStatusAutoreport" id="settings-serialTimeoutSdStatusAutoreport">
1730 <span class="add-on">s</span>
1731 </div>
1732 <span class="help-inline">Autoreport interval to request from firmware</span>
1733 </div>
1734 </div>
1735 </fieldset>
1736 <fieldset id="settings_serial_timeouts_timeouts">
1737 <legend>Timeouts</legend>
1738 <div class="control-group" title="Time after which the communication with your printer will be considered timed out if nothing was sent by your printer (and an attempt to get it talking again will be done). Increase this if your printer takes longer than this for some moves.">
1739 <label class="control-label" for="settings-serialTimeoutCommunication">Communication timeout</label>
1740 <div class="controls">
1741 <div class="input-append">
1742 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutCommunication" id="settings-serialTimeoutCommunication">
1743 <span class="add-on">s</span>
1744 </div>
1745 <span class="help-inline"><code>busy</code> protocol support not detected</span>
1746 </div>
1747 <div class="controls">
1748 <div class="input-append">
1749 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutCommunicationBusy" id="settings-serialTimeoutCommunicationBusy">
1750 <span class="add-on">s</span>
1751 </div>
1752 <span class="help-inline"><code>busy</code> protocol support detected</span>
1753 </div>
1754 </div>
1755 <div class="control-group" title="Time after which a connection attempt to the printer will be considered as having failed">
1756 <label class="control-label" for="settings-serialTimeoutConnection">Connection timeout</label>
1757 <div class="controls">
1758 <div class="input-append">
1759 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutConnection" id="settings-serialTimeoutConnection">
1760 <span class="add-on">s</span>
1761 </div>
1762 </div>
1763 </div>
1764 <div class="control-group" title="Time after which to consider an auto detection attempt to have failed if no successful connection is detected">
1765 <label class="control-label" for="settings-serialTimeoutDetection">Autodetection timeout</label>
1766 <div class="controls">
1767 <div class="input-append">
1768 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutDetection" id="settings-serialTimeoutDetection">
1769 <span class="add-on">s</span>
1770 </div>
1771 </div>
1772 </div>
1773 <div class="control-group" title="Time after which to consider a position query on pause or cancel to have failed">
1774 <label class="control-label" for="settings-serialTimeoutPositionLogWait">Position query timeout</label>
1775 <div class="controls">
1776 <div class="input-append">
1777 <input type="number" step="any" min="1" class="input-mini text-right" data-bind="value: serial_timeoutPositionLogWait" id="settings-serialTimeoutPositionLogWait">
1778 <span class="add-on">s</span>
1779 </div>
1780 </div>
1781 </div>
1782 <div>
1783 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', container: '#settings_serial_timeouts_timeouts .hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
1784 <div class="hide">
1785 <div class="control-group" title="Time to wait after opening the serial connection before starting baudrate detection">
1786 <label class="control-label" for="settings-serialTimeoutBaudrateDetectionPause">Initial baudrate detection pause</label>
1787 <div class="controls">
1788 <div class="input-append">
1789 <input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutBaudrateDetectionPause" id="settings-serialTimeoutBaudrateDetectionPause">
1790 <span class="add-on">s</span>
1791 </div>
1792 <span class="help-block">Some controllers need a bit of a breather before baudrate detection after initial connect. If baudrate detection fails due to a hanging controller, try increasing this value.</span>
1793 </div>
1794 </div>
1795 <div class="control-group" title="Maximum consecutive communication timeouts while idle. More than this and the printer will be considered to be gone. Set to 0 to disable.">
1796 <label class="control-label" for="settings-serialMaxTimeoutsIdle">Max. consecutive timeouts while idle</label>
1797 <div class="controls">
1798 <input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsIdle" data-bind="value: serial_maxTimeoutsIdle">
1799 <span class="help-block">Set to 0 to disable consecutive timeout detection and handling.</span>
1800 </div>
1801 </div>
1802 <div class="control-group" title="Maximum consecutive communication timeouts while printing. More than this and the printer will be considered to be gone. Set to 0 to disable.">
1803 <label class="control-label" for="settings-serialMaxTimeoutsPrinting">Max. consecutive timeouts while printing</label>
1804 <div class="controls">
1805 <input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsPrinting" data-bind="value: serial_maxTimeoutsPrinting">
1806 <span class="help-block">Set to 0 to disable consecutive timeout detection and handling.</span>
1807 </div>
1808 </div>
1809 <div class="control-group" title="Maximum consecutive communication timeouts while a long running command is active. More than this and the printer will be considered to be gone. Set to 0 to disable.">
1810 <label class="control-label" for="settings-serialMaxTimeoutsLong">Max. consecutive timeouts during long running commands</label>
1811 <div class="controls">
1812 <input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsLong" data-bind="value: serial_maxTimeoutsLong">
1813 <span class="help-block">Set to 0 to disable consecutive timeout detection and handling.</span>
1814 </div>
1815 </div>
1816 </div>
1817 </div>
1818 </fieldset>
1819 </div>
1820 <div id="settings_serial_protocol" class="tab-pane">
1821 <fieldset id="settings_serial_protocol_firmware">
1822 <legend>Firmware specific settings</legend>
1823 <div class="control-group">
1824 <div class="controls">
1825 <label class="checkbox">
1826 <input type="checkbox" data-bind="checked: serial_firmwareDetection" id="settings-serialFirmwareDetection"> Enable automatic firmware detection
1827 <span class="help-block">
1828 If enabled, OctoPrint will try to figure out your printer's firmware automatically and adjust some communication parameters based on that.
1829 If that doesn't work out, or you want more granular control, uncheck this and the parameters in question will become visible for you to adjust.
1830 </span>
1831 </label>
1832 </div>
1833 </div>
1834 <div data-bind="visible: !serial_firmwareDetection()">
1835 <div class="control-group">
1836 <div class="controls">
1837 <label class="checkbox">
1838 <input type="checkbox" data-bind="checked: serial_sdRelativePath" id="settings-serialSdRelativePath"> Select SD files by relative path <span class="label">RepRap Firmware</span>
1839 </label>
1840 </div>
1841 </div>
1842 <div class="control-group">
1843 <div class="controls">
1844 <label class="checkbox">
1845 <input type="checkbox" data-bind="checked: serial_sdAlwaysAvailable" id="settings-serialSdAlwaysAvailable"> Always assume SD card is present <span class="label">Repetier</span>
1846 </label>
1847 </div>
1848 </div>
1849 <div class="control-group">
1850 <div class="controls">
1851 <label class="checkbox">
1852 <input type="checkbox" data-bind="checked: serial_ignoreIdenticalResends" id="settings-serialIgnoreIdenticalResends"> Ignore consecutive resend requests for the same line <span class="label">Repetier</span>
1853 </label>
1854 </div>
1855 </div>
1856 <div class="control-group">
1857 <div class="controls">
1858 <label class="checkbox">
1859 <input type="checkbox" data-bind="checked: serial_repetierTargetTemp" id="settings-serialRepetierTargetTemp"> Support <code>TargetExtr%n</code>/<code>TargetBed</code> target temperature format <span class="label">Repetier</span>
1860 </label>
1861 </div>
1862 </div>
1863 <div class="control-group">
1864 <div class="controls">
1865 <label class="checkbox">
1866 <input type="checkbox" data-bind="checked: serial_disableExternalHeatupDetection" id="settings-serialExternalHeatupDetection"> Disable detection of external heatups <span class="label">Repetier</span>
1867 </label>
1868 </div>
1869 </div>
1870 <div class="control-group">
1871 <div class="controls">
1872 <label class="checkbox">
1873 <input type="checkbox" data-bind="checked: serial_blockWhileDwelling" id="settings-serialBlockWhileDwelling"> Actively pause communication during <code>G4</code> dwell command <span class="label">Repetier</span>
1874 </label>
1875 </div>
1876 </div>
1877 <div class="control-group">
1878 <label class="control-label">Send a checksum with the command</label>
1879 <div class="controls">
1880 <label class="radio">
1881 <input type="radio" name="sendChecksumGroup" value="print" data-bind="checked: serial_sendChecksum" id="settings-serialSendChecksumPrint"> When printing
1882 </label>
1883 <label class="radio">
1884 <input type="radio" name="sendChecksumGroup" value="always" data-bind="checked: serial_sendChecksum" id="settings-serialSendChecksumAlways"> Always <span class="label">Repetier</span>
1885 </label>
1886 <label class="radio">
1887 <input type="radio" name="sendChecksumGroup" value="never" data-bind="checked: serial_sendChecksum" id="settings-serialSendChecksumNever"> Never
1888 </label>
1889 </div>
1890 </div>
1891 </div>
1892 <div>
1893 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', container: '#settings_serial_protocol_firmware .hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
1894 <div class="hide">
1895 <div class="control-group">
1896 <div class="controls">
1897 <label class="checkbox">
1898 <input type="checkbox" data-bind="checked: serial_capAutoreportTemp" id="settings-serialCapAutoreportTemp"> Support temperature autoreporting by firmware, if detected
1899 </label>
1900 </div>
1901 </div>
1902 <div class="control-group">
1903 <div class="controls">
1904 <label class="checkbox">
1905 <input type="checkbox" data-bind="checked: serial_capAutoreportSdStatus" id="settings-serialCapAutoreportSdStatus"> Support sd status autoreporting by firmware, if detected
1906 </label>
1907 </div>
1908 </div>
1909 <div class="control-group">
1910 <div class="controls">
1911 <label class="checkbox">
1912 <input type="checkbox" data-bind="checked: serial_capEmergencyParser" id="settings-serialCapEmergencyParser"> Send emergency GCODES <code>M108</code> and <code>M410</code> without waiting for acknowledgement, if detected as supported by the firmware
1913 </label>
1914 </div>
1915 </div>
1916 <div class="control-group">
1917 <div class="controls">
1918 <label class="checkbox">
1919 <input type="checkbox" data-bind="checked: serial_capBusyProtocol" id="settings-serialCapBusyProtocol"> Support <code>busy</code> protocol, if detected
1920 </label>
1921 </div>
1922 </div>
1923 <div class="control-group">
1924 <div class="controls">
1925 <label class="checkbox">
1926 <input type="checkbox" data-bind="checked: serial_triggerOkForM29" id="settings-serialTriggerOkForM29"> Simulate <code>ok</code> for <code>M29</code>
1927 <span class="help-block">Most Marlin forks that were derived from Marlin versions < v1.1.0 do not send an acknowledging <code>ok</code> for a <code>M29</code>. Check this if you run into communication stalls following streaming of a file to your printer's SD.</span>
1928 </label>
1929 </div>
1930 </div>
1931 <div class="control-group">
1932 <label class="control-label"> Simulate <code>ok</code> for resend requests</label>
1933 <div class="controls">
1934 <label class="radio">
1935 <input type="radio" name="resendWithoutOkGroup" value="detect" data-bind="checked: serial_supportResendsWithoutOk" id="settings-serialSupportResendsWithoutOkDetect"> If detected as necessary
1936 </label>
1937 <label class="radio">
1938 <input type="radio" name="resendWithoutOkGroup" value="always" data-bind="checked: serial_supportResendsWithoutOk" id="settings-serialSupportResendsWithoutOkAlways"> Always
1939 </label>
1940 <label class="radio">
1941 <input type="radio" name="resendWithoutOkGroup" value="never" data-bind="checked: serial_supportResendsWithoutOk" id="settings-serialSupportResendsWithoutOkNever"> Never
1942 </label>
1943 <span class="help-block">Some Marlin forks lack an acknowledging <code>ok</code> with their resend requests. Set this to "always" or "if detected as necessary" if you run into communication stalls on resend requests.</span>
1944 </div>
1945 </div>
1946 </div>
1947 </div>
1948 </fieldset>
1949 <fieldset id="settings_serial_protocol_finetuning">
1950 <legend>Protocol fine tuning</legend>
1951 <div class="control-group">
1952 <div class="controls">
1953 <label class="checkbox">
1954 <input type="checkbox" data-bind="checked: serial_waitForStart" id="settings-serialWaitForStart"> Wait for <code>start</code> on connect
1955 <span class="help-block">Try checking this if you run into connection timeouts due to your printer taking too long to respond to OctoPrint's handshake attempts on connect.</span>
1956 </label>
1957 </div>
1958 </div>
1959 <div class="control-group">
1960 <label class="control-label" for="settings-serialBlockedCommands">Blocked commands</label>
1961 <div class="controls">
1962 <input type="text" class="input-block-level" id="settings-serialBlockedCommands" data-bind="value: serial_blockedCommands">
1963 <span class="help-inline">Use this to specify commands that should never be sent to the printer. Just the G or M code, comma separated. Defaults to <code>M0</code> and <code>M1</code> since most firmware will block until a button on the controller has been pressed if it receives either of those two commands.</span>
1964 </div>
1965 </div>
1966 <div class="control-group">
1967 <label class="control-label" for="settings-serialPausingCommands">Pausing commands</label>
1968 <div class="controls">
1969 <input type="text" class="input-block-level" id="settings-serialPausingCommands" data-bind="value: serial_pausingCommands">
1970 <span class="help-inline">Use this to specify commands on which OctoPrint should pause the print job. Just the G or M code, comma separated. Defaults to <code>M0</code>, <code>M1</code> and <code>M25</code>.</span>
1971 </div>
1972 </div>
1973 <div class="control-group">
1974 <label class="control-label" for="settings-serialEmergencyCommands">Emergency commands</label>
1975 <div class="controls">
1976 <input type="text" class="input-block-level" id="settings-serialEmergencyCommands" data-bind="value: serial_emergencyCommands">
1977 <span class="help-inline">Use this to specify emergency commands which should jump any queues and - if supported by the firmware - be force sent. Just the G or M code, comma separated. Defaults to <code>M112</code>, <code>M108</code> and <code>M410</code>.</span> </div>
1978 </div>
1979 <div>
1980 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', container: '#settings_serial_protocol_finetuning .hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
1981 <div class="hide">
1982 <div class="control-group" title="Command to send to the firmware on first handshake attempt.">
1983 <label class="control-label" for="settings-serialHelloCommand">"Hello" command</label>
1984 <div class="controls">
1985 <input type="text" class="input-block-level" id="settings-serialHelloCommand" data-bind="value: serial_helloCommand">
1986 <span class="help-inline">Use this to specify a different command than the default <code>M110</code> to send to the printer on initial connection to trigger a communication handshake.</span>
1987 </div>
1988 </div>
1989 <div class="control-group" title="Commands that are know to run long and hence should suppress communication timeouts from being triggered.">
1990 <label class="control-label" for="settings-serialLongRunningCommands">Long running commands</label>
1991 <div class="controls">
1992 <input type="text" class="input-block-level" id="settings-serialLongRunningCommands" data-bind="value: serial_longRunningCommands">
1993 <span class="help-inline">Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated.</span>
1994 </div>
1995 </div>
1996 <div class="control-group" title="Commands that always require a line number and checksum to be sent with them.">
1997 <label class="control-label" for="settings-checksumRequiringCommands">Commands that always require a checksum</label>
1998 <div class="controls">
1999 <input type="text" class="input-block-level" id="settings-checksumRequiringCommands" data-bind="value: serial_checksumRequiringCommands">
2000 <span class="help-inline">Use this to specify which commands <strong>always</strong> need to be sent with a checksum. Comma separated list.</span>
2001 </div>
2002 </div>
2003 <div class="control-group" title="ok buffer size">
2004 <label class="control-label" for="settings-serialAckMax"><code>ok</code> buffer size</label>
2005 <div class="controls">
2006 <input type="number" min="0" class="input-mini text-right" id="settings-serialAckMax" data-bind="value: serial_ackMax">
2007 <span class="help-block">Only modify if told to do so</span>
2008 </div>
2009 </div>
2010 </div>
2011 </div>
2012 </fieldset>
2013 </div>
2014 <div id="settings_serial_behaviour" class="tab-pane">
2015 <fieldset>
2016 <legend>Error handling</legend>
2017 <div class="control-group">
2018 <label class="control-label">What to do on a firmware error (<code>Error:</code> or <code>!!</code>)</label>
2019 <div class="controls">
2020 <label class="radio">
2021 <input type="radio" name="errorHandlingGroup" value="disconnect" data-bind="checked: serial_serialErrorBehaviour" id="settings-serialErrorBehaviourDisconnect"> Disconnect from the printer
2022 </label>
2023 <label class="radio">
2024 <input type="radio" name="errorHandlingGroup" value="cancel" data-bind="checked: serial_serialErrorBehaviour" id="settings-serialErrorBehaviourCancel"> Cancel any ongoing prints but stay connected to the printer <span></span>
2025 <span class="help-block">Please note that if you choose this, OctoPrint will still disconnect from the printer in case of <em>fatal</em> errors reported by your firmware (e.g. <code>kill() called</code>, <code>fatal:</code>).</span>
2026 </label>
2027 <label class="radio">
2028 <input type="radio" name="errorHandlingGroup" value="ignore" data-bind="checked: serial_serialErrorBehaviour" id="settings-serialErrorBehaviourIgnore"> Ignore <span class="label label-important">Warning</span>
2029 <span class="help-block">Only choose this if your firmware sends error messages that are not actual errors. Might mask printer issues (even fatal errors!), be careful!</span>
2030 </label>
2031 </div>
2032 </div>
2033 <div class="controls">
2034 <label class="checkbox">
2035 <input type="checkbox" data-bind="checked: serial_sendM112OnError" id="settings-serialSendM112OnError"> Send <code>M112</code> on disconnect due to error
2036 <span class="help-block">If this is checked, OctoPrint will try to send an <code>M112</code> prior to a disconnect due to a (fatal) error in order to disable heaters and motors.</span>
2037 </label>
2038 </div>
2039 </fieldset>
2040 <fieldset>
2041 <legend>Pausing</legend>
2042 <div class="controls">
2043 <label class="checkbox">
2044 <input type="checkbox" data-bind="checked: serial_logPositionOnPause" id="settings-serialLogPositionOnPause"> Log position on pause <span class="label label-important">Warning</span>
2045 <span class="help-block">If you disable this, the <code>pause_position</code> placeholders in your pause/resume GCODE scripts will stay unpopulated! However, pausing speed might improve slightly.</span>
2046 </label>
2047 </div>
2048 </fieldset>
2049 <fieldset>
2050 <legend>Cancelling</legend>
2051 <div class="controls">
2052 <label class="checkbox">
2053 <input type="checkbox" data-bind="checked: serial_logPositionOnCancel" id="settings-serialLogPositionOnCancel"> Log position on cancel <span class="label label-important">Warning</span>
2054 <span class="help-block">If you disable this, the <code>cancel_position</code> placeholders in your cancel GCODE script and the corresponding data in the print recovery data will stay unpopulated! However, cancelling speed might improve slightly.</span>
2055 </label>
2056 </div>
2057 <div class="controls">
2058 <label class="checkbox">
2059 <input type="checkbox" data-bind="checked: serial_abortHeatupOnCancel" id="settings-serialAbortHeatupOnCancel"> Attempt to abort any blocking heatups on cancel via <code>M108</code>.
2060 <span class="help-block">Uncheck this if your firmware doesn't support <code>M108</code> for aborting blocking heatups!</span>
2061 </label>
2062 </div>
2063 </fieldset>
2064 </div>
2065 </div>
2066</form>
2067 </div>
2068
2069
2070
2071
2072
2073
2074 <div id="settings_printerProfiles"
2075
2076 class="tab-pane "
2077
2078 >
2079 <h3>Printer Profiles</h3>
2080
2081<table class="table table-striped table-hover table-condensed table-hover" id="settings_printerProfiles_profiles" data-bind="visible: printerProfiles.profiles.items().length > 0" style="display: none">
2082 <thead>
2083 <tr>
2084 <th class="settings_printerProfiles_profiles_name">Name</th>
2085 <th class="settings_printerProfiles_profiles_model">Model</th>
2086 <th class="settings_printerProfiles_profiles_action">Action</th>
2087 </tr>
2088 </thead>
2089 <tbody data-bind="foreach: printerProfiles.profiles.paginatedItems">
2090 <tr data-bind="attr: {title: name}">
2091 <td class="settings_printerProfiles_profiles_name"><span class="fa fa-star" data-bind="invisible: !isdefault()"></span> <span data-bind="text: name, style: { 'font-weight': iscurrent() ? 'bold' : 'normal' }"></span></td>
2092 <td class="settings_printerProfiles_profiles_model" data-bind="text: model"></td>
2093 <td class="settings_printerProfiles_profiles_action">
2094 <a href="#" class="fa fa-star" title="Set as default profile" data-bind="click: function() { if ($root.printerProfiles.canMakeDefault($data) && !$root.printerProfiles.requestInProgress()) { $root.printerProfiles.makeDefault($data); } }, css: {disabled: !$root.printerProfiles.canMakeDefault($data) || $root.printerProfiles.requestInProgress()}, enabled: $root.printerProfile.canMakeDefault($data) && !$root.printerProfiles.requestInProgress()"></a> | <a href="#" class="fa fa-pencil" title="Edit Profile" data-bind="click: function() { if (!$root.printerProfiles.requestInProgress()) { $root.printerProfiles.showEditProfileDialog($data); } }, css: {disabled: $root.printerProfiles.requestInProgress()}, enabled: !$root.printerProfiles.requestInProgress()"></a> | <a href="#" class="fa fa-trash-o" title="Delete Profile" data-bind="click: function() { if ($root.printerProfiles.canRemove($data) && !$root.printerProfiles.requestInProgress()) { $root.printerProfiles.removeProfile($data); } }, css: {disabled: !$root.printerProfiles.canRemove($data) || $root.printerProfiles.requestInProgress()}, enabled: $root.printerProfiles.canRemove($data) && !$root.printerProfiles.requestInProgress()"></a>
2095 </td>
2096 </tr>
2097 </tbody>
2098</table>
2099
2100<div class="pagination pagination-mini pagination-centered">
2101 <ul>
2102 <li data-bind="css: {disabled: printerProfiles.profiles.currentPage() === 0}"><a href="#" data-bind="click: printerProfiles.profiles.prevPage">«</a></li>
2103 </ul>
2104 <ul data-bind="foreach: printerProfiles.profiles.pages">
2105 <li data-bind="css: { active: $data.number === $root.printerProfiles.profiles.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.printerProfiles.profiles.changePage($data.number); }"></a></li>
2106 </ul>
2107 <ul>
2108 <li data-bind="css: {disabled: printerProfiles.profiles.currentPage() === printerProfiles.profiles.lastPage()}"><a href="#" data-bind="click: printerProfiles.profiles.nextPage">»</a></li>
2109 </ul>
2110</div>
2111
2112<button class="btn pull-right" data-bind="click: function() { $root.printerProfiles.showEditProfileDialog(); }"><i class="fa fa-plus"></i> Add Profile...</button>
2113
2114<div id="settings_printerProfiles_editDialog" class="modal hide fade">
2115 <div class="modal-header">
2116 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
2117 <h3 class="modal-title"></h3>
2118 </div>
2119 <div class="modal-body">
2120 <div class="full-sized-box">
2121 <ul class="nav nav-pills">
2122 <li class="active"><a href="#settings_printerProfiles_editDialog_general" data-toggle="tab">General</a></li>
2123 <li><a href="#settings_printerProfiles_editDialog_buildvolume" data-toggle="tab">Print bed & build volume</a></li>
2124 <li><a href="#settings_printerProfiles_editDialog_axes" data-toggle="tab">Axes</a></li>
2125 <li><a href="#settings_printerProfiles_editDialog_extruder" data-toggle="tab">Hotend & extruder</a></li>
2126 </ul>
2127
2128 <!-- ko with: printerProfiles.editor -->
2129 <div class="tab-content">
2130 <div id="settings_printerProfiles_editDialog_general" class="tab-pane active">
2131 <form class="form-horizontal">
2132 <div class="control-group" data-bind="css: {error: nameInvalid()}">
2133 <label class="control-label">Name</label>
2134 <div class="controls">
2135 <input type="text" data-bind="value: name, valueUpdate: 'afterkeydown'">
2136 <span data-bind="visible: nameInvalid()"><br><span class="help-inline">Name must be set</span></span>
2137 </div>
2138 </div>
2139 <div class="control-group" data-bind="css: {error: identifierInvalid()}">
2140 <label class="control-label">Identifier</label>
2141 <div class="controls">
2142 <input type="text" data-bind="value: identifier, valueUpdate: 'afterkeydown', enable: isNew, css: {disabled: !isNew()}, attr: {placeholder: identifierPlaceholder}">
2143 <span data-bind="visible: identifierInvalid()"><br><span class="help-inline" data-bind="text: identifierInvalidText()"></span></span>
2144 </div>
2145 </div>
2146 <div class="control-group">
2147 <label class="control-label">Model</label>
2148 <div class="controls">
2149 <input type="text" data-bind="value: model">
2150 </div>
2151 </div>
2152</form>
2153 </div>
2154
2155 <div id="settings_printerProfiles_editDialog_buildvolume" class="tab-pane">
2156 <form class="form-horizontal">
2157 <div class="control-group">
2158 <label class="control-label">Form Factor</label>
2159 <div class="controls">
2160 <label class="radio"><input type="radio" name="printerProfileFormFactorGroup" value="rectangular" data-bind="checked: volumeFormFactor"> Rectangular</label>
2161 </div>
2162 <div class="controls">
2163 <label class="radio"><input type="radio" name="printerProfileFormFactorGroup" value="circular" data-bind="checked: volumeFormFactor"> Circular</label>
2164 </div>
2165 </div>
2166 <div class="control-group">
2167 <div class="control-group">
2168 <label class="control-label">Origin</label>
2169 <div class="controls">
2170 <select data-bind="value: volumeOrigin, options: availableOrigins, optionsText: 'name', optionsValue: 'key'">
2171 </select>
2172 </div>
2173 </div>
2174 </div>
2175 <div class="control-group">
2176 <label class="control-label">Heated Bed</label>
2177 <div class="controls">
2178 <input type="checkbox" data-bind="checked: heatedBed">
2179 </div>
2180 </div>
2181 <div class="control-group">
2182 <label class="control-label">Heated Chamber</label>
2183 <div class="controls">
2184 <input type="checkbox" data-bind="checked: heatedChamber">
2185 </div>
2186 </div>
2187
2188 <div class="control-group">
2189 <div class="controls">
2190 Please define the print volume.
2191 </div>
2192 </div>
2193
2194 <div data-bind="visible: volumeFormFactor() != 'circular'" style="display: none">
2195 <div class="control-group">
2196 <label class="control-label">Width (X)</label>
2197 <div class="controls">
2198 <div class="input-append">
2199 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: volumeWidth" placeholder="200">
2200 <span class="add-on">mm</span>
2201 </div>
2202 </div>
2203 </div>
2204 <div class="control-group">
2205 <label class="control-label">Depth (Y)</label>
2206 <div class="controls">
2207 <div class="input-append">
2208 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: volumeDepth" placeholder="200">
2209 <span class="add-on">mm</span>
2210 </div>
2211 </div>
2212 </div>
2213 </div>
2214 <div data-bind="visible: volumeFormFactor() == 'circular'" style="display: none">
2215 <div class="control-group">
2216 <label class="control-label">Diameter (X/Y)</label>
2217 <div class="controls">
2218 <div class="input-append">
2219 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: volumeWidth" placeholder="200">
2220 <span class="add-on">mm</span>
2221 </div>
2222 </div>
2223 </div>
2224 </div>
2225 <div class="control-group">
2226 <label class="control-label">Height (Z)</label>
2227 <div class="controls">
2228 <div class="input-append">
2229 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: volumeHeight" placeholder="200">
2230 <span class="add-on">mm</span>
2231 </div>
2232 </div>
2233 </div>
2234
2235 <div class="control-group">
2236 <div class="controls">
2237 If your printer's print head may move slightly outside the print volume (e.g. for nozzle cleaning routines)
2238 you can define a custom safe bounding box for its movements below.
2239 </div>
2240 </div>
2241
2242 <div class="control-group">
2243 <label class="control-label">Custom bounding box</label>
2244 <div class="controls">
2245 <input type="checkbox" data-bind="checked: customBoundingBox">
2246 </div>
2247 </div>
2248 <div data-bind="visible: customBoundingBox">
2249 <div class="control-group">
2250 <label class="control-label">X Coordinates</label>
2251 <div class="controls">
2252 <div class="input-prepend">
2253 <span class="add-on">Min</span>
2254 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMinX, attr: {placeholder: boundingBoxMinXPlaceholder, max: boundingBoxMinXPlaceholder}">
2255 </div>
2256 <div class="input-prepend">
2257 <span class="add-on">Max</span>
2258 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMaxX, attr: {placeholder: boundingBoxMaxXPlaceholder, min: boundingBoxMaxXPlaceholder}">
2259 </div>
2260 </div>
2261 </div>
2262 <div class="control-group">
2263 <label class="control-label">Y Coordinates</label>
2264 <div class="controls">
2265 <div class="input-prepend">
2266 <span class="add-on">Min</span>
2267 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMinY, attr: {placeholder: boundingBoxMinYPlaceholder, max: boundingBoxMinYPlaceholder}">
2268 </div>
2269 <div class="input-prepend">
2270 <span class="add-on">Max</span>
2271 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMaxY, attr: {placeholder: boundingBoxMaxYPlaceholder, min: boundingBoxMaxYPlaceholder}">
2272 </div>
2273 </div>
2274 </div>
2275 <div class="control-group">
2276 <label class="control-label">Z Coordinates</label>
2277 <div class="controls">
2278 <div class="input-prepend">
2279 <span class="add-on">Min</span>
2280 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMinZ, attr: {placeholder: boundingBoxMinZPlaceholder, max: boundingBoxMinZPlaceholder}">
2281 </div>
2282 <div class="input-prepend">
2283 <span class="add-on">Max</span>
2284 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: boundingBoxMaxZ, attr: {placeholder: boundingBoxMaxZPlaceholder, min: boundingBoxMaxZPlaceholder}">
2285 </div>
2286 </div>
2287 </div>
2288 </div>
2289
2290 <p>
2291 <small>This information is used for the temperature tab, the bounding box check, the GCODE Viewer and/or when slicing from OctoPrint.</small>
2292 </p>
2293</form>
2294 </div>
2295
2296 <div id="settings_printerProfiles_editDialog_axes" class="tab-pane">
2297 <form class="form-horizontal">
2298 <div class="control-group">
2299 <div class="controls">
2300 Please define the maximum speed/feedrate of the individual axes and whether their control should be inverted or not.
2301 </div>
2302 </div>
2303 <div class="control-group">
2304 <label class="control-label">X</label>
2305 <div class="controls form-inline">
2306 <div class="input-append">
2307 <input type="number" class="input-mini text-right" data-bind="value: axisXSpeed" placeholder="6000">
2308 <span class="add-on">mm/min</span>
2309 </div>
2310 <label class="checkbox">
2311 <input type="checkbox" data-bind="checked: axisXInverted"> Invert control
2312 </label>
2313 </div>
2314 </div>
2315 <div class="control-group">
2316 <label class="control-label">Y</label>
2317 <div class="controls form-inline">
2318 <div class="input-append">
2319 <input type="number" class="input-mini text-right" data-bind="value: axisYSpeed" placeholder="6000">
2320 <span class="add-on">mm/min</span>
2321 </div>
2322 <label class="checkbox">
2323 <input type="checkbox" data-bind="checked: axisYInverted"> Invert control
2324 </label>
2325 </div>
2326 </div>
2327 <div class="control-group">
2328 <label class="control-label">Z</label>
2329 <div class="controls form-inline">
2330 <div class="input-append">
2331 <input type="number" class="input-mini text-right" data-bind="value: axisZSpeed" placeholder="200">
2332 <span class="add-on">mm/min</span>
2333 </div>
2334 <label class="checkbox">
2335 <input type="checkbox" data-bind="checked: axisZInverted"> Invert control
2336 </label>
2337 </div>
2338 </div>
2339 <div class="control-group">
2340 <label class="control-label">E</label>
2341 <div class="controls form-inline">
2342 <div class="input-append">
2343 <input type="number" class="input-mini text-right" data-bind="value: axisESpeed" placeholder="300">
2344 <span class="add-on">mm/min</span>
2345 </div>
2346 </div>
2347 </div>
2348
2349 <p>
2350 <small>This information is used for manual control via the "Control" tab.</small>
2351 </p>
2352</form>
2353 </div>
2354
2355 <div id="settings_printerProfiles_editDialog_extruder" class="tab-pane">
2356 <form class="form-horizontal">
2357
2358 <div class="control-group">
2359 <label class="control-label">Nozzle Diameter</label>
2360 <div class="controls">
2361 <div class="input-append">
2362 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: nozzleDiameter" placeholder="0.4">
2363 <span class="add-on">mm</span>
2364 </div>
2365 </div>
2366 </div>
2367 <div class="control-group">
2368 <label class="control-label">Number of Extruders</label>
2369 <div class="controls">
2370 <input type="number" class="input-mini text-right" min="1" max="10" data-bind="value: extruders">
2371 <span class="help-block">Make sure to specify number of extruders available on your printer or you might run into issues</span>
2372 </div>
2373 </div>
2374 <div data-bind="visible: extruders() > 1" style="display: none">
2375 <div class="control-group">
2376 <label class="control-label">Shared nozzle</label>
2377 <div class="controls">
2378 <input type="checkbox" data-bind="checked: sharedNozzle">
2379 <span class="help-block">Check this if your printer has a single nozzle and heater shared among its extruders instead of one nozzle and heater per extruder</span>
2380 </div>
2381 </div>
2382
2383 <div data-bind="visible: !sharedNozzle()" style="display: none">
2384 <div class="control-group">
2385 <div class="controls">
2386 Please specify the nozzle offsets of the extruders relative to the first nozzle T0 <strong>if you haven't already done so in your firmware</strong>. Otherwise leave them at (0,0).
2387 </div>
2388 </div>
2389
2390 <!-- ko foreach: koExtruderOffsets -->
2391 <div class="control-group">
2392 <label class="control-label">Offset T<span data-bind="text: idx"></span></label>
2393 <div class="controls form-inline">
2394 <label>X</label>
2395 <div class="input-append">
2396 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: x" placeholder="0">
2397 <span class="add-on">mm</span>
2398 </div>
2399 <label>Y</label>
2400 <div class="input-append">
2401 <input type="number" step="0.01" class="input-mini text-right" data-bind="value: y" placeholder="0">
2402 <span class="add-on">mm</span>
2403 </div>
2404 </div>
2405 </div>
2406 <!-- /ko -->
2407 </div>
2408 </div>
2409
2410 <p>
2411 <small>This information is used for the graph and controls available in the "Temperature" tab, the GCODE viewer, when slicing from within OctoPrint and for deciding which toolchange commands are safe to send to the printer.</small>
2412 </p>
2413</form>
2414 </div>
2415 </div>
2416 <!-- /ko -->
2417 </div>
2418 </div>
2419 <div class="modal-footer">
2420 <button class="btn" data-dismiss="modal" aria-hidden="true">Abort</button>
2421 <button class="btn btn-primary btn-confirm" data-bind="enabled: printerProfiles.enableEditorSubmitButton, css: {disabled: !printerProfiles.enableEditorSubmitButton()}"><i class="fa fa-spinner fa-spin" data-bind="visible: printerProfiles.requestInProgress()"></i> Confirm</button>
2422 </div>
2423</div>
2424 </div>
2425
2426
2427
2428
2429
2430
2431 <div id="settings_temperature"
2432
2433 class="tab-pane "
2434
2435 >
2436 <form class="form-horizontal">
2437 <h3>Graph</h3>
2438 <div class="control-group">
2439 <label class="control-label" for="settings-temperatureCutoff">Graph cutoff</label>
2440 <div class="controls">
2441 <div class="input-append">
2442 <input type="number" min="1" class="input-mini text-right" data-bind="value: temperature_cutoff" id="settings-temperatureCutoff">
2443 <span class="add-on">min</span>
2444 </div>
2445 <span class="help-block">Needs a restart of OctoPrint to become active.</span>
2446 </div>
2447 </div>
2448 <h3>Fine adjustments</h3>
2449 <div class="control-group">
2450 <div class="controls">
2451 <label class="checkbox">
2452 <input type="checkbox" data-bind="checked: temperature_sendAutomatically"> Send temperature fine adjustments automatically
2453 </label>
2454 <span class="help-block">Enable this to have temperature fine adjustments you do via the + or - button be sent to the printer automatically.</span>
2455 </div>
2456 </div>
2457 <div class="control-group" data-bind="visible: temperature_sendAutomatically">
2458 <label class="control-label">Sending delay</label>
2459 <div class="controls">
2460 <div class="input-append">
2461 <input type="number" class="input-mini" min="0" max="30" data-bind="value: temperature_sendAutomaticallyAfter">
2462 <span class="add-on">sec</span>
2463 </div>
2464 <span class="help-block">OctoPrint will use this delay to limit the number of sent temperature commands should you perform multiple fine adjustments in a short time.</span>
2465 </div>
2466 </div>
2467 <h3>Presets</h3>
2468 <div class="row-fluid">
2469 <div class="offset4 span3"><h4>Extruder</h4></div>
2470 <div class="span3"><h4>Bed</h4></div>
2471 </div>
2472 <div data-bind="foreach: temperature_profiles">
2473 <div class="row-fluid" style="margin-bottom: 5px">
2474 <div class="span4">
2475 <input type="text" class="span12 text-right" data-bind="value: name">
2476 </div>
2477 <div class="input-append span3">
2478 <input type="number" min="0" step="1" class="input-mini text-right" data-bind="value: extruder">
2479 <span class="add-on">°C</span>
2480 </div>
2481 <div class="input-append span3">
2482 <input type="number" min="0" step="1" class="input-mini text-right" data-bind="value: bed">
2483 <span class="add-on">°C</span>
2484 </div>
2485 <div class="span2">
2486 <a title="Remove profile" class="btn btn-danger" data-bind="click: $parent.removeTemperatureProfile"><i class="fa fa-trash-o"></i></a>
2487 </div>
2488 </div>
2489 </div>
2490 <div class="row-fluid">
2491 <div class="offset10 span2">
2492 <a title="Add Profile" class="btn btn-primary" data-bind="click: addTemperatureProfile"><i class="fa fa-plus"></i></a>
2493 </div>
2494 </div>
2495</form>
2496 </div>
2497
2498
2499
2500
2501
2502
2503 <div id="settings_terminalFilters"
2504
2505 class="tab-pane "
2506
2507 >
2508 <form class="form-horizontal">
2509 <div class="row-fluid">
2510 <div class="span4"><h4>Name</h4></div>
2511 <div class="span6"><h4>RegExp <small><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions">?</a></small></h4></div>
2512 </div>
2513 <div data-bind="foreach: terminalFilters">
2514 <div class="row-fluid" style="margin-bottom: 5px">
2515 <div class="span4">
2516 <input type="text" class="span12" data-bind="value: name">
2517 </div>
2518 <div class="span6">
2519 <input type="text" class="span12" data-bind="value: regex">
2520 </div>
2521 <div class="span2">
2522 <a title="Remove Filter" class="btn btn-danger" data-bind="click: $parent.removeTerminalFilter"><i class="fa fa-trash-o"></i></a>
2523 </div>
2524 </div>
2525 </div>
2526 <div class="row-fluid">
2527 <div class="offset10 span2">
2528 <a title="Add Filter" class="btn btn-primary" data-bind="click: addTerminalFilter"><i class="fa fa-plus"></i></a>
2529 </div>
2530 </div>
2531</form>
2532 </div>
2533
2534
2535
2536
2537
2538
2539 <div id="settings_gcodeScripts"
2540
2541 class="tab-pane "
2542
2543 >
2544 <form class="form-horizontal">
2545 <div class="control-group">
2546 <label class="control-label">Before print job starts</label>
2547 <div class="controls">
2548 <textarea rows="4" class="block" data-bind="value: scripts_gcode_beforePrintStarted"></textarea>
2549 <small>Anything you put here will be executed <em>before</em> any lines in your files.</small>
2550 </div>
2551 </div>
2552 <div class="control-group">
2553 <label class="control-label">After print job completes</label>
2554 <div class="controls">
2555 <textarea rows="4" class="block" data-bind="value: scripts_gcode_afterPrintDone"></textarea>
2556 <small>Anything you put here will be executed <em>after</em> any lines in your files.</small>
2557 </div>
2558 </div>
2559 <div class="control-group">
2560 <label class="control-label">After print job is cancelled</label>
2561 <div class="controls">
2562 <textarea rows="4" class="block" data-bind="value: scripts_gcode_afterPrintCancelled"></textarea>
2563 <small>Anything you put here will be executed <em>after</em> any lines in your files.</small>
2564 </div>
2565 </div>
2566 <div class="control-group">
2567 <label class="control-label">After print job is paused</label>
2568 <div class="controls">
2569 <textarea rows="4" class="block" data-bind="value: scripts_gcode_afterPrintPaused"></textarea>
2570 <small>Anything you put here will be executed <em>after</em> any lines in your files.</small>
2571 </div>
2572 </div>
2573 <div class="control-group">
2574 <label class="control-label">Before print job is resumed</label>
2575 <div class="controls">
2576 <textarea rows="4" class="block" data-bind="value: scripts_gcode_beforePrintResumed"></textarea>
2577 <small>Anything you put here will be executed <em>before</em> any lines in your files.</small>
2578 </div>
2579 </div>
2580 <div class="control-group">
2581 <label class="control-label">Before tool change</label>
2582 <div class="controls">
2583 <textarea rows="4" class="block" data-bind="value: scripts_gcode_beforeToolChange"></textarea>
2584 <small>Anything you put here will be executed <em>before</em> any tool change commands <code>Tn</code>.</small>
2585 </div>
2586 </div>
2587 <div class="control-group">
2588 <label class="control-label">After tool change</label>
2589 <div class="controls">
2590 <textarea rows="4" class="block" data-bind="value: scripts_gcode_afterToolChange"></textarea>
2591 <small>Anything you put here will be executed <em>after</em> any tool change commands <code>Tn</code>.</small>
2592 </div>
2593 </div>
2594 <div class="control-group">
2595 <label class="control-label">After connection to printer is established</label>
2596 <div class="controls">
2597 <textarea rows="4" class="block" data-bind="value: scripts_gcode_afterPrinterConnected"></textarea>
2598 </div>
2599 </div>
2600 <div class="control-group">
2601 <label class="control-label">Before connection to printer is closed</label>
2602 <div class="controls">
2603 <textarea rows="4" class="block" data-bind="value: scripts_gcode_beforePrinterDisconnected"></textarea>
2604 <small>Anything you put here will only be executed when closing the connection actively. If the connection to the printer is suddenly lost nothing will be sent.</small>
2605 </div>
2606 </div>
2607</form>
2608 </div>
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618 <div id="settings_features"
2619
2620 class="tab-pane "
2621
2622 >
2623 <form class="form-horizontal">
2624 <div class="control-group">
2625 <div class="controls">
2626 <label class="checkbox">
2627 <input type="checkbox" data-bind="checked: feature_temperatureGraph" id="settings-featureTemperatureGraph"> Enable Temperature Graph
2628 </label>
2629 </div>
2630 </div>
2631 <div class="control-group">
2632 <div class="controls">
2633 <label class="checkbox">
2634 <input type="checkbox" data-bind="checked: feature_modelSizeDetection" id="settings-modelSizeDetection"> Enable model size detection and warn if model exceeds print bed <span class="label label-info">Beta</span>
2635 </label>
2636 </div>
2637 </div>
2638 <div class="control-group">
2639 <div class="controls">
2640 <label class="checkbox">
2641 <input type="checkbox" data-bind="checked: feature_printStartConfirmation" id="settings-printStartConfirmation"> Confirm before starting a print
2642 </label>
2643 </div>
2644 </div>
2645 <div class="control-group">
2646 <div class="controls">
2647 <label class="checkbox">
2648 <input type="checkbox" data-bind="checked: feature_printCancelConfirmation" id="settings-printCancelConfirmation"> Confirm before cancelling a print
2649 </label>
2650 </div>
2651 </div>
2652 <div class="control-group">
2653 <div class="controls">
2654 <label class="checkbox">
2655 <input type="checkbox" data-bind="checked: feature_sdSupport" id="settings-featureSdSupport"> Enable SD support
2656 </label>
2657 </div>
2658 </div>
2659 <div class="control-group">
2660 <div class="controls">
2661 <label class="checkbox">
2662 <input type="checkbox" data-bind="checked: feature_keyboardControl" id="settings-featureKeyboardControl"> Enable Keyboard Control
2663 </label>
2664 </div>
2665 </div>
2666 <div class="control-group">
2667 <div class="controls">
2668 <label class="checkbox">
2669 <input type="checkbox" data-bind="checked: feature_g90InfluencesExtruder" id="settings-g90InfluencesExtruder"> <code>G90</code>/<code>G91</code> overrides relative extruder mode <span class="label">Smoothieware</span>
2670 <span class="help-block">This is used by the GCODE analysis in the backend and the viewer in the frontend to interpret your sliced files correctly.</span>
2671 </label>
2672 </div>
2673 </div>
2674 <div class="control-group" title="Commands to not completely auto uppercase in the terminal tab">
2675 <label class="control-label" for="settings-featureAutoUppercaseBlacklist">Terminal Auto Uppercase Blacklist</label>
2676 <div class="controls">
2677 <input type="text" class="input-block-level" id="settings-featureAutoUppercaseBlacklist" data-bind="value: feature_autoUppercaseBlacklist">
2678 <span class="help-block">Use this to specify the commands that should not have their parameters automatically uppercased in the terminal tab. Just the G or M code, comma separated.</span>
2679 </div>
2680 </div>
2681
2682 <div class="control-group">
2683 <label class="control-label">Analyze gcode for time and model size estimates</label>
2684 <div class="controls">
2685 <label class="radio">
2686 <input type="radio" name="analysisRunAtGroup" value="always" data-bind="checked: gcodeAnalysis_runAt" id="settings-gcodeAnalysis_runAtAlways"> Always
2687 </label>
2688 <label class="radio">
2689 <input type="radio" name="analysisRunAtGroup" value="idle" data-bind="checked: gcodeAnalysis_runAt" id="settings-gcodeAnalysis_runAtIdle"> Only when idle (not printing)
2690 </label>
2691 <label class="radio">
2692 <input type="radio" name="analysisRunAtGroup" value="never" data-bind="checked: gcodeAnalysis_runAt" id="settings-gcodeAnalysis_runAtNever"> Never
2693 </label>
2694 </div>
2695 </div>
2696</form>
2697 </div>
2698
2699
2700
2701
2702
2703
2704 <div id="settings_webcam"
2705
2706 class="tab-pane "
2707
2708 >
2709 <h3>Webcam</h3>
2710
2711<form class="form-horizontal">
2712 <div class="control-group">
2713 <div class="controls">
2714 <label class="checkbox">
2715 <input type="checkbox" data-bind="checked: webcam_webcamEnabled" id="settings-webcamWebcamEnabled"> Enable webcam support
2716 </label>
2717 </div>
2718</div>
2719 <div class="control-group" title="URL to embed into the UI for live viewing of the webcam stream">
2720 <label class="control-label" for="settings-webcamStreamUrl">Stream URL</label>
2721 <div class="controls">
2722 <div class="input-append">
2723 <input type="text" class="input-block-level" data-bind="value: webcam_streamUrl, valueUpdate: 'afterkeydown'" id="settings-webcamStreamUrl">
2724 <button class="btn" type="button" data-bind="click: testWebcamStreamUrl, enable: webcam_streamUrl() && !testWebcamStreamUrlBusy(), css: {disabled: !webcam_streamUrl() || testWebcamStreamUrlBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testWebcamStreamUrlBusy"></i> Test</button>
2725 </div>
2726 <span class="help-inline">Needs to be reachable from the browser displaying the OctoPrint UI, used to embed the webcam stream into the page.</span>
2727 </div>
2728</div>
2729 <div class="control-group" title="Aspect ratio of the webcam stream, either 16:9 or 4:3">
2730 <label class="control-label" for="settings-webcamStreamRatio">Stream aspect ratio</label>
2731 <div class="controls">
2732 <select data-bind="options: webcam_available_ratios, value: webcam_streamRatio" id="settings-webcamStreamRatio"></select>
2733 <span class="help-inline">If the stream has a different aspect ratio than configured here it will be letterboxed.</span>
2734 </div>
2735</div>
2736 <div class="control-group">
2737 <div class="controls">
2738 <label class="checkbox">
2739 <input type="checkbox" data-bind="checked: webcam_flipH" id="settings-webcamFlipH"> Flip webcam horizontally
2740 </label>
2741 </div>
2742 <div class="controls">
2743 <label class="checkbox">
2744 <input type="checkbox" data-bind="checked: webcam_flipV" id="settings-webcamFlipV"> Flip webcam vertically
2745 </label>
2746 </div>
2747 <div class="controls">
2748 <label class="checkbox">
2749 <input type="checkbox" data-bind="checked: webcam_rotate90" id="settings-webcamRotate90"> Rotate webcam 90 degrees counter clockwise
2750 </label>
2751 </div>
2752</div>
2753
2754 <div>
2755 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.form-horizontal', container: '.hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
2756 <div class="hide">
2757 <div class="control-group" title="Timeout after which to unload the stream if the control tab is not visible">
2758 <label class="control-label" for="settings-webcamStreamTimeout">Stream timeout</label>
2759 <div class="controls">
2760 <div class="input-append">
2761 <input type="number" min="1" class="input-mini text-right" data-bind="value: webcam_streamTimeout" id="settings-webcamStreamTimeout">
2762 <span class="add-on">sec</span>
2763 </div>
2764 </div>
2765</div>
2766 </div>
2767 </div>
2768</form>
2769
2770<h3>Timelapse Recordings</h3>
2771
2772<form class="form-horizontal">
2773 <div class="control-group">
2774 <div class="controls">
2775 <label class="checkbox">
2776 <input type="checkbox" data-bind="checked: webcam_timelapseEnabled" id="settings-webcamTimelapseEnabled"> Enable timelapse support
2777 </label>
2778 </div>
2779</div>
2780 <div class="control-group" title="URL to use for retrieving webcam snapshot images for timelapse creation">
2781 <label class="control-label" for="settings-webcamSnapshotUrl">Snapshot URL</label>
2782 <div class="controls">
2783 <div class="input-append">
2784 <input type="text" class="input-block-level" data-bind="value: webcam_snapshotUrl, valueUpdate: 'afterkeydown'" id="settings-webcamSnapshotUrl">
2785 <button class="btn" type="button" data-bind="click: testWebcamSnapshotUrl, enable: webcam_snapshotUrl() && !testWebcamSnapshotUrlBusy(), css: {disabled: !webcam_snapshotUrl() || testWebcamSnapshotUrlBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testWebcamSnapshotUrlBusy"></i> Test</button>
2786 </div>
2787 <span class="help-inline">Fully qualified URL, needs to be reachable by OctoPrint's server</span>
2788 </div>
2789</div>
2790 <div class="control-group" title="Full path to the FFMPEG binary" data-bind="css: {error: webcam_ffmpegPathBroken, success: webcam_ffmpegPathOk}">
2791 <label class="control-label" for="settings-webcamFfmpegPath">Path to FFMPEG</label>
2792 <div class="controls">
2793 <div class="input-append">
2794 <input type="text" class="input-block-level" data-bind="value: webcam_ffmpegPath, valueUpdate: 'afterkeydown'" id="settings-webcamFfmpegPath">
2795 <button class="btn" type="button" data-bind="click: testWebcamFfmpegPath, enable: webcam_ffmpegPath() && !testWebcamFfmpegPathBusy(), css: {disabled: !webcam_ffmpegPath() || testWebcamFfmpegPathBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testWebcamFfmpegPathBusy"></i> Test</button>
2796 </div>
2797 <span class="help-block" data-bind="visible: webcam_ffmpegPathBroken() || webcam_ffmpegPathOk(), text: webcam_ffmpegPathText"></span>
2798 </div>
2799</div>
2800 <div class="control-group">
2801 <div class="controls">
2802 <label class="checkbox">
2803 <input type="checkbox" data-bind="checked: webcam_watermark" id="settings-webcamWatermark"> Enable OctoPrint watermark in timelapse movies
2804 </label>
2805 </div>
2806</div>
2807 <div>
2808 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.form-horizontal', container: '.hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
2809 <div class="hide">
2810 <div class="control-group" title="Bitrate to use for encoding the timelapse video">
2811 <label class="control-label" for="settings-webcamBitrate">Timelapse bitrate</label>
2812 <div class="controls">
2813 <div class="input-append">
2814 <input type="text" class="input-mini text-right" data-bind="value: webcam_bitrate" id="settings-webcamBitrate">
2815 <span class="add-on">bit/s</span>
2816 </div>
2817 </div>
2818</div>
2819 <div class="control-group" title="Number of FFMPEG encoding threads">
2820 <label class="control-label" for="settings-webcamFfmpegThreads">FFMPEG threads</label>
2821 <div class="controls">
2822 <input class="input-mini" data-bind="value: webcam_ffmpegThreads" id="settings-webcamFfmpegThreads" type="number" step="1" min="1">
2823 </div>
2824</div>
2825 <div class="control-group" title="Timeout for taking a snapshot">
2826 <label class="control-label" for="settings-webcamSnapshotTimeout">Snapshot timeout</label>
2827 <div class="controls">
2828 <div class="input-append">
2829 <input type="number" min="1" class="input-mini text-right" data-bind="value: webcam_snapshotTimeout" id="settings-webcamSnapshotTimeout">
2830 <span class="add-on">sec</span>
2831 </div>
2832 </div>
2833</div>
2834 <div class="control-group">
2835 <div class="controls">
2836 <label class="checkbox">
2837 <input type="checkbox" data-bind="checked: webcam_snapshotSslValidation" id="settings-webcamSnapshotSslValidation"> Validate SSL on snapshot URL (if applicable)
2838 </label>
2839 </div>
2840</div>
2841 <div class="control-group" title="Video codec used for encoding">
2842 <label class="control-label" for="settings-webcam_ffmpegVideoCodec">Video codec</label>
2843 <div class="controls">
2844 <select data-bind="options: webcam_available_videocodecs, value: webcam_ffmpegVideoCodec"></select>
2845 </div>
2846</div>
2847 </div>
2848 </div>
2849</form>
2850 </div>
2851
2852
2853
2854
2855
2856
2857 <div id="settings_users"
2858
2859 class="tab-pane "
2860
2861 >
2862 <ul class="nav nav-pills">
2863 <li id="settings_accesscontrol_users_link" class="active">
2864 <a href="#settings_accesscontrol_users" data-toggle="tab">Users</a>
2865 </li>
2866 <li id="settings_accesscontrol_groups_link">
2867 <a href="#settings_accesscontrol_groups" data-toggle="tab">Groups</a>
2868 </li>
2869</ul>
2870<div class="tab-content">
2871 <div id="settings_accesscontrol_users" class="tab-pane active">
2872 <table class="table table-condensed table-hover" id="system_users">
2873 <thead>
2874 <tr>
2875 <th class="settings_users_name">Name</th>
2876 <th class="settings_users_groups">Details</th>
2877 <th class="settings_users_active">Active</th>
2878 <th class="settings_users_actions">Action</th>
2879 </tr>
2880 </thead>
2881 <tbody data-bind="foreach: $root.access.users.listHelper.paginatedItems">
2882 <tr>
2883 <td class="settings_users_name"><span data-bind="text: name"></span></td>
2884 <td class="settings_users_details">
2885 <table class="table settings_users_details_table">
2886 <tr>
2887 <th class="settings_users_details_key">Groups</th>
2888 <td class="settings_users_details_value" data-bind="text: $root.access.groupList($data)"></td>
2889 </tr>
2890 <tr>
2891 <th class="settings_users_details_key">Permissions</th>
2892 <td class="settings_users_details_value" data-bind="text: $root.access.permissionList($data)"></td>
2893 </tr>
2894 <tr data-bind="visible: apikey">
2895 <th class="settings_users_details_key">API Key</th>
2896 <td class="settings_users_details_value"><span data-bind="text: apikey"></span> <a href="javascript:void(0)" title="Copy API Key to clipboard" data-bind="click: function() { copyToClipboard(apikey) }"><i class="fa fa-copy"></i></a></td>
2897 </tr>
2898 </table>
2899 </td>
2900 <td class="settings_users_active"><i class="fa" data-bind="css: { 'fa-check-square-o': active, 'fa-square-o': !active }"></i></td>
2901 <td class="settings_users_actions">
2902 <a href="#" class="fa fa-pencil" title="Update User" data-bind="click: function() { $root.access.users.showEditUserDialog($data); }"></a> | <a href="#" class="fa fa-key" title="Change password" data-bind="click: function() { $root.access.users.showChangePasswordDialog($data); }"></a> | <a href="#" class="fa fa-trash-o" title="Delete user" data-bind="click: function() { $root.access.users.removeUser($data); }"></a>
2903 </td>
2904 </tr>
2905 </tbody>
2906</table>
2907<div class="pagination pagination-mini pagination-centered">
2908 <ul>
2909 <li data-bind="css: {disabled: $root.access.users.listHelper.currentPage() === 0}"><a href="#" data-bind="click: access.users.listHelper.prevPage">«</a></li>
2910 </ul>
2911 <ul data-bind="foreach: access.users.listHelper.pages">
2912 <li data-bind="css: { active: $data.number === $root.access.users.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.access.users.listHelper.changePage($data.number); }"></a></li>
2913 </ul>
2914 <ul>
2915 <li data-bind="css: {disabled: $root.access.users.listHelper.currentPage() === access.users.listHelper.lastPage()}"><a href="#" data-bind="click: access.users.listHelper.nextPage">»</a></li>
2916 </ul>
2917</div>
2918
2919<button title="Add user" class="btn pull-right" data-bind="click: $root.access.users.showAddUserDialog"><i class="fa fa-plus"></i> Add user...</button>
2920
2921<!-- Modals for user management -->
2922
2923<script type="text/html" id="users-group-template">
2924 <!-- ko foreach: $root.access.groups.groupsList() -->
2925 <label class="checkbox">
2926 <input type="checkbox" data-bind="checkedValue: name, checked: $root.access.users.editor.groups"><span data-bind="text: name"></span><br>
2927 <span class="description" data-bind="text: description"></span>
2928 </label>
2929 <!-- /ko -->
2930</script>
2931
2932<div id="settings-usersEditorDialog" class="modal hide fade">
2933 <div class="modal-header">
2934 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
2935 <h3 data-bind="text: $root.access.users.editor.header"></h3>
2936 </div>
2937 <div class="modal-body">
2938 <div class="full-sized-box">
2939 <ul class="nav nav-pills">
2940 <li id="settings_accesscontrol_users_add_general_link" class="active">
2941 <a href="#settings_accesscontrol_users_add_general" data-toggle="tab">General</a>
2942 </li>
2943 <li id="settings_accesscontrol_users_add_groups_link">
2944 <a href="#settings_accesscontrol_users_add_groups" data-toggle="tab">Groups</a>
2945 </li>
2946 <li id="settings_accesscontrol_users_add_permissions_link">
2947 <a href="#settings_accesscontrol_users_add_permissions" data-toggle="tab">Additional permissions</a>
2948 </li>
2949 </ul>
2950 <div class="tab-content">
2951 <div id="settings_accesscontrol_users_add_general" class="tab-pane active">
2952 <form class="form-horizontal">
2953 <div class="control-group">
2954 <label class="control-label" for="settings-usersDialogAddUserName">Username</label>
2955 <div class="controls">
2956 <input type="text" class="input-block-level" id="settings-usersDialogAddUserName" data-bind="disable: !$root.access.users.editor.new(), value: $root.access.users.editor.name" required>
2957 </div>
2958 </div>
2959 <div class="control-group" data-bind="visible: $root.access.users.editor.new()">
2960 <label class="control-label" for="settings-usersDialogAddUserPassword1">Password</label>
2961 <div class="controls">
2962 <input type="password" class="input-block-level" id="settings-usersDialogAddUserPassword1" data-bind="value: $root.access.users.editor.password" required>
2963 </div>
2964 </div>
2965 <div class="control-group" data-bind="css: {error: $root.access.users.editor.passwordMismatch()}, visible: $root.access.users.editor.new()">
2966 <label class="control-label" for="settings-usersDialogAddUserPassword2">Repeat Password</label>
2967 <div class="controls">
2968 <input type="password" class="input-block-level" id="settings-usersDialogAddUserPassword2" data-bind="value: $root.access.users.editor.repeatedPassword, valueUpdate: 'afterkeydown'" required>
2969 <span class="help-inline" data-bind="visible: $root.access.users.editor.passwordMismatch()">Passwords do not match</span>
2970 </div>
2971 </div>
2972 <div class="control-group">
2973 <div class="controls">
2974 <label class="checkbox">
2975 <input type="checkbox" id="settings-usersDialogAddUserActive" data-bind="checked: $root.access.users.editor.active"> Active
2976 </label>
2977 </div>
2978 </div>
2979 </form>
2980 </div>
2981 <div id="settings_accesscontrol_users_add_groups" class="tab-pane">
2982 <!-- ko with: $root.access.users -->
2983 <!-- ko with: $root.access.groups -->
2984 <table class="table table-condensed table-hover settings_accesscontrol_groups_list">
2985 <tbody data-bind="foreach: groupsList()">
2986 <tr>
2987 <td class="settings_accesscontrol_groups_list_checkbox"><input type="checkbox" data-bind="checkedValue: key, checked: $parents[1].editor.groups, enable: toggleable"></td>
2988 <td class="settings_accesscontrol_groups_list_name" style="cursor: pointer" data-bind="click: function() { if ($data.toggleable) { $parents[1].editor.toggleGroup($data.key) } }, attr: {title: description}">
2989 <span class="name" data-bind="text: name, style: { fontWeight: ($parents[1].editor.groupSelected($data.name)) ? 'bold' : 'normal' }"></span> <small class="label label-info" data-bind="visible: !$data.toggleable" title="Fixed groups can't be added or removed to users.">Fixed</small><br>
2990 <small class="description" data-bind="text: description"></small><br>
2991 <small class="permissions muted" data-bind="text: $parents[1].editor.joinedGroupPermissions($data)"></small>
2992 </td>
2993 </tr>
2994 </tbody>
2995</table>
2996 <!-- /ko -->
2997 <!-- /ko -->
2998 </div>
2999 <div id="settings_accesscontrol_users_add_permissions" class="tab-pane">
3000 <!-- ko with: $root.access.users -->
3001 <!-- ko with: $root.access.permissions -->
3002 <table class="table table-condensed table-hover settings_accesscontrol_permissions_list">
3003 <tbody data-bind="foreach: permissionList()">
3004 <tr>
3005 <td class="settings_accesscontrol_permissions_list_checkbox"><input type="checkbox" data-bind="checkedValue: key, checked: $parents[1].editor.permissions"></td>
3006 <td class="settings_accesscontrol_permissions_list_name" style="cursor: pointer" data-bind="click: function() { $parents[1].editor.togglePermission($data.key) }, attr: {title: description}">
3007 <span class="name" data-bind="text: name, style: { fontWeight: ($parents[1].editor.permissionSelected($data.key)) ? 'bold' : 'normal' }"></span> <span class="label label-info" data-bind="visible: typeof(plugin) !== 'undefined'">Plugin</span> <span class="label label-important" data-bind="visible: dangerous">Warning</span><br>
3008 <small class="description muted" data-bind="text: description"></small>
3009 </td>
3010 </tr>
3011 </tbody>
3012</table>
3013 <!-- /ko -->
3014 <!-- /ko -->
3015 </div>
3016 </div>
3017 </div>
3018 </div>
3019 <div class="modal-footer">
3020 <button class="btn" data-dismiss="modal" aria-hidden="true">Abort</button>
3021 <button class="btn btn-primary" data-bind="click: function() { $root.access.users.editor.confirm(); }, enable: $root.access.users.editor.valid">Confirm</button>
3022 </div>
3023</div>
3024
3025<div id="settings-usersDialogChangePassword" class="modal hide fade">
3026 <div class="modal-header">
3027 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
3028 <h3>Change password for user "<span data-bind="text: $root.access.users.editor.name"></span>"</h3>
3029 </div>
3030 <div class="modal-body">
3031 <form class="form-horizontal">
3032 <div class="control-group">
3033 <label class="control-label" for="settings-usersDialogChangePasswordPassword1">New Password</label>
3034 <div class="controls">
3035 <input type="password" class="input-block-level" id="settings-usersDialogChangePasswordPassword1" data-bind="value: $root.access.users.editor.password" required>
3036 </div>
3037 </div>
3038 <div class="control-group" data-bind="css: {error: $root.access.users.editor.passwordMismatch()}">
3039 <label class="control-label" for="settings-usersDialogChangePasswordPassword2">Repeat Password</label>
3040 <div class="controls">
3041 <input type="password" class="input-block-level" id="settings-usersDialogChangePasswordPassword2" data-bind="value: $root.access.users.editor.repeatedPassword, valueUpdate: 'afterkeydown'" required>
3042 <span class="help-inline" data-bind="visible: $root.access.users.editor.passwordMismatch()">Passwords do not match</span>
3043 </div>
3044 </div>
3045 <fieldset>
3046 <legend>API Key</legend>
3047 <div class="control-group">
3048 <label class="control-label">Current API Key</label>
3049 <div class="controls">
3050 <div class="input-append input-block-level ">
3051 <input type="text" readonly="readonly" data-bind="value: $root.access.users.editor.apikey, valueUpdate: 'input', attr: {placeholder: 'N/A'}">
3052 <a class="btn add-on" title="Copy API Key to clipboard" data-bind="click: $root.access.users.copyApikey, css: {'disabled': !$root.access.users.editor.apikey()}"><i class="fa fa-copy"></i></a>
3053 <a class="btn add-on" title="Generate new API Key" data-bind="click: function() { $root.access.users.confirmGenerateApikey(); }"><i class="fa fa-refresh"></i></a>
3054 <a class="btn add-on btn-danger" title="Delete API Key" data-bind="click: function() { $root.access.users.confirmDeleteApikey(); }, css: {'disabled': !$root.access.users.editor.apikey()}"><i class="fa fa-trash-o"></i></a>
3055 </div>
3056
3057 </div>
3058 </div>
3059 </fieldset>
3060 </form>
3061 </div>
3062 <div class="modal-footer">
3063 <button class="btn" data-dismiss="modal" aria-hidden="true">Abort</button>
3064 <button class="btn btn-primary" data-bind="click: function() { $root.access.users.confirmChangePassword(); }, enable: !$root.access.users.editor.passwordMismatch()">Confirm</button>
3065 </div>
3066</div>
3067 </div>
3068 <div id="settings_accesscontrol_groups" class="tab-pane">
3069 <table class="table table-condensed table-hover" id="system_groups">
3070 <thead>
3071 <tr>
3072 <th class="settings_groups_default"></th>
3073 <th class="settings_groups_name">Name</th>
3074 <th class="settings_groups_details">Details</th>
3075 <th class="settings_groups_actions">Action</th>
3076 </tr>
3077 </thead>
3078 <tbody data-bind="foreach: $root.access.groups.listHelper.paginatedItems">
3079 <tr>
3080 <td class="settings_groups_default"><span class="fa fa-star" data-bind="invisible: !$data.default" title="Default group"></span></td>
3081 <td class="settings_groups_name">
3082 <span data-bind="text: name"></span><br>
3083 <small class="muted" data-bind="text: description"></small>
3084 </td>
3085 <td class="settings_groups_details">
3086 <table class="table settings_groups_details_table">
3087 <tr>
3088 <th class="settings_groups_details_key">Permissions</th>
3089 <td class="settings_groups_details_value" data-bind="text: $root.access.permissionList($data)"></td>
3090 </tr>
3091 <tr>
3092 <th class="settings_groups_details_key">Subgroups</th>
3093 <td class="settings_groups_details_value" data-bind="text: $root.access.subgroupList($data)"></td>
3094 </tr>
3095 </table>
3096 </td>
3097 <td class="settings_groups_actions">
3098 <a href="#" class="fa fa-pencil" title="Update group" data-bind="enable: changeable, css: {disabled: !changeable}, click: function() { $root.access.groups.showEditGroupDialog($data); }"></a> | <a href="#" class="fa fa-trash-o" title="Delete group" data-bind="enable: removable, css: {disabled: !removable}, click: function() { $root.access.groups.removeGroup($data); }"></a>
3099 </td>
3100 </tr>
3101 </tbody>
3102</table>
3103<div class="pagination pagination-mini pagination-centered">
3104 <ul>
3105 <li data-bind="css: {disabled: $root.access.groups.listHelper.currentPage() === 0}"><a href="#" data-bind="click: access.groups.listHelper.prevPage">«</a></li>
3106 </ul>
3107 <ul data-bind="foreach: $root.access.groups.listHelper.pages">
3108 <li data-bind="css: { active: $data.number === $root.access.groups.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.access.groups.listHelper.changePage($data.number); }"></a></li>
3109 </ul>
3110 <ul>
3111 <li data-bind="css: {disabled: $root.access.groups.listHelper.currentPage() === access.groups.listHelper.lastPage()}"><a href="#" data-bind="click: access.groups.listHelper.nextPage">»</a></li>
3112 </ul>
3113</div>
3114
3115<button title="Add group" class="btn pull-right" data-bind="click: $root.access.groups.showAddGroupDialog"><i class="fa fa-plus"></i> Add group...</button>
3116
3117<!-- Modals for group management -->
3118
3119<div id="settings-groupsEditorDialog" class="modal hide fade">
3120 <div class="modal-header">
3121 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
3122 <h3 data-bind="text: $root.access.groups.editor.header"></h3>
3123 </div>
3124 <div class="modal-body">
3125 <div class="full-sized-box">
3126 <ul class="nav nav-pills">
3127 <li id="settings_accesscontrol_groups_add_general_link" class="active">
3128 <a href="#settings_accesscontrol_groups_add_general" data-toggle="tab">General</a>
3129 </li>
3130 <li id="settings_accesscontrol_groups_add_permissions_link">
3131 <a href="#settings_accesscontrol_groups_add_permissions" data-toggle="tab">Permissions</a>
3132 </li>
3133 <li id="settings_accesscontrol_groups_add_subgroups_link">
3134 <a href="#settings_accesscontrol_groups_add_subgroups" data-toggle="tab">Subgroups</a>
3135 </li>
3136 </ul>
3137 <div class="tab-content">
3138 <div id="settings_accesscontrol_groups_add_general" class="tab-pane active">
3139 <form class="form-horizontal">
3140 <div class="control-group">
3141 <label class="control-label" for="settings-groupsDialogAddGroupName">Name</label>
3142 <div class="controls">
3143 <input type="text" class="input-block-level" id="settings-groupsDialogAddGroupName" data-bind="disable: !$root.access.groups.editor.new(), textInput: $root.access.groups.editor.name" required>
3144 </div>
3145 </div>
3146 <div class="control-group">
3147 <label class="control-label" for="settings-groupsDialogAddGroupDescription">Description</label>
3148 <div class="controls">
3149 <input type="text" class="input-block-level" id="settings-groupsDialogAddGroupDescription" data-bind="value: $root.access.groups.editor.description">
3150 </div>
3151 </div>
3152 <div class="control-group">
3153 <div class="controls">
3154 <label class="checkbox">
3155 <input type="checkbox" id="settings-groupsDialogEditDefault" data-bind="checked: $root.access.groups.editor.default"> Default
3156 </label>
3157 <span class="help-block">Marking a group as default will make it get pre selected when creating new users.</span>
3158 </div>
3159 </div>
3160 </form>
3161 </div>
3162 <div id="settings_accesscontrol_groups_add_permissions" class="tab-pane">
3163 <!-- ko with: $root.access.groups -->
3164 <!-- ko with: $root.access.permissions -->
3165 <table class="table table-condensed table-hover settings_accesscontrol_permissions_list">
3166 <tbody data-bind="foreach: permissionList()">
3167 <tr>
3168 <td class="settings_accesscontrol_permissions_list_checkbox"><input type="checkbox" data-bind="checkedValue: key, checked: $parents[1].editor.permissions"></td>
3169 <td class="settings_accesscontrol_permissions_list_name" style="cursor: pointer" data-bind="click: function() { $parents[1].editor.togglePermission($data.key) }, attr: {title: description}">
3170 <span class="name" data-bind="text: name, style: { fontWeight: ($parents[1].editor.permissionSelected($data.key)) ? 'bold' : 'normal' }"></span> <span class="label label-info" data-bind="visible: typeof(plugin) !== 'undefined'">Plugin</span> <span class="label label-important" data-bind="visible: dangerous">Warning</span><br>
3171 <small class="description muted" data-bind="text: description"></small>
3172 </td>
3173 </tr>
3174 </tbody>
3175</table>
3176 <!-- /ko -->
3177 <!-- /ko -->
3178 </div>
3179 <div id="settings_accesscontrol_groups_add_subgroups" class="tab-pane">
3180 <!-- ko with: $root.access.groups -->
3181 <!-- ko with: $root.access.groups -->
3182 <table class="table table-condensed table-hover settings_accesscontrol_groups_list">
3183 <tbody data-bind="foreach: groupsList()">
3184 <tr>
3185 <td class="settings_accesscontrol_subgroups_list_checkbox"><input type="checkbox" data-bind="checkedValue: key, checked: $parents[1].editor.subgroups, enable: toggleable"></td>
3186 <td class="settings_accesscontrol_subgroups_list_name" style="cursor: pointer" data-bind="click: function() { if ($data.toggleable) { $parents[1].editor.toggleSubgroup($data.key) } }, attr: {title: description}">
3187 <span class="name" data-bind="text: name, style: { fontWeight: ($parents[1].editor.subgroupSelected($data.name)) ? 'bold' : 'normal' }"></span> <small class="label label-info" data-bind="visible: !$data.toggleable" title="Fixed groups can't be added or removed to other groups.">Fixed</small><br>
3188 <small class="description" data-bind="text: description"></small><br>
3189 <small class="permissions muted" data-bind="text: $parents[1].editor.joinedGroupPermissions($data)"></small>
3190 </td>
3191 </tr>
3192 </tbody>
3193</table>
3194 <!-- /ko -->
3195 <!-- /ko -->
3196 </div>
3197 </div>
3198 </div>
3199 </div>
3200 <div class="modal-footer">
3201 <button class="btn" data-dismiss="modal" aria-hidden="true">Abort</button>
3202 <button class="btn btn-primary" data-bind="enable: $root.access.groups.editor.valid, click: function() { $root.access.groups.editor.confirm(); }">Confirm</button>
3203 </div>
3204</div>
3205 </div>
3206</div>
3207 </div>
3208
3209
3210
3211
3212
3213
3214 <div id="settings_gcodegcodevisualizer"
3215
3216 class="tab-pane "
3217
3218 >
3219 <form class="form-horizontal">
3220 <div class="control-group">
3221 <div class="controls">
3222 <label class="checkbox">
3223 <input type="checkbox" data-bind="checked: feature_gcodeViewer" id="settings-featureGcodeViewer"> Enable GCode Visualizer
3224 </label>
3225 </div>
3226 </div>
3227 <div class="control-group" title="Maximum size the GCodeViewer autoloads the file for preview">
3228 <label class="control-label" for="settings-featureSizeThreshold">GCode Visualizer file size threshold</label>
3229 <div class="controls">
3230 <div class="input-append">
3231 <input type="text" class="input-mini text-right" data-bind="value: feature_sizeThreshold_str" id="settings-featureSizeThreshold">
3232 </div>
3233 <span class="help-inline">on desktop</span>
3234 </div>
3235 <div class="controls">
3236 <div class="input-append">
3237 <input type="text" class="input-mini text-right" data-bind="value: feature_mobileSizeThreshold_str">
3238 </div>
3239 <span class="help-inline">on mobile</span>
3240 </div>
3241 <div class="controls">
3242 <span class="help-inline">
3243 Provide values including size unit. Allowed units are: b, byte, bytes, kb, mb, gb, tb (case insensitive). Example: <code>5MB</code>, <code>500KB</code>
3244 </span>
3245 </div>
3246 </div>
3247</form>
3248 </div>
3249
3250
3251
3252
3253
3254
3255 <div id="settings_api"
3256
3257 class="tab-pane "
3258
3259 >
3260 <form class="form-horizontal" onsubmit="return false;">
3261 <div class="control-group">
3262 <div class="controls">
3263 <label class="checkbox">
3264 <input type="checkbox" id="settings-apiCors" data-bind="checked: api_allowCrossOrigin"> Allow <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">Cross Origin Resource Sharing (CORS)</a> <label class="label label-info">Needs restart</label>
3265 </label>
3266 </div>
3267 </div>
3268 <div class="control-group">
3269 <label class="control-label" for="settings-apikey">API Key</label>
3270 <div class="controls">
3271 <div class="input-append input-block-level">
3272 <input type="text" readonly="readonly" id="settings-apikey" data-bind="value: api_key, attr: {placeholder: 'N/A'}">
3273 <a class="btn add-on" title="Copy API Key to clipboard" data-bind="click: copyApiKey, css: {'disabled': !api_key()}"><i class="fa fa-copy"></i></a>
3274 <a class="btn add-on" title="Generate new API Key" data-bind="click: generateApiKey"><i class="fa fa-refresh"></i></a>
3275 </div>
3276 <span class="help-block">Please note that changes to the API key are applied immediately, without having to "Save" first.</span>
3277 </div>
3278 </div>
3279 <div class="control-group" data-bind="visible: api_key">
3280 <label class="control-label">QR Code</label>
3281 <div class="controls">
3282 <div data-bind="qrcode: {text: api_key, size: 180}"></div>
3283 </div>
3284 </div>
3285</form>
3286 </div>
3287
3288
3289
3290
3291
3292 <!-- ko allowBindings: false -->
3293 <div id="settings_plugin_appkeys"
3294 data-bind="allowBindings: true"
3295 class="tab-pane "
3296
3297 >
3298 <div data-bind="visible: keys.allSize() <= 0">
3299 <p>There are no application keys registered yet.</p>
3300</div>
3301<div data-bind="visible: keys.allSize() > 0">
3302 <div class="pull-left">
3303 <div class="btn-group">
3304 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-square-o"></i> <span class="caret"></span></button>
3305 <ul class="dropdown-menu">
3306 <li><a href="javascript:void(0)" data-bind="click: markAllOnPageForDeletion">Select all on this page</a></li>
3307 <li><a href="javascript:void(0)" data-bind="click: markAllForDeletion">Select all</a></li>
3308 <li class="divider"></li>
3309 <li class="dropdown-submenu">
3310 <a href="javascript:void(0)" data-bind="javascript:void(0)">Select all by user...</a>
3311 <ul class="dropdown-menu" data-bind="foreach: users">
3312 <li><a href="javascript:void(0)" data-bind="click: function() { $root.markAllByUserForDeletion($data) }, text: $data"></a></li>
3313 </ul>
3314 </li>
3315 <li class="dropdown-submenu">
3316 <a href="javascript:void(0)" data-bind="javascript:void(0)">Select all by app...</a>
3317 <ul class="dropdown-menu" data-bind="foreach: apps">
3318 <li><a href="javascript:void(0)" data-bind="click: function() { $root.markAllByAppForDeletion($data) }, text: $data"></a></li>
3319 </ul>
3320 </li>
3321 <li class="divider"></li>
3322 <li><a href="javascript:void(0)" data-bind="click: clearMarked">Clear selection</a></li>
3323 </ul>
3324 </div>
3325 <button class="btn btn-small" data-bind="click: revokeMarked, enable: markedForDeletion().length > 0">Revoke selected</button>
3326 </div>
3327 <table class="table table-condensed table-hover" id="settings_plugin_appkeys_allkeys_table">
3328 <thead>
3329 <tr>
3330 <th class="settings_plugin_appkeys_checkbox"></th>
3331 <th class="settings_plugin_appkeys_user">User</th>
3332 <th class="settings_plugin_appkeys_app">Application identifier</th>
3333 <th class="settings_plugin_appkeys_actions">Action</th>
3334 </tr>
3335 </thead>
3336 <tbody data-bind="foreach: keys.paginatedItems">
3337 <tr>
3338 <td class="settings_plugin_appkeys_checkbox"><input type="checkbox" data-bind="value: api_key, checked: $root.markedForDeletion"></td>
3339 <td class="settings_plugin_appkeys_user"><span data-bind="text: user_id"></span></td>
3340 <td class="settings_plugin_appkeys_app"><span data-bind="text: app_id"></span><br /><small class="muted">API Key: <span data-bind="text: api_key"></span> <a href="javascript:void(0)" title="Copy API Key to clipboard" data-bind="click: function() { copyToClipboard(api_key) }"><i class="fa fa-copy"></i></a></small></td>
3341 <td class="settings_plugin_appkeys_actions"><a href="javascript:void(0)" title="Revoke" class="fa fa-trash-o" data-bind="click: function() { $parent.revokeKey($data.api_key, $data.user_id) }"></a></td>
3342 </tr>
3343 </tbody>
3344 </table>
3345 <div class="pagination pagination-mini pagination-centered">
3346 <ul>
3347 <li data-bind="css: {disabled: keys.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: keys.prevPage">«</a></li>
3348 </ul>
3349 <ul data-bind="foreach: keys.pages">
3350 <li data-bind="css: { active: $data.number === $root.keys.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.keys.changePage($data.number); }"></a></li>
3351 </ul>
3352 <ul>
3353 <li data-bind="css: {disabled: keys.currentPage() === keys.lastPage()}"><a href="javascript:void(0)" data-bind="click: keys.nextPage">»</a></li>
3354 </ul>
3355 </div>
3356</div>
3357 </div>
3358 <!-- /ko -->
3359
3360
3361
3362
3363
3364
3365
3366
3367 <div id="settings_server"
3368
3369 class="tab-pane "
3370
3371 >
3372 <form class="form-horizontal">
3373 <div class="control-group">
3374 <div class="controls">
3375 <label class="checkbox">
3376 <input type="checkbox" data-bind="checked: server_allowFraming" id="settings-serverAllowFraming"> Allow embedding the web interface into a frame or iframe <span class="label">Needs restart</span>
3377 </label>
3378 </div>
3379</div>
3380
3381 <h3>Commands</h3>
3382
3383 <div class="control-group" title="Command to restart the OctoPrint server">
3384 <label class="control-label" for="settings-serverRestartCommand">Restart OctoPrint</label>
3385 <div class="controls">
3386 <input type="text" class="input-block-level" data-bind="value: server_commands_serverRestartCommand" id="settings-serverRestartCommand">
3387 </div>
3388</div>
3389 <div class="control-group" title="Command to restart the system OctoPrint is running on">
3390 <label class="control-label" for="settings-systemRestartCommand">Restart system</label>
3391 <div class="controls">
3392 <input type="text" class="input-block-level" data-bind="value: server_commands_systemRestartCommand" id="settings-systemRestartCommand">
3393 </div>
3394</div>
3395 <div class="control-group" title="Command to shut down the system OctoPrint is running on">
3396 <label class="control-label" for="settings-systemShutdownCommand">Shutdown system</label>
3397 <div class="controls">
3398 <input type="text" class="input-block-level" data-bind="value: server_commands_systemShutdownCommand" id="settings-systemShutdownCommand">
3399 </div>
3400</div>
3401
3402 <h3>Connectivity check</h3>
3403
3404 <p>
3405 If the connectivity check is enabled, OctoPrint will regularly check if it's connected to the internet.
3406 This is <strong>useful to prevent resource intensive operations</strong> (such as checking for updates) if it's already
3407 clear that they won't succeed anyhow.
3408</p>
3409 <div class="control-group">
3410 <div class="controls">
3411 <label class="checkbox">
3412 <input type="checkbox" data-bind="checked: server_onlineCheck_enabled" id="settings-serverOnlineCheckEnabled"> Enable regular connectivity check
3413 </label>
3414 </div>
3415</div>
3416
3417<div data-bind="visible: server_onlineCheck_enabled">
3418 <div class="control-group">
3419 <div class="controls">
3420 <p>
3421 Define a check interval, a host and a port to check against. If you don't know what to set here, the
3422 default values (using Google's DNS server) should work. If you have concerns about using
3423 that, define the IP and port of a different online server that you trust and that has a high
3424 availability.
3425 </p>
3426 </div>
3427 </div>
3428
3429 <div class="control-group" title="Interval in which to check for internet connectivity">
3430 <label class="control-label" for="settings-serverOnlineCheckInterval">Check interval</label>
3431 <div class="controls">
3432 <span class="input-append">
3433 <input type="number" min="1" step="1" class="input-mini" data-bind="value: server_onlineCheck_interval" id="settings-serverOnlineCheckInterval">
3434 <span class="add-on">min</span>
3435 </span>
3436 </div>
3437</div>
3438 <div class="control-group" title="Host against which to check for internet connectivity" data-bind="css: {error: server_onlineCheckBroken, success: server_onlineCheckOk}">
3439 <label class="control-label" for="settings-serverOnlineCheckHost">Host IP</label>
3440 <div class="controls">
3441 <input type="text" class="input-small" data-bind="value: server_onlineCheck_host" id="settings-serverOnlineCheckHost">
3442 </div>
3443</div>
3444 <div class="control-group" title="Port against which to check for internet connectivity" data-bind="css: {error: server_onlineCheckBroken, success: server_onlineCheckOk}">
3445 <label class="control-label" for="settings-serverOnlineCheckPort">Port</label>
3446 <div class="controls">
3447 <input type="number" min="1" max="65535" step="1" class="input-small" data-bind="value: server_onlineCheck_port" id="settings-serverOnlineCheckPort">
3448 </div>
3449</div>
3450 <div class="control-group" title="Test" data-bind="css: {error: server_onlineCheckBroken, success: server_onlineCheckOk}">
3451 <div class="controls">
3452 <button class="btn" data-bind="click: testOnlineConnectivityConfig, enable: server_onlineCheck_host() && server_onlineCheck_port() && !testOnlineConnectivityConfigBusy(), css: {disabled: !server_onlineCheck_host() || !server_onlineCheck_port() || testOnlineConnectivityConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testOnlineConnectivityConfigBusy"></i> Test host & port</button>
3453 <span class="help-block" data-bind="visible: server_onlineCheckBroken() || server_onlineCheckOk(), text: server_onlineCheckText"></span>
3454 </div>
3455</div>
3456</div>
3457
3458 <h3>Plugin blacklist processing</h3>
3459
3460 <p>
3461 <strong>To protect against known severe issues with certain versions of third party plugins</strong>, OctoPrint supports
3462 the use of a centralized plugin version blacklist to automatically disable such plugins before they can interfere
3463 with normal operation.
3464</p>
3465
3466<p>
3467 By default, OctoPrint will use the blacklist hosted at <code>plugins.octoprint.org/blacklist.json</code> which you
3468 can also take a look at in a more human readable format <a href="https://plugins.octoprint.org/blacklist/" target="_blank">here</a>.
3469</p>
3470 <div class="control-group">
3471 <div class="controls">
3472 <label class="checkbox">
3473 <input type="checkbox" data-bind="checked: server_pluginBlacklist_enabled" id="settings-serverPluginBlacklistEnabled"> Enable plugin blacklist processing on startup
3474 <span class="help-block">Any changes take effect only on the next server start.</span>
3475 </label>
3476 </div>
3477</div>
3478
3479<div data-bind="visible: server_pluginBlacklist_enabled">
3480 <div class="advanced_options">
3481 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.advanced_options', container: '.hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
3482 <div class="hide">
3483 <div class="control-group" title="Plugin blacklist URL. You should normally not have to change this.">
3484 <label class="control-label" for="settings-serverPluginBlacklistUrl">Blacklist URL</label>
3485 <div class="controls">
3486 <input type="text" class="input-block-level" data-bind="value: server_pluginBlacklist_url" id="settings-serverPluginBlacklistUrl">
3487 </div>
3488</div>
3489 <div class="control-group" title="How long to cache the blacklist, in minutes. You should normally not have to change this.">
3490 <label class="control-label" for="settings-serverPluginBlacklistTtl">Blacklist cache TTL</label>
3491 <div class="controls">
3492 <div class="input-append">
3493 <input type="number" class="input-mini" data-bind="value: server_pluginBlacklist_ttl" id="settings-serverPluginBlacklistTtl">
3494 <span class="add-on">min</span>
3495 </div>
3496 </div>
3497</div>
3498 </div>
3499 </div>
3500</div>
3501</form>
3502 </div>
3503
3504
3505
3506
3507
3508
3509 <div id="settings_folders"
3510
3511 class="tab-pane "
3512
3513 >
3514 <form class="form-horizontal">
3515 <h3>Folders</h3>
3516
3517 <div class="control-group" data-bind="css: {error: testFolderConfigBroken.uploads, success: testFolderConfigOk.uploads}">
3518 <label class="control-label" for="settings-folderUploads">Upload Folder</label>
3519 <div class="controls">
3520 <div class="input-append input-block-level">
3521 <input type="text" data-bind="value: folder_uploads" id="settings-folderUploads">
3522 <a class="btn add-on" data-bind="click: function() { testFolderConfig('uploads'); }, enable: folder_uploads() && !testFolderConfigBusy(), css: {disabled: !folder_uploads() || testFolderConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testFolderConfigBusy"></i> Test</a>
3523 </div>
3524 <span class="help-block" data-bind="visible: testFolderConfigBroken.uploads() || testFolderConfigOk.uploads(), text: testFolderConfigText.uploads"></span>
3525 </div>
3526 </div>
3527 <div class="control-group" data-bind="css: {error: testFolderConfigBroken.timelapse, success: testFolderConfigOk.timelapse}">
3528 <label class="control-label" for="settings-folderTimelapse">Timelapse Folder</label>
3529 <div class="controls">
3530 <div class="input-append input-block-level">
3531 <input type="text" class="input-block-level" data-bind="value: folder_timelapse" id="settings-folderTimelapse">
3532 <a class="btn add-on" data-bind="click: function() { testFolderConfig('timelapse'); }, enable: folder_timelapse() && !testFolderConfigBusy(), css: {disabled: !folder_timelapse() || testFolderConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testFolderConfigBusy"></i> Test</a>
3533 </div>
3534 <span class="help-block" data-bind="visible: testFolderConfigBroken.timelapse() || testFolderConfigOk.timelapse(), text: testFolderConfigText.timelapse"></span>
3535 </div>
3536 </div>
3537 <div class="control-group" data-bind="css: {error: testFolderConfigBroken.timelapseTmp, success: testFolderConfigOk.timelapseTmp}">
3538 <label class="control-label" for="settings-folderTimelapseTemp">Timelapse Temp Folder</label>
3539 <div class="controls">
3540 <div class="input-append input-block-level">
3541 <input type="text" data-bind="value: folder_timelapseTmp" id="settings-folderTimelapseTemp">
3542 <a class="btn add-on" data-bind="click: function() { testFolderConfig('timelapseTmp'); }, enable: folder_timelapseTmp() && !testFolderConfigBusy(), css: {disabled: !folder_timelapseTmp() || testFolderConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testFolderConfigBusy"></i> Test</a>
3543 </div>
3544 <span class="help-block" data-bind="visible: testFolderConfigBroken.timelapseTmp() || testFolderConfigOk.timelapseTmp(), text: testFolderConfigText.timelapseTmp"></span>
3545 </div>
3546 </div>
3547 <div class="control-group" data-bind="css: {error: testFolderConfigBroken.logs, success: testFolderConfigOk.logs}">
3548 <label class="control-label" for="settings-folderLogs">Logs Folder</label>
3549 <div class="controls">
3550 <div class="input-append input-block-level">
3551 <input type="text" data-bind="value: folder_logs" id="settings-folderLogs">
3552 <a class="btn add-on" data-bind="click: function() { testFolderConfig('logs'); }, enable: folder_logs() && !testFolderConfigBusy(), css: {disabled: !folder_logs() || testFolderConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testFolderConfigBusy"></i> Test</a>
3553 </div>
3554 <span class="help-block" data-bind="visible: testFolderConfigBroken.logs() || testFolderConfigOk.logs(), text: testFolderConfigText.logs"></span>
3555 </div>
3556 </div>
3557 <div class="control-group" data-bind="css: {error: testFolderConfigBroken.watched, success: testFolderConfigOk.watched}">
3558 <label class="control-label" for="settings-folderWatched">Watched Folder</label>
3559 <div class="controls">
3560 <div class="input-append input-block-level">
3561 <input type="text" data-bind="value: folder_watched" id="settings-folderWatched">
3562 <a class="btn add-on" data-bind="click: function() { testFolderConfig('watched'); }, enable: folder_watched() && !testFolderConfigBusy(), css: {disabled: !folder_watched() || testFolderConfigBusy()}"><i class="fa fa-spinner fa-spin" data-bind="visible: testFolderConfigBusy"></i> Test</a>
3563 </div>
3564 <span class="help-block" data-bind="visible: testFolderConfigBroken.watched() || testFolderConfigOk.watched(), text: testFolderConfigText.watched"></span>
3565 </div>
3566 </div>
3567 <div class="control-group">
3568 <div class="controls">
3569 <label class="checkbox">
3570 <input type="checkbox" data-bind="checked: feature_pollWatched" id="settings-featurePollWatched"> Actively poll the watched folder. Check this if files in your watched folder aren't automatically added otherwise.
3571 </label>
3572 </div>
3573 </div>
3574
3575 <h3>Disk space thresholds</h3>
3576
3577 <p>If the free disk space falls below these thresholds, OctoPrint will warn the user.</p>
3578
3579 <div class="control-group" title="Threshold after which to warn about the remaining free space on disk.">
3580 <label class="control-label" for="settings-serverDiskusageWarning">Warning</label>
3581 <div class="controls">
3582 <input type="text" class="input-mini text-right" data-bind="value: server_diskspace_warning_str" id="settings-serverDiskusageWarning">
3583 </div>
3584 </div>
3585 <div class="control-group" title="Threshold after which to consider remaining free space on disk as critical.">
3586 <label class="control-label" for="settings-serverDiskusageCritical">Critical</label>
3587 <div class="controls">
3588 <input type="text" class="input-mini text-right" data-bind="value: server_diskspace_critical_str" id="settings-serverDiskusageCritical">
3589 </div>
3590 </div>
3591
3592 <p>Provide values including size unit. Allowed units are: b, byte, bytes, kb, mb, gb, tb (case insensitive). Example: <code>5MB</code>, <code>500KB</code></p>
3593</form>
3594 </div>
3595
3596
3597
3598
3599
3600
3601 <div id="settings_appearance"
3602
3603 class="tab-pane "
3604
3605 >
3606 <form class="form-horizontal">
3607 <div class="control-group" title="Name of this OctoPrint instance, will be shown in the navigation bar and broadcast on the network">
3608 <label class="control-label" for="settings-appearanceName">Title</label>
3609 <div class="controls">
3610 <input type="text" class="input-block-level" data-bind="value: appearance_name" id="settings-appearanceName">
3611 </div>
3612 </div>
3613 <div class="control-group" title="Personalize the color of the navigation bar - maybe to match your printer?">
3614 <label class="control-label" for="settings-appearanceColor">Color</label>
3615 <div class="controls">
3616 <select id="settings-appearanceColor" data-bind="value: appearance_color, options: appearance_available_colors, optionsText: 'name', optionsValue: 'key'">
3617 </select>
3618 </div>
3619 </div>
3620 <div class="control-group" title="For acrylic printers ;)">
3621 <div class="controls">
3622 <label class="checkbox">
3623 <input type="checkbox" data-bind="checked: appearance_colorTransparent"> Transparent color
3624 </label>
3625 </div>
3626 </div>
3627 <div class="control-group" title="Also personalize the icon of the browser tab">
3628 <div class="controls">
3629 <label class="checkbox">
3630 <input type="checkbox" data-bind="checked: appearance_colorIcon"> Colorize favicon (in supported browsers)
3631 </label>
3632 </div>
3633 </div>
3634 <div class="control-group" title="">
3635 <label class="control-label" for="settings-appearanceLanguages">Language Packs</label>
3636 <div class="controls">
3637 <button class="btn" data-bind="click: showTranslationManager" id="settings-appearanceLanguages">Manage...</button>
3638 </div>
3639 </div>
3640 <div class="control-group" title="">
3641 <label class="control-label" for="settings-appearanceDefaultLanguage">Default Language</label>
3642 <div class="controls">
3643 <select id="settings-appearanceDefaultLanguage" data-bind="options: locales,
3644 optionsText: function(item) { return item.display + ((item.language != undefined && item.english != undefined) ? ' [' + item.language + ', ' + item.english + ']' : '') },
3645 optionsValue: 'language',
3646 value: appearance_defaultLanguage">
3647 </select>
3648 <span class="help-inline">Changes to the default interface language will only become active after a reload of the page and only be active if not overridden by the users language settings.</span>
3649 </div>
3650 </div>
3651 <div class="control-group">
3652 <div class="controls">
3653 <label class="checkbox">
3654 <input type="checkbox" data-bind="checked: appearance_showFahrenheitAlso" id="settings-appearanceShowFahrenheitAlso"> Show temperatures in Fahrenheit as well as Celsius
3655 </label>
3656 </div>
3657 </div>
3658 <div class="control-group">
3659 <div class="controls">
3660 <label class="checkbox">
3661 <input type="checkbox" data-bind="checked: appearance_fuzzyTimes" id="settings-appearanceFuzzyTimes"> Show fuzzy print time estimates
3662 </label>
3663 </div>
3664 </div>
3665 <div class="control-group">
3666 <div class="controls">
3667 <label class="checkbox">
3668 <input type="checkbox" data-bind="checked: appearance_closeModalsWithClick" id="settings-appearanceCloseModalsWithClick"> Close dialogs by clicking outside
3669 </label>
3670 </div>
3671 </div>
3672</form>
3673
3674<div id="settings_appearance_managelanguagesdialog" class="modal hide fade">
3675 <div class="modal-header">
3676 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
3677 <h3>Manage Language Packs...</h3>
3678 </div>
3679 <div class="modal-body">
3680 <p>
3681 <strong>There is currently no central repository for language packs like there is for plugins - any help to change that is appreciated!</strong>
3682 </p>
3683 <p>
3684 Until a repository is available, please see <a href="https://github.com/foosel/OctoPrint/wiki#language-packs" target="_blank" >the wiki</a> for language packs provided by the community.
3685 </p>
3686
3687 <h4>Available Language Packs</h4>
3688
3689 <div data-bind="visible: languagePacksAvailable()">
3690 <div id="settings_appearance_managelanguagesdialog_list" data-bind="foreach: translations.paginatedItems">
3691 <div class="entry">
3692 <strong><a href="#" class="fa" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.entry', container: '.packs' }"><i class="fa fa-caret-down"></i> <span data-bind="text: $root.languagePackDisplay($data)"></span></a></strong>
3693 <div class="packs">
3694 <!-- ko foreach: $data.packs -->
3695 <div class="row-fluid">
3696 <div class="span8 offset1">
3697 <strong data-bind="text: display"></strong><br />
3698 <small data-bind="visible: pack.last_update" class="muted">Last update: <span data-bind="text: formatDate($data.pack.last_update)"></span></small>
3699 </div>
3700 <div class="span3">
3701 <button class="btn btn-block btn-small" data-bind="click: function() {$root.deleteLanguagePack($data.pack.locale, $data.identifier)}"><i class="fa fa-trash-o"></i> Delete</button>
3702 </div>
3703 </div>
3704 <!-- /ko -->
3705 </div>
3706 </div>
3707 </div>
3708 </div>
3709 <div id="settings_appearance_managelanguagesdialog_emptylist" data-bind="visible: !languagePacksAvailable()">
3710 <div>
3711 <p>
3712 <strong>No additional Language Packs are installed at the moment.</strong>
3713 </p>
3714 </div>
3715 </div>
3716
3717 <h4>Upload additional Language Packs</h4>
3718
3719 <form class="form-inline">
3720 <div class="control-group row-fluid" data-bind="css: {error: invalidTranslationArchive}">
3721 <div class="input-prepend span9">
3722 <span class="btn fileinput-button">
3723 <span>Browse...</span>
3724 <input id="settings_appearance_managelanguagesdialog_upload" type="file" name="file" accept=".zip,.tar.gz,.tgz,.tar" data-url="/api/languages">
3725 </span>
3726 <span class="add-on add-on-limited text-left" data-bind="text: translationUploadFilename, attr: {title: translationUploadFilename}"></span>
3727 </div>
3728 <button id="settings_appearance_managelanguagesdialog_upload_start" class="btn btn-primary span3" data-bind="enable: enableTranslationUpload, css: {disabled: !enableTranslationUpload()}, click: function(){}">Upload</button>
3729 </div>
3730 <span class="help-block" data-bind="visible: invalidTranslationArchive">This does not look like a valid language pack. Valid language packs should be either zip files or tarballs and have the extension ".zip", ".tar.gz", ".tgz" or ".tar"</span>
3731 </form>
3732
3733 <small>Please note that you will have to reload the page in order for any newly added language packs to become available.</small>
3734 </div>
3735 <div class="modal-footer">
3736 <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
3737 </div>
3738</div>
3739 </div>
3740
3741
3742
3743
3744
3745 <!-- ko allowBindings: false -->
3746 <div id="settings_plugin_logging"
3747 data-bind="allowBindings: true"
3748 class="tab-pane "
3749
3750 >
3751 <h3>Logs</h3>
3752
3753<div class="pull-right">
3754 <div class="btn-group">
3755 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-wrench"></i> <span class="caret"></span></button>
3756 <ul class="dropdown-menu dropdown-menu-right">
3757 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('name'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'name' ? 'visible' : 'hidden'}"></i> Sort by name (ascending)</a></li>
3758 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('modification'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'modification' ? 'visible' : 'hidden'}"></i> Sort by modification date (descending)</a></li>
3759 <li><a href="javascript:void(0)" data-bind="click: function() { listHelper.changeSorting('size'); }"><i class="fa fa-check" data-bind="style: {visibility: listHelper.currentSorting() == 'size' ? 'visible' : 'hidden'}"></i> Sort by file size (descending)</a></li>
3760 </ul>
3761 </div>
3762</div>
3763<div class="pull-left">
3764 <div class="btn-group">
3765 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-square-o"></i> <span class="caret"></span></button>
3766 <ul class="dropdown-menu">
3767 <li><a href="javascript:void(0)" data-bind="click: markFilesOnPage">Select all on this page</a></li>
3768 <li><a href="javascript:void(0)" data-bind="click: markAllFiles">Select all</a></li>
3769 <li class="divider"></li>
3770 <li><a href="javascript:void(0)" data-bind="click: clearMarkedFiles">Clear selection</a></li>
3771 </ul>
3772 </div>
3773 <button class="btn btn-small" data-bind="click: removeMarkedFiles, enable: markedForDeletion().length > 0">Delete selected</button>
3774</div>
3775<table class="table table-striped table-hover table-condensed table-hover" id="log_files">
3776 <thead>
3777 <tr>
3778 <th class="settings_logs_checkbox"></th>
3779 <th class="settings_logs_name">Name</th>
3780 <th class="settings_logs_size">Size</th>
3781 <th class="settings_logs_date">Date</th>
3782 <th class="settings_logs_action">Action</th>
3783 </tr>
3784 </thead>
3785 <tbody data-bind="foreach: listHelper.paginatedItems">
3786 <tr data-bind="attr: {title: name}">
3787 <td class="settings_logs_checkbox"><input type="checkbox" data-bind="value: name, checked: $root.markedForDeletion"></td>
3788 <td class="settings_logs_name" data-bind="text: name"></td>
3789 <td class="settings_logs_size" data-bind="text: formatSize(size)"></td>
3790 <td class="settings_logs_date" data-bind="text: formatDate(date)"></td>
3791 <td class="settings_logs_action">
3792 <a href="#" class="icon-trash" data-bind="click: function() { if ($root.loginState.isUser()) { $parent.removeFile($data.name); } else { return; } }, css: {disabled: !$root.loginState.isUser()}"></a> | <a href="#" class="icon-download" data-bind="attr: {href: refs.download}"></a>
3793 </td>
3794 </tr>
3795 </tbody>
3796</table>
3797<div class="pagination pagination-mini pagination-centered">
3798 <ul>
3799 <li data-bind="css: {disabled: listHelper.currentPage() === 0}">
3800 <a href="#" data-bind="click: listHelper.prevPage">«</a>
3801 </li>
3802 </ul>
3803 <ul data-bind="foreach: listHelper.pages">
3804 <li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }">
3805 <a href="#" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a>
3806 </li>
3807 </ul>
3808 <ul>
3809 <li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}">
3810 <a href="#" data-bind="click: listHelper.nextPage">»</a>
3811 </li>
3812 </ul>
3813</div>
3814
3815<h3>Logging Levels</h3>
3816<form class="form-horizontal">
3817
3818 <div class="row-fluid">
3819 <div class="span8"><h5>Name</h5></div>
3820 <div class="span2"><h5>Level</h5></div>
3821 </div>
3822 <div data-bind="foreach: configuredLoggersSorted">
3823 <div class="row-fluid" style="margin-bottom: 5px">
3824 <div class="span8">
3825 <span data-bind="text: component"></span>
3826 </div>
3827 <div class="span3">
3828 <select data-bind="value: level, event: { change: $parent.configuredLoggersHasChanged }" class="input-medium">
3829 <option value="DEBUG">DEBUG</option>
3830 <option value="INFO">INFO</option>
3831 <option value="WARNING">WARNING</option>
3832 <option value="ERROR">ERROR</option>
3833 <option value="CRITICAL">CRITICAL</option>
3834 </select>
3835 </div>
3836 <div class="span1">
3837 <a title="Remove" class="btn btn-danger" data-bind="click: $parent.removeLogger"><i class="icon-trash"></i></a>
3838 </div>
3839 </div>
3840 </div>
3841 <div>
3842 <div class="row-fluid" style="margin-bottom: 5px">
3843 <div class="span8">
3844 <select class="input-block-level" data-bind="options: availableLoggersSorted, value: availableLoggersName"></select>
3845 </div>
3846 <div class="span3">
3847 <select class="input-medium" data-bind="value: availableLoggersLevel">
3848 <option value="DEBUG">DEBUG</option>
3849 <option value="INFO">INFO</option>
3850 <option value="WARNING">WARNING</option>
3851 <option value="ERROR">ERROR</option>
3852 <option value="CRITICAL">CRITICAL</option>
3853 </select>
3854 </div>
3855 <div class="span1">
3856 <a title="Add" class="btn btn-primary" data-bind="click: $root.addLogger"><i class="icon-plus"></i></a>
3857 </div>
3858 </div>
3859 </div>
3860</form>
3861 </div>
3862 <!-- /ko -->
3863
3864
3865
3866
3867 <!-- ko allowBindings: false -->
3868 <div id="settings_plugin_pluginmanager"
3869 data-bind="allowBindings: true"
3870 class="tab-pane "
3871
3872 >
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883<ul class="nav nav-pills">
3884 <li class="active">
3885 <a href="#settings_plugin_pluginmanager_plugins" data-toggle="tab">Plugins</a>
3886 </li>
3887 <li>
3888 <a href="#settings_plugin_pluginmanager_cleanup" data-toggle="tab">Cleanup</a>
3889 </li>
3890</ul>
3891
3892<div class="tab-content">
3893 <div class="tab-pane active" id="settings_plugin_pluginmanager_plugins">
3894
3895<div class="alert" data-bind="visible: !enableManagement()">
3896 Take note that all plugin management functionality is disabled while your printer is printing or paused.
3897</div>
3898
3899
3900<div class="alert" data-bind="visible: !pipAvailable()">
3901 The <code>pip</code> command could not be found or does not work correctly
3902 for this installation of OctoPrint - please consult the log file for details
3903 and if necessary configure it manually. No installation and uninstallation of plugin
3904 packages is possible while <code>pip</code> is unavailable.
3905</div>
3906
3907
3908<div class="alert" data-bind="visible: safeMode">
3909 Safe mode is currently active. All third party plugins are disabled and cannot be
3910 enabled. Installation of plugin packages is disabled.
3911</div>
3912
3913
3914<div class="alert" data-bind="visible: throttled">
3915 The system OctoPrint is running on is currently throttled. Due to that it's not possible to install new
3916 plugins in order to avoid possible issues caused by system instability.
3917</div>
3918
3919
3920 <div class="pull-right">
3921 <button class="btn btn-small" data-bind="click: function() { $root.showPluginSettings(); }" title="Plugin Configuration"><i class="fa fa-wrench"></i></button>
3922 </div>
3923
3924 <h3>Installed Plugins</h3>
3925
3926 <div style="margin-bottom: 1em" class="clearfix">
3927 <input type="text" class="input-block search-query pull-left" data-bind="value: listingSearchQuery, valueUpdate: 'input'" placeholder="Search...">
3928
3929 <div class="pull-right">
3930 <div class="btn-group">
3931 <button class="btn btn-small" data-bind="click: function() { plugins.removeFilter('bundled'); plugins.removeFilter('3rdparty'); }, css: {active: !_.contains(plugins.currentFilters(), 'bundled') && !_.contains(plugins.currentFilters(), '3rdparty')}" title="Show both bundled and third-party plugins">All</button>
3932 <button class="btn btn-small" data-bind="click: function() { plugins.addFilter('bundled') }, css: {active: _.contains(plugins.currentFilters(), 'bundled')}" title="Show only bundled plugins">Bundled</button>
3933 <button class="btn btn-small" data-bind="click: function() { plugins.addFilter('3rdparty') }, css: {active: _.contains(plugins.currentFilters(), '3rdparty')}" title="Show only third-party plugins">3rd party</button>
3934 </div>
3935 <div class="btn-group">
3936 <button class="btn btn-small" data-bind="click: function() { plugins.removeFilter('enabled'); plugins.removeFilter('disabled'); }, css: {active: !_.contains(plugins.currentFilters(), 'enabled') && !_.contains(plugins.currentFilters(), 'disabled')}" title="Show both enabled and disabled plugins">All</button>
3937 <button class="btn btn-small" data-bind="click: function() { plugins.addFilter('enabled') }, css: {active: _.contains(plugins.currentFilters(), 'enabled')}" title="Show only enabled plugins">Enabled</button>
3938 <button class="btn btn-small" data-bind="click: function() { plugins.addFilter('disabled') }, css: {active: _.contains(plugins.currentFilters(), 'disabled')}" title="Show only disabled plugins">Disabled</button>
3939 </div>
3940 </div>
3941 </div>
3942
3943 <div id="settings_plugin_pluginmanager_pluginlist">
3944 <table class="table table-striped table-hover table-condensed table-hover">
3945 <thead>
3946 <tr>
3947 <th class="settings_plugin_plugin_manager_plugins_name">Name</th>
3948 <th class="settings_plugin_plugin_manager_plugins_actions">Actions</th>
3949 </tr>
3950 </thead>
3951 <tbody data-bind="foreach: plugins.paginatedItems">
3952 <tr>
3953 <td class="settings_plugin_plugin_manager_plugins_name">
3954 <div data-bind="css: {muted: !enabled}"><span data-bind="text: name"></span> <span data-bind="visible: version">(<span data-bind="text: version"></span>)</span> <i title="Bundled with OctoPrint" class="fa fa-th-large" data-bind="visible: bundled"></i> <i class="fa fa-lock" title="Cannot be uninstalled through OctoPrint" data-bind="visible: !managable"></i> <i title="Restart of OctoPrint needed for changes to take effect" class="fa fa-refresh" data-bind="visible: pending_enable || pending_disable || pending_install || pending_uninstall"></i> <i title="Pending install" class="fa fa-plus" data-bind="visible: pending_install"></i> <i title="Pending uninstall" class="fa fa-minus" data-bind="visible: pending_uninstall"></i> <i title="Disabled due to safe mode" class="fa fa-medkit" data-bind="visible: safe_mode_victim"></i> <i class="fa fa-exclamation-triangle" title="There are notices available regarding this plugin" data-bind="visible: notifications && notifications.length"></i> <i class="fa fa-ban" title="This plugin is blacklisted" data-bind="visible: blacklisted"></i></div>
3955 <div data-bind="visible: notifications && notifications.length"><a href="javascript:void(0)" class="text-error" style="text-decoration: underline" data-bind="click: function() { $root.showPluginNotifications($data) }, text: $root.showPluginNotificationsLinkText($data)"></a></div>
3956 <div><small class="muted" data-bind="text: description"> </small></div>
3957 <div data-bind="css: {muted: !enabled}">
3958 <small data-bind="visible: url"><i class="fa fa-home"></i> <a data-bind="attr: {href: url}" target="_blank" rel="noreferrer noopener">Homepage</a></small>
3959 <small data-bind="visible: license"><i class="fa fa-gavel"></i> <span data-bind="text: license"></span></small>
3960 <small data-bind="visible: author"><i class="fa fa-user"></i> <span data-bind="text: author"></span></small>
3961 <small> </small>
3962 </div>
3963 </td>
3964 <td class="settings_plugin_plugin_manager_plugins_actions">
3965 <a href="#" data-bind="css: $root.toggleButtonCss($data), attr: {title: $root.toggleButtonTitle($data)}, enable: $root.enableToggle($data), click: function() { $root.togglePlugin($data) }"></a> | <a href="#" class="fa fa-eraser" title="Cleanup Plugin Data" data-bind="css: {disabled: !$root.enableCleanup($data)}, enable: $root.enableCleanup($data), click: function() { $root.cleanupPlugin($data) }"></a> | <a href="#" class="fa fa-trash-o" title="Uninstall Plugin" data-bind="css: {disabled: !$root.enableUninstall($data)}, enable: $root.enableUninstall($data), click: function() { $root.uninstallPlugin($data) }"></a>
3966 </td>
3967 </tr>
3968 </tbody>
3969 </table>
3970 </div>
3971
3972 <button class="btn btn-block" data-bind="click: $root.showRepository">Get More...</button>
3973
3974 <div class="muted" data-bind="visible: pipAvailable()">
3975 <div>
3976 <small>
3977 <a href="javascript:void(0)" class="muted" onclick="$(this).children('i.toggle-arrow').toggleClass('fa-caret-right fa-caret-down').parent().parent().parent().next().slideToggle('fast')">
3978 <i class="fa toggle-arrow fa-caret-right"></i> Using pip of "<span data-bind="text: pipPython"></span>", Version <span data-bind="text: pipVersion"></span>
3979 </a>
3980 </small>
3981 </div>
3982 <div class="hide">
3983 <small>
3984 Installation directory: <span data-bind="text: pipInstallDir"></span> ("--user" flag: <span data-bind="text: pipUseUserString"></span>)<br />
3985 Virtual environment: <span data-bind="text: pipVirtualEnvString"></span><br />
3986 <span data-bind="visible: pipAdditionalArgs">Additional Arguments: <span data-bind="text: pipAdditionalArgs"></span></span>
3987 </small>
3988 </div>
3989 </div>
3990
3991 <div class="muted">
3992 <div>
3993 <small>
3994 <a href="javascript:void(0)" class="muted" onclick="$(this).children('i.toggle-arrow').toggleClass('fa-caret-right fa-caret-down').parent().parent().parent().next().slideToggle('fast')">
3995 <i class="toggle-arrow fa fa-caret-right"></i> <span data-bind="text: noticeCountText"></span>
3996 </a>
3997 </small>
3998 </div>
3999 <div class="hide">
4000 <small>
4001 <!-- ko if: noticeCount() > 0 --><a href="javascript:void(0)" data-bind="click: function() { reshowNotices(); }">Reshow current notices</a> ·<!-- /ko -->
4002 <a href="javascript:void(0)" data-bind="click: function() { refreshNotices(); }">Refresh notices from repository</a>
4003 </small>
4004 </div>
4005 </div>
4006 </div>
4007
4008 <div class="tab-pane" id="settings_plugin_pluginmanager_cleanup">
4009 <div class="pull-right">
4010 <button class="btn btn-small" data-bind="click: function() { $root.requestData({refresh_orphans: true}) }" title="Refresh"><i class="fa fa-refresh"></i></button>
4011 </div>
4012
4013 <h3>Cleanup</h3>
4014
4015 <div data-bind="visible: orphans.paginatedItems().length > 0">
4016 <div id="settings_plugin_pluginmanager_orphanlist">
4017 <table class="table table-striped table-hover table-condensed table-hover">
4018 <thead>
4019 <tr>
4020 <th class="settings_plugin_plugin_manager_orphans_id">Identifier</th>
4021 <th class="settings_plugin_plugin_manager_orphans_actions">Actions</th>
4022 </tr>
4023 </thead>
4024 <tbody data-bind="foreach: orphans.paginatedItems">
4025 <tr>
4026 <td class="settings_plugin_plugin_manager_orphans_id">
4027 <span data-bind="text: identifier"></span>
4028 </td>
4029 <td class="settings_plugin_plugin_manager_orphans_actions">
4030 <a href="javascript:void(0)" class="fa fa-eraser" title="Cleanup Plugin Data" data-bind="click: function() { $root.cleanupPlugin($data.identifier) }"></a>
4031 </td>
4032 </tr>
4033 </tbody>
4034 </table>
4035 </div>
4036
4037 <button class="btn btn-danger btn-block" data-bind="click: $root.cleanupAll">Cleanup all</button>
4038 </div>
4039 <div data-bind="visible: orphans.paginatedItems().length == 0">
4040 Nothing to cleanup! There are no settings or data left over from plugins which are no longer installed.
4041 </div>
4042 </div>
4043</div>
4044
4045<div id="settings_plugin_pluginmanager_workingdialog" class="modal hide fade">
4046 <div class="modal-header">
4047 <h3 data-bind="text: workingTitle"></h3>
4048 </div>
4049 <div class="modal-body">
4050 <pre id="settings_plugin_pluginmanager_workingdialog_output" class="pre-scrollable pre-output" style="height: 170px" data-bind="foreach: loglines"><span data-bind="text: line, css: {stdout: stream == 'stdout', stderr: stream == 'stderr', call: stream == 'call', message: stream == 'message', error: stream == 'error'}"></span></pre>
4051 </div>
4052 <div class="modal-footer">
4053 <button class="btn" data-dismiss="modal" data-bind="enable: !$root.working()" aria-hidden="true">Close</button>
4054 </div>
4055</div>
4056
4057<div id="settings_plugin_pluginmanager_repositorydialog" class="modal hide fade">
4058 <div class="modal-header">
4059 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
4060 <h3>Install new Plugins...</h3>
4061 </div>
4062 <div class="modal-body">
4063
4064<div class="alert" data-bind="visible: !enableManagement()">
4065 Take note that all plugin management functionality is disabled while your printer is printing or paused.
4066</div>
4067
4068
4069<div class="alert" data-bind="visible: !pipAvailable()">
4070 The <code>pip</code> command could not be found or does not work correctly
4071 for this installation of OctoPrint - please consult the log file for details
4072 and if necessary configure it manually. No installation and uninstallation of plugin
4073 packages is possible while <code>pip</code> is unavailable.
4074</div>
4075
4076
4077<div class="alert" data-bind="visible: safeMode">
4078 Safe mode is currently active. All third party plugins are disabled and cannot be
4079 enabled. Installation of plugin packages is disabled.
4080</div>
4081
4082
4083<div class="alert" data-bind="visible: throttled">
4084 The system OctoPrint is running on is currently throttled. Due to that it's not possible to install new
4085 plugins in order to avoid possible issues caused by system instability.
4086</div>
4087
4088
4089<div class="alert" data-bind="visible: !online()">
4090 It looks like OctoPrint has currently no connection to the internet. Due to that it's not possible
4091 to install new plugins from the plugin repository or archive URLs.
4092</div>
4093
4094 <h4 style="position: relative">
4095 ... from the <a href="https://plugins.octoprint.org" target="_blank">Plugin Repository</a>
4096 <div class="dropdown pull-right">
4097 <a class="dropdown-toggle" data-toggle="dropdown" href="#">
4098 <span class="fa fa-wrench"></span>
4099 </a>
4100 <ul class="dropdown-menu pull-right">
4101 <li><a href="#" data-bind="click: function() { repositoryplugins.changeSorting('title'); }"><i class="fa fa-check" data-bind="style: {visibility: repositoryplugins.currentSorting() == 'title' ? 'visible' : 'hidden'}"></i> Sort by title (ascending)</a></li>
4102 <li><a href="#" data-bind="click: function() { repositoryplugins.changeSorting('published'); }"><i class="fa fa-check" data-bind="style: {visibility: repositoryplugins.currentSorting() == 'published' ? 'visible' : 'hidden'}"></i> Sort by publication date (descending)</a></li>
4103 <li class="divider"></li>
4104 <li><a href="#" data-bind="click: function() { repositoryplugins.toggleFilter('filter_installed'); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains(repositoryplugins.currentFilters(), 'filter_installed') ? 'visible' : 'hidden'}"></i> Only show uninstalled plugins</a></li>
4105 <li><a href="#" data-bind="click: function() { repositoryplugins.toggleFilter('filter_incompatible'); }"><i class="fa fa-check" data-bind="style: {visibility: _.contains(repositoryplugins.currentFilters(), 'filter_incompatible') ? 'visible' : 'hidden'}"></i> Only show compatible plugins</a></li>
4106 <li class="divider"></li>
4107 <li><a href="#" data-bind="click: function() { refreshRepository(); }"><i class="fa fa-refresh"></i> Refresh list from repository</a></li>
4108 </ul>
4109 </div>
4110 </h4>
4111
4112 <form class="form-search" data-bind="submit: performRepositorySearch">
4113 <input type="text" class="input-block search-query" data-bind="value: repositorySearchQuery, valueUpdate: 'input'" placeholder="Search...">
4114 </form>
4115
4116 <div data-bind="visible: repositoryAvailable() && repositoryplugins.paginatedItems().length > 0">
4117 <div id="settings_plugin_pluginmanager_repositorydialog_list" data-bind="foreach: repositoryplugins.paginatedItems">
4118 <div class="entry">
4119 <div class="row-fluid">
4120 <div class="span9">
4121 <div><span data-bind="text: title"></span></div>
4122 <div><small class="muted" data-bind="text: description"> </small></div>
4123 <div>
4124 <small data-bind="visible: page"><i class="fa fa-info"></i> <a data-bind="attr: {href: page}" target="_blank">Details</a></small>
4125 <small data-bind="visible: homepage"><i class="fa fa-home"></i> <a data-bind="attr: {href: homepage}" target="_blank">Homepage</a></small>
4126 <small data-bind="visible: license"><i class="fa fa-gavel"></i> <span data-bind="text: license"></span></small>
4127 <small data-bind="visible: author"><i class="fa fa-user"></i> <span data-bind="text: author"></span></small>
4128 <small> </small>
4129 </div>
4130 </div>
4131 <div class="span3">
4132 <button class="btn btn-primary btn-block" data-bind="enable: $root.enableRepoInstall($data), css: {disabled: !$root.enableRepoInstall($data)}, click: function() { if ($root.enableRepoInstall($data)) { $root.installFromRepository($data); } else { return false; } }"><i class="fa fa-add"></i> <span data-bind="text: $root.installButtonText($data)"></span></button>
4133 <div data-bind="visible: $data.disabled !== undefined" style="text-align: center"><small><a data-bind="attr: {href: page}" target="_blank">"Why?"</a></small></div>
4134 </div>
4135 </div>
4136 </div>
4137 </div>
4138 </div>
4139 <div id="settings_plugin_pluginmanager_repositorydialog_unavailable" data-bind="visible: !repositoryAvailable()">
4140 <div>
4141 <p>
4142 <strong>Sadly the repository is currently not available</strong>
4143 </p>
4144 <p>
4145 <small>Is your OctoPrint installation connected to the internet?</small>
4146 </p>
4147 </div>
4148 </div>
4149 <div id="settings_plugin_pluginmanager_repositorydialog_empty" data-bind="visible: repositoryAvailable() && repositoryplugins.paginatedItems().length === 0">
4150 <div>
4151 <p>
4152 <strong>It looks like there are no compatible plugins available</strong>
4153 </p>
4154 </div>
4155 </div>
4156
4157 <h4>... from URL</h4>
4158
4159 <form class="form-inline">
4160 <div class="control-group row-fluid" data-bind="css: {error: invalidUrl}">
4161 <div class="span9">
4162 <input type="text" class="input-block-level" data-bind="value: installUrl, valueUpdate: 'input'" placeholder="Enter URL..." >
4163 </div>
4164 <button class="btn btn-primary span3" data-bind="enable: enableUrlInstall, css: {disabled: !enableUrlInstall()}, click: function() { if (enableUrlInstall()) { $root.installPlugin(); } }">Install</button>
4165 </div>
4166 <span class="help-block" data-bind="visible: invalidUrl">This does not look like a valid URL. Expected http, https or any of the <a href="https://pip.pypa.io/en/stable/reference/pip_install/#vcs-support" target="_blank">supported VCS URLs</a>.</span>
4167 </form>
4168
4169 <h4>... from an uploaded archive</h4>
4170
4171 <form class="form-inline">
4172 <div class="control-group row-fluid" data-bind="css: {error: invalidArchive}">
4173 <div class="input-prepend span9">
4174 <span class="btn fileinput-button">
4175 <span>Browse...</span>
4176 <input id="settings_plugin_pluginmanager_repositorydialog_upload" type="file" name="file" accept=".zip,.tar.gz,.tgz,.tar" data-url="/plugin/pluginmanager/upload_archive">
4177 </span>
4178 <span class="add-on add-on-limited text-left" data-bind="text: uploadFilename, attr: {title: uploadFilename}"></span>
4179 </div>
4180 <button id="settings_plugin_pluginmanager_repositorydialog_upload_start" class="btn btn-primary span3" data-bind="enable: enableArchiveInstall, css: {disabled: !enableArchiveInstall()}, click: function(){}">Install</button>
4181 </div>
4182 <span class="help-block" data-bind="visible: invalidArchive">This does not look like a valid plugin archive. Valid plugin archives should be either zip files or tarballs and have the extension ".zip", ".tar.gz", ".tgz" or ".tar"</span>
4183 </form>
4184
4185 <div>
4186 <div><small><a href="#" class="muted" onclick="$(this).children().toggleClass('fa-caret-right fa-caret-down').parent().parent().parent().next().slideToggle('fast')"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
4187 <div class="hide">
4188 <form class="form-horizontal">
4189 <div class="control-group">
4190 <div class="controls">
4191 <label class="checkbox">
4192 <input type="checkbox" data-bind="checked: followDependencyLinks"> Use <code>--process-dependency-links</code> with <code>pip install</code>
4193 </label>
4194 </div>
4195 </div>
4196 </form>
4197 </div>
4198 </div>
4199 </div>
4200 <div class="modal-footer">
4201 <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
4202 </div>
4203</div>
4204
4205<div id="settings_plugin_pluginmanager_configurationdialog" class="modal hide fade">
4206 <div class="modal-header">
4207 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
4208 <h3>Plugin Configuration</h3>
4209 </div>
4210 <div class="modal-body">
4211 <form class="form-horizontal">
4212 <fieldset>
4213 <legend>Confirmations</legend>
4214
4215 <div class="control-group" title="Confirm before disabling a plugin">
4216 <div class="controls">
4217 <label class="checkbox">
4218 <input type="checkbox" data-bind="checked: config_confirmDisable"> Confirm before disabling a plugin
4219 </label>
4220 </div>
4221 </div>
4222 </fieldset>
4223
4224 <p>You should normally <strong>not</strong> have to change <strong>any</strong> of the following settings, they are purely provided for convenience here.</p>
4225
4226 <fieldset>
4227 <legend>Plugin repository configuration</legend>
4228
4229 <div class="control-group" title="URL of the Plugin Repository to use. You should normally not have to change this.">
4230 <label class="control-label">Repository URL</label>
4231 <div class="controls">
4232 <input type="text" class="input-block-level" data-bind="value: config_repositoryUrl">
4233 </div>
4234 </div>
4235 <div class="control-group" title="How long to cache repository data, in minutes. You should normally not have to change this.">
4236 <label class="control-label">Repository cache TTL</label>
4237 <div class="controls">
4238 <div class="input-append">
4239 <input type="number" class="input-mini" data-bind="value: config_repositoryTtl">
4240 <span class="add-on">min</span>
4241 </div>
4242 </div>
4243 </div>
4244 </fieldset>
4245
4246 <fieldset>
4247 <legend>Notices configuration</legend>
4248
4249 <div class="control-group" title="URL of the Notices source to use. You should normally not have to change this.">
4250 <label class="control-label">Notices URL</label>
4251 <div class="controls">
4252 <input type="text" class="input-block-level" data-bind="value: config_noticesUrl">
4253 </div>
4254 </div>
4255 <div class="control-group" title="How long to cache notices, in minutes. You should normally not have to change this.">
4256 <label class="control-label">Notices cache TTL</label>
4257 <div class="controls">
4258 <div class="input-append">
4259 <input type="number" class="input-mini" data-bind="value: config_noticesTtl">
4260 <span class="add-on">min</span>
4261 </div>
4262 </div>
4263 </div>
4264 </fieldset>
4265
4266 <fieldset>
4267 <legend>pip configuration</legend>
4268
4269 <div class="control-group" title="Additional arguments for the pip command. You should normally not have to change this.">
4270 <label class="control-label">Additional arguments</label>
4271 <div class="controls">
4272 <input type="text" class="input-block-level" data-bind="value: config_pipAdditionalArgs">
4273 </div>
4274 </div>
4275 <div class="control-group">
4276 <div class="controls">
4277 <label class="checkbox">
4278 <input type="checkbox" data-bind="checked: config_pipForceUser"> Force the use of the <code>--user</code> flag with <code>pip install</code>
4279 </label>
4280 </div>
4281 </div>
4282 </fieldset>
4283
4284 </form>
4285 </div>
4286 <div class="modal-footer">
4287 <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
4288 <button class="btn btn-primary" data-bind="click: savePluginSettings" aria-hidden="true">Save</button>
4289 </div>
4290</div>
4291
4292 </div>
4293 <!-- /ko -->
4294
4295
4296
4297
4298 <!-- ko allowBindings: false -->
4299 <div id="settings_plugin_softwareupdate"
4300 data-bind="allowBindings: true"
4301 class="tab-pane "
4302
4303 >
4304 <div class="alert" data-bind="visible: octoprintUnconfigured()">
4305 Please configure the <strong>checkout folder</strong> of OctoPrint, otherwise
4306 this plugin won't be able to update it. Click on the <i class="fa fa-wrench"></i> button
4307 to do this. Also refer to the <a href="https://github.com/foosel/OctoPrint/wiki/Plugin:-Software-Update" target="_blank">Documentation</a>.
4308</div>
4309<div class="alert" data-bind="visible: !octoprintUnconfigured() && octoprintUnreleased()">
4310 <p>
4311 <strong>You are running a non-release version of OctoPrint but are tracking OctoPrint
4312 releases.</strong>
4313 </p><p>
4314 You probably want OctoPrint to track the matching development version instead.
4315 If you have a local OctoPrint checkout folder switched to another branch,
4316 <strong>simply switching over to "Commit" tracking</strong> will already
4317 take care of that. Otherwise please take a look at the
4318 <a href="http://docs.octoprint.org/en/master/bundledplugins/softwareupdate.html" target="_blank">Documentation</a>.
4319 </p>
4320</div>
4321<div class="alert" data-bind="visible: !environmentSupported()">
4322 <p>
4323 <strong>This version of the Python environment is not supported for direct updates.</strong>
4324 </p>
4325 <p>
4326 To reduce the likelihood of running into update problems in outdated environments, the following minimal
4327 versions are required to use this updater to update OctoPrint or any installed plugins:
4328 </p>
4329
4330 <ul data-bind="foreach: environmentVersions">
4331 <li><span data-bind="text: name"></span>: <span data-bind="text: minimum"></span> (you have: <span data-bind="text: current"></span>)</li>
4332 </ul>
4333
4334 <p>
4335 Please take a look at <a href="https://faq.octoprint.org/unsupported-python-environment" target="_blank">this FAQ entry on how to proceed</a>.
4336 </p>
4337</div>
4338<div class="alert" data-bind="visible: throttled()">
4339 <p>
4340 <strong>OctoPrint is running on a throttled system, updates are disabled.</strong>
4341 </p>
4342 <p>
4343 To reduce the likelihood of running into update problems on throttled and hence potentially unstable systems
4344 as seen in the past, OctoPrint doesn't support updating under such conditions. Please fix the current issue
4345 before trying to update. Take a look at the displayed warning in the navigation bar to learn about what is
4346 wrong and to get hints on how to solve the problem.
4347 </p>
4348</div>
4349<div class="alert" data-bind="visible: printerState.isPrinting()">
4350 <p>
4351 <strong>OctoPrint is currently printing, updates are disabled.</strong>
4352 </p>
4353 <p>
4354 Running updates is not supported while printing in order to not risk any kind of disruption to the print job.
4355 Please let the print finish before trying to update.
4356 </p>
4357</div>
4358
4359<div class="pull-right">
4360 <button class="btn btn-small" data-bind="click: function() { $root.showPluginSettings(); }" title="Plugin Configuration"><i class="fa fa-wrench"></i></button>
4361</div>
4362
4363<h3>Current versions</h3>
4364
4365<div id="settings_plugin_softwareupdate_updatelist">
4366 <table class="table table-striped table-hover table-condensed table-hover">
4367 <tbody data-bind="foreach: versions.paginatedItems">
4368 <tr data-bind="attr: {title: displayName}">
4369 <td class="settings_plugin_softwareupdate_column_update">
4370 <span data-bind="invisible: !updateAvailable"><i class="fa fa-bell-o" title="Update available"></i></span>
4371 </td>
4372 <td class="settings_plugin_softwareupdate_column_information">
4373 <a href="javascript:void(0)" data-bind="click: function() { $root.update(false, [$data]) }, visible: $root.enableUpdate() && updateAvailable && updatePossible" class="btn btn-primary pull-right">Update</a>
4374 <strong data-bind="text: displayName"></strong>: <span data-bind="text: displayVersion"></span> <span data-bind="invisible: updatePossible"><i class="fa fa-exclamation-triangle" data-bind="css: {'fa-unlink': !online && information && information.needs_online, 'fa-exclamation-triangle': !(!online && information && information.needs_online)}, attr: {title: $root.iconTitleForEntry($data)}"></i></span><br>
4375 <small class="muted">
4376 <span class="line">Installed: <span data-bind="text: information.local.name"></span></span>
4377 <span class="line">Available: <span data-bind="text: information.remote.name"></span></span>
4378 <span class="line" data-bind="visible: releaseNotes">Release Notes: <a data-bind="attr: {href: releaseNotes}, text: releaseNotes" target="_blank" rel="noreferrer noopener"></a></span>
4379 <span class="line text-error" data-bind="visible: error, text: $root.errorTextForEntry($data)"></span>
4380 </small>
4381 </td>
4382 </tr>
4383 </tbody>
4384 </table>
4385</div>
4386
4387<button class="btn btn-primary btn-block" data-bind="click: function() { $root.update(); }, enable: enableUpdate, css: {disabled: !enableUpdate}"><i class="fa fa-spinner fa-spin" data-bind="visible: updateInProgress"></i> Update all</button>
4388<button class="btn btn-block" data-bind="click: function() { $root.performCheck(true, false, true); }, enable: !checking(), css: {disabled: checking()}"><i class="fa fa-spinner fa-spin" data-bind="visible: checking"></i> Check for update now</button>
4389
4390<div>
4391 <div><small><a href="#" class="muted" onclick="$(this).children().toggleClass('fa-caret-right fa-caret-down').parent().parent().parent().next().slideToggle('fast')"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
4392 <div class="hide">
4393 <small class="muted" style="display: block">Last cache refresh: <span data-bind="text: cacheTimestampText"></span></small>
4394 <button class="btn btn-block" data-bind="click: function() { $root.performCheck(true, true, true); }, enable: !checking(), css: {disabled: checking()}"><i class="fa fa-spinner fa-spin" data-bind="visible: checking"></i> Force check for update (overrides cache used for update checks)</button>
4395 <button class="btn btn-block btn-danger" data-bind="visible: CONFIG_DEBUG, click: function() { $root.update(true); }, enable: enableUpdate() && !checking(), css: {disabled: !enableUpdate() || checking()}"><i class="fa fa-spinner fa-spin" data-bind="visible: checking"></i> Force update now (even if no new versions are available)</button>
4396 </div>
4397</div>
4398
4399<div id="settings_plugin_softwareupdate_configurationdialog" class="modal hide fade">
4400 <div class="modal-header">
4401 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
4402 <h3>Plugin Configuration</h3>
4403 </div>
4404 <div class="modal-body">
4405 <form class="form-horizontal">
4406 <div class="control-group" data-bind="visible: config_availableCheckTypes().length > 1">
4407 <label class="control-label">OctoPrint version tracking</label>
4408 <div class="controls">
4409 <select data-bind="value: config_checkType, options: config_availableCheckTypes, optionsText: 'name', optionsValue: 'key'"></select>
4410 </div>
4411</div>
4412 <div class="control-group" data-bind="visible: config_checkType() === 'github_commit'">
4413 <label class="control-label">Tracked branch</label>
4414 <div class="controls">
4415 <input type="text" class="input-block-level" data-bind="value: config_trackedBranch" placeholder="master">
4416 </div>
4417</div>
4418 <div class="control-group" data-bind="visible: config_checkType() === 'git_commit', css: {error: error_checkoutFolder}">
4419 <label class="control-label">OctoPrint checkout folder</label>
4420 <div class="controls">
4421 <input type="text" class="input-block-level" data-bind="value: config_checkoutFolder">
4422 <span class="help-block" data-bind="visible: error_checkoutFolder">This needs to be set if you select commit based version tracking.</span>
4423 </div>
4424</div>
4425 <div class="control-group" data-bind="visible: config_availableReleaseChannels().length && config_checkType() === 'github_release'">
4426 <label class="control-label">OctoPrint Release Channel</label>
4427 <div class="controls">
4428 <select data-bind="value: config_releaseChannel, options: config_availableReleaseChannels, optionsText: 'name', optionsValue: 'key'"></select>
4429 <span class="help-inline">Make sure you have read <a href="https://faq.octoprint.org/using-release-channels" target="_blank" rel="noreferrer noopener">"How to use the release channels to help test release candidates"</a> before switching to a release channel other than "Stable"</span>
4430 </div>
4431</div>
4432 <div class="control-group" data-bind="visible: config_checkType() === 'github_release' || config_checkType() === 'github_commit'">
4433 <label class="control-label">OctoPrint <code>pip</code> target</label>
4434 <div class="controls">
4435 <input type="text" class="input-block-level" data-bind="value: config_pipTarget">
4436 <span class="help-block">You should normally not have to change this.</span>
4437 </div>
4438</div>
4439 <div class="control-group">
4440 <div class="controls">
4441 <label class="checkbox">
4442 <input type="checkbox" data-bind="checked: config_pipEnableCheck"> Enable <code>pip</code> update checks
4443 <span class="help-block">If you check this, OctoPrint will also notify you of updates of the <code>pip</code> tool used by OctoPrint to install plugins and updates and allow you to update it through OctoPrint. <code>pip</code> is outside of the control of the OctoPrint maintainer, so enable at your own risk.</span>
4444 </label>
4445 </div>
4446</div>
4447 <div class="control-group">
4448 <label class="control-label">Version cache TTL</label>
4449 <div class="controls">
4450 <div class="input-append">
4451 <input type="number" class="input-mini" data-bind="value: config_cacheTtl">
4452 <span class="add-on">min</span>
4453 </div>
4454 </div>
4455 </div>
4456 <div class="control-group">
4457 <div class="controls">
4458 <label class="checkbox">
4459 <input type="checkbox" data-bind="checked: config_notifyUsers"> Show update notifications to users
4460 <span class="help-block">If you uncheck this, only logged in admins will see update notifications. Update notifications shown to users do not include the "Update now" button.</span>
4461 </label>
4462 </div>
4463 </div>
4464 </form>
4465 </div>
4466 <div class="modal-footer">
4467 <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
4468 <button class="btn btn-primary" data-bind="enable: enable_configSave, css: {disabled: !enable_configSave()}, click: savePluginSettings" aria-hidden="true">Save</button>
4469 </div>
4470</div>
4471
4472<div id="settings_plugin_softwareupdate_workingdialog" class="modal hide fade">
4473 <div class="modal-header">
4474 <h3 data-bind="text: workingTitle"></h3>
4475 </div>
4476 <div class="modal-body">
4477 <pre id="settings_plugin_softwareupdate_workingdialog_output" class="pre-scrollable pre-output" style="height: 170px; display: none" data-bind="visible: loginState.isAdmin, foreach: loglines"><span data-bind="text: line, css: {stdout: stream == 'stdout', stderr: stream == 'stderr', call: stream == 'call', message: stream == 'message'}"></span></pre>
4478 <p style="display: none" data-bind="visible: !loginState.isAdmin() && $root.working()"><i class="fa fa-spinner fa-spin"></i> Update in progress, please wait.</p>
4479 <p style="display: none" data-bind="visible: !loginState.isAdmin() && !$root.working()">Update done, please close this window.</p>
4480 </div>
4481 <div class="modal-footer">
4482 <button class="btn" data-dismiss="modal" data-bind="enable: !$root.working()" aria-hidden="true">Close</button>
4483 </div>
4484</div>
4485
4486 </div>
4487 <!-- /ko -->
4488
4489
4490
4491
4492 <!-- ko allowBindings: false -->
4493 <div id="settings_plugin_announcements"
4494 data-bind="allowBindings: true"
4495 class="tab-pane "
4496
4497 >
4498 <h3>Configured Channels</h3>
4499
4500<table class="table table-striped table-hover table-condensed table-hover">
4501 <thead>
4502 <tr>
4503 <th class="settings_plugin_announcements_channels_name">Name</th>
4504 <th class="settings_plugin_announcements_channels_actions">Actions</th>
4505 </tr>
4506 </thead>
4507 <tbody data-bind="foreach: channels.paginatedItems">
4508 <tr>
4509 <td class="settings_plugin_announcements_channels_name">
4510 <div data-bind="css: {muted: !enabled}"><strong data-bind="text: channel"></strong></div>
4511 <div data-bind="text: description, css: {muted: !enabled}"></div>
4512 <div><small class="muted" data-bind="text: url"> </small></div>
4513 </td>
4514 <td class="settings_plugin_announcements_channels_actions">
4515 <a href="javascript:void(0)" data-bind="css: $root.toggleButtonCss($data), attr: {title: $root.toggleButtonTitle($data)}, enable: $root.enableToggle($data), click: function() { $root.toggleChannel($data.key) }"></a>
4516 </td>
4517 </tr>
4518 </tbody>
4519</table>
4520<div class="pagination pagination-mini pagination-centered">
4521 <ul>
4522 <li data-bind="css: {disabled: channels.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: channels.prevPage">«</a></li>
4523 </ul>
4524 <ul data-bind="foreach: channels.pages">
4525 <li data-bind="css: { active: $data.number === $root.channels.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.channels.changePage($data.number); }"></a></li>
4526 </ul>
4527 <ul>
4528 <li data-bind="css: {disabled: channels.currentPage() === channels.lastPage()}"><a href="javascript:void(0)" data-bind="click: channels.nextPage">»</a></li>
4529 </ul>
4530</div>
4531
4532<button class="btn btn-block" data-bind="click: $root.refreshAnnouncements"><i class="fa fa-refresh"></i> Refresh Announcements</button>
4533 </div>
4534 <!-- /ko -->
4535
4536
4537
4538
4539 <!-- ko allowBindings: false -->
4540 <div id="settings_plugin_backup"
4541 data-bind="allowBindings: true"
4542 class="tab-pane "
4543
4544 >
4545 <div class="alert" data-bind="visible: unknownPlugins().length > 0">
4546
4547 Some plugins during the last restore could not be identified and hence not automatically installed.
4548 Please install them manually, they are listed below including their stated homepages:
4549
4550 <ul data-bind="foreach: unknownPlugins">
4551 <li><span data-bind="text: name"></span>: <a data-bind="text: url, attr: {href: url}" target="_blank" rel="noreferrer noopener"></a></li>
4552 </ul>
4553 <small><a href="javascript:void(0)" data-bind="click: deleteUnknownPluginRecord">Delete record of unknown plugins</a></small>
4554</div>
4555
4556
4557<h3>Existing backups</h3>
4558
4559<div data-bind="visible: backups.allSize() <= 0">
4560 <p>There are no backups. Maybe create one below?</p>
4561</div>
4562<div data-bind="visible: backups.allSize() > 0">
4563 <p>These are the backups of your settings and files that already exist on this OctoPrint instance. You may delete, download or restore them.</p>
4564
4565 <div class="pull-left">
4566 <div class="btn-group">
4567 <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-square-o"></i> <span class="caret"></span></button>
4568 <ul class="dropdown-menu">
4569 <li><a href="javascript:void(0)" data-bind="click: markFilesOnPage">Select all on this page</a></li>
4570 <li><a href="javascript:void(0)" data-bind="click: markAllFiles">Select all</a></li>
4571 <li class="divider"></li>
4572 <li><a href="javascript:void(0)" data-bind="click: clearMarkedFiles">Clear selection</a></li>
4573 </ul>
4574 </div>
4575 <button class="btn btn-small" data-bind="click: removeMarkedFiles, enable: markedForBackupDeletion().length > 0">Delete selected</button>
4576 </div>
4577 <table class="table table-condensed table-hover" id="settings_plugin_backup_backup_table">
4578 <thead>
4579 <tr>
4580 <th class="settings_plugin_backup_checkbox"></th>
4581 <th class="settings_plugin_backup_name">Name</th>
4582 <th class="settings_plugin_backup_date">Date</th>
4583 <th class="settings_plugin_backup_size">Size</th>
4584 <th class="settings_plugin_backup_actions">Action</th>
4585 </tr>
4586 </thead>
4587 <tbody data-bind="foreach: backups.paginatedItems">
4588 <tr>
4589 <td class="settings_plugin_backup_checkbox"><input type="checkbox" data-bind="value: name, checked: $root.markedForBackupDeletion"></td>
4590 <td class="settings_plugin_backup_name" data-bind="text: name"></td>
4591 <td class="settings_plugin_backup_date" data-bind="text: formatDate(date)"></td>
4592 <td class="settings_plugin_backup_size" data-bind="text: formatSize(size)"></td>
4593 <td class="settings_plugin_backup_actions"><a href="javascript:void(0)" title="Delete" class="fa fa-trash-o" data-bind="click: function() { $parent.removeBackup($data.name) }, css: {disabled: $root.backupInProgress() || $root.restoreInProgress()"></a> | <a href="javascript:void(0)" title="Download" class="fa fa-download" data-bind="attr: {href: url}"></a><span data-bind="visible: $parent.restoreSupported()"> | <a href="javascript:void(0)" title="Restore" data-bind="click: function() { $parent.restoreBackup($data.name) }, css: {disabled: $root.backupInProgress() || $root.restoreInProgress()"><i class="fa fa-refresh"></i></a></span></td>
4594 </tr>
4595 </tbody>
4596 </table>
4597 <div class="pagination pagination-mini pagination-centered">
4598 <ul>
4599 <li data-bind="css: {disabled: backups.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: backups.prevPage">«</a></li>
4600 </ul>
4601 <ul data-bind="foreach: backups.pages">
4602 <li data-bind="css: { active: $data.number === $root.backups.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.backups.changePage($data.number); }"></a></li>
4603 </ul>
4604 <ul>
4605 <li data-bind="css: {disabled: backups.currentPage() === backups.lastPage()}"><a href="javascript:void(0)" data-bind="click: backups.nextPage">»</a></li>
4606 </ul>
4607 </div>
4608</div>
4609
4610<h3>Create backup</h3>
4611
4612<p>Create a new backup of the current state.</p>
4613
4614<form class="form-horizontal">
4615 <div class="control-group">
4616 <div class="controls">
4617 <label class="checkbox">
4618 <input type="checkbox" data-bind="value: 'uploads', checked: excludeFromBackup"> Exclude uploaded files & metadata from backup
4619 </label>
4620 </div>
4621 </div>
4622
4623 <div class="control-group">
4624 <div class="controls">
4625 <label class="checkbox">
4626 <input type="checkbox" data-bind="value: 'timelapse', checked: excludeFromBackup"> Exclude timelapses from backup
4627 </label>
4628 </div>
4629 </div>
4630
4631 <div class="control-group">
4632 <div class="controls">
4633 <button class="btn btn-primary" data-bind="enable: !backupInProgress() && !restoreInProgress(), click: createBackup"><i class="fa fa-spinner fa-spin" data-bind="visible: backupInProgress"></i> Create backup now</button>
4634 </div>
4635 </div>
4636</form>
4637
4638<div data-bind="visible: restoreSupported()">
4639 <h3>Restore from uploaded backup</h3>
4640
4641 <p>Restore settings & files from an uploaded backup archive.</p>
4642
4643 <form class="form-horizontal">
4644 <div class="control-group">
4645 <label class="control-label">Backup file</label>
4646 <div class="controls">
4647 <div class="input-prepend">
4648 <span class="btn fileinput-button">
4649 <span>Browse...</span>
4650 <input id="settings-backup-upload" type="file" name="file" data-url="/plugin/backup/restore" accept=".zip">
4651 </span>
4652 <span class="add-on" data-bind="text: backupUploadName"></span>
4653 </div>
4654 </div>
4655 </div>
4656
4657 <div class="control-group">
4658 <div class="controls">
4659 <button class="btn btn-primary" data-bind="enable: !backupInProgress() && !restoreInProgress(), click: performRestoreFromUpload"><i class="fa fa-spinner fa-spin" data-bind="visible: restoreInProgress"></i> Upload & restore</button>
4660 </div>
4661 </div>
4662 </form>
4663</div>
4664
4665<div data-bind="visible: !restoreSupported()">
4666 Please note that the operating system that this OctoPrint server is running on does not support automatically restoring backups. You will have to <a href="https://faq.octoprint.org/manual-restore" target="_blank" rel="noopener noreferrer">restore your backups manually for now</a>.
4667</div>
4668
4669<div id="settings_plugin_backup_restoredialog" class="modal hide fade">
4670 <div class="modal-header">
4671 <h3>Restoring from backup...</h3>
4672 </div>
4673 <div class="modal-body">
4674 <pre id="settings_plugin_backup_restoredialog_output" class="pre-scrollable pre-output" style="height: 170px" data-bind="foreach: loglines"><span data-bind="text: line, css: {stdout: stream == 'stdout', stderr: stream == 'stderr', call: stream == 'call', message: stream == 'message', error: stream == 'error'}"></span></pre>
4675 </div>
4676 <div class="modal-footer">
4677 <button class="btn" data-dismiss="modal" data-bind="enable: !$root.restoreInProgress()" aria-hidden="true">Close</button>
4678 </div>
4679</div>
4680 </div>
4681 <!-- /ko -->
4682
4683
4684
4685
4686
4687 <div id="settings_plugin_tracking"
4688
4689 class="tab-pane "
4690
4691 >
4692 <h3>Anonymous Usage Tracking</h3>
4693
4694
4695<p>
4696 Anonymous usage tracking provides valuable insights into how many instances running what versions of OctoPrint are out there,
4697 whether they are successfully completing print jobs and various other metrics.
4698</p>
4699<p>
4700 By enabling it you help to identify problems with new releases and release candidates early on, and to better
4701 tailor OctoPrint's future development to actual use.
4702</p>
4703
4704
4705<form class="form-horizontal">
4706 <div class="control-group">
4707 <div class="controls">
4708 <label class="checkbox">
4709 <input type="checkbox" data-bind="checked: settings.plugins.tracking.enabled"> Enable anonymous usage tracking
4710 </label>
4711 </div>
4712 </div>
4713 <div class="control-group">
4714 <label class="control-label" title="Random unique instance ID">Instance ID</label>
4715 <div class="controls">
4716 <span style="padding-top: 5px; margin-bottom: 5px; display: inline-block" data-bind="text: settings.plugins.tracking.unique_id() || 'N/A'"></span>
4717 </div>
4718 </div>
4719 <div class="control-group">
4720 <label class="control-label" title="Events to track. The ping is mandatory.">Tracked events</label>
4721 <div class="controls">
4722 <label class="checkbox">
4723 <input type="checkbox" checked="checked" disabled="disabled"> Regular ping every 15min (incl. uptime)
4724 </label>
4725 <label class="checkbox">
4726 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.pong"> Regular pong every 24h (incl. plugin list)
4727 </label>
4728 <label class="checkbox">
4729 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.startup"> Server startup & shutdown
4730 </label>
4731 <label class="checkbox">
4732 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.printer"> Connected to printer
4733 </label>
4734 <label class="checkbox">
4735 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.printer_safety_check"> Printer Safety Check warnings
4736 </label>
4737 <label class="checkbox">
4738 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.printjob"> Print started/cancelled/finished
4739 </label>
4740 <label class="checkbox">
4741 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.commerror"> Errors in the communication with the printer and/or reported by the firmware
4742 </label>
4743 <label class="checkbox">
4744 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.plugin"> Plugin installed/uninstalled/enabled/disabled
4745 </label>
4746 <label class="checkbox">
4747 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.update"> OctoPrint or a plugin updated successfully or unsuccessfully
4748 </label>
4749 <label class="checkbox">
4750 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.throttled"> System got throttled/unthrottled (currently only detected on RPis)
4751 </label>
4752 <label class="checkbox">
4753 <input type="checkbox" data-bind="checked: settings.plugins.tracking.events.slicing"> Onboard slicing actions
4754 </label>
4755 </div>
4756 </div>
4757</form>
4758
4759<p>
4760 For details on what gets tracked, please refer to <a href="https://tracking.octoprint.org" target="_blank" rel="noopener noreferrer">tracking.octoprint.org</a>
4761 and also the <a href="https://tracking.octoprint.org/privacy" target="_blank" rel="noopener noreferrer">Privacy Policy at tracking.octoprint.org</a>.
4762</p>
4763 </div>
4764
4765
4766
4767
4768
4769
4770 <div id="settings_plugin_errortracking"
4771
4772 class="tab-pane "
4773
4774 >
4775 <h3>Error Tracking</h3>
4776
4777
4778<p>
4779 Error tracking will cause any logged exceptions in the server and the browser interface to be sent
4780 to OctoPrint's <a href="https://sentry.io/" target="_blank" rel="noopener noreferer">Sentry instance</a>.
4781</p>
4782<p>
4783 By enabling it you help to gather detailed information on the cause of bugs or other issues. This is especially valuable
4784 on release candidates, which is why this plugin will also prompt you to enable error tracking if it detects that
4785 you are subscribed to an RC release channel.
4786</p>
4787<p>
4788 Please enable this if you are running a release candidate, or are prompted to do so while debugging an issue that you reported.
4789</p>
4790
4791
4792<form class="form-horizontal">
4793 <div class="control-group">
4794 <div class="controls">
4795 <label class="checkbox">
4796 <input type="checkbox" data-bind="checked: settings.plugins.errortracking.enabled"> Enable error tracking
4797 </label>
4798 <span class="help-block">Please reload the page after enabling/disabling & saving</span>
4799 </div>
4800 </div>
4801 <div class="control-group">
4802 <label class="control-label" title="Random unique instance ID">Instance ID</label>
4803 <div class="controls">
4804 <span style="padding-top: 5px; margin-bottom: 5px; display: inline-block" data-bind="text: settings.plugins.errortracking.unique_id() || 'N/A'"></span>
4805 </div>
4806 </div>
4807</form>
4808
4809
4810<p>
4811 The Error Tracking plugin is using a Sentry instance kindly provided by
4812 <a href="https://sentry.io/" target="_blank" rel="noopener noreferer">sentry.io</a>. For information on their service
4813 please refer to their <a href="https://sentry.io/security/" target="_blank" rel="noopener noreferer">Security & Compliance documentation</a>
4814 and their <a href="https://sentry.io/privacy/" target="_blank" rel="noopener noreferer">Privacy Policy</a>.
4815</p>
4816
4817 </div>
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827 <div id="settings_plugin_action_command_prompt"
4828
4829 class="tab-pane "
4830
4831 >
4832 <h3>Action Command Prompt Settings</h3>
4833
4834<form class="form-horizontal">
4835 <div class="control-group">
4836 <label class="control-label">Enable support</label>
4837 <div class="controls">
4838 <label class="radio">
4839 <input type="radio" name="pluginActionCommandPromptEnableGroup" value="detected" data-bind="checked: settings.plugins.action_command_prompt.enable"> If detected as supported by the firmware (<code>PROMPT_SUPPORT</code> capability)
4840 </label>
4841 <label class="radio">
4842 <input type="radio" name="pluginActionCommandPromptEnableGroup" value="always" data-bind="checked: settings.plugins.action_command_prompt.enable"> Always
4843 </label>
4844 <label class="radio">
4845 <input type="radio" name="pluginActionCommandPromptEnableGroup" value="never" data-bind="checked: settings.plugins.action_command_prompt.enable"> Never
4846 </label>
4847 </div>
4848 </div>
4849 <div class="advanced_options">
4850 <div><small><a href="#" class="muted" data-bind="toggleContent: { class: 'fa-caret-right fa-caret-down', parent: '.advanced_options', container: '.hide' }"><i class="fa fa-caret-right"></i> Advanced options</a></small></div>
4851 <div class="hide">
4852 <div class="control-group">
4853 <label class="control-label">Dialog command</label>
4854 <div class="controls">
4855 <input type="text" class="input-block-level" data-bind="value: settings.plugins.action_command_prompt.command">
4856 <div class="help-block">Use this to define the dialog command. Default is <code>M876</code>. You normally should not have to change this.</div>
4857 </div>
4858 </div>
4859 <div class="control-group">
4860 <div class="controls">
4861 <label class="checkbox">
4862 <input type="checkbox" data-bind="checked: settings.plugins.action_command_prompt.enable_emergency_sending"> Enable force sending of the configured command to bypass blocking firmware routines if detected as supported. You normally should not have to change this.
4863 </label>
4864 </div>
4865 </div>
4866 <div class="control-group">
4867 <div class="controls">
4868 <label class="checkbox">
4869 <input type="checkbox" data-bind="checked: settings.plugins.action_command_prompt.enable_signal_support"> Enable signaling to the firmware that we support <code>prompt_*</code> actions if detected as supported. You normally should not have to change this.
4870 </label>
4871 </div>
4872 </div>
4873 </div>
4874 </div>
4875</form>
4876 </div>
4877
4878
4879
4880 </div>
4881 </div>
4882 </div>
4883 </div>
4884 <div class="modal-footer">
4885 <button class="btn aboutlink" data-bind="click: about.show"><i class="fa fa-info-circle"></i> About OctoPrint</button>
4886 <button class="btn" data-bind="click: function() { cancelData() }" aria-hidden="true">Close</button>
4887 <button class="btn btn-primary" data-bind="click: function() { saveData(undefined, $root.hide) }, enable: !exchanging(), css: {disabled: exchanging()}"><i class="fa fa-spinner fa-spin" data-bind="visible: sending"></i> Save</button>
4888 </div>
4889</div>
4890
4891<div id="settings_dialog_update_detected" class="modal hide fade" data-keyboard="false">
4892 <div class="modal-header">
4893 <h3>Settings update detected</h3>
4894 </div>
4895 <div class="modal-body">
4896 <p>
4897 The settings have been updated on the server. You may reload all settings,
4898 overwriting any changes you might have done locally, or alternatively
4899 only reload those settings you haven't changed locally.
4900 </p>
4901 <p>
4902 How do you want to proceed?
4903 </p>
4904 </div>
4905 <div class="modal-footer">
4906 <div class="row-fluid">
4907 <a href="#" class="btn btn-danger span6 reload_all">Reload all</a>
4908 <a href="#" class="btn btn-primary span6 reload_nonconflicts">Reload only non-conflicting changes</a>
4909 </div>
4910 </div>
4911</div>
4912 <div id="slicing_configuration_dialog" class="modal hide fade">
4913 <div class="modal-header">
4914 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
4915 <h3 data-bind="text: title"></h3>
4916 </div>
4917 <div class="modal-body">
4918 <div data-bind="visible: !enableSlicingDialog()">
4919 <p>Slicing is currently disabled since no slicer has been configured yet. Please configure a slicer under "Settings".</p>
4920 </div>
4921 <div data-bind="visible: enableSlicingDialog()">
4922 <p>Please configure which slicer and which slicing profile to use and name the GCode file to slice to below, or click "Cancel" if you do not wish to slice the file now.</p>
4923 <form class="form-horizontal">
4924 <div class="control-group">
4925 <label class="control-label">Slicer</label>
4926 <div class="controls">
4927 <select data-bind="options: matchingSlicers, optionsText: 'name', optionsValue: 'key', optionsCaption: 'Select a slicer...', value: slicer, valueAllowUnset: true"></select>
4928 </div>
4929 </div>
4930 <div class="control-group">
4931 <label class="control-label">Runs locally</label>
4932 <div class="controls">
4933 <strong data-bind="text: slicerSameDevice() ? gettext('Yes') : gettext('No')"></strong>
4934 <span class="help-block"><small>For performance reasons locally run slicers are disabled while printing</small></span>
4935 </div>
4936 </div>
4937 <div class="control-group">
4938 <label class="control-label">Slicing Profile</label>
4939 <div class="controls">
4940 <select data-bind="options: profiles, optionsText: 'name', optionsValue: 'key', optionsCaption: 'Select a slicing profile...', value: profile, valueAllowUnset: true"></select>
4941 </div>
4942 </div>
4943 <div class="control-group">
4944 <label class="control-label">Printer Profile</label>
4945 <div class="controls">
4946 <select data-bind="options: printerProfiles.profiles.items, optionsText: 'name', optionsValue: 'id', value: printerProfile, optionsCaption: 'Select a printer profile...'"></select>
4947 </div>
4948 </div>
4949 <div class="control-group">
4950 <label class="control-label">Output Filename</label>
4951 <div class="controls">
4952 <div class="input-append">
4953 <input type="text" data-bind="value: destinationFilename">
4954 <span class="add-on" data-bind="text: '.' + destinationExtension()"></span>
4955 </div>
4956 </div>
4957 </div>
4958 <div class="control-group">
4959 <label class="control-label">After slicing...</label>
4960 <div class="controls">
4961 <select data-bind="options: afterSlicingOptions, optionsText: 'text', optionsValue: 'value', value: afterSlicing"></select>
4962 </div>
4963 </div>
4964 </form>
4965 </div>
4966 </div>
4967 <div class="modal-footer">
4968 <a href="#" class="btn" data-dismiss="modal" aria-hidden="true">Cancel</a>
4969 <a href="#" class="btn btn-primary" data-bind="click: function() { if ($root.enableSliceButton()) { $root.slice() } }, enabled: enableSliceButton, css: {disabled: !$root.enableSliceButton()}, attr: {title: $root.sliceButtonTooltip}">Slice</a>
4970 </div>
4971</div>
4972 <div id="usersettings_dialog" class="modal hide fade">
4973 <div class="modal-header">
4974 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
4975 <h3>User Settings</h3>
4976 </div>
4977 <div class="modal-body">
4978 <ul class="nav nav-pills">
4979
4980
4981
4982
4983
4984 <li id="usersettings_access_link"
4985
4986 class="active "
4987
4988 >
4989 <a href="#usersettings_access" data-toggle="tab">Access</a>
4990 </li>
4991
4992
4993
4994
4995
4996
4997 <li id="usersettings_interface_link"
4998
4999 class=" "
5000
5001 >
5002 <a href="#usersettings_interface" data-toggle="tab">Interface</a>
5003 </li>
5004
5005
5006
5007
5008
5009 <!-- ko allowBindings: false -->
5010 <li id="usersettings_plugin_appkeys_link"
5011 data-bind="allowBindings: true"
5012 class=" "
5013
5014 >
5015 <a href="#usersettings_plugin_appkeys" data-toggle="tab">Application Keys</a>
5016 </li>
5017 <!-- /ko -->
5018
5019
5020 </ul>
5021
5022 <div class="tab-content">
5023
5024
5025
5026
5027
5028 <div id="usersettings_access"
5029
5030 class="tab-pane active "
5031
5032 >
5033 <form class="form-horizontal">
5034 <fieldset>
5035 <legend>Password</legend>
5036 <p>
5037 If you do not wish to change your password, just leave the following fields empty.
5038 </p>
5039 <div class="control-group">
5040 <label class="control-label" for="userSettings-access_password">New Password</label>
5041 <div class="controls">
5042 <input type="password" class="input-block-level" id="userSettings-access_password" data-bind="value: access_password" required>
5043 </div>
5044 </div>
5045 <div class="control-group" data-bind="css: {error: passwordMismatch()}">
5046 <label class="control-label" for="userSettings-access_repeatedPassword">Repeat Password</label>
5047 <div class="controls">
5048 <input type="password" class="input-block-level" id="userSettings-access_repeatedPassword" data-bind="value: access_repeatedPassword, valueUpdate: 'afterkeydown'" required>
5049 <span class="help-inline" data-bind="visible: passwordMismatch()">Passwords do not match</span>
5050 </div>
5051 </div>
5052 </fieldset>
5053 <fieldset>
5054 <legend>API Key</legend>
5055 <div class="control-group">
5056 <label class="control-label" for="userSettings-access_apikey">Current API Key</label>
5057 <div class="controls">
5058 <div class="input-append input-block-level">
5059 <input type="text" readonly="readonly" id="userSettings-access_apikey" data-bind="value: access_apikey, attr: {placeholder: 'N/A'}">
5060 <a class="btn add-on" title="Copy API Key to clipboard" data-bind="click: copyApikey, css: {'disabled': !access_apikey()}"><i class="fa fa-copy"></i></a>
5061 <a class="btn add-on" title="Generate new API Key" data-bind="click: generateApikey"><i class="fa fa-refresh"></i></a>
5062 <a class="btn btn-danger add-on" title="Delete API Key" data-bind="click: deleteApikey, css: {'disabled': !access_apikey()}"><i class="fa fa-trash-o"></i></a>
5063 </div>
5064 <span class="help-block">Please note that changes to the API key are applied immediately, without having to "Confirm" first.</span>
5065 </div>
5066 </div>
5067 <div class="control-group" data-bind="visible: access_apikey">
5068 <label class="control-label">QR Code</label>
5069 <div class="controls">
5070 <div data-bind="qrcode: {text: access_apikey, size: 150}"></div>
5071 </div>
5072 </div>
5073 </fieldset>
5074</form>
5075 </div>
5076
5077
5078
5079
5080
5081
5082 <div id="usersettings_interface"
5083
5084 class="tab-pane "
5085
5086 >
5087 <form class="form-horizontal">
5088 <fieldset>
5089 <legend>Language</legend>
5090 <div class="control-group">
5091 <div class="controls">
5092 <select data-bind="options: locales,
5093 optionsText: function(item) { return item.display + ((item.language != undefined && item.english != undefined) ? ' [' + item.language + ', ' + item.english + ']' : '') },
5094 optionsValue: 'language',
5095 value: interface_language">
5096 </select>
5097 <span class="help-inline">Changes to the interface language will only become active after a reload of the page.</span>
5098 </div>
5099 </div>
5100 </fieldset>
5101</form>
5102 </div>
5103
5104
5105
5106
5107
5108 <!-- ko allowBindings: false -->
5109 <div id="usersettings_plugin_appkeys"
5110 data-bind="allowBindings: true"
5111 class="tab-pane "
5112
5113 >
5114 <legend>Registered application keys</legend>
5115
5116<div data-bind="visible: keys.allSize() <= 0">
5117 <p>There are no application keys registered yet.</p>
5118</div>
5119<div data-bind="visible: keys.allSize() > 0">
5120 <table class="table table-condensed table-hover" id="settings_plugin_appkeys_userkeys_table">
5121 <thead>
5122 <tr>
5123 <th class="settings_plugin_appkeys_app">Application identifier</th>
5124 <th class="settings_plugin_appkeys_actions">Action</th>
5125 </tr>
5126 </thead>
5127 <tbody data-bind="foreach: keys.paginatedItems">
5128 <tr>
5129 <td class="settings_plugin_appkeys_app"><span data-bind="text: app_id"></span><br /><small class="muted">API Key: <span data-bind="text: api_key"></span> <a href="javascript:void(0)" title="Copy API Key to clipboard" data-bind="click: function() { copyToClipboard(api_key) }"><i class="fa fa-copy"></i></a></small></td>
5130 <td class="settings_plugin_appkeys_actions"><a href="javascript:void(0)" title="Revoke" class="fa fa-trash-o" data-bind="click: function() { $parent.revokeKey($data.api_key) }"></a></td>
5131 </tr>
5132 </tbody>
5133 </table>
5134 <div class="pagination pagination-mini pagination-centered">
5135 <ul>
5136 <li data-bind="css: {disabled: keys.currentPage() === 0}"><a href="javascript:void(0)" data-bind="click: keys.prevPage">«</a></li>
5137 </ul>
5138 <ul data-bind="foreach: keys.pages">
5139 <li data-bind="css: { active: $data.number === $root.keys.currentPage(), disabled: $data.number === -1 }"><a href="javascript:void(0)" data-bind="text: $data.text, click: function() { $root.keys.changePage($data.number); }"></a></li>
5140 </ul>
5141 <ul>
5142 <li data-bind="css: {disabled: keys.currentPage() === keys.lastPage()}"><a href="javascript:void(0)" data-bind="click: keys.nextPage">»</a></li>
5143 </ul>
5144 </div>
5145</div>
5146
5147<legend>Manually generate an application key</legend>
5148
5149<form class="form-horizontal">
5150 <div class="control-group">
5151 <label class="control-label">Application identifier</label>
5152 <div class="controls">
5153 <input type="text" data-bind="value: editorApp">
5154 </div>
5155 </div>
5156
5157 <div class="control-group">
5158 <div class="controls">
5159 <button class="btn btn-primary" data-bind="click: generateKey">Generate</button>
5160 </div>
5161 </div>
5162</form>
5163 </div>
5164 <!-- /ko -->
5165
5166
5167 </div>
5168 </div>
5169 <div class="modal-footer">
5170 <button class="btn" data-dismiss="modal" aria-hidden="true">Abort</button>
5171 <button class="btn btn-primary" data-bind="click: function() { save(); }, enable: saveEnabled()">Confirm</button>
5172 </div>
5173</div>
5174 <div id="wizard_dialog" class="modal hide fade large" data-backdrop="static" data-keyboard="false">
5175 <div class="modal-header">
5176 <h3><i class="fa fa-magic"></i> Setup Wizard</h3>
5177 </div>
5178 <div class="modal-body">
5179 <div class="full-sized-box">
5180 <div class="tabbable row-fluid">
5181 <div class="span3 scrollable" id="wizard_dialog_menu">
5182 <ul class="nav nav-list" id="wizardTabs">
5183
5184
5185 </ul>
5186 </div>
5187 <div class="tab-content span9 scrollable" id="wizard_dialog_content">
5188
5189
5190 </div>
5191 </div>
5192 </div>
5193 </div>
5194 <div class="modal-footer">
5195 <div class="pull-right">
5196 <button class="btn btn-primary button-next" name="next">Next</button>
5197 <button class="btn btn-primary button-finish" style="display: none" name="finish">Finish</button>
5198 </div>
5199 <div class="pull-left">
5200 <button class="btn button-previous" name="previous">Previous</button>
5201 </div>
5202 <div class="text-center" style="line-height: 20px; padding: 4px 12px;">
5203 Unless otherwise noted, you may just skip any wizard page by clicking "Next" or "Finish".
5204 </div>
5205 </div>
5206</div>
5207 <div id="about_dialog" class="modal hide fade large" tabindex="-1" role="dialog" aria-labelledby="about_dialog_label" aria-hidden="true">
5208 <div class="modal-header">
5209 <button type="button" class="close" data-dismiss="modal">×</button>
5210 <h3 id="about_dialog_label">About OctoPrint</h3>
5211 </div>
5212 <div class="modal-body">
5213 <div class="full-sized-box">
5214 <div class="tabbable row-fluid">
5215 <div class="span3 scrollable" id="about_dialog_menu">
5216 <ul class="nav nav-list" id="about_dialog_tabs">
5217
5218
5219
5220
5221
5222 <li id="about_about_link"
5223
5224 class="active "
5225
5226 >
5227 <a href="#about_about" data-toggle="tab">About OctoPrint</a>
5228 </li>
5229
5230
5231
5232
5233
5234
5235 <li id="about_sponsors_link"
5236
5237 class=" "
5238
5239 >
5240 <a href="#about_sponsors" data-toggle="tab">Supporters</a>
5241 </li>
5242
5243
5244
5245
5246
5247
5248 <li id="about_authors_link"
5249
5250 class=" "
5251
5252 >
5253 <a href="#about_authors" data-toggle="tab">Authors</a>
5254 </li>
5255
5256
5257
5258
5259
5260
5261 <li id="about_license_link"
5262
5263 class=" "
5264
5265 >
5266 <a href="#about_license" data-toggle="tab">OctoPrint License</a>
5267 </li>
5268
5269
5270
5271
5272
5273
5274 <li id="about_thirdparty_link"
5275
5276 class=" "
5277
5278 >
5279 <a href="#about_thirdparty" data-toggle="tab">Third Party Licenses</a>
5280 </li>
5281
5282
5283
5284
5285
5286 <!-- ko allowBindings: false -->
5287 <li id="about_plugin_pluginmanager_link"
5288 data-bind="allowBindings: true"
5289 class=" "
5290
5291 >
5292 <a href="#about_plugin_pluginmanager" data-toggle="tab">Plugin Licenses</a>
5293 </li>
5294 <!-- /ko -->
5295
5296
5297 </ul>
5298 </div>
5299 <div class="tab-content span9 scrollable" id="about_dialog_content">
5300
5301
5302
5303
5304
5305 <div id="about_about"
5306
5307 class="tab-pane active "
5308
5309 >
5310 <h3>OctoPrint</h3>
5311
5312<h4>The snappy web interface for your 3D printer</h4>
5313
5314<p>Version <span class="version"></span></p>
5315
5316<ul class="fa-ul">
5317 <li><i class="fa-li fa fa-home"></i> Website: <a href="https://octoprint.org" target="_blank" rel="noreferrer noopener">octoprint.org</a></li>
5318 <li><i class="fa-li fa fa-users"></i> Community Forum: <a href="https://community.octoprint.org" target="_blank" rel="noreferrer noopener">community.octoprint.org</a></li>
5319 <li><i class="fa-li fa fa-question-circle"></i> FAQ: <a href="https://faq.octoprint.org" target="_blank" rel="noreferrer noopener">faq.octoprint.org</a></li>
5320 <li><i class="fa-li fa fa-book"></i> Documentation: <a href="http://docs.octoprint.org" target="_blank" rel="noreferrer noopener">docs.octoprint.org</a></li>
5321 <li><i class="fa-li fa fa-github"></i> Source Code: <a href="https://github.com/foosel/OctoPrint" target="_blank" rel="noreferrer noopener">github.com/foosel/OctoPrint</a></li>
5322 <li><i class="fa-li fa fa-code-fork"></i> Changelog: <a href="https://github.com/foosel/OctoPrint/releases" target="_blank" rel="noreferrer noopener">github.com/foosel/OctoPrint/releases</a></li>
5323</ul>
5324
5325<p>
5326 <strong>Development of OctoPrint wouldn't be possible without <a href="javascript:void(0)" data-bind="click: function() { showTab('about_sponsors'); }">its supporters</a>.</strong><br>
5327 If you enjoy OctoPrint, please consider <a href="https://octoprint.org/support-octoprint/?utm_source=octoprint&utm_medium=about_dialog" target="_blank" rel="noreferrer noopener">supporting its ongoing development</a>.
5328</p>
5329
5330<p>
5331 © 2012-2020 <a href="javascript:void(0)" data-bind="click: function() { showTab('about_authors'); }">The OctoPrint Authors</a>
5332</p>
5333
5334<p>
5335 This program is free software: you can redistribute it and/or modify
5336 it under the terms of the GNU Affero General Public License as
5337 published by the Free Software Foundation, either version 3 of the
5338 License, or (at your option) any later version.
5339</p>
5340
5341<p>
5342 This program is distributed in the hope that it will be useful,
5343 but WITHOUT ANY WARRANTY; without even the implied warranty of
5344 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5345 GNU Affero General Public License for more details.
5346</p>
5347
5348<p>
5349 For a copy of the GNU Affero General Public License, see <a href="javascript:void(0)" data-bind="click: function() { showTab('about_license'); }">OctoPrint License</a>
5350 to the left.
5351</p>
5352
5353<p>
5354 OctoPrint also utilizes various dependencies under terms of their
5355 respective licenses, which can be found under <a href="javascript:void(0)" data-bind="click: function() { showTab('about_thirdparty'); }">Third Party Licenses</a> to
5356 the left. Copyright of those dependencies lies with their respective authors
5357</p>
5358
5359<p><small>
5360 "OctoPrint" is a registered trademark.
5361</small></p>
5362 </div>
5363
5364
5365
5366
5367
5368
5369 <div id="about_sponsors"
5370
5371 class="tab-pane "
5372
5373 >
5374 <h3>Supporters</h3>
5375<p>Development of this version of OctoPrint wouldn't have been possible without
5376<a href="https://octoprint.org/support-octoprint/" target="_blank" rel="noreferrer noopener">the financial support by the community</a> -
5377thanks to everyone who contributed!</p>
5378<h4>Patreon Patrons</h4>
5379<ul>
5380<li>Andre Bubel</li>
5381<li>Andrew Moorby</li>
5382<li>Arnljot Arntsen</li>
5383<li>BigTreeTech</li>
5384<li>Boris Hussein</li>
5385<li>Brad Jackson</li>
5386<li>Christian Petropolis</li>
5387<li>Christian Wolf</li>
5388<li>D Brian Kimmel</li>
5389<li>DeltaMaker 3D Printers</li>
5390<li>Dorian Gray</li>
5391<li>Eric Betts</li>
5392<li>Ernesto Martinez</li>
5393<li>Franziska Kunsmann</li>
5394<li>GadgetAngel</li>
5395<li>George Robles</li>
5396<li>Greg Holloway</li>
5397<li>Hugh Blemings</li>
5398<li>jean-claude migneault</li>
5399<li>Jeff Renfer</li>
5400<li>Jeremiah Avery</li>
5401<li>John Robinson (JRo)</li>
5402<li>Joshua Wills</li>
5403<li>Justin Kaufman</li>
5404<li>Kaile Riser</li>
5405<li>Kale Stedman</li>
5406<li>Kazuhiro Ogura</li>
5407<li>Kenneth Jiang</li>
5408<li>Kyle Menigoz</li>
5409<li>LA 3D Printer Repair</li>
5410<li>Lee Dohm</li>
5411<li>Makespace Madrid</li>
5412<li>Mark Walker</li>
5413<li>Martin Majewski</li>
5414<li>Michael Aumock</li>
5415<li>Miles Flavel</li>
5416<li>Mosaic Manufacturing</li>
5417<li>OMER MEHMET SUTAS</li>
5418<li>Patrick Glyré</li>
5419<li>Patrick McGinnis</li>
5420<li>Prof Yuh Wen Chen</li>
5421<li>Randy C. Will</li>
5422<li>Ranjib Dey</li>
5423<li>Robert Gusek</li>
5424<li>Ronald Griehsler</li>
5425<li>Shawn Lewis</li>
5426<li>Simon Hallam</li>
5427<li>Stefan Krister</li>
5428<li>Sven Mueller</li>
5429<li>The3DprintingMagic.com</li>
5430<li>Trent Shumay</li>
5431<li>Ulrich Kempken</li>
5432<li>Vladislav Kuzemchik</li>
5433</ul>
5434<p>and 1678 more wonderful people pledging on the <a href="https://patreon.com/foosel" target="_blank" rel="noreferrer noopener">Patreon campaign</a> or via <a href="https://github.com/users/foosel/sponsorship" target="_blank" rel="noreferrer noopener">Github Sponsors</a>!</p>
5435 </div>
5436
5437
5438
5439
5440
5441
5442 <div id="about_authors"
5443
5444 class="tab-pane "
5445
5446 >
5447 <h3>Authors</h3>
5448<p>The following people have contributed to OctoPrint's code base (ordered roughly by
5449date of first contribution):</p>
5450<ul>
5451<li><a href="https://github.com/foosel" target="_blank" rel="noreferrer noopener">Gina Häußge</a></li>
5452<li><a href="https://github.com/imitation" target="_blank" rel="noreferrer noopener">Thomas Sanladerer</a></li>
5453<li><a href="https://github.com/hudbrog" target="_blank" rel="noreferrer noopener">Alex Ustyantsev</a></li>
5454<li><a href="https://github.com/ajd4096" target="_blank" rel="noreferrer noopener">Andrew Dalgleish</a></li>
5455<li><a href="https://github.com/daprice" target="_blank" rel="noreferrer noopener">Dale Price</a></li>
5456<li><a href="https://github.com/AxTheB" target="_blank" rel="noreferrer noopener">Václav "ax" Hůla</a></li>
5457<li><a href="https://github.com/daftscience" target="_blank" rel="noreferrer noopener">Tom Perry</a></li>
5458<li><a href="https://github.com/splitbrain" target="_blank" rel="noreferrer noopener">Andreas Gohr</a></li>
5459<li><a href="https://github.com/norpchen" target="_blank" rel="noreferrer noopener">Lars Norpchen</a></li>
5460<li><a href="https://github.com/marwue" target="_blank" rel="noreferrer noopener">Marlon Wünnemann</a></li>
5461<li><a href="https://github.com/algspd" target="_blank" rel="noreferrer noopener">"algspd"</a></li>
5462<li><a href="https://github.com/peteruithoven" target="_blank" rel="noreferrer noopener">Peter Uithoven</a></li>
5463<li><a href="https://github.com/CapnBry" target="_blank" rel="noreferrer noopener">Bryan Mayland</a></li>
5464<li><a href="https://github.com/savorywatt" target="_blank" rel="noreferrer noopener">Ross Hendrickson</a></li>
5465<li><a href="https://github.com/DanLipsitt" target="_blank" rel="noreferrer noopener">Dan Lipsitt</a></li>
5466<li><a href="https://github.com/jamesgao" target="_blank" rel="noreferrer noopener">James Gao</a></li>
5467<li><a href="https://github.com/tonnerre" target="_blank" rel="noreferrer noopener">Tonnerre Lombard</a></li>
5468<li><a href="https://github.com/Salandora" target="_blank" rel="noreferrer noopener">Marc Hannappel</a></li>
5469<li><a href="https://github.com/brad" target="_blank" rel="noreferrer noopener">Brad Pitcher</a></li>
5470<li><a href="https://github.com/rosenhouse" target="_blank" rel="noreferrer noopener">Gabe Rosenhouse</a></li>
5471<li><a href="https://github.com/chriskoz" target="_blank" rel="noreferrer noopener">chriskoz</a></li>
5472<li><a href="https://github.com/nullie" target="_blank" rel="noreferrer noopener">Ilya Novoselov</a></li>
5473<li><a href="https://github.com/C-o-r-E" target="_blank" rel="noreferrer noopener">Corey C</a></li>
5474<li><a href="https://github.com/imrahil" target="_blank" rel="noreferrer noopener">Jarek Szczepanski</a></li>
5475<li><a href="https://github.com/jonnor" target="_blank" rel="noreferrer noopener">Jon Nordby</a></li>
5476<li><a href="https://github.com/qbit" target="_blank" rel="noreferrer noopener">Aaron Bieber</a></li>
5477<li><a href="https://github.com/guysoft" target="_blank" rel="noreferrer noopener">Guy Sheffer</a></li>
5478<li><a href="https://github.com/dattas" target="_blank" rel="noreferrer noopener">Dattas Moonchaser</a></li>
5479<li><a href="https://github.com/Booli" target="_blank" rel="noreferrer noopener">Pim Rutgers</a></li>
5480<li><a href="https://github.com/koenkooi" target="_blank" rel="noreferrer noopener">Koen Kooi</a></li>
5481<li><a href="https://github.com/Wallacoloo" target="_blank" rel="noreferrer noopener">Colin Wallace</a></li>
5482<li><a href="https://github.com/mangtronix" target="_blank" rel="noreferrer noopener">Michael Ang</a></li>
5483<li><a href="https://github.com/nosyjoe" target="_blank" rel="noreferrer noopener">Philipp Engel</a></li>
5484<li><a href="https://github.com/vishnubob" target="_blank" rel="noreferrer noopener">Giles Hall</a></li>
5485<li><a href="https://github.com/Bevaz" target="_blank" rel="noreferrer noopener">Bevaz</a></li>
5486<li><a href="https://github.com/bortek" target="_blank" rel="noreferrer noopener">Bortek</a></li>
5487<li><a href="https://github.com/rspeed" target="_blank" rel="noreferrer noopener">Rob Speed</a></li>
5488<li><a href="https://github.com/Renha" target="_blank" rel="noreferrer noopener">Renha</a></li>
5489<li><a href="https://github.com/Diaoul" target="_blank" rel="noreferrer noopener">Antoine Bertin</a></li>
5490<li><a href="https://github.com/hungerpirat" target="_blank" rel="noreferrer noopener">Teja Philipp</a></li>
5491<li><a href="https://github.com/matobago" target="_blank" rel="noreferrer noopener">"matobago"</a></li>
5492<li><a href="https://github.com/nophead" target="_blank" rel="noreferrer noopener">"nophead"</a></li>
5493<li><a href="https://github.com/thinkl33t" target="_blank" rel="noreferrer noopener">Bob Clough</a></li>
5494<li><a href="https://github.com/Mikk36" target="_blank" rel="noreferrer noopener">Mikk Kiilaspää</a></li>
5495<li><a href="https://github.com/jminardi" target="_blank" rel="noreferrer noopener">Jack Minardi</a></li>
5496<li><a href="https://github.com/markwal" target="_blank" rel="noreferrer noopener">Mark Walker</a></li>
5497<li><a href="https://github.com/lucas-clemente" target="_blank" rel="noreferrer noopener">Lucas Clemente</a></li>
5498<li><a href="https://github.com/aerickson" target="_blank" rel="noreferrer noopener">Andrew Erickson</a></li>
5499<li><a href="https://github.com/nicanor-romero" target="_blank" rel="noreferrer noopener">Nicanor Romero Venier</a></li>
5500<li><a href="https://github.com/masterhou" target="_blank" rel="noreferrer noopener">Thomas Hou</a></li>
5501<li><a href="https://github.com/markbastiaans" target="_blank" rel="noreferrer noopener">Mark Bastiaans</a></li>
5502<li><a href="https://github.com/punkkeks" target="_blank" rel="noreferrer noopener">Marcel Hellwig</a></li>
5503<li><a href="https://github.com/kevingelion" target="_blank" rel="noreferrer noopener">Kevin Murphy</a></li>
5504<li><a href="https://github.com/richjoyce" target="_blank" rel="noreferrer noopener">Richard Joyce</a></li>
5505<li><a href="https://github.com/bwgan" target="_blank" rel="noreferrer noopener">"bwgan"</a></li>
5506<li><a href="https://github.com/2ndalpha" target="_blank" rel="noreferrer noopener">Siim Raud</a></li>
5507<li><a href="https://github.com/geoporalis" target="_blank" rel="noreferrer noopener">"geoporalis"</a></li>
5508<li><a href="https://github.com/2bitoperations" target="_blank" rel="noreferrer noopener">Andrew Malota</a></li>
5509<li><a href="https://github.com/agarwali" target="_blank" rel="noreferrer noopener">Ishwar Agarwal</a></li>
5510<li><a href="https://github.com/eykrevooh" target="_blank" rel="noreferrer noopener">Kye Hoover</a></li>
5511<li><a href="https://github.com/carricktel" target="_blank" rel="noreferrer noopener">Joseph Carrick</a></li>
5512<li><a href="https://github.com/Alex9779" target="_blank" rel="noreferrer noopener">Alexander Leisentritt</a></li>
5513<li><a href="https://github.com/therealbstern" target="_blank" rel="noreferrer noopener">therealbstern</a></li>
5514<li><a href="https://github.com/philphilphil" target="_blank" rel="noreferrer noopener">Philipp Baum</a></li>
5515<li><a href="https://github.com/kevans91" target="_blank" rel="noreferrer noopener">Kyle Evans</a></li>
5516<li><a href="https://github.com/Javierma" target="_blank" rel="noreferrer noopener">Javier Martínez Arrieta</a></li>
5517<li><a href="https://github.com/ByReaL" target="_blank" rel="noreferrer noopener">Mircea Dan Gheorghe</a></li>
5518<li><a href="https://github.com/MoonshineSG" target="_blank" rel="noreferrer noopener">Ovidiu Hossu</a></li>
5519<li><a href="https://github.com/eyck" target="_blank" rel="noreferrer noopener">Eyck Jentzsch</a></li>
5520<li><a href="https://github.com/mathiasrw" target="_blank" rel="noreferrer noopener">Mathias Rangel Wulff</a></li>
5521<li><a href="https://github.com/clemniem" target="_blank" rel="noreferrer noopener">Clemens Niemeyer</a></li>
5522<li><a href="https://github.com/I-am-me" target="_blank" rel="noreferrer noopener">"I-am-me"</a></li>
5523<li><a href="https://github.com/jammi" target="_blank" rel="noreferrer noopener">J-J Heinonen</a></li>
5524<li><a href="https://github.com/noahsmartin" target="_blank" rel="noreferrer noopener">Noah Martin</a></li>
5525<li><a href="https://github.com/eyal0" target="_blank" rel="noreferrer noopener">Eyal Soha</a></li>
5526<li><a href="https://github.com/ghulands" target="_blank" rel="noreferrer noopener">Greg Hulands</a></li>
5527<li><a href="https://github.com/gallore" target="_blank" rel="noreferrer noopener">Andreas Werner</a></li>
5528<li><a href="https://github.com/kantlivelong" target="_blank" rel="noreferrer noopener">Shawn Bruce</a></li>
5529<li><a href="https://github.com/ClaudiuCeia" target="_blank" rel="noreferrer noopener">Claudiu Ceia</a></li>
5530<li><a href="https://github.com/mrvn" target="_blank" rel="noreferrer noopener">Goswin von Brederlow</a></li>
5531<li><a href="https://github.com/galamdring" target="_blank" rel="noreferrer noopener">Luke McKechnie</a></li>
5532<li><a href="https://github.com/pbackx" target="_blank" rel="noreferrer noopener">Peter Backx</a></li>
5533<li><a href="https://github.com/astateofblank" target="_blank" rel="noreferrer noopener">Josh Major</a></li>
5534<li><a href="https://github.com/alex-gh" target="_blank" rel="noreferrer noopener">"alex-gh"</a></li>
5535<li><a href="https://github.com/bzed" target="_blank" rel="noreferrer noopener">Bernd Zeimetz</a></li>
5536<li><a href="https://github.com/dforsi" target="_blank" rel="noreferrer noopener">Daniele Forsi</a></li>
5537<li><a href="https://github.com/ganey" target="_blank" rel="noreferrer noopener">Ganey</a></li>
5538<li><a href="https://github.com/malnvenshorn" target="_blank" rel="noreferrer noopener">Sven Lohrmann</a></li>
5539<li><a href="https://github.com/klikini" target="_blank" rel="noreferrer noopener">Andy Castille</a></li>
5540<li><a href="https://github.com/ZachNo" target="_blank" rel="noreferrer noopener">Zachary Nofzinger</a></li>
5541<li><a href="https://github.com/gdombiak" target="_blank" rel="noreferrer noopener">Gaston Dombiak</a></li>
5542<li><a href="https://github.com/bradcfisher" target="_blank" rel="noreferrer noopener">Brad Fisher</a></li>
5543<li><a href="https://github.com/fieldofview" target="_blank" rel="noreferrer noopener">Aldo Hoeben</a></li>
5544<li><a href="https://github.com/hgross" target="_blank" rel="noreferrer noopener">Henning Groß</a></li>
5545<li><a href="https://github.com/jubaleth" target="_blank" rel="noreferrer noopener">Jubaleth</a></li>
5546<li><a href="https://github.com/smurfix" target="_blank" rel="noreferrer noopener">Matthias Urlichs</a></li>
5547<li><a href="https://github.com/DanielJoyce" target="_blank" rel="noreferrer noopener">Daniel Joyce</a></li>
5548<li><a href="https://github.com/AndyQ" target="_blank" rel="noreferrer noopener">Andy Qua</a></li>
5549<li><a href="https://github.com/Fabi0San" target="_blank" rel="noreferrer noopener">Fabio Santos</a></li>
5550<li><a href="https://github.com/jackwilsdon" target="_blank" rel="noreferrer noopener">Jack Wilsdon</a></li>
5551<li><a href="https://github.com/rfinnie" target="_blank" rel="noreferrer noopener">Ryan Finnie</a></li>
5552<li><a href="https://github.com/tduehr" target="_blank" rel="noreferrer noopener">Timur Duehr</a></li>
5553<li><a href="https://github.com/dovecode" target="_blank" rel="noreferrer noopener">Nicolai Nielsen</a></li>
5554<li><a href="https://github.com/JanneMantyharju" target="_blank" rel="noreferrer noopener">Janne Mäntyharju</a></li>
5555<li><a href="https://github.com/flamenco" target="_blank" rel="noreferrer noopener">Steven Spungin</a></li>
5556<li><a href="https://github.com/pusewicz" target="_blank" rel="noreferrer noopener">Piotr Usewicz</a></li>
5557<li><a href="https://github.com/aliaksei135" target="_blank" rel="noreferrer noopener">Aliaksei Pilko</a></li>
5558<li><a href="https://github.com/byarmis" target="_blank" rel="noreferrer noopener">Ben Yarmis</a></li>
5559<li><a href="https://github.com/FHeilmann" target="_blank" rel="noreferrer noopener">Florian Heilmann</a></li>
5560<li><a href="https://github.com/RyuzakiKK" target="_blank" rel="noreferrer noopener">Ludovico de Nittis</a></li>
5561<li><a href="https://github.com/DominikPalo" target="_blank" rel="noreferrer noopener">Dominik Paľo</a></li>
5562<li><a href="https://github.com/cbxbiker61" target="_blank" rel="noreferrer noopener">Kelly Anderson</a></li>
5563</ul>
5564<p>OctoPrint started off as a fork of <a href="https://github.com/daid/Cura" target="_blank" rel="noreferrer noopener">Cura</a> by
5565<a href="https://github.com/daid" target="_blank" rel="noreferrer noopener">Daid Braam</a>. Parts of its communication layer and
5566the server side GCODE interpreter are still based on Cura's code base from
5567December 2012 and hence on the work of its authors up until then.</p>
5568 </div>
5569
5570
5571
5572
5573
5574
5575 <div id="about_license"
5576
5577 class="tab-pane "
5578
5579 >
5580 <h3 style="text-align: center;">GNU AFFERO GENERAL PUBLIC LICENSE</h3>
5581<p style="text-align: center;">Version 3, 19 November 2007</p>
5582
5583<p>Copyright © 2007 Free Software Foundation,
5584 Inc. <<a href="http://fsf.org/" target="_blank" rel="noreferrer noopener">http://fsf.org/</a>>
5585 <br />
5586 Everyone is permitted to copy and distribute verbatim copies
5587 of this license document, but changing it is not allowed.</p>
5588
5589<h3><a name="preamble"></a>Preamble</h3>
5590
5591<p>The GNU Affero General Public License is a free, copyleft license
5592 for software and other kinds of works, specifically designed to ensure
5593 cooperation with the community in the case of network server software.</p>
5594
5595<p>The licenses for most software and other practical works are
5596 designed to take away your freedom to share and change the works. By
5597 contrast, our General Public Licenses are intended to guarantee your
5598 freedom to share and change all versions of a program--to make sure it
5599 remains free software for all its users.</p>
5600
5601<p>When we speak of free software, we are referring to freedom, not
5602 price. Our General Public Licenses are designed to make sure that you
5603 have the freedom to distribute copies of free software (and charge for
5604 them if you wish), that you receive source code or can get it if you
5605 want it, that you can change the software or use pieces of it in new
5606 free programs, and that you know you can do these things.</p>
5607
5608<p>Developers that use our General Public Licenses protect your rights
5609 with two steps: (1) assert copyright on the software, and (2) offer
5610 you this License which gives you legal permission to copy, distribute
5611 and/or modify the software.</p>
5612
5613<p>A secondary benefit of defending all users' freedom is that
5614 improvements made in alternate versions of the program, if they
5615 receive widespread use, become available for other developers to
5616 incorporate. Many developers of free software are heartened and
5617 encouraged by the resulting cooperation. However, in the case of
5618 software used on network servers, this result may fail to come about.
5619 The GNU General Public License permits making a modified version and
5620 letting the public access it on a server without ever releasing its
5621 source code to the public.</p>
5622
5623<p>The GNU Affero General Public License is designed specifically to
5624 ensure that, in such cases, the modified source code becomes available
5625 to the community. It requires the operator of a network server to
5626 provide the source code of the modified version running there to the
5627 users of that server. Therefore, public use of a modified version, on
5628 a publicly accessible server, gives the public access to the source
5629 code of the modified version.</p>
5630
5631<p>An older license, called the Affero General Public License and
5632 published by Affero, was designed to accomplish similar goals. This is
5633 a different license, not a version of the Affero GPL, but Affero has
5634 released a new version of the Affero GPL which permits relicensing under
5635 this license.</p>
5636
5637<p>The precise terms and conditions for copying, distribution and
5638 modification follow.</p>
5639
5640<h3><a name="terms"></a>TERMS AND CONDITIONS</h3>
5641
5642<h4><a name="section0"></a>0. Definitions.</h4>
5643
5644<p>"This License" refers to version 3 of the GNU Affero General Public
5645 License.</p>
5646
5647<p>"Copyright" also means copyright-like laws that apply to other kinds
5648 of works, such as semiconductor masks.</p>
5649
5650<p>"The Program" refers to any copyrightable work licensed under this
5651 License. Each licensee is addressed as "you". "Licensees" and
5652 "recipients" may be individuals or organizations.</p>
5653
5654<p>To "modify" a work means to copy from or adapt all or part of the work
5655 in a fashion requiring copyright permission, other than the making of an
5656 exact copy. The resulting work is called a "modified version" of the
5657 earlier work or a work "based on" the earlier work.</p>
5658
5659<p>A "covered work" means either the unmodified Program or a work based
5660 on the Program.</p>
5661
5662<p>To "propagate" a work means to do anything with it that, without
5663 permission, would make you directly or secondarily liable for
5664 infringement under applicable copyright law, except executing it on a
5665 computer or modifying a private copy. Propagation includes copying,
5666 distribution (with or without modification), making available to the
5667 public, and in some countries other activities as well.</p>
5668
5669<p>To "convey" a work means any kind of propagation that enables other
5670 parties to make or receive copies. Mere interaction with a user through
5671 a computer network, with no transfer of a copy, is not conveying.</p>
5672
5673<p>An interactive user interface displays "Appropriate Legal Notices"
5674 to the extent that it includes a convenient and prominently visible
5675 feature that (1) displays an appropriate copyright notice, and (2)
5676 tells the user that there is no warranty for the work (except to the
5677 extent that warranties are provided), that licensees may convey the
5678 work under this License, and how to view a copy of this License. If
5679 the interface presents a list of user commands or options, such as a
5680 menu, a prominent item in the list meets this criterion.</p>
5681
5682<h4><a name="section1"></a>1. Source Code.</h4>
5683
5684<p>The "source code" for a work means the preferred form of the work
5685 for making modifications to it. "Object code" means any non-source
5686 form of a work.</p>
5687
5688<p>A "Standard Interface" means an interface that either is an official
5689 standard defined by a recognized standards body, or, in the case of
5690 interfaces specified for a particular programming language, one that
5691 is widely used among developers working in that language.</p>
5692
5693<p>The "System Libraries" of an executable work include anything, other
5694 than the work as a whole, that (a) is included in the normal form of
5695 packaging a Major Component, but which is not part of that Major
5696 Component, and (b) serves only to enable use of the work with that
5697 Major Component, or to implement a Standard Interface for which an
5698 implementation is available to the public in source code form. A
5699 "Major Component", in this context, means a major essential component
5700 (kernel, window system, and so on) of the specific operating system
5701 (if any) on which the executable work runs, or a compiler used to
5702 produce the work, or an object code interpreter used to run it.</p>
5703
5704<p>The "Corresponding Source" for a work in object code form means all
5705 the source code needed to generate, install, and (for an executable
5706 work) run the object code and to modify the work, including scripts to
5707 control those activities. However, it does not include the work's
5708 System Libraries, or general-purpose tools or generally available free
5709 programs which are used unmodified in performing those activities but
5710 which are not part of the work. For example, Corresponding Source
5711 includes interface definition files associated with source files for
5712 the work, and the source code for shared libraries and dynamically
5713 linked subprograms that the work is specifically designed to require,
5714 such as by intimate data communication or control flow between those
5715 subprograms and other parts of the work.</p>
5716
5717<p>The Corresponding Source need not include anything that users
5718 can regenerate automatically from other parts of the Corresponding
5719 Source.</p>
5720
5721<p>The Corresponding Source for a work in source code form is that
5722 same work.</p>
5723
5724<h4><a name="section2"></a>2. Basic Permissions.</h4>
5725
5726<p>All rights granted under this License are granted for the term of
5727 copyright on the Program, and are irrevocable provided the stated
5728 conditions are met. This License explicitly affirms your unlimited
5729 permission to run the unmodified Program. The output from running a
5730 covered work is covered by this License only if the output, given its
5731 content, constitutes a covered work. This License acknowledges your
5732 rights of fair use or other equivalent, as provided by copyright law.</p>
5733
5734<p>You may make, run and propagate covered works that you do not
5735 convey, without conditions so long as your license otherwise remains
5736 in force. You may convey covered works to others for the sole purpose
5737 of having them make modifications exclusively for you, or provide you
5738 with facilities for running those works, provided that you comply with
5739 the terms of this License in conveying all material for which you do
5740 not control copyright. Those thus making or running the covered works
5741 for you must do so exclusively on your behalf, under your direction
5742 and control, on terms that prohibit them from making any copies of
5743 your copyrighted material outside their relationship with you.</p>
5744
5745<p>Conveying under any other circumstances is permitted solely under
5746 the conditions stated below. Sublicensing is not allowed; section 10
5747 makes it unnecessary.</p>
5748
5749<h4><a name="section3"></a>3. Protecting Users' Legal Rights From Anti-Circumvention Law.</h4>
5750
5751<p>No covered work shall be deemed part of an effective technological
5752 measure under any applicable law fulfilling obligations under article
5753 11 of the WIPO copyright treaty adopted on 20 December 1996, or
5754 similar laws prohibiting or restricting circumvention of such
5755 measures.</p>
5756
5757<p>When you convey a covered work, you waive any legal power to forbid
5758 circumvention of technological measures to the extent such circumvention
5759 is effected by exercising rights under this License with respect to
5760 the covered work, and you disclaim any intention to limit operation or
5761 modification of the work as a means of enforcing, against the work's
5762 users, your or third parties' legal rights to forbid circumvention of
5763 technological measures.</p>
5764
5765<h4><a name="section4"></a>4. Conveying Verbatim Copies.</h4>
5766
5767<p>You may convey verbatim copies of the Program's source code as you
5768 receive it, in any medium, provided that you conspicuously and
5769 appropriately publish on each copy an appropriate copyright notice;
5770 keep intact all notices stating that this License and any
5771 non-permissive terms added in accord with section 7 apply to the code;
5772 keep intact all notices of the absence of any warranty; and give all
5773 recipients a copy of this License along with the Program.</p>
5774
5775<p>You may charge any price or no price for each copy that you convey,
5776 and you may offer support or warranty protection for a fee.</p>
5777
5778<h4><a name="section5"></a>5. Conveying Modified Source Versions.</h4>
5779
5780<p>You may convey a work based on the Program, or the modifications to
5781 produce it from the Program, in the form of source code under the
5782 terms of section 4, provided that you also meet all of these conditions:</p>
5783
5784<ul>
5785
5786 <li>a) The work must carry prominent notices stating that you modified
5787 it, and giving a relevant date.</li>
5788
5789 <li>b) The work must carry prominent notices stating that it is
5790 released under this License and any conditions added under section
5791 7. This requirement modifies the requirement in section 4 to
5792 "keep intact all notices".</li>
5793
5794 <li>c) You must license the entire work, as a whole, under this
5795 License to anyone who comes into possession of a copy. This
5796 License will therefore apply, along with any applicable section 7
5797 additional terms, to the whole of the work, and all its parts,
5798 regardless of how they are packaged. This License gives no
5799 permission to license the work in any other way, but it does not
5800 invalidate such permission if you have separately received it.</li>
5801
5802 <li>d) If the work has interactive user interfaces, each must display
5803 Appropriate Legal Notices; however, if the Program has interactive
5804 interfaces that do not display Appropriate Legal Notices, your
5805 work need not make them do so.</li>
5806
5807</ul>
5808
5809<p>A compilation of a covered work with other separate and independent
5810 works, which are not by their nature extensions of the covered work,
5811 and which are not combined with it such as to form a larger program,
5812 in or on a volume of a storage or distribution medium, is called an
5813 "aggregate" if the compilation and its resulting copyright are not
5814 used to limit the access or legal rights of the compilation's users
5815 beyond what the individual works permit. Inclusion of a covered work
5816 in an aggregate does not cause this License to apply to the other
5817 parts of the aggregate.</p>
5818
5819<h4><a name="section6"></a>6. Conveying Non-Source Forms.</h4>
5820
5821<p>You may convey a covered work in object code form under the terms
5822 of sections 4 and 5, provided that you also convey the
5823 machine-readable Corresponding Source under the terms of this License,
5824 in one of these ways:</p>
5825
5826<ul>
5827
5828 <li>a) Convey the object code in, or embodied in, a physical product
5829 (including a physical distribution medium), accompanied by the
5830 Corresponding Source fixed on a durable physical medium
5831 customarily used for software interchange.</li>
5832
5833 <li>b) Convey the object code in, or embodied in, a physical product
5834 (including a physical distribution medium), accompanied by a
5835 written offer, valid for at least three years and valid for as
5836 long as you offer spare parts or customer support for that product
5837 model, to give anyone who possesses the object code either (1) a
5838 copy of the Corresponding Source for all the software in the
5839 product that is covered by this License, on a durable physical
5840 medium customarily used for software interchange, for a price no
5841 more than your reasonable cost of physically performing this
5842 conveying of source, or (2) access to copy the
5843 Corresponding Source from a network server at no charge.</li>
5844
5845 <li>c) Convey individual copies of the object code with a copy of the
5846 written offer to provide the Corresponding Source. This
5847 alternative is allowed only occasionally and noncommercially, and
5848 only if you received the object code with such an offer, in accord
5849 with subsection 6b.</li>
5850
5851 <li>d) Convey the object code by offering access from a designated
5852 place (gratis or for a charge), and offer equivalent access to the
5853 Corresponding Source in the same way through the same place at no
5854 further charge. You need not require recipients to copy the
5855 Corresponding Source along with the object code. If the place to
5856 copy the object code is a network server, the Corresponding Source
5857 may be on a different server (operated by you or a third party)
5858 that supports equivalent copying facilities, provided you maintain
5859 clear directions next to the object code saying where to find the
5860 Corresponding Source. Regardless of what server hosts the
5861 Corresponding Source, you remain obligated to ensure that it is
5862 available for as long as needed to satisfy these requirements.</li>
5863
5864 <li>e) Convey the object code using peer-to-peer transmission, provided
5865 you inform other peers where the object code and Corresponding
5866 Source of the work are being offered to the general public at no
5867 charge under subsection 6d.</li>
5868
5869</ul>
5870
5871<p>A separable portion of the object code, whose source code is excluded
5872 from the Corresponding Source as a System Library, need not be
5873 included in conveying the object code work.</p>
5874
5875<p>A "User Product" is either (1) a "consumer product", which means any
5876 tangible personal property which is normally used for personal, family,
5877 or household purposes, or (2) anything designed or sold for incorporation
5878 into a dwelling. In determining whether a product is a consumer product,
5879 doubtful cases shall be resolved in favor of coverage. For a particular
5880 product received by a particular user, "normally used" refers to a
5881 typical or common use of that class of product, regardless of the status
5882 of the particular user or of the way in which the particular user
5883 actually uses, or expects or is expected to use, the product. A product
5884 is a consumer product regardless of whether the product has substantial
5885 commercial, industrial or non-consumer uses, unless such uses represent
5886 the only significant mode of use of the product.</p>
5887
5888<p>"Installation Information" for a User Product means any methods,
5889 procedures, authorization keys, or other information required to install
5890 and execute modified versions of a covered work in that User Product from
5891 a modified version of its Corresponding Source. The information must
5892 suffice to ensure that the continued functioning of the modified object
5893 code is in no case prevented or interfered with solely because
5894 modification has been made.</p>
5895
5896<p>If you convey an object code work under this section in, or with, or
5897 specifically for use in, a User Product, and the conveying occurs as
5898 part of a transaction in which the right of possession and use of the
5899 User Product is transferred to the recipient in perpetuity or for a
5900 fixed term (regardless of how the transaction is characterized), the
5901 Corresponding Source conveyed under this section must be accompanied
5902 by the Installation Information. But this requirement does not apply
5903 if neither you nor any third party retains the ability to install
5904 modified object code on the User Product (for example, the work has
5905 been installed in ROM).</p>
5906
5907<p>The requirement to provide Installation Information does not include a
5908 requirement to continue to provide support service, warranty, or updates
5909 for a work that has been modified or installed by the recipient, or for
5910 the User Product in which it has been modified or installed. Access to a
5911 network may be denied when the modification itself materially and
5912 adversely affects the operation of the network or violates the rules and
5913 protocols for communication across the network.</p>
5914
5915<p>Corresponding Source conveyed, and Installation Information provided,
5916 in accord with this section must be in a format that is publicly
5917 documented (and with an implementation available to the public in
5918 source code form), and must require no special password or key for
5919 unpacking, reading or copying.</p>
5920
5921<h4><a name="section7"></a>7. Additional Terms.</h4>
5922
5923<p>"Additional permissions" are terms that supplement the terms of this
5924 License by making exceptions from one or more of its conditions.
5925 Additional permissions that are applicable to the entire Program shall
5926 be treated as though they were included in this License, to the extent
5927 that they are valid under applicable law. If additional permissions
5928 apply only to part of the Program, that part may be used separately
5929 under those permissions, but the entire Program remains governed by
5930 this License without regard to the additional permissions.</p>
5931
5932<p>When you convey a copy of a covered work, you may at your option
5933 remove any additional permissions from that copy, or from any part of
5934 it. (Additional permissions may be written to require their own
5935 removal in certain cases when you modify the work.) You may place
5936 additional permissions on material, added by you to a covered work,
5937 for which you have or can give appropriate copyright permission.</p>
5938
5939<p>Notwithstanding any other provision of this License, for material you
5940 add to a covered work, you may (if authorized by the copyright holders of
5941 that material) supplement the terms of this License with terms:</p>
5942
5943<ul>
5944
5945 <li>a) Disclaiming warranty or limiting liability differently from the
5946 terms of sections 15 and 16 of this License; or</li>
5947
5948 <li>b) Requiring preservation of specified reasonable legal notices or
5949 author attributions in that material or in the Appropriate Legal
5950 Notices displayed by works containing it; or</li>
5951
5952 <li>c) Prohibiting misrepresentation of the origin of that material, or
5953 requiring that modified versions of such material be marked in
5954 reasonable ways as different from the original version; or</li>
5955
5956 <li>d) Limiting the use for publicity purposes of names of licensors or
5957 authors of the material; or</li>
5958
5959 <li>e) Declining to grant rights under trademark law for use of some
5960 trade names, trademarks, or service marks; or</li>
5961
5962 <li>f) Requiring indemnification of licensors and authors of that
5963 material by anyone who conveys the material (or modified versions of
5964 it) with contractual assumptions of liability to the recipient, for
5965 any liability that these contractual assumptions directly impose on
5966 those licensors and authors.</li>
5967
5968</ul>
5969
5970<p>All other non-permissive additional terms are considered "further
5971 restrictions" within the meaning of section 10. If the Program as you
5972 received it, or any part of it, contains a notice stating that it is
5973 governed by this License along with a term that is a further restriction,
5974 you may remove that term. If a license document contains a further
5975 restriction but permits relicensing or conveying under this License, you
5976 may add to a covered work material governed by the terms of that license
5977 document, provided that the further restriction does not survive such
5978 relicensing or conveying.</p>
5979
5980<p>If you add terms to a covered work in accord with this section, you
5981 must place, in the relevant source files, a statement of the
5982 additional terms that apply to those files, or a notice indicating
5983 where to find the applicable terms.</p>
5984
5985<p>Additional terms, permissive or non-permissive, may be stated in the
5986 form of a separately written license, or stated as exceptions;
5987 the above requirements apply either way.</p>
5988
5989<h4><a name="section8"></a>8. Termination.</h4>
5990
5991<p>You may not propagate or modify a covered work except as expressly
5992 provided under this License. Any attempt otherwise to propagate or
5993 modify it is void, and will automatically terminate your rights under
5994 this License (including any patent licenses granted under the third
5995 paragraph of section 11).</p>
5996
5997<p>However, if you cease all violation of this License, then your
5998 license from a particular copyright holder is reinstated (a)
5999 provisionally, unless and until the copyright holder explicitly and
6000 finally terminates your license, and (b) permanently, if the copyright
6001 holder fails to notify you of the violation by some reasonable means
6002 prior to 60 days after the cessation.</p>
6003
6004<p>Moreover, your license from a particular copyright holder is
6005 reinstated permanently if the copyright holder notifies you of the
6006 violation by some reasonable means, this is the first time you have
6007 received notice of violation of this License (for any work) from that
6008 copyright holder, and you cure the violation prior to 30 days after
6009 your receipt of the notice.</p>
6010
6011<p>Termination of your rights under this section does not terminate the
6012 licenses of parties who have received copies or rights from you under
6013 this License. If your rights have been terminated and not permanently
6014 reinstated, you do not qualify to receive new licenses for the same
6015 material under section 10.</p>
6016
6017<h4><a name="section9"></a>9. Acceptance Not Required for Having Copies.</h4>
6018
6019<p>You are not required to accept this License in order to receive or
6020 run a copy of the Program. Ancillary propagation of a covered work
6021 occurring solely as a consequence of using peer-to-peer transmission
6022 to receive a copy likewise does not require acceptance. However,
6023 nothing other than this License grants you permission to propagate or
6024 modify any covered work. These actions infringe copyright if you do
6025 not accept this License. Therefore, by modifying or propagating a
6026 covered work, you indicate your acceptance of this License to do so.</p>
6027
6028<h4><a name="section10"></a>10. Automatic Licensing of Downstream Recipients.</h4>
6029
6030<p>Each time you convey a covered work, the recipient automatically
6031 receives a license from the original licensors, to run, modify and
6032 propagate that work, subject to this License. You are not responsible
6033 for enforcing compliance by third parties with this License.</p>
6034
6035<p>An "entity transaction" is a transaction transferring control of an
6036 organization, or substantially all assets of one, or subdividing an
6037 organization, or merging organizations. If propagation of a covered
6038 work results from an entity transaction, each party to that
6039 transaction who receives a copy of the work also receives whatever
6040 licenses to the work the party's predecessor in interest had or could
6041 give under the previous paragraph, plus a right to possession of the
6042 Corresponding Source of the work from the predecessor in interest, if
6043 the predecessor has it or can get it with reasonable efforts.</p>
6044
6045<p>You may not impose any further restrictions on the exercise of the
6046 rights granted or affirmed under this License. For example, you may
6047 not impose a license fee, royalty, or other charge for exercise of
6048 rights granted under this License, and you may not initiate litigation
6049 (including a cross-claim or counterclaim in a lawsuit) alleging that
6050 any patent claim is infringed by making, using, selling, offering for
6051 sale, or importing the Program or any portion of it.</p>
6052
6053<h4><a name="section11"></a>11. Patents.</h4>
6054
6055<p>A "contributor" is a copyright holder who authorizes use under this
6056 License of the Program or a work on which the Program is based. The
6057 work thus licensed is called the contributor's "contributor version".</p>
6058
6059<p>A contributor's "essential patent claims" are all patent claims
6060 owned or controlled by the contributor, whether already acquired or
6061 hereafter acquired, that would be infringed by some manner, permitted
6062 by this License, of making, using, or selling its contributor version,
6063 but do not include claims that would be infringed only as a
6064 consequence of further modification of the contributor version. For
6065 purposes of this definition, "control" includes the right to grant
6066 patent sublicenses in a manner consistent with the requirements of
6067 this License.</p>
6068
6069<p>Each contributor grants you a non-exclusive, worldwide, royalty-free
6070 patent license under the contributor's essential patent claims, to
6071 make, use, sell, offer for sale, import and otherwise run, modify and
6072 propagate the contents of its contributor version.</p>
6073
6074<p>In the following three paragraphs, a "patent license" is any express
6075 agreement or commitment, however denominated, not to enforce a patent
6076 (such as an express permission to practice a patent or covenant not to
6077 sue for patent infringement). To "grant" such a patent license to a
6078 party means to make such an agreement or commitment not to enforce a
6079 patent against the party.</p>
6080
6081<p>If you convey a covered work, knowingly relying on a patent license,
6082 and the Corresponding Source of the work is not available for anyone
6083 to copy, free of charge and under the terms of this License, through a
6084 publicly available network server or other readily accessible means,
6085 then you must either (1) cause the Corresponding Source to be so
6086 available, or (2) arrange to deprive yourself of the benefit of the
6087 patent license for this particular work, or (3) arrange, in a manner
6088 consistent with the requirements of this License, to extend the patent
6089 license to downstream recipients. "Knowingly relying" means you have
6090 actual knowledge that, but for the patent license, your conveying the
6091 covered work in a country, or your recipient's use of the covered work
6092 in a country, would infringe one or more identifiable patents in that
6093 country that you have reason to believe are valid.</p>
6094
6095<p>If, pursuant to or in connection with a single transaction or
6096 arrangement, you convey, or propagate by procuring conveyance of, a
6097 covered work, and grant a patent license to some of the parties
6098 receiving the covered work authorizing them to use, propagate, modify
6099 or convey a specific copy of the covered work, then the patent license
6100 you grant is automatically extended to all recipients of the covered
6101 work and works based on it.</p>
6102
6103<p>A patent license is "discriminatory" if it does not include within
6104 the scope of its coverage, prohibits the exercise of, or is
6105 conditioned on the non-exercise of one or more of the rights that are
6106 specifically granted under this License. You may not convey a covered
6107 work if you are a party to an arrangement with a third party that is
6108 in the business of distributing software, under which you make payment
6109 to the third party based on the extent of your activity of conveying
6110 the work, and under which the third party grants, to any of the
6111 parties who would receive the covered work from you, a discriminatory
6112 patent license (a) in connection with copies of the covered work
6113 conveyed by you (or copies made from those copies), or (b) primarily
6114 for and in connection with specific products or compilations that
6115 contain the covered work, unless you entered into that arrangement,
6116 or that patent license was granted, prior to 28 March 2007.</p>
6117
6118<p>Nothing in this License shall be construed as excluding or limiting
6119 any implied license or other defenses to infringement that may
6120 otherwise be available to you under applicable patent law.</p>
6121
6122<h4><a name="section12"></a>12. No Surrender of Others' Freedom.</h4>
6123
6124<p>If conditions are imposed on you (whether by court order, agreement or
6125 otherwise) that contradict the conditions of this License, they do not
6126 excuse you from the conditions of this License. If you cannot convey a
6127 covered work so as to satisfy simultaneously your obligations under this
6128 License and any other pertinent obligations, then as a consequence you may
6129 not convey it at all. For example, if you agree to terms that obligate you
6130 to collect a royalty for further conveying from those to whom you convey
6131 the Program, the only way you could satisfy both those terms and this
6132 License would be to refrain entirely from conveying the Program.</p>
6133
6134<h4><a name="section13"></a>13. Remote Network Interaction; Use with the GNU General Public License.</h4>
6135
6136<p>Notwithstanding any other provision of this License, if you modify the
6137 Program, your modified version must prominently offer all users
6138 interacting with it remotely through a computer network (if your version
6139 supports such interaction) an opportunity to receive the Corresponding
6140 Source of your version by providing access to the Corresponding Source
6141 from a network server at no charge, through some standard or customary
6142 means of facilitating copying of software. This Corresponding Source
6143 shall include the Corresponding Source for any work covered by version 3
6144 of the GNU General Public License that is incorporated pursuant to the
6145 following paragraph.</p>
6146
6147<p>Notwithstanding any other provision of this License, you have permission
6148 to link or combine any covered work with a work licensed under version 3
6149 of the GNU General Public License into a single combined work, and to
6150 convey the resulting work. The terms of this License will continue to
6151 apply to the part which is the covered work, but the work with which it is
6152 combined will remain governed by version 3 of the GNU General Public
6153 License.</p>
6154
6155<h4><a name="section14"></a>14. Revised Versions of this License.</h4>
6156
6157<p>The Free Software Foundation may publish revised and/or new versions of
6158 the GNU Affero General Public License from time to time. Such new
6159 versions will be similar in spirit to the present version, but may differ
6160 in detail to address new problems or concerns.</p>
6161
6162<p>Each version is given a distinguishing version number. If the
6163 Program specifies that a certain numbered version of the GNU Affero
6164 General Public License "or any later version" applies to it, you have
6165 the option of following the terms and conditions either of that
6166 numbered version or of any later version published by the Free
6167 Software Foundation. If the Program does not specify a version number
6168 of the GNU Affero General Public License, you may choose any version
6169 ever published by the Free Software Foundation.</p>
6170
6171<p>If the Program specifies that a proxy can decide which future
6172 versions of the GNU Affero General Public License can be used, that
6173 proxy's public statement of acceptance of a version permanently
6174 authorizes you to choose that version for the Program.</p>
6175
6176<p>Later license versions may give you additional or different
6177 permissions. However, no additional obligations are imposed on any
6178 author or copyright holder as a result of your choosing to follow a
6179 later version.</p>
6180
6181<h4><a name="section15"></a>15. Disclaimer of Warranty.</h4>
6182
6183<p>THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
6184 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
6185 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
6186 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
6187 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
6188 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
6189 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
6190 ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</p>
6191
6192<h4><a name="section16"></a>16. Limitation of Liability.</h4>
6193
6194<p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
6195 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
6196 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
6197 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
6198 USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
6199 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
6200 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
6201 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
6202 SUCH DAMAGES.</p>
6203
6204<h4><a name="section17"></a>17. Interpretation of Sections 15 and 16.</h4>
6205
6206<p>If the disclaimer of warranty and limitation of liability provided
6207 above cannot be given local legal effect according to their terms,
6208 reviewing courts shall apply local law that most closely approximates
6209 an absolute waiver of all civil liability in connection with the
6210 Program, unless a warranty or assumption of liability accompanies a
6211 copy of the Program in return for a fee.</p>
6212
6213<p>END OF TERMS AND CONDITIONS</p>
6214
6215<h3><a name="howto"></a>How to Apply These Terms to Your New Programs</h3>
6216
6217<p>If you develop a new program, and you want it to be of the greatest
6218 possible use to the public, the best way to achieve this is to make it
6219 free software which everyone can redistribute and change under these terms.</p>
6220
6221<p>To do so, attach the following notices to the program. It is safest
6222 to attach them to the start of each source file to most effectively
6223 state the exclusion of warranty; and each file should have at least
6224 the "copyright" line and a pointer to where the full notice is found.</p>
6225
6226<pre> <one line to give the program's name and a brief idea of what it does.>
6227 Copyright (C) <year> <name of author>
6228
6229 This program is free software: you can redistribute it and/or modify
6230 it under the terms of the GNU Affero General Public License as
6231 published by the Free Software Foundation, either version 3 of the
6232 License, or (at your option) any later version.
6233
6234 This program is distributed in the hope that it will be useful,
6235 but WITHOUT ANY WARRANTY; without even the implied warranty of
6236 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6237 GNU Affero General Public License for more details.
6238
6239 You should have received a copy of the GNU Affero General Public License
6240 along with this program. If not, see <http://www.gnu.org/licenses/>.
6241</pre>
6242
6243<p>Also add information on how to contact you by electronic and paper mail.</p>
6244
6245<p>If your software can interact with users remotely through a computer
6246 network, you should also make sure that it provides a way for users to
6247 get its source. For example, if your program is a web application, its
6248 interface could display a "Source" link that leads users to an archive
6249 of the code. There are many ways you could offer source, and different
6250 solutions will be better for different programs; see section 13 for the
6251 specific requirements.</p>
6252
6253<p>You should also get your employer (if you work as a programmer) or school,
6254 if any, to sign a "copyright disclaimer" for the program, if necessary.
6255 For more information on this, and how to apply and follow the GNU AGPL, see
6256 <<a href="http://www.gnu.org/licenses/" target="_blank" rel="noreferrer noopener">http://www.gnu.org/licenses/</a>>.</p>
6257 </div>
6258
6259
6260
6261
6262
6263
6264 <div id="about_thirdparty"
6265
6266 class="tab-pane "
6267
6268 >
6269 <h3>Third Party Licenses</h3>
6270<h4>Web Interface</h4>
6271<ul>
6272<li><a href="https://gist.github.com/viking/2424106" target="_blank" rel="noreferrer noopener">AVLTree</a> (modified): GPL, LGPL (dual licensed)</li>
6273<li><a href="https://github.com/mitsuhiko/babel/blob/master/contrib/babel.js" target="_blank" rel="noreferrer noopener">Babel JavaScript Support</a>: BSD</li>
6274<li><a href="http://getbootstrap.com/" target="_blank" rel="noreferrer noopener">Bootstrap</a>: Apache License 2.0</li>
6275<li><a href="http://jschr.github.io/bootstrap-modal/" target="_blank" rel="noreferrer noopener">Bootstrap Modal</a>: Apache License 2.0</li>
6276<li><a href="https://github.com/cosminstefanxp/bootstrap-slider-knockout-binding" target="_blank" rel="noreferrer noopener">Bootstrap Slider Knockout Binding</a>: MIT</li>
6277<li><a href="http://seiyria.com/bootstrap-slider/" target="_blank" rel="noreferrer noopener">Bootstrap Slider</a>: Apache License 2.0</li>
6278<li><a href="http://www.eyecon.ro/bootstrap-tabdrop" target="_blank" rel="noreferrer noopener">Bootstrap Tabdrop</a>: Apache License 2.0</li>
6279<li><a href="https://github.com/marcj/css-element-queries" target="_blank" rel="noreferrer noopener">css-element-queries</a>: MIT</li>
6280<li><a href="http://detectmobilebrowsers.com/" target="_blank" rel="noreferrer noopener">Detect Mobile Browser</a>: Public Domain</li>
6281<li><a href="http://www.flotcharts.org/" target="_blank" rel="noreferrer noopener">Flot</a>: MIT</li>
6282<li><a href="https://github.com/blueimp/JavaScript-MD5" target="_blank" rel="noreferrer noopener">JavaScript MD5</a>: MIT</li>
6283<li><a href="http://jquery.com/" target="_blank" rel="noreferrer noopener">JQuery</a>: MIT</li>
6284<li><a href="http://github.com/VinceG/twitter-bootstrap-wizard" target="_blank" rel="noreferrer noopener">JQuery Bootstrap Wizard</a>: MIT, GPL (dual licensed)</li>
6285<li><a href="https://github.com/blueimp/jQuery-File-Upload" target="_blank" rel="noreferrer noopener">JQuery File Upload</a>: MIT</li>
6286<li><a href="https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js" target="_blank" rel="noreferrer noopener">JQuery iframe transport</a>: MIT</li>
6287<li><a href="http://larsjung.de/jquery-qrcode/" target="_blank" rel="noreferrer noopener">JQuery QRCode</a>: MIT</li>
6288<li><a href="http://rocha.la/jQuery-slimScroll" target="_blank" rel="noreferrer noopener">JQuery Slimscroll</a>: MIT, GPL (dual licensed)</li>
6289<li><a href="http://jqueryui.com" target="_blank" rel="noreferrer noopener">JQuery UI Core, Mouse, Slider and Widget</a>: MIT</li>
6290<li><a href="http://knockoutjs.com/" target="_blank" rel="noreferrer noopener">Knockout</a>: MIT</li>
6291<li><a href="http://lesscss.org" target="_blank" rel="noreferrer noopener">LESS</a>: Apache License 2.0</li>
6292<li><a href="https://lodash.com" target="_blank" rel="noreferrer noopener">lodash</a>: MIT</li>
6293<li><a href="https://github.com/pimterry/loglevel" target="_blank" rel="noreferrer noopener">Loglevel</a>: MIT</li>
6294<li><a href="http://modernizr.com" target="_blank" rel="noreferrer noopener">Modernizr</a>: MIT</li>
6295<li><a href="http://momentjs.com/" target="_blank" rel="noreferrer noopener">Moment.js</a>: MIT</li>
6296<li><a href="http://sciactive.com/pnotify/" target="_blank" rel="noreferrer noopener">PNotify</a>: GPL, LGPL, MPL (triple licensed)</li>
6297<li><a href="http://cache.preserve.io/5g18q0pw/index.html" target="_blank" rel="noreferrer noopener">pusher.color.js</a> (original link dead): MIT</li>
6298<li><a href="https://github.com/sockjs/sockjs-client" target="_blank" rel="noreferrer noopener">SockJS</a>: MIT</li>
6299<li><a href="http://alexei.ro/" target="_blank" rel="noreferrer noopener">sprintf-js</a>: BSD</li>
6300</ul>
6301<h4>Server</h4>
6302<ul>
6303<li><a href="http://github.com/ActiveState/appdirs" target="_blank" rel="noreferrer noopener">appdirs</a>: MIT</li>
6304<li><a href="https://pypi.python.org/pypi/awesome-slugify" target="_blank" rel="noreferrer noopener">Awesome-Slugify</a>: GPLv3</li>
6305<li><a href="https://bitbucket.org/jeunice/chainmap" target="_blank" rel="noreferrer noopener">chainmap</a>: Python</li>
6306<li><a href="http://click.pocoo.org/" target="_blank" rel="noreferrer noopener">Click</a>: BSD</li>
6307<li><a href="https://github.com/carpedm20/emoji/" target="_blank" rel="noreferrer noopener">emoji</a>: BSD</li>
6308<li><a href="https://github.com/kurtmckee/feedparser" target="_blank" rel="noreferrer noopener">feedparser</a>: BSD</li>
6309<li><a href="http://flask.pocoo.org/" target="_blank" rel="noreferrer noopener">Flask</a>: BSD</li>
6310<li><a href="http://github.com/miracle2k/flask-assets" target="_blank" rel="noreferrer noopener">Flask-Assets</a>: BSD</li>
6311<li><a href="http://github.com/mitsuhiko/flask-babel" target="_blank" rel="noreferrer noopener">Flask-Babel</a>: BSD</li>
6312<li><a href="https://github.com/maxcountryman/flask-login" target="_blank" rel="noreferrer noopener">Flask-Login</a>: MIT</li>
6313<li><a href="http://github.com/dcolish/flask-markdown" target="_blank" rel="noreferrer noopener">Flask-Markdown</a>: BSD</li>
6314<li><a href="http://packages.python.org/Flask-Principal/" target="_blank" rel="noreferrer noopener">Flask-Principal</a>: MIT</li>
6315<li><a href="https://python-future.org/" target="_blank" rel="noreferrer noopener">future</a>: MIT</li>
6316<li><a href="https://github.com/agronholm/pythonfutures" target="_blank" rel="noreferrer noopener">futures</a>: Python</li>
6317<li><a href="https://github.com/atdt/monotonic" target="_blank" rel="noreferrer noopener">monotonic</a>: Apache License 2.0</li>
6318<li><a href="https://github.com/drkjam/netaddr/" target="_blank" rel="noreferrer noopener">netaddr</a>: BSD</li>
6319<li><a href="https://bitbucket.org/al45tair/netifaces" target="_blank" rel="noreferrer noopener">netifaces</a>: MIT</li>
6320<li><a href="http://pypi.python.org/pypi/pkginfo/" target="_blank" rel="noreferrer noopener">pkginfo</a>: Python</li>
6321<li><a href="https://github.com/giampaolo/psutil" target="_blank" rel="noreferrer noopener">psutil</a>: BSD</li>
6322<li><a href="https://github.com/jlhutch/pylru" target="_blank" rel="noreferrer noopener">pylru</a>: GPLv2</li>
6323<li><a href="http://pyserial.sourceforge.net/" target="_blank" rel="noreferrer noopener">pyserial</a>: Python</li>
6324<li><a href="http://pyyaml.org/wiki/PyYAML" target="_blank" rel="noreferrer noopener">PyYAML</a>: MIT</li>
6325<li><a href="http://python-requests.org/" target="_blank" rel="noreferrer noopener">requests</a>: Apache License 2.0</li>
6326<li><a href="http://stuvel.eu/rsa" target="_blank" rel="noreferrer noopener">rsa</a>: Apache License 2.0</li>
6327<li><a href="http://sarge.readthedocs.org/" target="_blank" rel="noreferrer noopener">sarge</a>: BSD</li>
6328<li><a href="https://github.com/benhoyt/scandir" target="_blank" rel="noreferrer noopener">scandir</a>: BSD</li>
6329<li><a href="https://github.com/rbarrois/python-semanticversion" target="_blank" rel="noreferrer noopener">semantic_version</a>: BSD</li>
6330<li><a href="http://github.com/mrjoes/sockjs-tornado/" target="_blank" rel="noreferrer noopener">SockJS-Tornado</a>: MIT</li>
6331<li><a href="http://www.tornadoweb.org/" target="_blank" rel="noreferrer noopener">Tornado</a>: Apache License 2.0</li>
6332<li><a href="http://github.com/gorakhargosh/watchdog" target="_blank" rel="noreferrer noopener">watchdog</a>: Apache License 2.0</li>
6333<li><a href="https://github.com/liris/websocket-client" target="_blank" rel="noreferrer noopener">websocket-client</a>: LGPLv3</li>
6334<li><a href="http://wrapt.readthedocs.org/" target="_blank" rel="noreferrer noopener">wrapt</a>: BSD</li>
6335</ul>
6336<h4>Development (testing, documentation generation, etc)</h4>
6337<ul>
6338<li><a href="https://github.com/txels/ddt" target="_blank" rel="noreferrer noopener">ddt</a>: MIT</li>
6339<li><a href="https://github.com/testing-cabal/mock" target="_blank" rel="noreferrer noopener">mock</a>: BSD</li>
6340<li><a href="http://pythonhosted.org/nose/" target="_blank" rel="noreferrer noopener">nose</a>: LGPL</li>
6341<li><a href="http://sphinx-doc.org/" target="_blank" rel="noreferrer noopener">Sphinx</a>: BSD</li>
6342<li><a href="https://bitbucket.org/birkenfeld/sphinx-contrib/src/default/httpdomain/" target="_blank" rel="noreferrer noopener">sphinxcontrib-httpdomain</a>: BSD</li>
6343<li><a href="https://github.com/mgaitan/sphinxcontrib-mermaid" target="_blank" rel="noreferrer noopener">sphinxcontrib-mermad</a>: BSD</li>
6344<li><a href="https://github.com/snide/sphinx_rtd_theme/" target="_blank" rel="noreferrer noopener">sphinx_rtd_theme</a>: BSD</li>
6345</ul>
6346 </div>
6347
6348
6349
6350
6351
6352 <!-- ko allowBindings: false -->
6353 <div id="about_plugin_pluginmanager"
6354 data-bind="allowBindings: true"
6355 class="tab-pane "
6356
6357 >
6358 <h3>Plugin Licenses</h3>
6359
6360<ul>
6361
6362</ul>
6363
6364
6365 </div>
6366 <!-- /ko -->
6367
6368
6369 </div>
6370 </div>
6371 </div>
6372 </div>
6373 <div class="modal-footer">
6374 <button class="btn btn-block" data-dismiss="modal" aria-hidden="true">Close</button>
6375 </div>
6376</div>
6377 <div id="add_folder_dialog" class="modal hide fade">
6378 <div class="modal-header">
6379 <a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
6380 <h3>Create Folder</h3>
6381 </div>
6382 <div class="modal-body">
6383 <p>Please specify the name of the folder to create.</p>
6384 <form class="form-horizontal" action="javascript:void(0)">
6385 <div class="control-group">
6386 <label class="control-label">Folder name</label>
6387 <div class="controls">
6388 <input type="text" data-bind="value: addFolderName, valueUpdate: 'afterkeydown'">
6389 </div>
6390 </div>
6391 </form>
6392 </div>
6393 <div class="modal-footer">
6394 <a href="#" class="btn" data-dismiss="modal" aria-hidden="true">Cancel</a>
6395 <a href="#" class="btn btn-primary" data-bind="click: function() { if ($root.enableAddFolder()) { $root.addFolder() } }, enabled: $root.enableAddFolder(), css: {disabled: !$root.enableAddFolder()}"><i class="fa fa-spinner fa-spin" data-bind="visible: addingFolder"></i> Create</a>
6396 </div>
6397</div>
6398 <div id="change_offset_dialog" class="modal hide fade">
6399 <div class="modal-header">
6400 <a href="javascript:void(0)" class="close" data-dismiss="modal" aria-hidden="true">×</a>
6401 <h3 data-bind="text: changingOffset.title"></h3>
6402 </div>
6403 <div class="modal-body">
6404 <p data-bind="text: changingOffset.description"></p>
6405 <form class="form-horizontal" data-bind="submit: confirmChangeOffset">
6406 <div class="control-group">
6407 <label class="control-label">Current Offset</label>
6408 <div class="controls">
6409 <label class="control-text" data-bind="html: changingOffset.offset() + ' °C'"></label>
6410 </div>
6411 </div>
6412 <div class="control-group">
6413 <label class="control-label">New Offset</label>
6414 <div class="controls">
6415 <div class="input-prepend input-append">
6416 <button type="button" class="btn btn-input-dec" data-bind="click: $root.decrementChangeOffset" title="-1"><i class="fa fa-minus"></i></button>
6417 <input type="number" min="-50" max="50" class="input-mini input-nospin" style="width: 30px" data-bind="value: changingOffset.newOffset, event: { focus: function(d, e) {$root.handleFocus(e, 'target', changingOffset.item);}, keyup: function(d, e) {$root.handleEnter(e, 'offset', changingOffset.item);} }">
6418 <span class="add-on">°C</span>
6419 <button type="button" class="btn btn-input-inc" data-bind="click: $root.incrementChangeOffset" title="+1"><i class="fa fa-plus"></i></button>
6420 </div>
6421 <button type="button" class="btn" data-bind="click: $root.deleteChangeOffset" title="Delete Offset"><i class="fa fa-trash"></i></button>
6422 <span class="help-block">Hint: Hitting <kbd>Enter</kbd> in the input field will also submit the form</span>
6423 </div>
6424 </div>
6425 </form>
6426 </div>
6427 <div class="modal-footer">
6428 <a href="javascript:void(0)" class="btn" data-dismiss="modal" aria-hidden="true">Cancel</a>
6429 <a href="javascript:void(0)" class="btn btn-primary" data-bind="click: confirmChangeOffset">Save</a>
6430 </div>
6431</div>
6432 <!-- End of dialogs -->
6433
6434 <!-- Overlays -->
6435 <div id="drop_overlay" data-bind="visible: loginState.hasPermissionKo(access.permissions.FILES_UPLOAD)">
6436 <div id="drop_overlay_background"></div>
6437 <div id="drop_overlay_wrapper">
6438
6439 <div class="dropzone" id="drop_locally"><span class="text"><i class="fa fa-upload"></i><br>Upload locally</span></div>
6440 <div class="dropzone_background" id="drop_locally_background"></div>
6441 <div class="dropzone" id="drop_sd"><span class="text"><i class="fa fa-upload"></i><br>Upload to SD<br><small data-bind="visible: isSdReady() && isPrinting()">(Cannot upload to printer's SD while printing)</small><small data-bind="visible: !isSdReady()">(SD not initialized)</small></span></div>
6442 <div class="dropzone_background" id="drop_sd_background"></div>
6443
6444 </div>
6445</div>
6446 <div id="offline_overlay">
6447 <div id="offline_overlay_background"></div>
6448 <div id="offline_overlay_wrapper">
6449 <div class="container">
6450 <div class="hero-unit">
6451 <h1 id="offline_overlay_title">Server is offline</h1>
6452 <p id="offline_overlay_message"></p>
6453 <p>
6454 <a class="btn btn-primary btn-large" id="offline_overlay_reconnect">Attempt to reconnect</a>
6455 </p>
6456 </div>
6457 </div>
6458 </div>
6459</div>
6460 <div id="reloadui_overlay">
6461 <div id="reloadui_overlay_background"></div>
6462 <div id="reloadui_overlay_wrapper">
6463 <div class="container">
6464 <div class="hero-unit">
6465 <h1>Please reload</h1>
6466 <p>
6467 There is a new version of the server active now, a reload
6468 of the user interface is needed. This will not interrupt
6469 any print jobs you might have ongoing. Please reload the
6470 web interface now by clicking the button below.
6471 </p>
6472 <p>
6473 <button class="btn btn-primary btn-large" title="Reload now" onclick="var event = arguments[0] || window.event; var source = event.target || event.srcElement; if (source.disabled) return; source.disabled = true; source.className += ' disabled'; source.firstChild.style.display = ''; location.reload(true); return false;"><i class="fa fa-spinner fa-spin" style="display: none"></i> Reload now</button>
6474 </p>
6475 </div>
6476 </div>
6477 </div>
6478</div>
6479 <!-- End of overlays -->
6480
6481 <script type="text/javascript" src="/static/webassets/packed_libs.js?3339d949"></script>
6482<script type="text/javascript" src="/static/webassets/packed_client.js?92e73cbf"></script>
6483
6484<script type="text/javascript" src="/static/webassets/packed_core.js?bfdd4fa0"></script>
6485<script type="text/javascript" src="/i18n/en/messages.js"></script>
6486
6487 <!-- Generic plugin template files -->
6488
6489
6490 <script type="text/javascript">
6491 var ERRORTRACKING_ENABLED = false;
6492
6493 var ERRORTRACKING_ENABLE = function() {
6494 var errortracking_url_coreui = "https://1da95af9c999483ba5705577f24d1e28@sentry.io/1374096";
6495 var errortracking_unique_id = "6fdc2098-95f1-4c8c-8411-3c51c3b373ae";
6496
6497 Sentry.init({
6498 dsn: errortracking_url_coreui,
6499 release: VERSION,
6500 whitelistUrls: [
6501 // only include static assets
6502 "/static/"
6503 ],
6504 blacklistUrls: [
6505 // exclude third party plugins
6506 "/static/webassets/packed_plugins.js"
6507 ]
6508 });
6509 Sentry.configureScope(function (scope) {
6510 scope.setUser({"id": errortracking_unique_id});
6511 });
6512 ERRORTRACKING_ENABLED = true;
6513 log.info("Initialized error tracking");
6514 };
6515
6516 $(function() {
6517 if (ERRORTRACKING_ENABLED) {
6518 ERRORTRACKING_ENABLE();
6519 }
6520 });
6521</script>
6522
6523
6524 <div id="plugin_announcements_dialog" class="modal hide fade large" tabindex="-1" role="dialog" aria-labelledby="announcements_dialog_label" aria-hidden="true">
6525 <div class="modal-header">
6526 <button type="button" class="close" data-dismiss="modal">×</button>
6527 <h3 id="announcements_dialog_label">Announcements</h3>
6528 </div>
6529 <div class="modal-body">
6530 <div class="full-sized-box">
6531 <div class="tabbable row-fluid">
6532 <div class="span3 scrollable" id="plugin_announcements_dialog_menu">
6533 <ul class="nav nav-list" id="plugin_announcements_dialog_tabs">
6534 <!-- ko foreach: {data: channels.items, afterAdd: setupTabLink} -->
6535 <!-- ko if: $data.enabled || $data.forced -->
6536 <li>
6537 <a data-toggle="tab" target="_blank" data-bind="text: $data.channel, attr: {href: '#plugin_announcements_dialog_channel_' + $data.key, title: $data.description}, css: {unread: $data.unread}"></a>
6538 </li>
6539 <!-- /ko -->
6540 <!-- /ko -->
6541 </ul>
6542 </div>
6543 <div class="tab-content span9 scrollable" id="plugin_announcements_dialog_content">
6544 <!-- ko foreach: channels.items -->
6545 <!-- ko if: $data.enabled || $data.forced -->
6546 <div class="tab-pane" data-bind="attr: {id: 'plugin_announcements_dialog_channel_' + $data.key}">
6547 <!-- ko foreach: $data.data -->
6548 <article data-bind="css: {read: $data.read}">
6549 <hr data-bind="visible: $index() > 0">
6550 <h3><a data-bind="text: $data.title, attr: {href: $data.link}" target="_blank" rel="noreferrer noopener"></a> <small data-bind="text: formatTimeAgo($data.published), attr: {title: formatDate($data.published)}"></small></h3>
6551 <div class="content" data-bind="html: $data.summary"></div>
6552 <div class="actions">
6553 <span class="articlelink"><small><a data-bind="text: $root.cleanedLink($data), attr: {href: $data.link}" target="_blank" rel="noreferrer noopener"></a></small></span>
6554 <span class="markread"><small><a href="javascript:void(0)" data-bind="click: function() { $root.markRead($parent.key, $data.published, true) }"><i class="fa fa-eye"></i> Mark as last read</a></small></span>
6555 </div>
6556 </article>
6557 <!-- /ko -->
6558 </div>
6559 <!-- /ko -->
6560 <!-- /ko -->
6561 </div>
6562 </div>
6563 </div>
6564 </div>
6565 <div class="modal-footer">
6566 <button class="btn configurelink" data-bind="click: configureAnnouncements"><i class="fa fa-wrench"></i></button>
6567 <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
6568 </div>
6569</div>
6570
6571 <!-- End of generic plugin template files -->
6572 <!-- /ko -->
6573 </div>
6574
6575 </body>
6576</html>