From 821a3eec95072ece732dfbdc9ec8d414b0259016 Mon Sep 17 00:00:00 2001 From: Ganesh Kumar Venkata Krishnan Date: Fri, 25 May 2018 17:03:51 +0530 Subject: [PATCH 1/5] fix(oui-progress): progress component implementation Added progress component --- packages/common/component-utils.js | 12 ++ packages/oui-angular/src/index.js | 4 +- packages/oui-angular/src/index.spec.js | 1 + packages/oui-progress/README.md | 111 ++++++++++++ packages/oui-progress/src/index.js | 8 + packages/oui-progress/src/index.spec.js | 164 ++++++++++++++++++ .../src/progress-bar.component.js | 16 ++ .../src/progress-bar.controller.js | 23 +++ packages/oui-progress/src/progress-bar.html | 7 + .../src/progress-threshold.component.js | 11 ++ .../src/progress-threshold.controller.js | 19 ++ .../oui-progress/src/progress.component.js | 13 ++ .../oui-progress/src/progress.controller.js | 14 ++ packages/oui-progress/src/progress.html | 9 + 14 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 packages/oui-progress/README.md create mode 100644 packages/oui-progress/src/index.js create mode 100644 packages/oui-progress/src/index.spec.js create mode 100644 packages/oui-progress/src/progress-bar.component.js create mode 100644 packages/oui-progress/src/progress-bar.controller.js create mode 100644 packages/oui-progress/src/progress-bar.html create mode 100644 packages/oui-progress/src/progress-threshold.component.js create mode 100644 packages/oui-progress/src/progress-threshold.controller.js create mode 100644 packages/oui-progress/src/progress.component.js create mode 100644 packages/oui-progress/src/progress.controller.js create mode 100644 packages/oui-progress/src/progress.html diff --git a/packages/common/component-utils.js b/packages/common/component-utils.js index b8d91dad..60018d27 100644 --- a/packages/common/component-utils.js +++ b/packages/common/component-utils.js @@ -53,6 +53,18 @@ export function hasAttributeValue (element, attributeName) { return attribute && attribute !== ""; } +/** + * Check if an attribute is present and have a value in an HTML element. + * @param {HTMLElement} element a HTML element + * @param {string} attributeName the attribute name + * @return {Boolean} true if it exists and have a value + */ +export function throwErrorOnMissingAttributeValue (element, attributeName) { + if (!hasAttributeValue(element, attributeName)) { + throw new Error(`ovh-ui-angular: required attribute "${attributeName}" is not defined`); + } +} + /** * Return the value of an attribute of an HTML Element. * @param {HTMLElement} element a HTML element diff --git a/packages/oui-angular/src/index.js b/packages/oui-angular/src/index.js index 214320dd..471a1e6e 100644 --- a/packages/oui-angular/src/index.js +++ b/packages/oui-angular/src/index.js @@ -34,6 +34,7 @@ import "@oui-angular/oui-page-header/src"; import "@oui-angular/oui-tile/src"; import "@oui-angular/oui-guide-menu/src"; import "@oui-angular/oui-header-tabs/src"; +import "@oui-angular/oui-progress/src"; angular.module("oui", [ "oui.button", @@ -71,5 +72,6 @@ angular.module("oui", [ "oui.page-header", "oui.tile", "oui.guide-menu", - "oui.header-tabs" + "oui.header-tabs", + "oui.progress" ]); diff --git a/packages/oui-angular/src/index.spec.js b/packages/oui-angular/src/index.spec.js index 624cda3e..3014b647 100644 --- a/packages/oui-angular/src/index.spec.js +++ b/packages/oui-angular/src/index.spec.js @@ -35,6 +35,7 @@ loadTests(require.context("../../oui-page-header/src/", true, /.*((\.spec)|(inde loadTests(require.context("../../oui-tile/src/", true, /.*((\.spec)|(index))$/)); loadTests(require.context("../../oui-guide-menu/src/", true, /.*((\.spec)|(index))$/)); loadTests(require.context("../../oui-header-tabs/src/", true, /.*((\.spec)|(index))$/)); +loadTests(require.context("../../oui-progress/src/", true, /.*((\.spec)|(index))$/)); function loadTests (context) { context.keys().forEach(context); diff --git a/packages/oui-progress/README.md b/packages/oui-progress/README.md new file mode 100644 index 00000000..9d8777fe --- /dev/null +++ b/packages/oui-progress/README.md @@ -0,0 +1,111 @@ +# oui-progress + + + +## Usage + +### Simple + +```html:preview + + + + + + + + + + + + +``` + +### With labels + +```html:preview + + 5% + + + 10% + + + 60% + + + 100% + +``` + +### Custom max value + +```html:preview + + 150/200 + +``` + +### Stacked + +```html:preview + + 30% + 15% + +``` + +### Thresholds + +```html:preview + + + 80% + + + + + + 30% + 25% + +``` + +### Label alignment + +```html:preview + + Progression: 30% + +``` + +### Indeterminate + +```html:preview + + +``` + +## API + +### oui-progress + +| Attribute | Type | Binding | One-time binding | Values | default | Description | +| ---- | ---- | ---- | ---- | ---- | ---- | ---- | +| type | String | @ | yes | `info`, `success`, `warning`, `error` | | Type of the progress component | +| max-value | Number | @? | yes | | 100 | The max value for the progress bar | +| indeterminate | Boolean | { + + let TestUtils; + beforeEach(angular.mock.module("oui.progress")); + beforeEach(angular.mock.module("oui.test-utils")); + + beforeEach(inject((_TestUtils_) => { + TestUtils = _TestUtils_; + })); + + describe("ouiProgress Component", () => { + function getProgressComponent (element, type) { + return element[0].querySelector(`.oui-progress_${type}`); + } + + function getProgressBarComponent (element, type) { + return element[0].querySelector(`.oui-progress__bar_${type}`); + } + + function getIndeterminateProgressComponent (element) { + return element[0].querySelector(".oui-progress_indeterminate"); + } + + function getProgressBarLabel (element) { + return element[0].querySelector(".oui-progress__label"); + } + + function getProgressBarAlignedLabel (element, alignment) { + return element[0].querySelector(`.oui-progress__bar_text-${alignment}`); + } + + function getProgressThreshold (element) { + return element[0].querySelector(".oui-progress__threshold"); + } + + it("should display a progress", () => { + const infoValue = 5; + const successValue = 10; + const warningValue = 60; + const errorValue = 100; + const infoElement = TestUtils.compileTemplate(` + + + ` + ); + const successElement = TestUtils.compileTemplate(` + + + ` + ); + const warningElement = TestUtils.compileTemplate(` + + + ` + ); + const errorElement = TestUtils.compileTemplate(` + + + ` + ); + + expect(getProgressComponent(infoElement, "info")).toBeTruthy(); + expect(getProgressComponent(successElement, "success")).toBeTruthy(); + expect(getProgressComponent(warningElement, "warning")).toBeTruthy(); + expect(getProgressComponent(errorElement, "error")).toBeTruthy(); + expect(getProgressBarComponent(infoElement, "info")).toBeTruthy(); + expect(getProgressBarComponent(successElement, "success")).toBeTruthy(); + expect(getProgressBarComponent(warningElement, "warning")).toBeTruthy(); + expect(getProgressBarComponent(errorElement, "error")).toBeTruthy(); + }); + + it("should display a indeterminate progress", () => { + const element = TestUtils.compileTemplate(""); + expect(getIndeterminateProgressComponent(element)).toBeTruthy(); + }); + + describe("ouiProgressBar Component", () => { + it("should have the correct width set", () => { + const value = 5; + const element = TestUtils.compileTemplate(` + + + ` + ); + + const progressBarEl = getProgressBarComponent(element, "info"); + expect(progressBarEl).toBeTruthy(); + expect(progressBarEl.getAttribute("style")).toBe(`width: ${value}%;`); + }); + + it("should have the correct width when max-value is used", () => { + const value = 10; + const expectedWidth = value / 2; + const element = TestUtils.compileTemplate(` + + + ` + ); + + const progressBarEl = getProgressBarComponent(element, "info"); + expect(progressBarEl).toBeTruthy(); + expect(progressBarEl.getAttribute("style")).toBe(`width: ${expectedWidth}%;`); + }); + + it("should overide parent's type", () => { + const type = "warning"; + const element = TestUtils.compileTemplate(` + + + ` + ); + + const progressBarEl = getProgressBarComponent(element, type); + expect(progressBarEl).toBeTruthy(); + }); + + it("should have the correct label", () => { + const value = 5; + const label = `${value}%`; + const element = TestUtils.compileTemplate(` + + ${label} + ` + ); + + const progressBarLabelEl = getProgressBarLabel(element); + expect(progressBarLabelEl.innerHTML).toBe(label); + }); + + it("should have the label aligned correctly", () => { + const rightLabelElement = TestUtils.compileTemplate(` + + 5% + ` + ); + const leftLabelElement = TestUtils.compileTemplate(` + + 5% + ` + ); + expect(getProgressBarAlignedLabel(rightLabelElement, "right")).toBeTruthy(); + expect(getProgressBarAlignedLabel(leftLabelElement, "left")).toBeTruthy(); + }); + }); + + describe("ouiProgressThreshold Component", () => { + it("should have the correct position according to value", () => { + const value = 10; + const maxValue = 200; + const leftPosition = value / (maxValue / 100); + const element = TestUtils.compileTemplate(` + + + ${value}% + ` + ); + + const thresholdEl = getProgressThreshold(element); + expect(thresholdEl).toBeTruthy(); + expect(thresholdEl.getAttribute("style")).toBe(`left: ${leftPosition}%;`); + }); + }); + }); +}); diff --git a/packages/oui-progress/src/progress-bar.component.js b/packages/oui-progress/src/progress-bar.component.js new file mode 100644 index 00000000..4897cf32 --- /dev/null +++ b/packages/oui-progress/src/progress-bar.component.js @@ -0,0 +1,16 @@ +import controller from "./progress-bar.controller"; +import template from "./progress-bar.html"; + +export default { + template, + controller, + bindings: { + type: "@?", + value: "<", + labelAlign: "@?" + }, + require: { + parent: "^^ouiProgress" + }, + transclude: true +}; diff --git a/packages/oui-progress/src/progress-bar.controller.js b/packages/oui-progress/src/progress-bar.controller.js new file mode 100644 index 00000000..d9651b7f --- /dev/null +++ b/packages/oui-progress/src/progress-bar.controller.js @@ -0,0 +1,23 @@ +import { addDefaultParameter, throwErrorOnMissingAttributeValue } from "@oui-angular/common/component-utils"; + +export default class { + constructor ($attrs, $element) { + "ngInject"; + this.$attrs = $attrs; + this.$element = $element; + } + + $onInit () { + throwErrorOnMissingAttributeValue(this.$element[0], "value"); + addDefaultParameter(this, "type", this.parent.type); + addDefaultParameter(this, "labelAlign", "right"); + } + + $postLink () { + const maxValuePercentage = 100; + const widthPrecentage = (this.value * maxValuePercentage) / this.parent.maxValue; + this.$element.addClass("oui-progress__bar"); + this.$element.addClass(`oui-progress__bar_${this.type}`); + this.$element.css("width", `${widthPrecentage}%`); + } +} diff --git a/packages/oui-progress/src/progress-bar.html b/packages/oui-progress/src/progress-bar.html new file mode 100644 index 00000000..3bca7f88 --- /dev/null +++ b/packages/oui-progress/src/progress-bar.html @@ -0,0 +1,7 @@ +
+ +
diff --git a/packages/oui-progress/src/progress-threshold.component.js b/packages/oui-progress/src/progress-threshold.component.js new file mode 100644 index 00000000..3eea3e0c --- /dev/null +++ b/packages/oui-progress/src/progress-threshold.component.js @@ -0,0 +1,11 @@ +import controller from "./progress-threshold.controller"; + +export default { + controller, + bindings: { + value: "<" + }, + require: { + parent: "^^ouiProgress" + } +}; diff --git a/packages/oui-progress/src/progress-threshold.controller.js b/packages/oui-progress/src/progress-threshold.controller.js new file mode 100644 index 00000000..b5cbd972 --- /dev/null +++ b/packages/oui-progress/src/progress-threshold.controller.js @@ -0,0 +1,19 @@ +import { throwErrorOnMissingAttributeValue } from "@oui-angular/common/component-utils"; + +export default class { + constructor ($attrs, $element) { + "ngInject"; + this.$element = $element; + } + + $onInit () { + throwErrorOnMissingAttributeValue(this.$element[0], "value"); + } + + $postLink () { + const maxValuePercentage = 100; + const leftPrecentage = (this.value * maxValuePercentage) / this.parent.maxValue; + this.$element.addClass("oui-progress__threshold"); + this.$element.css("left", `${leftPrecentage}%`); + } +} diff --git a/packages/oui-progress/src/progress.component.js b/packages/oui-progress/src/progress.component.js new file mode 100644 index 00000000..380a8e94 --- /dev/null +++ b/packages/oui-progress/src/progress.component.js @@ -0,0 +1,13 @@ +import controller from "./progress.controller"; +import template from "./progress.html"; + +export default { + template, + controller, + bindings: { + type: "@", + maxValue: "@?", + indeterminate: " +
+
From e64ece9270b4fcb7e35ea9219e833c92eb0a7d6e Mon Sep 17 00:00:00 2001 From: Ganesh Kumar Venkata Krishnan Date: Fri, 1 Jun 2018 12:57:45 +0530 Subject: [PATCH 2/5] feat(oui-progress): progress component implementation updated to match the latest UI spec --- packages/oui-progress/README.md | 112 ++++++--------- packages/oui-progress/src/index.js | 2 - packages/oui-progress/src/index.spec.js | 136 ++++++------------ .../src/progress-bar.component.js | 16 --- .../src/progress-bar.controller.js | 23 --- packages/oui-progress/src/progress-bar.html | 7 - .../src/progress-threshold.component.js | 2 + .../src/progress-threshold.controller.js | 7 - .../oui-progress/src/progress-threshold.html | 3 + .../oui-progress/src/progress.component.js | 4 +- .../oui-progress/src/progress.controller.js | 15 +- packages/oui-progress/src/progress.html | 22 +-- 12 files changed, 123 insertions(+), 226 deletions(-) delete mode 100644 packages/oui-progress/src/progress-bar.component.js delete mode 100644 packages/oui-progress/src/progress-bar.controller.js delete mode 100644 packages/oui-progress/src/progress-bar.html create mode 100644 packages/oui-progress/src/progress-threshold.html diff --git a/packages/oui-progress/README.md b/packages/oui-progress/README.md index 9d8777fe..b6d49945 100644 --- a/packages/oui-progress/README.md +++ b/packages/oui-progress/README.md @@ -1,111 +1,87 @@ # oui-progress - + ## Usage ### Simple ```html:preview - - - - - - - - - - - - + + + + ``` -### With labels +### With custom labels ```html:preview - - 5% - - - 10% - - - 60% - - - 100% + ``` ### Custom max value ```html:preview - - 150/200 - -``` - -### Stacked - -```html:preview - - 30% - 15% + ``` ### Thresholds ```html:preview - - - 80% + + - + - 30% - 25% ``` -### Label alignment +### Compact mode ```html:preview - - Progression: 30% + + + + + + + -``` - -### Indeterminate - -```html:preview - - ``` ## API ### oui-progress -| Attribute | Type | Binding | One-time binding | Values | default | Description | -| ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| type | String | @ | yes | `info`, `success`, `warning`, `error` | | Type of the progress component | -| max-value | Number | @? | yes | | 100 | The max value for the progress bar | -| indeterminate | Boolean | { })); describe("ouiProgress Component", () => { - function getProgressComponent (element, type) { - return element[0].querySelector(`.oui-progress_${type}`); - } - function getProgressBarComponent (element, type) { return element[0].querySelector(`.oui-progress__bar_${type}`); } - function getIndeterminateProgressComponent (element) { - return element[0].querySelector(".oui-progress_indeterminate"); - } - function getProgressBarLabel (element) { return element[0].querySelector(".oui-progress__label"); } - function getProgressBarAlignedLabel (element, alignment) { - return element[0].querySelector(`.oui-progress__bar_text-${alignment}`); - } - function getProgressThreshold (element) { return element[0].querySelector(".oui-progress__threshold"); } @@ -39,108 +27,73 @@ describe("ouiProgress", () => { const warningValue = 60; const errorValue = 100; const infoElement = TestUtils.compileTemplate(` - - + ` ); const successElement = TestUtils.compileTemplate(` - - + ` ); const warningElement = TestUtils.compileTemplate(` - - + ` ); const errorElement = TestUtils.compileTemplate(` - - + ` ); - - expect(getProgressComponent(infoElement, "info")).toBeTruthy(); - expect(getProgressComponent(successElement, "success")).toBeTruthy(); - expect(getProgressComponent(warningElement, "warning")).toBeTruthy(); - expect(getProgressComponent(errorElement, "error")).toBeTruthy(); expect(getProgressBarComponent(infoElement, "info")).toBeTruthy(); expect(getProgressBarComponent(successElement, "success")).toBeTruthy(); expect(getProgressBarComponent(warningElement, "warning")).toBeTruthy(); expect(getProgressBarComponent(errorElement, "error")).toBeTruthy(); }); - it("should display a indeterminate progress", () => { - const element = TestUtils.compileTemplate(""); - expect(getIndeterminateProgressComponent(element)).toBeTruthy(); - }); - - describe("ouiProgressBar Component", () => { - it("should have the correct width set", () => { - const value = 5; - const element = TestUtils.compileTemplate(` - - - ` - ); - - const progressBarEl = getProgressBarComponent(element, "info"); - expect(progressBarEl).toBeTruthy(); - expect(progressBarEl.getAttribute("style")).toBe(`width: ${value}%;`); - }); + it("should have the correct width set", () => { + const value = 5; + const element = TestUtils.compileTemplate(` + + ` + ); - it("should have the correct width when max-value is used", () => { - const value = 10; - const expectedWidth = value / 2; - const element = TestUtils.compileTemplate(` - - - ` - ); + const progressBarEl = getProgressBarComponent(element, "info"); + expect(progressBarEl).toBeTruthy(); + expect(progressBarEl.getAttribute("style")).toBe(`width: ${value}%;`); + }); - const progressBarEl = getProgressBarComponent(element, "info"); - expect(progressBarEl).toBeTruthy(); - expect(progressBarEl.getAttribute("style")).toBe(`width: ${expectedWidth}%;`); - }); + it("should have the correct width when max-value is used", () => { + const value = 10; + const expectedWidth = value / 2; + const element = TestUtils.compileTemplate(` + + ` + ); - it("should overide parent's type", () => { - const type = "warning"; - const element = TestUtils.compileTemplate(` - - - ` - ); + const progressBarEl = getProgressBarComponent(element, "info"); + expect(progressBarEl).toBeTruthy(); + expect(progressBarEl.getAttribute("style")).toBe(`width: ${expectedWidth}%;`); + }); - const progressBarEl = getProgressBarComponent(element, type); - expect(progressBarEl).toBeTruthy(); - }); + it("should have the correct default label", () => { + const value = 5; + const element = TestUtils.compileTemplate(` + + ` + ); - it("should have the correct label", () => { - const value = 5; - const label = `${value}%`; - const element = TestUtils.compileTemplate(` - - ${label} - ` - ); + const progressBarLabelEl = getProgressBarLabel(element); + expect(progressBarLabelEl.innerHTML.trim()).toBe(`${value}%`); + }); - const progressBarLabelEl = getProgressBarLabel(element); - expect(progressBarLabelEl.innerHTML).toBe(label); - }); + it("should have the correct label", () => { + const value = 5; + const label = `Progress: ${value}%`; + const element = TestUtils.compileTemplate(` + + ` + ); - it("should have the label aligned correctly", () => { - const rightLabelElement = TestUtils.compileTemplate(` - - 5% - ` - ); - const leftLabelElement = TestUtils.compileTemplate(` - - 5% - ` - ); - expect(getProgressBarAlignedLabel(rightLabelElement, "right")).toBeTruthy(); - expect(getProgressBarAlignedLabel(leftLabelElement, "left")).toBeTruthy(); - }); + const progressBarLabelEl = getProgressBarLabel(element); + expect(progressBarLabelEl.innerHTML.trim()).toBe(label); }); describe("ouiProgressThreshold Component", () => { @@ -149,9 +102,8 @@ describe("ouiProgress", () => { const maxValue = 200; const leftPosition = value / (maxValue / 100); const element = TestUtils.compileTemplate(` - + - ${value}% ` ); diff --git a/packages/oui-progress/src/progress-bar.component.js b/packages/oui-progress/src/progress-bar.component.js deleted file mode 100644 index 4897cf32..00000000 --- a/packages/oui-progress/src/progress-bar.component.js +++ /dev/null @@ -1,16 +0,0 @@ -import controller from "./progress-bar.controller"; -import template from "./progress-bar.html"; - -export default { - template, - controller, - bindings: { - type: "@?", - value: "<", - labelAlign: "@?" - }, - require: { - parent: "^^ouiProgress" - }, - transclude: true -}; diff --git a/packages/oui-progress/src/progress-bar.controller.js b/packages/oui-progress/src/progress-bar.controller.js deleted file mode 100644 index d9651b7f..00000000 --- a/packages/oui-progress/src/progress-bar.controller.js +++ /dev/null @@ -1,23 +0,0 @@ -import { addDefaultParameter, throwErrorOnMissingAttributeValue } from "@oui-angular/common/component-utils"; - -export default class { - constructor ($attrs, $element) { - "ngInject"; - this.$attrs = $attrs; - this.$element = $element; - } - - $onInit () { - throwErrorOnMissingAttributeValue(this.$element[0], "value"); - addDefaultParameter(this, "type", this.parent.type); - addDefaultParameter(this, "labelAlign", "right"); - } - - $postLink () { - const maxValuePercentage = 100; - const widthPrecentage = (this.value * maxValuePercentage) / this.parent.maxValue; - this.$element.addClass("oui-progress__bar"); - this.$element.addClass(`oui-progress__bar_${this.type}`); - this.$element.css("width", `${widthPrecentage}%`); - } -} diff --git a/packages/oui-progress/src/progress-bar.html b/packages/oui-progress/src/progress-bar.html deleted file mode 100644 index 3bca7f88..00000000 --- a/packages/oui-progress/src/progress-bar.html +++ /dev/null @@ -1,7 +0,0 @@ -
- -
diff --git a/packages/oui-progress/src/progress-threshold.component.js b/packages/oui-progress/src/progress-threshold.component.js index 3eea3e0c..782f0fc6 100644 --- a/packages/oui-progress/src/progress-threshold.component.js +++ b/packages/oui-progress/src/progress-threshold.component.js @@ -1,6 +1,8 @@ import controller from "./progress-threshold.controller"; +import template from "./progress-threshold.html"; export default { + template, controller, bindings: { value: "<" diff --git a/packages/oui-progress/src/progress-threshold.controller.js b/packages/oui-progress/src/progress-threshold.controller.js index b5cbd972..85a4e20a 100644 --- a/packages/oui-progress/src/progress-threshold.controller.js +++ b/packages/oui-progress/src/progress-threshold.controller.js @@ -9,11 +9,4 @@ export default class { $onInit () { throwErrorOnMissingAttributeValue(this.$element[0], "value"); } - - $postLink () { - const maxValuePercentage = 100; - const leftPrecentage = (this.value * maxValuePercentage) / this.parent.maxValue; - this.$element.addClass("oui-progress__threshold"); - this.$element.css("left", `${leftPrecentage}%`); - } } diff --git a/packages/oui-progress/src/progress-threshold.html b/packages/oui-progress/src/progress-threshold.html new file mode 100644 index 00000000..78c4003c --- /dev/null +++ b/packages/oui-progress/src/progress-threshold.html @@ -0,0 +1,3 @@ +
+
diff --git a/packages/oui-progress/src/progress.component.js b/packages/oui-progress/src/progress.component.js index 380a8e94..cedf2312 100644 --- a/packages/oui-progress/src/progress.component.js +++ b/packages/oui-progress/src/progress.component.js @@ -6,8 +6,10 @@ export default { controller, bindings: { type: "@", + value: "<", + compact: " { + this.$element.addClass("oui-progress"); + if (this.compact) { + this.$element.addClass("oui-progress_compact"); + } + }); } } diff --git a/packages/oui-progress/src/progress.html b/packages/oui-progress/src/progress.html index e516d329..2269a4c1 100644 --- a/packages/oui-progress/src/progress.html +++ b/packages/oui-progress/src/progress.html @@ -1,9 +1,15 @@ -
-
+
+
+
+
+
+
+ {{ $ctrl.label !== undefined ? $ctrl.label : ($ctrl.value + "%") }}
From fa254292e9f3e4e6f9c862c80a6e1f4936d4d146 Mon Sep 17 00:00:00 2001 From: Axel Peter Date: Mon, 2 Jul 2018 11:33:57 +0200 Subject: [PATCH 3/5] chore(oui-progress): review files structure --- packages/oui-progress/src/bar/progress-bar.component.js | 0 packages/oui-progress/src/bar/progress-bar.controller.js | 0 packages/oui-progress/src/bar/progress-bar.html | 0 packages/oui-progress/src/index.js | 2 +- packages/oui-progress/src/progress.component.js | 2 +- packages/oui-progress/src/progress.html | 6 +++--- .../src/{ => threshold}/progress-threshold.component.js | 0 .../src/{ => threshold}/progress-threshold.controller.js | 0 .../src/{ => threshold}/progress-threshold.html | 0 9 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 packages/oui-progress/src/bar/progress-bar.component.js create mode 100644 packages/oui-progress/src/bar/progress-bar.controller.js create mode 100644 packages/oui-progress/src/bar/progress-bar.html rename packages/oui-progress/src/{ => threshold}/progress-threshold.component.js (100%) rename packages/oui-progress/src/{ => threshold}/progress-threshold.controller.js (100%) rename packages/oui-progress/src/{ => threshold}/progress-threshold.html (100%) diff --git a/packages/oui-progress/src/bar/progress-bar.component.js b/packages/oui-progress/src/bar/progress-bar.component.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/oui-progress/src/bar/progress-bar.controller.js b/packages/oui-progress/src/bar/progress-bar.controller.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/oui-progress/src/bar/progress-bar.html b/packages/oui-progress/src/bar/progress-bar.html new file mode 100644 index 00000000..e69de29b diff --git a/packages/oui-progress/src/index.js b/packages/oui-progress/src/index.js index ca149edd..7aac66dc 100644 --- a/packages/oui-progress/src/index.js +++ b/packages/oui-progress/src/index.js @@ -1,5 +1,5 @@ import Progress from "./progress.component.js"; -import ProgressThreshold from "./progress-threshold.component.js"; +import ProgressThreshold from "./threshold/progress-threshold.component.js"; angular.module("oui.progress", []) .component("ouiProgress", Progress) diff --git a/packages/oui-progress/src/progress.component.js b/packages/oui-progress/src/progress.component.js index cedf2312..463b7fbe 100644 --- a/packages/oui-progress/src/progress.component.js +++ b/packages/oui-progress/src/progress.component.js @@ -9,7 +9,7 @@ export default { value: "<", compact: " +
-
- {{ $ctrl.label !== undefined ? $ctrl.label : ($ctrl.value + "%") }} + {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }}
diff --git a/packages/oui-progress/src/progress-threshold.component.js b/packages/oui-progress/src/threshold/progress-threshold.component.js similarity index 100% rename from packages/oui-progress/src/progress-threshold.component.js rename to packages/oui-progress/src/threshold/progress-threshold.component.js diff --git a/packages/oui-progress/src/progress-threshold.controller.js b/packages/oui-progress/src/threshold/progress-threshold.controller.js similarity index 100% rename from packages/oui-progress/src/progress-threshold.controller.js rename to packages/oui-progress/src/threshold/progress-threshold.controller.js diff --git a/packages/oui-progress/src/progress-threshold.html b/packages/oui-progress/src/threshold/progress-threshold.html similarity index 100% rename from packages/oui-progress/src/progress-threshold.html rename to packages/oui-progress/src/threshold/progress-threshold.html From 0c54d09f418ee4f5ec15ae1d50972d0bbcf5f50d Mon Sep 17 00:00:00 2001 From: Axel Peter Date: Tue, 3 Jul 2018 13:49:50 +0200 Subject: [PATCH 4/5] chore(oui-progress): update for compatibility support --- packages/oui-progress/README.md | 123 ++++++++++++------ .../src/bar/progress-bar.component.js | 15 +++ .../src/bar/progress-bar.controller.js | 55 ++++++++ .../oui-progress/src/bar/progress-bar.html | 3 + packages/oui-progress/src/index.js | 2 + .../oui-progress/src/progress.component.js | 11 +- .../oui-progress/src/progress.controller.js | 17 ++- packages/oui-progress/src/progress.html | 26 ++-- .../threshold/progress-threshold.component.js | 2 - .../progress-threshold.controller.js | 14 +- .../src/threshold/progress-threshold.html | 3 - 11 files changed, 197 insertions(+), 74 deletions(-) delete mode 100644 packages/oui-progress/src/threshold/progress-threshold.html diff --git a/packages/oui-progress/README.md b/packages/oui-progress/README.md index b6d49945..c639db5c 100644 --- a/packages/oui-progress/README.md +++ b/packages/oui-progress/README.md @@ -1,44 +1,79 @@ # oui-progress - + ## Usage ### Simple ```html:preview - - - - + + + + + + + + + + + + + + + ``` ### With custom labels ```html:preview - + + + ``` ### Custom max value ```html:preview - + + + + +``` + +### Stacked + +```html:preview + + + ``` ### Thresholds ```html:preview - + + + + + + + + + - + + + @@ -48,23 +83,30 @@ ### Compact mode ```html:preview - + + + - + + + + - + + + + - + + + + ``` @@ -72,16 +114,21 @@ ### oui-progress -| Attribute | Type | Binding | One-time binding | Values | default | Description | -| ---- | ---- | ---- | ---- | ---- | ---- | ---- | -| type | String | @ | yes | `info`, `success`, `warning`, `error` | | Type of the progress component | -| value | Number | < | no | | | The current value for the progress bar | -| compact | Boolean | { + this.$element + .attr("ariaValuenow", value); + + if (!this.compact) { + this.$element + .css("width", this.parent.getPercentageValue(value)); + } + }); + } + + $postLink () { + this.$timeout(() => { + this.$element + .addClass("oui-progress__bar") + .addClass(`oui-progress__bar_${this.type}`) + .attr("ariaValuenow", this.value) + .attr("ariaValuemin", this.minValue) + .attr("ariaValuemax", this.maxValue) + .attr("role", "progressbar"); + + if (this.text) { + this.$element + .attr("ariaValuetext", this.text); + } + + if (!this.compact) { + this.$element + .css("width", this.parent.getPercentageValue(this.value)); + } + }); + } +} diff --git a/packages/oui-progress/src/bar/progress-bar.html b/packages/oui-progress/src/bar/progress-bar.html index e69de29b..33102c01 100644 --- a/packages/oui-progress/src/bar/progress-bar.html +++ b/packages/oui-progress/src/bar/progress-bar.html @@ -0,0 +1,3 @@ + + {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }} + diff --git a/packages/oui-progress/src/index.js b/packages/oui-progress/src/index.js index 7aac66dc..f6cb9fa3 100644 --- a/packages/oui-progress/src/index.js +++ b/packages/oui-progress/src/index.js @@ -1,6 +1,8 @@ import Progress from "./progress.component.js"; +import ProgressBar from "./bar/progress-bar.component.js"; import ProgressThreshold from "./threshold/progress-threshold.component.js"; angular.module("oui.progress", []) .component("ouiProgress", Progress) + .component("ouiProgressBar", ProgressBar) .component("ouiProgressThreshold", ProgressThreshold); diff --git a/packages/oui-progress/src/progress.component.js b/packages/oui-progress/src/progress.component.js index 463b7fbe..ee84eb62 100644 --- a/packages/oui-progress/src/progress.component.js +++ b/packages/oui-progress/src/progress.component.js @@ -1,15 +1,10 @@ import controller from "./progress.controller"; -import template from "./progress.html"; export default { - template, controller, bindings: { - type: "@", - value: "<", compact: " { this.$element.addClass("oui-progress"); + if (this.compact) { this.$element.addClass("oui-progress_compact"); } }); } + + getPercentageValue (value) { + const percent = 100; + const minValue = this.minValue; + const maxValue = Math.max(this.maxValue - this.minValue, minValue); + const currentValue = Math.max(value - this.minValue, minValue); + + return `${(currentValue / maxValue) * percent}%`; + } } diff --git a/packages/oui-progress/src/progress.html b/packages/oui-progress/src/progress.html index 7fd8f423..cc63d027 100644 --- a/packages/oui-progress/src/progress.html +++ b/packages/oui-progress/src/progress.html @@ -1,15 +1,13 @@ -
-
-
-
-
-
- {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }} +
+
+ + {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }} +
diff --git a/packages/oui-progress/src/threshold/progress-threshold.component.js b/packages/oui-progress/src/threshold/progress-threshold.component.js index 782f0fc6..3eea3e0c 100644 --- a/packages/oui-progress/src/threshold/progress-threshold.component.js +++ b/packages/oui-progress/src/threshold/progress-threshold.component.js @@ -1,8 +1,6 @@ import controller from "./progress-threshold.controller"; -import template from "./progress-threshold.html"; export default { - template, controller, bindings: { value: "<" diff --git a/packages/oui-progress/src/threshold/progress-threshold.controller.js b/packages/oui-progress/src/threshold/progress-threshold.controller.js index 85a4e20a..83466c9e 100644 --- a/packages/oui-progress/src/threshold/progress-threshold.controller.js +++ b/packages/oui-progress/src/threshold/progress-threshold.controller.js @@ -1,12 +1,16 @@ -import { throwErrorOnMissingAttributeValue } from "@oui-angular/common/component-utils"; - export default class { - constructor ($attrs, $element) { + constructor ($element, $timeout) { "ngInject"; + this.$element = $element; + this.$timeout = $timeout; } - $onInit () { - throwErrorOnMissingAttributeValue(this.$element[0], "value"); + $postLink () { + this.$timeout(() => + this.$element + .addClass("oui-progress__threshold") + .css("left", this.parent.getPercentageValue(this.value)) + ); } } diff --git a/packages/oui-progress/src/threshold/progress-threshold.html b/packages/oui-progress/src/threshold/progress-threshold.html deleted file mode 100644 index 78c4003c..00000000 --- a/packages/oui-progress/src/threshold/progress-threshold.html +++ /dev/null @@ -1,3 +0,0 @@ -
-
From fd0f6418aa36479ec08d3db5a77cfddd58dac150 Mon Sep 17 00:00:00 2001 From: Axel Peter Date: Tue, 3 Jul 2018 17:50:10 +0200 Subject: [PATCH 5/5] chore(oui-progress): add unit tests --- packages/common/component-utils.js | 12 -- .../src/bar/progress-bar.component.js | 2 +- .../src/bar/progress-bar.controller.js | 10 +- .../oui-progress/src/bar/progress-bar.html | 4 +- packages/oui-progress/src/index.spec.js | 125 ++++++++++++------ packages/oui-progress/src/progress.html | 13 -- .../threshold/progress-threshold.component.js | 2 +- .../progress-threshold.controller.js | 2 +- 8 files changed, 96 insertions(+), 74 deletions(-) delete mode 100644 packages/oui-progress/src/progress.html diff --git a/packages/common/component-utils.js b/packages/common/component-utils.js index 60018d27..b8d91dad 100644 --- a/packages/common/component-utils.js +++ b/packages/common/component-utils.js @@ -53,18 +53,6 @@ export function hasAttributeValue (element, attributeName) { return attribute && attribute !== ""; } -/** - * Check if an attribute is present and have a value in an HTML element. - * @param {HTMLElement} element a HTML element - * @param {string} attributeName the attribute name - * @return {Boolean} true if it exists and have a value - */ -export function throwErrorOnMissingAttributeValue (element, attributeName) { - if (!hasAttributeValue(element, attributeName)) { - throw new Error(`ovh-ui-angular: required attribute "${attributeName}" is not defined`); - } -} - /** * Return the value of an attribute of an HTML Element. * @param {HTMLElement} element a HTML element diff --git a/packages/oui-progress/src/bar/progress-bar.component.js b/packages/oui-progress/src/bar/progress-bar.component.js index 353f6ffe..66ba2fd0 100644 --- a/packages/oui-progress/src/bar/progress-bar.component.js +++ b/packages/oui-progress/src/bar/progress-bar.component.js @@ -10,6 +10,6 @@ export default { text: "@?" }, require: { - parent: "^^ouiProgress" + progressCtrl: "^^ouiProgress" } }; diff --git a/packages/oui-progress/src/bar/progress-bar.controller.js b/packages/oui-progress/src/bar/progress-bar.controller.js index 80b79b5a..cd8cff25 100644 --- a/packages/oui-progress/src/bar/progress-bar.controller.js +++ b/packages/oui-progress/src/bar/progress-bar.controller.js @@ -12,9 +12,9 @@ export default class { $onInit () { addDefaultParameter(this, "type", "info"); - this.compact = this.parent.compact; - this.minValue = this.parent.minValue; - this.maxValue = this.parent.maxValue; + this.compact = this.progressCtrl.compact; + this.minValue = this.progressCtrl.minValue; + this.maxValue = this.progressCtrl.maxValue; } $onChanges (changes) { @@ -26,7 +26,7 @@ export default class { if (!this.compact) { this.$element - .css("width", this.parent.getPercentageValue(value)); + .css("width", this.progressCtrl.getPercentageValue(value)); } }); } @@ -48,7 +48,7 @@ export default class { if (!this.compact) { this.$element - .css("width", this.parent.getPercentageValue(this.value)); + .css("width", this.progressCtrl.getPercentageValue(this.value)); } }); } diff --git a/packages/oui-progress/src/bar/progress-bar.html b/packages/oui-progress/src/bar/progress-bar.html index 33102c01..9970e2a6 100644 --- a/packages/oui-progress/src/bar/progress-bar.html +++ b/packages/oui-progress/src/bar/progress-bar.html @@ -1,3 +1,3 @@ - - {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }} + diff --git a/packages/oui-progress/src/index.spec.js b/packages/oui-progress/src/index.spec.js index d5a84546..532b28de 100644 --- a/packages/oui-progress/src/index.spec.js +++ b/packages/oui-progress/src/index.spec.js @@ -1,99 +1,144 @@ describe("ouiProgress", () => { - let TestUtils; + let $timeout; + + const progressClass = "oui-progress"; + const progressBarClass = `${progressClass}__bar`; + const progressLabelClass = `${progressClass}__label`; + const progressThresholdClass = `${progressClass}__threshold`; + beforeEach(angular.mock.module("oui.progress")); beforeEach(angular.mock.module("oui.test-utils")); - beforeEach(inject((_TestUtils_) => { + beforeEach(inject((_TestUtils_, _$timeout_) => { TestUtils = _TestUtils_; + $timeout = _$timeout_; })); describe("ouiProgress Component", () => { function getProgressBarComponent (element, type) { - return element[0].querySelector(`.oui-progress__bar_${type}`); + if (type) { + return angular.element(element[0].querySelector(`.${progressBarClass}_${type}`)); + } + + return angular.element(element[0].querySelector(`.${progressBarClass}`)); } function getProgressBarLabel (element) { - return element[0].querySelector(".oui-progress__label"); + return angular.element(element[0].querySelector(`.${progressLabelClass}`)); } function getProgressThreshold (element) { - return element[0].querySelector(".oui-progress__threshold"); + return angular.element(element[0].querySelector(`.${progressThresholdClass}`)); } it("should display a progress", () => { - const infoValue = 5; - const successValue = 10; - const warningValue = 60; - const errorValue = 100; - const infoElement = TestUtils.compileTemplate(` - + const element = TestUtils.compileTemplate(` + + ` ); - const successElement = TestUtils.compileTemplate(` - + + $timeout.flush(); + + expect(element.hasClass(progressClass)).toBeTruthy(); + expect(getProgressBarComponent(element).length).toBe(1); + }); + + it("should display a compact progress bar", () => { + const element = TestUtils.compileTemplate(` + + ` ); - const warningElement = TestUtils.compileTemplate(` - + + $timeout.flush(); + + expect(element.hasClass(`${progressClass}_compact`)).toBeTruthy(); + }); + + it("should set type info by default", () => { + const element = TestUtils.compileTemplate(` + + ` ); - const errorElement = TestUtils.compileTemplate(` - + + $timeout.flush(); + + expect(getProgressBarComponent(element, "info").length).toBe(1); + }); + + it("should display a progress bar of each type", () => { + const element = TestUtils.compileTemplate(` + + + + + ` ); - expect(getProgressBarComponent(infoElement, "info")).toBeTruthy(); - expect(getProgressBarComponent(successElement, "success")).toBeTruthy(); - expect(getProgressBarComponent(warningElement, "warning")).toBeTruthy(); - expect(getProgressBarComponent(errorElement, "error")).toBeTruthy(); + + $timeout.flush(); + + expect(getProgressBarComponent(element, "info").length).toBe(1); + expect(getProgressBarComponent(element, "success").length).toBe(1); + expect(getProgressBarComponent(element, "warning").length).toBe(1); + expect(getProgressBarComponent(element, "error").length).toBe(1); }); it("should have the correct width set", () => { const value = 5; const element = TestUtils.compileTemplate(` - + + ` ); - const progressBarEl = getProgressBarComponent(element, "info"); - expect(progressBarEl).toBeTruthy(); - expect(progressBarEl.getAttribute("style")).toBe(`width: ${value}%;`); + $timeout.flush(); + + expect(getProgressBarComponent(element).css("width")).toBe(`${value}%`); }); it("should have the correct width when max-value is used", () => { const value = 10; const expectedWidth = value / 2; const element = TestUtils.compileTemplate(` - + + ` ); - const progressBarEl = getProgressBarComponent(element, "info"); - expect(progressBarEl).toBeTruthy(); - expect(progressBarEl.getAttribute("style")).toBe(`width: ${expectedWidth}%;`); + $timeout.flush(); + + expect(getProgressBarComponent(element).css("width")).toBe(`${expectedWidth}%`); }); it("should have the correct default label", () => { const value = 5; const element = TestUtils.compileTemplate(` - + + ` ); - const progressBarLabelEl = getProgressBarLabel(element); - expect(progressBarLabelEl.innerHTML.trim()).toBe(`${value}%`); + $timeout.flush(); + + expect(getProgressBarLabel(element).text()).toBe(`${value}%`); }); it("should have the correct label", () => { const value = 5; - const label = `Progress: ${value}%`; + const text = `Progress: ${value}%`; const element = TestUtils.compileTemplate(` - + + ` ); - const progressBarLabelEl = getProgressBarLabel(element); - expect(progressBarLabelEl.innerHTML.trim()).toBe(label); + $timeout.flush(); + + expect(getProgressBarLabel(element).text()).toBe(text); }); describe("ouiProgressThreshold Component", () => { @@ -102,14 +147,16 @@ describe("ouiProgress", () => { const maxValue = 200; const leftPosition = value / (maxValue / 100); const element = TestUtils.compileTemplate(` - + ` ); + $timeout.flush(); + const thresholdEl = getProgressThreshold(element); - expect(thresholdEl).toBeTruthy(); - expect(thresholdEl.getAttribute("style")).toBe(`left: ${leftPosition}%;`); + expect(thresholdEl.length).toBe(1); + expect(thresholdEl.css("left")).toBe(`${leftPosition}%`); }); }); }); diff --git a/packages/oui-progress/src/progress.html b/packages/oui-progress/src/progress.html deleted file mode 100644 index cc63d027..00000000 --- a/packages/oui-progress/src/progress.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
- - {{ $ctrl.text !== undefined ? $ctrl.text : ($ctrl.value + "%") }} - -
diff --git a/packages/oui-progress/src/threshold/progress-threshold.component.js b/packages/oui-progress/src/threshold/progress-threshold.component.js index 3eea3e0c..ff6c68ef 100644 --- a/packages/oui-progress/src/threshold/progress-threshold.component.js +++ b/packages/oui-progress/src/threshold/progress-threshold.component.js @@ -6,6 +6,6 @@ export default { value: "<" }, require: { - parent: "^^ouiProgress" + progressCtrl: "^^ouiProgress" } }; diff --git a/packages/oui-progress/src/threshold/progress-threshold.controller.js b/packages/oui-progress/src/threshold/progress-threshold.controller.js index 83466c9e..9f1b64fa 100644 --- a/packages/oui-progress/src/threshold/progress-threshold.controller.js +++ b/packages/oui-progress/src/threshold/progress-threshold.controller.js @@ -10,7 +10,7 @@ export default class { this.$timeout(() => this.$element .addClass("oui-progress__threshold") - .css("left", this.parent.getPercentageValue(this.value)) + .css("left", this.progressCtrl.getPercentageValue(this.value)) ); } }