mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-01 11:37:58 +00:00
<img width="1240" alt="Screenshot 2025-06-05 at 12 39 04 AM" src="https://github.com/user-attachments/assets/0071cd23-38c3-4638-946e-f1fbd11ec845" /> ## Changes Give the admins an option to delete conversation via the context menu - enable conversation deletion in routes and controller - expose delete API on conversations - add delete option in conversation context menu and integrate with card and list - implement store action and mutation for delete - update i18n with new strings fixes: https://github.com/chatwoot/chatwoot/issues/947 --------- Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Pranav <pranavrajs@gmail.com>
220 lines
6.6 KiB
JavaScript
220 lines
6.6 KiB
JavaScript
const roleMapping = {
|
|
0: 'agent',
|
|
1: 'administrator',
|
|
};
|
|
|
|
const availabilityMapping = {
|
|
0: 'online',
|
|
1: 'offline',
|
|
2: 'busy',
|
|
};
|
|
|
|
const translationKeys = {
|
|
'automationrule:create': `AUDIT_LOGS.AUTOMATION_RULE.ADD`,
|
|
'automationrule:update': `AUDIT_LOGS.AUTOMATION_RULE.EDIT`,
|
|
'automationrule:destroy': `AUDIT_LOGS.AUTOMATION_RULE.DELETE`,
|
|
'webhook:create': `AUDIT_LOGS.WEBHOOK.ADD`,
|
|
'webhook:update': `AUDIT_LOGS.WEBHOOK.EDIT`,
|
|
'webhook:destroy': `AUDIT_LOGS.WEBHOOK.DELETE`,
|
|
'inbox:create': `AUDIT_LOGS.INBOX.ADD`,
|
|
'inbox:update': `AUDIT_LOGS.INBOX.EDIT`,
|
|
'inbox:destroy': `AUDIT_LOGS.INBOX.DELETE`,
|
|
'user:sign_in': `AUDIT_LOGS.USER_ACTION.SIGN_IN`,
|
|
'user:sign_out': `AUDIT_LOGS.USER_ACTION.SIGN_OUT`,
|
|
'team:create': `AUDIT_LOGS.TEAM.ADD`,
|
|
'team:update': `AUDIT_LOGS.TEAM.EDIT`,
|
|
'team:destroy': `AUDIT_LOGS.TEAM.DELETE`,
|
|
'macro:create': `AUDIT_LOGS.MACRO.ADD`,
|
|
'macro:update': `AUDIT_LOGS.MACRO.EDIT`,
|
|
'macro:destroy': `AUDIT_LOGS.MACRO.DELETE`,
|
|
'accountuser:create': `AUDIT_LOGS.ACCOUNT_USER.ADD`,
|
|
'accountuser:update:self': `AUDIT_LOGS.ACCOUNT_USER.EDIT.SELF`,
|
|
'accountuser:update:other': `AUDIT_LOGS.ACCOUNT_USER.EDIT.OTHER`,
|
|
'accountuser:update:deleted': `AUDIT_LOGS.ACCOUNT_USER.EDIT.DELETED`,
|
|
'inboxmember:create': `AUDIT_LOGS.INBOX_MEMBER.ADD`,
|
|
'inboxmember:destroy': `AUDIT_LOGS.INBOX_MEMBER.REMOVE`,
|
|
'teammember:create': `AUDIT_LOGS.TEAM_MEMBER.ADD`,
|
|
'teammember:destroy': `AUDIT_LOGS.TEAM_MEMBER.REMOVE`,
|
|
'account:update': `AUDIT_LOGS.ACCOUNT.EDIT`,
|
|
'conversation:destroy': `AUDIT_LOGS.CONVERSATION.DELETE`,
|
|
};
|
|
|
|
function extractAttrChange(attrChange) {
|
|
if (Array.isArray(attrChange)) {
|
|
return attrChange[attrChange.length - 1];
|
|
}
|
|
return attrChange;
|
|
}
|
|
|
|
export function extractChangedAccountUserValues(auditedChanges) {
|
|
let changes = [];
|
|
let values = [];
|
|
|
|
// Check roles
|
|
if (auditedChanges.role && auditedChanges.role.length) {
|
|
changes.push('role');
|
|
values.push(roleMapping[extractAttrChange(auditedChanges.role)]);
|
|
}
|
|
|
|
// Check availability
|
|
if (auditedChanges.availability && auditedChanges.availability.length) {
|
|
changes.push('availability');
|
|
values.push(
|
|
availabilityMapping[extractAttrChange(auditedChanges.availability)]
|
|
);
|
|
}
|
|
|
|
return { changes, values };
|
|
}
|
|
|
|
function getAgentName(userId, agentList) {
|
|
if (userId === null) {
|
|
return 'System';
|
|
}
|
|
|
|
const agentName = agentList.find(agent => agent.id === userId)?.name;
|
|
|
|
// If agent does not exist(removed/deleted), return userId
|
|
return agentName || userId;
|
|
}
|
|
|
|
function handleAccountUserCreate(auditLogItem, translationPayload, agentList) {
|
|
translationPayload.invitee = getAgentName(
|
|
auditLogItem.audited_changes.user_id,
|
|
agentList
|
|
);
|
|
|
|
const roleKey = auditLogItem.audited_changes.role;
|
|
translationPayload.role = roleMapping[roleKey] || 'unknown'; // 'unknown' as a fallback in case an unrecognized key is provided
|
|
|
|
return translationPayload;
|
|
}
|
|
|
|
function handleAccountUserUpdate(auditLogItem, translationPayload, agentList) {
|
|
if (auditLogItem.user_id !== auditLogItem.auditable?.user_id) {
|
|
translationPayload.user = getAgentName(
|
|
auditLogItem.auditable?.user_id,
|
|
agentList
|
|
);
|
|
}
|
|
|
|
const accountUserChanges = extractChangedAccountUserValues(
|
|
auditLogItem.audited_changes
|
|
);
|
|
if (accountUserChanges) {
|
|
translationPayload.attributes = accountUserChanges.changes;
|
|
translationPayload.values = accountUserChanges.values;
|
|
}
|
|
return translationPayload;
|
|
}
|
|
|
|
function setUserInPayload(auditLogItem, translationPayload, agentList) {
|
|
const userIdChange = auditLogItem.audited_changes.user_id;
|
|
if (userIdChange && userIdChange !== undefined) {
|
|
translationPayload.user = getAgentName(userIdChange, agentList);
|
|
}
|
|
return translationPayload;
|
|
}
|
|
|
|
function setTeamIdInPayload(auditLogItem, translationPayload) {
|
|
if (auditLogItem.audited_changes.team_id) {
|
|
translationPayload.team_id = auditLogItem.audited_changes.team_id;
|
|
}
|
|
return translationPayload;
|
|
}
|
|
|
|
function setInboxIdInPayload(auditLogItem, translationPayload) {
|
|
if (auditLogItem.audited_changes.inbox_id) {
|
|
translationPayload.inbox_id = auditLogItem.audited_changes.inbox_id;
|
|
}
|
|
return translationPayload;
|
|
}
|
|
|
|
function handleInboxTeamMember(auditLogItem, translationPayload, agentList) {
|
|
if (auditLogItem.audited_changes) {
|
|
translationPayload = setUserInPayload(
|
|
auditLogItem,
|
|
translationPayload,
|
|
agentList
|
|
);
|
|
translationPayload = setTeamIdInPayload(auditLogItem, translationPayload);
|
|
translationPayload = setInboxIdInPayload(auditLogItem, translationPayload);
|
|
}
|
|
return translationPayload;
|
|
}
|
|
|
|
function handleAccountUser(
|
|
auditLogItem,
|
|
translationPayload,
|
|
agentList,
|
|
action
|
|
) {
|
|
if (action === 'create') {
|
|
return handleAccountUserCreate(auditLogItem, translationPayload, agentList);
|
|
}
|
|
|
|
if (action === 'update') {
|
|
return handleAccountUserUpdate(auditLogItem, translationPayload, agentList);
|
|
}
|
|
|
|
return translationPayload;
|
|
}
|
|
|
|
export function generateTranslationPayload(auditLogItem, agentList) {
|
|
let translationPayload = {
|
|
agentName: getAgentName(auditLogItem.user_id, agentList),
|
|
id: auditLogItem.auditable_id,
|
|
};
|
|
|
|
const auditableType = auditLogItem.auditable_type.toLowerCase();
|
|
const action = auditLogItem.action.toLowerCase();
|
|
|
|
if (auditableType === 'conversation' && action === 'destroy') {
|
|
translationPayload.id =
|
|
auditLogItem.audited_changes?.display_id || auditLogItem.auditable_id;
|
|
}
|
|
|
|
if (auditableType === 'accountuser') {
|
|
translationPayload = handleAccountUser(
|
|
auditLogItem,
|
|
translationPayload,
|
|
agentList,
|
|
action
|
|
);
|
|
}
|
|
|
|
if (auditableType === 'inboxmember' || auditableType === 'teammember') {
|
|
translationPayload = handleInboxTeamMember(
|
|
auditLogItem,
|
|
translationPayload,
|
|
agentList
|
|
);
|
|
}
|
|
|
|
return translationPayload;
|
|
}
|
|
|
|
function getAccountUserUpdateSuffix(auditLogItem) {
|
|
if (auditLogItem.auditable === null) {
|
|
// If the user is deleted, we don't need to check if the user is the same as the auditLogItem.user_id
|
|
// Else we can use the deleted translation key
|
|
// It doesn't need the agent name
|
|
return ':deleted';
|
|
}
|
|
return auditLogItem.user_id === auditLogItem.auditable.user_id
|
|
? ':self'
|
|
: ':other';
|
|
}
|
|
|
|
export const generateLogActionKey = auditLogItem => {
|
|
const auditableType = auditLogItem.auditable_type.toLowerCase();
|
|
const action = auditLogItem.action.toLowerCase();
|
|
let logActionKey = `${auditableType}:${action}`;
|
|
|
|
if (auditableType === 'accountuser' && action === 'update') {
|
|
logActionKey += getAccountUserUpdateSuffix(auditLogItem);
|
|
}
|
|
|
|
return translationKeys[logActionKey] || '';
|
|
};
|