Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
f5c6d6d
Change omnichannel office hours data structure
Jun 4, 2020
387e801
Rename omnichannel office hours templates
Jun 4, 2020
6d4b2e6
Renaming things from office hour to business hour
Jun 5, 2020
a1adbbd
Partially remove LivechatOfficeHour model
Jun 5, 2020
4803883
remove obsolete setting
Jun 5, 2020
ebd93a9
Remove settings from the template
Jun 5, 2020
5a911b3
Add support to cron jobs on omnichannel business hours
Jun 9, 2020
acf7b70
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 9, 2020
4f93201
Add dynamic template to omnichannel business hours
Jun 9, 2020
7d3e345
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 9, 2020
d94d750
Open and close business hours
Jun 12, 2020
d3e2670
Remove references to LivechatOfficeHours
Jun 12, 2020
bb4c82b
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 12, 2020
25c4d88
Open and close business hour automatically on startup and setting cha…
Jun 15, 2020
1becb7c
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 15, 2020
a2b2c9b
Improve open and close business hours process
Jun 16, 2020
c496ca2
Removing separated interfaces
Jun 16, 2020
388afa0
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 16, 2020
e0a0021
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 17, 2020
0b05ad8
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 17, 2020
9371c3d
Apply suggestions from review
Jun 17, 2020
83e32f5
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 17, 2020
c890eb1
Basic configuration to support multiple business hours
Jun 18, 2020
5b866a3
Basic business hour insert and update operations
Jun 18, 2020
931fa51
Remove business hour
Jun 18, 2020
19e6288
Open multiple business hours automatically when the server starts
Jun 19, 2020
5f2bd37
Fix leak of business logic
Jun 19, 2020
1e133e5
Open multiple business hours
Jun 19, 2020
4c3cda8
Close multiple business hour
Jun 19, 2020
7765960
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 19, 2020
36f3673
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 19, 2020
7e48e71
Changing pt-br term
Jun 19, 2020
c22bd6d
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 19, 2020
96bf764
General improvements on business hour layout
Jun 19, 2020
572ecea
Merge remote-tracking branch 'origin/improvements/refactor-livechat-o…
Jun 19, 2020
caeb16e
UI improvements
Jun 19, 2020
4e74a73
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 19, 2020
243cf63
Apply suggestions from review
Jun 19, 2020
113f364
Add departments conditions
Jun 20, 2020
c76348c
Close business hours when remove department
Jun 20, 2020
5554c67
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 20, 2020
4e6bd27
Remove online verification
Jun 20, 2020
87ff84c
Refactor business hour to new data structure
Jun 20, 2020
e788448
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 20, 2020
ef33a6a
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 20, 2020
b724b3f
Change data structure
Jun 21, 2020
ad3f2d7
Ignore if collection does not exist
Jun 21, 2020
704c2e1
Merge branch 'develop' into improvements/refactor-livechat-office-hours
Jun 21, 2020
25218ee
Merge remote-tracking branch 'origin/improvements/refactor-livechat-o…
Jun 21, 2020
b5f3cc8
Merge branch 'develop' into improvements/refactor-livechat-office-hours
renatobecker Jun 21, 2020
ed5f027
Merge branch 'improvements/refactor-livechat-office-hours' into feat/…
Jun 21, 2020
c6eb73f
Fix businessHourManager startup.
renatobecker Jun 21, 2020
e87e2aa
Remove console log.
renatobecker Jun 21, 2020
db5a462
Fix Multiple business hours
Jun 21, 2020
448ac62
Merge remote-tracking branch 'origin/feat/multiple-business-hours' in…
Jun 21, 2020
805a518
Merge branch 'develop' into feat/multiple-business-hours
Jun 21, 2020
478019d
Merge branch 'develop' into feat/multiple-business-hours
renatobecker Jun 21, 2020
a1caa5e
open/close business hours when removing/adding agent to department.
renatobecker Jun 21, 2020
ff81137
Improve code
Jun 21, 2020
32c2e02
Fix error on creating department.
renatobecker Jun 21, 2020
24e7b39
Add set to default when it is the last department
Jun 22, 2020
f8fc7fb
Fix wrong condition
Jun 22, 2020
8d72b7a
Merge branch 'develop' into feat/multiple-business-hours
renatobecker Jun 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/livechat/client/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const livechatManagerRoutes = FlowRouter.group({
name: 'livechat-manager',
});

const load = () => import('./views/admin');
export const load = () => import('./views/admin');

AccountBox.addRoute({
name: 'livechat-dashboard',
Expand Down
29 changes: 17 additions & 12 deletions app/livechat/client/views/app/business-hours/BusinessHours.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import { Meteor } from 'meteor/meteor';

import { IBusinessHour } from './IBusinessHour';
import { SingleBusinessHour } from './Single';
import { callbacks } from '../../../../../callbacks/client';
import { ILivechatBusinessHour } from '../../../../../../definition/ILivechatBusinessHour';

class BusinessHoursManager {
private businessHour: IBusinessHour;

onStartBusinessHourManager(businessHour: IBusinessHour): void {
this.registerBusinessHour(businessHour);
constructor(businessHour: IBusinessHour) {
this.setBusinessHourManager(businessHour);
}

setBusinessHourManager(businessHour: IBusinessHour): void {
this.registerBusinessHourMethod(businessHour);
}

registerBusinessHour(businessHour: IBusinessHour): void {
registerBusinessHourMethod(businessHour: IBusinessHour): void {
this.businessHour = businessHour;
}

getTemplate(): string {
return this.businessHour.getView();
}
}

export const businessHourManager = new BusinessHoursManager();
shouldShowCustomTemplate(businessHourData: ILivechatBusinessHour): boolean {
return this.businessHour.shouldShowCustomTemplate(businessHourData);
}

shouldShowBackButton(): boolean {
return this.businessHour.shouldShowBackButton();
}
}

Meteor.startup(() => {
const { BusinessHourClass } = callbacks.run('on-business-hour-start', { BusinessHourClass: SingleBusinessHour });
businessHourManager.onStartBusinessHourManager(new BusinessHourClass() as IBusinessHour);
});
export const businessHourManager = new BusinessHoursManager(new SingleBusinessHour() as IBusinessHour);
4 changes: 4 additions & 0 deletions app/livechat/client/views/app/business-hours/IBusinessHour.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { ILivechatBusinessHour } from '../../../../../../definition/ILivechatBusinessHour';

export interface IBusinessHour {
getView(): string;
shouldShowCustomTemplate(businessHourData: ILivechatBusinessHour): boolean;
shouldShowBackButton(): boolean;
}
8 changes: 8 additions & 0 deletions app/livechat/client/views/app/business-hours/Single.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ export class SingleBusinessHour implements IBusinessHour {
getView(): string {
return 'livechatBusinessHoursForm';
}

shouldShowCustomTemplate(): boolean {
return false;
}

shouldShowBackButton(): boolean {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@
{{#requiresPermission 'view-livechat-business-hours'}}
<form class="rocket-form" id="businessHoursForm">

{{#if customFieldsTemplate}}
{{> Template.dynamic template=customFieldsTemplate data=data }}
{{/if}}

<!-- days open -->
<fieldset>
<legend>{{_ "Open_days_of_the_week"}}</legend>
{{#each day in days}}
{{#if open day}}
<label class="dayOpenCheck"><input type="checkbox" name={{openName day}} checked>{{name day}}
</label>
<label class="dayOpenCheck"><input type="checkbox" name={{openName day}} checked>{{name
day}}</label>
{{else}}
<label class="dayOpenCheck"><input type="checkbox" name={{openName day}}>{{name day}}</label>
<label class="dayOpenCheck"><input type="checkbox" name={{openName day}}>{{name day}}
</label>
{{/if}}
{{/each}}
</fieldset>
Expand All @@ -29,14 +34,16 @@ <h1><strong>{{name day}}</strong></h1>
<tr>
<td>
<div style="margin-right:30px">
<input type="time" class="preview-settings rc-input__element" name={{startName
day}} id={{startName day}} value={{start day}} style="width=100px;">
<input type="time" class="preview-settings rc-input__element"
name={{startName day}} id={{startName day}} value={{start day}}
style="width=100px;">
</div>
</td>
<td>
<div style="margin-right:30px">
<input type="time" class="preview-settings rc-input__element" name={{finishName
day}} id={{finishName day}} value={{finish day}} style="width=100px;">
<input type="time" class="preview-settings rc-input__element"
name={{finishName day}} id={{finishName day}} value={{finish day}}
style="width=100px;">
</div>
</td>
</tr>
Expand All @@ -46,8 +53,9 @@ <h1><strong>{{name day}}</strong></h1>
</fieldset>


<div class="rc-button__group submit">
<button class="rc-button rc-button--primary"><i class="icon-floppy"></i>{{_ "Save"}}</button>
<div class="rc-button__group">
{{#if showBackButton}}<button class="rc-button back" type="button"><i class="icon-left-big"></i><span>{{_ "Back"}}</span></button>{{/if}}
<button class="rc-button rc-button--primary save"><i class="icon-floppy"></i><span>{{_ "Save"}}</span></button>
</div>
</form>
{{/requiresPermission}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import { Template } from 'meteor/templating';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import { FlowRouter } from 'meteor/kadira:flow-router';
import toastr from 'toastr';
import moment from 'moment';

import { t, handleError, APIClient } from '../../../../../utils/client';
import './livechatBusinessHoursForm.html';
import { getCustomFormTemplate } from '../customTemplates/register';
import { businessHourManager } from './BusinessHours';

Template.livechatBusinessHoursForm.helpers({
days() {
Expand All @@ -33,6 +36,18 @@ Template.livechatBusinessHoursForm.helpers({
open(day) {
return Template.instance().dayVars[day.day].open.get();
},
customFieldsTemplate() {
if (!businessHourManager.shouldShowCustomTemplate(Template.instance().businessHour.get())) {
return;
}
return getCustomFormTemplate('livechatBusinessHoursForm');
},
showBackButton() {
return businessHourManager.shouldShowBackButton();
},
data() {
return Template.instance().businessHour;
},
});

const splitDayAndPeriod = (value) => value.split('_');
Expand Down Expand Up @@ -69,6 +84,12 @@ Template.livechatBusinessHoursForm.events({
instance[e.currentTarget.name].set(value);
}
},

'click button.back'(e/* , instance*/) {
e.preventDefault();
FlowRouter.go('livechat-business-hours');
},

'submit .rocket-form'(e, instance) {
e.preventDefault();

Expand All @@ -87,14 +108,23 @@ Template.livechatBusinessHoursForm.events({
});
}
}
Meteor.call('livechat:saveBusinessHour', {

const businessHourData = {
...instance.businessHour.get(),
workHours: days,
}, function(err /* ,result*/) {
};

instance.$('.customFormField').each((i, el) => {
const elField = instance.$(el);
const name = elField.attr('name');
businessHourData[name] = elField.val();
});
Meteor.call('livechat:saveBusinessHour', businessHourData, function(err /* ,result*/) {
if (err) {
return handleError(err);
}
toastr.success(t('Business_hours_updated'));
FlowRouter.go('livechat-business-hours');
});
},
});
Expand All @@ -112,7 +142,6 @@ const createDefaultBusinessHour = () => {
};
};


Template.livechatBusinessHoursForm.onCreated(async function() {
this.dayVars = createDefaultBusinessHour().workHours.reduce((acc, day) => {
acc[day.day] = {
Expand All @@ -124,21 +153,28 @@ Template.livechatBusinessHoursForm.onCreated(async function() {
}, {});
this.businessHour = new ReactiveVar({});

const { businessHour } = await APIClient.v1.get('livechat/business-hour');
this.businessHour.set({
...createDefaultBusinessHour(),
});
if (businessHour) {
this.businessHour.set(businessHour);
businessHour.workHours.forEach((d) => {
if (businessHour.timezone.name) {
this.dayVars[d.day].start.set(moment.utc(d.start.utc.time, 'HH:mm').tz(businessHour.timezone.name).format('HH:mm'));
this.dayVars[d.day].finish.set(moment.utc(d.finish.utc.time, 'HH:mm').tz(businessHour.timezone.name).format('HH:mm'));
} else {
this.dayVars[d.day].start.set(moment.utc(d.start.utc.time, 'HH:mm').local().format('HH:mm'));
this.dayVars[d.day].finish.set(moment.utc(d.finish.utc.time, 'HH:mm').local().format('HH:mm'));
}
this.dayVars[d.day].open.set(d.open);
});
}
this.autorun(async () => {
const id = FlowRouter.getParam('_id');
let url = 'livechat/business-hour';
if (id) {
url += `?_id=${ id }`;
}
const { businessHour } = await APIClient.v1.get(url);
if (businessHour) {
this.businessHour.set(businessHour);
businessHour.workHours.forEach((d) => {
if (businessHour.timezone.name) {
this.dayVars[d.day].start.set(moment.utc(d.start.utc.time, 'HH:mm').tz(businessHour.timezone.name).format('HH:mm'));
this.dayVars[d.day].finish.set(moment.utc(d.finish.utc.time, 'HH:mm').tz(businessHour.timezone.name).format('HH:mm'));
} else {
this.dayVars[d.day].start.set(moment.utc(d.start.utc.time, 'HH:mm').local().format('HH:mm'));
this.dayVars[d.day].finish.set(moment.utc(d.finish.utc.time, 'HH:mm').local().format('HH:mm'));
}
this.dayVars[d.day].open.set(d.open);
});
}
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<template name="livechatMainBusinessHours">
{{#requiresPermission 'view-livechat-business-hours'}}
<div class="livechat-businessHours-div">
{{> Template.dynamic template=getTemplate}}
</div>
{{> Template.dynamic template=getTemplate}}
{{/requiresPermission}}
</template>
2 changes: 2 additions & 0 deletions app/livechat/client/views/app/customTemplates/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export const customFormTemplate = new Map();

export const addCustomFormTemplate = (form, customTemplateName) => customFormTemplate.set(form, customTemplateName);

export const removeCustomTemplate = (form) => customFormTemplate.delete(form);

export const getCustomFormTemplate = (form) => customFormTemplate.get(form);
47 changes: 44 additions & 3 deletions app/livechat/server/business-hour/AbstractBusinessHour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ import { LivechatBusinessHours, Users } from '../../../models/server/raw';
export interface IBusinessHour {
saveBusinessHour(businessHourData: ILivechatBusinessHour): Promise<void>;
allowAgentChangeServiceStatus(agentId: string): Promise<boolean>;
getBusinessHour(id: string): Promise<ILivechatBusinessHour>;
getBusinessHour(id: string): Promise<ILivechatBusinessHour | undefined>;
findHoursToCreateJobs(): Promise<IWorkHoursForCreateCronJobs[]>;
openBusinessHoursByDayHour(day: string, hour: string): Promise<void>;
closeBusinessHoursByDayAndHour(day: string, hour: string): Promise<void>;
removeBusinessHoursFromUsers(): Promise<void>;
removeBusinessHourById(id: string): Promise<void>;
removeBusinessHourFromUsers(departmentId: string, businessHourId: string): Promise<void>;
openBusinessHoursIfNeeded(): Promise<void>;
removeBusinessHourFromUsersByIds(userIds: string[], businessHourId: string): Promise<void>;
addBusinessHourToUsersByIds(userIds: string[], businessHourId: string): Promise<void>;
setDefaultToUsersIfNeeded(userIds: string[]): Promise<void>;
}

export abstract class AbstractBusinessHour {
Expand All @@ -36,10 +41,10 @@ export abstract class AbstractBusinessHour {
await this.UsersRepository.updateLivechatStatusBasedOnBusinessHours();
}

protected async getBusinessHoursThatMustBeOpened(day: string, currentTime: any, activeBusinessHours: ILivechatBusinessHour[]): Promise<Record<string, any>[]> {
protected async getBusinessHoursThatMustBeOpened(currentTime: any, activeBusinessHours: ILivechatBusinessHour[]): Promise<Record<string, any>[]> {
return activeBusinessHours
.filter((businessHour) => businessHour.workHours
.filter((hour) => hour.start.cron.dayOfWeek === day)
.filter((hour) => hour.open)
.some((hour) => {
const localTimeStart = moment(`${ hour.start.cron.dayOfWeek }:${ hour.start.cron.time }`, 'dddd:HH:mm');
const localTimeFinish = moment(`${ hour.finish.cron.dayOfWeek }:${ hour.finish.cron.time }`, 'dddd:HH:mm');
Expand All @@ -50,4 +55,40 @@ export abstract class AbstractBusinessHour {
type: businessHour.type,
}));
}

protected convertWorkHoursWithServerTimezone(businessHourData: ILivechatBusinessHour): ILivechatBusinessHour {
businessHourData.workHours.forEach((hour: any) => {
hour.start = {
time: hour.start,
utc: {
dayOfWeek: this.formatDayOfTheWeekFromUTC(`${ hour.day }:${ hour.start }`, 'dddd'),
time: this.formatDayOfTheWeekFromUTC(`${ hour.day }:${ hour.start }`, 'HH:mm'),
},
cron: {
dayOfWeek: this.formatDayOfTheWeekFromServerTimezone(`${ hour.day }:${ hour.start }`, 'dddd'),
time: this.formatDayOfTheWeekFromServerTimezone(`${ hour.day }:${ hour.start }`, ' HH:mm'),
},
};
hour.finish = {
time: hour.finish,
utc: {
dayOfWeek: this.formatDayOfTheWeekFromUTC(`${ hour.day }:${ hour.finish }`, 'dddd'),
time: this.formatDayOfTheWeekFromUTC(`${ hour.day }:${ hour.finish }`, 'HH:mm'),
},
cron: {
dayOfWeek: this.formatDayOfTheWeekFromServerTimezone(`${ hour.day }:${ hour.finish }`, 'dddd'),
time: this.formatDayOfTheWeekFromServerTimezone(`${ hour.day }:${ hour.finish }`, 'HH:mm'),
},
};
});
return businessHourData;
}

protected formatDayOfTheWeekFromServerTimezone(hour: string, format: string): string {
return moment(hour, 'dddd:HH:mm').format(format);
}

protected formatDayOfTheWeekFromUTC(hour: string, format: string): string {
return moment(hour, 'dddd:HH:mm').utc().format(format);
}
}
Loading