Skip to content

Conversation

shinde-rahul
Copy link
Contributor

@shinde-rahul shinde-rahul commented Mar 4, 2025

Q A
Bug fix? (use the a.b branch)
New feature/enhancement? (use the a.x branch) ✔️
Deprecations?
BC breaks? (use the c.x branch)
Automated tests included? ✔️
Related user documentation PR URL mautic/user-documentation#...
Related developer documentation PR URL mautic/developer-documentation-new#...
Issue(s) addressed Fixes #...

Description

User Story

As an admin user,
I want to see a detailed history of changes made to a campaign,
So that I can audit and debug modifications effectively.

Details:

Currently, the Recent Activity section only indicates that a campaign was updated but does not provide details on what was changed. To improve auditing and debugging, the system should track and display a versioned change log that includes:

  • Timestamp of each change
  • User who made the change
  • Fields modified (e.g., campaign name, conditions, actions, triggers, settings, etc.)
  • Previous and new values of changed fields
Before After
image image

📋 Steps to test this PR:

  1. Open this PR on Gitpod or pull it down for testing locally (see docs on testing PRs here)
  2. Open any campaign and see the new tab labeled Audit Log
  3. If there are no campaigns created, here are the steps
    1. Create a New Campaign
      1. Add name and description
    2. Click Launch Campaign Builder.
    3. Add a Contact Source
    4. Add the First Event - Click Action and select Adjust contact points action
      1. Add required data
    5. Click on the Save and then the Close builder button
    6. Save & Close the campaign
    7. Modify it to add and delete Actions, Conditions, or Decisions.
    8. While you're done modifying it, please see the Audit log tab on the Campaign details page.

@shinde-rahul shinde-rahul added user-experience Anything related to related to workflows, feedback, and navigation enhancement Any improvement to an existing feature or functionality campaigns Anything related to campaigns and campaign builder developer-experience Anything related to developer experience mautic-6 labels Mar 4, 2025
@shinde-rahul shinde-rahul self-assigned this Mar 4, 2025
Copy link

codecov bot commented Mar 4, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 65.69%. Comparing base (df6c49a) to head (ce9f493).
Report is 57 commits behind head on 7.x.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##                7.x   #14676      +/-   ##
============================================
+ Coverage     65.62%   65.69%   +0.07%     
- Complexity    34953    34959       +6     
============================================
  Files          2299     2300       +1     
  Lines        140589   140616      +27     
============================================
+ Hits          92262    92380     +118     
+ Misses        48327    48236      -91     
Files with missing lines Coverage Δ
...Listener/CampaignInjectCustomContentSubscriber.php 100.00% <100.00%> (ø)

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shinde-rahul shinde-rahul added ready-to-test PR's that are ready to test code-review-needed PR's that require a code review before merging labels Mar 4, 2025
@shinde-rahul shinde-rahul marked this pull request as ready for review March 4, 2025 12:28
@shinde-rahul shinde-rahul moved this to 🧑🏻‍💻 Needs a code review in Open Source Fridays Mar 4, 2025
@shinde-rahul shinde-rahul marked this pull request as draft March 4, 2025 12:37
@escopecz
Copy link
Member

escopecz commented Mar 4, 2025

@shinde-rahul isn't this already possible with #13373?

@adiux
Copy link
Contributor

adiux commented Mar 5, 2025

@escopecz we did not see that PR #13373. It looks like a great feature. From the description, I think it is a bit different to this. The audit log there is more targeted for an overview of all the changes. Here we would see the changes that were made to the campaign. For the editor user to double check or debug what was done. In the same way as we do it with e.g. the contacts.

So I see an added benefit with this feature.

@escopecz
Copy link
Member

escopecz commented Mar 5, 2025

@adiux what I worry a little with this is adding duplicated features in various places in Mautic. I agree that this is more convenient when the users only want to see the campaign and campaign event changes.

I'm thinking whether we could instead create a new Report() entity, configure it for this specific campaign and let the Report bundle to generate the outcome. To at least reuse the code instead of creating it in the campaign bundle from scratch. But then I can see there are "removed" events that the audit log report doesn't display this nicely. So perhaps it's different enough to have its own implementation.

@shinde-rahul is this ready for review? I can see that reviewers were requested but the PR is still in the Draft stage.

Copy link

@imaabasiee imaabasiee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
The change log now shows details made to campaigns - the timestamp, fields modified, previous/new values of changed field etc.

@escopecz
Copy link
Member

@shinde-rahul Looking at the screenshots, I'm missing the username. I can see the column header is there but instead of username it shows action that was taken. Can you please explain what's going on?

@shinde-rahul shinde-rahul requested a review from imaabasiee March 27, 2025 11:26
@shinde-rahul
Copy link
Contributor Author

@imaabasiee, thanks for catching this. I have corrected the names.

@escopecz, The wrong variable got committed since starting.

I apologize for this oversight.

Copy link

@imaabasiee imaabasiee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The User Name is returning accurately now @escopecz @escopecz
image

Copy link
Member

@escopecz escopecz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot find anything in the code. Nicely done! You can ignore my JS rant. It's just an FYI for future PRs. But I'd like @andersonjeccel input on the icons in the translation text. I think we should be using the icons from the icon set in Mautic for unified look and feel. But it's not my expertise.

Comment on lines 2338 to 2359
mQuery("#campaign-auditlog a[data-activate-details='all']").on('click', function() {
let $icon = mQuery(this).find('span').first();
if ($icon.hasClass('ri-arrow-down-s-line')) {
mQuery("#campaign-auditlog a[data-activate-details!='all']").each(function () {
const detailsId = mQuery(this).data('activate-details');
if (detailsId && mQuery('#auditlog-details-' + detailsId).length) {
mQuery('#auditlog-details-' + detailsId).removeClass('hide');
mQuery(this).addClass('active');
}
});
$icon.removeClass('ri-arrow-down-s-line').addClass('ri-arrow-up-s-line');
} else {
mQuery("#campaign-auditlog a[data-activate-details!='all']").each(function () {
const detailsId = mQuery(this).data('activate-details');
if (detailsId && mQuery('#auditlog-details-' + detailsId).length) {
mQuery('#auditlog-details-' + detailsId).addClass('hide');
mQuery(this).removeClass('active');
}
});
$icon.removeClass('ri-arrow-up-s-line').addClass('ri-arrow-down-s-line');
}
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a small optimization but just so you'd know about it. Every time you create a jQuery object it does quite an expensive operation of finding the right HTML element(s). So it's better to find it once and store it in a variable than finding it over and over.

Notice that for example mQuery('#auditlog-details-' + detailsId) could be stored into a variable and used in other places.

Copy link
Contributor

@adiux adiux Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @escopecz for pointing that out. That's a good point.

For simple stuff like selecting an element, I would even go one step further and don't use mQuery. So that we can get rid of this dependency at some point. But that might just be my point of view.

So it would be something like:
const auditlog = document.getElementById('#auditlog-details-' + detailsId);

Also just an FYI, can be ignored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excelent point!

mautic.campaign.event.create="Campaign created"
mautic.campaign.event.update="Campaign updated"
mautic.campaign.timeline.toggle_details="Toggle details."
mautic.campaign.changelog.event_removed="❌ Event Removed"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@escopecz escopecz added ready-to-commit PR's with 2 successful tests, 1 approval, automated tests and docs and is ready to be merged code-review-passed PRs which have passed code review user-testing-passed PRs which have been successfully tested by the required number of people. and removed ready-to-test PR's that are ready to test code-review-needed PR's that require a code review before merging labels Mar 28, 2025
@escopecz escopecz added this to the 7.0.0-alpha milestone Mar 28, 2025
Copy link
Member

@kuzmany kuzmany left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did basic tests and works.
Only output is bit geeky.
At least I would [] and null replace with empty string in output, to not scare basic users. Replace quotes in string output would be better too. But it couldn't be part of this PR, we can improve it later.

image

@shinde-rahul shinde-rahul moved this from 🧑🏻‍💻 Needs a code review to 🎉 Ready to commit in Open Source Fridays Apr 4, 2025
@escopecz escopecz merged commit f9161d0 into mautic:7.x Apr 9, 2025
15 checks passed
@github-project-automation github-project-automation bot moved this from 🎉 Ready to commit to 🥳 Done in Open Source Fridays Apr 9, 2025
@levente999
Copy link
Contributor

Hi @shinde-rahul
I found an issue when update the campaign event.
image

This is current audit log data:
125 1 Admin Mautic campaign campaign 3 update a:1:{s:6:"events";a:1:{s:5:"added";a:1:{s:43:"newe67902939b77ecffc7dfedbeb4f357f10170c6c2";a:2:{i:0;s:43:"newe67902939b77ecffc7dfedbeb4f357f10170c6c2";i:1;a:8:{s:4:"name";a:2:{i:0;N;i:1;s:4:"test";}s:11:"triggerMode";a:2:{i:0;N;i:1;s:9:"immediate";}s:15:"triggerInterval";a:2:{i:0;i:0;i:1;i:1;}s:19:"triggerIntervalUnit";a:2:{i:0;N;i:1;s:1:"d";}s:10:"properties";a:2:{i:0;a:0:{}i:1;a:21:{s:14:"canvasSettings";a:2:{s:8:"droppedX";s:2:"10";s:8:"droppedY";s:3:"263";}s:4:"name";s:4:"test";s:11:"triggerMode";s:9:"immediate";s:11:"triggerDate";N;s:15:"triggerInterval";s:1:"1";s:19:"triggerIntervalUnit";s:1:"d";s:11:"triggerHour";s:0:"";s:26:"triggerRestrictedStartHour";s:0:"";s:25:"triggerRestrictedStopHour";s:0:"";s:13:"triggerWindow";s:1:"0";s:6:"anchor";s:10:"leadsource";s:10:"properties";a:3:{s:8:"operator";s:1:"=";s:5:"score";s:4:"1111";s:5:"group";s:1:"1";}s:4:"type";s:11:"lead.points";s:9:"eventType";s:9:"condition";s:15:"anchorEventType";s:6:"source";s:10:"campaignId";s:1:"3";s:6:"_token";s:116:"91d612e76a6bf.bDrd_GtYJSCQAa8oNqzeGhljlPlKZ9gy66WBo3Qer08.P3fslyUdZE3IQOZeR_2MWXsbwLtzNqBCk8u56DNE7g49CIfRPDZERvVmyA";s:7:"buttons";a:1:{s:4:"save";s:0:"";}s:8:"operator";s:1:"=";s:5:"score";i:1111;s:5:"group";i:1;}}s:4:"type";a:2:{i:0;N;i:1;s:11:"lead.points";}s:9:"eventType";a:2:{i:0;N;i:1;s:9:"condition";}s:6:"tempId";a:2:{i:0;N;i:1;s:43:"newe67902939b77ecffc7dfedbeb4f357f10170c6c2";}}}}}}

126 1 Admin Mautic form form 1 update a:6:{s:4:"name";a:2:{i:0;N;i:1;s:9:"test form";}s:7:"noIndex";a:2:{i:0;N;i:1;b:0;}s:10:"postAction";a:2:{i:0;s:7:"message";i:1;s:6:"return";}s:6:"fields";a:1:{s:43:"new064002cb3e22524fe280a7e35892c22eff5bfd7f";a:5:{s:5:"label";a:2:{i:0;N;i:1;s:6:"Submit";}s:5:"alias";a:2:{i:0;N;i:1;s:6:"submit";}s:4:"type";a:2:{i:0;N;i:1;s:6:"button";}s:15:"inputAttributes";a:2:{i:0;N;i:1;s:21:"class="btn btn-ghost"";}s:5:"order";a:2:{i:0;i:0;i:1;i:1;}}}s:5:"alias";a:2:{i:0;N;i:1;s:9:"test_form";}s:12:"dateModified";a:2:{i:0;N;i:1;s:25:"2025-04-16T16:22:02+00:00";}}

127 1 Admin Mautic campaign campaign 3 update a:1:{s:5:"forms";a:1:{s:5:"added";a:1:{i:1;s:9:"test form";}}}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
campaigns Anything related to campaigns and campaign builder code-review-passed PRs which have passed code review developer-experience Anything related to developer experience enhancement Any improvement to an existing feature or functionality ready-to-commit PR's with 2 successful tests, 1 approval, automated tests and docs and is ready to be merged user-experience Anything related to related to workflows, feedback, and navigation user-testing-passed PRs which have been successfully tested by the required number of people.
Projects
Status: 🥳 Done
Development

Successfully merging this pull request may close these issues.

7 participants