diff options
| -rw-r--r-- | VERSION | 2 | ||||
| -rw-r--r-- | src_js/common.js | 3 | ||||
| -rw-r--r-- | src_js/states.js | 1 | ||||
| -rw-r--r-- | src_js/vt.js | 53 | ||||
| -rw-r--r-- | src_scss/_grid.scss | 53 | ||||
| -rw-r--r-- | src_scss/main.scss | 15 |
6 files changed, 58 insertions, 69 deletions
@@ -1 +1 @@ -0.3.0 +0.3.1 diff --git a/src_js/common.js b/src_js/common.js index 6e164f9..bf1327a 100644 --- a/src_js/common.js +++ b/src_js/common.js @@ -17,6 +17,7 @@ let itemCounter = 0; export async function calculate() { + r.set('calculating', true); try { const method = r.get('form', 'method'); const params = createCalculateParams(); @@ -35,6 +36,8 @@ export async function calculate() { showNotification('success', 'New calculation available'); } catch (e) { showNotification('error', e); + } finally { + r.set('calculating', false); } } diff --git a/src_js/states.js b/src_js/states.js index f55716f..a696007 100644 --- a/src_js/states.js +++ b/src_js/states.js @@ -11,6 +11,7 @@ export const main = { panel: null, item: null }, + calculating: false }; diff --git a/src_js/vt.js b/src_js/vt.js index 1dc467e..8320f75 100644 --- a/src_js/vt.js +++ b/src_js/vt.js @@ -59,15 +59,15 @@ function leftPanel() { ['span.fa.fa-github'] ] ], - ['div.group', + ['div.form', ['label', 'Method'], selectInput(r.get('form', 'method'), - ['forward_greedy', 'greedy'], - val => r.set(['form', 'method'], val)) - ], - ['div.group', + [['forward_greedy', 'Forward greedy'], + ['greedy', 'Greedy']], + val => r.set(['form', 'method'], val)), ['label', 'Cut width'], numberInput(r.get('form', 'cut_width'), + u.isNumber, val => r.set(['form', 'cut_width'], val)) ], ['div.content', @@ -75,6 +75,9 @@ function leftPanel() { leftPanelItems() ], ['button.calculate', { + props: { + disabled: r.get('calculating') + }, on: { click: common.calculate }}, @@ -87,6 +90,13 @@ function leftPanel() { function leftPanelPanels() { const panelsPath = ['form', 'panels']; + const panelNames = new Set(); + const nameValidator = name => { + const valid = !panelNames.has(name); + panelNames.add(name); + return valid; + } + return ['div', ['table', ['thead', @@ -103,24 +113,28 @@ function leftPanelPanels() { ['td.col-name', ['div', textInput(panel.name, + nameValidator, val => r.set([panelsPath, index, 'name'], val)) ] ], ['td.col-quantity', ['div', numberInput(panel.quantity, + u.isInteger, val => r.set([panelsPath, index, 'quantity'], val)) ] ], ['td.col-height', ['div', numberInput(panel.height, + u.isNumber, val => r.set([panelsPath, index, 'height'], val)) ] ], ['td.col-width', ['div', numberInput(panel.width, + u.isNumber, val => r.set([panelsPath, index, 'width'], val)) ] ], @@ -175,6 +189,13 @@ function leftPanelPanels() { function leftPanelItems() { const itemsPath = ['form', 'items']; + const itemNames = new Set(); + const nameValidator = name => { + const valid = !itemNames.has(name); + itemNames.add(name); + return valid; + } + return ['div', ['table', ['thead', @@ -192,24 +213,28 @@ function leftPanelItems() { ['td.col-name', ['div', textInput(item.name, + nameValidator, val => r.set([itemsPath, index, 'name'], val)) ] ], ['td.col-quantity', ['div', numberInput(item.quantity, + u.isInteger, val => r.set([itemsPath, index, 'quantity'], val)) ] ], ['td.col-height', ['div', numberInput(item.height, + u.isNumber, val => r.set([itemsPath, index, 'height'], val)) ] ], ['td.col-width', ['div', numberInput(item.width, + u.isNumber, val => r.set([itemsPath, index, 'width'], val)) ] ], @@ -415,12 +440,15 @@ function centerPanel() { } -function textInput(value, onChange) { +function textInput(value, validator, onChange) { return ['input', { props: { type: 'text', value: value }, + class: { + invalid: validator && !validator(value) + }, on: { change: evt => onChange(evt.target.value) } @@ -428,12 +456,16 @@ function textInput(value, onChange) { } -function numberInput(value, onChange) { +function numberInput(value, validator, onChange) { + return ['input', { props: { type: 'number', value: value }, + class: { + invalid: validator && !validator(value) + }, on: { change: evt => onChange(evt.target.valueAsNumber) } @@ -459,11 +491,12 @@ function selectInput(selected, values, onChange) { on: { change: evt => onChange(evt.target.value) }}, - values.map(i => ['option', { + values.map(([value, label]) => ['option', { props: { - selected: i == selected + selected: value == selected, + value: value }}, - i + label ]) ]; } diff --git a/src_scss/_grid.scss b/src_scss/_grid.scss deleted file mode 100644 index 68c9cb9..0000000 --- a/src_scss/_grid.scss +++ /dev/null @@ -1,53 +0,0 @@ -@import 'color';
-
-
-table.grid {
- table-layout: fixed;
- border-spacing: 0px;
- border: 1px solid $color-grey-400;
-
- td:not(:last-child) {
- border-right: 1px solid $color-grey-300;
- }
-
- thead tr, tfoot tr {
- background-color: $color-grey-200;
- }
-
- td, th {
- padding: 4px;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- tbody td {
- background-color: white;
- }
-
- tbody td, tfoot td {
- border-top: 1px solid $color-grey-400;
- }
-
- input {
- width: 100%;
- }
-
- input[type=text] {
- position: relative;
- border: 1px;
- font-size: 10pt;
- font-family: 'Roboto';
- }
-
- tfoot td > div {
- display: flex;
-
- & > .spacer {
- flex-grow: 1;
- }
- }
-
- .invalid {
- background-color: rgba(red, 0.2);
- }
-}
diff --git a/src_scss/main.scss b/src_scss/main.scss index 80cb0ab..ed40ab2 100644 --- a/src_scss/main.scss +++ b/src_scss/main.scss @@ -36,6 +36,10 @@ body { background-color: $color-grey-100; overflow: auto; + .invalid { + background-color: rgba(red, 0.3); + } + & > .header { flex-shrink: 0; margin: 1rem; @@ -63,12 +67,13 @@ body { } } - & > .group { - flex-shrink: 0; - display: flex; - flex-direction: column; + & > .form { + display: grid; + grid-template-columns: auto 1fr; + grid-column-gap: 0.5rem; + grid-row-gap: 0.3rem; + align-items: center; margin: 1rem; - margin-bottom: 0; } & > .content { |
