Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev-app/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
state="${link.isActive ? 'active' : ''}"
>
</c-nav-horizontal-item>
<c-nav-horizontal-item position="right" href="https://github.com/bindable-ui/bindable" title="v1.0.22"></c-nav-horizontal-item>
<c-nav-horizontal-item position="right" href="https://github.com/bindable-ui/bindable" title="v1.0.24"></c-nav-horizontal-item>
</c-nav-horizontal>
</l-box>
</l-sidebar>
Expand Down
2 changes: 1 addition & 1 deletion dev-app/routes/components/timeline/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
snap-add.bind="true"
zoom-level.bind="zoomLevel"
is-loading.bind="loading"
prevent-create.call="preventCreate(isoTime)"
prevent-create.bind="preventCreate"
snap-add.bind="true"
></c-timeline>
</template>
4 changes: 2 additions & 2 deletions dev-app/routes/components/timeline/demo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ export class TimelineExample {
// },
];

public zoomLevel = 5;
public zoomLevel = 2;
public displayView = 'three-day';
public loading = false;
public preventCreate = _isoTime => false;
public preventCreate = false;

// constructor() {
// const genRandom = (min, max) => Math.random() * (max - min + 1) + min;
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@bindable-ui/bindable",
"description": "An Aurelia component library",
"version": "1.0.23",
"version": "1.0.24",
"repository": {
"type": "git",
"url": "https://github.com/bindable-ui/bindable"
Expand Down
12 changes: 1 addition & 11 deletions src/components/forms/date/c-form-date/c-form-date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,14 @@ Copyright 2020, Verizon Media
Licensed under the terms of the MIT license. See the LICENSE file in the project root for license terms.
*/

import {bindable, bindingMode, computedFrom, containerless} from 'aurelia-framework';
import * as datetimepicker from 'eonasdan-bootstrap-datetimepicker';
import {bindable, bindingMode, containerless} from 'aurelia-framework';
import * as moment from 'moment';
import {authState} from '../../../../decorators/auth-state';

import * as styles from './c-form-date.css.json';

declare const window: any;
declare let $: any;

if (window.$) {
$ = window.$;
}

$.fn.extend({
datetimepicker,
});

/**
* @param id {String} - Element ID.
* @param timestamp {Number} - Unix timestamp.
Expand Down
107 changes: 107 additions & 0 deletions src/components/timeline/c-timeline/c-timeline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Licensed under the terms of the MIT license. See the LICENSE file in the project
*/

import {TaskQueue} from 'aurelia-framework';
import * as moment from 'moment';
import {instance, mock} from 'ts-mockito';

import {CTimeline, ZOOM_LEVELS} from './c-timeline';
Expand All @@ -13,6 +14,42 @@ import {CToastsService} from '../../toasts/c-toasts/c-toasts-service';
const taskQueue = mock(TaskQueue);
const toastsService = mock(CToastsService);

// Mock _.debounce
// @ts-ignore
jest.spyOn(_, 'debounce').mockImplementation(fn => fn);

const now = moment('12/12/2020', 'MM/DD/YYYY')
.startOf('day')
.add(12, 'hours');
const startDay = moment(now)
.startOf('day')
.toISOString();

const sortedEntries: any[] = [
{
duration: 240,
start: now.toISOString(),
},
{
duration: 120,
start: moment(now)
.add(1, 'hour')
.toISOString(),
},
{
duration: 120,
start: moment(now)
.add(1, 'hour')
.toISOString(),
},
{
duration: 120,
start: moment(now)
.add(1, 'day')
.toISOString(),
},
];

describe('c-timeline-block element', () => {
let component;

Expand All @@ -30,7 +67,26 @@ describe('c-timeline-block element', () => {

describe('Unit', () => {
beforeEach(() => {
jest.useFakeTimers();
component = new CTimeline(instance(taskQueue), instance(toastsService));

component.date = startDay;
component.entries = sortedEntries;
component.placeholderEntry = {
openPopover: jest.fn(),
};

component.attached();

component.parentScrollElem = {
offset: () => ({top: 0}),
scrollTop: () => 0,
};
});

afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});

describe('#mapAllowedTimes', () => {
Expand Down Expand Up @@ -73,6 +129,57 @@ describe('c-timeline-block element', () => {
});
});

describe('#togglePopover', () => {
test('regular interval positioning', () => {
const ev = {
layerY: 10,
pageY: 10,
};

component.togglePopover(ev);
expect(component.newItem.title).toBe('00:00 (New Item)');

ev.layerY = 30;
component.togglePopover(ev);
expect(component.newItem.title).toBe('00:15 (New Item)');

ev.pageY = 60;
component.togglePopover(ev);
expect(component.newItem.title).toBe('00:45 (New Item)');
});

test('snap add positioning', () => {
const ev = {
layerY: 10,
pageY: 1600,
};

component.snapAdd = true;

// No snapping
component.togglePopover(ev);
expect(component.newItem.title).toBe('16:00 (New Item)');

// Snapping
ev.pageY = 1200;
component.togglePopover(ev);
expect(component.newItem.title).toBe('12:04 (New Item)');
});

test('opening popover', () => {
const ev = {
layerY: 10,
pageY: 10,
};

component.togglePopover(ev);

jest.runOnlyPendingTimers();

expect(component.placeholderEntry.openPopover).toHaveBeenCalled();
});
});

describe('#getHoursMinutes', () => {
let data;

Expand Down
56 changes: 46 additions & 10 deletions src/components/timeline/c-timeline/c-timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ export class CTimeline {
this.timeView,
this.editEntryViewModel,
this.date,
this.getTzOffet(),
this.zoomLevel,
);
}

Expand All @@ -227,6 +229,8 @@ export class CTimeline {
this.timeView,
this.editEntryViewModel,
this.date,
this.getTzOffet(),
this.zoomLevel,
);

startTime.add(1, 'day');
Expand Down Expand Up @@ -438,6 +442,11 @@ export class CTimeline {
}

public attached() {
// Trigger the default TZ stuff
if (!this.timezone) {
this.setupTimezone();
}

this.getParentScrollElem();
this.buildTimeline();

Expand Down Expand Up @@ -496,16 +505,7 @@ export class CTimeline {
}

public timezoneChanged() {
const tzNames = moment.tz.names();
const tzIndex = tzNames.findIndex(name => name === this.timezone);

if (tzIndex > -1) {
moment.tz.setDefault(this.timezone);
} else {
moment.tz.setDefault();
}

this.renderTimeline();
this.setupTimezone(true);
}

public scrollTimeChanged(_new, old) {
Expand Down Expand Up @@ -535,6 +535,42 @@ export class CTimeline {

// Private methods

/**
* Return the offset in minutes from the selected timezone to the browser timezone
*/
private getTzOffet(): number {
const browserOffset = moment.tz.zone(moment.tz.guess()).utcOffset(moment());
const offset = moment().utcOffset();

return browserOffset + offset;
}

/**
* Sets up the timezone data
*
* @param updateDate Boolean value to determine whether or not to update `this.date`
*/
private setupTimezone(updateDate?: boolean) {
const tzNames = moment.tz.names();
const tzIndex = tzNames.findIndex(name => name === this.timezone);

if (tzIndex > -1) {
moment.tz.setDefault(this.timezone);
} else {
moment.tz.setDefault();
}

if (updateDate) {
// This prevents issues where the date will look in the past and throw off the three-day view
const offset = this.getTzOffet();
this.date = moment(this.date)
.add(offset * -1, 'minutes')
.toISOString();
}

this.renderTimeline();
}

/**
* Get the closest parent element that scrolls
*/
Expand Down
8 changes: 4 additions & 4 deletions src/components/timeline/c-timeline/workers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,29 @@ describe('Web worker functions', () => {

describe('#mapEntries', () => {
it('tests formatting', async () => {
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString());
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString(), 0, 2);

expect(data[0].startTime).toBe('12:00');
expect(data[0].endTime).toBe('12:04');
});

it('tests positioning', async () => {
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString());
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString(), 0, 2);

expect(data[0].top).toBe(1440);
expect(data[0].height).toBe(8);
});

it('tests same time entries', async () => {
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString());
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString(), 0, 2);

expect(data[0].widthCalc).toBeUndefined();
expect(data[2].widthCalc).toBeDefined();
expect(data[3].widthCalc).toBeDefined();
});

it('tests nested entries', async () => {
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString());
const data = await mapEntries(sortedEntries, 2, startDay, endDay, 'day', '', now.toISOString(), 0, 2);

expect(data[0].widthCalc).toBeUndefined();
expect(data[1].widthCalc).toBeDefined();
Expand Down
Loading