Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DialogUser - use DialogData.outputConversion before submit and refresh #422

Merged
merged 8 commits into from
Nov 4, 2019
13 changes: 8 additions & 5 deletions src/dialog-user/components/dialog-user/dialogUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ export class DialogUserController extends DialogClass implements IDialogs {
* @param {Object} DialogData factory.
*/

/*@ngInject*/
constructor(private DialogData: any,private $scope : ng.IScope) {
/* @ngInject */
constructor(private DialogData, private $q) {
super();
}

/**
* Runs when component is initialized
* @memberof DialogUserController
Expand Down Expand Up @@ -82,6 +83,10 @@ export class DialogUserController extends DialogClass implements IDialogs {
data: this.dialogValues
};
this.onUpdate({ data: outputData });
this.service.data = {
fields: this.dialogFields,
values: this.dialogValues,
};
}

public validateFields() {
Expand Down Expand Up @@ -184,13 +189,12 @@ export class DialogUserController extends DialogClass implements IDialogs {
promiseList.push(this.refreshSingleField(field));
});

Promise.all(promiseList).then((_data) => {
this.$q.all(promiseList).then((_data) => {
this.refreshRequestCount -= promiseList.length;
if (this.refreshRequestCount === 0) {
this.areFieldsBeingRefreshed = false;
}
this.saveDialogData();
this.$scope.$apply();
});
}

Expand Down Expand Up @@ -224,7 +228,6 @@ export class DialogUserController extends DialogClass implements IDialogs {
this.dialogFields[field].fieldBeingRefreshed = false;

this.saveDialogData();
this.$scope.$apply();

if (! _.isEmpty(this.fieldAssociations[field])) {
this.updateTargetedFieldsFrom(field);
Expand Down
116 changes: 81 additions & 35 deletions src/dialog-user/services/dialogData.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import DialogData from './dialogData';
import * as angular from 'angular';

const dialogField = {
'href': 'http://localhost:3001/api/service_templates/10000000000015/service_dialogs/10000000007060',
'id': 10000000007060,
Expand Down Expand Up @@ -465,41 +466,86 @@ describe('DialogDataService test', () => {
});
});

it('should allow a select list to be sorted', () => {
const testDropDown = {
values: [
[1, 'Test'],
[5, 'Test2'],
[2, 'Test5']
],
options: { sort_by: 'value', sort_order: 'descending', data_type: 'integer' }
};
const testSorted = dialogData.updateFieldSortOrder(testDropDown);
const expectedResult = [[5, 'Test2'], [2, 'Test5'], [1, 'Test']];
expect(testSorted).toEqual(expectedResult);
const testDropDownDescription = {
values: [
[1, 'B'],
[5, 'C'],
[2, 'A']
],
options: { sort_by: 'description', sort_order: 'descending' }
};
const testSortedDescription = dialogData.updateFieldSortOrder(testDropDownDescription);
const expectedSortedResult = [[5, 'C'], [1, 'B'], [2, 'A']];
expect(testSortedDescription).toEqual(expectedSortedResult);
describe('#outputConversion', () => {
beforeEach(() => {
const configuredField = dialogData.setupField({
name: 'date_1',
type: 'DialogFieldDateControl',
default_value: '2019-10-15',
});

dialogData.data = {
fields: {
[configuredField.name]: configuredField,
},
values: {
[configuredField.name]: configuredField.default_value,
},
};
});

it('converts Dates to string', () => {
let input = dialogData.data.values;
let output = dialogData.outputConversion(input);

expect(input === output).toBe(false); // shallow copy
expect(typeof input.date_1).toEqual('object'); // Date
expect(typeof output.date_1).toEqual('string');
expect(output.date_1).toMatch(/^\d+-\d+-\d+$/); // YYYY-MM-DD
});

// this test requires the "local timezone" to be UTC+1 or more
// timezone-mock is not compatible with current karma it seems:
// ERROR [karma]: { inspect: [Function: inspect] }
xit('preserves local timezone', () => {
let input = dialogData.data.values;
input.default_value = new Date('2019-10-15T00:11:22+01:00');

let output = dialogData.outputConversion(input);

expect(input.date_1.getUTCDate()).toEqual(14); // UTC is off by one
expect(output.date_1).toEqual('2019-10-15'); // not 2019-10-14
});
});
it('should allow a numeric Description field to be sorted in a dropdown', () => {
const testDropDownDescription = {
values: [
['zero', '1'],
['five', '5'],
['two', '2']
],
options: { sort_by: 'description', sort_order: 'descending' }
};
const testSortedDescription = dialogData.updateFieldSortOrder(testDropDownDescription);
const expectedSortedResult = [['five', '5'], ['two', '2'], ['zero', '1']];
expect(testSortedDescription).toEqual(expectedSortedResult);

describe('#updateFieldSortOrder', () => {
it('should allow a select list to be sorted', () => {
const testDropDown = {
values: [
[1, 'Test'],
[5, 'Test2'],
[2, 'Test5']
],
options: { sort_by: 'value', sort_order: 'descending', data_type: 'integer' }
};
const testSorted = dialogData.updateFieldSortOrder(testDropDown);
const expectedResult = [[5, 'Test2'], [2, 'Test5'], [1, 'Test']];
expect(testSorted).toEqual(expectedResult);
const testDropDownDescription = {
values: [
[1, 'B'],
[5, 'C'],
[2, 'A']
],
options: { sort_by: 'description', sort_order: 'descending' }
};
const testSortedDescription = dialogData.updateFieldSortOrder(testDropDownDescription);
const expectedSortedResult = [[5, 'C'], [1, 'B'], [2, 'A']];
expect(testSortedDescription).toEqual(expectedSortedResult);
});

it('should allow a numeric Description field to be sorted in a dropdown', () => {
const testDropDownDescription = {
values: [
['zero', '1'],
['five', '5'],
['two', '2']
],
options: { sort_by: 'description', sort_order: 'descending' }
};
const testSortedDescription = dialogData.updateFieldSortOrder(testDropDownDescription);
const expectedSortedResult = [['five', '5'], ['two', '2'], ['zero', '1']];
expect(testSortedDescription).toEqual(expectedSortedResult);
});
});
});
33 changes: 33 additions & 0 deletions src/dialog-user/services/dialogData.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as _ from 'lodash';
import * as angular from 'angular';
import {__} from '../../common/translateFunction';
import {sprintf} from 'sprintf-js';

export default class DialogDataService {
public data: any;

/**
* Sets up and configures properties for a dialog field
Expand Down Expand Up @@ -246,4 +248,35 @@ export default class DialogDataService {

return invalid;
}

// converts the internal representation into the representation parsed by the API
// currently, this means we convert Date instances to strings
public outputConversion(dialogData) {
const dateString = (date) => {
let y = date.getFullYear(),
m = date.getMonth() + 1,
d = date.getDate();
return sprintf('%04d-%02d-%02d', y, m, d);
};

let out = {...dialogData};

Object.values(this.data.fields || {}).forEach(({name, type}) => {
let value = out[name];

switch (type) {
case 'DialogFieldDateControl':
// server expects 2019-10-20, anything longer gets cut
// converting first to prevent timezone conversions
out[name] = _.isDate(value) ? dateString(value) : null;
break;
case 'DialogFieldDateTimeControl':
// explicit conversion to ISO datetime
out[name] = _.isDate(value) ? value.toISOString() : null;
break;
};
});

return out;
}
}