Node-Red configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ui_chart.html 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. <style>
  2. #ui-chart-colors input[type="color"] {
  3. font-weight: bold;
  4. }
  5. #ui-chart-colors input[type="color"]::-webkit-color-swatch,
  6. #ui-chart-colors input[type="color"]::-moz-color-swatch {
  7. border: none;
  8. }
  9. .node-chart-properties {
  10. display: inline-flex;
  11. align-items: center;
  12. width: 70%;
  13. gap: 16px;
  14. flex-wrap: wrap;
  15. }
  16. .node-chart-properties .red-ui-typedInput-container {
  17. flex-grow: 1;
  18. }
  19. .node-chart-property {
  20. display: flex;
  21. gap: 8px;
  22. align-items: center;
  23. flex-grow: 1;
  24. }
  25. .node-chart-property label {
  26. margin: 0;
  27. }
  28. .node-chart-property#node-container-category {
  29. width: 100%;
  30. }
  31. </style>
  32. <script type="text/javascript">
  33. (function () {
  34. const l8n = function (property) {
  35. return RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.' + property)
  36. }
  37. const noneType = { value: 'none', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.none'), hasValue: false }
  38. const propertyType = { value: 'property', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.key') }
  39. function hexToRgb (hex) {
  40. const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  41. return result
  42. ? {
  43. r: parseInt(result[1], 16),
  44. g: parseInt(result[2], 16),
  45. b: parseInt(result[3], 16)
  46. }
  47. : null
  48. }
  49. function getSeriesTypes (xAxisType) {
  50. if (xAxisType === 'category') {
  51. return [noneType, 'msg', 'str', 'json', propertyType]
  52. } else {
  53. return [noneType, 'msg', 'str', 'json', propertyType]
  54. }
  55. }
  56. RED.nodes.registerType('ui-chart', {
  57. category: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.label.category'),
  58. color: RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.colors.medium'),
  59. defaults: {
  60. group: { type: 'ui-group', required: true },
  61. name: { value: '' },
  62. label: { value: 'chart' },
  63. order: { value: Number.MAX_SAFE_INTEGER },
  64. chartType: { value: 'line' },
  65. category: { value: 'topic' },
  66. categoryType: { value: 'msg' },
  67. xAxisLabel: { value: '' },
  68. xAxisProperty: { value: null },
  69. xAxisPropertyType: { value: 'property' },
  70. xAxisType: { value: 'time' },
  71. xAxisFormat: { value: '' },
  72. xAxisFormatType: { value: 'auto' },
  73. yAxisLabel: { value: '' },
  74. yAxisProperty: { value: null },
  75. ymin: { value: '', validate: function (value) { return value === '' || RED.validators.number() } },
  76. ymax: { value: '', validate: function (value) { return value === '' || RED.validators.number() } },
  77. action: { value: 'append' },
  78. stackSeries: { value: false },
  79. pointShape: { value: 'circle' },
  80. pointRadius: { value: 4 },
  81. showLegend: { value: true },
  82. removeOlder: { value: 1, validate: RED.validators.number(), required: true },
  83. removeOlderUnit: { value: '3600', required: true },
  84. removeOlderPoints: { value: '', validate: function (value) { return value === '' || RED.validators.number() } },
  85. colors: { value: ['#0095FF', '#FF0000', '#FF7F0E', '#2CA02C', '#A347E1', '#D62728', '#FF9896', '#9467BD', '#C5B0D5'] },
  86. textColor: { value: ['#666666'] },
  87. textColorDefault: { value: true },
  88. gridColor: { value: ['#e5e5e5'] },
  89. gridColorDefault: { value: true },
  90. width: {
  91. value: 6,
  92. validate: function (v) {
  93. const width = v || 0
  94. const currentGroup = $('#node-input-group').val() || this.group
  95. const groupNode = RED.nodes.node(currentGroup)
  96. const valid = !groupNode || +width <= +groupNode.width
  97. $('#node-input-size').toggleClass('input-error', !valid)
  98. return valid
  99. }
  100. },
  101. height: { value: 8 },
  102. className: { value: '' }
  103. },
  104. inputs: 1,
  105. outputs: 1,
  106. inputLabels: function () { return this.chartType },
  107. outputLabels: ['chart state'],
  108. icon: 'font-awesome/fa-line-chart',
  109. align: 'right',
  110. paletteLabel: 'chart',
  111. label: function () {
  112. return this.name || (~this.label.indexOf('{' + '{') ? null : this.label) || this.mode + ' chart'
  113. },
  114. labelStyle: function () { return this.name ? 'node_label_italic' : '' },
  115. oneditprepare: function () {
  116. const node = this
  117. // add "Clear History" button
  118. const clearHistoryBtn = $('<button>')
  119. .attr('class', 'ui-button ui-corner-all ui-widget leftButton')
  120. .attr('id', 'node-dialog-clear-history')
  121. .text('Clear Chart History')
  122. .on('click', () => {
  123. // call the HTTP Admin Endpoint
  124. $.ajax({
  125. url: `dashboard/chart/${node.id}/clear`,
  126. type: 'POST',
  127. success: (data) => {
  128. RED.notify(l8n('notifications.clearSuccess'), { type: 'success' })
  129. },
  130. error: (xhr, status, error) => {
  131. RED.notify(node._('common.notification.error', { message: 'Unable to clear chart history' }), 'error')
  132. }
  133. })
  134. })
  135. $('.red-ui-tray-toolbar').append(clearHistoryBtn)
  136. // if this groups parent is a subflow template, set the node-config-input-width and node-config-input-height up
  137. // as typedInputs and hide the elementSizer (as it doesn't make sense for subflow templates)
  138. if (RED.nodes.subflow(this.z)) {
  139. // change inputs from hidden to text & display them
  140. $('#node-input-width').attr('type', 'text')
  141. $('#node-input-height').attr('type', 'text')
  142. $('div.form-row.nr-db-ui-element-sizer-row').hide()
  143. $('div.form-row.nr-db-ui-manual-size-row').show()
  144. } else {
  145. // not in a subflow, use the elementSizer
  146. $('div.form-row.nr-db-ui-element-sizer-row').show()
  147. $('div.form-row.nr-db-ui-manual-size-row').hide()
  148. $('#node-input-size').elementSizer({
  149. width: '#node-input-width',
  150. height: '#node-input-height',
  151. group: '#node-input-group'
  152. })
  153. }
  154. // use jQuery UI tooltip to convert the plain old title attribute to a nice tooltip
  155. $('.ui-node-popover-title').tooltip({
  156. show: {
  157. effect: 'slideDown',
  158. delay: 150
  159. }
  160. })
  161. // Allowable "X-Axis Type" choices for chart type
  162. // line : time, linear
  163. // bar : categorical (or just hide)
  164. // scatter : time, linear
  165. // pie : radial
  166. // doughnut : radial
  167. // handle event when x axis type is changed
  168. $('#node-input-xAxisType').on('change', (evt) => {
  169. const value = $('#node-input-xAxisType').val()
  170. if (value === 'time') {
  171. $('#x-axis-format').show()
  172. } else {
  173. $('#x-axis-format').hide()
  174. }
  175. if (value === 'radial') {
  176. // hide irrelevant fields
  177. $('#node-container-xAxisLabel').hide()
  178. $('#node-container-yAxisLabel').hide()
  179. $('#y-axis-show').hide()
  180. } else {
  181. // make sure they're shown
  182. $('#node-container-xAxisLabel').show()
  183. $('#node-container-yAxisLabel').show()
  184. $('#y-axis-show').show()
  185. }
  186. // update the series types allowed
  187. $('#node-input-category').typedInput('types', getSeriesTypes(value))
  188. })
  189. $('#node-input-xAxisFormat').typedInput({
  190. default: 'auto',
  191. typeField: $('#node-input-xAxisFormatType'),
  192. types: [
  193. { value: 'HH:mm:ss', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.HHmmss'), hasValue: false },
  194. { value: 'HH:mm', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.HHmm'), hasValue: false },
  195. { value: 'y-L-d', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.yLd'), hasValue: false },
  196. { value: 'd/L', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.dL'), hasValue: false },
  197. { value: 'ccc HH:mm', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.cccHHmm'), hasValue: false },
  198. { value: 'custom', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.custom'), icon: 'fa fa-font' },
  199. { value: 'auto', label: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.auto'), hasValue: false }
  200. ]
  201. })
  202. $('#node-input-category').typedInput({
  203. default: 'msg',
  204. typeField: $('#node-input-categoryType'),
  205. types: getSeriesTypes($('#node-input-xAxisType').val())
  206. })
  207. $('#node-input-xAxisProperty').typedInput({
  208. default: propertyType.value,
  209. typeField: $('#node-input-xAxisPropertyType'),
  210. types: ['msg', 'str', propertyType]
  211. })
  212. $('#node-input-yAxisProperty').typedInput({
  213. default: propertyType.value,
  214. typeField: $('#node-input-yAxisPropertyType'),
  215. types: [propertyType]
  216. })
  217. const updateXAxisTypeOptions = function (options, defaultValue) {
  218. const $el = $('#node-input-xAxisType')
  219. const currentValue = $el.val() || node.xAxisType
  220. const allOptions = [
  221. { value: 'time', text: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.timescale') },
  222. { value: 'linear', text: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.linear') },
  223. { value: 'radial', text: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.radial') },
  224. { value: 'category', text: RED._('@flowfuse/node-red-dashboard/ui-chart:ui-chart.label.categorical') }
  225. ]
  226. const theseOptions = allOptions.filter((option) => options.indexOf(option.value) !== -1)
  227. $el.css('pointer-events', 'none') // temporarily inhibit events
  228. $el.empty()
  229. theseOptions.forEach((option) => {
  230. $el.append($('<option>', option))
  231. })
  232. // set the value to the current value if it's still valid otherwise set to default/first option
  233. if (theseOptions.find((option) => option.value === currentValue)) {
  234. $el.val(currentValue)
  235. } else if (defaultValue && theseOptions.find((option) => option.value === defaultValue)) {
  236. $el.val(defaultValue)
  237. } else if (theseOptions.length > 0) {
  238. $el.val(theseOptions[0].value)
  239. } else {
  240. $el.val('')
  241. }
  242. $el.css('pointer-events', '') // remove the inhibition
  243. $el.trigger('change') // trigger the change event to update the UI
  244. }
  245. // handle event when chart's type is changed
  246. $('#node-input-chartType').on('change', (evt) => {
  247. const value = $(evt.target).val()
  248. if (value === 'line' || value === 'scatter') {
  249. // for line and scatter
  250. // types - time, linear
  251. updateXAxisTypeOptions(['time', 'linear'], 'time')
  252. // no concept of stacking in line/scatter charts
  253. $('#config-stackSeries').hide()
  254. // show x-axis limit options & points sizing
  255. $('#x-axis-show').show()
  256. $('#point-radius-show').show()
  257. } else if (value === 'pie' || value === 'doughnut') {
  258. // for pie/doughnut
  259. // types - radial
  260. updateXAxisTypeOptions(['radial'], 'radial')
  261. // no stacking options in pie/doughnut charts
  262. $('#config-stackSeries').hide()
  263. // hide x-axis limit options & points sizing
  264. $('#x-axis-show').hide()
  265. $('#point-radius-show').hide()
  266. } else if (value === 'bar') {
  267. // for bar
  268. // types - categorical
  269. updateXAxisTypeOptions(['category'], 'category')
  270. // show the ability to control if content is stacked or not
  271. $('#config-stackSeries').show()
  272. // hide x-axis limit options & points sizing
  273. $('#x-axis-show').hide()
  274. $('#point-radius-show').hide()
  275. }
  276. })
  277. // handle event when chart's type is changed
  278. $('#node-input-category').change((evt) => {
  279. const categoryType = $(evt.target).val()
  280. if (categoryType === 'json') {
  281. // hide y-axis property setting as category will now control that
  282. $('#node-container-yAxisProperty').hide()
  283. } else {
  284. $('#node-container-yAxisProperty').show()
  285. }
  286. })
  287. // ensure the xAxis PropertyType isn't an invalid value
  288. if (this.xAxisPropertyType === 'msg' && this.xAxisProperty === '') {
  289. // auto-fix it for the user
  290. this.xAxisPropertyType = propertyType.value
  291. $('#node-input-xAxisProperty').typedInput('type', propertyType.value)
  292. }
  293. // Stack/Group-By Options - convert from bool to string values for <select>
  294. if (this.stackSeries === true) {
  295. $('#chart-input-stackSeries').val('true')
  296. } else {
  297. $('#chart-input-stackSeries').val('false')
  298. }
  299. // Series Color Pickers
  300. const setColor = function (id, value) {
  301. $(id).val(value)
  302. $(id).css('background-color', value)
  303. const rgb = hexToRgb(value)
  304. const level = ((rgb.r * 299) + (rgb.g * 587) + (rgb.b * 114)) / 1000
  305. const textColor = (level >= 128) ? '#111111' : '#eeeeee'
  306. $(id).css('color', textColor)
  307. }
  308. $('.series-color').on('change', function () {
  309. setColor('#' + $(this).attr('id'), $(this).val())
  310. })
  311. const defaultColors = ['#1F77B4', '#AEC7E8', '#FF7F0E', '#2CA02C', '#98DF8A', '#D62728', '#FF9896', '#9467BD', '#C5B0D5']
  312. if (this.colors) {
  313. for (let i = 0; i < this.colors.length; i++) {
  314. const value = this.colors[i] || defaultColors[i]
  315. setColor('#node-input-color' + (i + 1), value)
  316. }
  317. } else {
  318. for (let c = 0; c < defaultColors.length; c++) {
  319. setColor('#node-input-color' + (c + 1), defaultColors[c])
  320. }
  321. }
  322. if (this.textColor) {
  323. setColor('#node-chart-text-color', this.textColor[0])
  324. } else {
  325. setColor('#node-chart-text-color', '#666666')
  326. }
  327. if (this.gridColor) {
  328. setColor('#node-chart-grid-color', this.gridColor[0])
  329. } else {
  330. setColor('#node-chart-grid-color', '#e5e5e5')
  331. }
  332. if (this.textColorDefault || this.textColorDefault === undefined) {
  333. $('#node-chart-text-color').hide()
  334. }
  335. if (this.gridColorDefault || this.gridColorDefault === undefined) {
  336. $('#node-chart-grid-color').hide()
  337. }
  338. },
  339. oneditsave: function () {
  340. // Stack By - convert from string values to bool
  341. this.stackSeries = $('#chart-input-stackSeries').val() === 'true'
  342. // Colors
  343. const colors = []
  344. for (let i = 0; i < 9; i++) {
  345. const color = $('#node-input-color' + (i + 1)).val()
  346. if (color) {
  347. colors.push(color)
  348. }
  349. }
  350. this.colors = colors
  351. const textColor = []
  352. const color = $('#node-chart-text-color').val()
  353. if (color) {
  354. textColor.push(color)
  355. }
  356. this.textColor = textColor
  357. const gridColor = []
  358. const gcolor = $('#node-chart-grid-color').val()
  359. if (gcolor) {
  360. gridColor.push(gcolor)
  361. }
  362. this.gridColor = gridColor
  363. }
  364. })
  365. })()
  366. </script>
  367. <script type="text/html" data-template-name="ui-chart">
  368. <div class="form-row">
  369. <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
  370. <input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
  371. </div>
  372. <div class="form-row">
  373. <label for="node-input-group"><i class="fa fa-table"></i> <span data-i18n="ui-chart.label.group"></span></label>
  374. <input type="text" id="node-input-group">
  375. </div>
  376. <div class="form-row nr-db-ui-element-sizer-row">
  377. <label><i class="fa fa-object-group"></i> <span data-i18n="ui-chart-group.label.size"></label>
  378. <button class="editor-button" id="node-input-size"></button>
  379. </div>
  380. <div class="form-row nr-db-ui-manual-size-row">
  381. <label><i class="fa fa-arrows-h"></i> <span data-i18n="ui-chart-group.label.width">Width</label>
  382. <input type="hidden" id="node-input-width">
  383. </div>
  384. <div class="form-row nr-db-ui-manual-size-row">
  385. <label><i class="fa fa-arrows-v"></i> <span data-i18n="ui-chart-group.label.height">Height</label>
  386. <input type="hidden" id="node-input-height">
  387. </div>
  388. <div class="form-row">
  389. <label for="node-input-label"><i class="fa fa-i-cursor"></i> <span data-i18n="ui-chart.label.label"></span></label>
  390. <input type="text" id="node-input-label" data-i18n="[placeholder]ui-chart.label.optionalChartTitle">
  391. </div>
  392. <div class="form-row">
  393. <label for="node-input-className"><i class="fa fa-code"></i> <span data-i18n="ui-chart.label.class"></span></label>
  394. <div style="display: inline;">
  395. <input style="width: 70%;" type="text" id="node-input-className" data-i18n="[placeholder]ui-chart.label.optionalCssClassNames" style="flex-grow: 1;">
  396. <a
  397. data-html="true"
  398. title="Dynamic Property: Send msg.class to append new classes to this widget. NOTE: classes set at runtime will be applied in addition to any class(es) set in the nodes class field."
  399. class="red-ui-button ui-node-popover-title"
  400. style="margin-left: 4px; cursor: help; font-size: 0.625rem; border-radius: 50%; width: 24px; height: 24px; display: inline-flex; justify-content: center; align-items: center;">
  401. <i style="font-family: ui-serif;">fx</i>
  402. </a>
  403. </div>
  404. </div>
  405. <h4>Chart Configuration</h4>
  406. <div class="form-row" style="display: flex; align-items: center; gap: 36px;">
  407. <div>
  408. <label for="node-input-chartType"><i class="fa fa-bar-chart"></i> <span data-i18n="ui-chart.label.type"></span></label>
  409. <select id="node-input-chartType">
  410. <option value="line" data-i18n="ui-chart.label.line"></option>
  411. <option value="bar" data-i18n="ui-chart.label.bar"></option>
  412. <option value="scatter" data-i18n="ui-chart.label.scatter"></option>
  413. <option value="pie" data-i18n="ui-chart.label.pie"></option>
  414. <option value="doughnut" data-i18n="ui-chart.label.doughnut"></option>
  415. </select>
  416. </div>
  417. <div>
  418. <label style="width:auto" for="node-input-showLegend"><i class="fa fa-th-list"></i> <span data-i18n="ui-chart.label.showLegend"></span></label>
  419. <input type="checkbox" checked id="node-input-showLegend" style="display: inline-block; width: auto; margin: 0px 0px 0px 4px;">
  420. </div>
  421. </div>
  422. <div class="form-row" id="config-stackSeries">
  423. <!-- do not use node-input here to prevent NR automatic binding -->
  424. <label for="chart-input-stackSeries"><i class="fa fa-bookmark"></i> <span data-i18n="ui-chart.label.stackSeries"></span></label>
  425. <select id="chart-input-stackSeries">
  426. <option value="true" data-i18n="ui-chart.label.stackSeriesTrue"></option>
  427. <option value="false" data-i18n="ui-chart.label.stackSeriesFalse"></option>
  428. </select>
  429. </div>
  430. <div class="form-row">
  431. <label for="node-input-action" data-i18n="ui-chart.label.action"></label></label>
  432. <select id="node-input-action">
  433. <option value="append" data-i18n="ui-chart.label.append"></option>
  434. <option value="replace" data-i18n="ui-chart.label.replace"></option>
  435. </select>
  436. </div>
  437. <div class="form-row form-row-flex" id="point-radius-show">
  438. <label for="node-input-pointRadius" data-i18n="ui-chart.label.pointStyle"></label>
  439. <div style="display: flex; align-items: center; gap: 36px;">
  440. <div>
  441. <label for="node-input-pointShape" style="width: auto; display: none;" data-i18n="ui-chart.label.pointShape"></label>
  442. <select id="node-input-pointShape">
  443. <option value="circle" data-i18n="ui-chart.label.circle"></option>
  444. <option value="cross" data-i18n="ui-chart.label.cross"></option>
  445. <option value="crossRot" data-i18n="ui-chart.label.crossRotated"></option>
  446. <option value="dash" data-i18n="ui-chart.label.dash"></option>
  447. <option value="line" data-i18n="ui-chart.label.line2"></option>
  448. <option value="rect" data-i18n="ui-chart.label.rectangle"></option>
  449. <option value="rectRounded" data-i18n="ui-chart.label.roundedRectangle"></option>
  450. <option value="rectRot" data-i18n="ui-chart.label.rotatedRectangle"></option>
  451. <option value="star" data-i18n="ui-chart.label.star"></option>
  452. <option value="triangle" data-i18n="ui-chart.label.triangle"></option>
  453. <option value="false" data-i18n="ui-chart.label.none"></option>
  454. </select>
  455. </div>
  456. <div>
  457. <label for="node-input-pointRadius" style="width: auto;" data-i18n="ui-chart.label.pointRadius"></label>
  458. <input type="number" id="node-input-pointRadius">
  459. </div>
  460. </div>
  461. </div>
  462. <h4>Axis Configuration</h4>
  463. <div class="form-row">
  464. <label for="node-input-xAxisType" data-i18n="ui-chart.label.xType"></label></label>
  465. <select id="node-input-xAxisType"> </select>
  466. </div>
  467. <div class="form-row" id="x-axis-format">
  468. <label for="node-input-xAxisFormat" data-i18n="ui-chart.label.xFormat"></label></label>
  469. <input type="text" id="node-input-xAxisFormat">
  470. <input type="hidden" id="node-input-xAxisFormatType">
  471. </div>
  472. <div class="form-row" id="node-container-xAxisLabel">
  473. <label for="node-input-xAxisLabel" data-i18n="ui-chart.label.xLabel"></label></label>
  474. <input type="text" id="node-input-xAxisLabel">
  475. </div>
  476. <div class="form-row" id="x-axis-show">
  477. <label for="node-input-removeOlder" data-i18n="ui-chart.label.xLimit"></label>
  478. <label for="node-input-removeOlder" style="width:auto" data-i18n="ui-chart.label.last"></label>
  479. <input type="text" id="node-input-removeOlder" style="width:50px;">
  480. <select id="node-input-removeOlderUnit" style="width:100px;">
  481. <option value="1" data-i18n="ui-chart.label.seconds"></option>
  482. <option value="60" data-i18n="ui-chart.label.minutes"></option>
  483. <option value="3600" data-i18n="ui-chart.label.hours"></option>
  484. <option value="86400" data-i18n="ui-chart.label.days"></option>
  485. <option value="604800" data-i18n="ui-chart.label.weeks"></option>
  486. </select>
  487. <label for="node-input-removeOlderPoints" style="width:auto; margin-left:10px; margin-right:10px;" data-i18n="ui-chart.label.or"></label>
  488. <input type="text" id="node-input-removeOlderPoints" style="width:60px;" placeholder="1000">
  489. <span style="margin-left:5px;" data-i18n="ui-chart.label.points"></span>
  490. </div>
  491. <div class="form-row" id="node-container-yAxisLabel">
  492. <label for="node-input-yAxisLabel" data-i18n="ui-chart.label.yLabel"></label></label>
  493. <input type="text" id="node-input-yAxisLabel">
  494. </div>
  495. <div class="form-row" id="y-axis-show">
  496. <label id="y-label-show" for="node-input-ymin" data-i18n="ui-chart.label.yAxis"></label>
  497. <label for="node-input-ymin" style="width:auto" data-i18n="ui-chart.label.min"></label>
  498. <input type="text" id="node-input-ymin" style="width:92px">
  499. <label for="node-input-ymax" style="width:auto; margin-left:20px;" data-i18n="ui-chart.label.max"></label>
  500. <input type="text" id="node-input-ymax" style="width:92px">
  501. </div>
  502. <div class="form-row">
  503. <label data-i18n="ui-chart.label.properties"></label>
  504. <div id="node-container-axisKeys" class="node-chart-properties">
  505. <div id="node-container-category" class="node-chart-property">
  506. <label style="width: auto" for="node-input-category" data-i18n="ui-chart.label.series"></label>
  507. <input style="flex-grow: 1" type="text" id="node-input-category" placeholder="topic">
  508. <input type="hidden" id="node-input-categoryType">
  509. </div>
  510. <div id="node-container-xAxisProperty" class="node-chart-property">
  511. <label style="width: auto" for="node-input-xAxisProperty">X:</label>
  512. <input style="flex-grow: 1" type="text" id="node-input-xAxisProperty" data-i18n="[placeholder]ui-chart.label.propertyPlaceholder">
  513. <input type="hidden" id="node-input-xAxisPropertyType">
  514. </div>
  515. <div id="node-container-yAxisProperty" class="node-chart-property">
  516. <label style="width: auto" for="node-input-yAxisProperty">Y:</label>
  517. <input style="flex-grow: 1" type="text" id="node-input-yAxisProperty" data-i18n="[placeholder]ui-chart.label.propertyPlaceholder">
  518. </div>
  519. </div>
  520. </div>
  521. <h4>Styling/Colors</h4>
  522. <div class="form-row" id="ui-chart-colors">
  523. <label for="node-input-color1" data-i18n="ui-chart.label.seriesColors"></label>
  524. <input type="color" id="node-input-color1" class="series-color" style="width:100px;"/>
  525. <input type="color" id="node-input-color2" class="series-color" style="width:100px;"/>
  526. <input type="color" id="node-input-color3" class="series-color" style="width:100px;"/>
  527. <div style="margin-top:5px; margin-left:104px;">
  528. <input type="color" id="node-input-color4" class="series-color" style="width:100px;"/>
  529. <input type="color" id="node-input-color5" class="series-color" style="width:100px;"/>
  530. <input type="color" id="node-input-color6" class="series-color" style="width:100px;"/>
  531. </div>
  532. <div style="margin-top:5px; margin-left:104px;">
  533. <input type="color" id="node-input-color7" class="series-color" style="width:100px;"/>
  534. <input type="color" id="node-input-color8" class="series-color" style="width:100px;"/>
  535. <input type="color" id="node-input-color9" class="series-color" style="width:100px;"/>
  536. </div>
  537. </div>
  538. <div class="form-row" style="display: flex; align-items: center; gap: 36px; height: 34px;">
  539. <div>
  540. <label for="node-chart-text-color" data-i18n="ui-chart.label.textColor"></label>
  541. </div>
  542. <div>
  543. <input type="checkbox" checked id="node-input-textColorDefault" style="display: inline-block; width: auto; margin: 0px 0px 0px 4px;" onclick="this.checked ? $('#node-chart-text-color').hide(): $('#node-chart-text-color').show()">
  544. <label style="width:auto" for="node-input-textColorDefault"> <span data-i18n="ui-chart.label.setTextColorDefault"></span></label>
  545. </div>
  546. <div>
  547. <input type="color" id="node-chart-text-color" class="series-color" style="width:100px;"/>
  548. </div>
  549. </div>
  550. <div class="form-row" style="display: flex; align-items: center; gap: 36px; height: 34px;">
  551. <div>
  552. <label for="node-chart-grid-color" data-i18n="ui-chart.label.gridColor"></label>
  553. </div>
  554. <div>
  555. <input type="checkbox" checked id="node-input-gridColorDefault" style="display: inline-block; width: auto; margin: 0px 0px 0px 4px;" onclick="this.checked ? $('#node-chart-grid-color').hide() : $('#node-chart-grid-color').show()">
  556. <label style="width:auto" for="node-input-gridColorDefault"> <span data-i18n="ui-chart.label.setGridColorDefault"></span></label>
  557. </div>
  558. <div>
  559. <input type="color" id="node-chart-grid-color" class="series-color" style="width:100px;"/>
  560. </div>
  561. </div>
  562. </script>