Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
{#
Variables
- campaignSettings
- campaignId
#}
{% for eventGroup, color in {'action': 'primary', 'decision': 'success', 'condition': 'danger'} %}
<div id="{{ eventGroup|title }}GroupList" class="hide">
<h4 class="mb-xs">
<span>{{ ('mautic.campaign.event.'~eventGroup~'s.header')|trans }}</span>
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
icon: 'ri-fw ri-corner-right-up-line',
label: 'mautic.campaign.event.back_to_panel',
icon_only: true,
size: 'xs',
variant: color,
attributes: {
'class': 'pull-right mb-xs',
'type': 'button'
}
}
]
} %}
</h4>
<select id="{{ eventGroup|title }}List" class="campaign-event-selector">
<option value=""></option>
{% for k, e in eventSettings[eventGroup] %}
<option id="campaignEvent_{{ k|replace({'.': ''}) }}"
class="option_campaignEvent_{{ k|replace({'.': ''}) }}"
data-href="{{ path('mautic_campaignevent_action', {
'objectAction': 'new',
'type': k,
'eventType': eventGroup,
'campaignId': campaignId,
'anchor': '',
}) }}"
data-target="#CampaignEventModal"
data-method="POST"
title="{{ e['description']|e }}"
value="{{ k|e }}">
<span>{{ e['label'] }}</span>
</option>
{% endfor %}
</select>
</div>
{% endfor %}

View File

@@ -0,0 +1,106 @@
{#
Variables
- event
- campaignId
#}
{% set route = route|default('mautic_campaignevent_action') %}
{% set decisionTileContent %}
<h3 class="type-heading-02 mb-lg">{{ 'mautic.campaign.event.decision.header'|trans }}</h3>
<div class="type-helper-text-01 mb-32">{{ 'mautic.campaign.event.decision.descr'|trans }}</div>
{% endset %}
{% set actionTileContent %}
<h3 class="type-heading-02 mb-lg">{{ 'mautic.campaign.event.action.header'|trans }}</h3>
<div class="type-helper-text-01 mb-32">{{ 'mautic.campaign.event.action.descr'|trans }}</div>
{% endset %}
{% set conditionTileContent %}
<h3 class="type-heading-02 mb-lg">{{ 'mautic.campaign.event.condition.header'|trans }}</h3>
<div class="type-helper-text-01 mb-32">{{ 'mautic.campaign.event.condition.descr'|trans }}</div>
{% endset %}
<div class="hide" id="CampaignEventPanel">
<div id="CampaignEventPanelGroups">
<div class="row">
<div class="mr-0 ml-0 pl-xs pr-xs campaign-group-container col-md-4" id="DecisionGroupSelector">
{% include '@MauticCore/Components/tile.html.twig' with {
'type': 'clickable',
'content': decisionTileContent,
'icon': 'ri-node-tree',
'attributes': {
'data-type': 'Decision'
}
} %}
</div>
<div class="mr-0 ml-0 pl-xs pr-xs campaign-group-container col-md-4" id="ActionGroupSelector">
{% include '@MauticCore/Components/tile.html.twig' with {
'type': 'clickable',
'content': actionTileContent,
'icon': 'ri-function-add-line',
'attributes': {
'data-type': 'Action'
}
} %}
</div>
<div class="mr-0 ml-0 pl-xs pr-xs campaign-group-container col-md-4" id="ConditionGroupSelector">
{% include '@MauticCore/Components/tile.html.twig' with {
'type': 'clickable',
'content': conditionTileContent,
'icon': 'ri-filter-3-line',
'attributes': {
'data-type': 'Condition'
}
} %}
</div>
</div>
<div class="row">
<div class="mr-0 ml-0 pl-xs pr-xs mt-xs campaign-group-container col-md-12">
<div id="CampaignPasteContainer" class="panel mb-0">
<div id="CampaignPasteDescription" class="panel-body">
<div><b>{{ 'mautic.campaign.event.clone.header'|trans }}</b></div>
<div><span class="text-secondary">{{ 'mautic.campaign.event.clone.name'|trans }}: </span><span data-campaign-event-clone="sourceEventName"></span></div>
<div><span class="text-secondary">{{ 'mautic.campaign.event.clone.from'|trans }}: </span><span data-campaign-event-clone="sourceCampaignName"></span></div>
</div>
<div class="panel-footer">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.campaign.event.clone.insert',
size: 'md',
href: path(route, {
'objectAction': 'insert',
'campaignId': campaignId,
'anchor': 'none',
'anchorEventType': 'none'
}),
variant: 'ghost',
attributes: {
'id': 'EventInsertButton',
'data-toggle': 'ajax',
'data-target': 'CampaignEvent_',
'data-ignore-formexit': 'true',
'data-method': 'POST',
'data-hide-loadingbar': 'true'
}
}
]
} %}
</div>
</div>
</div>
</div>
</div>
<div id="CampaignEventPanelLists" class="hide">
{{- include('@MauticCampaign/Campaign/Builder/_source_list.html.twig', {
'campaignSources': campaignSources,
'campaignId': campaignId,
}) -}}
{{- include('@MauticCampaign/Campaign/Builder/_event_list.html.twig', {
'eventSettings': eventSettings,
'campaignId': campaignId,
}) -}}
</div>
</div>
<div class="clearfix"></div>

View File

@@ -0,0 +1,24 @@
{#
Variables
- campaignSources
- campaignId
#}
<div id="SourceGroupList" class="hide">
<h4 class="mb-xs">
<span>{{ 'mautic.campaign.leadsource.header'|trans }}</span>
</h4>
<select id="SourceList" class="campaign-event-selector">
<option value=""></option>
{% for option in ['lists', 'forms'] %}
<option id="campaignLeadSource_{{ option }}"
class="option_campaignLeadSource_{{ option }}"
data-href="{{ path('mautic_campaignsource_action', {'objectAction': 'new', 'objectId': campaignId, 'sourceType': option}) }}"
data-target="#CampaignEventModal"
title="{{ ('mautic.campaign.leadsource.'~option~'.tooltip')|trans|e }}"
value="{{ option|e }}"
{% if campaignSources[option] is defined %}disabled{% endif %}>
<span>{{ ('mautic.campaign.leadsource.'~option)|trans }}</span>
</option>
{% endfor %}
</select>
</div>

View File

@@ -0,0 +1,128 @@
<div class="table-responsive campaign-changelog">
<ul class="media-list media-list-feed">
<li class="media">
<!-- Changelog : Events -->
{% if details.events is defined %}
{% set changeSet = details.events %}
{% if changeSet.removed is defined %}
{% set key = changeSet.removed|keys|first %}
<div class="table-caption text-danger">
<strong>{{ 'mautic.campaign.changelog.event_removed'|trans }}</strong><br>
{{ 'mautic.campaign.changelog.event_removed_details'|trans({
'%event_name%': changeSet.removed[key],
'%event_id%': key
}) }}
</div>
{% endif %}
{% if changeSet.added is defined %}
{% for key, change in changeSet.added %}
{% set subChanges = change[1] %}
{% if subChanges is iterable %}
<div class="table-wrapper media-body">
<table class="table table-striped table-bordered">
<caption class="table-caption text-success">
<strong>{{ 'mautic.campaign.changelog.event_updated'|trans }}</strong><br>
{{ 'mautic.campaign.changelog.event_updated_details'|trans({
'%event_id%': key
}) }}
</caption>
<thead class="thead-dark">
<tr>
<th>{{ 'mautic.lead.audit.log.field'|trans }}</th>
<th>{{ 'mautic.lead.audit.log.old_value'|trans }}</th>
<th>{{ 'mautic.lead.audit.log.new_value'|trans }}</th>
</tr>
</thead>
<tbody>
{% for subKey, subChange in subChanges %}
<tr>
<td>{{ subKey }}</td>
<td>
<pre
class="text-muted">{{ subChange[0] is same as([]) or subChange[0] is null ? '""' : subChange[0]|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
</td>
<td>
<pre
class="text-muted">{{ subChange[1] is same as([]) or subChange[1] is null ? '' : subChange[1]|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<hr />
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
<!-- Changelog : Events Ends -->
<!-- Changelog : Source list -->
{% set sourceDetails = details|filter((value, key) => key == 'lists') %}
{% if sourceDetails is not empty and sourceDetails.lists is defined %}
<div class="table-wrapper media-body">
<table class="table table-striped table-bordered">
<caption class="table-caption text-success">
<strong>{{ 'mautic.campaign.changelog.source.updated'|trans }}</strong>
</caption>
<thead class="thead-dark">
<tr>
<th>{{ 'mautic.lead.audit.log.field'|trans }}</th>
<th>{{ 'mautic.lead.audit.log.new_value'|trans }}</th>
</tr>
</thead>
<tbody>
{% set listsUpdates = sourceDetails.lists %}
{% for key, value in listsUpdates %}
<tr>
<td>{{ 'mautic.campaign.leadsource.header'|trans }} - {{ key|capitalize }}</td>
<td>
{{ value|json_encode(constant('JSON_PRETTY_PRINT')) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<hr />
{% endif %}
<!-- Changelog : Source list end -->
<!-- Changelog : Rest of the meta -->
{% set filteredDetails = details|filter((value, key) => key != 'events' and key != 'lists') %}
{% if filteredDetails is not empty %}
<div class="table-wrapper media-body">
<table class="table table-striped table-bordered">
<caption class="table-caption text-success">
<strong>{{ 'mautic.campaign.changelog.settings_updated'|trans }}</strong>
</caption>
<thead class="thead-dark">
<tr>
<th>{{ 'mautic.lead.audit.log.field'|trans }}</th>
<th>{{ 'mautic.lead.audit.log.old_value'|trans }}</th>
<th>{{ 'mautic.lead.audit.log.new_value'|trans }}</th>
</tr>
</thead>
<tbody>
{% for key, value in filteredDetails %}
{% if key != 'events' and value[0] is defined and value[1] is defined %}
<tr>
<td>{{ key }}</td>
<td>
<pre class="text-muted">{{ value[0]|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
</td>
<td>
<pre class="text-muted">{{ value[1]|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
<hr />
{% endif %}
<!-- Changelog : Rest of the meta End-->
</li>
</ul>
</div>

View File

@@ -0,0 +1,5 @@
<li class="">
<a href="#recent-activity-container" role="tab" data-toggle="tab">
{{ 'mautic.core.audit_log'|trans }}
</a>
</li>

View File

@@ -0,0 +1,68 @@
<div class="tab-pane fade in bdr-w-0 page-list" id="recent-activity-container">
<!-- auditlog -->
<div class="table-responsive">
<table class="table table-hover" id="campaign-auditlog">
<tr>
<th class="timeline-icon np"></th>
<th class="table-expand np">
<a class="table-expand-button" data-activate-details="all" data-toggle="tooltip" title="{{ 'mautic.lead.timeline.toggle_details'|trans }}">
<span class="ri-arrow-down-s-line"></span>
</a>
</th>
{{ include('@MauticCore/Helper/tableheader.html.twig', {
'text': 'mautic.campaign.timeline.user_name',
'class': 'timeline-name',
'target': '#recent-activity-container',
}) }}
{{ include('@MauticCore/Helper/tableheader.html.twig', {
'text': 'mautic.audit_log.report.action',
'class': 'visible-md visible-lg timeline-type',
'target': '#recent-activity-container',
}) }}
{{ include('@MauticCore/Helper/tableheader.html.twig', {
'text': 'mautic.lead.timeline.event_timestamp',
'class': 'visible-md visible-lg timeline-timestamp',
'target': '#recent-activity-container',
}) }}
</tr>
<tbody>
{% for log in logs %}
{% set counter = loop.index0 + 1 %}
{% set icon = 'ri-history-line' %}
{% if log.action == 'create' %}
{% set icon = 'ri-check-line' %}
{% endif %}
{% set rowStripe = cycle(['', 'timeline-row-highlighted'], loop.index0) %}
<tr class="timeline-row {{ rowStripe }}">
<td class="timeline-icon np">
<span class="fa ri-fw {{ icon }}"></span>
</td>
<td class="table-expand np">
{% if log.action != 'create' %}
<a href="javascript:void(0);"
data-activate-details="{{ counter }}"
class="table-expand-button"
data-toggle="tooltip"
title="{{ 'mautic.lead.timeline.toggle_details'|trans }}">
<span class="ri-arrow-down-s-line"></span>
</a>
{% endif %}
</td>
<td class="timeline-name">{{ log.userName }}</td>
<td class="timeline-type">{{ ('mautic.campaign.event.'~log.action)|trans }}
</td>
<td class="timeline-timestamp">{{ dateToText(log.dateAdded, 'local', 'Y-m-d H:i:s', true) }}</td>
</tr>
{% if log.action != 'create' %}
<tr class="timeline-row {{ rowStripe }} timeline-details hide" id="auditlog-details-{{ counter }}">
<td colspan="5">
{{- include('@MauticCampaign/Campaign/Tab/_details.html.twig', {'details': log.details|default({})}) -}}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,106 @@
{#
Variables
- campaignId
- campaignEvents
- campaignSources
- campaignElements
- eventSettings
- canvasSettings
#}
<div id="campaign-builder" class="hide builder campaign-builder live animation--slide-in-down">
<div id="builder-errors" class="alert alert-danger" role="alert" style="display: none;">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true"><i class="fa fa-times"></i></button>
<span></span>
</div>
{% include '@MauticCore/Components/uishell.html.twig' with {
Header: {
ariaLabel: 'mautic.campaign.builder',
children: {
HeaderName: {
prefix: entity.name is empty ? '' : 'mautic.campaign.campaign',
children: entity.name|default('mautic.campaign.unsaved'),
},
HeaderGlobal: {
children: [
{
HeaderGlobalAction: {
ariaLabel: 'mautic.core.form.apply',
onClick: 'Mautic.saveCampaignFromBuilder();',
renderActionIcon: 'ri-save-line',
}
},
{
HeaderGlobalAction: {
ariaLabel: 'mautic.core.close.builder',
onClick: 'Mautic.closeCampaignBuilder();',
renderActionIcon: 'ri-close-line',
}
}
]
}
}
}
} %}
<div class="builder-content">
<div id="CampaignCanvas">
<div id="CampaignEvent_newsource{% if campaignSources is defined and campaignSources is not empty %}_hide{% endif %}" class="text-center list-campaign-source list-campaign-leadsource">
<div class="campaign-event-content">
<div>
<span class="campaign-event-name ellipsis">
<i class="mr-sm ri-team-line"></i> {{ 'mautic.campaign.add_new_source'|trans }}
</span>
</div>
</div>
</div>
{% for source in campaignSources %}
{{- include('@MauticCampaign/Source/_index.html.twig', {
'sourceType': source.sourceType,
'names': source.names,
'campaignId': source.campaignId,
}) -}}
{% endfor %}
{% for event in campaignEvents %}
{% if event.deleted|default(null) is empty %}
{% set settings = eventSettings[event.eventType][event.type]|default(null) %}
{{- include(settings['template']|default('@MauticCampaign/Event/_generic.html.twig'), {
'event': event,
'campaignId': campaignId,
}) -}}
{% endif %}
{% endfor %}
{{- include('@MauticCampaign/Campaign/Builder/_index.html.twig', {
'campaignSources': campaignSources,
'eventSettings': eventSettings,
'campaignId': campaignId,
}) -}}
</div>
<div id="EventJumpOverlay"></div>
</div>
</div>
<!-- dropped coordinates -->
<input type="hidden" value="" id="droppedX"/>
<input type="hidden" value="" id="droppedY"/>
<input type="hidden" value="{{ campaignId|e }}" id="campaignId"/>
{{- include('@MauticCore/Helper/modal.html.twig', {
'id': 'CampaignEventModal',
'header': false,
'footerButtons': true,
'dismissible': false,
}) -}}
<script>
/**
* We typecast to object here so that an empty value will
* be encoded to {} instead of []. Adding JSON_FORCE_OBJECT
* is not an option because it does a deep transform to
* object, whereas typecasting only does the first level.
*/
Mautic.campaignBuilderCampaignElements = {% if campaignElements is not empty %}{{ campaignElements|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderCanvasSettings = {% if canvasSettings is not empty %}{{ canvasSettings|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderCanvasSources = {% if campaignSources is not empty %}{{ campaignSources|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderCanvasEvents = {% if campaignEvents is not empty %}{{ campaignEvents|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderConnectionRestrictions = {% if eventSettings['connectionRestrictions'] is not empty %}{{ eventSettings['connectionRestrictions']|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderHasEventClone = {% if hasEventClone %}true{% else %}false{% endif %};
</script>

View File

@@ -0,0 +1,50 @@
{#
Variables
- events
#}
{% if events is not empty and events is iterable %}
<!-- start: trigger type event -->
<ul class="campaign-event-list">
{% for event in events %}
{% set typeClass = ('action' == event.eventType and 'no' == event.decisionPath) ? 'danger' : 'success' %}
{% set percentLabel = ('danger' == typeClass) ? 'mautic.report.campaign.no.percent' : 'mautic.report.campaign.yes.percent' %}
{% set percentProp = ('danger' == typeClass) ? 'noPercent' : 'yesPercent' %}
<li class="list-group-item">
<div class="progress-bar progress-bar-{{ typeClass }}" style="width:{{ event.yesPercent }}%; left: 0;"></div>
<div class="progress-bar progress-bar-danger" style="width:{{ event['noPercent'] }}%; left: {{ event['yesPercent'] }}%"></div>
<div class="box-layout">
<div class="visible-sm visible-md visible-lg col-stats">
<span class="mt-xs label label-{{ typeClass }}" data-toggle="tooltip" title="{{ percentLabel|trans }}">
{{ event[percentProp] }}%
</span>
{% if event.eventType is defined and 'action' != event.eventType %}
<span class="label label-danger" data-toggle="tooltip" title="{{ 'mautic.report.campaign.no.percent'|trans }}">
{{ event.noPercent }}%
</span>
{% endif %}
<span class="mt-xs label label-warning" data-toggle="tooltip" title="{{ 'mautic.report.campaign.completed.actions'|trans }}">
{{ event.logCountProcessed }}
</span>
<span size="sm" class="mt-xs label label-gray" data-toggle="tooltip" title="{{ 'mautic.report.campaign.pending.actions'|trans }}">
{{ event.logCountForPending }}
</span>
</div>
<div class="col-md-5 va-m">
<h5 class="fw-sb text-interactive mb-xs">
{{ event.name }}
{% if event.eventType is defined and 'action' != event.eventType %}
<small class="text-secondary">{{ event.percent }}%</small>
{% endif %}
</h5>
<h6 class="text-white dark-sm">{{ event.description }}</h6>
</div>
<div class="col-md-3 va-m text-right">
<em class="text-white dark-sm">{{ ('mautic.campaign.'~event.type)|trans }}</em>
</div>
</div>
</li>
{% endfor %}
</ul>
<!--/ end: trigger type event -->
{% endif %}

View File

@@ -0,0 +1,77 @@
{#
Variables
- campaign
- campaignId
- campaignEvents
- campaignSources
- eventSettings
- canvasSettings
#}
<div id="campaign-builder" class="builder campaign-builder preview">
<div class="builder-content">
<div id="CampaignCanvas">
<div id="CampaignEvent_newsource{% if campaignSources is not empty %}_hide{% endif %}" class="text-center list-campaign-source list-campaign-leadsource">
<div class="campaign-event-content">
<div>
<span class="campaign-event-name ellipsis">
<i class="mr-sm ri-team-line"></i> {{'mautic.campaign.add_new_source'|trans }}
</span>
</div>
</div>
</div>
{% if campaign.forms|length %}
{% set names = [] %}
{% for form in campaign.forms.toArray %}
{% set names = names + [form.name] %}
{% endfor %}
{{- include('@MauticCampaign/Source/_index.html.twig', {
'sourceType': 'forms',
'campaignId': campaign.id,
'names': names|join(', '),
}) -}}
{% endif %}
{% if campaign.lists|length %}
{% set names = [] %}
{% for list in campaign.lists.toArray %}
{% set names = names + [list.name] %}
{% endfor %}
{{- include('@MauticCampaign/Source/_index.html.twig', {
'sourceType': 'lists',
'campaignId': campaign.id,
'names': names|join(', '),
}) -}}
{% endif %}
{% for event in campaignEvents %}
{{- include('@MauticCampaign/Event/_preview.html.twig', {
'event': event,
'campaignId': campaign.id,
}) -}}
{% endfor %}
{{- include('@MauticCampaign/Campaign/Builder/_index.html.twig', {
'campaignSources': campaignSources,
'eventSettings': eventSettings,
'campaignId': campaign.id,
}) -}}
</div>
</div>
</div>
<!-- dropped coordinates -->
<input type="hidden" value="" id="droppedX"/>
<input type="hidden" value="" id="droppedY"/>
<input type="hidden" value="{{ campaign.id|e }}" id="campaignId"/>
{{- include('@MauticCore/Helper/modal.html.twig', {
'id': 'CampaignEventModal',
'header': false,
'footerButtons': true,
'dismissible': false,
}) -}}
<script>
Mautic.campaignBuilderCanvasSettings = {% if canvasSettings is not empty %}{{ canvasSettings|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderCanvasSources = {% if campaignSources is not empty %}{{ campaignSources|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderCanvasEvents = {% if campaignEvents is not empty %}{{ campaignEvents|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
Mautic.campaignBuilderConnectionRestrictions = {% if eventSettings['connectionRestrictions'] is not empty %}{{ eventSettings['connectionRestrictions']|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}{% else %}{}{% endif %};
</script>

View File

@@ -0,0 +1,275 @@
{% extends '@MauticCore/Default/content.html.twig' %}
{% block preHeader %}
{{- include('@MauticCore/Helper/page_actions.html.twig', {
'item': campaign,
'templateButtons': {
'close': securityHasEntityAccess(
permissions['campaign:campaigns:viewown'],
permissions['campaign:campaigns:viewother'],
campaign.createdBy
),
},
'routeBase': 'campaign',
'targetLabel': 'mautic.campaign.campaigns'|trans
}) -}}
{{ include('@MauticCore/Modules/category--inline.html.twig', {'category': campaign.category}) }}
{{ include('@MauticProject/Modules/projects.html.twig', {'item': campaign}) }}
{% endblock %}
{% block headerTitle %}{{ campaign.name }}{% endblock %}
{% block actions %}
{% set buttons = [] %}
{% if securityHasEntityAccess(permissions['campaign:campaigns:viewown'], permissions['campaign:campaigns:viewother'], campaign.createdBy) and enableExportPermission is not empty%}
{% set buttons = buttons|merge([{
'attr': {
'data-toggle': 'download',
'href': path('mautic_campaign_action', {'objectAction': 'export', 'objectId': campaign.id}),
},
'btnText': 'mautic.core.export'|trans,
'iconClass': 'ri-export-line',
}]) %}
{% endif %}
{{- include('@MauticCore/Helper/page_actions.html.twig', {
'item': campaign,
'customButtons': buttons,
'templateButtons': {
'edit': securityHasEntityAccess(
permissions['campaign:campaigns:editown'],
permissions['campaign:campaigns:editother'],
campaign.createdBy
),
'clone': permissions['campaign:campaigns:create'],
'delete': securityHasEntityAccess(
permissions['campaign:campaigns:deleteown'],
permissions['campaign:campaigns:deleteother'],
campaign.createdBy
),
},
'routeBase': 'campaign',
}) -}}
{% endblock %}
{% block publishStatus %}
{{ include('@MauticCore/Helper/publishstatus_badge.html.twig', {'entity': campaign}) }}
<div class="label__divider"></div>
{% if campaign.allowRestart is defined and campaign.allowRestart == 1 %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
tags: [{
label: 'mautic.campaign.allow_restart'|trans,
icon: 'ri-restart-fill',
color: 'blue',
icon_only: true
}]
} %}
{% endif %}
{% endblock %}
{% block content %}
<!-- start: box layout -->
<div class="box-layout">
<!-- left section -->
<div class="col-md-9 height-auto">
<div>
<!-- campaign detail header -->
{% include '@MauticCore/Helper/description--expanded.html.twig' with {'description': campaign.description} %}
<!--/ campaign detail header -->
<!-- campaign detail collapseable -->
<div class="collapse pr-md pl-md" id="campaign-details">
<div class="pr-md pl-md pb-md">
<div class="panel shd-none mb-0">
<table class="table table-hover mb-0">
<tbody>
{{ include('@MauticCore/Helper/details.html.twig', {'entity': campaign}) }}
{% for sourceType, typeNames in sources %}
{% if typeNames is not empty %}
<tr>
<td width="20%"><span class="fw-b textTitle">
{{ ('mautic.campaign.leadsource.'~sourceType)|trans }}
</td>
<td>
{{ typeNames|join(', ') }}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!--/ campaign detail collapseable -->
</div>
<div>
<!-- campaign detail collapseable toggler -->
<div class="hr-expand nm">
<span data-toggle="tooltip" title="Detail">
<a href="javascript:void(0)" class="arrow text-secondary collapsed" data-toggle="collapse"
data-target="#campaign-details"><span
class="caret"></span> {{ 'mautic.core.details'|trans }}</a>
</span>
</div>
<!--/ campaign detail collapseable toggler -->
{{ customContent('left.section.top', _context) }}
{% set dateFrom = dateRangeForm.children['date_from'].vars['data'] %}
{% set dateTo = dateRangeForm.children['date_to'].vars['data'] %}
<!-- some stats -->
<div class="stats-menu pl-md mt-lg">
<!-- tabs controls -->
<ul class="nav nav-tabs nav-tabs-contained">
<li class="active">
<a href="#stats-container" role="tab" data-toggle="tab">
{{ 'mautic.campaign.stats'|trans }}
</a>
</li>
{% if showEmailStats|default(false) %}
<li>
<a href="#campaign-email-stats" role="tab" data-toggle="tab" data-load="campaign-email-stats">
{{ 'mautic.campaign.email_stats'|trans }}
</a>
</li>
{% endif %}
<li>
<a href="#reads-map-container" role="tab" data-toggle="tab" data-load="map">
{{ 'mautic.email.thead.maps'|trans }}
</a>
</li>
</ul>
<!--/ tabs controls -->
<div class="date-range">
{{ include('@MauticCore/Helper/graph_dateselect.html.twig', {
'dateRangeForm': dateRangeForm,
}) }}
</div>
</div>
<div class="stats-menu__content tab-content pa-md mb-lg shd-sm">
<div class="tab-pane active bdr-w-0" id="stats-container">
<div id="campaign-graph-div" data-target-url="{{ path('mautic_campaign_graph', {'objectId' : campaign.id, 'dateFrom' : dateFrom|date('Y-m-d'), 'dateTo' : dateTo|date('Y-m-d')}) }}">
<div class="spinner"><i class="fa fa-spin fa-spinner"></i></div>
<div class="clearfix"></div>
</div>
</div>
<div class="tab-pane bdr-w-0" id="reads-map-container"
data-map-url="{{ path('mautic_campaign_map_stats', {'objectId' : campaign.id, 'dateFrom' : dateFrom|date('Y-m-d'), 'dateTo' : dateTo|date('Y-m-d')}) }}">
<div class="spinner">
<i class="ri-loader-3-line ri-spin"></i>
</div>
</div>
{% if showEmailStats|default(false) %}
<div class="tab-pane bdr-w-0" id="campaign-email-stats">
<div class="row">
<div class="col-md-6">
<h4 class="text-muted ml-20 mb-md">{{ 'mautic.campaign.email_stats.weekday' | trans }}</h4>
<div data-campaign-email-stats-weekdays="{{ path('mautic_campaign_metrics_email_weekdays', {'objectId' : campaign.id, 'dateFrom' : dateFrom|date('Y-m-d'), 'dateTo' : dateTo|date('Y-m-d')}) }}">
<div class="d-flex jc-center ai-center">
<div class="spinner fs-42">
<i class="ri-loader-3-line ri-spin"></i>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<h4 class="text-muted ml-20 mb-md">{{ 'mautic.campaign.email_stats.hour' | trans }}</h4>
<div data-campaign-email-stats-hours="{{ path('mautic_campaign_metrics_email_hours', {'objectId' : campaign.id, 'dateFrom' : dateFrom|date('Y-m-d'), 'dateTo' : dateTo|date('Y-m-d')}) }}">
<div class="d-flex jc-center ai-center">
<div class="spinner fs-42">
<i class="ri-loader-3-line ri-spin"></i>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>
<!--/ stats -->
{{ customContent('details.stats.graph.below', _context) }}
<!-- tabs controls -->
<ul class="nav nav-tabs nav-tabs-contained" id="campaign_nav_header_ul">
<li class="active" id="preview_li">
<a href="#preview-container" role="tab" data-toggle="tab">
{{ 'mautic.campaign.preview.header'|trans }}
</a>
</li>
<li class="" id="decisions_li">
<a href="#decisions-container" role="tab" data-toggle="tab">
{{ 'mautic.campaign.event.decisions.header'|trans }}
</a>
</li>
<li class="" id="actions_li">
<a href="#actions-container" role="tab" data-toggle="tab">
{{ 'mautic.campaign.event.actions.header'|trans }}
</a>
</li>
<li class="" id="conditions_li">
<a href="#conditions-container" role="tab" data-toggle="tab">
{{ 'mautic.campaign.event.conditions.header'|trans }}
</a>
</li>
<li class="">
<a href="#leads-container" role="tab" data-toggle="tab">
{{ 'mautic.lead.leads'|trans }}
</a>
</li>
{{ customContent('tabs', _context) }}
</ul>
<!--/ tabs controls -->
</div>
<!-- start: tab-content -->
<div class="tab-content pa-md" id="campaign-tab-content"
data-event-target-url="{{ path('mautic_campaign_event_stats', {'objectId' : campaign.id, 'dateFromValue' : dateFrom|date('Y-m-d'), 'dateToValue' : dateTo|date('Y-m-d')}) }}">
<!-- #events-container -->
<div class="active tab-pane fade in bdr-w-0" id="preview-container">
<div class="spinner"><i class="fa fa-spin fa-spinner"></i></div>
<div class="clearfix"></div>
</div>
<div class="tab-pane fade in bdr-w-0" id="decisions-container">
<div class="spinner"><i class="fa fa-spin fa-spinner"></i></div>
<div class="clearfix"></div>
</div>
<div class="tab-pane fade in bdr-w-0" id="actions-container">
<div class="spinner"><i class="fa fa-spin fa-spinner"></i></div>
<div class="clearfix"></div>
</div>
<div class="tab-pane fade in bdr-w-0" id="conditions-container">
<div class="spinner"><i class="fa fa-spin fa-spinner"></i></div>
<div class="clearfix"></div>
</div>
<!--/ #events-container -->
<div class="tab-pane fade in bdr-w-0 page-list"
id="leads-container"
data-target-url="{{ path('mautic_campaign_contacts', {'objectId': campaign.id, 'page': app.session.get('mautic.campaign.contact.page', 1)}) }}">
<div class="spinner"><i class="ri-loader-3-line ri-spin"></i></div>
<div class="clearfix"></div>
</div>
{{ customContent('tabs.content', _context) }}
</div>
<!--/ end: tab-content -->
{{ customContent('left.section.bottom', _context) }}
</div>
<!--/ left section -->
<!-- right section -->
{% set right_top = customContent('right.section.top', _context) %}
{% set right_bottom = customContent('right.section.bottom', _context) %}
{% if right_top or right_bottom %}
<div class="col-md-3 bdr-l height-auto">
{{ right_top }}
{{ right_bottom }}
</div>
{% endif %}
<!--/ right section -->
</div>
<!--/ end: box layout -->
{% endblock %}

View File

@@ -0,0 +1,58 @@
{% extends '@MauticCore/Default/content.html.twig' %}
{% block headerTitle %}
{% if entity.id %}
{{ 'mautic.campaign.menu.edit'|trans({
'%name%': entity.name|trans,
}) }}
{% else %}
{{ 'mautic.campaign.menu.new'|trans }}
{% endif %}
{% endblock %}
{% block content %}
{{ form_start(form) }}
<!-- start: box layout -->
<div class="box-layout">
<!-- container -->
<div class="col-md-9 height-auto bdr-r">
<div class="pa-md">
{% if entity.id and entity.isPublished %}
<div class="alert alert-danger"><p>{{ 'mautic.campaign.modify.warning'|trans }}</p></div>
{% endif %}
<div class="row">
<div class="col-md-6">
{{ form_row(form.name) }}
</div>
</div>
<div class="row">
<div class="col-md-12">
{{ form_row(form.description) }}
</div>
</div>
</div>
</div>
<div class="col-md-3 height-auto">
<div class="pr-lg pl-lg pt-md pb-md">
{{ form_row(form.category) }}
{{ form_row(form.projects) }}
{{ form_row(form.allowRestart) }}
{{ form_row(form.isPublished) }}
{{ form_row(form.publishUp) }}
{{ form_row(form.publishDown) }}
</div>
</div>
</div>
<input type="hidden" name="submit" value="1">
{{ form_end(form) }}
{{- include('@MauticCampaign/Campaign/_builder.html.twig', {
'campaignId': form.sessionId.vars['data'],
'campaignEvents': campaignEvents,
'campaignSources': campaignSources,
'campaignElements': campaignElements,
'eventSettings': eventSettings,
'canvasSettings': entity.canvasSettings,
}) -}}
{% endblock %}

View File

@@ -0,0 +1,7 @@
<div id="emailGraphStats" class="d-flex fd-column h-384">
{{- include('@MauticCore/Helper/chart.html.twig', {
'chartData': stats,
'chartType': 'line',
'chartHeight': 300
}) -}}
</div>

View File

@@ -0,0 +1,253 @@
{% set isIndex = tmpl == 'index' ? true : false %}
{% set tmpl = 'list' %}
{% extends isIndex ? '@MauticCore/Default/content.html.twig' : '@MauticCore/Default/raw_output.html.twig' %}
{% block headerTitle %}{{ 'mautic.campaign.campaigns'|trans }}{% endblock %}
{% block content %}
{% if isIndex %}
<div id="page-list-wrapper" class="{% if items|length > 0 or searchValue is not empty %}panel {% endif %}panel-default">
{%- set pageButtons = [] %}
{% if permissions['campaign:campaigns:create'] %}
{% if permissions['campaign:imports:create'] %}
{% set pageButtons = pageButtons|merge([
{
'attr': {
'href': path('mautic_campaign_import_action', {'objectAction': 'new'}),
'data-toggle': '0',
},
'iconClass': 'ri-import-line',
'btnText': 'mautic.campaign.campaign.import',
}
]) %}
{% endif %}
{% endif %}
{{- include('@MauticCore/Helper/list_toolbar.html.twig', {
'searchValue': searchValue,
'action': currentRoute,
'actionRoute': actionRoute,
'indexRoute': indexRoute,
'translationBase': translationBase,
'preCustomButtons': toolBarButtons|default(null),
'templateButtons': {
'delete': permissions[permissionBase~':delete'],
},
'filters': filters|default([]),
'page_actions': {
'templateButtons': {
'new': permissions['campaign:campaigns:create'],
},
'routeBase': 'campaign',
'langVar': 'campaign.campaigns',
'customButtons': pageButtons,
},
'bulk_actions': {
'routeBase': 'campaign',
'templateButtons': {
'delete': permissions['campaign:campaigns:deleteown'] or permissions['campaign:campaigns:deleteother'],
},
},
'quickFilters': [
{
'search': 'mautic.core.searchcommand.ispublished',
'label': 'mautic.core.form.active',
'tooltip': 'mautic.core.searchcommand.ispublished.description',
'icon': 'ri-check-line'
},
{
'search': 'mautic.core.searchcommand.isunpublished',
'label': 'mautic.core.form.inactive',
'tooltip': 'mautic.core.searchcommand.isunpublished.description',
'icon': 'ri-close-line'
},
{
'search': 'mautic.core.searchcommand.isuncategorized',
'label': 'mautic.core.form.uncategorized',
'tooltip': 'mautic.core.searchcommand.isuncategorized.description',
'icon': 'ri-folder-unknow-line'
},
{
'search': 'mautic.core.searchcommand.ismine',
'label': 'mautic.core.searchcommand.ismine.label',
'tooltip': 'mautic.core.searchcommand.ismine.description',
'icon': 'ri-user-line'
},
{
'search': 'mautic.campaign.campaign.searchcommand.isexpired',
'label': 'mautic.core.form.no_longer_available',
'tooltip': 'mautic.campaign.campaign.searchcommand.isexpired.description',
'icon': 'ri-time-line'
},
{
'search': 'mautic.campaign.campaign.searchcommand.ispending',
'label': 'mautic.core.form.not_yet_available',
'tooltip': 'mautic.campaign.campaign.searchcommand.ispending.description',
'icon': 'ri-timer-line'
}
]
}) -}}
<div class="page-list">
{{- customContent('content.above', _context) -}}
{% endif %}
{% if items|length > 0 %}
<div class="table-responsive">
<table class="table table-hover campaign-list" id="campaignTable">
<thead>
<tr>
{{ include('@MauticCore/Helper/tableheader.html.twig', {
'checkall': 'true',
'target': '#campaignTable',
}) }}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'c.name',
'text': 'mautic.core.name',
'class': 'col-campaign-name',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'cat.title',
'text': 'mautic.core.category',
'class': 'visible-md visible-lg col-campaign-category',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'c.dateAdded',
'text': 'mautic.lead.import.label.dateAdded',
'class': 'visible-md visible-lg col-campaign-dateAdded',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'c.dateModified',
'text': 'mautic.lead.import.label.dateModified',
'class': 'visible-md visible-lg col-campaign-dateModified',
'default': true,
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'c.createdByUser',
'text': 'mautic.core.createdby',
'class': 'visible-md visible-lg col-campaign-createdByUser',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar': 'campaign',
'orderBy': 'c.id',
'text': 'mautic.core.id',
'class': 'visible-md visible-lg col-campaign-id',
}) -}}
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>
{{- include('@MauticCore/Helper/list_actions.html.twig', {
'item': item,
'templateButtons' : {
'edit': securityHasEntityAccess(
permissions['campaign:campaigns:editown'],
permissions['campaign:campaigns:editother'],
item.createdBy
),
'clone': permissions['campaign:campaigns:create'],
'export': enableExportPermission,
'delete': securityHasEntityAccess(
permissions['campaign:campaigns:deleteown'],
permissions['campaign:campaigns:deleteother'],
item.createdBy
),
},
'routeBase': 'campaign',
}) -}}
</td>
<td>
<div>
{{ include('@MauticCore/Helper/publishstatus_icon.html.twig', {
'item': item,
'model': 'campaign',
'onclick': item.onclickMethod,
'attributes': item.dataAttributes,
'transKeys': item.translationKeysDataAttributes,
}) }}
<a href="{{ path('mautic_campaign_action', {'objectAction': 'view', 'objectId': item.id}) }}" data-toggle="ajax">
{{- item.name -}}
{{- customContent('campaign.name', _context|merge({'item': item})) -}}
</a>
{{ include('@MauticProject/Modules/projects.html.twig') }}
</div>
{{ include('@MauticCore/Helper/description--inline.html.twig', {
'description': item.description
}) }}
</td>
<td class="visible-md visible-lg">
{{ include('@MauticCore/Modules/category--expanded.html.twig', {'category': item.category}) }}
</td>
<td class="visible-md visible-lg" title="{{ item.dateAdded ? dateToFullConcat(item.dateAdded) : '' }}">
{{ item.dateAdded ? dateToDate(item.dateAdded) : '' }}
</td>
<td class="visible-md visible-lg" title="{{ item.dateModified ? dateToFullConcat(item.dateModified) : '' }}">
{{ item.dateModified ? dateToDate(item.dateModified) : '' }}
</td>
<td class="visible-md visible-lg">{{ item.createdByUser }}</td>
<td class="visible-md visible-lg">{{ item.id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="panel-footer">
{{- include('@MauticCore/Helper/pagination.html.twig', {
'totalItems': items|length,
'page': page,
'limit': limit,
'menuLinkId': 'mautic_campaign_index',
'baseUrl': path('mautic_campaign_index'),
'sessionVar': 'campaign',
}) -}}
</div>
{% else %}
{% if searchValue is not empty %}
{{- include('@MauticCore/Helper/noresults.html.twig', {'tip' : 'mautic.campaign.noresults.tip'}) -}}
{% else %}
<div class="mt-80 col-md-offset-2 col-lg-offset-3 col-md-8 col-lg-5 height-auto">
{% set childContainer %}
<div class="mt-32 mb-md">
{% include '@MauticCore/Components/pictogram.html.twig' with {
'pictogram': 'ibm--automation-platform',
'size': '80'
} %}
</div>
{% endset %}
{{ include('@MauticCore/Components/content-block.html.twig', {
heading: 'mautic.campaign.contentblock.heading',
subheading: 'mautic.campaign.contentblock.subheading',
copy: 'mautic.campaign.contentblock.copy',
childContainer: childContainer,
}) }}
</div>
{% endif %}
{% endif %}
{% if isIndex %}
{{- customContent('content.below', _context) -}}
</div>
</div>
{{ include('@MauticCore/Modules/protip.html.twig', {
tip: random(['mautic.protip.campaigns.reengagement', 'mautic.protip.campaigns.survey', 'mautic.protip.campaigns.crosssell', 'mautic.protip.campaigns.onboarding'])
}) }}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,116 @@
{#
Variables
- event
- campaignId
#}
{% set route = route|default('mautic_campaignevent_action') %}
{% if update is not defined %}
<div id="CampaignEvent_{{ event['id'] }}"
data-type="{{ event['eventType'] }}"
class="draggable list-campaign-event list-campaign-{{ event['eventType'] }}"
data-event="{{ event['type'] }}"
data-event-id="{{ event['id'] }}">
{% endif %}
<div class="campaign-event-type">
{% if event['eventType'] == 'decision' %}
<div class="campaign-event-content fw-nowrap gap-xs ai-center fd-row d-flex fg-1 pa-md">
<span class="h5 fw-b event-type-color">{{ 'mautic.campaign.when'|trans }}</span>
<span>{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name label label-info ml-5 mr-lg ellipsis">
{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}
</span>
<i class="{{ getCampaignEventIcon(event['type']) }} ri-lg ml-a campaign-event-icon event-type-color"></i>
</div>
{% elseif event['eventType'] == 'action' %}
<div class="campaign-event-content d-flex fw-nowrap ai-center gap-sm">
<div class="campaign-event-icon pa-sm mr-5"><i class="{{ getCampaignEventIcon(event['type']) }}"></i></div>
<div class="d-flex fd-column ai-start">
<span class="fs-18 fw-l">{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name ellipsis">{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}</span>
</div>
</div>
{% elseif event['eventType'] == 'condition' %}
<div class="campaign-event-content fw-nowrap gap-xs ai-center fd-row d-flex fg-1 pa-md">
<span class="h5 fw-b event-type-color">{{ 'mautic.campaign.if'|trans }}</span>
<span>{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name label label-warning ml-5 mr-lg ellipsis">
{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}
</span>
<i class="{{ getCampaignEventIcon(event['type']) }} ri-lg ml-a campaign-event-icon event-type-color"></i>
</div>
{% endif %}
</div>
{% if update is not defined %}
<div class="campaign-event-buttons hide">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
href: path(route, {
'objectAction': 'clone',
'objectId': event['id'],
'campaignId': campaignId
}),
variant: 'secondary',
icon: 'ri-file-copy-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.clone.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajax',
'data-target': 'CampaignEvent_' ~ event['id'],
'data-ignore-formexit': 'true',
'data-method': 'POST',
'data-hide-loadingbar': 'true',
'class': 'btn-clone'
}
},
{
href: path(route, {
'objectAction': 'edit',
'objectId': event['id'],
'campaignId': campaignId
}),
variant: 'secondary',
icon: 'ri-pencil-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.edit.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajaxmodal',
'data-prevent-dismiss': 'true',
'data-target': '#CampaignEventModal',
'data-method': 'POST',
'class': 'btn-edit'
}
},
{
href: path(route, {
'objectAction': 'delete',
'objectId': event['id'],
'campaignId': campaignId
}),
variant: 'primary',
icon: 'ri-delete-bin-line',
size: 'xs',
danger: true,
icon_only: true,
label: 'mautic.campaign.event.remove.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajax-delete',
'data-target': 'CampaignEvent_' ~ event['id'],
'data-ignore-formexit': 'true',
'data-method': 'POST',
'data-hide-loadingbar': 'true',
'class': 'btn-delete'
}
}
]
} %}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,93 @@
{#
Variables
- event
- campaignId
#}
{% if route is not defined or route is empty %}
{% set route = 'mautic_campaignevent_action' %}
{% endif %}
{% set eventType = event['eventType'] %}
{% set eventLogic = '' %}
{# Show ID in dev mode to help with debugging #}
{% set eventName = ('dev' == constant('MAUTIC_ENV')) ? event['name']~' <small>'~event.id~'</small>' : event['name'] %}
{% if update is not defined or update is empty %}
<div id="CampaignEvent_{{ event['id'] }}"
data-type="{{ event['eventType'] }}"
class="draggable list-campaign-event list-campaign-{{ event['eventType'] }}"
data-event="{{ event['type'] }}"
data-event-id="{{ event['id'] }}"
data-event-yes-percent="{{ event['yesPercent'] }}"
data-event-no-percent="{{ event['noPercent'] }}">
{% endif %}
<div class="campaign-event-type">
{% if event['eventType'] == 'decision' %}
<div class="campaign-event-content fw-nowrap gap-xs ai-center fd-row d-flex fg-1 pa-sm">
<span class="h5 fw-b event-type-color">{{ 'mautic.campaign.when'|trans }}</span>
<span>{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name label label-info ml-5 mr-5 ellipsis">
{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}
</span>
<i class="{{ getCampaignEventIcon(event['type']) }} ri-lg ml-a campaign-event-icon event-type-color"></i>
<div class="campaign-event-stat pa-4">
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.completed.actions'|trans }}"><span class="ri-check-line"></span> {{ event.logCountProcessed }}</span>
{% if (event.logCountForPending) %}
<span class="campaign-event-stat-divider">|</span>
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.pending.actions'|trans }}"><span class="ri-hourglass-line"></span> {{ event.logCountForPending }}</span>
{% endif %}
</div>
</div>
{% elseif event['eventType'] == 'action' %}
<div class="campaign-event-content d-flex fw-nowrap ai-center gap-sm">
<div class="campaign-event-icon pa-sm mr-5"><i class="{{ getCampaignEventIcon(event['type']) }}"></i></div>
<div class="d-flex fd-column ai-start">
<span class="fs-18 fw-l">{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name ellipsis">{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}</span>
</div>
<div class="campaign-event-stat pa-4">
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.completed.actions'|trans }}"><span class="ri-check-line"></span> {{ event.logCountProcessed }}</span>
{% if (event.logCountForPending) %}
<span class="campaign-event-stat-divider">|</span>
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.pending.actions'|trans }}"><span class="ri-hourglass-line"></span> {{ event.logCountForPending }}</span>
{% endif %}
</div>
</div>
{% elseif event['eventType'] == 'condition' %}
<div class="campaign-event-content fw-nowrap gap-xs ai-center fd-row d-flex fg-1 pa-sm">
<span class="h5 fw-b event-type-color">{{ 'mautic.campaign.if'|trans }}</span>
<span>{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name label label-warning ml-5 mr-5 ellipsis">
{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}
</span>
<i class="{{ getCampaignEventIcon(event['type']) }} ri-lg ml-a campaign-event-icon event-type-color"></i>
<div class="campaign-event-stat pa-4">
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.completed.actions'|trans }}"><span class="ri-check-line"></span> {{ event.logCountProcessed }}</span>
{% if (event.logCountForPending) %}
<span class="campaign-event-stat-divider">|</span>
<span data-toggle="tooltip" title="{{ 'mautic.report.campaign.pending.actions'|trans }}"><span class="ri-hourglass-line"></span> {{ event.logCountForPending }}</span>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% if update is not defined %}
<div class="campaign-event-buttons hide">
<a data-toggle="ajax" data-target="CampaignEvent_{{ event['id'] }}" data-ignore-formexit="true" data-method="POST" data-hide-loadingbar="true" href="{{ path(route, {'objectAction': 'clone', 'objectId': event['id'], 'campaignId': campaignId}) }}" class="btn btn-secondary btn-clone btn-xs" title="{{ 'mautic.campaign.event.clone.btn.tooltip'|trans }}">
<i class="ri-file-copy-line"></i>
</a>
<a data-toggle="ajaxmodal" data-prevent-dismiss="true" data-target="#CampaignEventModal" data-method="POST" href="{{ path(route, {'objectAction': 'edit', 'objectId': event['id'], 'campaignId': campaignId}) }}" class="btn btn-secondary btn-xs btn-edit" title="{{ 'mautic.campaign.event.edit.btn.tooltip'|trans }}">
<i class="ri-pencil-line"></i>
</a>
<a data-toggle="ajax-delete" data-target="CampaignEvent_{{ event['id'] }}" data-ignore-formexit="true" data-method="POST" data-hide-loadingbar="true" href="{{ path(route, {'objectAction': 'delete', 'objectId': event['id'], 'campaignId': campaignId}) }}" class="btn btn-delete btn-danger btn-xs" title="{{ 'mautic.campaign.event.remove.btn.tooltip'|trans }}">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,116 @@
{#
Variables
- form
#}
{% form_theme form with [
'@MauticCampaign/FormTheme/Event/_campaignevent_properties_row.html.twig',
] %}
{% if formTheme is defined %}
{% form_theme form formTheme %}
{% endif %}
<div class="bundle-form">
<div class="bundle-form-header mb-10">
<h3>{{ eventHeader }}</h3>
{% if eventDescription is defined %}
<h6 class="text-secondary">{{ eventDescription|purify }}</h6>
{% endif %}
</div>
{{ form_start(form) }}
{{ form_widget(form.canvasSettings.droppedX) }}
{{ form_widget(form.canvasSettings.droppedY) }}
{{ form_row(form.name) }}
{% if form.triggerMode is defined %}
<div class="mb-lg{% if hideTriggerMode %} hide{% endif %}">
{{ form_row(form.triggerMode) }}
<div{% if ('date' != form.triggerMode.vars['data']) %} class="hide"{% endif %} id="triggerDate">
{{ form_row(form.triggerDate) }}
</div>
<div{% if 'interval' != form.triggerMode.vars['data'] %} class="hide"{% endif %} id="triggerInterval">
<div class="row">
<div class="col-sm-4">
{{ form_row(form.triggerInterval) }}
</div>
<div class="col-sm-8">
{{ form_row(form.triggerIntervalUnit) }}
</div>
</div>
<div id="interval_settings">
<hr />
<div class="row">
<div class="col-sm-12">
<div class="d-flex fd-row fw-nowrap ai-center gap-sm">
<div>{{ 'mautic.campaign.form.type.interval_schedule_at'|trans }} </div>
<div>{{ form_widget(form.triggerHour) }}</div>
<div> {{ 'mautic.campaign.form.type.interval_schedule_between_hours'|trans }} </div>
<div>{{ form_widget(form.triggerRestrictedStartHour) }}</div>
<div> {{ 'mautic.core.and'|trans }} </div>
<div>{{ form_widget(form.triggerRestrictedStopHour) }}</div>
</div>
</div>
</div>
<hr />
<div class="row mt-5">
<div class="col-sm-12" style="font-weight: 600;">{{ 'mautic.campaign.form.type.interval_trigger_restricted_dow'|trans }}</div>
</div>
<div class="row">
<div class="col-sm-3">
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][0]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][0]) }}</label>
</div>
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][1]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][1]) }}</label>
</div>
</div>
<div class="col-sm-3">
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][2]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][2]) }}</label>
</div>
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][3]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][3]) }}</label>
</div>
</div>
<div class="col-sm-3">
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][4]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][4]) }}</label>
</div>
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][5]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][5]) }}</label>
</div>
</div>
<div class="col-sm-3">
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][6]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][6]) }}</label>
</div>
<div class="checkbox">
<label>{{ form_widget(form['triggerRestrictedDaysOfWeek'][7]) }} {{ form_label(form['triggerRestrictedDaysOfWeek'][7]) }}</label>
</div>
</div>
</div>
</div>
</div>
<div{% if ('optimized' != form.triggerMode.vars['data']) %} class="hide"{% endif %} id="triggerOptimized">
<div class="row">
<div class="col-xs-7">
<div class="mb-15">
{% for child in form.triggerWindow %}
<div>
{{ form_widget(child) }}
{{ form_label(child, null) }}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
<input type="hidden" name="submit" value="1">
{{ form_end(form) }}
</div>

View File

@@ -0,0 +1,68 @@
{% set route = route|default('mautic_campaignevent_action') %}
{% if update is not defined %}
<div id="CampaignEvent_{{ event['id'] }}" data-type="{{ event['eventType'] }}" class="draggable list-campaign-event list-campaign-{{ event['eventType'] }} list-campaign-jump" data-event="{{ event['type'] }}" data-event-id="{{ event['id'] }}">
{% endif %}
<div class="campaign-event-type">
<div class="campaign-event-content d-flex fw-nowrap ai-center gap-sm">
<div class="campaign-event-icon pa-sm mr-5"><i class="{{ getCampaignEventIcon(event['type']) }}"></i></div>
<span class="fs-18 fw-l">{{ ('mautic.campaign.'~event['type'])|trans }}</span>
<span class="campaign-event-name label label-primary ellipsis">{% if ('dev' == constant('MAUTIC_ENV')) %}<small>{{ event['id'] }}</small> {% endif %}{{ event['name'] }}</span>
<a class="label label-primary has-click-event highlight-jump-target ml-sm" href="javascript:void(0)" onClick="Mautic.highlightJumpTarget(event, this)" data-jump-target="{{ event['properties']['jumpToEvent'] }}">
{{ 'mautic.campaign.locate'|trans }}
<i class="ri-map-pin-2-line"></i>
</a>
</div>
</div>
{% if update is not defined %}
<div class="campaign-event-buttons hide">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
href: path(route, {
'objectAction': 'edit',
'objectId': event['id'],
'campaignId': campaignId
}),
variant: 'secondary',
icon: 'ri-pencil-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.edit.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajaxmodal',
'data-prevent-dismiss': 'true',
'data-target': '#CampaignEventModal',
'data-method': 'POST',
'class': 'btn-edit'
}
},
{
href: path(route, {
'objectAction': 'delete',
'objectId': event['id'],
'campaignId': campaignId
}),
variant: 'primary',
danger: true,
icon: 'ri-delete-bin-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.remove.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajax-delete',
'data-target': 'CampaignEvent_' ~ event['id'],
'data-ignore-formexit': 'true',
'data-method': 'POST',
'data-hide-loadingbar': 'true',
'class': 'btn-delete'
}
}
]
} %}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,42 @@
{% block _config_campaignconfig_widget %}
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.config.tab.campaignconfig'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.campaignconfig.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
{{ form_row(form.campaign_time_wait_on_event_false) }}
{{ form_row(form.campaign_by_range) }}
</div>
<div class="col-md-6">
{{ form_row(form.campaign_use_summary) }}
{{ form_row(form.campaign_email_stats_enabled) }}
</div>
</div>
</div>
</div>
</div>
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.config.peak_interaction_timer.title'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.peak_interaction_timer.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
{{ form_row(form.peak_interaction_timer_best_default_hour_start) }}
{{ form_row(form.peak_interaction_timer_best_default_hour_end) }}
{{ form_row(form.peak_interaction_timer_best_default_days) }}
</div>
<hr>
<div class="col-xs-12">
{{ form_row(form.peak_interaction_timer_cache_timeout) }}
{{ form_row(form.peak_interaction_timer_fetch_interactions_from) }}
{{ form_row(form.peak_interaction_timer_fetch_limit) }}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,3 @@
{# Doesn't seem like this file is used? #}
<hr />
{{ form_row(form) }}

View File

@@ -0,0 +1,36 @@
<div class="pa-sm">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
href: path('mautic_campaign_index'),
variant: 'primary',
icon: 'ri-list-check-2',
label: 'mautic.campaign.campaigns'
},
{
href: path('mautic_campaign_import_action', {'objectAction': 'new'}),
variant: 'secondary',
icon: 'ri-import-line',
label: 'mautic.campaign.campaign.reimport'
}
]
} %}
{% set hasOnlyNew = true %}
{% for group in importSummary %}
{% if group.update is defined and group.update is not empty %}
{% set hasOnlyNew = false %}
{% endif %}
{% endfor %}
{% if hasOnlyNew %}
{{ include('@MauticCore/Helper/confirm.html.twig', {
'btnClass': 'btn btn-danger btn-nospin',
'message': 'mautic.campaign.campaign.import.undoconfirm'|trans,
'confirmText': 'mautic.campaign.campaign.import.undo'|trans,
'confirmAction': path('mautic_campaign_import_action', {'objectAction' : 'undo'}),
'iconClass': 'ri-delete-bin-line',
'btnText': 'mautic.campaign.campaign.import.undo'|trans
}) }}
{% endif %}
</div>

View File

@@ -0,0 +1,28 @@
<div class="justify-content-center">
<ul class="text-danger">
{# Show errors from importSummary.errors #}
{% for error in importSummary.errors|default([]) %}
<li>{{ error }}</li>
{% endfor %}
{# Show errors from analyzeSummary (grouped errors) #}
{% for group in analyzeSummary|default([]) %}
{% if group.errors is defined and group.errors.messages is defined %}
{% for message in group.errors.messages %}
<li>{{ message }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
</div>
<div class="justify-content-center gap-3 mt-md">
{{ include('@MauticCore/Helper/confirm.html.twig', {
'btnClass': 'btn btn-danger btn-nospin',
'message': 'mautic.campaign.campaign.import.cancelmessage'|trans,
'confirmText': 'mautic.campaign.campaign.import.cancelconfirm'|trans,
'confirmAction': path('mautic_campaign_import_action', {'objectAction' : 'cancel'}),
'iconClass': 'ri-delete-bin-line',
'btnText': 'mautic.campaign.campaign.import.cancel'|trans
}) }}
</div>

View File

@@ -0,0 +1,82 @@
{% set summaryId = tableId|default('summaryTable') %}
{% set showLinks = showLinks|default(false) %}
{% set isAnalyzeStage = isAnalyzeStage|default(false) %}
<div class="pa-sm mt-md mb-lg">
{% if heading is defined %}
<h4 class="pa-sm">{{ heading }}</h4>
{% endif %}
<table class="table table-hover" id="{{ summaryId }}">
<thead>
<tr>
<th class="text-center">{{ 'mautic.campaign.campaign.import.entity'|trans }}</th>
<th class="text-center">{{ 'mautic.campaign.campaign.import.name'|trans }}</th>
<th class="text-center">{{ 'mautic.campaign.event.actions.header'|trans }}</th>
</tr>
</thead>
<tbody>
{% for entityKey, details in summary %}
{% set entity = entityKey|replace({'_create':'', '_update':''}) %}
{% set entityTranslations = {
'point_group': 'mautic.point.group.header.index',
'page': 'mautic.page.page',
'lists': 'mautic.segment.segment',
'lead_field': 'mautic.lead.field.header.index',
'form_field': 'mautic.form.field',
'form_action': 'mautic.form.actions',
'forms': 'mautic.form.form',
'email': 'mautic.email.email',
'dynamic_content': 'mautic.dynamicContent.dynamicContent',
'campaign_event': 'mautic.campaign.events',
'asset': 'mautic.asset.asset',
'campaign': 'mautic.campaign.campaign'
} %}
{% set translatedEntity = entityTranslations[entity] ? entityTranslations[entity]|trans : entity|capitalize %}
{% set names = details.names is iterable ? details.names : [details.names] %}
{% if isAnalyzeStage %}
{% set ids = details.uuids is iterable ? details.uuids : [details.uuids] %}
{% else %}
{% set ids = details.ids is iterable ? details.ids : [details.ids] %}
{% endif %}
{% for i in 0..(names|length - 1) %}
<tr>
<td class="text-center"><strong>{{ translatedEntity }}</strong></td>
<td>
{% if entity == 'campaign' and showLinks %}
<a href="{{ path('mautic_campaign_action', {'objectAction': 'view', 'objectId': ids[i]}) }}">
{{ names[i] }}
</a>
{% else %}
{{ names[i] }}
{% endif %}
</td>
<td class="text-center">
{% if isAnalyzeStage %}
{% if entity == 'campaign_event' %}
{{ 'mautic.campaign.campaign.import.follow_campaign_action'|trans }}
{% elseif entity == 'form_field' %}
{{ 'mautic.campaign.campaign.import.follow_form'|trans }}
{% elseif entity == 'form_action' %}
{{ 'mautic.campaign.campaign.import.follow_form'|trans }}
{% elseif entityKey ends with '_update' %}
<select name="importAction[{{ entity }}][{{ ids[i] }}]" class="form-control input-sm">
<option value="update" selected>{{ 'mautic.campaign.campaign.import.update_entity'|trans }}</option>
<option value="create">{{ 'mautic.campaign.campaign.import.create_entity'|trans }}</option>
</select>
{% else %}
{{ details.status }}
{% endif %}
{% else %}
{{ details.status }}
{% endif %}
</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,50 @@
{#
Variables
- form
#}
{% extends '@MauticCore/Default/content.html.twig' %}
{% block mauticContent %}campaignImport{% endblock %}
{% block headerTitle %}
{{ 'mautic.campaign.campaign.import.title'|trans }}
{% endblock %}
{% block actions %}
{{- include('@MauticCore/Helper/page_actions.html.twig', {
'routeBase': 'campaign',
'templateButtons': {'close': true},
'routeVars': {
'close': {
'object': app.request.get('object', 'campaigns'),
},
},
}) -}}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-offset-3 col-sm-6">
<div class="ml-lg mr-lg mt-md pa-lg">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">{{ 'mautic.campaign.campaign.import.instructions'|trans({'%size%': 100}) }}</div>
</div>
<div class="panel-body">
{{ form_start(form) }}
<div class="input-group well mt-lg">
{{ form_widget(form.campaignFile) }}
<span class="input-group-btn">
{{ form_widget(form.start) }}
</span>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,146 @@
{% extends '@MauticCore/Default/content.html.twig' %}
{% block mauticContent %}campaignImport{% endblock %}
{% block headerTitle %}
{{ 'mautic.campaign.campaign.import.title'|trans }}
{% endblock %}
{% block content %}
{% set progress = importProgress ?? 0 %}
{% set isComplete = progress >= 100 %}
{% set hasErrors = (
(importSummary|default([]))|filter(s =>
s.update is defined and s.update.errors is defined and s.update.errors is not empty
) is not empty
or
(analyzeSummary|default([]))|filter(group =>
group.errors is defined and group.errors.messages is defined and group.errors.messages is not empty
) is not empty
) %}
{% set id = hasErrors ? 'campaignImportError' : 'campaignImportSuccess' %}
<div class="row ma-lg" id="{{ id }}">
<div class="col-sm-offset-3 col-sm-6 text-center">
<div class="panel panel-{% if hasErrors %}danger{% elseif isComplete %}success{% else %}info{% endif %}">
<div class="panel-heading text-center">
<h4 class="panel-title">
{{ hasErrors
? 'mautic.campaign.campaign.import.error'|trans
: (isComplete
? 'mautic.campaign.campaign.import.success'|trans
: 'mautic.campaign.campaign.import.inprogress'|trans)
}}
</h4>
</div>
<div class="panel-body">
{% if hasErrors %}
{% include '@MauticCampaign/Import/_import_error_block.html.twig' %}
{% elseif not isComplete %}
<form method="post" action="{{ path('mautic_campaign_import_action', {'objectAction': 'progress'}) }}">
{% set processedUuids = [] %}
{% for group in analyzeSummary %}
{% set merged = {} %}
{% if group.update is defined %}
{% for entity, details in group.update %}
{% set skip = false %}
{% for uuid in details.uuids %}
{% if uuid in processedUuids %}
{% set skip = true %}
{% endif %}
{% endfor %}
{% if not skip %}
{% for uuid in details.uuids %}
{% set processedUuids = processedUuids|merge([uuid]) %}
{% endfor %}
{% set merged = merged|merge({ (entity ~ '_update'): details|merge({'status': 'Update'}) }) %}
{% endif %}
{% endfor %}
{% endif %}
{% if group.new is defined %}
{% for entity, details in group.new %}
{% set skip = false %}
{% for uuid in details.uuids %}
{% if uuid in processedUuids %}
{% set skip = true %}
{% endif %}
{% endfor %}
{% if not skip %}
{% for uuid in details.uuids %}
{% set processedUuids = processedUuids|merge([uuid]) %}
{% endfor %}
{% set merged = merged|merge({ (entity ~ '_create'): details|merge({'status': 'Create'}) }) %}
{% endif %}
{% endfor %}
{% endif %}
{% if merged is not empty %}
{% include '@MauticCampaign/Import/_summary_table.html.twig' with {
summary: merged,
tableId: 'importCombinedTable',
isAnalyzeStage: true
} %}
{% endif %}
{% endfor %}
<div class="justify-content-center gap-3 mt-md">
{{ include('@MauticCore/Helper/confirm.html.twig', {
'btnClass': 'btn btn-danger btn-nospin',
'message': 'mautic.campaign.campaign.import.cancelmessage'|trans,
'confirmText': 'mautic.campaign.campaign.import.cancelconfirm'|trans,
'confirmAction': path('mautic_campaign_import_action', {'objectAction' : 'cancel'}),
'iconClass': 'ri-delete-bin-line',
'btnText': 'mautic.campaign.campaign.import.cancel'|trans
}) }}
<button type="submit" class="btn btn-primary">
<i class="ri-play-line me-1"></i>
{{ 'mautic.campaign.campaign.import.proceed'|trans }}
</button>
</div>
</form>
{% else %}
<h4 class="text-success">{{ 'mautic.campaign.campaign.import.finished'|trans }}</h4>
{% for group in importSummary %}
{% if group.update is defined and 'email' in group.update|keys %}
{% set emailName = group.update['email'].names[0] %}
<h4 class="text-info pa-sm">
{{ 'mautic.campaign.campaign.import.email_notice'|trans({'%emailName%': emailName}) }}
</h4>
{% endif %}
{% endfor %}
{% for group in importSummary %}
{% set merged = {} %}
{% if group.update is defined %}
{% for entity, details in group.update %}
{% set merged = merged|merge({ (entity ~ '_update'): details|merge({'status': 'mautic.campaign.campaign.import.status.updated'|trans}) }) %}
{% endfor %}
{% endif %}
{% if group.new is defined %}
{% for entity, details in group.new %}
{% set merged = merged|merge({ (entity ~ '_create'): details|merge({'status': 'mautic.campaign.campaign.import.status.created'|trans}) }) %}
{% endfor %}
{% endif %}
{% if merged is not empty %}
{% include '@MauticCampaign/Import/_summary_table.html.twig' with {
summary: merged,
tableId: 'importCombinedTable',
showLinks: true
} %}
{% endif %}
{% endfor %}
{% include '@MauticCampaign/Import/_import_buttons.html.twig' %}
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,65 @@
{#
Variables
- sourceType
- campaignId
- names
#}
{% set sourceType = sourceType|default(null) %}
{% if update is not defined or update is empty %}
<div id="CampaignEvent_{{ sourceType }}" data-type="source" class="draggable list-campaign-source list-campaign-leadsource">
{% endif %}
<div class="campaign-event-content">
<div class="h5 fw-b mb-5 campaign-source-title">{{'mautic.campaign.form.lead_source'|trans}}</div>
<div><span class="campaign-event-name ellipsis" title="{{ names|default(null) }}"><i class="mr-xs campaign-event-icon {% if 'lists' == sourceType %}ri-pie-chart-line{% else %}ri-survey-line{% endif %}"></i>{{ names|default(null) }}</span></div>
</div>
{% if update is not defined or update is empty %}
<div class="campaign-event-buttons hide">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
href: path('mautic_campaignsource_action', {
'objectAction': 'edit',
'objectId': campaignId,
'sourceType': sourceType
}),
variant: 'secondary',
icon: 'ri-edit-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.edit.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajaxmodal',
'data-prevent-dismiss': 'true',
'data-target': '#CampaignEventModal',
'data-method': 'POST',
'class': 'btn-edit'
}
},
{
href: path('mautic_campaignsource_action', {
'objectAction': 'delete',
'objectId': campaignId,
'sourceType': sourceType
}),
variant: 'primary',
danger: true,
icon: 'ri-close-line',
size: 'xs',
icon_only: true,
label: 'mautic.campaign.event.remove.btn.tooltip'|trans,
attributes: {
'data-toggle': 'ajax',
'data-target': 'CampaignEvent_' ~ sourceType,
'data-ignore-formexit': 'true',
'data-method': 'POST',
'data-hide-loadingbar': 'true',
'class': 'btn-delete'
}
}
]
} %}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,9 @@
<div class="bundle-form">
<div class="bundle-form-header mb-15">
<h3>{{ 'mautic.campaign.leadsource.header.singular'|trans }}</h3>
<h6 class="text-secondary">{{ ('mautic.campaign.leadsource.'~sourceType~'.tooltip')|trans }}</h6>
</div>
{{ form_start(form) }}
<input type="hidden" name="submit" value="1">
{{ form_end(form) }}
</div>

View File

@@ -0,0 +1,16 @@
{% if showMore is defined %}
<a href="{{ url('mautic_campaign_index', {'search': searchString}) }}" data-toggle="ajax">
<span>{{ 'mautic.core.search.more'|trans({'%count%': remaining}) }}</span>
</a>
</div>
{% else %}
<a href="{{ url('mautic_campaign_action', {'objectAction': 'view', 'objectId': item.id}) }}" data-toggle="ajax">
<span class="fw-sb">{{ item.name }}</span>
<span class="ml-4 mr-sm">#{{ item.id }}</span>
{{- include('@MauticCore/Helper/publishstatus_badge.html.twig', {
'entity': item,
'status': 'active',
'simplified': 'true'
}) -}}
</a>
{% endif %}

View File

@@ -0,0 +1,92 @@
{% set item = event.extra.log %}
{% set errors = false %}
{% if (item.metadata.errors is defined and item.metadata.errors is not empty) %}
{% set errors = (item.metadata.errors is iterable) ? item.metadata.errors|join('<br />') : item.metadata.errors %}
{% elseif (item.metadata.failed is defined and item.metadata.failed is not empty) %}
{% set errors = (item.metadata.reason is not empty) ? item.metadata.reason : 'mautic.campaign.event.failed.timeline' %}
{% set errors = errors|trans %}
{% elseif (item.fail_reason is defined and item.fail_reason is not empty) %}
{% set errors = item.fail_reason %}
{% endif %}
{% set parentDetails = false %}
{% if (event.extra.parentDetails is defined) %}
{% set parentDetails = event.extra.parentDetails %}
{% endif %}
{% set cancelled = item.isScheduled is empty and item.dateTriggered is empty %}
{% set dateSpan = item.triggerDate is not empty ? '<span class="timeline-campaign-event-date-' ~ item.event_id ~ '" data-date="' ~ item.triggerDate.format('Y-m-d H:i:s') ~ '">' ~ dateToFullConcat(item.triggerDate) ~ '</span>' : '' %}
{% if (cancelled) %}
{# Note is scheduled #}
{% set item = item|merge({'isScheduled': true}) %}
{% endif %}
<div class="mt-10">
{% if (item.isScheduled) %}
<p class="mt-0 mb-10 text-info" id="timeline-campaign-event-{{ item.event_id }}">
<span id="timeline-campaign-event-text-{{ item.event_id }}"{{ cancelled ? ' class="text-warning"' : '' }}>
<i class="ri-time-line"></i>
<span class="timeline-campaign-event-scheduled-{{ item.event_id }}{{ cancelled ? ' hide' : '' }}">
{{ 'mautic.core.timeline.event.scheduled.time'|trans({'%date%' : dateSpan, '%event%' : event.eventLabel})|purify }}
</span>
<span class="timeline-campaign-event-cancelled-{{ item.event_id }}{{ cancelled is empty ? ' hide' : '' }}">
{{ 'mautic.campaign.event.cancelled.time'|trans({'%date%' : dateSpan, '%event%' : event.eventLabel}) }}
</span>
</span>
{% if (lead and securityHasEntityAccess('lead:leads:editown', 'lead:leads:editother', lead.getPermissionUser())) %}
<span class="form-buttons btn-group btn-group-xs mb-3" role="group" aria-label="Field options">
<button type="button" id="timeline-campaign-event-save-{{ item.event_id }}"
class="btn btn-ghost btn-nospin" onmousedown="return false;"
onclick="Mautic.saveScheduledCampaignEvent({{ item.event_id }}, {{ lead.getId() }})"
data-toggle="tooltip" title="{{ 'mautic.campaign.event.save'|trans }}" style="display:none">
<i class="ri-save-line text-interactive"></i>
</button>
<button type="button" class="btn btn-ghost btn-nospin btn-reschedule"
onclick="Mautic.updateScheduledCampaignEvent({{ item.event_id }}, {{ lead.getId() }})"
data-toggle="tooltip" title="{{ 'mautic.campaign.event.reschedule'|trans }}">
<i class="ri-time-line text-interactive"></i>
</button>
<button type="button"
class="btn btn-ghost btn-nospin"{{ cancelled ? ' disabled' : '' }} onclick="Mautic.cancelScheduledCampaignEvent({{ item.event_id }}, {{ lead.getId() }})"
data-toggle="tooltip" title="{{ 'mautic.campaign.event.cancel'|trans }}">
<i class="ri-close-line text-danger"></i>
</button>
</span>
{% endif %}
</p>
{% endif %}
{% if (errors) %}
{% if (item.isScheduled) %}
<hr/>
{% endif %}
<p class="text-danger mt-0 mb-10"><i class="ri-alert-line"></i> {{ 'mautic.campaign.event.last_error'|trans }}
:<br/>{{ errors|purify }}</p>
{% endif %}
{% if (item.metadata.timeline is defined and item.metadata.timeline is not empty or item.campaign_description or item.event_description) %}
<hr/>
{% if (item.metadata.timeline is defined and item.metadata.timeline is not empty) %}
<p class="mt-0 mb-10">{{ item.metadata.timeline }}</p>
{% endif %}
{% if (item.campaign_description) %}
<p class="mt-0 mb-10">{{ 'mautic.campaign.campaign.description'|trans({'%description%' : item.campaign_description})|purify }}</p>
{% endif %}
{% if (item.event_description) %}
<p class="mt-0 mb-10">{{ 'mautic.campaign.campaign.description'|trans({'%description%' : item.event_description})|purify }}</p>
{% endif %}
{% endif %}
{% if parentDetails != false %}
<h6 class="mt-lg mb-sm">
{{ 'mautic.campaign.parent.details'|trans({'%path%': parentDetails.path, '%type%': parentDetails.type, '%name%': parentDetails.name})|purify }}
</h6>
<dl class="dl-horizontal">
{% for key, value in parentDetails.properties %}
<dt>{{ key|capitalize }}:</dt>
<dd>{{ value|json_encode()|trim('"') }}</dd>
{% endfor %}
</dl>
{% endif %}
</div>