Fix/roll (#39)

* roll locks to first

in case there are events with overlapping time, roll will play the one that started first

* sanitize data entry

fixes issue where input field would not return seconds if not modified

* update chakra

* fix time input in chrome

fix issue in chrome where value of input does not contain seconds
This commit is contained in:
Carlos Valente
2021-11-14 21:13:47 +01:00
committed by GitHub
parent 26cb8a5bfc
commit 885d965db1
6 changed files with 650 additions and 511 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@chakra-ui/react": "^1.6.10", "@chakra-ui/react": "^1.7.1",
"@emotion/react": "^11.5.0", "@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0", "@emotion/styled": "^11.3.0",
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
+12 -4
View File
@@ -28,14 +28,17 @@ export default function EditableTimer(props) {
// Check if there is anything there // Check if there is anything there
if (value === '') return false; if (value === '') return false;
// ensure we have seconds
const val = value.split(':').length === 3 ? value : `${value}:00`;
// Time now and time submitedVal // Time now and time submitedVal
const original = stringFromMillis(time + delay, true); const original = stringFromMillis(time + delay, true);
// check if time is different from before // check if time is different from before
if (value === original) return false; if (val === original) return false;
// convert to millis object // convert to millis object
const millis = timeStringToMillis(value); const millis = timeStringToMillis(val);
// validate with parent // validate with parent
if (!validate(name, millis)) return false; if (!validate(name, millis)) return false;
@@ -52,11 +55,16 @@ export default function EditableTimer(props) {
onSubmit={(v) => validateValue(v)} onSubmit={(v) => validateValue(v)}
onCancel={() => setValue(stringFromMillis(time + delay, true))} onCancel={() => setValue(stringFromMillis(time + delay, true))}
value={value} value={value}
placeholder='--:--:--'
className={delay > 0 ? style.delayedEditable : style.editable} className={delay > 0 ? style.delayedEditable : style.editable}
> >
<EditablePreview /> <EditablePreview />
<EditableInput type='time' step='1' min='00:00:00' max='23:59:00' /> <EditableInput
type='time'
placeholder='--:--:--'
min='00:00:00'
max='23:59:59'
step='1'
/>
</Editable> </Editable>
); );
} }
+482 -491
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "ontime", "name": "ontime",
"version": "0.1.5", "version": "0.2.1",
"author": "Carlos Valente", "author": "Carlos Valente",
"description": "Time keeping for live events", "description": "Time keeping for live events",
"repository": "https://github.com/cpvalente/ontime", "repository": "https://github.com/cpvalente/ontime",
@@ -242,3 +242,143 @@ describe('test that roll loads selection in right order', () => {
expect(state).toStrictEqual(expected); expect(state).toStrictEqual(expected);
}); });
}); });
// test getSelectionByRoll()
describe('test that roll behaviour with overlapping times', () => {
const eventlist = [
{
id: 1,
timeStart: 10,
timeEnd: 10,
isPublic: false,
},
{
id: 2,
timeStart: 10,
timeEnd: 20,
isPublic: true,
},
{
id: 3,
timeStart: 10,
timeEnd: 30,
isPublic: false,
},
];
it('if timer is at 0', () => {
const now = 0;
const expected = {
nowIndex: null,
nowId: null,
publicIndex: null,
nextIndex: 0,
publicNextIndex: 1,
timers: null,
timeToNext: 10,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
it('if timer is at 10', () => {
const now = 10;
const expected = {
nowIndex: 1,
nowId: 2,
publicIndex: 1,
nextIndex: 2,
publicNextIndex: null,
timers: {
_finishAt: 20,
_startedAt: 10,
current: 10,
duration: 10,
},
timeToNext: 0,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
it('if timer is at 15', () => {
const now = 15;
const expected = {
nowIndex: 1,
nowId: 2,
publicIndex: 1,
nextIndex: 2,
publicNextIndex: null,
timers: {
_startedAt: 10,
_finishAt: 20,
current: 5,
duration: 10,
},
timeToNext: -5,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
it('if timer is at 20', () => {
const now = 20;
const expected = {
nowIndex: 2,
nowId: 3,
publicIndex: 1,
nextIndex: null,
publicNextIndex: null,
timers: {
_startedAt: 10,
_finishAt: 30,
current: 10,
duration: 20,
},
timeToNext: null,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
it('if timer is at 25', () => {
const now = 25;
const expected = {
nowIndex: 2,
nowId: 3,
publicIndex: 1,
nextIndex: null,
publicNextIndex: null,
timers: {
_startedAt: 10,
_finishAt: 30,
current: 5,
duration: 20,
},
timeToNext: null,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
it('if timer is at 31', () => {
const now = 31;
const expected = {
nowIndex: null,
nowId: null,
publicIndex: null,
nextIndex: null,
publicNextIndex: null,
timers: null,
timeToNext: null,
};
const state = getSelectionByRoll(eventlist, now);
expect(state).toStrictEqual(expected);
});
});
+14 -14
View File
@@ -37,6 +37,9 @@ export const getSelectionByRoll = (arr, now) => {
// Order events by startTime // Order events by startTime
const orderedEvents = sortArrayByProperty(arr, 'timeStart'); const orderedEvents = sortArrayByProperty(arr, 'timeStart');
// flags: select first event if several overlapping
let nowFound = false;
// exit early if we are past the events // exit early if we are past the events
const lastEventEnd = orderedEvents[orderedEvents.length - 1].timeEnd; const lastEventEnd = orderedEvents[orderedEvents.length - 1].timeEnd;
if (now > lastEventEnd) { if (now > lastEventEnd) {
@@ -57,7 +60,7 @@ export const getSelectionByRoll = (arr, now) => {
const normalEnd = const normalEnd =
e.timeEnd < e.timeStart ? (e.timeEnd += this.DAYMS) : e.timeEnd; e.timeEnd < e.timeStart ? (e.timeEnd += this.DAYMS) : e.timeEnd;
if (normalEnd < now) { if (normalEnd <= now) {
// event ran already // event ran already
// public event might not be the one running // public event might not be the one running
@@ -65,7 +68,7 @@ export const getSelectionByRoll = (arr, now) => {
publicTime = normalEnd; publicTime = normalEnd;
publicIndex = arr.findIndex((a) => a.id === e.id); publicIndex = arr.findIndex((a) => a.id === e.id);
} }
} else if (normalEnd >= now && now >= e.timeStart) { } else if (normalEnd > now && now >= e.timeStart && !nowFound) {
// event is running // event is running
// it could also be public // it could also be public
@@ -84,6 +87,7 @@ export const getSelectionByRoll = (arr, now) => {
duration: normalEnd - e.timeStart, duration: normalEnd - e.timeStart,
current: normalEnd - now, current: normalEnd - now,
}; };
nowFound = true;
} else if (normalEnd > now) { } else if (normalEnd > now) {
// event will run // event will run
@@ -93,18 +97,14 @@ export const getSelectionByRoll = (arr, now) => {
// look for next events // look for next events
// check how far the start is from now // check how far the start is from now
const wait = e.timeStart - now; const wait = e.timeStart - now;
if (wait > 0) {
if (nextIndex === null || wait < timeToNext) { if (nextIndex === null || wait < timeToNext) {
timeToNext = wait; timeToNext = wait;
nextIndex = arr.findIndex((a) => a.id === e.id); nextIndex = arr.findIndex((a) => a.id === e.id);
} }
if ( if ((publicNextIndex === null || wait < publicTimeToNext) && e.isPublic) {
(publicNextIndex === null || wait < publicTimeToNext) && publicTimeToNext = wait;
e.isPublic publicNextIndex = arr.findIndex((a) => a.id === e.id);
) {
publicTimeToNext = wait;
publicNextIndex = arr.findIndex((a) => a.id === e.id);
}
} }
} }
} }