Skip to content

Commit 37ee069

Browse files
authored
feat(ui5-duration-picker): implement seconds-step & minutes-step properties (#1603)
1 parent ef62f81 commit 37ee069

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

packages/main/src/DurationPicker.js

+63-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18
44
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
55
import { isShow } from "@ui5/webcomponents-base/dist/Keys.js";
66
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
7+
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
78
import DurationPickerTemplate from "./generated/templates/DurationPickerTemplate.lit.js";
89
import PopoverPlacementType from "./types/PopoverPlacementType.js";
910
import PopoverHorizontalAlign from "./types/PopoverHorizontalAlign.js";
@@ -43,6 +44,30 @@ const metadata = {
4344
defaultValue: "00:00:00",
4445
},
4546

47+
/**
48+
* Defines the selection step for the minutes
49+
* @type {Integer}
50+
* @public
51+
* @defaultValue 1
52+
* @since 1.0.0-rc.8
53+
*/
54+
minutesStep: {
55+
type: Integer,
56+
defaultValue: 1,
57+
},
58+
59+
/**
60+
* Defines the selection step for the seconds
61+
* @type {Integer}
62+
* @public
63+
* @defaultValue 1
64+
* @since 1.0.0-rc.8
65+
*/
66+
secondsStep: {
67+
type: Integer,
68+
defaultValue: 1,
69+
},
70+
4671
/**
4772
* Defines a formatted maximal time that the user will be able to adjust.
4873
*
@@ -227,8 +252,8 @@ class DurationPicker extends UI5Element {
227252
}
228253

229254
/**
230-
* reads string from format hh:mm:ss
231-
* @private
255+
* reads string from format hh:mm:ss and returns an array which contains the hours, minutes and seconds
256+
* @param {string} value string in formathh:mm:ss
232257
*/
233258
readFormattedValue(value) {
234259
value = value.replace(/\s/g, ""); // Remove spaces
@@ -250,6 +275,9 @@ class DurationPicker extends UI5Element {
250275
}
251276

252277
if (currentMinutes > -1) {
278+
if (parseInt(currentMinutes) % this.minutesStep !== 0) {
279+
currentMinutes = this.findNearestStep(currentMinutes, this.minutesStep);
280+
}
253281
if (this._maxValue[0] && this.selectedHours === this._maxValue[0]) {
254282
currentMinutes = currentMinutes > this._maxValue[1] ? this._maxValue[1] : currentMinutes;
255283
} else if (currentMinutes > this._maxValue[1]) {
@@ -260,6 +288,9 @@ class DurationPicker extends UI5Element {
260288
}
261289

262290
if (currentSeconds > -1) {
291+
if (parseInt(currentSeconds) % this.secondsStep !== 0) {
292+
currentSeconds = this.findNearestStep(currentSeconds, this.secondsStep);
293+
}
263294
if (this._maxValue[0] && this._maxValue[1] && this.selectedHours >= this._maxValue[0] && this.selectedSeconds >= this._maxValue[1]) {
264295
currentSeconds = currentSeconds > this._maxValue[2] ? this._maxValue[2] : currentSeconds;
265296
} else if (currentSeconds > this._maxValue[2]) {
@@ -296,21 +327,47 @@ class DurationPicker extends UI5Element {
296327
this[`_${name}`] = temp;
297328
}
298329

330+
findNearestStep(currentValue, step) {
331+
const curr = parseInt(currentValue);
332+
const biggerClosest = this._getClosest(curr, step, true),
333+
lowerClosest = this._getClosest(curr, step, false);
334+
335+
const diffToBiggerClosest = biggerClosest - curr,
336+
diffToLowerClosest = curr - lowerClosest;
337+
338+
return diffToBiggerClosest > diffToLowerClosest ? lowerClosest.toString() : biggerClosest.toString();
339+
}
340+
341+
/**
342+
* Finds the nearest lower/bigger number to the givent curr
343+
* @param {Integer} curr the starting number
344+
* @param {Boolean} larger defines if we are searching for bigger or lower number
345+
*/
346+
_getClosest(curr, step, larger = true) {
347+
while (curr % step !== 0) {
348+
curr = larger ? ++curr : --curr;
349+
}
350+
351+
return curr;
352+
}
353+
299354
_onkeydown(event) {
300355
if (isShow(event)) {
301356
this.togglePicker();
302357
}
303358
}
304359

305-
generateTimeItemsArray(arrayLength) {
360+
generateTimeItemsArray(arrayLength, step = 1) {
306361
const resultArray = [];
307362
for (let i = 0; i < arrayLength; i++) {
308363
let tempString = i.toString();
309364
if (tempString.length === 1) {
310365
tempString = `0${tempString}`;
311366
}
312367

313-
resultArray.push(tempString);
368+
if (tempString % step === 0) {
369+
resultArray.push(tempString);
370+
}
314371
}
315372

316373
return resultArray;
@@ -394,13 +451,13 @@ class DurationPicker extends UI5Element {
394451
get minutesArray() {
395452
const currentMinutes = parseInt(this.readFormattedValue(this.maxValue)[1]);
396453
const minutes = currentMinutes && currentMinutes > 0 && currentMinutes < 60 ? currentMinutes + 1 : 60;
397-
return this.generateTimeItemsArray(minutes);
454+
return this.generateTimeItemsArray(minutes, this.minutesStep);
398455
}
399456

400457
get secondsArray() {
401458
const currentSeconds = parseInt(this.readFormattedValue(this.maxValue)[2]);
402459
const seconds = currentSeconds && currentSeconds > 0 && currentSeconds < 60 ? currentSeconds + 1 : 60;
403-
return this.generateTimeItemsArray(seconds);
460+
return this.generateTimeItemsArray(seconds, this.secondsStep);
404461
}
405462

406463
get secondsSlider() {

packages/main/test/pages/DurationPicker.html

+14
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@
2727

2828
<ui5-duration-picker readonly id="duration-picker2"></ui5-duration-picker>
2929

30+
<br>
31+
<br>
32+
3033
<ui5-title>Duration Picker With Seconds</ui5-title>
3134

3235
<br>
3336

3437
<ui5-duration-picker show-seconds id="duration-picker3"></ui5-duration-picker>
3538

39+
<br>
3640
<br>
3741

3842
<ui5-title>Duration Pickers With MaxValue</ui5-title>
@@ -41,5 +45,15 @@
4145

4246
<ui5-duration-picker value="7:20:10" max-value="05:10:08" show-seconds id="duration-picker4"></ui5-duration-picker>
4347
<ui5-duration-picker max-value="05:10:08" value="05:10:00" show-seconds id="duration-picker5"></ui5-duration-picker>
48+
49+
<br>
50+
<br>
51+
52+
<ui5-title>Duration Pickers With Step</ui5-title>
53+
54+
<br>
55+
56+
<ui5-duration-picker value="05:10:02" seconds-step="5" show-seconds id="duration-picker6"></ui5-duration-picker>
57+
<ui5-duration-picker value="05:12" minutes-step="5" id="duration-picker7"></ui5-duration-picker>
4458
</body>
4559
</html>

packages/main/test/samples/DurationPicker.sample.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ <h3>Basic Duration Picker</h3>
2020
</section>
2121

2222
<section>
23-
<h3>Duration Picker With Seconds</h3>
23+
<h3>Duration Picker With Seconds & Steps</h3>
2424
<div class="snippet">
2525
<ui5-duration-picker value="05:00:30" show-seconds></ui5-duration-picker>
26+
<ui5-duration-picker value="05:08:32" show-seconds seconds-step="5" minutes-step="10"></ui5-duration-picker>
2627
</div>
2728
<pre class="prettyprint lang-html"><xmp>
2829
<ui5-duration-picker value="05:00:30" show-seconds></ui5-duration-picker>
30+
<ui5-duration-picker value="05:08:32" show-seconds seconds-step="5" minutes-step="10"></ui5-duration-picker>
2931
</xmp></pre>
3032
</section>
3133

packages/main/test/specs/DurationPicker.spec.js

+26
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,30 @@ describe("Duration Picker general interaction", () => {
3737
assert.strictEqual(durationPicker.getProperty("_maxValue")[2], "08", "max value is read correctly");
3838
});
3939

40+
it("Tests seconds-step property", () => {
41+
const durationPicker = browser.$("#duration-picker6");
42+
43+
assert.strictEqual(durationPicker.getProperty("value"), "05:10:00", "The initial value is taking in consideration the seconds-step property");
44+
45+
durationPicker.click();
46+
durationPicker.keys("Backspace");
47+
durationPicker.keys("2");
48+
durationPicker.keys("Enter");
49+
50+
assert.strictEqual(durationPicker.getProperty("value"), "05:10:00", "Editing the value is taking in consideration the seconds-step property");
51+
});
52+
53+
it("Tests minutes-step property", () => {
54+
const durationPicker = browser.$("#duration-picker7");
55+
56+
assert.strictEqual(durationPicker.getProperty("value"), "05:10", "The initial value is taking in consideration the minutes-step property");
57+
58+
durationPicker.click();
59+
durationPicker.keys("Backspace");
60+
durationPicker.keys("2");
61+
durationPicker.keys("Enter");
62+
63+
assert.strictEqual(durationPicker.getProperty("value"), "05:10", "Editing the value is taking in consideration the minutes-step property");
64+
});
65+
4066
});

0 commit comments

Comments
 (0)