diff --git a/app/components/progress-bar.hbs b/app/components/progress-bar.hbs
new file mode 100644
index 00000000..e9220e79
--- /dev/null
+++ b/app/components/progress-bar.hbs
@@ -0,0 +1,51 @@
+
{{@task.title}}
diff --git a/app/components/task/holder.hbs b/app/components/task/holder.hbs
index 2b96de6f..27beaa29 100644
--- a/app/components/task/holder.hbs
+++ b/app/components/task/holder.hbs
@@ -7,6 +7,8 @@
@percentCompleted={{this.percentCompleted}}
@progressBarClass={{this.progressBarClass}}
@isProgressBarDisabled={{this.isProgressBarDisabled}}
+ @onInputChange={{this.progressBarInputChange}}
+ @dev={{@dev}}
/>
diff --git a/app/components/task/holder.js b/app/components/task/holder.js
index 1153550a..bf4642c4 100644
--- a/app/components/task/holder.js
+++ b/app/components/task/holder.js
@@ -66,18 +66,23 @@ export default class TasksHolderComponent extends Component {
return 'progress-bar-yellow';
}
+ @action progressBarInputChange(value) {
+ this.percentCompleted = value;
+ }
+
get isProgressBarDisabled() {
return this.args.task.status !== TASK_KEYS.IN_PROGRESS;
}
@action
- onPercentageChange(e) {
+ async onPercentageChange(e) {
const { value } = e.target;
this.percentCompleted = value;
this.args.onTaskChange('percentCompleted', value);
if (value === TASK_PERCENTAGE.completedPercentage) {
this.percentCompleted = this.args.task.percentCompleted;
}
+ await this.onUpdate(this.args.task.id);
}
@action
diff --git a/app/components/tasks.hbs b/app/components/tasks.hbs
index 1ee3fd20..f7329a3b 100644
--- a/app/components/tasks.hbs
+++ b/app/components/tasks.hbs
@@ -23,6 +23,7 @@
@onTaskUpdate={{@onTaskUpdate}}
@userSelectedTask={{@userSelectedTask}}
@disabled={{@disabled}}
+ @dev={{@dev}}
/>
{{/each}}
diff --git a/app/modifiers/focus-when.js b/app/modifiers/focus-when.js
new file mode 100644
index 00000000..fa90e385
--- /dev/null
+++ b/app/modifiers/focus-when.js
@@ -0,0 +1,7 @@
+import { modifier } from 'ember-modifier';
+
+export default modifier(function focusWhen(element, [isFocused]) {
+ if (isFocused) {
+ element.focus();
+ }
+});
diff --git a/app/styles/app.css b/app/styles/app.css
index 307b7444..4f75d41c 100644
--- a/app/styles/app.css
+++ b/app/styles/app.css
@@ -17,6 +17,7 @@
@import 'card.css';
@import 'discord.css';
@import 'qrcode.css';
+@import 'progress-bar.css';
html,
body {
diff --git a/app/styles/progress-bar.css b/app/styles/progress-bar.css
new file mode 100644
index 00000000..0990f110
--- /dev/null
+++ b/app/styles/progress-bar.css
@@ -0,0 +1,81 @@
+:root {
+ --progress-bar-color: rgba(0, 128, 0, 0.9);
+ --light-grey: rgba(128, 128, 128, 0.5);
+ --black: black;
+ --white: white;
+}
+.progress-slider {
+ display: flex;
+ gap: 4px;
+}
+
+.progress-slider__button {
+ width: 1.5rem;
+ height: 1.1rem;
+ border: 2px solid var(--black);
+ border-radius: 4px;
+ background-color: transparent;
+ display: flex;
+ align-items: center;
+ justify-items: center;
+}
+
+.progress-slider__button__text {
+ font-size: 0.6em;
+ font-weight: bolder;
+ margin: auto;
+}
+
+.progress-slider__button__edit-icon {
+ width: 1rem;
+ height: 1rem;
+ margin: 3px;
+}
+.progress-slider__input-slider {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 90%;
+ height: 1.1rem;
+ cursor: pointer;
+ outline: none;
+ overflow: hidden;
+ border: 2px solid var(--black);
+ border-radius: 4px;
+}
+
+.progress-slider__input-slider:focus {
+ box-shadow: 0 0 0 2px var(--progress-bar-color);
+}
+.progress-slider__input-slider:disabled {
+ cursor: auto;
+}
+
+.progress-slider__input-slider::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 0;
+ box-shadow: -20rem 0 0 20rem var(--progress-bar-color);
+}
+
+.progress-slider__input-slider::-moz-range-thumb {
+ border: none;
+ width: 0;
+ box-shadow: -20rem 0 0 20rem var(--progress-bar-color);
+}
+
+.progress-slider__input-slider[step] {
+ background-color: transparent;
+ background: repeating-linear-gradient(
+ to right,
+ var(--white),
+ var(--white) calc(10.05% - 1.5px),
+ var(--black) 10.05%
+ );
+}
+
+.progress-slider__button--hover:hover {
+ background-color: var(--light-grey);
+}
+
+.progress-slider__button__edit-icon__inner {
+ fill: var(--progress-bar-color);
+}
diff --git a/app/styles/tasks.css b/app/styles/tasks.css
index 016cd280..7fa599d1 100644
--- a/app/styles/tasks.css
+++ b/app/styles/tasks.css
@@ -18,17 +18,17 @@
}
.progress-bar-red {
- --progress-bar-color: red;
+ --progress-bar-color:rgba(255, 0, 0, 0.8);
}
.progress-bar-yellow {
- --progress-bar-color: #ecef08;
+ --progress-bar-color: rgba(255, 255, 0, 0.9);
}
.progress-bar-green {
- --progress-bar-color: green;
+ --progress-bar-color: rgba(0, 128, 0, 0.9);
}
.progress-bar-orange {
- --progress-bar-color: orange;
+ --progress-bar-color: rgba(255, 165, 0,0.9);
}
.tasks-page {
@@ -83,8 +83,9 @@
}
.task-card__progress-bar-container {
- padding: 1em;
- width: 15rem;
+ padding-right: 0.5em;
+ padding-bottom: 0.5em;
+ width: 14.5rem;
flex-shrink: 0;
}
diff --git a/package.json b/package.json
index e4d944aa..b1a70313 100644
--- a/package.json
+++ b/package.json
@@ -32,10 +32,10 @@
"dotenv": "^16.0.1",
"ember-cli-qrcode": "^2.1.0",
"ember-click-outside": "^5.0.1",
+ "ember-resources": "^5.6.0",
"mixpanel-browser": "^2.43.0",
"webpack": "^5.74.0",
- "webpack-5": "^0.0.0",
- "ember-resources": "^5.6.0"
+ "webpack-5": "^0.0.0"
},
"devDependencies": {
"@ember/jquery": "^2.0.0",
@@ -57,12 +57,14 @@
"ember-cli-dependency-checker": "^3.2.0",
"ember-cli-htmlbars": "^5.3.2",
"ember-cli-inject-live-reload": "^2.0.2",
+ "ember-cli-mirage": "^2.4.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.1",
"ember-data": "~3.25.0",
"ember-export-application-global": "^2.0.1",
"ember-load-initializers": "^2.1.2",
"ember-maybe-import-regenerator": "^0.1.6",
+ "ember-modifier": "^4.1.0",
"ember-page-title": "^6.2.1",
"ember-qunit": "^5.1.3",
"ember-resolver": "^8.0.2",
@@ -85,7 +87,6 @@
"qunit": "^2.14.0",
"qunit-dom": "^1.6.0",
"toastr": "^2.1.4",
- "ember-cli-mirage": "^2.4.0",
"tracked-maps-and-sets": "^3.0.2"
},
"engines": {
diff --git a/tests/integration/components/progress-bar-test.js b/tests/integration/components/progress-bar-test.js
new file mode 100644
index 00000000..91562c94
--- /dev/null
+++ b/tests/integration/components/progress-bar-test.js
@@ -0,0 +1,86 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { find, render, fillIn, click, waitFor } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | progress-bar', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ await render(hbs`
`);
+
+ assert.dom('[data-test-progress-bar]').exists();
+ });
+
+ test('it has edit button', async function (assert) {
+ await render(hbs`
`);
+
+ assert.dom('[data-test-progress-bar-button]').exists();
+ });
+
+ test('it has clickable edit button', async function (assert) {
+ this.setProperties({
+ percentageCompleted: '10',
+ onUpdate: (value) => {
+ this.percentageCompleted = value;
+ },
+ });
+ await render(
+ hbs`
`
+ );
+ const editButton = find('[data-test-progress-bar-button]');
+
+ await click(editButton);
+ assert.dom(editButton).containsText('10');
+ });
+
+ test('it should display the correct value on update', async function (assert) {
+ this.setProperties({
+ percentageCompleted: '10',
+ onUpdate: (value) => {
+ this.percentageCompleted = value;
+ },
+ });
+ await render(
+ hbs`
`
+ );
+
+ const editButton = find('[data-test-progress-bar-button]');
+
+ await click(editButton);
+
+ const progressBarInput = find('[data-test-progress-bar]');
+
+ await fillIn(progressBarInput, '50');
+
+ assert.dom('[data-test-progress-bar-button]').exists();
+ assert.equal(progressBarInput.value, '50', "The value should be '50'.");
+ });
+
+ test('it should display the old value when an update fails', async function (assert) {
+ this.setProperties({
+ percentageCompleted: '10',
+ onChange: () => {
+ this.percentageCompleted = '10';
+ },
+ });
+ await render(
+ hbs`
`
+ );
+
+ const editButton = find('[data-test-progress-bar-button]');
+
+ await click(editButton);
+ let progressBarInput = find('[data-test-progress-bar]');
+
+ await fillIn(progressBarInput, '50');
+
+ assert.dom('[data-test-progress-bar-button]').exists();
+
+ await waitFor(editButton);
+
+ await click(editButton);
+
+ assert.dom('[data-test-progress-bar-button]').hasText('10');
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 009984fd..b31ba9f2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1253,6 +1253,15 @@
broccoli-funnel "^3.0.8"
semver "^7.3.8"
+"@embroider/addon-shim@^1.8.4":
+ version "1.8.6"
+ resolved "https://registry.yarnpkg.com/@embroider/addon-shim/-/addon-shim-1.8.6.tgz#b676991b4fa32c3a98dc7db7dc6cd655029c3f09"
+ integrity sha512-siC9kP78uucEbpDcVyxjkwa76pcs5rVzDVpWO4PDc9EAXRX+pzmUuSTLAK3GztUwx7/PWhz1BenAivqdSvSgfg==
+ dependencies:
+ "@embroider/shared-internals" "^2.2.3"
+ broccoli-funnel "^3.0.8"
+ semver "^7.3.8"
+
"@embroider/macros@^0.41.0":
version "0.41.0"
resolved "https://registry.yarnpkg.com/@embroider/macros/-/macros-0.41.0.tgz#3e78b6f388d7229906abf4c75edfff8bb0208aca"
@@ -1320,6 +1329,20 @@
semver "^7.3.5"
typescript-memoize "^1.0.1"
+"@embroider/shared-internals@^2.2.3":
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/@embroider/shared-internals/-/shared-internals-2.2.3.tgz#2c7ffaa42066906bfc30c766450c199d9602cdd9"
+ integrity sha512-4RXJ07TqkQN4FpLBnQ92TZWW4wGAH7CRG37F1iE99rjxoD3IkoKe1IeyNr0Q85lws+2awx4/cEpaUsSwUYiJSg==
+ dependencies:
+ babel-import-util "^1.1.0"
+ ember-rfc176-data "^0.3.17"
+ fs-extra "^9.1.0"
+ js-string-escape "^1.0.1"
+ lodash "^4.17.21"
+ resolve-package-path "^4.0.1"
+ semver "^7.3.5"
+ typescript-memoize "^1.0.1"
+
"@embroider/util@^0.39.1 || ^0.40.0 || ^0.41.0 || ^1.0.0", "@embroider/util@^1.0.0", "@embroider/util@^1.9.0":
version "1.10.0"
resolved "https://registry.yarnpkg.com/@embroider/util/-/util-1.10.0.tgz#8320d73651e7f5d48dac1b71fb9e6d21cac7c803"
@@ -5751,6 +5774,15 @@ ember-modifier@^3.1.0, ember-modifier@^3.2.0, ember-modifier@^3.2.7:
ember-cli-typescript "^5.0.0"
ember-compatibility-helpers "^1.2.5"
+ember-modifier@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ember-modifier/-/ember-modifier-4.1.0.tgz#cb91efbf8ca4ff4a1a859767afa42dddba5a2bbd"
+ integrity sha512-YFCNpEYj6jdyy3EjslRb2ehNiDvaOrXTilR9+ngq+iUqSHYto2zKV0rleiA1XJQ27ELM1q8RihT29U6Lq5EyqQ==
+ dependencies:
+ "@embroider/addon-shim" "^1.8.4"
+ ember-cli-normalize-entity-name "^1.0.0"
+ ember-cli-string-utils "^1.1.0"
+
ember-named-blocks-polyfill@^0.2.4:
version "0.2.5"
resolved "https://registry.yarnpkg.com/ember-named-blocks-polyfill/-/ember-named-blocks-polyfill-0.2.5.tgz#d5841406277026a221f479c815cfbac6cdcaeecb"