[IMPROVE] Replace livechat:customFields to REST (#15496)

* Create livechat custom fields endpoints to replace pub

* Replace livechat:customFields subscribes

* Apply suggestions from review

* Add support to pagination

* Remove unecessary async
pull/15937/head
Marcos Spessatto Defendi 6 years ago committed by Renato Becker
parent 003e135a5c
commit 931e793a87
  1. 17
      app/livechat/client/views/app/livechatCustomFieldForm.js
  2. 2
      app/livechat/client/views/app/livechatCustomFields.html
  3. 39
      app/livechat/client/views/app/livechatCustomFields.js
  4. 35
      app/livechat/server/api/lib/customFields.js
  5. 33
      app/livechat/server/api/v1/customField.js
  6. 1
      app/livechat/server/publications/customFields.js
  7. 5
      app/models/server/raw/LivechatCustomField.js
  8. 3
      app/models/server/raw/index.js
  9. 61
      tests/end-to-end/api/livechat/custom-fields.js

@ -5,8 +5,8 @@ import { Template } from 'meteor/templating';
import toastr from 'toastr';
import { t, handleError } from '../../../../utils';
import { LivechatCustomField } from '../../collections/LivechatCustomField';
import './livechatCustomFieldForm.html';
import { APIClient } from '../../../../utils/client';
Template.livechatCustomFieldForm.helpers({
customField() {
@ -60,15 +60,10 @@ Template.livechatCustomFieldForm.events({
},
});
Template.livechatCustomFieldForm.onCreated(function() {
Template.livechatCustomFieldForm.onCreated(async function() {
this.customField = new ReactiveVar({});
this.autorun(() => {
const sub = this.subscribe('livechat:customFields', FlowRouter.getParam('_id'));
if (sub.ready()) {
const customField = LivechatCustomField.findOne({ _id: FlowRouter.getParam('_id') });
if (customField) {
this.customField.set(customField);
}
}
});
const { customField } = await APIClient.v1.get(`livechat/custom-fields/${ FlowRouter.getParam('_id') }`);
if (customField) {
this.customField.set(customField);
}
});

@ -1,7 +1,7 @@
<template name="livechatCustomFields">
{{#requiresPermission 'view-livechat-customfields'}}
<div class="rc-table-content">
{{#table fixed='true'}}
{{#table fixed='true' onScroll=onTableScroll}}
<thead>
<tr>
<th><div class="table-fake-th">{{_ "Field"}}</div></th>

@ -1,20 +1,35 @@
import { Meteor } from 'meteor/meteor';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { modal } from '../../../../ui-utils';
import { t, handleError } from '../../../../utils';
import { LivechatCustomField } from '../../collections/LivechatCustomField';
import { t, handleError, APIClient } from '../../../../utils/client';
import './livechatCustomFields.html';
const CUSTOM_FIELDS_COUNT = 50;
Template.livechatCustomFields.helpers({
customFields() {
return LivechatCustomField.find();
return Template.instance().customFields.get();
},
onTableScroll() {
const instance = Template.instance();
return function(currentTarget) {
if (currentTarget.offsetHeight + currentTarget.scrollTop < currentTarget.scrollHeight - 100) {
return;
}
const customFields = instance.customFields.get();
if (instance.total.get() <= customFields.length) {
return;
}
return instance.offset.set(instance.offset.get() + CUSTOM_FIELDS_COUNT);
};
},
});
Template.livechatCustomFields.events({
'click .remove-custom-field'(e) {
'click .remove-custom-field'(e, instance) {
e.preventDefault();
e.stopPropagation();
@ -32,6 +47,7 @@ Template.livechatCustomFields.events({
if (error) {
return handleError(error);
}
instance.offset.set(0);
modal.open({
title: t('Removed'),
text: t('Field_removed'),
@ -50,5 +66,18 @@ Template.livechatCustomFields.events({
});
Template.livechatCustomFields.onCreated(function() {
this.subscribe('livechat:customFields');
this.customFields = new ReactiveVar([]);
this.offset = new ReactiveVar(0);
this.total = new ReactiveVar(0);
this.autorun(async () => {
const offset = this.offset.get();
const { customFields, total } = await APIClient.v1.get(`livechat/custom-fields?count=${ CUSTOM_FIELDS_COUNT }&offset=${ offset }`);
if (offset === 0) {
this.customFields.set(customFields);
} else {
this.customFields.set(this.customFields.get().concat(customFields));
}
this.total.set(total);
});
});

@ -0,0 +1,35 @@
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { LivechatCustomField } from '../../../../models/server/raw';
export async function findLivechatCustomFields({ userId, pagination: { offset, count, sort } }) {
if (!await hasPermissionAsync(userId, 'view-l-room')) {
throw new Error('error-not-authorized');
}
const cursor = await LivechatCustomField.find({}, {
sort: sort || { label: 1 },
skip: offset,
limit: count,
});
const total = await cursor.count();
const customFields = await cursor.toArray();
return {
customFields,
count: customFields.length,
offset,
total,
};
}
export async function findCustomFieldById({ userId, customFieldId }) {
if (!await hasPermissionAsync(userId, 'view-l-room')) {
throw new Error('error-not-authorized');
}
return {
customField: await LivechatCustomField.findOneById(customFieldId),
};
}

@ -4,6 +4,7 @@ import { Match, check } from 'meteor/check';
import { API } from '../../../../api';
import { findGuest } from '../lib/livechat';
import { Livechat } from '../../lib/Livechat';
import { findLivechatCustomFields, findCustomFieldById } from '../lib/customFields';
API.v1.addRoute('livechat/custom.field', {
post() {
@ -64,3 +65,35 @@ API.v1.addRoute('livechat/custom.fields', {
return API.v1.success({ fields });
},
});
API.v1.addRoute('livechat/custom-fields', { authRequired: true }, {
get() {
const { offset, count } = this.getPaginationItems();
const { sort } = this.parseJsonQuery();
const customFields = Promise.await(findLivechatCustomFields({
userId: this.userId,
pagination: {
offset,
count,
sort,
},
}));
return API.v1.success(customFields);
},
});
API.v1.addRoute('livechat/custom-fields/:_id', { authRequired: true }, {
get() {
check(this.urlParams, {
_id: String,
});
const { customField } = Promise.await(findCustomFieldById({ userId: this.userId, customFieldId: this.urlParams._id }));
return API.v1.success({
customField,
});
},
});

@ -5,6 +5,7 @@ import { hasPermission } from '../../../authorization';
import { LivechatCustomField } from '../../../models';
Meteor.publish('livechat:customFields', function(_id) {
console.warn('The publication "livechat:customFields" is deprecated and will be removed after version v3.0.0');
if (!this.userId) {
return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:customFields' }));
}

@ -0,0 +1,5 @@
import { BaseRaw } from './BaseRaw';
export class LivechatCustomFieldRaw extends BaseRaw {
}

@ -10,6 +10,8 @@ import UsersModel from '../models/Users';
import { UsersRaw } from './Users';
import RoomsModel from '../models/Rooms';
import { RoomsRaw } from './Rooms';
import LivechatCustomFieldModel from '../models/LivechatCustomField';
import { LivechatCustomFieldRaw } from './LivechatCustomField';
import LivechatTriggerModel from '../models/LivechatTrigger';
import { LivechatTriggerRaw } from './LivechatTrigger';
import LivechatDepartmentModel from '../models/LivechatDepartment';
@ -31,6 +33,7 @@ export const Subscriptions = new SubscriptionsRaw(SubscriptionsModel.model.rawCo
export const Settings = new SettingsRaw(SettingsModel.model.rawCollection());
export const Users = new UsersRaw(UsersModel.model.rawCollection());
export const Rooms = new RoomsRaw(RoomsModel.model.rawCollection());
export const LivechatCustomField = new LivechatCustomFieldRaw(LivechatCustomFieldModel.model.rawCollection());
export const LivechatTrigger = new LivechatTriggerRaw(LivechatTriggerModel.model.rawCollection());
export const LivechatDepartment = new LivechatDepartmentRaw(LivechatDepartmentModel.model.rawCollection());
export const LivechatDepartmentAgents = new LivechatDepartmentAgentsRaw(LivechatDepartmentAgentsModel.model.rawCollection());

@ -0,0 +1,61 @@
import { getCredentials, api, request, credentials } from '../../../data/api-data.js';
import { updatePermission, updateSetting } from '../../../data/permissions.helper';
describe('LIVECHAT - custom fields', function() {
this.retries(0);
before((done) => getCredentials(done));
before((done) => {
updateSetting('Livechat_enabled', true).then(done);
});
describe('livechat/custom-fields', () => {
it('should return an "unauthorized error" when the user does not have the necessary permission', (done) => {
updatePermission('view-l-room', []).then(() => {
request.get(api('livechat/custom-fields'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.error).to.be.equal('error-not-authorized');
})
.end(done);
});
});
it('should return an array of custom fields', (done) => {
updatePermission('view-l-room', ['admin'])
.then(() => {
request.get(api('livechat/custom-fields'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body.customFields).to.be.an('array');
expect(res.body).to.have.property('offset');
expect(res.body).to.have.property('total');
expect(res.body).to.have.property('count');
})
.end(done);
});
});
});
describe('livechat/custom-fields/id', () => {
it('should return an "unauthorized error" when the user does not have the necessary permission', (done) => {
updatePermission('view-l-room', []).then(() => {
request.get(api('livechat/custom-fields/invalid-id'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.error).to.be.equal('error-not-authorized');
})
.end(() => updatePermission('view-l-room', ['admin']).then(done));
});
});
});
});
Loading…
Cancel
Save