import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import connect from 'dojo/_base/connect';
import string from 'dojo/string';
import environment from '../../Environment';
import validator from '../../Validator';
import utility from 'argos/Utility';
import Edit from 'argos/Edit';
import recur from '../../Recurrence';
import format from 'argos/Format';
import getResource from 'argos/I18n';
import MODEL_NAMES from '../../Models/Names';
import { getPicklistByActivityType } from '../../Models/Activity/ActivityTypePicklists';
const resource = getResource('activityEdit');
const dtFormatResource = getResource('activityEditDateTimeFormat');
/**
* @class crm.Views.Activity.Edit
* @extends argos.Edit
*
*/
const __class = declare('crm.Views.Activity.Edit', [Edit], /** @lends crm.Views.Activity.Edit# */{
// Localization
activityCategoryTitleText: resource.activityCategoryTitleText,
activityDescriptionTitleText: resource.activityDescriptionTitleText,
locationText: resource.locationText,
activityTypeTitleText: resource.activityTypeTitleText,
alarmText: resource.alarmText,
reminderText: resource.reminderText,
categoryText: resource.categoryText,
durationText: resource.durationText,
durationTitleText: resource.durationTitleText,
durationInvalidText: resource.durationInvalidText,
reminderInvalidText: resource.reminderInvalidText,
reminderTitleText: resource.reminderInvalidText,
leaderText: resource.leaderText,
longNotesText: resource.longNotesText,
longNotesTitleText: resource.longNotesTitleText,
priorityText: resource.priorityText,
priorityTitleText: resource.priorityTitleText,
regardingText: resource.regardingText,
rolloverText: resource.rolloverText,
startingText: resource.startingText,
startingFormatText: dtFormatResource.startingFormatText,
startingFormatText24: dtFormatResource.startingFormatText24,
startingTimelessFormatText: dtFormatResource.startingTimelessFormatText,
repeatsText: resource.repeatsText,
recurringText: resource.recurringText,
recurringTitleText: resource.recurringTitleText,
timelessText: resource.timelessText,
titleText: resource.titleText,
typeText: resource.typeText,
accountText: resource.accountText,
contactText: resource.contactText,
opportunityText: resource.opportunityText,
ticketNumberText: resource.ticketNumberText,
companyText: resource.companyText,
leadText: resource.leadText,
isLeadText: resource.isLeadText,
yesText: resource.yesText,
noText: resource.noText,
phoneText: resource.phoneText,
updateUserActErrorText: resource.updateUserActErrorText,
reminderValueText: {
0: resource.noneText,
5: resource.fiveMinText,
15: resource.quarterHourText,
30: resource.halfHourText,
60: resource.hourText,
1440: resource.dayText,
},
durationValueText: {
0: resource.noneText,
15: resource.quarterHourText,
30: resource.halfHourText,
60: resource.hourText,
90: resource.hourAndHalfText,
120: resource.twoHoursText,
},
/**
* @property {Number}
* The number of minutes that should be rounded to as a default start when creating a new activity
*/
ROUND_MINUTES: 15,
// View Properties
id: 'activity_edit',
detailView: 'activity_detail',
fieldsForLeads: ['AccountName', 'Lead'],
fieldsForStandard: ['Account', 'Contact', 'Opportunity', 'Ticket'],
/**
* @deprecated Use ActivityTypePicklists from Modes/Activity/ActivityTypePicklists instead
*/
picklistsByType: {
atAppointment: {
Category: 'Meeting Category Codes',
Description: 'Meeting Regarding',
},
atLiterature: {
Description: 'Lit Request Regarding',
},
atPersonal: {
Category: 'Meeting Category Codes',
Description: 'Personal Activity Regarding',
},
atPhoneCall: {
Category: 'Phone Call Category Codes',
Description: 'Phone Call Regarding',
},
atToDo: {
Category: 'To Do Category Codes',
Description: 'To Do Regarding',
},
atEMail: {
Category: 'E-mail Category Codes',
Description: 'E-mail Regarding',
},
},
groupOptionsByType: {
atToDo: 'ActivityToDoOptions',
atPersonal: 'ActivityPersonalOptions',
atPhoneCall: 'ActivityPhoneOptions',
atAppointment: 'ActivityMeetingOptions',
},
entityName: 'Activity',
modelName: MODEL_NAMES.ACTIVITY,
insertSecurity: null, // 'Entities/Activity/Add',
updateSecurity: null, // 'Entities/Activity/Edit',
contractName: 'system',
resourceKind: 'activities',
recurrence: null,
_previousRecurrence: null,
init: function init() {
this.inherited(arguments);
this.recurrence = {
RecurIterations: '0',
RecurPeriod: '-1',
RecurPeriodSpec: '0',
};
this.connect(this.fields.Lead, 'onChange', this.onLeadChange);
this.connect(this.fields.IsLead, 'onChange', this.onIsLeadChange);
this.connect(this.fields.Leader, 'onChange', this.onLeaderChange);
this.connect(this.fields.Timeless, 'onChange', this.onTimelessChange);
this.connect(this.fields.Alarm, 'onChange', this.onAlarmChange);
this.connect(this.fields.Account, 'onChange', this.onAccountChange);
this.connect(this.fields.Contact, 'onChange', this.onContactChange);
this.connect(this.fields.Opportunity, 'onChange', this.onOpportunityChange);
this.connect(this.fields.Ticket, 'onChange', this.onTicketChange);
this.connect(this.fields.StartDate, 'onChange', this.onStartDateChange);
this.connect(this.fields.RecurrenceUI, 'onChange', this.onRecurrenceUIChange);
this.connect(this.fields.Recurrence, 'onChange', this.onRecurrenceChange);
},
onAddComplete: function onAddComplete() {
environment.refreshActivityLists();
this.inherited(arguments);
},
onPutComplete: function onPutComplete(entry, updatedEntry) {
const view = App.getView(this.detailView);
const originalKey = (this.options.entry && this.options.entry.$key) || updatedEntry.$key;
this.enable();
environment.refreshActivityLists();
connect.publish('/app/refresh', [{
resourceKind: this.resourceKind,
key: updatedEntry.$key,
data: updatedEntry,
}]);
if (updatedEntry.$key !== originalKey && view) {
// Editing single occurrence results in new $key/record
view.show({
key: updatedEntry.$key,
}, {
returnTo: -2,
});
} else {
this.onUpdateCompleted(updatedEntry);
}
},
convertEntry: function convertEntry() {
const entry = this.inherited(arguments);
if (!this.options.entry) {
if (entry && entry.Leader.$key) {
this.requestLeader(entry.Leader.$key);
}
}
return entry;
},
requestLeader: function requestLeader(userId) {
const request = new Sage.SData.Client.SDataSingleResourceRequest(this.getConnection())
.setResourceKind('users')
.setResourceSelector(`'${userId}'`)
.setQueryArg('select', [
'UserInfo/FirstName',
'UserInfo/LastName',
].join(','));
request.read({
success: this.processLeader,
failure: this.requestLeaderFailure,
scope: this,
});
},
requestLeaderFailure: function requestLeaderFailure() {},
processLeader: function processLeader(leader) {
if (leader) {
this.entry.Leader = leader;
this.fields.Leader.setValue(leader);
}
},
currentUserCanEdit: function currentUserCanEdit(entry) {
return (entry && (entry.AllowEdit));
},
currentUserCanSetAlarm: function currentUserCanSetAlarm(entry) {
return !!entry && (entry.Leader.$key === App.context.user.$key);
},
isActivityForLead: function isActivityForLead(entry) {
return entry && /^[\w]{12}$/.test(entry.LeadId);
},
isActivityRecurring: function isActivityRecurring() {
return (/rstMaster/)
.test(this.fields.RecurrenceState.getValue());
},
isInLeadContext: function isInLeadContext() {
const insert = this.options && this.options.insert;
const entry = this.options && this.options.entry;
const context = this._getNavContext();
let isLeadContext = false;
if (context.resourceKind === 'leads') {
isLeadContext = true;
}
const lead = (insert && isLeadContext) || this.isActivityForLead(entry);
return !!lead;
},
beforeTransitionTo: function beforeTransitionTo() {
this.inherited(arguments);
// we hide the lead or standard fields here, as the view is currently hidden, in order to prevent flashing.
// the value for the 'IsLead' field will be set later, based on the value derived here.
if (this.options.isForLead !== undefined) {
return;
}
this.options.isForLead = this.isInLeadContext();
if (this.options.isForLead) {
this.showFieldsForLead();
} else {
this.showFieldsForStandard();
}
},
disableFields: function disableFields(predicate) {
for (const name in this.fields) {
if (!predicate || predicate(this.fields[name])) {
this.fields[name].disable();
}
}
},
enableFields: function enableFields(predicate) {
for (const name in this.fields) {
if (!predicate || predicate(this.fields[name])) {
this.fields[name].enable();
}
}
},
onIsLeadChange: function onIsLeadChange(value) {
this.options.isForLead = value;
if (this.options.isForLead) {
this.showFieldsForLead();
} else {
this.showFieldsForStandard();
}
},
showFieldsForLead: function showFieldsForLead() {
this.fieldsForStandard.concat(this.fieldsForLeads).forEach((item) => {
if (this.fields[item]) {
this.fields[item].hide();
}
}, this);
this.fieldsForLeads.forEach((item) => {
if (this.fields[item]) {
this.fields[item].show();
}
}, this);
},
showFieldsForStandard: function showFieldsForStandard() {
this.fieldsForStandard.concat(this.fieldsForLeads).forEach((item) => {
if (this.fields[item]) {
this.fields[item].hide();
}
}, this);
this.fieldsForStandard.forEach((item) => {
if (this.fields[item]) {
this.fields[item].show();
}
}, this);
},
toggleSelectField: function toggleSelectField(field, disable) {
if (disable) {
field.disable();
} else {
field.enable();
}
},
onTimelessChange: function onTimelessChange(value) {
this.toggleSelectField(this.fields.Duration, value);
const startDateField = this.fields.StartDate;
if (value) { // StartDate timeless
this.fields.Rollover.enable();
startDateField.dateFormatText = this.startingTimelessFormatText;
startDateField.showTimePicker = false;
startDateField.timeless = true;
const startDate = this._getNewStartDate(startDateField.getValue(), true);
if (startDate) {
startDateField.setValue(startDate);
}
} else { // StartDate with out time (Timeless)
this.fields.Rollover.setValue(false);
this.fields.Rollover.disable();
startDateField.dateFormatText = (App.is24HourClock()) ? this.startingFormatText24 : this.startingFormatText;
startDateField.showTimePicker = true;
startDateField.timeless = false;
const startDate = this._getNewStartDate(startDateField.getValue(), false);
if (startDate) {
startDateField.setValue(startDate);
}
}
},
onAlarmChange: function onAlarmChange() {
if (this.fields.Alarm.getValue()) {
this.fields.Reminder.enable();
} else {
this.fields.Reminder.disable();
}
},
onLeadChange: function onLeadChange(value, field) {
const selection = field.getSelection();
if (selection && this.insert) {
this.fields.AccountName.setValue(utility.getValue(selection, 'Company'));
}
const entry = field.currentSelection;
if (entry.WorkPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.WorkPhone);
}
},
onLeaderChange: function onLeaderChange(value, field) {
const user = field.getValue();
let resourceId = '';
let key = user.$key;
// The key is a composite key on activityresourceviews endpoint.
// The format is 'ResourceId-AccessId'.
// The feed does include these as seperate fields, but we need to keep the $key/$descriptor format for doing
// the PUT to the activities endpoint. We will convert the composite key to something the activities endpoint will understand.
if (key) {
key = key.split('-');
resourceId = key[0];
if (resourceId) {
this.fields.UserId.setValue(resourceId);
// Set back to a single $key so the PUT request payload is not messed up
this.fields.Leader.setValue({
$key: resourceId,
$descriptor: user.$descriptor,
});
}
}
},
onAccountChange: function onAccountChange(value, field) {
const fields = this.fields;
['Contact', 'Opportunity', 'Ticket'].forEach((f) => {
if (value) {
fields[f].dependsOn = 'Account';
fields[f].where = `Account.Id eq "${value.AccountId || value.key}"`;
if (fields[f].currentSelection &&
fields[f].currentSelection.Account.$key !== (value.AccountId || value.key)) {
fields[f].setValue(false);
}
// No way to determine if the field is part of the changed account, clear it
if (!fields[f].currentSelection) {
fields[f].setValue(null);
}
} else {
fields[f].dependsOn = null;
fields[f].where = 'Account.AccountName ne null';
}
});
if (value === null || typeof value === 'undefined') {
return;
}
const entry = field.currentSelection;
if (entry && entry.MainPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.MainPhone);
}
},
onContactChange: function onContactChange(value, field) {
this.onAccountDependentChange(value, field);
const entry = field.currentSelection;
if (entry && entry.WorkPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.WorkPhone);
}
},
onOpportunityChange: function onOpportunityChange(value, field) {
this.onAccountDependentChange(value, field);
const entry = field.currentSelection;
if (entry && entry.Account && entry.Account.MainPhone) {
const phoneField = this.fieldsPhoneNumber;
phoneField.setValue(entry.Account.MainPhone);
}
},
onTicketChange: function onTicketChange(value, field) {
this.onAccountDependentChange(value, field);
const entry = field.currentSelection;
const phone = entry && entry.Contact && entry.Contact.WorkPhone || entry && entry.Account && entry.Account.MainPhone;
if (phone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(phone);
}
},
onAccountDependentChange: function onAccountDependentChange(value, field) {
if (value && !field.dependsOn && field.currentSelection && field.currentSelection.Account) {
const accountField = this.fields.Account;
accountField.setValue({
AccountId: field.currentSelection.Account.$key,
AccountName: field.currentSelection.Account.AccountName,
});
this.onAccountChange(accountField.getValue(), accountField);
}
},
onStartDateChange: function onStartDateChange(value) {
this.recurrence.StartDate = value;
// Need recalculate RecurPeriodSpec in case weekday on StartDate changes
this.recurrence.RecurPeriodSpec = recur.getRecurPeriodSpec(
this.recurrence.RecurPeriod,
this.recurrence.StartDate,
this.recurrence.RecurPeriodSpec - this.recurrence.RecurPeriodSpec % 65536, // weekdays
this.recurrence.RecurPeriodSpec % 65536 // interval
);
this.resetRecurrence(this.recurrence);
recur.createSimplifiedOptions(value);
const repeats = (this.recurrence.RecurrenceState === 'rstMaster');
this.fields.RecurrenceUI.setValue(recur.getPanel(repeats && this.recurrence.RecurPeriod));
},
onRecurrenceUIChange: function onRecurrenceUIChange(value, field) {
const key = field.currentValue && field.currentValue.key;
const opt = recur.simplifiedOptions[key];
// preserve #iterations (and EndDate) if matching recurrence
if (this._previousRecurrence === key) {
opt.RecurIterations = this.recurrence.RecurIterations;
}
this.resetRecurrence(opt);
this._previousRecurrence = key;
},
onRecurrenceChange: function onRecurrenceChange(value) {
// did the StartDate change on the recurrence_edit screen?
const startDate = argos.Convert.toDateFromString(value.StartDate); // TODO: Avoid global
const currentDate = this.fields.StartDate.getValue();
if (startDate.getDate() !== currentDate.getDate() || startDate.getMonth() !== currentDate.getMonth()) {
this.fields.StartDate.setValue(startDate);
}
this.resetRecurrence(value);
},
resetRecurrence: function resetRecurrence(o) {
this.recurrence.StartDate = this.fields.StartDate.getValue();
if (typeof o.Recurring !== 'undefined' && o.Recurring !== null) {
this.recurrence.Recurring = o.Recurring;
}
if (typeof o.RecurrenceState !== 'undefined' && o.RecurrenceState !== null) {
this.recurrence.RecurrenceState = o.RecurrenceState;
}
if (typeof o.RecurPeriod !== 'undefined' && o.RecurPeriod !== null) {
this.recurrence.RecurPeriod = o.RecurPeriod;
}
if (typeof o.RecurPeriodSpec !== 'undefined' && o.RecurPeriodSpec !== null) {
this.recurrence.RecurPeriodSpec = o.RecurPeriodSpec;
}
if (typeof o.RecurIterations !== 'undefined' && o.RecurIterations !== null) {
this.recurrence.RecurIterations = o.RecurIterations;
}
this.recurrence.EndDate = recur.calcEndDate(this.recurrence.StartDate, this.recurrence);
this.fields.RecurrenceUI.setValue(recur.getPanel(this.recurrence.RecurPeriod));
this.fields.Recurrence.setValue(this.recurrence);
this.fields.Recurring.setValue(this.recurrence.Recurring);
this.fields.RecurPeriod.setValue(this.recurrence.RecurPeriod);
this.fields.RecurPeriodSpec.setValue(this.recurrence.Recurring ? this.recurrence.RecurPeriodSpec : 0);
this.fields.RecurrenceState.setValue(this.recurrence.RecurrenceState);
this.fields.RecurIterations.setValue(this.recurrence.RecurIterations);
this.fields.EndDate.setValue(this.recurrence.EndDate);
if (o.Recurring) {
this.fields.Recurrence.enable();
} else {
this.fields.Recurrence.disable();
}
},
formatPicklistForType: function formatPicklistForType(type, which) {
return getPicklistByActivityType(type, which);
},
formatRecurrence: function formatRecurrence(recurrence) {
if (typeof recurrence === 'string') {
return recurrence;
}
return recur.toString(recurrence, true);
},
_getCalculatedStartTime: function _getCalculatedStartTime(selectedDate) {
const now = moment();
let thisSelectedDate = selectedDate;
if (!moment.isMoment(selectedDate)) {
thisSelectedDate = moment(selectedDate);
}
// Take the start of the selected date, add the *current* time to it,
// and round it up to the nearest ROUND_MINUTES
// Examples:
// 11:24 -> 11:30
// 11:12 -> 11:15
// 11:31 -> 11:45
const startDate = thisSelectedDate.clone()
.startOf('day')
.hours(now.hours())
.add({
minutes: (Math.floor(now.minutes() / this.ROUND_MINUTES) * this.ROUND_MINUTES) + this.ROUND_MINUTES,
});
return startDate;
},
applyUserActivityContext: function applyUserActivityContext(optionsDate) {
return this._getCalculatedStartTime(optionsDate);
},
applyContext: function applyContext() {
this.inherited(arguments);
let startDate = this._getCalculatedStartTime(moment());
const activityType = this.options && this.options.activityType;
const activityGroup = this.groupOptionsByType[activityType] || '';
const activityDuration = App.context.userOptions && App.context.userOptions[`${activityGroup}:Duration`] || 15;
const alarmEnabled = App.context.userOptions && App.context.userOptions[`${activityGroup}:AlarmEnabled`] || true;
const alarmDuration = App.context.userOptions && App.context.userOptions[`${activityGroup}:AlarmLead`] || 15;
if (this.options && this.options.currentDate) {
startDate = this.applyUserActivityContext(moment(this.options.currentDate));
}
this.fields.StartDate.setValue(startDate.toDate());
this.fields.Type.setValue(activityType);
this.fields.Duration.setValue(activityDuration);
this.fields.Alarm.setValue(alarmEnabled);
this.fields.Reminder.setValue(alarmDuration);
const user = App.context.user;
if (user) {
this.fields.UserId.setValue(user.$key);
const leaderField = this.fields.Leader;
leaderField.setValue(user);
this.onLeaderChange(user, leaderField);
}
const found = this._getNavContext();
const accountField = this.fields.Account;
this.onAccountChange(accountField.getValue(), accountField);
const context = (found && found.options && found.options.source) || found;
const lookup = {
accounts: this.applyAccountContext,
contacts: this.applyContactContext,
opportunities: this.applyOpportunityContext,
tickets: this.applyTicketContext,
leads: this.applyLeadContext,
};
if (context && lookup[context.resourceKind]) {
lookup[context.resourceKind].call(this, context);
}
},
_getNavContext: function _getNavContext() {
const navContext = App.queryNavigationContext((o) => {
const context = (o.options && o.options.source) || o;
if (/^(accounts|contacts|opportunities|tickets|leads)$/.test(context.resourceKind) && context.key) {
return true;
}
return false;
});
return navContext;
},
applyAccountContext: function applyAccountContext(context) {
const view = App.getView(context.id);
const entry = context.entry || (view && view.entry) || context;
if (!entry || !entry.$key) {
return;
}
const accountField = this.fields.Account;
accountField.setSelection(entry);
accountField.setValue({
AccountId: entry.$key,
AccountName: entry.$descriptor,
});
this.onAccountChange(accountField.getValue(), accountField);
},
applyContactContext: function applyContactContext(context) {
const view = App.getView(context.id);
const entry = context.entry || (view && view.entry) || context;
if (!entry || !entry.$key) {
return;
}
const contactField = this.fields.Contact;
contactField.setSelection(entry);
contactField.setValue({
ContactId: entry.$key,
ContactName: entry.$descriptor,
});
this.onAccountDependentChange(contactField.getValue(), contactField);
const accountField = this.fields.Account;
accountField.setValue({
AccountId: utility.getValue(entry, 'Account.$key'),
AccountName: utility.getValue(entry, 'Account.AccountName'),
});
if (entry.WorkPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.WorkPhone);
}
},
applyTicketContext: function applyTicketContext(context) {
const view = App.getView(context.id);
const entry = context.entry || (view && view.entry);
if (!entry || !entry.$key) {
return;
}
const ticketField = this.fields.Ticket;
ticketField.setSelection(entry);
ticketField.setValue({
TicketId: entry.$key,
TicketNumber: entry.$descriptor,
});
this.onAccountDependentChange(ticketField.getValue(), ticketField);
const contactField = this.fields.Contact;
contactField.setValue({
ContactId: utility.getValue(entry, 'Contact.$key'),
ContactName: utility.getValue(entry, 'Contact.NameLF'),
});
this.onAccountDependentChange(contactField.getValue(), contactField);
const accountField = this.fields.Account;
accountField.setValue({
AccountId: utility.getValue(entry, 'Account.$key'),
AccountName: utility.getValue(entry, 'Account.AccountName'),
});
const phone = entry && entry.Contact && entry.Contact.WorkPhone || entry && entry.Account && entry.Account.MainPhone;
if (phone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(phone);
}
},
applyOpportunityContext: function applyOpportunityContext(context) {
const view = App.getView(context.id);
const entry = context.entry || (view && view.entry);
if (!entry || !entry.$key) {
return;
}
const opportunityField = this.fields.Opportunity;
opportunityField.setSelection(entry);
opportunityField.setValue({
OpportunityId: entry.$key,
OpportunityName: entry.$descriptor,
});
this.onAccountDependentChange(opportunityField.getValue(), opportunityField);
const accountField = this.fields.Account;
accountField.setValue({
AccountId: utility.getValue(entry, 'Account.$key'),
AccountName: utility.getValue(entry, 'Account.AccountName'),
});
if (entry.Account && entry.Account.MainPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.Account.MainPhone);
}
},
applyLeadContext: function applyLeadContext(context) {
const view = App.getView(context.id);
const entry = context.entry || (view && view.entry);
if (!entry || !entry.$key) {
return;
}
const leadField = this.fields.Lead;
leadField.setSelection(entry);
leadField.setValue({
LeadId: entry.$key,
LeadName: entry.$descriptor,
});
this.onLeadChange(leadField.getValue(), leadField);
this.fields.AccountName.setValue(entry.Company);
const isLeadField = this.fields.IsLead;
isLeadField.setValue(context.resourceKind === 'leads');
this.onIsLeadChange(isLeadField.getValue(), isLeadField);
if (entry.WorkPhone) {
const phoneField = this.fields.PhoneNumber;
phoneField.setValue(entry.WorkPhone);
}
},
setValues: function setValues(values) {
if (values.StartDate && values.AlarmTime) {
const startTime = (this.isDateTimeless(values.StartDate)) ? moment(values.StartDate)
.add({
minutes: values.StartDate.getTimezoneOffset(),
})
.toDate()
.getTime() : values.StartDate.getTime();
const span = startTime - values.AlarmTime.getTime(); // ms
const reminder = span / (1000 * 60);
values.Reminder = format.fixed(reminder, 0);
}
this.inherited(arguments);
this.enableFields();
if (values.Timeless) {
this.fields.Duration.disable();
this.fields.Rollover.enable();
} else {
this.fields.Duration.enable();
this.fields.Rollover.disable();
}
if (values.Alarm) {
this.fields.Reminder.enable();
} else {
this.fields.Reminder.disable();
}
if (this.isInLeadContext()) {
const isLeadField = this.fields.IsLead;
isLeadField.setValue(true);
this.onIsLeadChange(isLeadField.getValue(), isLeadField);
this.fields.Lead.setValue(values, true);
this.fields.AccountName.setValue(values.AccountName);
}
const entry = this.options.entry || this.entry;
const denyEdit = !this.options.insert && !this.currentUserCanEdit(entry);
const allowSetAlarm = !denyEdit || this.currentUserCanSetAlarm(entry);
if (denyEdit) {
this.disableFields();
}
if (allowSetAlarm) {
this.enableFields((f) => {
if (values.Alarm) {
return (/^Alarm|Reminder$/)
.test(f.name);
}
return (/^Alarm$/)
.test(f.name);
});
}
this.recurrence.StartDate = argos.Convert.toDateFromString(values.StartDate); // TODO: Avoid global
this.resetRecurrence(values);
this.onStartDateChange(this.fields.StartDate.getValue(), this.fields.StartDate);
if (this.isActivityRecurring) {
this.fields.EndDate.hide();
}
},
isDateTimeless: function isDateTimeless(date) {
if (!date) {
return false;
}
if (date.getUTCHours() !== 0) {
return false;
}
if (date.getUTCMinutes() !== 0) {
return false;
}
if (date.getUTCSeconds() !== 5) {
return false;
}
return true;
},
isDateTimelessLocal: function isDateTimelessLocal(date) {
if (!date) {
return false;
}
if (date.getHours() !== 0) {
return false;
}
if (date.getMinutes() !== 0) {
return false;
}
if (date.getSeconds() !== 5) {
return false;
}
return true;
},
getValues: function getValues() {
const isStartDateDirty = this.fields.StartDate.isDirty();
const isReminderDirty = this.fields.Reminder.isDirty();
const reminderIn = this.fields.Reminder.getValue();
const timeless = this.fields.Timeless.getValue();
let startDate = this.fields.StartDate.getValue();
let values = this.inherited(arguments);
// Fix timeless if necessary (The date picker won't add 5 seconds)
if (timeless) {
values.StartDate = startDate = this._getNewStartDate(startDate, true);
}
// if StartDate is dirty, always update AlarmTime
if (startDate && (isStartDateDirty || isReminderDirty)) {
values = values || {};
const alarmTime = this._getNewAlarmTime(startDate, timeless, reminderIn);
values.AlarmTime = alarmTime;
}
return values;
},
createReminderData: function createReminderData() {
const list = [];
for (const duration in this.reminderValueText) {
if (this.reminderValueText.hasOwnProperty(duration)) {
list.push({
$key: duration,
$descriptor: this.reminderValueText[duration],
});
}
}
return {
$resources: list,
};
},
createDurationData: function createDurationData() {
const list = [];
for (const duration in this.durationValueText) {
if (this.durationValueText.hasOwnProperty(duration)) {
list.push({
$key: duration,
$descriptor: this.durationValueText[duration],
});
}
}
return {
$resources: list,
};
},
createRecurringData: function createRecurringData() {
return recur.createSimplifiedOptions(this.fields.StartDate.getValue());
},
formatDependentQuery: function formatDependentQuery(dependentValue, theFormat, property) {
return string.substitute(theFormat, [utility.getValue(dependentValue, property || '$key')]);
},
_getNewStartDate: function _getNewStartDate(orginalStartDate, timeless) {
if (!orginalStartDate) {
return null;
}
let startDate = orginalStartDate;
const isTimeLessDate = this.isDateTimeless(startDate) || this.isDateTimelessLocal(startDate);
if (timeless) {
if (!isTimeLessDate) {
let wrapped = moment(startDate);
wrapped = moment.utc(wrapped.format('YYYY-MM-DD'), 'YYYY-MM-DD');
wrapped.add('seconds', 5);
startDate = wrapped.toDate();
}
} else {
if (isTimeLessDate) {
const currentTime = moment();
const wrapped = moment(startDate);
wrapped.subtract({
minutes: wrapped.utcOffset(),
});
wrapped.hours(currentTime.hours());
wrapped.minutes(currentTime.minutes());
wrapped.seconds(0);
startDate = wrapped.toDate();
}
}
return startDate;
},
_getNewAlarmTime: function _getNewAlarmTime(startDate, timeless, reminderIn) {
let alarmTime;
if (!startDate) {
return null;
}
if (timeless) {
const wrapped = moment(startDate);
wrapped.subtract({
minutes: wrapped.utcOffset(),
});
wrapped.hours(24);
wrapped.minutes(0);
wrapped.seconds(0);
alarmTime = wrapped.toDate();
alarmTime = moment(alarmTime)
.clone()
.add({
days: -1,
})
.add({
minutes: -1 * reminderIn,
})
.toDate();
} else {
alarmTime = moment(startDate)
.clone()
.add({
minutes: -1 * reminderIn,
})
.toDate();
}
return alarmTime;
},
createLayout: function createLayout() {
return this.layout || (this.layout = [{
name: 'Type',
property: 'Type',
type: 'hidden',
}, {
dependsOn: 'Type',
label: this.regardingText,
name: 'Description',
property: 'Description',
picklist: this.formatPicklistForType.bindDelegate(this, 'Description'),
title: this.activityDescriptionTitleText,
orderBy: 'text asc',
type: 'picklist',
maxTextLength: 64,
validator: validator.exceedsMaxTextLength,
autoFocus: true,
}, {
label: this.longNotesText,
noteProperty: false,
name: 'LongNotes',
property: 'LongNotes',
title: this.longNotesTitleText,
type: 'note',
view: 'text_edit',
}, {
name: 'Location',
property: 'Location',
label: this.locationText,
type: 'text',
maxTextLength: 255,
validator: validator.exceedsMaxTextLength,
}, {
label: this.priorityText,
name: 'Priority',
property: 'Priority',
picklist: 'Priorities',
title: this.priorityTitleText,
type: 'picklist',
maxTextLength: 64,
validator: validator.exceedsMaxTextLength,
}, {
dependsOn: 'Type',
label: this.categoryText,
name: 'Category',
property: 'Category',
picklist: this.formatPicklistForType.bindDelegate(this, 'Category'),
orderBy: 'text asc',
title: this.activityCategoryTitleText,
type: 'picklist',
maxTextLength: 64,
validator: validator.exceedsMaxTextLength,
}, {
label: this.startingText,
name: 'StartDate',
property: 'StartDate',
type: 'date',
timeless: false,
showTimePicker: true,
showRelativeDateTime: true,
dateFormatText: (App.is24HourClock()) ? this.startingFormatText24 : this.startingFormatText,
minValue: (new Date(1900, 0, 1)),
validator: [
validator.exists,
validator.isDateInRange,
],
}, {
type: 'date',
name: 'EndDate',
property: 'EndDate',
showRelativeDateTime: true,
include: true,
}, {
dependsOn: 'StartDate',
label: this.repeatsText,
title: this.recurringTitleText,
name: 'RecurrenceUI',
property: 'RecurrenceUI',
type: 'select',
view: 'select_list',
data: this.createRecurringData.bindDelegate(this),
exclude: true,
}, {
dependsOn: 'RecurrenceUI',
label: this.recurringText,
name: 'Recurrence',
property: 'Recurrence',
type: 'recurrences',
applyTo: '.',
view: 'recurrence_edit',
exclude: true,
formatValue: this.formatRecurrence.bindDelegate(this),
}, {
type: 'hidden',
name: 'RecurPeriod',
property: 'RecurPeriod',
include: true,
}, {
type: 'hidden',
name: 'RecurPeriodSpec',
property: 'RecurPeriodSpec',
include: true,
}, {
type: 'hidden',
name: 'RecurrenceState',
property: 'RecurrenceState',
include: true,
}, {
type: 'hidden',
name: 'Recurring',
property: 'Recurring',
include: true,
}, {
type: 'hidden',
name: 'RecurIterations',
property: 'RecurIterations',
include: true,
}, {
label: this.timelessText,
name: 'Timeless',
property: 'Timeless',
type: 'boolean',
}, {
label: this.durationText,
title: this.durationTitleText,
name: 'Duration',
property: 'Duration',
type: 'duration',
view: 'select_list',
data: this.createDurationData(),
}, {
name: 'Alarm',
property: 'Alarm',
label: this.alarmText,
type: 'boolean',
}, {
label: this.reminderText,
title: this.reminderTitleText,
include: false,
name: 'Reminder',
property: 'Reminder',
type: 'duration',
view: 'select_list',
data: this.createReminderData(),
}, {
label: this.rolloverText,
name: 'Rollover',
property: 'Rollover',
type: 'boolean',
}, {
type: 'hidden',
name: 'UserId',
property: 'UserId',
}, {
label: this.leaderText,
name: 'Leader',
property: 'Leader',
include: true,
type: 'lookup',
requireSelection: true,
view: 'calendar_access_list',
}, {
label: this.isLeadText,
name: 'IsLead',
property: 'IsLead',
include: false,
type: 'boolean',
onText: this.yesText,
offText: this.noText,
}, {
label: this.accountText,
name: 'Account',
property: 'Account',
type: 'lookup',
emptyText: '',
applyTo: '.',
valueKeyProperty: 'AccountId',
valueTextProperty: 'AccountName',
view: 'account_related',
}, {
dependsOn: 'Account',
label: this.contactText,
name: 'Contact',
property: 'Contact',
type: 'lookup',
emptyText: '',
applyTo: function applyTo(payload, value) {
if (value === null) {
payload[this.valueKeyProperty] = null;
payload[this.valueTextProperty] = null;
}
},
valueKeyProperty: 'ContactId',
valueTextProperty: 'ContactName',
view: 'contact_related',
where: this.formatDependentQuery.bindDelegate(
this, 'Account.Id eq "${0}"', 'AccountId'
),
}, {
dependsOn: 'Account',
label: this.opportunityText,
name: 'Opportunity',
property: 'Opportunity',
type: 'lookup',
emptyText: '',
applyTo: function applyTo(payload, value) {
if (value === null) {
payload[this.valueKeyProperty] = null;
payload[this.valueTextProperty] = null;
}
},
valueKeyProperty: 'OpportunityId',
valueTextProperty: 'OpportunityName',
view: 'opportunity_related',
where: this.formatDependentQuery.bindDelegate(
this, 'Account.Id eq "${0}"', 'AccountId'
),
}, {
dependsOn: 'Account',
label: this.ticketNumberText,
name: 'Ticket',
property: 'Ticket',
type: 'lookup',
emptyText: '',
applyTo: function applyTo(payload, value) {
if (value === null) {
payload[this.valueKeyProperty] = null;
payload[this.valueTextProperty] = null;
}
},
valueKeyProperty: 'TicketId',
valueTextProperty: 'TicketNumber',
view: 'ticket_related',
where: this.formatDependentQuery.bindDelegate(
this, 'Account.Id eq "${0}"', 'AccountId'
),
}, {
label: this.leadText,
name: 'Lead',
property: 'Lead',
type: 'lookup',
emptyText: '',
applyTo: '.',
valueKeyProperty: 'LeadId',
valueTextProperty: 'LeadName',
view: 'lead_related',
}, {
label: this.companyText,
name: 'AccountName',
property: 'AccountName',
type: 'text',
}, {
name: 'PhoneNumber',
property: 'PhoneNumber',
label: this.phoneText,
type: 'phone',
maxTextLength: 32,
validator: validator.exceedsMaxTextLength,
}]);
},
});
lang.setObject('Mobile.SalesLogix.Views.Activity.Edit', __class);
export default __class;