2574 Filter tag by composed color #443

Merged
joan merged 8 commits from 2574-itemTag_refactor into dev 2020-11-10 14:01:50 +00:00
12 changed files with 184 additions and 34085 deletions

View File

@ -718,11 +718,13 @@ INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`) INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
VALUES VALUES
('YEL', 'Yellow', 1, 1, 'F4D03F'), ('YEL', 'Yellow', 1, 1, 'F4D03F'),
('BLU', 'Blue', 1, 2, '5DADE2'), ('BLU', 'Blue', 1, 2, '5DADE2'),
('RED', 'Red', 1, 3, 'EC7063'), ('RED', 'Red', 1, 3, 'EC7063'),
('SLV', 'Silver', 1, 4, 'CACFD2'), ('SLV', 'Silver', 1, 4, 'CACFD2'),
('BRW', 'Brown', 1, 5, 'DC7633'); ('BRW', 'Brown', 1, 5, 'DC7633'),
('BLK', 'Black', 1, 6, '000000'),
('BAS', 'Blue/Silver', 1, 7, '5DADE2');
INSERT INTO `vn`.`origin`(`id`,`code`, `name`) INSERT INTO `vn`.`origin`(`id`,`code`, `name`)
VALUES VALUES

5148
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('filterValue', {
description: 'Returns a list of tag values',
accepts: [{
arg: 'id',
type: 'Number',
required: true,
description: 'The tag id',
http: {source: 'path'}
}, {
arg: 'filter',
type: 'Object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/:id/filterValue`,
verb: 'GET'
}
});
Self.filterValue = async(id, filter) => {
const conn = Self.dataSource.connector;
const tag = await Self.findById(id);
let stmt;
if (!tag.isFree && tag.sourceTable) {
stmt = new ParameterizedSQL(
`SELECT value FROM (
SELECT name AS value FROM ${tag.sourceTable}) v`);
} else
stmt = new ParameterizedSQL(`SELECT value FROM itemTag`);
let where = filter.where;
if (where && where.value) {
stmt.merge(conn.makeWhere({value: {like: `%${where.value}%`}}));
stmt.merge(`
ORDER BY value LIKE '${where.value}' DESC,
value LIKE '${where.value}%' DESC`);
}
stmt.merge(conn.makeLimit(filter));
return conn.executeStmt(stmt);
};
};

View File

@ -0,0 +1,37 @@
const app = require('vn-loopback/server/server');
describe('tag filterValue()', () => {
const colorTagId = 1;
it('should return a list of color values', async() => {
const filter = {limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
expect(result.length).toEqual(5);
});
it('should return the values matching color "Blue"', async() => {
const filter = {where: {value: 'Blue'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Blue');
expect(result[1].value).toEqual('Blue/Silver');
});
it('should return the values matching color "Blue/Silver"', async() => {
const filter = {where: {value: 'Blue/Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
expect(result.length).toEqual(1);
expect(result[0].value).toEqual('Blue/Silver');
});
it('should return the values matching color "Silver"', async() => {
const filter = {where: {value: 'Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Silver');
expect(result[1].value).toEqual('Blue/Silver');
});
});

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/tag/filterValue')(Self);
};

View File

@ -40,12 +40,12 @@
</vn-textfield> </vn-textfield>
<vn-autocomplete vn-three <vn-autocomplete vn-three
ng-show="tag.selection.isFree === false" ng-show="tag.selection.isFree === false"
url="{{$ctrl.sourceTables[itemTag.id].url}}" url="{{'Tags/' + itemTag.tagFk + '/filterValue'}}"
search-function="{name: {like: $search +'%'}}" search-function="{value: $search}"
label="Value" label="Value"
ng-model="itemTag.value" ng-model="itemTag.value"
show-field="{{$ctrl.sourceTables[itemTag.id].field}}" show-field="value"
value-field="{{$ctrl.sourceTables[itemTag.id].field}}" value-field="value"
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-input-number vn-one <vn-input-number vn-one

View File

@ -10,40 +10,6 @@ class Controller extends Section {
fields: ['id', 'name', 'isFree', 'sourceTable'] fields: ['id', 'name', 'isFree', 'sourceTable']
} }
}; };
this.sourceTables = {};
}
set itemTags(value) {
if (value) {
value.forEach(tag => {
this.getSourceTable(tag);
});
this._itemTags = value;
}
}
get itemTags() {
return this._itemTags;
}
getSourceTable(obj) {
let sourceTable;
this.sourceTables[obj.id] = {};
let tag = obj.tag || obj.selection;
if (!tag || !tag.sourceTable && (tag.isFree === true || tag.isFree === undefined))
sourceTable = null;
else if (tag.sourceTable) {
sourceTable = '' + tag.sourceTable.charAt(0).toUpperCase() +
tag.sourceTable.substring(1) + 's';
this.sourceTables[obj.id].field = 'name';
} else {
sourceTable = `ItemTags/filterItemTags/${tag.id}`;
this.sourceTables[obj.id].field = 'value';
}
this.sourceTables[obj.id].url = sourceTable;
} }
add() { add() {

View File

@ -16,46 +16,6 @@ describe('Item', () => {
controller = $componentController('vnItemTags', {$element, $scope}); controller = $componentController('vnItemTags', {$element, $scope});
})); }));
describe('itemTags setter', () => {
it('should call getSourceTable one time for each element in the value array', () => {
jest.spyOn(controller, 'getSourceTable');
let itemTags = [
{id: 1},
{id: 2},
{id: 3},
{id: 4}
];
controller.itemTags = itemTags;
expect(controller.getSourceTable.mock.calls.length).toEqual(4);
expect(controller.itemTags).toEqual(itemTags);
});
});
describe('getSourceTable', () => {
it('should return null when the property isFree equals true', () => {
let tag = {id: 1};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe(null);
});
it('should return the route of the model in loopback with the first char of the string uppercase and adding a s', () => {
let tag = {id: 1, tag: {sourceTable: 'ink'}};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe('Inks');
});
it('should return the route filteritemtags with the id of the selection', () => {
let tag = {id: 1, tag: {id: 3, sourceTable: null, isFree: false}};
controller.getSourceTable(tag);
expect(controller.sourceTables[1].url).toBe('ItemTags/filterItemTags/3');
});
});
describe('getHighestPriority', () => { describe('getHighestPriority', () => {
it('should return the highest priority value + 1 from the array', () => { it('should return the highest priority value + 1 from the array', () => {
let result = controller.getHighestPriority(); let result = controller.getHighestPriority();

View File

@ -23,11 +23,12 @@
<vn-autocomplete <vn-autocomplete
vn-one vn-one
ng-show="tag.selection.isFree == false" ng-show="tag.selection.isFree == false"
url="{{$ctrl.getSourceTable(tag.selection)}}" url="{{'Tags/' + tag.selection.id + '/filterValue'}}"
search-function="{value: $search}"
label="Value" label="Value"
ng-model="tagValue.value" ng-model="tagValue.value"
show-field="name" show-field="value"
value-field="name"> value-field="value">
</vn-autocomplete> </vn-autocomplete>
<vn-icon-button <vn-icon-button
vn-none vn-none

View File

@ -21,18 +21,6 @@ class Controller extends SearchPanel {
this.$.filter = value; this.$.filter = value;
} }
getSourceTable(selection) {
if (!selection || selection.isFree == true)
return null;
if (selection.sourceTable) {
return ''
+ selection.sourceTable.charAt(0).toUpperCase()
+ selection.sourceTable.substring(1) + 's';
} else if (selection.sourceTable == null)
return `ItemTags/filterItemTags/${selection.id}`;
}
addValue() { addValue() {
this.filter.values.push({}); this.filter.values.push({});
setTimeout(() => this.popover.relocate()); setTimeout(() => this.popover.relocate());

27174
package-lock.json generated

File diff suppressed because it is too large Load Diff

1743
print/package-lock.json generated

File diff suppressed because it is too large Load Diff