2834-sort-starred-modules #636
|
@ -12,17 +12,23 @@ module.exports = function(Self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getStarredModules = async ctx => {
|
Self.getStarredModules = async(ctx, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
let myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
where: {
|
where: {
|
||||||
workerFk: userId
|
workerFk: userId
|
||||||
},
|
},
|
||||||
fields: ['moduleFk']
|
fields: ['id', 'workerFk', 'moduleFk', 'position'],
|
||||||
|
order: 'position ASC'
|
||||||
};
|
};
|
||||||
|
|
||||||
const starredModules = await Self.app.models.StarredModule.find(filter);
|
return models.StarredModule.find(filter, myOptions);
|
||||||
|
|
||||||
return starredModules;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
module.exports = function(Self) {
|
||||||
|
Self.remoteMethodCtx('setPosition', {
|
||||||
|
description: 'sets the position of a given module',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'moduleName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The module name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'direction',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Whether to move left or right the module position'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/setPosition`,
|
||||||
|
verb: 'post'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.setPosition = async(ctx, moduleName, direction, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
let tx;
|
||||||
|
let myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: userId,
|
||||||
|
moduleFk: moduleName
|
||||||
|
},
|
||||||
|
order: 'position DESC'
|
||||||
|
};
|
||||||
|
|
||||||
|
const [movingModule] = await models.StarredModule.find(filter, myOptions);
|
||||||
|
|
||||||
|
let operator;
|
||||||
|
let order;
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case 'left':
|
||||||
|
operator = {lt: movingModule.position};
|
||||||
|
order = 'position DESC';
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
operator = {gt: movingModule.position};
|
||||||
|
order = 'position ASC';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pushedModule = await models.StarredModule.findOne({
|
||||||
|
where: {
|
||||||
|
position: operator,
|
||||||
|
workerFk: userId
|
||||||
|
},
|
||||||
|
order: order
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (!pushedModule) return;
|
||||||
|
|
||||||
|
const movingPosition = pushedModule.position;
|
||||||
|
const pushingPosition = movingModule.position;
|
||||||
|
|
||||||
|
await movingModule.updateAttribute('position', movingPosition, myOptions);
|
||||||
|
await pushedModule.updateAttribute('position', pushingPosition, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return {
|
||||||
|
movingModule: movingModule,
|
||||||
|
pushedModule: pushedModule
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -19,7 +19,7 @@ describe('getStarredModules()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should return the starred modules for a given user`, async() => {
|
it(`should return the starred modules for a given user`, async() => {
|
||||||
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'Clients'});
|
const newStarred = await app.models.StarredModule.create({workerFk: 9, moduleFk: 'Clients', position: 1});
|
||||||
const starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
const starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
||||||
|
|
||||||
expect(starredModules.length).toEqual(1);
|
expect(starredModules.length).toEqual(1);
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('setPosition()', () => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const ctx = {
|
||||||
|
req: activeCtx
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should increase the orders module position by replacing it with clients and vice versa', async() => {
|
||||||
|
const tx = await app.models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: ctx.req.accessToken.userId,
|
||||||
|
moduleFk: 'Orders'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
|
||||||
|
let orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
let clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(orders.position).toEqual(1);
|
||||||
|
expect(clients.position).toEqual(2);
|
||||||
|
|
||||||
|
await app.models.StarredModule.setPosition(ctx, 'Clients', 'left', options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(clients.position).toEqual(1);
|
||||||
|
expect(orders.position).toEqual(2);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should decrease the orders module position by replacing it with clients and vice versa', async() => {
|
||||||
|
const tx = await app.models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: ctx.req.accessToken.userId,
|
||||||
|
moduleFk: 'Orders'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
|
||||||
|
let orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
let clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(orders.position).toEqual(1);
|
||||||
|
expect(clients.position).toEqual(2);
|
||||||
|
|
||||||
|
await app.models.StarredModule.setPosition(ctx, 'Orders', 'right', options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(orders.position).toEqual(2);
|
||||||
|
expect(clients.position).toEqual(1);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch two modules after adding and deleting several modules', async() => {
|
||||||
|
const tx = await app.models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: ctx.req.accessToken.userId,
|
||||||
|
moduleFk: 'Items'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options);
|
||||||
|
|
||||||
|
const items = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Claims';
|
||||||
|
const claims = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
let clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
let orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Zones';
|
||||||
|
const zones = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(items.position).toEqual(1);
|
||||||
|
expect(claims.position).toEqual(2);
|
||||||
|
expect(clients.position).toEqual(3);
|
||||||
|
expect(orders.position).toEqual(4);
|
||||||
|
expect(zones.position).toEqual(5);
|
||||||
|
|
||||||
|
await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(orders.position).toEqual(3);
|
||||||
|
expect(clients.position).toEqual(4);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch two modules after adding and deleting a module between them', async() => {
|
||||||
|
const tx = await app.models.StarredModule.beginTransaction({});
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: ctx.req.accessToken.userId,
|
||||||
|
moduleFk: 'Items'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options);
|
||||||
|
|
||||||
|
const items = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
let clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Claims';
|
||||||
|
const claims = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
let orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Zones';
|
||||||
|
const zones = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(items.position).toEqual(1);
|
||||||
|
expect(clients.position).toEqual(2);
|
||||||
|
expect(claims.position).toEqual(3);
|
||||||
|
expect(orders.position).toEqual(4);
|
||||||
|
expect(zones.position).toEqual(5);
|
||||||
|
|
||||||
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
|
||||||
|
await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Clients';
|
||||||
|
clients = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
filter.where.moduleFk = 'Orders';
|
||||||
|
orders = await app.models.StarredModule.findOne(filter, options);
|
||||||
|
|
||||||
|
expect(orders.position).toEqual(2);
|
||||||
|
expect(clients.position).toEqual(4);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -27,6 +27,7 @@ describe('toggleStarredModule()', () => {
|
||||||
expect(starredModules.length).toEqual(1);
|
expect(starredModules.length).toEqual(1);
|
||||||
expect(starredModule.moduleFk).toEqual('Orders');
|
expect(starredModule.moduleFk).toEqual('Orders');
|
||||||
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
|
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
|
||||||
|
expect(starredModule.position).toEqual(starredModules.length);
|
||||||
|
|
||||||
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders');
|
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders');
|
||||||
starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
starredModules = await app.models.StarredModule.getStarredModules(ctx);
|
||||||
|
|
|
@ -18,24 +18,61 @@ module.exports = function(Self) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.toggleStarredModule = async(ctx, moduleName) => {
|
Self.toggleStarredModule = async(ctx, moduleName, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const filter = {
|
|
||||||
where: {
|
let tx;
|
||||||
workerFk: userId,
|
let myOptions = {};
|
||||||
moduleFk: moduleName
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filter = {
|
||||||
|
where: {
|
||||||
|
workerFk: userId,
|
||||||
|
moduleFk: moduleName
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [starredModule] = await models.StarredModule.find(filter, myOptions);
|
||||||
|
|
||||||
|
delete filter.moduleName;
|
||||||
|
const allStarredModules = await models.StarredModule.getStarredModules(ctx, myOptions);
|
||||||
|
|
||||||
|
let addedModule;
|
||||||
|
|
||||||
|
if (starredModule)
|
||||||
|
await starredModule.destroy(myOptions);
|
||||||
|
else {
|
||||||
|
let highestPosition;
|
||||||
|
if (allStarredModules.length) {
|
||||||
|
allStarredModules.sort((a, b) => {
|
||||||
|
return a.position - b.position;
|
||||||
|
});
|
||||||
|
highestPosition = allStarredModules[allStarredModules.length - 1].position + 1;
|
||||||
|
} else
|
||||||
|
highestPosition = 1;
|
||||||
|
|
||||||
|
addedModule = await models.StarredModule.create({
|
||||||
|
workerFk: userId,
|
||||||
|
moduleFk: moduleName,
|
||||||
|
position: highestPosition
|
||||||
|
}, myOptions);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const [starredModule] = await Self.app.models.StarredModule.find(filter);
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
if (starredModule)
|
return addedModule;
|
||||||
await starredModule.destroy();
|
} catch (e) {
|
||||||
else {
|
if (tx) await tx.rollback();
|
||||||
return Self.app.models.StarredModule.create({
|
throw e;
|
||||||
workerFk: userId,
|
|
||||||
moduleFk: moduleName
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/starred-module/getStarredModules')(Self);
|
require('../methods/starred-module/getStarredModules')(Self);
|
||||||
require('../methods/starred-module/toggleStarredModule')(Self);
|
require('../methods/starred-module/toggleStarredModule')(Self);
|
||||||
|
require('../methods/starred-module/setPosition')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
"moduleFk": {
|
"moduleFk": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE `vn`.`starredModule`
|
||||||
|
ADD `position` INT NOT NULL AFTER `moduleFk`;
|
|
@ -9,18 +9,33 @@
|
||||||
<vn-icon icon="push_pin"></vn-icon>
|
<vn-icon icon="push_pin"></vn-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
<a
|
<a
|
||||||
ng-repeat="mod in ::$ctrl.modules"
|
ng-repeat="mod in $ctrl.modules | orderBy: '+position'"
|
||||||
|
ng-animate-ref="{{mod.position}}"
|
||||||
ng-if='mod.starred'
|
ng-if='mod.starred'
|
||||||
ui-sref="{{::mod.route.state}}"
|
ui-sref="{{::mod.route.state}}"
|
||||||
translate-attr="{title: mod.name}"
|
translate-attr="{title: mod.name}"
|
||||||
class="vn-shadow">
|
class="vn-shadow">
|
||||||
<div
|
<span>
|
||||||
vn-tooltip="Remove from favorites"
|
<vn-icon
|
||||||
class="pin"
|
vn-tooltip="Move left"
|
||||||
ng-click="$ctrl.toggleStarredModule(mod, $event)">
|
class="small-icon"
|
||||||
<vn-icon icon="remove_circle"></vn-icon>
|
ng-click="$ctrl.moveModule(mod, $event, 'left')"
|
||||||
</div>
|
icon="arrow_left">
|
||||||
|
</vn-icon>
|
||||||
|
<vn-icon
|
||||||
|
vn-tooltip="Remove from favorites"
|
||||||
|
class="small-icon"
|
||||||
|
ng-click="$ctrl.toggleStarredModule(mod, $event)"
|
||||||
|
icon="remove_circle">
|
||||||
|
</vn-icon>
|
||||||
|
<vn-icon
|
||||||
|
vn-tooltip="Move right"
|
||||||
|
class="small-icon"
|
||||||
|
ng-click="$ctrl.moveModule(mod, $event, 'right')"
|
||||||
|
icon="arrow_right">
|
||||||
|
</vn-icon>
|
||||||
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,17 +56,19 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
<a
|
<a
|
||||||
ng-repeat="mod in ::$ctrl.modules"
|
ng-repeat="mod in $ctrl.modules"
|
||||||
ng-if='!mod.starred'
|
ng-if='!mod.starred'
|
||||||
ui-sref="{{::mod.route.state}}"
|
ui-sref="{{::mod.route.state}}"
|
||||||
translate-attr="{title: mod.name}"
|
translate-attr="{title: mod.name}"
|
||||||
class="vn-shadow">
|
class="vn-shadow">
|
||||||
<div
|
<span>
|
||||||
vn-tooltip="Add to favorites"
|
<div
|
||||||
class="pin"
|
vn-tooltip="Add to favorites"
|
||||||
ng-click="$ctrl.toggleStarredModule(mod, $event)">
|
class="small-icon"
|
||||||
<vn-icon icon="push_pin"></vn-icon>
|
ng-click="$ctrl.toggleStarredModule(mod, $event)">
|
||||||
</div>
|
<vn-icon icon="push_pin"></vn-icon>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -35,6 +35,7 @@ export default class Controller extends Component {
|
||||||
for (let starredModule of res.data) {
|
for (let starredModule of res.data) {
|
||||||
const module = this.modules.find(mod => mod.name === starredModule.moduleFk);
|
const module = this.modules.find(mod => mod.name === starredModule.moduleFk);
|
||||||
module.starred = true;
|
module.starred = true;
|
||||||
|
module.position = starredModule.position;
|
||||||
}
|
}
|
||||||
this.countModules();
|
this.countModules();
|
||||||
});
|
});
|
||||||
|
@ -48,9 +49,10 @@ export default class Controller extends Component {
|
||||||
const params = {moduleName: module.name};
|
const params = {moduleName: module.name};
|
||||||
const query = `starredModules/toggleStarredModule`;
|
const query = `starredModules/toggleStarredModule`;
|
||||||
this.$http.post(query, params).then(res => {
|
this.$http.post(query, params).then(res => {
|
||||||
if (res.data)
|
if (res.data) {
|
||||||
module.starred = true;
|
module.starred = true;
|
||||||
else
|
module.position = res.data.position;
|
||||||
|
} else
|
||||||
module.starred = false;
|
module.starred = false;
|
||||||
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
@ -74,6 +76,26 @@ export default class Controller extends Component {
|
||||||
|
|
||||||
return this.$sce.trustAsHtml(getName(mod));
|
return this.$sce.trustAsHtml(getName(mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveModule(module, event, direction) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const params = {moduleName: module.name, direction: direction};
|
||||||
|
const query = `starredModules/setPosition`;
|
||||||
|
this.$http.post(query, params).then(res => {
|
||||||
|
if (res.data) {
|
||||||
|
module.position = res.data.movingModule.position;
|
||||||
|
this.modules.forEach(mod => {
|
||||||
|
if (mod.name == res.data.pushedModule.moduleFk)
|
||||||
|
mod.position = res.data.pushedModule.position;
|
||||||
|
});
|
||||||
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
this.countModules();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$element', '$scope', 'vnModules', '$sce'];
|
Controller.$inject = ['$element', '$scope', 'vnModules', '$sce'];
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ describe('Salix Component vnHome', () => {
|
||||||
expect(controller._modules[0].starred).toBe(true);
|
expect(controller._modules[0].starred).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should set the received module as regular if it was starred`, () => {
|
it('should set the received module as regular if it was starred', () => {
|
||||||
const event = new Event('target');
|
const event = new Event('target');
|
||||||
controller._modules = [{module: 'client', name: 'Clients', starred: true}];
|
controller._modules = [{module: 'client', name: 'Clients', starred: true}];
|
||||||
|
|
||||||
|
@ -72,4 +72,34 @@ describe('Salix Component vnHome', () => {
|
||||||
expect(controller._modules[0].starred).toBe(false);
|
expect(controller._modules[0].starred).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('moveModule()', () => {
|
||||||
|
it('should perform a query to setPosition and the apply the position to the moved and pushed modules', () => {
|
||||||
|
const starredModules = [
|
||||||
|
{id: 1, moduleFk: 'Clients', workerFk: 9},
|
||||||
|
{id: 2, moduleFk: 'Orders', workerFk: 9}
|
||||||
|
];
|
||||||
|
|
||||||
|
const movedModules = {
|
||||||
|
movingModule: {position: 2, moduleFk: 'Clients'},
|
||||||
|
pushedModule: {position: 1, moduleFk: 'Orders'}
|
||||||
|
};
|
||||||
|
const event = new Event('target');
|
||||||
|
controller._modules = [
|
||||||
|
{module: 'client', name: 'Clients', position: 1},
|
||||||
|
{module: 'orders', name: 'Orders', position: 2}
|
||||||
|
];
|
||||||
|
|
||||||
|
$httpBackend.whenRoute('GET', 'starredModules/getStarredModules').respond(starredModules);
|
||||||
|
$httpBackend.expectPOST('starredModules/setPosition').respond(movedModules);
|
||||||
|
|
||||||
|
expect(controller._modules[0].position).toEqual(1);
|
||||||
|
expect(controller._modules[1].position).toEqual(2);
|
||||||
|
controller.moveModule(controller._modules[0], event, 'right');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller._modules[0].position).toEqual(2);
|
||||||
|
expect(controller._modules[1].position).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
Favorites: Favoritos
|
Favorites: Favoritos
|
||||||
You can set modules as favorites by clicking their icon: Puedes establecer módulos como favoritos haciendo clic en el icono
|
You can set modules as favorites by clicking their icon: Puedes establecer módulos como favoritos haciendo clic en el icono
|
||||||
Add to favorites: Añadir a favoritos.
|
Add to favorites: Añadir a favoritos
|
||||||
Remove from favorites: Quitar de favoritos.
|
Remove from favorites: Quitar de favoritos
|
||||||
|
Move left: Mover a la izquierda
|
||||||
|
Move right: Mover a la derecha
|
|
@ -52,6 +52,11 @@ vn-home {
|
||||||
max-width: 704px;
|
max-width: 704px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
& > a:first-child span vn-icon[icon="arrow_left"],
|
||||||
|
& > a:last-child span vn-icon[icon="arrow_right"] {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
& > a {
|
& > a {
|
||||||
@extend %clickable-light;
|
@extend %clickable-light;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -66,19 +71,18 @@ vn-home {
|
||||||
background-color: $color-button;
|
background-color: $color-button;
|
||||||
color: $color-font-dark;
|
color: $color-font-dark;
|
||||||
|
|
||||||
& .pin {
|
& .small-icon {
|
||||||
|
display: inline-flex;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
flex-direction: row;
|
|
||||||
justify-content: left;
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
vn-icon {
|
vn-icon {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover .pin {
|
&:hover .small-icon {
|
||||||
|
flex-direction: row;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
|
|
Loading…
Reference in New Issue