diff --git a/back/methods/starred-module/getStarredModules.js b/back/methods/starred-module/getStarredModules.js
index 88c0fa8a9..7b0f0e945 100644
--- a/back/methods/starred-module/getStarredModules.js
+++ b/back/methods/starred-module/getStarredModules.js
@@ -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;
+
+ let myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
const filter = {
where: {
workerFk: userId
},
- fields: ['moduleFk']
+ fields: ['id', 'workerFk', 'moduleFk', 'position'],
+ order: 'position ASC'
};
- const starredModules = await Self.app.models.StarredModule.find(filter);
-
- return starredModules;
+ return models.StarredModule.find(filter, myOptions);
};
};
diff --git a/back/methods/starred-module/setPosition.js b/back/methods/starred-module/setPosition.js
new file mode 100644
index 000000000..adfd87feb
--- /dev/null
+++ b/back/methods/starred-module/setPosition.js
@@ -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: 'action',
+ type: 'string',
+ required: true,
+ description: 'Whether to increases or decreases the module position, last if undefined'
+ }
+ ],
+ http: {
+ path: `/setPosition`,
+ verb: 'post'
+ }
+ });
+
+ Self.setPosition = async(ctx, moduleName, action, 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 (action) {
+ case 'increase':
+ operator = {lt: movingModule.position};
+ order = 'position DESC';
+ break;
+ case 'decrease':
+ 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;
+ }
+ };
+};
diff --git a/back/methods/starred-module/specs/getStarredModules.spec.js b/back/methods/starred-module/specs/getStarredModules.spec.js
index c39ed57e9..b5d2f25c8 100644
--- a/back/methods/starred-module/specs/getStarredModules.spec.js
+++ b/back/methods/starred-module/specs/getStarredModules.spec.js
@@ -19,7 +19,7 @@ describe('getStarredModules()', () => {
});
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);
expect(starredModules.length).toEqual(1);
diff --git a/back/methods/starred-module/specs/setPosition.spec.js b/back/methods/starred-module/specs/setPosition.spec.js
new file mode 100644
index 000000000..c1b566aae
--- /dev/null
+++ b/back/methods/starred-module/specs/setPosition.spec.js
@@ -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', 'increase', 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', 'decrease', 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', 'decrease', 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', 'decrease', 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;
+ }
+ });
+});
diff --git a/back/methods/starred-module/specs/toggleStarredModule.spec.js b/back/methods/starred-module/specs/toggleStarredModule.spec.js
index a765a29a0..1aed4f54a 100644
--- a/back/methods/starred-module/specs/toggleStarredModule.spec.js
+++ b/back/methods/starred-module/specs/toggleStarredModule.spec.js
@@ -27,6 +27,7 @@ describe('toggleStarredModule()', () => {
expect(starredModules.length).toEqual(1);
expect(starredModule.moduleFk).toEqual('Orders');
expect(starredModule.workerFk).toEqual(activeCtx.accessToken.userId);
+ expect(starredModule.position).toEqual(starredModules.length);
await app.models.StarredModule.toggleStarredModule(ctx, 'Orders');
starredModules = await app.models.StarredModule.getStarredModules(ctx);
diff --git a/back/methods/starred-module/toggleStarredModule.js b/back/methods/starred-module/toggleStarredModule.js
index 38d82eba4..16e14740b 100644
--- a/back/methods/starred-module/toggleStarredModule.js
+++ b/back/methods/starred-module/toggleStarredModule.js
@@ -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 filter = {
- where: {
- workerFk: userId,
- moduleFk: moduleName
+
+ 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
+ }
+ };
+
+ 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)
- await starredModule.destroy();
- else {
- return Self.app.models.StarredModule.create({
- workerFk: userId,
- moduleFk: moduleName
- });
+ return addedModule;
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
}
};
};
diff --git a/back/models/starred-module.js b/back/models/starred-module.js
index f153003ca..5753fdc85 100644
--- a/back/models/starred-module.js
+++ b/back/models/starred-module.js
@@ -1,4 +1,5 @@
module.exports = Self => {
require('../methods/starred-module/getStarredModules')(Self);
require('../methods/starred-module/toggleStarredModule')(Self);
+ require('../methods/starred-module/setPosition')(Self);
};
diff --git a/back/models/starred-module.json b/back/models/starred-module.json
index e383fa17a..ec4c3ce03 100644
--- a/back/models/starred-module.json
+++ b/back/models/starred-module.json
@@ -18,6 +18,10 @@
"moduleFk": {
"type": "string",
"required": true
+ },
+ "position": {
+ "type": "number",
+ "required": true
}
},
"relations": {
diff --git a/db/changes/10320-monitors/02-starredModule.sql b/db/changes/10320-monitors/02-starredModule.sql
new file mode 100644
index 000000000..595d9acf0
--- /dev/null
+++ b/db/changes/10320-monitors/02-starredModule.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `vn`.`starredModule`
+ ADD `position` INT NOT NULL AFTER `moduleFk`;
\ No newline at end of file
diff --git a/front/salix/components/home/home.html b/front/salix/components/home/home.html
index 2904d7d70..80e0eb8ab 100644
--- a/front/salix/components/home/home.html
+++ b/front/salix/components/home/home.html
@@ -9,18 +9,36 @@