From 8698828ae3fc4519fa51dd040f36200c19fce0b6 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 18 Jul 2025 00:50:11 +0530 Subject: [PATCH 01/19] Activity Logging --- .../activityLoggingSettingPage.js | 303 ++++++++++++++++++ .../callAndSMSLoggingSettingPage.js | 198 ------------ src/components/admin/managedSettingsPage.js | 4 +- src/core/user.js | 75 ++++- src/popup.js | 12 +- src/service/embeddableServices.js | 204 ++++++++---- src/service/logService.js | 3 +- 7 files changed, 526 insertions(+), 273 deletions(-) create mode 100644 src/components/admin/managedSettings/activityLoggingSettingPage.js delete mode 100644 src/components/admin/managedSettings/callAndSMSLoggingSettingPage.js diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js new file mode 100644 index 0000000..b2526bd --- /dev/null +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -0,0 +1,303 @@ +function getActivityLoggingSettingPageRender({ adminUserSettings }) { + return { + id: 'activityLoggingSettingPage', + title: 'Activity logging', + type: 'page', + schema: { + type: 'object', + required: [], + properties: { + enableActivityLoggingSection: { + type: 'object', + title: 'Enable automatic activity logging for:', + description: 'Automatically log activities for the selected entities', + properties: { + autoLogAnsweredIncoming: { + type: 'object', + title: 'Answered incoming calls', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogMissedIncoming: { + type: 'object', + title: 'Missed incoming calls', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogOutgoing: { + type: 'object', + title: 'Outgoing calls', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogVoicemails: { + type: 'object', + title: 'Voicemails', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogSMS: { + type: 'object', + title: 'SMS', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogInboundFax: { + type: 'object', + title: 'Inbound faxes', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + autoLogOutboundFax: { + type: 'object', + title: 'Outbound faxes', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + } + } + }, + preferencesSection: { + type: 'object', + title: 'Preferences', + description: 'Delays logging until full call details are available', + properties: { + oneTimeLog: { + type: 'object', + title: 'One-time call logging', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + } + } + }, + logSyncFrequencySection: { + type: 'object', + title: 'Log sync frequency', + description: 'How often to sync missed activity; disable to turn off background logging', + properties: { + logSyncFrequency: { + type: 'object', + title: 'Frequency', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'string', + title: 'Value', + enum: ['disabled', '10min', '30min', '1hour', '3hours', '1day'], + enumNames: ['Disabled', '10 min', '30 min', '1 hour', '3 hours', '1 day'] + } + } + } + } + }, + autoOpenSection: { + type: 'object', + title: 'Auto-open logging page after:', + description: 'Opens the logging page for manual entry after selected events', + properties: { + popupLogPageAfterSMS: { + type: 'object', + title: 'SMS is sent', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }, + popupLogPageAfterCall: { + type: 'object', + title: 'Call ends', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + } + } + } + } + }, + uiSchema: { + enableActivityLoggingSection: { + "ui:collapsible": true, + autoLogAnsweredIncoming: { + "ui:collapsible": true, + }, + autoLogMissedIncoming: { + "ui:collapsible": true, + }, + autoLogOutgoing: { + "ui:collapsible": true, + }, + autoLogVoicemails: { + "ui:collapsible": true, + }, + autoLogSMS: { + "ui:collapsible": true, + }, + autoLogInboundFax: { + "ui:collapsible": true, + }, + autoLogOutboundFax: { + "ui:collapsible": true, + } + }, + preferencesSection: { + "ui:collapsible": true, + oneTimeLog: { + "ui:collapsible": true, + } + }, + logSyncFrequencySection: { + "ui:collapsible": true, + logSyncFrequency: { + "ui:collapsible": true, + } + }, + autoOpenSection: { + "ui:collapsible": true, + popupLogPageAfterSMS: { + "ui:collapsible": true, + }, + popupLogPageAfterCall: { + "ui:collapsible": true, + } + }, + submitButtonOptions: { + submitText: 'Save', + } + }, + formData: { + enableActivityLoggingSection: { + autoLogAnsweredIncoming: { + customizable: adminUserSettings?.autoLogAnsweredIncoming?.customizable ?? true, + value: adminUserSettings?.autoLogAnsweredIncoming?.value ?? false + }, + autoLogMissedIncoming: { + customizable: adminUserSettings?.autoLogMissedIncoming?.customizable ?? true, + value: adminUserSettings?.autoLogMissedIncoming?.value ?? false + }, + autoLogOutgoing: { + customizable: adminUserSettings?.autoLogOutgoing?.customizable ?? true, + value: adminUserSettings?.autoLogOutgoing?.value ?? false + }, + autoLogVoicemails: { + customizable: adminUserSettings?.autoLogVoicemails?.customizable ?? true, + value: adminUserSettings?.autoLogVoicemails?.value ?? false + }, + autoLogSMS: { + customizable: adminUserSettings?.autoLogSMS?.customizable ?? true, + value: adminUserSettings?.autoLogSMS?.value ?? false + }, + autoLogInboundFax: { + customizable: adminUserSettings?.autoLogInboundFax?.customizable ?? true, + value: adminUserSettings?.autoLogInboundFax?.value ?? false + }, + autoLogOutboundFax: { + customizable: adminUserSettings?.autoLogOutboundFax?.customizable ?? true, + value: adminUserSettings?.autoLogOutboundFax?.value ?? false + } + }, + preferencesSection: { + oneTimeLog: { + customizable: adminUserSettings?.oneTimeLog?.customizable ?? true, + value: adminUserSettings?.oneTimeLog?.value ?? false + } + }, + logSyncFrequencySection: { + logSyncFrequency: { + customizable: adminUserSettings?.logSyncFrequency?.customizable ?? true, + value: adminUserSettings?.logSyncFrequency?.value ?? '10min' + } + }, + autoOpenSection: { + popupLogPageAfterSMS: { + customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? true, + value: adminUserSettings?.popupLogPageAfterSMS?.value ?? false + }, + popupLogPageAfterCall: { + customizable: adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, + value: adminUserSettings?.popupLogPageAfterCall?.value ?? false + } + } + } + } +} + +exports.getActivityLoggingSettingPageRender = getActivityLoggingSettingPageRender; \ No newline at end of file diff --git a/src/components/admin/managedSettings/callAndSMSLoggingSettingPage.js b/src/components/admin/managedSettings/callAndSMSLoggingSettingPage.js deleted file mode 100644 index 4accf19..0000000 --- a/src/components/admin/managedSettings/callAndSMSLoggingSettingPage.js +++ /dev/null @@ -1,198 +0,0 @@ -function getCallAndSMSLoggingSettingPageRender({ adminUserSettings }) { - return { - id: 'callAndSMSLoggingSettingPage', - title: 'Call and SMS logging', - type: 'page', - schema: { - type: 'object', - required: [], - properties: { - autoLogCall: { - type: 'object', - title: 'Log phone calls automatically', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogSMS: { - type: 'object', - title: 'Log SMS conversations automatically', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogInboundFax: { - type: 'object', - title: 'Log inbound faxes automatically', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogOutboundFax: { - type: 'object', - title: 'Log outbound faxes automatically', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - enableRetroCallLogSync: { - type: 'object', - title: 'Disable retroactive call log sync', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - oneTimeLog: { - type: 'object', - title: 'Enable one-time call logging', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - popupLogPageAfterCall: { - type: 'object', - title: '(Manual log) Open call logging page after call', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - popupLogPageAfterSMS: { - type: 'object', - title: '(Manual log) Open SMS logging page after message', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - } - } - }, - uiSchema: { - autoLogCall: { - "ui:collapsible": true, - }, - autoLogSMS: { - "ui:collapsible": true, - }, - autoLogInboundFax: { - "ui:collapsible": true, - }, - autoLogOutboundFax: { - "ui:collapsible": true, - }, - enableRetroCallLogSync: { - "ui:collapsible": true, - }, - oneTimeLog: { - "ui:collapsible": true, - }, - popupLogPageAfterCall: { - "ui:collapsible": true, - }, - popupLogPageAfterSMS: { - "ui:collapsible": true, - }, - submitButtonOptions: { - submitText: 'Save', - } - }, - formData: { - autoLogCall: - { - customizable: adminUserSettings?.autoLogCall?.customizable ?? true, - value: adminUserSettings?.autoLogCall?.value ?? false - }, - autoLogSMS: - { - customizable: adminUserSettings?.autoLogSMS?.customizable ?? true, - value: adminUserSettings?.autoLogSMS?.value ?? false - }, - autoLogInboundFax: - { - customizable: adminUserSettings?.autoLogInboundFax?.customizable ?? true, - value: adminUserSettings?.autoLogInboundFax?.value ?? false - }, - autoLogOutboundFax: - { - customizable: adminUserSettings?.autoLogOutboundFax?.customizable ?? true, - value: adminUserSettings?.autoLogOutboundFax?.value ?? false - }, - enableRetroCallLogSync: - { - customizable: adminUserSettings?.enableRetroCallLogSync?.customizable ?? true, - value: adminUserSettings?.enableRetroCallLogSync?.value ?? true - }, - oneTimeLog: - { - customizable: adminUserSettings?.oneTimeLog?.customizable ?? true, - value: adminUserSettings?.oneTimeLog?.value ?? false - }, - popupLogPageAfterCall: - { - customizable: adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, - value: adminUserSettings?.popupLogPageAfterCall?.value ?? false - }, - popupLogPageAfterSMS: - { - customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? true, - value: adminUserSettings?.popupLogPageAfterSMS?.value ?? false - } - } - } -} - -exports.getCallAndSMSLoggingSettingPageRender = getCallAndSMSLoggingSettingPageRender; \ No newline at end of file diff --git a/src/components/admin/managedSettingsPage.js b/src/components/admin/managedSettingsPage.js index f831782..d4339ef 100644 --- a/src/components/admin/managedSettingsPage.js +++ b/src/components/admin/managedSettingsPage.js @@ -14,8 +14,8 @@ function getManagedSettingsPageRender({ crmManifest }) { title: "General" }, { - const: "callAndSMSLogging", - title: "Call and SMS logging" + const: "activityLogging", + title: "Activity logging" }, { const: "contactSetting", diff --git a/src/core/user.js b/src/core/user.js index 0051287..7445a19 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -75,7 +75,8 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false contacts: getShowContactsTabSetting(userSettings).value }, '*'); const autoLogMessagesGroupTrigger = (userSettings?.autoLogSMS?.value ?? false) || (userSettings?.autoLogInboundFax?.value ?? false) || (userSettings?.autoLogOutboundFax?.value ?? false); - RCAdapter.setAutoLog({ call: userSettings.autoLogCall?.value ?? false, message: autoLogMessagesGroupTrigger }) + const autoLogCallsGroupTrigger = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || (userSettings?.autoLogMissedIncoming?.value ?? false) || (userSettings?.autoLogOutgoing?.value ?? false); + RCAdapter.setAutoLog({ call: autoLogCallsGroupTrigger || (userSettings.autoLogCall?.value ?? false), message: autoLogMessagesGroupTrigger }) if (!isAvoidForceChange) { const showAiAssistantWidgetSetting = getShowAiAssistantWidgetSetting(userSettings); const autoStartAiAssistantSetting = getAutoStartAiAssistantSetting(userSettings); @@ -160,6 +161,73 @@ function getAutoLogOutboundFaxSetting(userSettings) { } } +function getAutoLogAnsweredIncomingSetting(userSettings, isAdmin) { + const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; + if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { + return { + value: false, + readOnly: true, + readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', + warning: 'Unavailable while server side call logging enabled' + } + } + return { + value: userSettings?.autoLogAnsweredIncoming?.value ?? false, + readOnly: userSettings?.autoLogAnsweredIncoming?.customizable === undefined ? false : !userSettings?.autoLogAnsweredIncoming?.customizable, + readOnlyReason: !userSettings?.autoLogAnsweredIncoming?.customizable ? 'This setting is managed by admin' : '' + } +} + +function getAutoLogMissedIncomingSetting(userSettings, isAdmin) { + const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; + if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { + return { + value: false, + readOnly: true, + readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', + warning: 'Unavailable while server side call logging enabled' + } + } + return { + value: userSettings?.autoLogMissedIncoming?.value ?? false, + readOnly: userSettings?.autoLogMissedIncoming?.customizable === undefined ? false : !userSettings?.autoLogMissedIncoming?.customizable, + readOnlyReason: !userSettings?.autoLogMissedIncoming?.customizable ? 'This setting is managed by admin' : '' + } +} + +function getAutoLogOutgoingSetting(userSettings, isAdmin) { + const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; + if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { + return { + value: false, + readOnly: true, + readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', + warning: 'Unavailable while server side call logging enabled' + } + } + return { + value: userSettings?.autoLogOutgoing?.value ?? false, + readOnly: userSettings?.autoLogOutgoing?.customizable === undefined ? false : !userSettings?.autoLogOutgoing?.customizable, + readOnlyReason: !userSettings?.autoLogOutgoing?.customizable ? 'This setting is managed by admin' : '' + } +} + +function getAutoLogVoicemailsSetting(userSettings) { + return { + value: userSettings?.autoLogVoicemails?.value ?? false, + readOnly: userSettings?.autoLogVoicemails?.customizable === undefined ? false : !userSettings?.autoLogVoicemails?.customizable, + readOnlyReason: !userSettings?.autoLogVoicemails?.customizable ? 'This setting is managed by admin' : '' + } +} + +function getLogSyncFrequencySetting(userSettings) { + return { + value: userSettings?.logSyncFrequency?.value ?? '10min', + readOnly: userSettings?.logSyncFrequency?.customizable === undefined ? false : !userSettings?.logSyncFrequency?.customizable, + readOnlyReason: !userSettings?.logSyncFrequency?.customizable ? 'This setting is managed by admin' : '' + } +} + function getEnableRetroCallLogSync(userSettings) { return { value: userSettings?.enableRetroCallLogSync?.value ?? true, @@ -362,6 +430,11 @@ exports.getAutoLogCallSetting = getAutoLogCallSetting; exports.getAutoLogSMSSetting = getAutoLogSMSSetting; exports.getAutoLogInboundFaxSetting = getAutoLogInboundFaxSetting; exports.getAutoLogOutboundFaxSetting = getAutoLogOutboundFaxSetting; +exports.getAutoLogAnsweredIncomingSetting = getAutoLogAnsweredIncomingSetting; +exports.getAutoLogMissedIncomingSetting = getAutoLogMissedIncomingSetting; +exports.getAutoLogOutgoingSetting = getAutoLogOutgoingSetting; +exports.getAutoLogVoicemailsSetting = getAutoLogVoicemailsSetting; +exports.getLogSyncFrequencySetting = getLogSyncFrequencySetting; exports.getEnableRetroCallLogSync = getEnableRetroCallLogSync; exports.getOneTimeLogSetting = getOneTimeLogSetting; exports.getCallPopSetting = getCallPopSetting; diff --git a/src/popup.js b/src/popup.js index 2b4203a..b89f77f 100644 --- a/src/popup.js +++ b/src/popup.js @@ -19,7 +19,7 @@ import reportPage from './components/reportPage'; import adminPage from './components/admin/adminPage'; import managedSettingsPage from './components/admin/managedSettingsPage'; import generalSettingPage from './components/admin/generalSettingPage'; -import callAndSMSLoggingSettingPage from './components/admin/managedSettings/callAndSMSLoggingSettingPage'; +import activityLoggingSettingPage from './components/admin/managedSettings/activityLoggingSettingPage'; import customAdapterPage from './components/admin/customAdapterPage'; import serverSideLoggingPage from './components/admin/serverSideLoggingPage'; import contactSettingPage from './components/admin/managedSettings/contactSettingPage'; @@ -985,15 +985,15 @@ window.addEventListener('message', async (e) => { path: `/customized/${clickToDialEmbedPageRender.id}`, // page id }, '*'); break; - case 'callAndSMSLogging': - const callAndSMSLoggingSettingPageRender = callAndSMSLoggingSettingPage.getCallAndSMSLoggingSettingPageRender({ adminUserSettings: adminSettings?.userSettings }); + case 'activityLogging': + const activityLoggingSettingPageRender = activityLoggingSettingPage.getActivityLoggingSettingPageRender({ adminUserSettings: adminSettings?.userSettings }); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ type: 'rc-adapter-register-customized-page', - page: callAndSMSLoggingSettingPageRender + page: activityLoggingSettingPageRender }); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ type: 'rc-adapter-navigate-to', - path: `/customized/${callAndSMSLoggingSettingPageRender.id}`, // page id + path: `/customized/${activityLoggingSettingPageRender.id}`, // page id }, '*'); break; case 'serverSideLoggingSetting': @@ -2065,7 +2065,7 @@ window.addEventListener('message', async (e) => { break; case '/custom-button-click': switch (data.body.button.id) { - case 'callAndSMSLoggingSettingPage': + case 'activityLoggingSettingPage': case 'contactSettingPage': case 'advancedFeaturesSettingPage': case 'customSettingsPage': diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 9accaf2..74f6a3e 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -55,79 +55,153 @@ async function getServiceManifest() { { id: 'logging', type: 'group', - name: 'Call and SMS logging', + name: 'Activity logging', items: [ { - id: 'autoLogCall', - type: 'boolean', - name: 'Log phone calls automatically', - description: 'Automatically log calls when they end in this app', - readOnly: userCore.getAutoLogCallSetting(userSettings, isAdmin).readOnly, - readOnlyReason: userCore.getAutoLogCallSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogCallSetting(userSettings, isAdmin).readOnlyReason, - value: userCore.getAutoLogCallSetting(userSettings, isAdmin).value, - }, - { - id: 'autoLogSMS', - type: 'boolean', - name: 'Log SMS conversations automatically', - description: 'Automatically log SMS when they are sent or received in this app', - readOnly: userCore.getAutoLogSMSSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogSMSSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogSMSSetting(userSettings).value, - }, - { - id: 'autoLogInboundFax', - type: 'boolean', - name: 'Log inbound faxes automatically', - description: 'Automatically log inbound faxes when they are received in this app', - readOnly: userCore.getAutoLogInboundFaxSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogInboundFaxSetting(userSettings).value, - }, - { - id: 'autoLogOutboundFax', - type: 'boolean', - name: 'Log outbound faxes automatically', - description: 'Automatically log outbound faxes when they are sent in this app', - readOnly: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogOutboundFaxSetting(userSettings).value, - }, - { - id: "enableRetroCallLogSync", - type: "boolean", - name: 'Retroactive call log sync', - description: 'Periodically scans for and logs any missed activity', - readOnly: userCore.getEnableRetroCallLogSync(userSettings).readOnly, - readOnlyReason: userCore.getEnableRetroCallLogSync(userSettings).readOnlyReason, - value: userCore.getEnableRetroCallLogSync(userSettings).value + id: 'enableActivityLoggingSection', + type: 'section', + name: 'Enable automatic activity logging for:', + items: [ + { + id: 'autoLogAnsweredIncoming', + type: 'boolean', + name: 'Answered incoming calls', + readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly, + readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason, + value: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value, + }, + { + id: 'autoLogMissedIncoming', + type: 'boolean', + name: 'Missed incoming calls', + readOnly: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly, + readOnlyReason: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason, + value: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value, + }, + { + id: 'autoLogOutgoing', + type: 'boolean', + name: 'Outgoing calls', + readOnly: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly, + readOnlyReason: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason, + value: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value, + }, + { + id: 'autoLogVoicemails', + type: 'boolean', + name: 'Voicemails', + readOnly: userCore.getAutoLogVoicemailsSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason, + value: userCore.getAutoLogVoicemailsSetting(userSettings).value, + }, + { + id: 'autoLogSMS', + type: 'boolean', + name: 'SMS', + readOnly: userCore.getAutoLogSMSSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogSMSSetting(userSettings).readOnlyReason, + value: userCore.getAutoLogSMSSetting(userSettings).value, + }, + { + id: 'autoLogInboundFax', + type: 'boolean', + name: 'Inbound faxes', + readOnly: userCore.getAutoLogInboundFaxSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason, + value: userCore.getAutoLogInboundFaxSetting(userSettings).value, + }, + { + id: 'autoLogOutboundFax', + type: 'boolean', + name: 'Outbound faxes', + readOnly: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason, + value: userCore.getAutoLogOutboundFaxSetting(userSettings).value, + } + ], + description: 'Automatically log activities for the selected entities' }, { - id: "oneTimeLog", - type: "boolean", - name: 'One-time call logging', - description: 'Delays logging until full call details are available', - readOnly: userCore.getOneTimeLogSetting(userSettings).readOnly, - readOnlyReason: userCore.getOneTimeLogSetting(userSettings).readOnlyReason, - value: userCore.getOneTimeLogSetting(userSettings).value + id: 'preferencesSection', + type: 'section', + name: 'Preferences', + items: [ + { + id: "oneTimeLog", + type: "boolean", + name: 'One-time call logging', + readOnly: userCore.getOneTimeLogSetting(userSettings).readOnly, + readOnlyReason: userCore.getOneTimeLogSetting(userSettings).readOnlyReason, + value: userCore.getOneTimeLogSetting(userSettings).value + } + ], + description: 'Delays logging until full call details are available' }, { - id: "popupLogPageAfterCall", - type: "boolean", - name: '(Manual log) Open call logging page after call', - description: 'Automatically open the logging form after each call', - readOnly: userCore.getCallPopSetting(userSettings).readOnly, - readOnlyReason: userCore.getCallPopSetting(userSettings).readOnlyReason, - value: userCore.getCallPopSetting(userSettings).value + id: 'logSyncFrequencySection', + type: 'section', + name: 'Log sync frequency', + items: [ + { + id: "logSyncFrequency", + type: "option", + name: 'Frequency', + options: [ + { + id: 'disabled', + name: 'Disabled' + }, + { + id: '10min', + name: '10 min' + }, + { + id: '30min', + name: '30 min' + }, + { + id: '1hour', + name: '1 hour' + }, + { + id: '3hours', + name: '3 hours' + }, + { + id: '1day', + name: '1 day' + } + ], + value: userCore.getLogSyncFrequencySetting(userSettings).value, + readOnly: userCore.getLogSyncFrequencySetting(userSettings).readOnly, + readOnlyReason: userCore.getLogSyncFrequencySetting(userSettings).readOnlyReason, + } + ], + description: 'How often to sync missed activity; disable to turn off background logging' }, { - id: "popupLogPageAfterSMS", - type: "boolean", - name: '(Manual log) Open SMS logging page after message', - description: 'Automatically open the logging form after each message', - readOnly: userCore.getSMSPopSetting(userSettings).readOnly, - readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason, - value: userCore.getSMSPopSetting(userSettings).value + id: 'autoOpenSection', + type: 'section', + name: 'Auto-open logging page after:', + items: [ + { + id: "popupLogPageAfterSMS", + type: "boolean", + name: 'SMS is sent', + readOnly: userCore.getSMSPopSetting(userSettings).readOnly, + readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason, + value: userCore.getSMSPopSetting(userSettings).value + }, + { + id: "popupLogPageAfterCall", + type: "boolean", + name: 'Call ends', + readOnly: userCore.getCallPopSetting(userSettings).readOnly, + readOnlyReason: userCore.getCallPopSetting(userSettings).readOnlyReason, + value: userCore.getCallPopSetting(userSettings).value + } + ], + description: 'Opens the logging page for manual entry after selected events' } ] }, diff --git a/src/service/logService.js b/src/service/logService.js index 9b3ed39..d5fde0f 100644 --- a/src/service/logService.js +++ b/src/service/logService.js @@ -13,7 +13,8 @@ async function retroAutoCallLog({ const { isAdmin } = await chrome.storage.local.get({ isAdmin: false }); const { userSettings } = await chrome.storage.local.get({ userSettings: {} }); const { rcAdditionalSubmission } = await chrome.storage.local.get({ rcAdditionalSubmission: {} }); - if (!userCore.getEnableRetroCallLogSync(userSettings).value) { + const logSyncFrequency = userCore.getLogSyncFrequencySetting(userSettings).value; + if (logSyncFrequency === 'disabled') { return; } const { retroAutoCallLogMaxAttempt } = await chrome.storage.local.get({ retroAutoCallLogMaxAttempt: 10 }); From 6c5800ca3adbda3896350c60986d0d8cfd9d0d7f Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 18 Jul 2025 02:45:08 +0530 Subject: [PATCH 02/19] Admin setting reflection for activity logging --- .../activityLoggingSettingPage.js | 4 - src/core/admin.js | 34 +++++-- src/core/user.js | 14 +++ src/popup.js | 90 ++++++++++++++++--- 4 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index b2526bd..4256dd3 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -10,7 +10,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { enableActivityLoggingSection: { type: 'object', title: 'Enable automatic activity logging for:', - description: 'Automatically log activities for the selected entities', properties: { autoLogAnsweredIncoming: { type: 'object', @@ -115,7 +114,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { preferencesSection: { type: 'object', title: 'Preferences', - description: 'Delays logging until full call details are available', properties: { oneTimeLog: { type: 'object', @@ -136,7 +134,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { logSyncFrequencySection: { type: 'object', title: 'Log sync frequency', - description: 'How often to sync missed activity; disable to turn off background logging', properties: { logSyncFrequency: { type: 'object', @@ -159,7 +156,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { autoOpenSection: { type: 'object', title: 'Auto-open logging page after:', - description: 'Opens the logging page for manual entry after selected events', properties: { popupLogPageAfterSMS: { type: 'object', diff --git a/src/core/admin.js b/src/core/admin.js index 53479d1..9fb5169 100644 --- a/src/core/admin.js +++ b/src/core/admin.js @@ -33,18 +33,40 @@ async function refreshAdminSettings() { const platform = manifest.platforms[platformInfo.platformName]; const rcAccessToken = getRcAccessToken(); let adminSettings; - // Admin tab render + + // First try to get from server const storedAdminSettings = await getAdminSettings({ serverUrl: manifest.serverUrl, rcAccessToken }); - await chrome.storage.local.set({ isAdmin: !!storedAdminSettings }); - if (storedAdminSettings) { + + // If server returns null, try to get from local storage + let finalAdminSettings = storedAdminSettings; + if (!storedAdminSettings) { + const { adminSettings: localAdminSettings } = await chrome.storage.local.get({ adminSettings: null }); + finalAdminSettings = localAdminSettings; + } + + // If both server and local storage are empty, initialize with proper structure + if (!finalAdminSettings) { + finalAdminSettings = { + userSettings: {} + }; + } + + // Ensure userSettings exists + if (!finalAdminSettings.userSettings) { + finalAdminSettings.userSettings = {}; + } + + await chrome.storage.local.set({ isAdmin: !!finalAdminSettings }); + + if (finalAdminSettings) { try { const adminPageRender = adminPage.getAdminPageRender({ platform }); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ type: 'rc-adapter-register-customized-page', page: adminPageRender, }, '*'); - await chrome.storage.local.set({ adminSettings: storedAdminSettings }); - adminSettings = storedAdminSettings; + await chrome.storage.local.set({ adminSettings: finalAdminSettings }); + adminSettings = finalAdminSettings; } catch (e) { console.log('Cannot find admin settings', e); } @@ -52,7 +74,7 @@ async function refreshAdminSettings() { // Set user setting display name const { crmUserInfo } = await chrome.storage.local.get({ crmUserInfo: null }); - authCore.setAccountName(crmUserInfo?.name, !!storedAdminSettings); + authCore.setAccountName(crmUserInfo?.name, !!finalAdminSettings); return { adminSettings } } diff --git a/src/core/user.js b/src/core/user.js index 7445a19..d5fcfb2 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -228,6 +228,19 @@ function getLogSyncFrequencySetting(userSettings) { } } +function getLogSyncFrequencyInMilliseconds(userSettings) { + const frequency = getLogSyncFrequencySetting(userSettings).value; + const frequencyMap = { + 'disabled': 0, + '10min': 10 * 60 * 1000, // 10 minutes + '30min': 30 * 60 * 1000, // 30 minutes + '1hour': 60 * 60 * 1000, // 1 hour + '3hours': 3 * 60 * 60 * 1000, // 3 hours + '1day': 24 * 60 * 60 * 1000 // 1 day + }; + return frequencyMap[frequency] || frequencyMap['10min']; +} + function getEnableRetroCallLogSync(userSettings) { return { value: userSettings?.enableRetroCallLogSync?.value ?? true, @@ -435,6 +448,7 @@ exports.getAutoLogMissedIncomingSetting = getAutoLogMissedIncomingSetting; exports.getAutoLogOutgoingSetting = getAutoLogOutgoingSetting; exports.getAutoLogVoicemailsSetting = getAutoLogVoicemailsSetting; exports.getLogSyncFrequencySetting = getLogSyncFrequencySetting; +exports.getLogSyncFrequencyInMilliseconds = getLogSyncFrequencyInMilliseconds; exports.getEnableRetroCallLogSync = getEnableRetroCallLogSync; exports.getOneTimeLogSetting = getOneTimeLogSetting; exports.getCallPopSetting = getCallPopSetting; diff --git a/src/popup.js b/src/popup.js index b89f77f..074717f 100644 --- a/src/popup.js +++ b/src/popup.js @@ -78,6 +78,37 @@ let platform = null; let hasOngoingCall = false; let lastUserSettingSyncDate = new Date(); +async function restartSyncInterval() { + // Clear existing interval + const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); + if (retroAutoCallLogIntervalId) { + clearInterval(retroAutoCallLogIntervalId); + } + + // Check if auto logging is enabled + const autoLogCallsGroupTrigger = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || + (userSettings?.autoLogMissedIncoming?.value ?? false) || + (userSettings?.autoLogOutgoing?.value ?? false); + const isAutoLogEnabled = autoLogCallsGroupTrigger || (userSettings?.autoLogCall?.value ?? false); + + console.log({ message: 'isAutoLogEnabled:', isAutoLogEnabled, crmAuthed, userSettings }); + if (isAutoLogEnabled && crmAuthed) { + const syncIntervalMs = userCore.getLogSyncFrequencyInMilliseconds(userSettings); + if (syncIntervalMs > 0) { + const newRetroAutoCallLogIntervalId = setInterval( + function () { + logService.retroAutoCallLog({ + manifest, + platformName, + platform + }) + }, syncIntervalMs); + await chrome.storage.local.set({ retroAutoCallLogIntervalId: newRetroAutoCallLogIntervalId }); + console.log(`Sync interval restarted with frequency: ${syncIntervalMs}ms`); + } + } +} + checkC2DCollision(); getCustomManifest(); @@ -397,6 +428,10 @@ window.addEventListener('message', async (e) => { type: 'rc-adapter-update-authorization-status', authorized: crmAuthed }, '*'); + + // Initialize sync interval + await restartSyncInterval(); + setInterval(function () { logService.forceCallLogMatcherCheck(); }, 600000) @@ -576,15 +611,14 @@ window.addEventListener('message', async (e) => { trackEditSettings({ changedItem: 'auto-call-log', status: data.autoLog }); if (!!data.autoLog && !!crmAuthed) { await chrome.storage.local.set({ retroAutoCallLogMaxAttempt: 10 }); - const retroAutoCallLogIntervalId = setInterval( - function () { - logService.retroAutoCallLog({ - manifest, - platformName, - platform - }) - }, 60000); - await chrome.storage.local.set({ retroAutoCallLogIntervalId }); + await restartSyncInterval(); + } else { + // Clear interval if auto logging is disabled + const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); + if (retroAutoCallLogIntervalId) { + clearInterval(retroAutoCallLogIntervalId); + await chrome.storage.local.remove('retroAutoCallLogIntervalId'); + } } break; case 'rc-messageLogger-auto-log-notify': @@ -2073,13 +2107,43 @@ window.addEventListener('message', async (e) => { case 'notificationLevelSettingPage': case 'clickToDialEmbedPage': window.postMessage({ type: 'rc-log-modal-loading-on' }, '*'); - const settingDataKeys = Object.keys(data.body.button.formData); - for (const k of settingDataKeys) { - adminSettings.userSettings[k] = data.body.button.formData[k]; + + // Handle nested form data structure properly + const formData = data.body.button.formData; + console.log('Admin settings form data received:', formData); + + for (const sectionKey of Object.keys(formData)) { + const section = formData[sectionKey]; + if (section && typeof section === 'object') { + // Process nested settings within sections + for (const settingKey of Object.keys(section)) { + const setting = section[settingKey]; + if (setting && typeof setting === 'object' && (setting.customizable !== undefined || setting.value !== undefined)) { + // This is an individual setting, save it directly + console.log(`Saving admin setting: ${settingKey}`, setting); + adminSettings.userSettings[settingKey] = setting; + } + } + } } + + console.log('Final admin settings to save:', adminSettings); await chrome.storage.local.set({ adminSettings }); await adminCore.uploadAdminSettings({ serverUrl: manifest.serverUrl, adminSettings }); - await userCore.refreshUserSettings({}); + userSettings = await userCore.refreshUserSettings({}); + + // Refresh the service manifest to reflect admin changes in user settings + const serviceManifest = await embeddableServices.getServiceManifest(); + document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ + type: 'rc-adapter-register-third-party-service', + service: serviceManifest + }, '*'); + + // Restart sync interval if activity logging settings changed + if (data.body.button.id === 'activityLoggingSettingPage') { + await restartSyncInterval(); + } + showNotification({ level: 'success', message: `Settings saved.`, ttl: 3000 }); window.postMessage({ type: 'rc-log-modal-loading-off' }, '*'); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ From 3c1e51d4276b14dd2f3bdb216ef7bac381da7d0d Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 21 Jul 2025 12:18:01 +0530 Subject: [PATCH 03/19] Activit logging --- .../activityLoggingSettingPage.js | 311 +++++------------- src/core/user.js | 34 +- src/popup.js | 144 +++++++- src/service/embeddableServices.js | 195 ++++++----- 4 files changed, 357 insertions(+), 327 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index 4256dd3..a23ab7e 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -7,127 +7,42 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { type: 'object', required: [], properties: { - enableActivityLoggingSection: { + activityLoggingOptions: { type: 'object', title: 'Enable automatic activity logging for:', properties: { - autoLogAnsweredIncoming: { - type: 'object', - title: 'Answered incoming calls', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } + customizable: { + type: 'boolean', + title: 'Customizable by user' }, - autoLogMissedIncoming: { - type: 'object', - title: 'Missed incoming calls', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogOutgoing: { - type: 'object', - title: 'Outgoing calls', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogVoicemails: { - type: 'object', - title: 'Voicemails', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogSMS: { - type: 'object', - title: 'SMS', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogInboundFax: { - type: 'object', - title: 'Inbound faxes', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - }, - autoLogOutboundFax: { - type: 'object', - title: 'Outbound faxes', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } - } - } - }, - preferencesSection: { - type: 'object', - title: 'Preferences', - properties: { - oneTimeLog: { - type: 'object', - title: 'One-time call logging', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } + value: { + type: 'array', + title: 'Selected options', + items: { + type: 'string', + enum: [ + 'oneTimeLog', + 'autoLogAnsweredIncoming', + 'autoLogMissedIncoming', + 'autoLogOutgoing', + 'autoLogVoicemails', + 'autoLogSMS', + 'autoLogInboundFax', + 'autoLogOutboundFax' + + ], + enumNames: [ + 'One-time call logging', + 'Answered incoming calls', + 'Missed incoming calls', + 'Outgoing calls', + 'Voicemails', + 'SMS', + 'Inbound faxes', + 'Outbound faxes' + ] + }, + uniqueItems: true } } }, @@ -153,128 +68,76 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { } } }, - autoOpenSection: { + autoOpenOptions: { type: 'object', title: 'Auto-open logging page after:', properties: { - popupLogPageAfterSMS: { - type: 'object', - title: 'SMS is sent', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } + customizable: { + type: 'boolean', + title: 'Customizable by user' }, - popupLogPageAfterCall: { - type: 'object', - title: 'Call ends', - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'boolean', - title: 'Value' - } - } + value: { + type: 'array', + title: 'Selected options', + items: { + type: 'string', + enum: [ + 'popupLogPageAfterSMS', + 'popupLogPageAfterCall' + ] + }, + uniqueItems: true } } } } }, uiSchema: { - enableActivityLoggingSection: { + activityLoggingOptions: { "ui:collapsible": true, - autoLogAnsweredIncoming: { - "ui:collapsible": true, - }, - autoLogMissedIncoming: { - "ui:collapsible": true, - }, - autoLogOutgoing: { - "ui:collapsible": true, - }, - autoLogVoicemails: { - "ui:collapsible": true, - }, - autoLogSMS: { - "ui:collapsible": true, - }, - autoLogInboundFax: { - "ui:collapsible": true, - }, - autoLogOutboundFax: { - "ui:collapsible": true, - } - }, - preferencesSection: { - "ui:collapsible": true, - oneTimeLog: { - "ui:collapsible": true, + value: { + "ui:widget": "checkboxes", + "ui:options": { + "inline": false + } } }, logSyncFrequencySection: { "ui:collapsible": true, - logSyncFrequency: { - "ui:collapsible": true, - } }, - autoOpenSection: { + autoOpenOptions: { "ui:collapsible": true, - popupLogPageAfterSMS: { - "ui:collapsible": true, - }, - popupLogPageAfterCall: { - "ui:collapsible": true, + value: { + "ui:widget": "checkboxes", + "ui:options": { + "inline": false + } } }, submitButtonOptions: { submitText: 'Save', - } + }, }, formData: { - enableActivityLoggingSection: { - autoLogAnsweredIncoming: { - customizable: adminUserSettings?.autoLogAnsweredIncoming?.customizable ?? true, - value: adminUserSettings?.autoLogAnsweredIncoming?.value ?? false - }, - autoLogMissedIncoming: { - customizable: adminUserSettings?.autoLogMissedIncoming?.customizable ?? true, - value: adminUserSettings?.autoLogMissedIncoming?.value ?? false - }, - autoLogOutgoing: { - customizable: adminUserSettings?.autoLogOutgoing?.customizable ?? true, - value: adminUserSettings?.autoLogOutgoing?.value ?? false - }, - autoLogVoicemails: { - customizable: adminUserSettings?.autoLogVoicemails?.customizable ?? true, - value: adminUserSettings?.autoLogVoicemails?.value ?? false - }, - autoLogSMS: { - customizable: adminUserSettings?.autoLogSMS?.customizable ?? true, - value: adminUserSettings?.autoLogSMS?.value ?? false - }, - autoLogInboundFax: { - customizable: adminUserSettings?.autoLogInboundFax?.customizable ?? true, - value: adminUserSettings?.autoLogInboundFax?.value ?? false - }, - autoLogOutboundFax: { - customizable: adminUserSettings?.autoLogOutboundFax?.customizable ?? true, - value: adminUserSettings?.autoLogOutboundFax?.value ?? false - } - }, - preferencesSection: { - oneTimeLog: { - customizable: adminUserSettings?.oneTimeLog?.customizable ?? true, - value: adminUserSettings?.oneTimeLog?.value ?? false - } + activityLoggingOptions: { + customizable: adminUserSettings?.autoLogAnsweredIncoming?.customizable ?? + adminUserSettings?.autoLogMissedIncoming?.customizable ?? + adminUserSettings?.autoLogOutgoing?.customizable ?? + adminUserSettings?.autoLogVoicemails?.customizable ?? + adminUserSettings?.autoLogSMS?.customizable ?? + adminUserSettings?.autoLogInboundFax?.customizable ?? + adminUserSettings?.autoLogOutboundFax?.customizable ?? + adminUserSettings?.oneTimeLog?.customizable ?? true, + value: [ + ...((adminUserSettings?.autoLogAnsweredIncoming?.value ?? false) ? ['autoLogAnsweredIncoming'] : []), + ...((adminUserSettings?.autoLogMissedIncoming?.value ?? false) ? ['autoLogMissedIncoming'] : []), + ...((adminUserSettings?.autoLogOutgoing?.value ?? false) ? ['autoLogOutgoing'] : []), + ...((adminUserSettings?.autoLogVoicemails?.value ?? false) ? ['autoLogVoicemails'] : []), + ...((adminUserSettings?.autoLogSMS?.value ?? false) ? ['autoLogSMS'] : []), + ...((adminUserSettings?.autoLogInboundFax?.value ?? false) ? ['autoLogInboundFax'] : []), + ...((adminUserSettings?.autoLogOutboundFax?.value ?? false) ? ['autoLogOutboundFax'] : []), + ...((adminUserSettings?.oneTimeLog?.value ?? false) ? ['oneTimeLog'] : []) + ] }, logSyncFrequencySection: { logSyncFrequency: { @@ -282,15 +145,13 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { value: adminUserSettings?.logSyncFrequency?.value ?? '10min' } }, - autoOpenSection: { - popupLogPageAfterSMS: { - customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? true, - value: adminUserSettings?.popupLogPageAfterSMS?.value ?? false - }, - popupLogPageAfterCall: { - customizable: adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, - value: adminUserSettings?.popupLogPageAfterCall?.value ?? false - } + autoOpenOptions: { + customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? + adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, + value: [ + ...((adminUserSettings?.popupLogPageAfterSMS?.value ?? false) ? ['popupLogPageAfterSMS'] : []), + ...((adminUserSettings?.popupLogPageAfterCall?.value ?? false) ? ['popupLogPageAfterCall'] : []) + ] } } } diff --git a/src/core/user.js b/src/core/user.js index d5fcfb2..c260ef9 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -51,19 +51,47 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false } const rcAccessToken = getRcAccessToken(); const manifest = await getManifest(); - let userSettings = await getUserSettingsOnline({ serverUrl: manifest.serverUrl, rcAccessToken }); + + // Try to get user settings from server, with fallback to local storage + let userSettings; + try { + userSettings = await getUserSettingsOnline({ serverUrl: manifest.serverUrl, rcAccessToken }); + } catch (e) { + console.log('Failed to get user settings from server, trying local storage:', e); + const { userSettings: localUserSettings } = await chrome.storage.local.get({ userSettings: {} }); + userSettings = localUserSettings; + } + + // If both server and local storage fail, initialize with empty object + if (!userSettings) { + userSettings = {}; + } if (changedSettings) { + console.log('Applying changed settings:', changedSettings); for (const k of Object.keys(changedSettings)) { - if (userSettings[k] === undefined || !userSettings[k].value) { + if (userSettings[k] === undefined) { userSettings[k] = changedSettings[k]; + console.log(`Setting ${k} to new value:`, changedSettings[k]); } else { userSettings[k].value = changedSettings[k].value; + console.log(`Updating ${k} value from ${userSettings[k].value} to ${changedSettings[k].value}`); } } + console.log('Final user settings after changes:', userSettings); } await chrome.storage.local.set({ userSettings }); - userSettings = await uploadUserSettings({ serverUrl: manifest.serverUrl, userSettings }); + + // Try to upload user settings to server, but continue if it fails + try { + const uploadedSettings = await uploadUserSettings({ serverUrl: manifest.serverUrl, userSettings }); + if (uploadedSettings) { + userSettings = uploadedSettings; + } + } catch (e) { + console.log('Failed to upload user settings to server, using local settings:', e); + // Continue with local settings if upload fails + } document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ type: 'rc-adapter-update-features-flags', chat: getShowChatTabSetting(userSettings).value, diff --git a/src/popup.js b/src/popup.js index 074717f..96912a0 100644 --- a/src/popup.js +++ b/src/popup.js @@ -2066,15 +2066,63 @@ window.addEventListener('message', async (e) => { break; case '/settings': const changedSettings = {}; + console.log('Raw settings data from widget:', data.body.settings); for (const s of data.body.settings) { + console.log('Processing setting section:', s); if (s.items !== undefined) { for (const i of s.items) { + console.log('Processing setting item:', i); if (i?.items !== undefined) { for (const ii of i.items) { - changedSettings[ii.id] = { value: ii.value }; + console.log('Processing nested setting item:', ii); + // Handle checkbox options for activity logging at nested level + if (ii.id === 'activityLoggingOptions') { + // Convert array of selected options to individual boolean settings + const selectedOptions = ii.value || []; + console.log('Activity logging options selected:', selectedOptions); + changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; + changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; + changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; + changedSettings.autoLogVoicemails = { value: selectedOptions.includes('autoLogVoicemails') }; + changedSettings.autoLogSMS = { value: selectedOptions.includes('autoLogSMS') }; + changedSettings.autoLogInboundFax = { value: selectedOptions.includes('autoLogInboundFax') }; + changedSettings.autoLogOutboundFax = { value: selectedOptions.includes('autoLogOutboundFax') }; + changedSettings.oneTimeLog = { value: selectedOptions.includes('oneTimeLog') }; + console.log('Activity logging changed settings:', changedSettings); + } else if (ii.id === 'autoOpenOptions') { + // Convert array of selected options to individual boolean settings + const selectedOptions = ii.value || []; + console.log('Auto-open options selected:', selectedOptions); + changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; + changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; + } else { + changedSettings[ii.id] = { value: ii.value }; + } } } else { - changedSettings[i.id] = { value: i.value }; + // Handle checkbox options for activity logging at direct level (fallback) + if (i.id === 'activityLoggingOptions') { + // Convert array of selected options to individual boolean settings + const selectedOptions = i.value || []; + console.log('Activity logging options selected:', selectedOptions); + changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; + changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; + changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; + changedSettings.autoLogVoicemails = { value: selectedOptions.includes('autoLogVoicemails') }; + changedSettings.autoLogSMS = { value: selectedOptions.includes('autoLogSMS') }; + changedSettings.autoLogInboundFax = { value: selectedOptions.includes('autoLogInboundFax') }; + changedSettings.autoLogOutboundFax = { value: selectedOptions.includes('autoLogOutboundFax') }; + changedSettings.oneTimeLog = { value: selectedOptions.includes('oneTimeLog') }; + console.log('Activity logging changed settings:', changedSettings); + } else if (i.id === 'autoOpenOptions') { + // Convert array of selected options to individual boolean settings + const selectedOptions = i.value || []; + console.log('Auto-open options selected:', selectedOptions); + changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; + changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; + } else { + changedSettings[i.id] = { value: i.value }; + } } } } @@ -2085,6 +2133,14 @@ window.addEventListener('message', async (e) => { userSettings = await userCore.refreshUserSettings({ changedSettings }); + + // Refresh the service manifest to reflect user settings changes + const serviceManifest = await embeddableServices.getServiceManifest(); + document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ + type: 'rc-adapter-register-third-party-service', + service: serviceManifest + }, '*'); + if (data.body.setting.id === "developerMode") { showNotification({ level: 'success', message: `Developer mode is turned ${data.body.setting.value ? 'ON' : 'OFF'}.`, ttl: 5000 }); await chrome.storage.local.set({ developerMode: data.body.setting.value }); @@ -2112,16 +2168,84 @@ window.addEventListener('message', async (e) => { const formData = data.body.button.formData; console.log('Admin settings form data received:', formData); - for (const sectionKey of Object.keys(formData)) { - const section = formData[sectionKey]; - if (section && typeof section === 'object') { - // Process nested settings within sections - for (const settingKey of Object.keys(section)) { - const setting = section[settingKey]; - if (setting && typeof setting === 'object' && (setting.customizable !== undefined || setting.value !== undefined)) { - // This is an individual setting, save it directly + // For activity logging page, handle both flat and nested structures + if (data.body.button.id === 'activityLoggingSettingPage') { + // Handle checkbox array structure + for (const settingKey of Object.keys(formData)) { + const setting = formData[settingKey]; + if (setting && typeof setting === 'object') { + if (settingKey === 'activityLoggingOptions') { + // Handle activity logging checkbox array + const selectedOptions = setting.value || []; + adminSettings.userSettings.autoLogAnsweredIncoming = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogAnsweredIncoming') + }; + adminSettings.userSettings.autoLogMissedIncoming = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogMissedIncoming') + }; + adminSettings.userSettings.autoLogOutgoing = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogOutgoing') + }; + adminSettings.userSettings.autoLogVoicemails = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogVoicemails') + }; + adminSettings.userSettings.autoLogSMS = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogSMS') + }; + adminSettings.userSettings.autoLogInboundFax = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogInboundFax') + }; + adminSettings.userSettings.autoLogOutboundFax = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('autoLogOutboundFax') + }; + adminSettings.userSettings.oneTimeLog = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('oneTimeLog') + }; + console.log('Saved activity logging options:', selectedOptions); + } else if (settingKey === 'autoOpenOptions') { + // Handle auto-open checkbox array + const selectedOptions = setting.value || []; + adminSettings.userSettings.popupLogPageAfterSMS = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('popupLogPageAfterSMS') + }; + adminSettings.userSettings.popupLogPageAfterCall = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes('popupLogPageAfterCall') + }; + console.log('Saved auto-open options:', selectedOptions); + } else if (setting.customizable !== undefined || setting.value !== undefined) { + // This is a direct setting console.log(`Saving admin setting: ${settingKey}`, setting); adminSettings.userSettings[settingKey] = setting; + } else if (settingKey === 'logSyncFrequencySection' && setting.logSyncFrequency) { + // Handle the nested logSyncFrequency setting + console.log(`Saving admin setting: logSyncFrequency`, setting.logSyncFrequency); + adminSettings.userSettings.logSyncFrequency = setting.logSyncFrequency; + } + } + } + } else { + // For other pages, handle nested structure + for (const sectionKey of Object.keys(formData)) { + const section = formData[sectionKey]; + if (section && typeof section === 'object') { + // Process nested settings within sections + for (const settingKey of Object.keys(section)) { + const setting = section[settingKey]; + if (setting && typeof setting === 'object' && (setting.customizable !== undefined || setting.value !== undefined)) { + // This is an individual setting, save it directly + console.log(`Saving admin setting: ${settingKey}`, setting); + adminSettings.userSettings[settingKey] = setting; + } } } } diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 74f6a3e..ad01907 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -58,84 +58,94 @@ async function getServiceManifest() { name: 'Activity logging', items: [ { - id: 'enableActivityLoggingSection', + id: 'activityLoggingSection', type: 'section', name: 'Enable automatic activity logging for:', + description: 'Select which activities to log automatically', items: [ { - id: 'autoLogAnsweredIncoming', - type: 'boolean', - name: 'Answered incoming calls', - readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly, - readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason, - value: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value, - }, - { - id: 'autoLogMissedIncoming', - type: 'boolean', - name: 'Missed incoming calls', - readOnly: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly, - readOnlyReason: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason, - value: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value, - }, - { - id: 'autoLogOutgoing', - type: 'boolean', - name: 'Outgoing calls', - readOnly: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly, - readOnlyReason: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).warning ?? userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason, - value: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value, - }, - { - id: 'autoLogVoicemails', - type: 'boolean', - name: 'Voicemails', - readOnly: userCore.getAutoLogVoicemailsSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogVoicemailsSetting(userSettings).value, - }, - { - id: 'autoLogSMS', - type: 'boolean', - name: 'SMS', - readOnly: userCore.getAutoLogSMSSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogSMSSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogSMSSetting(userSettings).value, - }, - { - id: 'autoLogInboundFax', - type: 'boolean', - name: 'Inbound faxes', - readOnly: userCore.getAutoLogInboundFaxSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogInboundFaxSetting(userSettings).value, - }, - { - id: 'autoLogOutboundFax', - type: 'boolean', - name: 'Outbound faxes', - readOnly: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason, - value: userCore.getAutoLogOutboundFaxSetting(userSettings).value, - } - ], - description: 'Automatically log activities for the selected entities' - }, - { - id: 'preferencesSection', - type: 'section', - name: 'Preferences', - items: [ - { - id: "oneTimeLog", - type: "boolean", - name: 'One-time call logging', - readOnly: userCore.getOneTimeLogSetting(userSettings).readOnly, - readOnlyReason: userCore.getOneTimeLogSetting(userSettings).readOnlyReason, - value: userCore.getOneTimeLogSetting(userSettings).value + id: 'activityLoggingOptions', + type: 'option', + name: 'Activity types', + multiple: true, + checkbox: true, + options: [ + { + id: 'oneTimeLog', + name: 'One-time call logging' + }, + { + id: 'autoLogAnsweredIncoming', + name: 'Answered incoming calls' + }, + { + id: 'autoLogMissedIncoming', + name: 'Missed incoming calls' + }, + { + id: 'autoLogOutgoing', + name: 'Outgoing calls' + }, + { + id: 'autoLogVoicemails', + name: 'Voicemails' + }, + { + id: 'autoLogSMS', + name: 'SMS' + }, + { + id: 'autoLogInboundFax', + name: 'Inbound faxes' + }, + { + id: 'autoLogOutboundFax', + name: 'Outbound faxes' + } + + ], + value: (() => { + const activityLoggingValues = [ + ...(userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value ? ['autoLogAnsweredIncoming'] : []), + ...(userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value ? ['autoLogMissedIncoming'] : []), + ...(userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value ? ['autoLogOutgoing'] : []), + ...(userCore.getAutoLogVoicemailsSetting(userSettings).value ? ['autoLogVoicemails'] : []), + ...(userCore.getAutoLogSMSSetting(userSettings).value ? ['autoLogSMS'] : []), + ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), + ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []), + ...(userCore.getOneTimeLogSetting(userSettings).value ? ['oneTimeLog'] : []) + ]; + console.log('Service manifest activity logging values:', activityLoggingValues); + console.log('User settings for activity logging:', { + autoLogAnsweredIncoming: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin), + autoLogMissedIncoming: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin), + autoLogOutgoing: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin), + autoLogVoicemails: userCore.getAutoLogVoicemailsSetting(userSettings), + autoLogSMS: userCore.getAutoLogSMSSetting(userSettings), + autoLogInboundFax: userCore.getAutoLogInboundFaxSetting(userSettings), + autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings), + oneTimeLog: userCore.getOneTimeLogSetting(userSettings) + }); + return activityLoggingValues; + })(), + readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogVoicemailsSetting(userSettings).readOnly || + userCore.getAutoLogSMSSetting(userSettings).readOnly || + userCore.getAutoLogInboundFaxSetting(userSettings).readOnly || + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly || + userCore.getOneTimeLogSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason || + userCore.getAutoLogSMSSetting(userSettings).readOnlyReason || + userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason || + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason || + userCore.getOneTimeLogSetting(userSettings).readOnlyReason } - ], - description: 'Delays logging until full call details are available' + ] }, { id: 'logSyncFrequencySection', @@ -183,25 +193,32 @@ async function getServiceManifest() { id: 'autoOpenSection', type: 'section', name: 'Auto-open logging page after:', + description: 'Choose when to automatically open the logging page', items: [ { - id: "popupLogPageAfterSMS", - type: "boolean", - name: 'SMS is sent', - readOnly: userCore.getSMSPopSetting(userSettings).readOnly, - readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason, - value: userCore.getSMSPopSetting(userSettings).value - }, - { - id: "popupLogPageAfterCall", - type: "boolean", - name: 'Call ends', - readOnly: userCore.getCallPopSetting(userSettings).readOnly, - readOnlyReason: userCore.getCallPopSetting(userSettings).readOnlyReason, - value: userCore.getCallPopSetting(userSettings).value + id: 'autoOpenOptions', + type: 'option', + name: 'Trigger events', + multiple: true, + checkbox: true, + options: [ + { + id: 'popupLogPageAfterSMS', + name: 'SMS is sent' + }, + { + id: 'popupLogPageAfterCall', + name: 'Call ends' + } + ], + value: [ + ...(userCore.getSMSPopSetting(userSettings).value ? ['popupLogPageAfterSMS'] : []), + ...(userCore.getCallPopSetting(userSettings).value ? ['popupLogPageAfterCall'] : []) + ], + readOnly: userCore.getSMSPopSetting(userSettings).readOnly || userCore.getCallPopSetting(userSettings).readOnly, + readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason || userCore.getCallPopSetting(userSettings).readOnlyReason } - ], - description: 'Opens the logging page for manual entry after selected events' + ] } ] }, From 3a55c8ce83f954e0ee629124af341a1757b11b10 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 25 Jul 2025 12:48:05 +0530 Subject: [PATCH 04/19] UI change --- .../activityLoggingSettingPage.js | 111 +++- .../managedSettings/customSettingsPage.js | 5 + src/popup.js | 77 ++- src/service/embeddableServices.js | 510 +++++++++++------- 4 files changed, 496 insertions(+), 207 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index a23ab7e..21f765e 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -1,5 +1,5 @@ -function getActivityLoggingSettingPageRender({ adminUserSettings }) { - return { +function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, userPermissions = {} }) { + const page = { id: 'activityLoggingSettingPage', title: 'Activity logging', type: 'page', @@ -154,7 +154,114 @@ function getActivityLoggingSettingPageRender({ adminUserSettings }) { ] } } + }; + + // Add custom settings with section "activityLogging" + if (crmManifest?.settings) { + for (const customSetting of crmManifest.settings) { + if (customSetting.section === 'activityLogging') { + console.log('Adding custom setting to activity logging admin page:', customSetting.id); + + // Handle different types of custom settings + switch (customSetting.type) { + case 'option': + // Filter options based on permissions + const filteredOptions = customSetting.options ? customSetting.options.filter(opt => + !opt.requiredPermission || userPermissions[opt.requiredPermission] + ) : []; + + page.schema.properties[customSetting.id] = { + type: 'object', + title: customSetting.name, + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'array', + title: customSetting.name, + items: { + type: 'string', + enum: filteredOptions.map(opt => opt.id), + enumNames: filteredOptions.map(opt => opt.name) + }, + uniqueItems: true + } + } + }; + + page.uiSchema[customSetting.id] = { + "ui:collapsible": true, + value: { + "ui:widget": "checkboxes", + "ui:options": { + "inline": false + } + } + }; + + // Determine current value based on individual setting values + const currentSelectedOptions = []; + let isCustomizable = true; + + for (const option of filteredOptions) { + if (adminUserSettings?.[option.id]?.value) { + currentSelectedOptions.push(option.id); + } + // If any individual option is not customizable, the whole section becomes non-customizable + if (adminUserSettings?.[option.id]?.customizable === false) { + isCustomizable = false; + } + } + + page.formData[customSetting.id] = { + customizable: isCustomizable, + value: currentSelectedOptions + }; + + console.log(`Admin page loading - ${customSetting.id}:`, { + customizable: isCustomizable, + selectedOptions: currentSelectedOptions, + individualSettings: filteredOptions.map(opt => ({ + id: opt.id, + value: adminUserSettings?.[opt.id]?.value, + customizable: adminUserSettings?.[opt.id]?.customizable + })) + }); + break; + + case 'boolean': + page.schema.properties[customSetting.id] = { + type: 'object', + title: customSetting.name, + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Value' + } + } + }; + + page.uiSchema[customSetting.id] = { + "ui:collapsible": true + }; + + page.formData[customSetting.id] = { + customizable: adminUserSettings?.[customSetting.id]?.customizable ?? true, + value: adminUserSettings?.[customSetting.id]?.value ?? customSetting.defaultValue ?? false + }; + break; + } + } + } } + + return page; } exports.getActivityLoggingSettingPageRender = getActivityLoggingSettingPageRender; \ No newline at end of file diff --git a/src/components/admin/managedSettings/customSettingsPage.js b/src/components/admin/managedSettings/customSettingsPage.js index 054d87b..6f73c62 100644 --- a/src/components/admin/managedSettings/customSettingsPage.js +++ b/src/components/admin/managedSettings/customSettingsPage.js @@ -22,6 +22,11 @@ function getCustomSettingsPageRender({ crmManifest, adminUserSettings, userSetti } } for (const section of crmManifest.settings) { + // Skip sections that should appear in Activity logging admin page + if (section.section === 'activityLogging') { + continue; + } + page.schema.properties[section.id] = { type: 'string', description: section.name diff --git a/src/popup.js b/src/popup.js index 96912a0..516b5ae 100644 --- a/src/popup.js +++ b/src/popup.js @@ -1020,7 +1020,12 @@ window.addEventListener('message', async (e) => { }, '*'); break; case 'activityLogging': - const activityLoggingSettingPageRender = activityLoggingSettingPage.getActivityLoggingSettingPageRender({ adminUserSettings: adminSettings?.userSettings }); + const { userPermissions } = await chrome.storage.local.get({ userPermissions: {} }); + const activityLoggingSettingPageRender = activityLoggingSettingPage.getActivityLoggingSettingPageRender({ + adminUserSettings: adminSettings?.userSettings, + crmManifest: platform, + userPermissions + }); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ type: 'rc-adapter-register-customized-page', page: activityLoggingSettingPageRender @@ -2095,6 +2100,20 @@ window.addEventListener('message', async (e) => { console.log('Auto-open options selected:', selectedOptions); changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; + } else if (ii.id === 'callLogDetails') { + // Convert array of selected options to individual boolean settings + const selectedOptions = ii.value || []; + console.log('Call log details options selected:', selectedOptions); + changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; + changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; + changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; + changedSettings.addCallLogContactNumber = { value: selectedOptions.includes('addCallLogContactNumber') }; + changedSettings.addCallLogDateTime = { value: selectedOptions.includes('addCallLogDateTime') }; + changedSettings.addCallLogDuration = { value: selectedOptions.includes('addCallLogDuration') }; + changedSettings.addCallLogResult = { value: selectedOptions.includes('addCallLogResult') }; + changedSettings.addCallLogRecording = { value: selectedOptions.includes('addCallLogRecording') }; + changedSettings.addCallLogAiNote = { value: selectedOptions.includes('addCallLogAiNote') }; + changedSettings.addCallLogTranscript = { value: selectedOptions.includes('addCallLogTranscript') }; } else { changedSettings[ii.id] = { value: ii.value }; } @@ -2120,6 +2139,20 @@ window.addEventListener('message', async (e) => { console.log('Auto-open options selected:', selectedOptions); changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; + } else if (i.id === 'callLogDetails') { + // Convert array of selected options to individual boolean settings + const selectedOptions = i.value || []; + console.log('Call log details options selected:', selectedOptions); + changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; + changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; + changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; + changedSettings.addCallLogContactNumber = { value: selectedOptions.includes('addCallLogContactNumber') }; + changedSettings.addCallLogDateTime = { value: selectedOptions.includes('addCallLogDateTime') }; + changedSettings.addCallLogDuration = { value: selectedOptions.includes('addCallLogDuration') }; + changedSettings.addCallLogResult = { value: selectedOptions.includes('addCallLogResult') }; + changedSettings.addCallLogRecording = { value: selectedOptions.includes('addCallLogRecording') }; + changedSettings.addCallLogAiNote = { value: selectedOptions.includes('addCallLogAiNote') }; + changedSettings.addCallLogTranscript = { value: selectedOptions.includes('addCallLogTranscript') }; } else { changedSettings[i.id] = { value: i.value }; } @@ -2222,6 +2255,41 @@ window.addEventListener('message', async (e) => { value: selectedOptions.includes('popupLogPageAfterCall') }; console.log('Saved auto-open options:', selectedOptions); + } else if (Array.isArray(setting.value) && setting.customizable !== undefined) { + // Handle custom activity logging settings (like call log details) + const selectedOptions = setting.value || []; + console.log(`Saving custom activity logging setting: ${settingKey}`, { + selectedOptions, + customizable: setting.customizable, + settingObject: setting + }); + + // Find the custom setting definition to get the options + let customSettingDef = null; + if (platform?.settings) { + for (const cs of platform.settings) { + if (cs.id === settingKey && cs.section === 'activityLogging') { + customSettingDef = cs; + break; + } + } + } + + if (customSettingDef && customSettingDef.options) { + console.log(`Found custom setting definition for ${settingKey}:`, customSettingDef); + // Set each individual option as a separate admin setting + for (const option of customSettingDef.options) { + const individualSetting = { + customizable: setting.customizable ?? true, + value: selectedOptions.includes(option.id) + }; + adminSettings.userSettings[option.id] = individualSetting; + console.log(`Set admin setting ${option.id}:`, individualSetting); + } + console.log(`Processed ${customSettingDef.options.length} options for ${settingKey}`); + } else { + console.warn(`No custom setting definition found for ${settingKey}`); + } } else if (setting.customizable !== undefined || setting.value !== undefined) { // This is a direct setting console.log(`Saving admin setting: ${settingKey}`, setting); @@ -2254,7 +2322,12 @@ window.addEventListener('message', async (e) => { console.log('Final admin settings to save:', adminSettings); await chrome.storage.local.set({ adminSettings }); await adminCore.uploadAdminSettings({ serverUrl: manifest.serverUrl, adminSettings }); - userSettings = await userCore.refreshUserSettings({}); + + // Add delay to avoid race condition - wait for server to process admin settings + await new Promise(resolve => setTimeout(resolve, 1000)); + console.log('Admin settings uploaded, refreshing user settings after delay...'); + + userSettings = await userCore.refreshUserSettings({ isAfterAdminChanges: true }); // Refresh the service manifest to reflect admin changes in user settings const serviceManifest = await embeddableServices.getServiceManifest(); diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index ad01907..8671b67 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -53,172 +53,151 @@ async function getServiceManifest() { settingsPath: '/settings', settings: [ { - id: 'logging', - type: 'group', + id: 'activityLogging', + type: 'section', name: 'Activity logging', items: [ { - id: 'activityLoggingSection', - type: 'section', - name: 'Enable automatic activity logging for:', - description: 'Select which activities to log automatically', - items: [ + id: 'activityLoggingOptions', + type: 'option', + name: ' Enable automatic activity logging for:', + multiple: true, + checkbox: true, + description: 'Automatically log activities for the selected entities', + options: [ { - id: 'activityLoggingOptions', - type: 'option', - name: 'Activity types', - multiple: true, - checkbox: true, - options: [ - { - id: 'oneTimeLog', - name: 'One-time call logging' - }, - { - id: 'autoLogAnsweredIncoming', - name: 'Answered incoming calls' - }, - { - id: 'autoLogMissedIncoming', - name: 'Missed incoming calls' - }, - { - id: 'autoLogOutgoing', - name: 'Outgoing calls' - }, - { - id: 'autoLogVoicemails', - name: 'Voicemails' - }, - { - id: 'autoLogSMS', - name: 'SMS' - }, - { - id: 'autoLogInboundFax', - name: 'Inbound faxes' - }, - { - id: 'autoLogOutboundFax', - name: 'Outbound faxes' - } - - ], - value: (() => { - const activityLoggingValues = [ - ...(userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value ? ['autoLogAnsweredIncoming'] : []), - ...(userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value ? ['autoLogMissedIncoming'] : []), - ...(userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value ? ['autoLogOutgoing'] : []), - ...(userCore.getAutoLogVoicemailsSetting(userSettings).value ? ['autoLogVoicemails'] : []), - ...(userCore.getAutoLogSMSSetting(userSettings).value ? ['autoLogSMS'] : []), - ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), - ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []), - ...(userCore.getOneTimeLogSetting(userSettings).value ? ['oneTimeLog'] : []) - ]; - console.log('Service manifest activity logging values:', activityLoggingValues); - console.log('User settings for activity logging:', { - autoLogAnsweredIncoming: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin), - autoLogMissedIncoming: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin), - autoLogOutgoing: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin), - autoLogVoicemails: userCore.getAutoLogVoicemailsSetting(userSettings), - autoLogSMS: userCore.getAutoLogSMSSetting(userSettings), - autoLogInboundFax: userCore.getAutoLogInboundFaxSetting(userSettings), - autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings), - oneTimeLog: userCore.getOneTimeLogSetting(userSettings) - }); - return activityLoggingValues; - })(), - readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogVoicemailsSetting(userSettings).readOnly || - userCore.getAutoLogSMSSetting(userSettings).readOnly || - userCore.getAutoLogInboundFaxSetting(userSettings).readOnly || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly || - userCore.getOneTimeLogSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason || - userCore.getAutoLogSMSSetting(userSettings).readOnlyReason || - userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason || - userCore.getOneTimeLogSetting(userSettings).readOnlyReason + id: 'oneTimeLog', + name: 'One-time call logging' + }, + { + id: 'autoLogAnsweredIncoming', + name: 'Answered incoming calls' + }, + { + id: 'autoLogMissedIncoming', + name: 'Missed incoming calls' + }, + { + id: 'autoLogOutgoing', + name: 'Outgoing calls' + }, + { + id: 'autoLogVoicemails', + name: 'Voicemails' + }, + { + id: 'autoLogSMS', + name: 'SMS' + }, + { + id: 'autoLogInboundFax', + name: 'Inbound faxes' + }, + { + id: 'autoLogOutboundFax', + name: 'Outbound faxes' } - ] + + ], + value: (() => { + const activityLoggingValues = [ + ...(userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value ? ['autoLogAnsweredIncoming'] : []), + ...(userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value ? ['autoLogMissedIncoming'] : []), + ...(userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value ? ['autoLogOutgoing'] : []), + ...(userCore.getAutoLogVoicemailsSetting(userSettings).value ? ['autoLogVoicemails'] : []), + ...(userCore.getAutoLogSMSSetting(userSettings).value ? ['autoLogSMS'] : []), + ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), + ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []), + ...(userCore.getOneTimeLogSetting(userSettings).value ? ['oneTimeLog'] : []) + ]; + console.log('Service manifest activity logging values:', activityLoggingValues); + console.log('User settings for activity logging:', { + autoLogAnsweredIncoming: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin), + autoLogMissedIncoming: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin), + autoLogOutgoing: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin), + autoLogVoicemails: userCore.getAutoLogVoicemailsSetting(userSettings), + autoLogSMS: userCore.getAutoLogSMSSetting(userSettings), + autoLogInboundFax: userCore.getAutoLogInboundFaxSetting(userSettings), + autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings), + oneTimeLog: userCore.getOneTimeLogSetting(userSettings) + }); + return activityLoggingValues; + })(), + readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly || + userCore.getAutoLogVoicemailsSetting(userSettings).readOnly || + userCore.getAutoLogSMSSetting(userSettings).readOnly || + userCore.getAutoLogInboundFaxSetting(userSettings).readOnly || + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly || + userCore.getOneTimeLogSetting(userSettings).readOnly, + readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason || + userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason || + userCore.getAutoLogSMSSetting(userSettings).readOnlyReason || + userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason || + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason || + userCore.getOneTimeLogSetting(userSettings).readOnlyReason }, { - id: 'logSyncFrequencySection', - type: 'section', - name: 'Log sync frequency', - items: [ + id: "logSyncFrequency", + type: "option", + name: ' Log sync frequency', + description: 'How often to sync missed activity; disable to turn off background logging', + options: [ { - id: "logSyncFrequency", - type: "option", - name: 'Frequency', - options: [ - { - id: 'disabled', - name: 'Disabled' - }, - { - id: '10min', - name: '10 min' - }, - { - id: '30min', - name: '30 min' - }, - { - id: '1hour', - name: '1 hour' - }, - { - id: '3hours', - name: '3 hours' - }, - { - id: '1day', - name: '1 day' - } - ], - value: userCore.getLogSyncFrequencySetting(userSettings).value, - readOnly: userCore.getLogSyncFrequencySetting(userSettings).readOnly, - readOnlyReason: userCore.getLogSyncFrequencySetting(userSettings).readOnlyReason, + id: 'disabled', + name: 'Disabled' + }, + { + id: '10min', + name: '10 min' + }, + { + id: '30min', + name: '30 min' + }, + { + id: '1hour', + name: '1 hour' + }, + { + id: '3hours', + name: '3 hours' + }, + { + id: '1day', + name: '1 day' } ], - description: 'How often to sync missed activity; disable to turn off background logging' + value: userCore.getLogSyncFrequencySetting(userSettings).value, + readOnly: userCore.getLogSyncFrequencySetting(userSettings).readOnly, + readOnlyReason: userCore.getLogSyncFrequencySetting(userSettings).readOnlyReason, }, { - id: 'autoOpenSection', - type: 'section', + id: 'autoOpenOptions', + type: 'option', name: 'Auto-open logging page after:', - description: 'Choose when to automatically open the logging page', - items: [ + description: 'Opens the logging page for manual entry after selected events.', + multiple: true, + checkbox: true, + options: [ { - id: 'autoOpenOptions', - type: 'option', - name: 'Trigger events', - multiple: true, - checkbox: true, - options: [ - { - id: 'popupLogPageAfterSMS', - name: 'SMS is sent' - }, - { - id: 'popupLogPageAfterCall', - name: 'Call ends' - } - ], - value: [ - ...(userCore.getSMSPopSetting(userSettings).value ? ['popupLogPageAfterSMS'] : []), - ...(userCore.getCallPopSetting(userSettings).value ? ['popupLogPageAfterCall'] : []) - ], - readOnly: userCore.getSMSPopSetting(userSettings).readOnly || userCore.getCallPopSetting(userSettings).readOnly, - readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason || userCore.getCallPopSetting(userSettings).readOnlyReason + id: 'popupLogPageAfterSMS', + name: 'SMS is sent' + }, + { + id: 'popupLogPageAfterCall', + name: 'Call ends' } - ] + ], + value: [ + ...(userCore.getSMSPopSetting(userSettings).value ? ['popupLogPageAfterSMS'] : []), + ...(userCore.getCallPopSetting(userSettings).value ? ['popupLogPageAfterCall'] : []) + ], + readOnly: userCore.getSMSPopSetting(userSettings).readOnly || userCore.getCallPopSetting(userSettings).readOnly, + readOnlyReason: userCore.getSMSPopSetting(userSettings).readOnlyReason || userCore.getCallPopSetting(userSettings).readOnlyReason } ] }, @@ -521,76 +500,201 @@ async function getServiceManifest() { if (customSettings) { for (const cs of customSettings) { const items = []; - for (const item of cs.items) { - if (item.requiredPermission && !userPermissions[item.requiredPermission]) { - continue; - } - switch (item.type) { - case 'inputField': + + // Handle direct setting (cs itself is the setting) + if (cs.type && !cs.items) { + switch (cs.type) { + case 'option': + // Filter options based on permissions + const filteredOptions = cs.options ? cs.options.filter(opt => + !opt.requiredPermission || userPermissions[opt.requiredPermission] + ) : []; + + // For checkbox options, build value array from individual option settings + let finalValue; + let isReadOnly = false; + let readOnlyReason = ''; + + if (cs.multiple && cs.checkbox && cs.options) { + // Build value array from individual option values + finalValue = []; + for (const option of filteredOptions) { + const optionSetting = userCore.getCustomSetting(userSettings, option.id, false); + if (optionSetting.value) { + finalValue.push(option.id); + } + // If any option is read-only, mark the whole section as read-only + if (optionSetting.readOnly) { + isReadOnly = true; + readOnlyReason = optionSetting.readOnlyReason || 'This setting is managed by admin'; + } + } + console.log(`User-side ${cs.id} checkbox values:`, { + finalValue, + isReadOnly, + readOnlyReason, + optionDetails: filteredOptions.map(opt => ({ + id: opt.id, + setting: userCore.getCustomSetting(userSettings, opt.id, false) + })) + }); + } else { + // Single value setting + const currentValue = userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value; + finalValue = currentValue !== undefined ? currentValue : + (cs.multiple ? (cs.defaultValue || []) : (cs.defaultValue || "")); + const settingInfo = userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue); + isReadOnly = settingInfo.readOnly; + readOnlyReason = settingInfo.readOnlyReason; + } + items.push({ - id: item.id, - type: 'string', - name: item.name, - description: item.description, - placeHolder: item.placeHolder ?? "", - value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value, - readOnly: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnly, - readOnlyReason: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnlyReason + id: cs.id, + type: "option", + name: cs.name, + description: cs.description, + options: filteredOptions, + multiple: cs.multiple ?? false, + checkbox: cs.checkbox ?? false, + required: cs.required ?? false, + value: finalValue, + readOnly: isReadOnly, + readOnlyReason: readOnlyReason }); break; case 'boolean': items.push({ - id: item.id, - type: item.type, - name: item.name, - description: item.description, - value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value, - readOnly: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnly, - readOnlyReason: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnlyReason + id: cs.id, + type: cs.type, + name: cs.name, + description: cs.description, + value: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value, + readOnly: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnly, + readOnlyReason: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnlyReason }); break; - case 'warning': - items.push( - { + case 'inputField': + items.push({ + id: cs.id, + type: 'string', + name: cs.name, + description: cs.description, + placeHolder: cs.placeHolder ?? "", + value: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value, + readOnly: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnly, + readOnlyReason: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnlyReason + }); + break; + } + } + // Handle container with items (existing behavior) + else if (cs.items) { + for (const item of cs.items) { + if (item.requiredPermission && !userPermissions[item.requiredPermission]) { + continue; + } + switch (item.type) { + case 'inputField': + items.push({ id: item.id, + type: 'string', name: item.name, - type: 'admonition', - severity: 'warning', - value: item.value - } - ) - break; - case 'option': - items.push( - { + description: item.description, + placeHolder: item.placeHolder ?? "", + value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value, + readOnly: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnly, + readOnlyReason: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnlyReason + }); + break; + case 'boolean': + items.push({ id: item.id, - type: "option", + type: item.type, name: item.name, description: item.description, - options: item.dynamicOptions ? userCore.getCustomSetting(userSettings, item.id, item.defaultValue).options : item.options, - multiple: item.multiple ?? false, - checkbox: item.checkbox ?? false, - required: item.required ?? false, - value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value ?? (item.multiple ? [] : ""), + value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value, readOnly: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnly, readOnlyReason: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnlyReason - } - ) - break; + }); + break; + case 'warning': + items.push( + { + id: item.id, + name: item.name, + type: 'admonition', + severity: 'warning', + value: item.value + } + ) + break; + case 'option': + items.push( + { + id: item.id, + type: "option", + name: item.name, + description: item.description, + options: item.dynamicOptions ? userCore.getCustomSetting(userSettings, item.id, item.defaultValue).options : item.options, + multiple: item.multiple ?? false, + checkbox: item.checkbox ?? false, + required: item.required ?? false, + value: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).value ?? (item.multiple ? [] : ""), + readOnly: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnly, + readOnlyReason: userCore.getCustomSetting(userSettings, item.id, item.defaultValue).readOnlyReason + } + ) + break; + } } } - const group = { - id: cs.id, - type: cs.type, - name: cs.name, - items - }; - if (cs.group) { - group.groupId = cs.group; + // Handle custom settings with section property - add to existing sections + if (cs.section) { + console.log({ message: "Adding to existing section", cs, section: cs.section }); + const targetSection = services.settings.find(s => s.id === cs.section); + if (targetSection && targetSection.items) { + // For direct settings (cs.type && !cs.items), add the processed items directly + if (cs.type && !cs.items) { + // Add each processed item directly to the target section + targetSection.items.push(...items); + console.log(`Added ${items.length} direct setting(s) from ${cs.id} to section ${cs.section}`); + } else { + // For container settings, add as a subsection + const subsection = { + id: cs.id, + type: cs.type, + name: cs.name, + items + }; + targetSection.items.push(subsection); + console.log(`Added custom setting subsection ${cs.id} to section ${cs.section}`); + } + } else { + console.warn(`Target section ${cs.section} not found, adding as top-level group`); + // Fallback: add as top-level group if section not found + const group = { + id: cs.id, + type: cs.type, + name: cs.name, + items + }; + services.settings.splice(1, 0, group); + } + } else { + // Handle as regular group (existing behavior) + const group = { + id: cs.id, + type: cs.type, + name: cs.name, + items + }; + if (cs.group) { + group.groupId = cs.group; + } + services.settings.splice(1, 0, group); } - services.settings.splice(1, 0, group); } - }; + } if (platformName === 'clio' || platformName === 'insightly' || platformName === 'netsuite') { const numberFormatterComponent = [ { From b8897316ced802b2cc7c5135d77de4cb7e72ab67 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 25 Jul 2025 13:40:46 +0530 Subject: [PATCH 05/19] CHange description --- src/service/embeddableServices.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 8671b67..511beaa 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -63,7 +63,7 @@ async function getServiceManifest() { name: ' Enable automatic activity logging for:', multiple: true, checkbox: true, - description: 'Automatically log activities for the selected entities', + helper: `Select the types of communications you'd like automatically logged to your CRM.`, options: [ { id: 'oneTimeLog', @@ -143,8 +143,8 @@ async function getServiceManifest() { { id: "logSyncFrequency", type: "option", - name: ' Log sync frequency', - description: 'How often to sync missed activity; disable to turn off background logging', + name: 'Log sync frequency', + helper: `Specify how often you'd like to check for any unlogged calls.`, options: [ { id: 'disabled', @@ -179,7 +179,7 @@ async function getServiceManifest() { id: 'autoOpenOptions', type: 'option', name: 'Auto-open logging page after:', - description: 'Opens the logging page for manual entry after selected events.', + helper: 'Opens the logging page for manual entry after selected events.', multiple: true, checkbox: true, options: [ @@ -552,7 +552,7 @@ async function getServiceManifest() { id: cs.id, type: "option", name: cs.name, - description: cs.description, + helper: cs.helper, options: filteredOptions, multiple: cs.multiple ?? false, checkbox: cs.checkbox ?? false, @@ -567,7 +567,7 @@ async function getServiceManifest() { id: cs.id, type: cs.type, name: cs.name, - description: cs.description, + helper: cs.helper, value: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value, readOnly: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnly, readOnlyReason: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnlyReason @@ -578,7 +578,7 @@ async function getServiceManifest() { id: cs.id, type: 'string', name: cs.name, - description: cs.description, + helper: cs.helper, placeHolder: cs.placeHolder ?? "", value: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value, readOnly: userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).readOnly, From ca49dc85365d2e2fc9418f9fea7e4e07bc39b702 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 28 Jul 2025 16:47:44 +0530 Subject: [PATCH 06/19] change frequency logic --- src/core/user.js | 23 +++++- src/popup.js | 15 +++- src/service/embeddableServices.js | 1 - src/service/logService.js | 133 +++++++++++++++++++----------- 4 files changed, 119 insertions(+), 53 deletions(-) diff --git a/src/core/user.js b/src/core/user.js index c260ef9..8c7144d 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -158,10 +158,27 @@ function getAutoLogCallSetting(userSettings, isAdmin) { warning: 'Unavailable while server side call logging enabled' } } + + // Check if any of the individual auto logging settings are enabled + const autoLogAnsweredIncoming = userSettings?.autoLogAnsweredIncoming?.value ?? false; + const autoLogMissedIncoming = userSettings?.autoLogMissedIncoming?.value ?? false; + const autoLogOutgoing = userSettings?.autoLogOutgoing?.value ?? false; + const legacyAutoLogCall = userSettings?.autoLogCall?.value ?? false; // Fallback for backwards compatibility + + const isAnyAutoLogEnabled = autoLogAnsweredIncoming || autoLogMissedIncoming || autoLogOutgoing || legacyAutoLogCall; + + // Check if any setting is read-only (managed by admin) + const isReadOnly = (userSettings?.autoLogAnsweredIncoming?.customizable === false) || + (userSettings?.autoLogMissedIncoming?.customizable === false) || + (userSettings?.autoLogOutgoing?.customizable === false) || + (userSettings?.autoLogCall?.customizable === false); + + const readOnlyReason = isReadOnly ? 'This setting is managed by admin' : ''; + return { - value: userSettings?.autoLogCall?.value ?? false, - readOnly: userSettings?.autoLogCall?.customizable === undefined ? false : !userSettings?.autoLogCall?.customizable, - readOnlyReason: !userSettings?.autoLogCall?.customizable ? 'This setting is managed by admin' : '' + value: isAnyAutoLogEnabled, + readOnly: isReadOnly, + readOnlyReason: readOnlyReason } } diff --git a/src/popup.js b/src/popup.js index 516b5ae..74f62ce 100644 --- a/src/popup.js +++ b/src/popup.js @@ -83,6 +83,7 @@ async function restartSyncInterval() { const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); if (retroAutoCallLogIntervalId) { clearInterval(retroAutoCallLogIntervalId); + await chrome.storage.local.set({ retroAutoCallLogIntervalId: null }); } // Check if auto logging is enabled @@ -91,24 +92,27 @@ async function restartSyncInterval() { (userSettings?.autoLogOutgoing?.value ?? false); const isAutoLogEnabled = autoLogCallsGroupTrigger || (userSettings?.autoLogCall?.value ?? false); - console.log({ message: 'isAutoLogEnabled:', isAutoLogEnabled, crmAuthed, userSettings }); + // Start interval if conditions are met if (isAutoLogEnabled && crmAuthed) { const syncIntervalMs = userCore.getLogSyncFrequencyInMilliseconds(userSettings); + if (syncIntervalMs > 0) { + await chrome.storage.local.set({ retroAutoCallLogMaxAttempt: 10 }); const newRetroAutoCallLogIntervalId = setInterval( function () { logService.retroAutoCallLog({ manifest, platformName, platform - }) + }); }, syncIntervalMs); await chrome.storage.local.set({ retroAutoCallLogIntervalId: newRetroAutoCallLogIntervalId }); - console.log(`Sync interval restarted with frequency: ${syncIntervalMs}ms`); } } } + + checkC2DCollision(); getCustomManifest(); @@ -286,6 +290,8 @@ window.addEventListener('message', async (e) => { setInterval(async function () { await triggerPendingRecordingCheck({ serverUrl: manifest.serverUrl }); }, 300000); + + } // Unique: Bullhorn if (platform.name === 'bullhorn' && crmAuthed) { @@ -2167,6 +2173,9 @@ window.addEventListener('message', async (e) => { changedSettings }); + // Restart sync interval to respect any changes to sync frequency or activity logging settings + await restartSyncInterval(); + // Refresh the service manifest to reflect user settings changes const serviceManifest = await embeddableServices.getServiceManifest(); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 511beaa..ef76ef9 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -650,7 +650,6 @@ async function getServiceManifest() { } // Handle custom settings with section property - add to existing sections if (cs.section) { - console.log({ message: "Adding to existing section", cs, section: cs.section }); const targetSection = services.settings.find(s => s.id === cs.section); if (targetSection && targetSection.items) { // For direct settings (cs.type && !cs.items), add the processed items directly diff --git a/src/service/logService.js b/src/service/logService.js index d5fde0f..611b263 100644 --- a/src/service/logService.js +++ b/src/service/logService.js @@ -13,11 +13,15 @@ async function retroAutoCallLog({ const { isAdmin } = await chrome.storage.local.get({ isAdmin: false }); const { userSettings } = await chrome.storage.local.get({ userSettings: {} }); const { rcAdditionalSubmission } = await chrome.storage.local.get({ rcAdditionalSubmission: {} }); + const logSyncFrequency = userCore.getLogSyncFrequencySetting(userSettings).value; + if (logSyncFrequency === 'disabled') { return; } + const { retroAutoCallLogMaxAttempt } = await chrome.storage.local.get({ retroAutoCallLogMaxAttempt: 10 }); + let retroLoggedCount = 0; if (retroAutoCallLogMaxAttempt > 0) { await chrome.storage.local.set({ retroAutoCallLogMaxAttempt: retroAutoCallLogMaxAttempt - 1 }); @@ -25,45 +29,71 @@ async function retroAutoCallLog({ let effectiveCount = 0; const itemsPerPage = 50; const pageNumber = 1; - const { calls, hasMore } = await RCAdapter.getUnloggedCalls(itemsPerPage, pageNumber) - const isAutoLog = userCore.getAutoLogCallSetting(userSettings, isAdmin).value; - const { retroAutoCallLogNotificationId } = await chrome.storage.local.get({ retroAutoCallLogNotificationId: null }) - if (isAutoLog) { + + let retroAutoCallLogNotificationId; + + try { + const { calls, hasMore } = await RCAdapter.getUnloggedCalls(itemsPerPage, pageNumber); + + const isAutoLog = userCore.getAutoLogCallSetting(userSettings, isAdmin).value; + + if (!isAutoLog) { + return; + } + + const notificationData = await chrome.storage.local.get({ retroAutoCallLogNotificationId: null }); + retroAutoCallLogNotificationId = notificationData.retroAutoCallLogNotificationId; + if (!retroAutoCallLogNotificationId) { - const newRetroAutoCallLogNotificationId = await showNotification({ level: 'success', message: 'Attempting to sync historical call logs in the background...', ttl: 5000 }); + const newRetroAutoCallLogNotificationId = await showNotification({ + level: 'success', + message: 'Attempting to sync historical call logs in the background...', + ttl: 5000 + }); await chrome.storage.local.set({ retroAutoCallLogNotificationId: newRetroAutoCallLogNotificationId }); } + for (const c of calls) { if (effectiveCount >= effectiveTotal) { break; } + const contactPhoneNumber = c.direction === 'Inbound' ? c.from.phoneNumber : c.to.phoneNumber; - const { matched: callContactMatched, returnMessage: callLogContactMatchMessage, contactInfo: callMatchedContact } = await contactCore.getContact({ serverUrl: manifest.serverUrl, phoneNumber: contactPhoneNumber, platformName }); - if (!callContactMatched) { - continue; - } - const { hasConflict, autoSelectAdditionalSubmission } = await getLogConflictInfo({ - platform, - isAutoLog, - contactInfo: callMatchedContact, - logType: 'callLog', - direction: c.direction, - isVoicemail: false - }); - if (!hasConflict) { - const callLogSubject = c.direction === 'Inbound' ? - `Inbound Call from ${callMatchedContact[0]?.name ?? ''}` : - `Outbound Call to ${callMatchedContact[0]?.name ?? ''}`; - const note = await logCore.getCachedNote({ sessionId: c.sessionId }); - const exsitingLog = await logCore.getLog({ + + try { + const { matched: callContactMatched, returnMessage: callLogContactMatchMessage, contactInfo: callMatchedContact } = await contactCore.getContact({ serverUrl: manifest.serverUrl, - logType: 'Call', - sessionIds: c.sessionId, - requireDetails: false + phoneNumber: contactPhoneNumber, + platformName + }); + + if (!callContactMatched) { + continue; + } + + const { hasConflict, autoSelectAdditionalSubmission } = await getLogConflictInfo({ + platform, + isAutoLog, + contactInfo: callMatchedContact, + logType: 'callLog', + direction: c.direction, + isVoicemail: false }); - if (!!exsitingLog?.callLogs[0] && !exsitingLog.callLogs[0].matched) { - await logCore.addLog( - { + + if (!hasConflict) { + const callLogSubject = c.direction === 'Inbound' ? + `Inbound Call from ${callMatchedContact[0]?.name ?? ''}` : + `Outbound Call to ${callMatchedContact[0]?.name ?? ''}`; + const note = await logCore.getCachedNote({ sessionId: c.sessionId }); + const exsitingLog = await logCore.getLog({ + serverUrl: manifest.serverUrl, + logType: 'Call', + sessionIds: c.sessionId, + requireDetails: false + }); + + if (!!exsitingLog?.callLogs[0] && !exsitingLog.callLogs[0].matched) { + await logCore.addLog({ serverUrl: manifest.serverUrl, logType: 'Call', logInfo: c, @@ -78,33 +108,44 @@ async function retroAutoCallLog({ contactName: callMatchedContact[0]?.name, isShowNotification: false }); - if (!isObjectEmpty(autoSelectAdditionalSubmission) && !userCore.getOneTimeLogSetting(userSettings).value) { - await dispositionCore.upsertDisposition({ - serverUrl: manifest.serverUrl, - logType: 'Call', - sessionId: c.sessionId, - dispositions: { ...autoSelectAdditionalSubmission, note }, - rcAdditionalSubmission - }); + + if (!isObjectEmpty(autoSelectAdditionalSubmission) && !userCore.getOneTimeLogSetting(userSettings).value) { + await dispositionCore.upsertDisposition({ + serverUrl: manifest.serverUrl, + logType: 'Call', + sessionId: c.sessionId, + dispositions: { ...autoSelectAdditionalSubmission, note }, + rcAdditionalSubmission + }); + } + retroLoggedCount++; + effectiveCount++; + } + else { + // force call log matcher check + document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ + type: 'rc-adapter-trigger-call-logger-match', + sessionIds: [exsitingLog.callLogs[0].sessionId] + }, '*'); } - retroLoggedCount++; - effectiveCount++; - } - else { - // force call log matcher check - document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ - type: 'rc-adapter-trigger-call-logger-match', - sessionIds: [exsitingLog.callLogs[0].sessionId] - }, '*'); } + } catch (error) { + console.error('Error processing call:', c.sessionId, error); } } + if (!hasMore) { const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); clearInterval(retroAutoCallLogIntervalId); dismissNotification({ notificationId: retroAutoCallLogNotificationId }); showNotification({ level: 'success', message: `Historical call syncing finished. ${retroLoggedCount} call(s) synced.`, ttl: 5000 }); } + } catch (error) { + console.error('Error fetching calls:', error); + const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); + clearInterval(retroAutoCallLogIntervalId); + dismissNotification({ notificationId: retroAutoCallLogNotificationId }); + showNotification({ level: 'error', message: 'Failed to fetch historical calls for sync.', ttl: 5000 }); } } else { From 5879f7c39b14100829c2a241b0cbed3a60aff7ef Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 28 Jul 2025 18:44:06 +0530 Subject: [PATCH 07/19] Enum name --- .../admin/managedSettings/activityLoggingSettingPage.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index 21f765e..e760370 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -84,6 +84,10 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u enum: [ 'popupLogPageAfterSMS', 'popupLogPageAfterCall' + ], + enumNames: [ + 'SMS is sent', + 'Call ends' ] }, uniqueItems: true From b89c4ac9f9b1774fd866e70ed9029c68cfe36fad Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 28 Jul 2025 19:17:52 +0530 Subject: [PATCH 08/19] remove console log --- src/core/user.js | 7 +------ src/popup.js | 31 ------------------------------- src/service/embeddableServices.js | 12 ------------ src/service/logService.js | 1 - 4 files changed, 1 insertion(+), 50 deletions(-) diff --git a/src/core/user.js b/src/core/user.js index 8c7144d..810a26a 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -57,7 +57,6 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false try { userSettings = await getUserSettingsOnline({ serverUrl: manifest.serverUrl, rcAccessToken }); } catch (e) { - console.log('Failed to get user settings from server, trying local storage:', e); const { userSettings: localUserSettings } = await chrome.storage.local.get({ userSettings: {} }); userSettings = localUserSettings; } @@ -67,18 +66,14 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false userSettings = {}; } if (changedSettings) { - console.log('Applying changed settings:', changedSettings); for (const k of Object.keys(changedSettings)) { if (userSettings[k] === undefined) { userSettings[k] = changedSettings[k]; - console.log(`Setting ${k} to new value:`, changedSettings[k]); } else { userSettings[k].value = changedSettings[k].value; - console.log(`Updating ${k} value from ${userSettings[k].value} to ${changedSettings[k].value}`); } } - console.log('Final user settings after changes:', userSettings); } await chrome.storage.local.set({ userSettings }); @@ -89,7 +84,7 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false userSettings = uploadedSettings; } } catch (e) { - console.log('Failed to upload user settings to server, using local settings:', e); + console.log('Failed to upload user settings to server, using local settings:'); // Continue with local settings if upload fails } document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ diff --git a/src/popup.js b/src/popup.js index 74f62ce..5bb1f61 100644 --- a/src/popup.js +++ b/src/popup.js @@ -2077,20 +2077,15 @@ window.addEventListener('message', async (e) => { break; case '/settings': const changedSettings = {}; - console.log('Raw settings data from widget:', data.body.settings); for (const s of data.body.settings) { - console.log('Processing setting section:', s); if (s.items !== undefined) { for (const i of s.items) { - console.log('Processing setting item:', i); if (i?.items !== undefined) { for (const ii of i.items) { - console.log('Processing nested setting item:', ii); // Handle checkbox options for activity logging at nested level if (ii.id === 'activityLoggingOptions') { // Convert array of selected options to individual boolean settings const selectedOptions = ii.value || []; - console.log('Activity logging options selected:', selectedOptions); changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; @@ -2103,13 +2098,11 @@ window.addEventListener('message', async (e) => { } else if (ii.id === 'autoOpenOptions') { // Convert array of selected options to individual boolean settings const selectedOptions = ii.value || []; - console.log('Auto-open options selected:', selectedOptions); changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; } else if (ii.id === 'callLogDetails') { // Convert array of selected options to individual boolean settings const selectedOptions = ii.value || []; - console.log('Call log details options selected:', selectedOptions); changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; @@ -2129,7 +2122,6 @@ window.addEventListener('message', async (e) => { if (i.id === 'activityLoggingOptions') { // Convert array of selected options to individual boolean settings const selectedOptions = i.value || []; - console.log('Activity logging options selected:', selectedOptions); changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; @@ -2138,17 +2130,14 @@ window.addEventListener('message', async (e) => { changedSettings.autoLogInboundFax = { value: selectedOptions.includes('autoLogInboundFax') }; changedSettings.autoLogOutboundFax = { value: selectedOptions.includes('autoLogOutboundFax') }; changedSettings.oneTimeLog = { value: selectedOptions.includes('oneTimeLog') }; - console.log('Activity logging changed settings:', changedSettings); } else if (i.id === 'autoOpenOptions') { // Convert array of selected options to individual boolean settings const selectedOptions = i.value || []; - console.log('Auto-open options selected:', selectedOptions); changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; } else if (i.id === 'callLogDetails') { // Convert array of selected options to individual boolean settings const selectedOptions = i.value || []; - console.log('Call log details options selected:', selectedOptions); changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; @@ -2208,7 +2197,6 @@ window.addEventListener('message', async (e) => { // Handle nested form data structure properly const formData = data.body.button.formData; - console.log('Admin settings form data received:', formData); // For activity logging page, handle both flat and nested structures if (data.body.button.id === 'activityLoggingSettingPage') { @@ -2251,7 +2239,6 @@ window.addEventListener('message', async (e) => { customizable: setting.customizable ?? true, value: selectedOptions.includes('oneTimeLog') }; - console.log('Saved activity logging options:', selectedOptions); } else if (settingKey === 'autoOpenOptions') { // Handle auto-open checkbox array const selectedOptions = setting.value || []; @@ -2263,16 +2250,9 @@ window.addEventListener('message', async (e) => { customizable: setting.customizable ?? true, value: selectedOptions.includes('popupLogPageAfterCall') }; - console.log('Saved auto-open options:', selectedOptions); } else if (Array.isArray(setting.value) && setting.customizable !== undefined) { // Handle custom activity logging settings (like call log details) const selectedOptions = setting.value || []; - console.log(`Saving custom activity logging setting: ${settingKey}`, { - selectedOptions, - customizable: setting.customizable, - settingObject: setting - }); - // Find the custom setting definition to get the options let customSettingDef = null; if (platform?.settings) { @@ -2285,7 +2265,6 @@ window.addEventListener('message', async (e) => { } if (customSettingDef && customSettingDef.options) { - console.log(`Found custom setting definition for ${settingKey}:`, customSettingDef); // Set each individual option as a separate admin setting for (const option of customSettingDef.options) { const individualSetting = { @@ -2293,19 +2272,15 @@ window.addEventListener('message', async (e) => { value: selectedOptions.includes(option.id) }; adminSettings.userSettings[option.id] = individualSetting; - console.log(`Set admin setting ${option.id}:`, individualSetting); } - console.log(`Processed ${customSettingDef.options.length} options for ${settingKey}`); } else { console.warn(`No custom setting definition found for ${settingKey}`); } } else if (setting.customizable !== undefined || setting.value !== undefined) { // This is a direct setting - console.log(`Saving admin setting: ${settingKey}`, setting); adminSettings.userSettings[settingKey] = setting; } else if (settingKey === 'logSyncFrequencySection' && setting.logSyncFrequency) { // Handle the nested logSyncFrequency setting - console.log(`Saving admin setting: logSyncFrequency`, setting.logSyncFrequency); adminSettings.userSettings.logSyncFrequency = setting.logSyncFrequency; } } @@ -2320,24 +2295,18 @@ window.addEventListener('message', async (e) => { const setting = section[settingKey]; if (setting && typeof setting === 'object' && (setting.customizable !== undefined || setting.value !== undefined)) { // This is an individual setting, save it directly - console.log(`Saving admin setting: ${settingKey}`, setting); adminSettings.userSettings[settingKey] = setting; } } } } } - - console.log('Final admin settings to save:', adminSettings); await chrome.storage.local.set({ adminSettings }); await adminCore.uploadAdminSettings({ serverUrl: manifest.serverUrl, adminSettings }); // Add delay to avoid race condition - wait for server to process admin settings await new Promise(resolve => setTimeout(resolve, 1000)); - console.log('Admin settings uploaded, refreshing user settings after delay...'); - userSettings = await userCore.refreshUserSettings({ isAfterAdminChanges: true }); - // Refresh the service manifest to reflect admin changes in user settings const serviceManifest = await embeddableServices.getServiceManifest(); document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({ diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index ef76ef9..5fb1f8f 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -529,15 +529,6 @@ async function getServiceManifest() { readOnlyReason = optionSetting.readOnlyReason || 'This setting is managed by admin'; } } - console.log(`User-side ${cs.id} checkbox values:`, { - finalValue, - isReadOnly, - readOnlyReason, - optionDetails: filteredOptions.map(opt => ({ - id: opt.id, - setting: userCore.getCustomSetting(userSettings, opt.id, false) - })) - }); } else { // Single value setting const currentValue = userCore.getCustomSetting(userSettings, cs.id, cs.defaultValue).value; @@ -656,7 +647,6 @@ async function getServiceManifest() { if (cs.type && !cs.items) { // Add each processed item directly to the target section targetSection.items.push(...items); - console.log(`Added ${items.length} direct setting(s) from ${cs.id} to section ${cs.section}`); } else { // For container settings, add as a subsection const subsection = { @@ -666,10 +656,8 @@ async function getServiceManifest() { items }; targetSection.items.push(subsection); - console.log(`Added custom setting subsection ${cs.id} to section ${cs.section}`); } } else { - console.warn(`Target section ${cs.section} not found, adding as top-level group`); // Fallback: add as top-level group if section not found const group = { id: cs.id, diff --git a/src/service/logService.js b/src/service/logService.js index 611b263..0430cbd 100644 --- a/src/service/logService.js +++ b/src/service/logService.js @@ -141,7 +141,6 @@ async function retroAutoCallLog({ showNotification({ level: 'success', message: `Historical call syncing finished. ${retroLoggedCount} call(s) synced.`, ttl: 5000 }); } } catch (error) { - console.error('Error fetching calls:', error); const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); clearInterval(retroAutoCallLogIntervalId); dismissNotification({ notificationId: retroAutoCallLogNotificationId }); From 6b110d4f9e456c32dd18d7bd5fd246c957801b63 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 28 Jul 2025 19:19:18 +0530 Subject: [PATCH 09/19] remove console log --- .../managedSettings/activityLoggingSettingPage.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index e760370..68d8789 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -164,7 +164,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u if (crmManifest?.settings) { for (const customSetting of crmManifest.settings) { if (customSetting.section === 'activityLogging') { - console.log('Adding custom setting to activity logging admin page:', customSetting.id); // Handle different types of custom settings switch (customSetting.type) { @@ -223,16 +222,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u customizable: isCustomizable, value: currentSelectedOptions }; - - console.log(`Admin page loading - ${customSetting.id}:`, { - customizable: isCustomizable, - selectedOptions: currentSelectedOptions, - individualSettings: filteredOptions.map(opt => ({ - id: opt.id, - value: adminUserSettings?.[opt.id]?.value, - customizable: adminUserSettings?.[opt.id]?.customizable - })) - }); break; case 'boolean': From 1052a13d97b49258eef41e8c4396408003db5a9d Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Wed, 30 Jul 2025 18:34:51 +0530 Subject: [PATCH 10/19] Review Change and improvements --- .../activityLoggingSettingPage.js | 2 +- .../managedSettings/customSettingsPage.js | 6 +- src/core/user.js | 2 +- src/popup.js | 63 +++++++++++++++++-- src/service/embeddableServices.js | 2 +- src/service/logService.js | 12 +++- 6 files changed, 73 insertions(+), 14 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index 68d8789..7e5aa33 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -48,7 +48,7 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u }, logSyncFrequencySection: { type: 'object', - title: 'Log sync frequency', + title: 'Call Log Sync Frequency', properties: { logSyncFrequency: { type: 'object', diff --git a/src/components/admin/managedSettings/customSettingsPage.js b/src/components/admin/managedSettings/customSettingsPage.js index 6f73c62..7c3bc6a 100644 --- a/src/components/admin/managedSettings/customSettingsPage.js +++ b/src/components/admin/managedSettings/customSettingsPage.js @@ -23,9 +23,9 @@ function getCustomSettingsPageRender({ crmManifest, adminUserSettings, userSetti } for (const section of crmManifest.settings) { // Skip sections that should appear in Activity logging admin page - if (section.section === 'activityLogging') { - continue; - } + // if (section.section === 'activityLogging') { + // continue; + // } page.schema.properties[section.id] = { type: 'string', diff --git a/src/core/user.js b/src/core/user.js index 810a26a..7bed749 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -97,7 +97,7 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false recordings: getShowRecordingsTabSetting(userSettings).value, contacts: getShowContactsTabSetting(userSettings).value }, '*'); - const autoLogMessagesGroupTrigger = (userSettings?.autoLogSMS?.value ?? false) || (userSettings?.autoLogInboundFax?.value ?? false) || (userSettings?.autoLogOutboundFax?.value ?? false); + const autoLogMessagesGroupTrigger = (userSettings?.autoLogSMS?.value ?? false) || (userSettings?.autoLogInboundFax?.value ?? false) || (userSettings?.autoLogOutboundFax?.value ?? false) || (userSettings?.autoLogVoicemails?.value ?? false); const autoLogCallsGroupTrigger = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || (userSettings?.autoLogMissedIncoming?.value ?? false) || (userSettings?.autoLogOutgoing?.value ?? false); RCAdapter.setAutoLog({ call: autoLogCallsGroupTrigger || (userSettings.autoLogCall?.value ?? false), message: autoLogMessagesGroupTrigger }) if (!isAvoidForceChange) { diff --git a/src/popup.js b/src/popup.js index 5bb1f61..dfcaa45 100644 --- a/src/popup.js +++ b/src/popup.js @@ -78,6 +78,52 @@ let platform = null; let hasOngoingCall = false; let lastUserSettingSyncDate = new Date(); +// Helper function to determine if a call should be auto-logged based on direction and result +function shouldAutoLogCall(call, userSettings) { + let shouldAutoLog = false; + + if (call.direction === 'Inbound') { + if (call.result === 'Answered') { + shouldAutoLog = userSettings?.autoLogAnsweredIncoming?.value ?? false; + } else if (call.result === 'Missed') { + shouldAutoLog = userSettings?.autoLogMissedIncoming?.value ?? false; + } + } else if (call.direction === 'Outbound') { + shouldAutoLog = userSettings?.autoLogOutgoing?.value ?? false; + } + + // Fallback to legacy setting for backward compatibility + if (!shouldAutoLog) { + shouldAutoLog = userSettings?.autoLogCall?.value ?? false; + } + + return shouldAutoLog; +} + +// Helper function for presence update auto-logging (maps presence results to call results) +function shouldAutoLogCallFromPresence(call, userSettings) { + let shouldAutoLog = false; + + if (call.direction === 'Inbound') { + // For inbound calls: CallConnected = answered, Disconnected = missed + if (call.result === 'CallConnected') { + shouldAutoLog = userSettings?.autoLogAnsweredIncoming?.value ?? false; + } else if (call.result === 'Disconnected') { + shouldAutoLog = userSettings?.autoLogMissedIncoming?.value ?? false; + } + } else if (call.direction === 'Outbound') { + // For outbound calls: both CallConnected and Disconnected mean call was made + shouldAutoLog = userSettings?.autoLogOutgoing?.value ?? false; + } + + // Fallback to legacy setting for backward compatibility + if (!shouldAutoLog) { + shouldAutoLog = userSettings?.autoLogCall?.value ?? false; + } + + return shouldAutoLog; +} + async function restartSyncInterval() { // Clear existing interval const { retroAutoCallLogIntervalId } = await chrome.storage.local.get({ retroAutoCallLogIntervalId: null }); @@ -1357,16 +1403,23 @@ window.addEventListener('message', async (e) => { }); // Translate: If no existing call log, create condition here to navigate to auto log - if (userCore.getAutoLogCallSetting(userSettings).value && data.body.triggerType === 'callLogSync' && !(existingCalls?.length > 0 && existingCalls[0]?.matched)) { - data.body.triggerType = 'createLog'; - isAutoLog = true; + if (data.body.triggerType === 'callLogSync' && !(existingCalls?.length > 0 && existingCalls[0]?.matched)) { + if (shouldAutoLogCall(data.body.call, userSettings)) { + data.body.triggerType = 'createLog'; + isAutoLog = true; + } } // Translate: Right after call, once presence update to Disconnect, auto log the call if (data.body.triggerType === 'presenceUpdate') { if (data.body.call.result === 'Disconnected' || data.body.call.result === 'CallConnected') { - data.body.triggerType = 'createLog'; - isAutoLog = true; + if (shouldAutoLogCallFromPresence(data.body.call, userSettings)) { + data.body.triggerType = 'createLog'; + isAutoLog = true; + } else { + responseMessage(data.requestId, { data: 'ok' }); + break; + } } else { responseMessage(data.requestId, { data: 'ok' }); diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 5fb1f8f..2db3b47 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -143,7 +143,7 @@ async function getServiceManifest() { { id: "logSyncFrequency", type: "option", - name: 'Log sync frequency', + name: 'Call Log Sync Frequency', helper: `Specify how often you'd like to check for any unlogged calls.`, options: [ { diff --git a/src/service/logService.js b/src/service/logService.js index 0430cbd..ff6bdaa 100644 --- a/src/service/logService.js +++ b/src/service/logService.js @@ -5,6 +5,8 @@ import contactCore from '../core/contact'; import { showNotification, dismissNotification, isObjectEmpty, getRcAccessToken } from '../lib/util'; import { getLogConflictInfo } from '../lib/logUtil'; + + async function retroAutoCallLog({ manifest, platformName, @@ -35,9 +37,13 @@ async function retroAutoCallLog({ try { const { calls, hasMore } = await RCAdapter.getUnloggedCalls(itemsPerPage, pageNumber); - const isAutoLog = userCore.getAutoLogCallSetting(userSettings, isAdmin).value; + // Check if any individual auto-logging setting is enabled + const hasAnyAutoLogEnabled = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || + (userSettings?.autoLogMissedIncoming?.value ?? false) || + (userSettings?.autoLogOutgoing?.value ?? false) || + (userSettings?.autoLogCall?.value ?? false); - if (!isAutoLog) { + if (!hasAnyAutoLogEnabled) { return; } @@ -73,7 +79,7 @@ async function retroAutoCallLog({ const { hasConflict, autoSelectAdditionalSubmission } = await getLogConflictInfo({ platform, - isAutoLog, + isAutoLog: true, contactInfo: callMatchedContact, logType: 'callLog', direction: c.direction, From 78da9b3fed9747f01e9d945aea5ab205979c2fd7 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 1 Aug 2025 02:44:32 +0530 Subject: [PATCH 11/19] Extract One-time call logging out --- .../activityLoggingSettingPage.js | 29 +++++++++++++++---- src/service/embeddableServices.js | 25 ++++++++-------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index 7e5aa33..1bd39bc 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -21,7 +21,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u items: { type: 'string', enum: [ - 'oneTimeLog', 'autoLogAnsweredIncoming', 'autoLogMissedIncoming', 'autoLogOutgoing', @@ -32,7 +31,6 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u ], enumNames: [ - 'One-time call logging', 'Answered incoming calls', 'Missed incoming calls', 'Outgoing calls', @@ -68,6 +66,20 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u } } }, + oneTimeLog: { + type: 'object', + title: 'One-time call logging', + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'boolean', + title: 'Enable one-time call logging functionality' + } + } + }, autoOpenOptions: { type: 'object', title: 'Auto-open logging page after:', @@ -109,6 +121,9 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u logSyncFrequencySection: { "ui:collapsible": true, }, + oneTimeLog: { + "ui:collapsible": true, + }, autoOpenOptions: { "ui:collapsible": true, value: { @@ -130,8 +145,7 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u adminUserSettings?.autoLogVoicemails?.customizable ?? adminUserSettings?.autoLogSMS?.customizable ?? adminUserSettings?.autoLogInboundFax?.customizable ?? - adminUserSettings?.autoLogOutboundFax?.customizable ?? - adminUserSettings?.oneTimeLog?.customizable ?? true, + adminUserSettings?.autoLogOutboundFax?.customizable ?? true, value: [ ...((adminUserSettings?.autoLogAnsweredIncoming?.value ?? false) ? ['autoLogAnsweredIncoming'] : []), ...((adminUserSettings?.autoLogMissedIncoming?.value ?? false) ? ['autoLogMissedIncoming'] : []), @@ -139,8 +153,7 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u ...((adminUserSettings?.autoLogVoicemails?.value ?? false) ? ['autoLogVoicemails'] : []), ...((adminUserSettings?.autoLogSMS?.value ?? false) ? ['autoLogSMS'] : []), ...((adminUserSettings?.autoLogInboundFax?.value ?? false) ? ['autoLogInboundFax'] : []), - ...((adminUserSettings?.autoLogOutboundFax?.value ?? false) ? ['autoLogOutboundFax'] : []), - ...((adminUserSettings?.oneTimeLog?.value ?? false) ? ['oneTimeLog'] : []) + ...((adminUserSettings?.autoLogOutboundFax?.value ?? false) ? ['autoLogOutboundFax'] : []) ] }, logSyncFrequencySection: { @@ -149,6 +162,10 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u value: adminUserSettings?.logSyncFrequency?.value ?? '10min' } }, + oneTimeLog: { + customizable: adminUserSettings?.oneTimeLog?.customizable ?? true, + value: adminUserSettings?.oneTimeLog?.value ?? false + }, autoOpenOptions: { customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 2db3b47..8538a71 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -65,10 +65,6 @@ async function getServiceManifest() { checkbox: true, helper: `Select the types of communications you'd like automatically logged to your CRM.`, options: [ - { - id: 'oneTimeLog', - name: 'One-time call logging' - }, { id: 'autoLogAnsweredIncoming', name: 'Answered incoming calls' @@ -107,8 +103,7 @@ async function getServiceManifest() { ...(userCore.getAutoLogVoicemailsSetting(userSettings).value ? ['autoLogVoicemails'] : []), ...(userCore.getAutoLogSMSSetting(userSettings).value ? ['autoLogSMS'] : []), ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), - ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []), - ...(userCore.getOneTimeLogSetting(userSettings).value ? ['oneTimeLog'] : []) + ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []) ]; console.log('Service manifest activity logging values:', activityLoggingValues); console.log('User settings for activity logging:', { @@ -118,8 +113,7 @@ async function getServiceManifest() { autoLogVoicemails: userCore.getAutoLogVoicemailsSetting(userSettings), autoLogSMS: userCore.getAutoLogSMSSetting(userSettings), autoLogInboundFax: userCore.getAutoLogInboundFaxSetting(userSettings), - autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings), - oneTimeLog: userCore.getOneTimeLogSetting(userSettings) + autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings) }); return activityLoggingValues; })(), @@ -129,16 +123,14 @@ async function getServiceManifest() { userCore.getAutoLogVoicemailsSetting(userSettings).readOnly || userCore.getAutoLogSMSSetting(userSettings).readOnly || userCore.getAutoLogInboundFaxSetting(userSettings).readOnly || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly || - userCore.getOneTimeLogSetting(userSettings).readOnly, + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly, readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason || userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason || userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason || userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason || userCore.getAutoLogSMSSetting(userSettings).readOnlyReason || userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason || - userCore.getOneTimeLogSetting(userSettings).readOnlyReason + userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason }, { id: "logSyncFrequency", @@ -175,6 +167,15 @@ async function getServiceManifest() { readOnly: userCore.getLogSyncFrequencySetting(userSettings).readOnly, readOnlyReason: userCore.getLogSyncFrequencySetting(userSettings).readOnlyReason, }, + { + id: 'oneTimeLog', + type: 'boolean', + name: 'One-time call logging', + description: 'Enable one-time call logging functionality.', + value: userCore.getOneTimeLogSetting(userSettings).value, + readOnly: userCore.getOneTimeLogSetting(userSettings).readOnly, + readOnlyReason: userCore.getOneTimeLogSetting(userSettings).readOnlyReason + }, { id: 'autoOpenOptions', type: 'option', From 9e78df9da10a778fd7bb0d4733e47f5b76a0f895 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Fri, 1 Aug 2025 09:01:29 +0530 Subject: [PATCH 12/19] remove console log --- src/service/embeddableServices.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index 8538a71..abf6b3f 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -105,16 +105,6 @@ async function getServiceManifest() { ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []) ]; - console.log('Service manifest activity logging values:', activityLoggingValues); - console.log('User settings for activity logging:', { - autoLogAnsweredIncoming: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin), - autoLogMissedIncoming: userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin), - autoLogOutgoing: userCore.getAutoLogOutgoingSetting(userSettings, isAdmin), - autoLogVoicemails: userCore.getAutoLogVoicemailsSetting(userSettings), - autoLogSMS: userCore.getAutoLogSMSSetting(userSettings), - autoLogInboundFax: userCore.getAutoLogInboundFaxSetting(userSettings), - autoLogOutboundFax: userCore.getAutoLogOutboundFaxSetting(userSettings) - }); return activityLoggingValues; })(), readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly || @@ -171,7 +161,7 @@ async function getServiceManifest() { id: 'oneTimeLog', type: 'boolean', name: 'One-time call logging', - description: 'Enable one-time call logging functionality.', + description: 'Delays logging until full call details are available.', value: userCore.getOneTimeLogSetting(userSettings).value, readOnly: userCore.getOneTimeLogSetting(userSettings).readOnly, readOnlyReason: userCore.getOneTimeLogSetting(userSettings).readOnlyReason From 1a95d45f96e2414c8b41c8db969d020366ae1fee Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Mon, 4 Aug 2025 18:02:46 +0530 Subject: [PATCH 13/19] Remove autoCallLog --- src/core/user.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/core/user.js b/src/core/user.js index 7bed749..d64ab8a 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -65,6 +65,27 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false if (!userSettings) { userSettings = {}; } + + // TEMP: to be deleted after this version 1.6.1 + // Backward compatibility - migrate old autoLogCall setting to new individual settings + // Only run for exactly version 1.6.1 + const currentVersionNumbers = manifest.version.split('.').map(v => parseInt(v)); + const targetVersionNumbers = [1, 6, 1]; // 1.6.1 + const isExactVersion = ( + currentVersionNumbers[0] === targetVersionNumbers[0] && + currentVersionNumbers[1] === targetVersionNumbers[1] && + currentVersionNumbers[2] === targetVersionNumbers[2] + ); + + + if (isExactVersion && userSettings.autoLogCall && userSettings.autoLogCall.value === true) { + // One-time translation: Set all three new settings to true + userSettings.autoLogAnsweredIncoming = { customizable: true, value: true }; + userSettings.autoLogMissedIncoming = { customizable: true, value: true }; + userSettings.autoLogOutgoing = { customizable: true, value: true }; + // Delete the old autoLogCall setting + delete userSettings.autoLogCall; + } if (changedSettings) { for (const k of Object.keys(changedSettings)) { if (userSettings[k] === undefined) { From 954ffb8f701e1a7308af0395bf6652a0136119ac Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Tue, 5 Aug 2025 13:21:46 +0530 Subject: [PATCH 14/19] Review Changes --- .../managedSettings/customSettingsPage.js | 5 -- src/core/user.js | 48 +------------------ 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/components/admin/managedSettings/customSettingsPage.js b/src/components/admin/managedSettings/customSettingsPage.js index 7c3bc6a..054d87b 100644 --- a/src/components/admin/managedSettings/customSettingsPage.js +++ b/src/components/admin/managedSettings/customSettingsPage.js @@ -22,11 +22,6 @@ function getCustomSettingsPageRender({ crmManifest, adminUserSettings, userSetti } } for (const section of crmManifest.settings) { - // Skip sections that should appear in Activity logging admin page - // if (section.section === 'activityLogging') { - // continue; - // } - page.schema.properties[section.id] = { type: 'string', description: section.name diff --git a/src/core/user.js b/src/core/user.js index d64ab8a..15433e5 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -68,17 +68,7 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false // TEMP: to be deleted after this version 1.6.1 // Backward compatibility - migrate old autoLogCall setting to new individual settings - // Only run for exactly version 1.6.1 - const currentVersionNumbers = manifest.version.split('.').map(v => parseInt(v)); - const targetVersionNumbers = [1, 6, 1]; // 1.6.1 - const isExactVersion = ( - currentVersionNumbers[0] === targetVersionNumbers[0] && - currentVersionNumbers[1] === targetVersionNumbers[1] && - currentVersionNumbers[2] === targetVersionNumbers[2] - ); - - - if (isExactVersion && userSettings.autoLogCall && userSettings.autoLogCall.value === true) { + if (userSettings.autoLogCall && userSettings.autoLogCall.value === true) { // One-time translation: Set all three new settings to true userSettings.autoLogAnsweredIncoming = { customizable: true, value: true }; userSettings.autoLogMissedIncoming = { customizable: true, value: true }; @@ -88,7 +78,7 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false } if (changedSettings) { for (const k of Object.keys(changedSettings)) { - if (userSettings[k] === undefined) { + if (userSettings[k] === undefined || !userSettings[k].value) { userSettings[k] = changedSettings[k]; } else { @@ -164,39 +154,7 @@ async function updateSSCLToken({ serverUrl, platform, token }) { } } -function getAutoLogCallSetting(userSettings, isAdmin) { - const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; - if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { - return { - value: false, - readOnly: true, - readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', - warning: 'Unavailable while server side call logging enabled' - } - } - - // Check if any of the individual auto logging settings are enabled - const autoLogAnsweredIncoming = userSettings?.autoLogAnsweredIncoming?.value ?? false; - const autoLogMissedIncoming = userSettings?.autoLogMissedIncoming?.value ?? false; - const autoLogOutgoing = userSettings?.autoLogOutgoing?.value ?? false; - const legacyAutoLogCall = userSettings?.autoLogCall?.value ?? false; // Fallback for backwards compatibility - - const isAnyAutoLogEnabled = autoLogAnsweredIncoming || autoLogMissedIncoming || autoLogOutgoing || legacyAutoLogCall; - // Check if any setting is read-only (managed by admin) - const isReadOnly = (userSettings?.autoLogAnsweredIncoming?.customizable === false) || - (userSettings?.autoLogMissedIncoming?.customizable === false) || - (userSettings?.autoLogOutgoing?.customizable === false) || - (userSettings?.autoLogCall?.customizable === false); - - const readOnlyReason = isReadOnly ? 'This setting is managed by admin' : ''; - - return { - value: isAnyAutoLogEnabled, - readOnly: isReadOnly, - readOnlyReason: readOnlyReason - } -} function getAutoLogSMSSetting(userSettings) { return { @@ -499,8 +457,6 @@ exports.getUserSettingsOnline = getUserSettingsOnline; exports.uploadUserSettings = uploadUserSettings; exports.refreshUserSettings = refreshUserSettings; exports.updateSSCLToken = updateSSCLToken; - -exports.getAutoLogCallSetting = getAutoLogCallSetting; exports.getAutoLogSMSSetting = getAutoLogSMSSetting; exports.getAutoLogInboundFaxSetting = getAutoLogInboundFaxSetting; exports.getAutoLogOutboundFaxSetting = getAutoLogOutboundFaxSetting; From 0a74af326ca3fd0bee2d2c99000a3cede9dae30c Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Tue, 5 Aug 2025 20:36:56 +0530 Subject: [PATCH 15/19] Review Changes --- .../activityLoggingSettingPage.js | 42 +---- src/core/user.js | 110 ++++++++---- src/popup.js | 162 ++++-------------- src/service/embeddableServices.js | 6 +- src/service/logService.js | 7 +- 5 files changed, 125 insertions(+), 202 deletions(-) diff --git a/src/components/admin/managedSettings/activityLoggingSettingPage.js b/src/components/admin/managedSettings/activityLoggingSettingPage.js index 1bd39bc..1010e05 100644 --- a/src/components/admin/managedSettings/activityLoggingSettingPage.js +++ b/src/components/admin/managedSettings/activityLoggingSettingPage.js @@ -139,22 +139,8 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u }, formData: { activityLoggingOptions: { - customizable: adminUserSettings?.autoLogAnsweredIncoming?.customizable ?? - adminUserSettings?.autoLogMissedIncoming?.customizable ?? - adminUserSettings?.autoLogOutgoing?.customizable ?? - adminUserSettings?.autoLogVoicemails?.customizable ?? - adminUserSettings?.autoLogSMS?.customizable ?? - adminUserSettings?.autoLogInboundFax?.customizable ?? - adminUserSettings?.autoLogOutboundFax?.customizable ?? true, - value: [ - ...((adminUserSettings?.autoLogAnsweredIncoming?.value ?? false) ? ['autoLogAnsweredIncoming'] : []), - ...((adminUserSettings?.autoLogMissedIncoming?.value ?? false) ? ['autoLogMissedIncoming'] : []), - ...((adminUserSettings?.autoLogOutgoing?.value ?? false) ? ['autoLogOutgoing'] : []), - ...((adminUserSettings?.autoLogVoicemails?.value ?? false) ? ['autoLogVoicemails'] : []), - ...((adminUserSettings?.autoLogSMS?.value ?? false) ? ['autoLogSMS'] : []), - ...((adminUserSettings?.autoLogInboundFax?.value ?? false) ? ['autoLogInboundFax'] : []), - ...((adminUserSettings?.autoLogOutboundFax?.value ?? false) ? ['autoLogOutboundFax'] : []) - ] + customizable: adminUserSettings?.activityLoggingOptions?.customizable ?? true, + value: adminUserSettings?.activityLoggingOptions?.value ?? [] }, logSyncFrequencySection: { logSyncFrequency: { @@ -167,12 +153,8 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u value: adminUserSettings?.oneTimeLog?.value ?? false }, autoOpenOptions: { - customizable: adminUserSettings?.popupLogPageAfterSMS?.customizable ?? - adminUserSettings?.popupLogPageAfterCall?.customizable ?? true, - value: [ - ...((adminUserSettings?.popupLogPageAfterSMS?.value ?? false) ? ['popupLogPageAfterSMS'] : []), - ...((adminUserSettings?.popupLogPageAfterCall?.value ?? false) ? ['popupLogPageAfterCall'] : []) - ] + customizable: adminUserSettings?.autoOpenOptions?.customizable ?? true, + value: adminUserSettings?.autoOpenOptions?.value ?? [] } } }; @@ -221,19 +203,9 @@ function getActivityLoggingSettingPageRender({ adminUserSettings, crmManifest, u } }; - // Determine current value based on individual setting values - const currentSelectedOptions = []; - let isCustomizable = true; - - for (const option of filteredOptions) { - if (adminUserSettings?.[option.id]?.value) { - currentSelectedOptions.push(option.id); - } - // If any individual option is not customizable, the whole section becomes non-customizable - if (adminUserSettings?.[option.id]?.customizable === false) { - isCustomizable = false; - } - } + // Get current value from array-based setting + const currentSelectedOptions = adminUserSettings?.[customSetting.id]?.value ?? []; + let isCustomizable = adminUserSettings?.[customSetting.id]?.customizable ?? true; page.formData[customSetting.id] = { customizable: isCustomizable, diff --git a/src/core/user.js b/src/core/user.js index 15433e5..f0d0694 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -76,6 +76,8 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false // Delete the old autoLogCall setting delete userSettings.autoLogCall; } + + if (changedSettings) { for (const k of Object.keys(changedSettings)) { if (userSettings[k] === undefined || !userSettings[k].value) { @@ -108,8 +110,9 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false recordings: getShowRecordingsTabSetting(userSettings).value, contacts: getShowContactsTabSetting(userSettings).value }, '*'); - const autoLogMessagesGroupTrigger = (userSettings?.autoLogSMS?.value ?? false) || (userSettings?.autoLogInboundFax?.value ?? false) || (userSettings?.autoLogOutboundFax?.value ?? false) || (userSettings?.autoLogVoicemails?.value ?? false); - const autoLogCallsGroupTrigger = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || (userSettings?.autoLogMissedIncoming?.value ?? false) || (userSettings?.autoLogOutgoing?.value ?? false); + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const autoLogMessagesGroupTrigger = activityLoggingOptions.includes('autoLogSMS') || activityLoggingOptions.includes('autoLogInboundFax') || activityLoggingOptions.includes('autoLogOutboundFax') || activityLoggingOptions.includes('autoLogVoicemails'); + const autoLogCallsGroupTrigger = activityLoggingOptions.includes('autoLogAnsweredIncoming') || activityLoggingOptions.includes('autoLogMissedIncoming') || activityLoggingOptions.includes('autoLogOutgoing'); RCAdapter.setAutoLog({ call: autoLogCallsGroupTrigger || (userSettings.autoLogCall?.value ?? false), message: autoLogMessagesGroupTrigger }) if (!isAvoidForceChange) { const showAiAssistantWidgetSetting = getShowAiAssistantWidgetSetting(userSettings); @@ -157,26 +160,35 @@ async function updateSSCLToken({ serverUrl, platform, token }) { function getAutoLogSMSSetting(userSettings) { + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogSMS'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogSMS?.value ?? false, - readOnly: userSettings?.autoLogSMS?.customizable === undefined ? false : !userSettings?.autoLogSMS?.customizable, - readOnlyReason: !userSettings?.autoLogSMS?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } function getAutoLogInboundFaxSetting(userSettings) { + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogInboundFax'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogInboundFax?.value ?? false, - readOnly: userSettings?.autoLogInboundFax?.customizable === undefined ? false : !userSettings?.autoLogInboundFax?.customizable, - readOnlyReason: !userSettings?.autoLogInboundFax?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } function getAutoLogOutboundFaxSetting(userSettings) { + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogOutboundFax'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogOutboundFax?.value ?? false, - readOnly: userSettings?.autoLogOutboundFax?.customizable === undefined ? false : !userSettings?.autoLogOutboundFax?.customizable, - readOnlyReason: !userSettings?.autoLogOutboundFax?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } @@ -190,10 +202,13 @@ function getAutoLogAnsweredIncomingSetting(userSettings, isAdmin) { warning: 'Unavailable while server side call logging enabled' } } + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogAnsweredIncoming'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogAnsweredIncoming?.value ?? false, - readOnly: userSettings?.autoLogAnsweredIncoming?.customizable === undefined ? false : !userSettings?.autoLogAnsweredIncoming?.customizable, - readOnlyReason: !userSettings?.autoLogAnsweredIncoming?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } @@ -207,10 +222,13 @@ function getAutoLogMissedIncomingSetting(userSettings, isAdmin) { warning: 'Unavailable while server side call logging enabled' } } + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogMissedIncoming'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogMissedIncoming?.value ?? false, - readOnly: userSettings?.autoLogMissedIncoming?.customizable === undefined ? false : !userSettings?.autoLogMissedIncoming?.customizable, - readOnlyReason: !userSettings?.autoLogMissedIncoming?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } @@ -224,18 +242,24 @@ function getAutoLogOutgoingSetting(userSettings, isAdmin) { warning: 'Unavailable while server side call logging enabled' } } + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogOutgoing'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogOutgoing?.value ?? false, - readOnly: userSettings?.autoLogOutgoing?.customizable === undefined ? false : !userSettings?.autoLogOutgoing?.customizable, - readOnlyReason: !userSettings?.autoLogOutgoing?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } function getAutoLogVoicemailsSetting(userSettings) { + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const value = activityLoggingOptions.includes('autoLogVoicemails'); + const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: userSettings?.autoLogVoicemails?.value ?? false, - readOnly: userSettings?.autoLogVoicemails?.customizable === undefined ? false : !userSettings?.autoLogVoicemails?.customizable, - readOnlyReason: !userSettings?.autoLogVoicemails?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } @@ -277,18 +301,24 @@ function getOneTimeLogSetting(userSettings) { } function getCallPopSetting(userSettings) { + const autoOpenOptions = userSettings?.autoOpenOptions?.value ?? []; + const value = autoOpenOptions.includes('popupLogPageAfterCall'); + const isCustomizable = userSettings?.autoOpenOptions?.customizable ?? true; return { - value: userSettings?.popupLogPageAfterCall?.value ?? false, - readOnly: userSettings?.popupLogPageAfterCall?.customizable === undefined ? false : !userSettings?.popupLogPageAfterCall?.customizable, - readOnlyReason: !userSettings?.popupLogPageAfterCall?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } function getSMSPopSetting(userSettings) { + const autoOpenOptions = userSettings?.autoOpenOptions?.value ?? []; + const value = autoOpenOptions.includes('popupLogPageAfterSMS'); + const isCustomizable = userSettings?.autoOpenOptions?.customizable ?? true; return { - value: userSettings?.popupLogPageAfterSMS?.value ?? false, - readOnly: userSettings?.popupLogPageAfterSMS?.customizable === undefined ? false : !userSettings?.popupLogPageAfterSMS?.customizable, - readOnlyReason: !userSettings?.popupLogPageAfterSMS?.customizable ? 'This setting is managed by admin' : '' + value: value, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } } @@ -452,6 +482,25 @@ function getCustomSetting(userSettings, id, defaultValue) { } } +function getCustomCallLogDetailsSetting(userSettings, id, defaultValue) { + if (userSettings === undefined) { + return { + value: null, + readOnly: false, + readOnlyReason: '' + }; + } + const callLogDetails = userSettings?.callLogDetails?.value ?? []; + const value = callLogDetails.includes(id); + const isCustomizable = userSettings?.callLogDetails?.customizable ?? true; + return { + value: value ?? defaultValue, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '', + } +} + + exports.preloadUserSettingsFromAdmin = preloadUserSettingsFromAdmin; exports.getUserSettingsOnline = getUserSettingsOnline; exports.uploadUserSettings = uploadUserSettings; @@ -488,4 +537,5 @@ exports.getShowContactsTabSetting = getShowContactsTabSetting; exports.getClickToDialEmbedMode = getClickToDialEmbedMode; exports.getClickToDialUrls = getClickToDialUrls; exports.getNotificationLevelSetting = getNotificationLevelSetting; -exports.getCustomSetting = getCustomSetting; \ No newline at end of file +exports.getCustomSetting = getCustomSetting; +exports.getCustomCallLogDetailsSetting = getCustomCallLogDetailsSetting; \ No newline at end of file diff --git a/src/popup.js b/src/popup.js index dfcaa45..74a3817 100644 --- a/src/popup.js +++ b/src/popup.js @@ -82,14 +82,16 @@ let lastUserSettingSyncDate = new Date(); function shouldAutoLogCall(call, userSettings) { let shouldAutoLog = false; + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + if (call.direction === 'Inbound') { if (call.result === 'Answered') { - shouldAutoLog = userSettings?.autoLogAnsweredIncoming?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogAnsweredIncoming'); } else if (call.result === 'Missed') { - shouldAutoLog = userSettings?.autoLogMissedIncoming?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogMissedIncoming'); } } else if (call.direction === 'Outbound') { - shouldAutoLog = userSettings?.autoLogOutgoing?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogOutgoing'); } // Fallback to legacy setting for backward compatibility @@ -104,16 +106,18 @@ function shouldAutoLogCall(call, userSettings) { function shouldAutoLogCallFromPresence(call, userSettings) { let shouldAutoLog = false; + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + if (call.direction === 'Inbound') { // For inbound calls: CallConnected = answered, Disconnected = missed if (call.result === 'CallConnected') { - shouldAutoLog = userSettings?.autoLogAnsweredIncoming?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogAnsweredIncoming'); } else if (call.result === 'Disconnected') { - shouldAutoLog = userSettings?.autoLogMissedIncoming?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogMissedIncoming'); } } else if (call.direction === 'Outbound') { // For outbound calls: both CallConnected and Disconnected mean call was made - shouldAutoLog = userSettings?.autoLogOutgoing?.value ?? false; + shouldAutoLog = activityLoggingOptions.includes('autoLogOutgoing'); } // Fallback to legacy setting for backward compatibility @@ -133,9 +137,10 @@ async function restartSyncInterval() { } // Check if auto logging is enabled - const autoLogCallsGroupTrigger = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || - (userSettings?.autoLogMissedIncoming?.value ?? false) || - (userSettings?.autoLogOutgoing?.value ?? false); + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const autoLogCallsGroupTrigger = activityLoggingOptions.includes('autoLogAnsweredIncoming') || + activityLoggingOptions.includes('autoLogMissedIncoming') || + activityLoggingOptions.includes('autoLogOutgoing'); const isAutoLogEnabled = autoLogCallsGroupTrigger || (userSettings?.autoLogCall?.value ?? false); // Start interval if conditions are met @@ -1848,9 +1853,10 @@ window.addEventListener('message', async (e) => { responseMessage(data.requestId, { data: 'ok' }); break; } - const isAutoLogSMS = userSettings.autoLogSMS?.value ?? false; - const isAutoLogInboundFax = userSettings.autoLogInboundFax?.value ?? false; - const isAutoLogOutboundFax = userSettings.autoLogOutboundFax?.value ?? false; + const messageActivityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const isAutoLogSMS = messageActivityLoggingOptions.includes('autoLogSMS'); + const isAutoLogInboundFax = messageActivityLoggingOptions.includes('autoLogInboundFax'); + const isAutoLogOutboundFax = messageActivityLoggingOptions.includes('autoLogOutboundFax'); const messageAutoPopup = userCore.getSMSPopSetting(userSettings).value; const messageLogPrefId = `rc-crm-conversation-pref-${data.body.conversation.conversationLogId}`; @@ -2135,79 +2141,16 @@ window.addEventListener('message', async (e) => { for (const i of s.items) { if (i?.items !== undefined) { for (const ii of i.items) { - // Handle checkbox options for activity logging at nested level - if (ii.id === 'activityLoggingOptions') { - // Convert array of selected options to individual boolean settings - const selectedOptions = ii.value || []; - changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; - changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; - changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; - changedSettings.autoLogVoicemails = { value: selectedOptions.includes('autoLogVoicemails') }; - changedSettings.autoLogSMS = { value: selectedOptions.includes('autoLogSMS') }; - changedSettings.autoLogInboundFax = { value: selectedOptions.includes('autoLogInboundFax') }; - changedSettings.autoLogOutboundFax = { value: selectedOptions.includes('autoLogOutboundFax') }; - changedSettings.oneTimeLog = { value: selectedOptions.includes('oneTimeLog') }; - console.log('Activity logging changed settings:', changedSettings); - } else if (ii.id === 'autoOpenOptions') { - // Convert array of selected options to individual boolean settings - const selectedOptions = ii.value || []; - changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; - changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; - } else if (ii.id === 'callLogDetails') { - // Convert array of selected options to individual boolean settings - const selectedOptions = ii.value || []; - changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; - changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; - changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; - changedSettings.addCallLogContactNumber = { value: selectedOptions.includes('addCallLogContactNumber') }; - changedSettings.addCallLogDateTime = { value: selectedOptions.includes('addCallLogDateTime') }; - changedSettings.addCallLogDuration = { value: selectedOptions.includes('addCallLogDuration') }; - changedSettings.addCallLogResult = { value: selectedOptions.includes('addCallLogResult') }; - changedSettings.addCallLogRecording = { value: selectedOptions.includes('addCallLogRecording') }; - changedSettings.addCallLogAiNote = { value: selectedOptions.includes('addCallLogAiNote') }; - changedSettings.addCallLogTranscript = { value: selectedOptions.includes('addCallLogTranscript') }; - } else { - changedSettings[ii.id] = { value: ii.value }; - } + changedSettings[ii.id] = { value: ii.value }; } } else { - // Handle checkbox options for activity logging at direct level (fallback) - if (i.id === 'activityLoggingOptions') { - // Convert array of selected options to individual boolean settings - const selectedOptions = i.value || []; - changedSettings.autoLogAnsweredIncoming = { value: selectedOptions.includes('autoLogAnsweredIncoming') }; - changedSettings.autoLogMissedIncoming = { value: selectedOptions.includes('autoLogMissedIncoming') }; - changedSettings.autoLogOutgoing = { value: selectedOptions.includes('autoLogOutgoing') }; - changedSettings.autoLogVoicemails = { value: selectedOptions.includes('autoLogVoicemails') }; - changedSettings.autoLogSMS = { value: selectedOptions.includes('autoLogSMS') }; - changedSettings.autoLogInboundFax = { value: selectedOptions.includes('autoLogInboundFax') }; - changedSettings.autoLogOutboundFax = { value: selectedOptions.includes('autoLogOutboundFax') }; - changedSettings.oneTimeLog = { value: selectedOptions.includes('oneTimeLog') }; - } else if (i.id === 'autoOpenOptions') { - // Convert array of selected options to individual boolean settings - const selectedOptions = i.value || []; - changedSettings.popupLogPageAfterSMS = { value: selectedOptions.includes('popupLogPageAfterSMS') }; - changedSettings.popupLogPageAfterCall = { value: selectedOptions.includes('popupLogPageAfterCall') }; - } else if (i.id === 'callLogDetails') { - // Convert array of selected options to individual boolean settings - const selectedOptions = i.value || []; - changedSettings.addCallLogNote = { value: selectedOptions.includes('addCallLogNote') }; - changedSettings.addCallSessionId = { value: selectedOptions.includes('addCallSessionId') }; - changedSettings.addCallLogSubject = { value: selectedOptions.includes('addCallLogSubject') }; - changedSettings.addCallLogContactNumber = { value: selectedOptions.includes('addCallLogContactNumber') }; - changedSettings.addCallLogDateTime = { value: selectedOptions.includes('addCallLogDateTime') }; - changedSettings.addCallLogDuration = { value: selectedOptions.includes('addCallLogDuration') }; - changedSettings.addCallLogResult = { value: selectedOptions.includes('addCallLogResult') }; - changedSettings.addCallLogRecording = { value: selectedOptions.includes('addCallLogRecording') }; - changedSettings.addCallLogAiNote = { value: selectedOptions.includes('addCallLogAiNote') }; - changedSettings.addCallLogTranscript = { value: selectedOptions.includes('addCallLogTranscript') }; - } else { - changedSettings[i.id] = { value: i.value }; - } + console.log('Setting at i level:', i.id, 'value:', i.value); + changedSettings[i.id] = { value: i.value }; } } } else if (s.value !== undefined) { + console.log('Setting at s level:', s.id, 'value:', s.value); changedSettings[s.id] = { value: s.value }; } } @@ -2257,51 +2200,11 @@ window.addEventListener('message', async (e) => { for (const settingKey of Object.keys(formData)) { const setting = formData[settingKey]; if (setting && typeof setting === 'object') { - if (settingKey === 'activityLoggingOptions') { - // Handle activity logging checkbox array - const selectedOptions = setting.value || []; - adminSettings.userSettings.autoLogAnsweredIncoming = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogAnsweredIncoming') - }; - adminSettings.userSettings.autoLogMissedIncoming = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogMissedIncoming') - }; - adminSettings.userSettings.autoLogOutgoing = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogOutgoing') - }; - adminSettings.userSettings.autoLogVoicemails = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogVoicemails') - }; - adminSettings.userSettings.autoLogSMS = { + if (settingKey === 'activityLoggingOptions' || settingKey === 'autoOpenOptions') { + // Save as array setting (consistent with user interface) + adminSettings.userSettings[settingKey] = { customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogSMS') - }; - adminSettings.userSettings.autoLogInboundFax = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogInboundFax') - }; - adminSettings.userSettings.autoLogOutboundFax = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('autoLogOutboundFax') - }; - adminSettings.userSettings.oneTimeLog = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('oneTimeLog') - }; - } else if (settingKey === 'autoOpenOptions') { - // Handle auto-open checkbox array - const selectedOptions = setting.value || []; - adminSettings.userSettings.popupLogPageAfterSMS = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('popupLogPageAfterSMS') - }; - adminSettings.userSettings.popupLogPageAfterCall = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes('popupLogPageAfterCall') + value: setting.value || [] }; } else if (Array.isArray(setting.value) && setting.customizable !== undefined) { // Handle custom activity logging settings (like call log details) @@ -2318,14 +2221,11 @@ window.addEventListener('message', async (e) => { } if (customSettingDef && customSettingDef.options) { - // Set each individual option as a separate admin setting - for (const option of customSettingDef.options) { - const individualSetting = { - customizable: setting.customizable ?? true, - value: selectedOptions.includes(option.id) - }; - adminSettings.userSettings[option.id] = individualSetting; - } + // Save as array setting (consistent with user interface) + adminSettings.userSettings[settingKey] = { + customizable: setting.customizable ?? true, + value: selectedOptions + }; } else { console.warn(`No custom setting definition found for ${settingKey}`); } diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index abf6b3f..e7970b9 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -32,7 +32,7 @@ async function getServiceManifest() { authorized: crmAuthed, authorizedAccount: `${crmUserInfo?.name ?? ''} (Admin)`, info: `Developed by ${manifest?.author?.name ?? 'Unknown'}`, - + // Enable call log sync feature callLoggerPath: '/callLogger', callLogPageInputChangedEventPath: '/callLogger/inputChanged', @@ -435,7 +435,7 @@ async function getServiceManifest() { ], buttonEventPath: '/custom-button-click' } - + if (platform.useLicense) { const licenseStatusResponse = await authCore.getLicenseStatus({ serverUrl: manifest.serverUrl }); services.licenseStatus = `License: ${licenseStatusResponse.licenseStatus}`; @@ -510,7 +510,7 @@ async function getServiceManifest() { // Build value array from individual option values finalValue = []; for (const option of filteredOptions) { - const optionSetting = userCore.getCustomSetting(userSettings, option.id, false); + const optionSetting = userCore.getCustomCallLogDetailsSetting(userSettings, option.id, false); if (optionSetting.value) { finalValue.push(option.id); } diff --git a/src/service/logService.js b/src/service/logService.js index ff6bdaa..17e63b1 100644 --- a/src/service/logService.js +++ b/src/service/logService.js @@ -38,9 +38,10 @@ async function retroAutoCallLog({ const { calls, hasMore } = await RCAdapter.getUnloggedCalls(itemsPerPage, pageNumber); // Check if any individual auto-logging setting is enabled - const hasAnyAutoLogEnabled = (userSettings?.autoLogAnsweredIncoming?.value ?? false) || - (userSettings?.autoLogMissedIncoming?.value ?? false) || - (userSettings?.autoLogOutgoing?.value ?? false) || + const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; + const hasAnyAutoLogEnabled = activityLoggingOptions.includes('autoLogAnsweredIncoming') || + activityLoggingOptions.includes('autoLogMissedIncoming') || + activityLoggingOptions.includes('autoLogOutgoing') || (userSettings?.autoLogCall?.value ?? false); if (!hasAnyAutoLogEnabled) { From 12a3ed354339b9bd9ef0d034d1119c6282596e43 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Wed, 6 Aug 2025 11:35:30 +0530 Subject: [PATCH 16/19] Review change --- .../managedSettings/customSettingsPage.js | 186 +++++++++--------- src/popup.js | 39 ++-- 2 files changed, 114 insertions(+), 111 deletions(-) diff --git a/src/components/admin/managedSettings/customSettingsPage.js b/src/components/admin/managedSettings/customSettingsPage.js index 054d87b..275507a 100644 --- a/src/components/admin/managedSettings/customSettingsPage.js +++ b/src/components/admin/managedSettings/customSettingsPage.js @@ -22,62 +22,31 @@ function getCustomSettingsPageRender({ crmManifest, adminUserSettings, userSetti } } for (const section of crmManifest.settings) { - page.schema.properties[section.id] = { - type: 'string', - description: section.name - } - page.uiSchema[section.id] = { - "ui:field": "typography", - "ui:variant": "title2" - } - for (const setting of section.items) { - switch (setting.type) { - case 'warning': - page.schema.properties[setting.id] = { - type: 'string', - description: setting.value - }; - page.uiSchema[setting.id] = { - "ui:field": "admonition", - "ui:severity": "warning" - } - break; - case 'inputField': - case 'boolean': - page.schema.properties[setting.id] = { - type: 'object', - title: setting.name, - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: setting.type === 'inputField' ? 'string' : 'boolean', - title: setting.name - } + // Only process sections that don't belong to Activity Logging and have items + if (section.section !== 'activityLogging' && section.items) { + page.schema.properties[section.id] = { + type: 'string', + description: section.name + } + page.uiSchema[section.id] = { + "ui:field": "typography", + "ui:variant": "title2" + } + for (const setting of section.items) { + + switch (setting.type) { + case 'warning': + page.schema.properties[setting.id] = { + type: 'string', + description: setting.value + }; + page.uiSchema[setting.id] = { + "ui:field": "admonition", + "ui:severity": "warning" } - }; - page.formData[setting.id] = { - customizable: adminUserSettings?.[setting.id]?.customizable ?? true, - value: adminUserSettings?.[setting.id]?.value ?? setting.defaultValue - }; - page.uiSchema[setting.id] = { - "ui:collapsible": true, - } - break; - case 'option': - page.formData[setting.id] = { - customizable: adminUserSettings?.[setting.id]?.customizable ?? true, - value: adminUserSettings?.[setting.id]?.value ?? setting?.defaultValue - }; - if (setting.dynamicOptions) { - page.formData[setting.id].options = userSettings?.[setting.id]?.options ?? []; - } - page.uiSchema[setting.id] = { - "ui:collapsible": true, - } - if (setting.checkbox) { + break; + case 'inputField': + case 'boolean': page.schema.properties[setting.id] = { type: 'object', title: setting.name, @@ -87,48 +56,83 @@ function getCustomSettingsPageRender({ crmManifest, adminUserSettings, userSetti title: 'Customizable by user' }, value: { - type: 'array', - title: setting.name, - items: { - type: 'string', - enum: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => option.id) : setting.options.map(option => option.id), - enumNames: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => option.name) : setting.options.map(option => option.name) - }, - uniqueItems: true + type: setting.type === 'inputField' ? 'string' : 'boolean', + title: setting.name } } + }; + page.formData[setting.id] = { + customizable: adminUserSettings?.[setting.id]?.customizable ?? true, + value: adminUserSettings?.[setting.id]?.value ?? setting.defaultValue + }; + page.uiSchema[setting.id] = { + "ui:collapsible": true, } - page.uiSchema[setting.id].value = { - 'ui:widget': 'checkboxes', - 'ui:options': { - inline: true, - }, + break; + case 'option': + page.formData[setting.id] = { + customizable: adminUserSettings?.[setting.id]?.customizable ?? true, + value: adminUserSettings?.[setting.id]?.value ?? setting?.defaultValue }; - } - else { - page.schema.properties[setting.id] = { - type: 'object', - title: setting.name, - properties: { - customizable: { - type: 'boolean', - title: 'Customizable by user' - }, - value: { - type: 'string', - title: setting.name, - oneOf: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => ({ - const: option.id, - title: option.name - })) : setting.options.map(option => ({ - const: option.id, - title: option.name - })) + if (setting.dynamicOptions) { + page.formData[setting.id].options = userSettings?.[setting.id]?.options ?? []; + } + page.uiSchema[setting.id] = { + "ui:collapsible": true, + } + if (setting.checkbox) { + page.schema.properties[setting.id] = { + type: 'object', + title: setting.name, + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'array', + title: setting.name, + items: { + type: 'string', + enum: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => option.id) : setting.options.map(option => option.id), + enumNames: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => option.name) : setting.options.map(option => option.name) + }, + uniqueItems: true + } } } - }; - } - break; + page.uiSchema[setting.id].value = { + 'ui:widget': 'checkboxes', + 'ui:options': { + inline: true, + }, + }; + } + else { + page.schema.properties[setting.id] = { + type: 'object', + title: setting.name, + properties: { + customizable: { + type: 'boolean', + title: 'Customizable by user' + }, + value: { + type: 'string', + title: setting.name, + oneOf: setting.dynamicOptions ? userSettings?.[setting.id]?.options?.map(option => ({ + const: option.id, + title: option.name + })) : setting.options.map(option => ({ + const: option.id, + title: option.name + })) + } + } + }; + } + break; + } } } } diff --git a/src/popup.js b/src/popup.js index 74a3817..e68a5a5 100644 --- a/src/popup.js +++ b/src/popup.js @@ -84,15 +84,11 @@ function shouldAutoLogCall(call, userSettings) { const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - if (call.direction === 'Inbound') { - if (call.result === 'Answered') { - shouldAutoLog = activityLoggingOptions.includes('autoLogAnsweredIncoming'); - } else if (call.result === 'Missed') { - shouldAutoLog = activityLoggingOptions.includes('autoLogMissedIncoming'); - } - } else if (call.direction === 'Outbound') { - shouldAutoLog = activityLoggingOptions.includes('autoLogOutgoing'); - } + const callType = call.direction === 'Inbound' + ? (call.result === 'Answered' ? 'autoLogAnsweredIncoming' : 'autoLogMissedIncoming') + : 'autoLogOutgoing'; + + shouldAutoLog = activityLoggingOptions.includes(callType); // Fallback to legacy setting for backward compatibility if (!shouldAutoLog) { @@ -108,17 +104,12 @@ function shouldAutoLogCallFromPresence(call, userSettings) { const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - if (call.direction === 'Inbound') { - // For inbound calls: CallConnected = answered, Disconnected = missed - if (call.result === 'CallConnected') { - shouldAutoLog = activityLoggingOptions.includes('autoLogAnsweredIncoming'); - } else if (call.result === 'Disconnected') { - shouldAutoLog = activityLoggingOptions.includes('autoLogMissedIncoming'); - } - } else if (call.direction === 'Outbound') { - // For outbound calls: both CallConnected and Disconnected mean call was made - shouldAutoLog = activityLoggingOptions.includes('autoLogOutgoing'); - } + // Determine auto-log setting based on call direction and result + const callType = call.direction === 'Inbound' + ? (call.result === 'CallConnected' ? 'autoLogAnsweredIncoming' : 'autoLogMissedIncoming') + : 'autoLogOutgoing'; + + shouldAutoLog = activityLoggingOptions.includes(callType); // Fallback to legacy setting for backward compatibility if (!shouldAutoLog) { @@ -2238,6 +2229,14 @@ window.addEventListener('message', async (e) => { } } } + } else if (data.body.button.id === 'customSettingsPage') { + // Handle custom settings page - settings are stored directly by ID + for (const settingKey of Object.keys(formData)) { + const setting = formData[settingKey]; + if (setting && typeof setting === 'object' && (setting.customizable !== undefined || setting.value !== undefined)) { + adminSettings.userSettings[settingKey] = setting; + } + } } else { // For other pages, handle nested structure for (const sectionKey of Object.keys(formData)) { From 109b8d6a07181bc62745ff175240a2dabee3c578 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Wed, 6 Aug 2025 14:37:34 +0530 Subject: [PATCH 17/19] Review changes --- src/core/user.js | 105 ++++-------------------------- src/service/embeddableServices.js | 35 ++-------- 2 files changed, 18 insertions(+), 122 deletions(-) diff --git a/src/core/user.js b/src/core/user.js index f0d0694..197e47f 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -159,42 +159,17 @@ async function updateSSCLToken({ serverUrl, platform, token }) { -function getAutoLogSMSSetting(userSettings) { - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogSMS'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} - -function getAutoLogInboundFaxSetting(userSettings) { - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogInboundFax'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} +// Unified function to get activity logging settings +function getActivityLoggingSetting(userSettings, isAdmin = false) { + const activityLoggingValue = userSettings?.activityLoggingOptions?.value ?? []; -function getAutoLogOutboundFaxSetting(userSettings) { - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogOutboundFax'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} - -function getAutoLogAnsweredIncomingSetting(userSettings, isAdmin) { + // Check for server side logging conflicts for call-related settings + const callRelatedSettings = ['autoLogAnsweredIncoming', 'autoLogMissedIncoming', 'autoLogOutgoing']; const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; - if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { + const hasCallRelatedSettings = callRelatedSettings.some(setting => activityLoggingValue.includes(setting)); + if (hasCallRelatedSettings && + serverSideLoggingEnabled && + (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { return { value: false, readOnly: true, @@ -202,62 +177,12 @@ function getAutoLogAnsweredIncomingSetting(userSettings, isAdmin) { warning: 'Unavailable while server side call logging enabled' } } - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogAnsweredIncoming'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} -function getAutoLogMissedIncomingSetting(userSettings, isAdmin) { - const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; - if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { - return { - value: false, - readOnly: true, - readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', - warning: 'Unavailable while server side call logging enabled' - } - } - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogMissedIncoming'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} - -function getAutoLogOutgoingSetting(userSettings, isAdmin) { - const serverSideLoggingEnabled = userSettings?.serverSideLogging?.enable ?? false; - if (serverSideLoggingEnabled && (userSettings?.serverSideLogging?.loggingLevel === 'Account' || isAdmin)) { - return { - value: false, - readOnly: true, - readOnlyReason: 'This cannot be turn ON becauase server side logging is enabled by admin', - warning: 'Unavailable while server side call logging enabled' - } - } - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogOutgoing'); + // Standard activity logging logic const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; - return { - value: value, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' - } -} -function getAutoLogVoicemailsSetting(userSettings) { - const activityLoggingOptions = userSettings?.activityLoggingOptions?.value ?? []; - const value = activityLoggingOptions.includes('autoLogVoicemails'); - const isCustomizable = userSettings?.activityLoggingOptions?.customizable ?? true; return { - value: value, + value: activityLoggingValue, readOnly: !isCustomizable, readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '' } @@ -506,13 +431,7 @@ exports.getUserSettingsOnline = getUserSettingsOnline; exports.uploadUserSettings = uploadUserSettings; exports.refreshUserSettings = refreshUserSettings; exports.updateSSCLToken = updateSSCLToken; -exports.getAutoLogSMSSetting = getAutoLogSMSSetting; -exports.getAutoLogInboundFaxSetting = getAutoLogInboundFaxSetting; -exports.getAutoLogOutboundFaxSetting = getAutoLogOutboundFaxSetting; -exports.getAutoLogAnsweredIncomingSetting = getAutoLogAnsweredIncomingSetting; -exports.getAutoLogMissedIncomingSetting = getAutoLogMissedIncomingSetting; -exports.getAutoLogOutgoingSetting = getAutoLogOutgoingSetting; -exports.getAutoLogVoicemailsSetting = getAutoLogVoicemailsSetting; +exports.getActivityLoggingSetting = getActivityLoggingSetting; exports.getLogSyncFrequencySetting = getLogSyncFrequencySetting; exports.getLogSyncFrequencyInMilliseconds = getLogSyncFrequencyInMilliseconds; exports.getEnableRetroCallLogSync = getEnableRetroCallLogSync; diff --git a/src/service/embeddableServices.js b/src/service/embeddableServices.js index e7970b9..1970fa8 100644 --- a/src/service/embeddableServices.js +++ b/src/service/embeddableServices.js @@ -43,9 +43,9 @@ async function getServiceManifest() { messagesLogPageInputChangedEventPath: '/messageLogger/inputChanged', messageLogEntityMatcherPath: '/messageLogger/match', messageLoggerAutoSettingLabel: 'Log SMS conversations automatically', - messageLoggerAutoSettingReadOnly: userCore.getAutoLogSMSSetting(userSettings).readOnly, - messageLoggerAutoSettingReadOnlyReason: userCore.getAutoLogSMSSetting(userSettings).readOnlyReason, - messageLoggerAutoSettingReadOnlyValue: userCore.getAutoLogSMSSetting(userSettings).value, + messageLoggerAutoSettingReadOnly: userCore.getActivityLoggingSetting(userSettings, isAdmin).readOnly, + messageLoggerAutoSettingReadOnlyReason: userCore.getActivityLoggingSetting(userSettings, isAdmin).readOnlyReason, + messageLoggerAutoSettingReadOnlyValue: userCore.getActivityLoggingSetting(userSettings, isAdmin).value, callLoggerAutoLogSettingHidden: true, messageLoggerAutoSettingHidden: true, @@ -95,32 +95,9 @@ async function getServiceManifest() { } ], - value: (() => { - const activityLoggingValues = [ - ...(userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).value ? ['autoLogAnsweredIncoming'] : []), - ...(userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).value ? ['autoLogMissedIncoming'] : []), - ...(userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).value ? ['autoLogOutgoing'] : []), - ...(userCore.getAutoLogVoicemailsSetting(userSettings).value ? ['autoLogVoicemails'] : []), - ...(userCore.getAutoLogSMSSetting(userSettings).value ? ['autoLogSMS'] : []), - ...(userCore.getAutoLogInboundFaxSetting(userSettings).value ? ['autoLogInboundFax'] : []), - ...(userCore.getAutoLogOutboundFaxSetting(userSettings).value ? ['autoLogOutboundFax'] : []) - ]; - return activityLoggingValues; - })(), - readOnly: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnly || - userCore.getAutoLogVoicemailsSetting(userSettings).readOnly || - userCore.getAutoLogSMSSetting(userSettings).readOnly || - userCore.getAutoLogInboundFaxSetting(userSettings).readOnly || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnly, - readOnlyReason: userCore.getAutoLogAnsweredIncomingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogMissedIncomingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogOutgoingSetting(userSettings, isAdmin).readOnlyReason || - userCore.getAutoLogVoicemailsSetting(userSettings).readOnlyReason || - userCore.getAutoLogSMSSetting(userSettings).readOnlyReason || - userCore.getAutoLogInboundFaxSetting(userSettings).readOnlyReason || - userCore.getAutoLogOutboundFaxSetting(userSettings).readOnlyReason + value: userSettings?.activityLoggingOptions?.value ?? [], + readOnly: userCore.getActivityLoggingSetting(userSettings, isAdmin).readOnly, + readOnlyReason: userCore.getActivityLoggingSetting(userSettings, isAdmin).readOnlyReason }, { id: "logSyncFrequency", From 9dcba41573db798ebd49efa88d2cd833831a44dd Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Wed, 6 Aug 2025 20:23:10 +0530 Subject: [PATCH 18/19] Review Change --- src/core/admin.js | 22 ++++++++++++- src/core/user.js | 82 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/core/admin.js b/src/core/admin.js index 9fb5169..3ccce3c 100644 --- a/src/core/admin.js +++ b/src/core/admin.js @@ -20,10 +20,30 @@ async function getAdminSettings({ serverUrl }) { async function uploadAdminSettings({ serverUrl, adminSettings }) { const rcAccessToken = getRcAccessToken(); const { rcUnifiedCrmExtJwt } = await chrome.storage.local.get('rcUnifiedCrmExtJwt'); + + let adminSettingsToUpload = { ...adminSettings }; + + // Convert callLogDetails array format to individual boolean settings for backend + if (adminSettingsToUpload.userSettings?.callLogDetails && Array.isArray(adminSettingsToUpload.userSettings.callLogDetails.value)) { + const callLogDetailsArray = adminSettingsToUpload.userSettings.callLogDetails.value; + const customizable = adminSettingsToUpload.userSettings.callLogDetails.customizable; + const callLogDetailOptions = ['addCallLogNote', 'addCallSessionId', 'addCallLogSubject', + 'addCallLogContactNumber', 'addCallLogDuration', 'addCallLogResult', + 'addCallLogRecording', 'addCallLogAiNote', 'addCallLogTranscript', 'addCallLogDateTime']; + + // Convert to individual boolean settings for backend + for (const option of callLogDetailOptions) { + adminSettingsToUpload.userSettings[option] = { + customizable: customizable, + value: callLogDetailsArray.includes(option) + }; + } + } + const uploadAdminSettingsResponse = await axios.post( `${serverUrl}/admin/settings?jwtToken=${rcUnifiedCrmExtJwt}&rcAccessToken=${rcAccessToken}`, { - adminSettings + adminSettings: adminSettingsToUpload }); } diff --git a/src/core/user.js b/src/core/user.js index 197e47f..bb52294 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -28,13 +28,32 @@ async function getUserSettingsOnline({ serverUrl }) { async function uploadUserSettings({ serverUrl, userSettings }) { const { rcUnifiedCrmExtJwt } = await chrome.storage.local.get('rcUnifiedCrmExtJwt'); const { selectedRegion } = await chrome.storage.local.get({ selectedRegion: 'US' }); - let userSettingsToUpload = userSettings; + let userSettingsToUpload = { ...userSettings }; + if (userSettingsToUpload.selectedRegion) { userSettingsToUpload.selectedRegion.value = selectedRegion; } else { userSettingsToUpload.selectedRegion = { value: selectedRegion }; } + + // Convert callLogDetails array format to individual boolean settings for backend + if (userSettingsToUpload.callLogDetails && Array.isArray(userSettingsToUpload.callLogDetails.value)) { + const callLogDetailsArray = userSettingsToUpload.callLogDetails.value; + const customizable = userSettingsToUpload.callLogDetails.customizable; + const callLogDetailOptions = ['addCallLogNote', 'addCallSessionId', 'addCallLogSubject', + 'addCallLogContactNumber', 'addCallLogDuration', 'addCallLogResult', + 'addCallLogRecording', 'addCallLogAiNote', 'addCallLogTranscript', 'addCallLogDateTime']; + + // Convert to individual boolean settings for backend + for (const option of callLogDetailOptions) { + userSettingsToUpload[option] = { + customizable: customizable, + value: callLogDetailsArray.includes(option) + }; + } + } + const uploadUserSettingsResponse = await axios.post( `${serverUrl}/user/settings?jwtToken=${rcUnifiedCrmExtJwt}`, { @@ -78,6 +97,33 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false } + // TEMP: to be deleted after this version 1.6.1 + // Migrate existing individual boolean call log details to array format (backward compatibility) + const callLogDetailOptions = ['addCallLogNote', 'addCallSessionId', 'addCallLogSubject', + 'addCallLogContactNumber', 'addCallLogDuration', 'addCallLogResult', + 'addCallLogRecording', 'addCallLogAiNote', 'addCallLogTranscript', 'addCallLogDateTime']; + + if (!userSettings.callLogDetails && callLogDetailOptions.some(option => userSettings[option])) { + // Migrate from individual boolean settings to array format + const enabledOptions = []; + let isCustomizable = true; + + for (const option of callLogDetailOptions) { + if (userSettings[option]?.value === true) { + enabledOptions.push(option); + } + // If any option is not customizable, make the whole array not customizable + if (userSettings[option]?.customizable === false) { + isCustomizable = false; + } + } + + userSettings.callLogDetails = { + customizable: isCustomizable, + value: enabledOptions + }; + } + if (changedSettings) { for (const k of Object.keys(changedSettings)) { if (userSettings[k] === undefined || !userSettings[k].value) { @@ -415,14 +461,34 @@ function getCustomCallLogDetailsSetting(userSettings, id, defaultValue) { readOnlyReason: '' }; } - const callLogDetails = userSettings?.callLogDetails?.value ?? []; - const value = callLogDetails.includes(id); - const isCustomizable = userSettings?.callLogDetails?.customizable ?? true; - return { - value: value ?? defaultValue, - readOnly: !isCustomizable, - readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '', + + // Check if we have the new array format + if (userSettings?.callLogDetails?.value) { + const callLogDetails = userSettings.callLogDetails.value; + const value = callLogDetails.includes(id); + const isCustomizable = userSettings.callLogDetails.customizable ?? true; + return { + value: value ?? defaultValue, + readOnly: !isCustomizable, + readOnlyReason: !isCustomizable ? 'This setting is managed by admin' : '', + } + } + + // Fallback to individual boolean settings (backward compatibility) + if (userSettings[id]) { + return { + value: userSettings[id].value ?? defaultValue, + readOnly: !userSettings[id].customizable, + readOnlyReason: !userSettings[id].customizable ? 'This setting is managed by admin' : '', + } } + + // Default fallback + return { + value: defaultValue, + readOnly: false, + readOnlyReason: '' + }; } From 8492efe2091a2bbe70171e9625b7d1e3f26c2462 Mon Sep 17 00:00:00 2001 From: SushilMallRC Date: Wed, 6 Aug 2025 20:25:00 +0530 Subject: [PATCH 19/19] typo --- src/core/user.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/user.js b/src/core/user.js index bb52294..619efde 100644 --- a/src/core/user.js +++ b/src/core/user.js @@ -96,8 +96,6 @@ async function refreshUserSettings({ changedSettings, isAvoidForceChange = false delete userSettings.autoLogCall; } - - // TEMP: to be deleted after this version 1.6.1 // Migrate existing individual boolean call log details to array format (backward compatibility) const callLogDetailOptions = ['addCallLogNote', 'addCallSessionId', 'addCallLogSubject', 'addCallLogContactNumber', 'addCallLogDuration', 'addCallLogResult',