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,3 @@
{% for child in form %}
{{ form_row(child) }}
{% endfor %}

View File

@@ -0,0 +1,65 @@
{% extends '@MauticForm/Action/base_form_action.html.twig' %}
{% set footerContent %}
{% if action.properties.email is defined and securityIsGranted('email:emails:view') %}
<!-- Email to send to contact -->
{% set email = getEntity('Mautic\\EmailBundle\\Entity\\Email', action.properties.email) %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
'tags': [{
'label': email.name,
'icon': 'ri-mail-line',
'attributes': {
'href': path('mautic_email_action', {'objectAction': 'view', 'objectId': action.properties.email }),
'target': '_blank'
}
}]
} %}
{% endif %}
{% if action.properties.useremail is defined and action.properties.useremail.email is defined and securityIsGranted('email:emails:view') %}
<!-- Email to send to user -->
{% set email = getEntity('Mautic\\EmailBundle\\Entity\\Email', action.properties.useremail.email) %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
'tags': [{
'label': email.name,
'icon': 'ri-mail-line',
'attributes': {
'href': path('mautic_email_action', {'objectAction': 'view', 'objectId': action.properties.useremail.email }),
'target': '_blank'
}
}]
} %}
{% endif %}
{% if action.properties.user_id is defined and action.properties.user_id is not empty %}
<!-- Send email to users -->
{% set users = getEntities('Mautic\\UserBundle\\Entity\\User', action.properties.user_id) %}
{% for user in users %}
{% if user.firstName is defined %}
{% if securityIsGranted('user:users:edit') %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
'tags': [{
'label': user.firstName,
'icon': 'ri-account-circle-line',
'attributes': {
'href': path('mautic_user_action', {'objectAction': 'edit', 'objectId': user.id }),
'target': '_blank'
}
}]
} %}
{% else %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
'tags': [{
'label': user.firstName,
'icon': 'ri-account-circle-line',
}]
} %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endset %}
{% block action_label %}
{{ footerContent|raw }}
{% endblock %}

View File

@@ -0,0 +1,256 @@
{% if items|length > 0 %}
<div class="table-responsive">
<table class="table table-hover email-list">
<thead>
<tr>
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'checkall' : 'true'
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.name',
'text' : 'mautic.core.name',
'class' : 'col-email-name',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'c.title',
'text' : 'mautic.core.category',
'class' : 'visible-md visible-lg col-email-category',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.template',
'text' : 'mautic.core.form.theme',
'class' : 'visible-md visible-lg col-email-template',
}) -}}
<th class="visible-sm visible-md visible-lg col-email-stats">{{ 'mautic.core.stats'|trans }}</th>
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.dateAdded',
'text' : 'mautic.lead.import.label.dateAdded',
'class' : 'visible-lg col-email-dateAdded',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.dateModified',
'defaultDir' : 'DESC',
'text' : 'mautic.lead.import.label.dateModified',
'class' : 'visible-lg col-email-dateModified',
'default' : true,
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.createdByUser',
'text' : 'mautic.core.createdby',
'class' : 'visible-lg col-email-createdByUser',
}) -}}
{{- include('@MauticCore/Helper/tableheader.html.twig', {
'sessionVar' : 'email',
'orderBy' : 'e.id',
'text' : 'mautic.core.id',
'class' : 'visible-md visible-lg col-email-id',
}) -}}
</tr>
</thead>
<tbody>
{% for item in items %}
{% set hasVariants = item.isVariant(true) %}
{% set hasChildrenVariants = item.hasVariants() %}
{% set hasTranslations = item.isTranslation() %}
{% set type = item.getEmailType() %}
{% set hasDraft = item.hasDraft() %}
{% set mauticTemplateVars = _context|merge({'item' : item}) %}
<tr id="row_email_{{ item.id }}">
<td>
{% set edit = securityHasEntityAccess(
permissions['email:emails:editown'],
permissions['email:emails:editother'],
item.getCreatedBy()
) %}
{% set sendButton = {
'attr': {
'data-toggle': 'ajax',
'href' : path('mautic_email_action', {'objectAction' : 'send', 'objectId' : item.getId()}),
},
'iconClass': 'ri-send-plane-line',
'btnText': 'mautic.email.send'
} %}
{% if item.isBackgroundSending() %}
{% set sendButton = sendButton|merge({
'attr': {
'href': 'javascript:void(0);',
'disabled': true
},
'tooltip': 'mautic.email.send.disabled',
'btnClass': 'disabled'
}) %}
{% endif %}
{% set previewButton = {
'attr': {
'class': 'btn btn-ghost btn-sm btn-nospin',
'href': url('mautic_email_preview', {'objectId': item.getId()}),
'target': '_blank',
'data-toggle': '',
},
'iconClass': 'ri-external-link-line',
'btnText': 'mautic.core.open_link'|trans,
'priority': 100
} %}
{% set customButtons = ('list' == type) ? [sendButton, previewButton] : [previewButton] %}
{{- include('@MauticCore/Helper/list_actions.html.twig', {
'item' : item,
'templateButtons' : {
'edit' : edit,
'clone' : permissions['email:emails:create'],
'delete' : securityHasEntityAccess(
permissions['email:emails:deleteown'],
permissions['email:emails:deleteother'],
item.getCreatedBy()
),
'abtest' : ((not hasVariants) and edit and permissions['email:emails:create']),
},
'routeBase' : 'email',
'customButtons' : customButtons,
}) -}}
</td>
<td>
<div>
{{- include('@MauticCore/Helper/publishstatus_icon.html.twig', {
'item' : item,
'model' : 'email',
'status': item.getSendingStatus(),
}) -}}
<a href="{{ path('mautic_email_action', {'objectAction' : 'view', 'objectId' : item.getId()}) }}"
data-toggle="ajax">
{{ item.getName() }}
{% if hasChildrenVariants > 0 %}
<span data-toggle="tooltip" title="{{ 'mautic.email.icon_tooltip.ab_test.has.children'|trans }}"><i class="ri-fw ri-organization-chart fs-14"></i></span>
{% endif %}
{% if hasVariants %}
<span data-toggle="tooltip" title="{{ 'mautic.email.icon_tooltip.ab_test.has.parent'|trans }}"><i class="ri-fw ri-a-b fs-14"></i></span>
{% endif %}
{% if hasTranslations %}
<span data-toggle="tooltip" title="{{ 'mautic.core.icon_tooltip.translation'|trans }}"><i class="ri-fw ri-translate fs-14"></i></span>
{% endif %}
{% if 'list' == type %}
<span data-toggle="tooltip"title="{{ 'mautic.email.icon_tooltip.list_email'|trans }}"><i class="ri-pie-chart-line fs-14"></i></span>
{% endif %}
{% if isDraftEnabled and hasDraft %}
<span data-toggle="tooltip" title="{{ 'mautic.email.icon_tooltip.has_draft'|trans }}">
<i class="fa fa-fw fa-file"></i>
</span>
{% endif %}
{{ customContent('email.name', mauticTemplateVars) }}
</a>
{{ include('@MauticProject/Modules/projects.html.twig') }}
</div>
{% if item.getDescription() is not empty %}
<div class="text-secondary mt-4">
<small>{{ item.getDescription()|purify }}</small>
</div>
{% endif %}
</td>
<td class="visible-md visible-lg">
{{ include('@MauticCore/Modules/category--expanded.html.twig', {'category': item.category}) }}
</td>
<td class="visible-md visible-lg">
{% if item.getTemplate() %}
{{ getThemeName(item.getTemplate()) }}
{% else %}
<span class="text-muted">{{ 'mautic.core.form.default'|trans }}</span>
{% endif %}
</td>
<td class="visible-sm visible-md visible-lg col-stats" data-stats="{{ item.getId() }}">
{{ customContent('email.stats.above', mauticTemplateVars) }}
<span class="mt-xs label label-warm-gray{{ (item.getPendingCount() > 0 and 'list' == item.getEmailType()) ? '' : ' hide' }}"
id="pending-{{ item.getId() }}"
data-toggle="tooltip"
title="{{ 'mautic.email.stat.leadcount.tooltip'|trans }}">
<i class="ri-more-fill"></i><a href="{{ path('mautic_contact_index', {'search' : 'mautic.lead.lead.searchcommand.email_pending'|trans ~ ':' ~ item.getId()}) }}">
{{ 'mautic.email.stat.leadcount'|trans ({'%count%' : item.getPendingCount()}) }}
</a>
</span>
<span class="mt-xs label label-magenta{{ item.getQueuedCount() > 0 ? '' : ' hide' }}"
id="queued-{{ item.getId() }}"
data-toggle="tooltip"
title="{{ 'mautic.email.stat.queued.tooltip'|trans }}">
<i class="ri-mail-send-line"></i><a href="{{ path('mautic_contact_index', {'search' : 'mautic.lead.lead.searchcommand.email_queued'|trans ~ ':' ~ item.getId()}) }}">
{{ 'mautic.email.stat.queuedcount'|trans ({'%count%' : item.getQueuedCount()}) }}
</a>
</span>
<span class="mt-xs label label-blue" id="sent-count-{{ item.getId() }}">
<i class="ri-mail-unread-line"></i><a href="{{ path('mautic_contact_index', {'search' : 'mautic.lead.lead.searchcommand.email_sent'|trans ~ ':' ~ item.getId()}) }}"
data-toggle="tooltip"
title="{{ 'mautic.email.stat.tooltip'|trans }}">{{ 'mautic.email.stat.sentcount'|trans ({'%count%' : item.getSentCount(true)}) }}</a>
</span>
<span class="mt-xs label label-teal" id="read-count-{{ item.getId() }}">
<i class="ri-mail-open-line"></i><a href="{{ path('mautic_contact_index', {'search' : 'mautic.lead.lead.searchcommand.email_read'|trans ~ ':' ~ item.getId()}) }}"
data-toggle="tooltip"
title="{{ 'mautic.email.stat.tooltip'|trans }}">{{ 'mautic.email.stat.readcount'|trans ({'%count%' : item.getReadCount(true)}) }}</a>
<span id="read-percent-{{ item.getId() }}">
({{ item.getReadPercentage(true) }}%)
</span>
</span>
{{ customContent('email.stats', mauticTemplateVars) }}
{{ customContent('email.stats.below', mauticTemplateVars) }}
</td>
<td class="visible-lg" title="{{ item.getDateAdded() ? dateToFullConcat(item.getDateAdded()) : '' }}">
{{ item.getDateAdded() ? dateToDate(item.getDateAdded()) : '' }}
</td>
<td class="visible-lg" title="{{ item.getDateModified() ? dateToFullConcat(item.getDateModified()) : '' }}">
{{ item.getDateModified() ? dateToDate(item.getDateModified()) : '' }}
</td>
<td class="visible-lg">{{ item.getCreatedByUser()|escape }}</td>
<td class="visible-md visible-lg">{{ item.getId() }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="panel-footer">
{{- include('@MauticCore/Helper/pagination.html.twig', {
'totalItems' : totalItems,
'page' : page,
'limit' : limit,
'baseUrl' : path('mautic_email_index'),
'sessionVar' : 'email',
}) -}}
</div>
{% else %}
{% if searchValue is not empty %}
{{- include('@MauticCore/Helper/noresults.html.twig') -}}
{% 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': 'mail--verse',
'size': '80'
} %}
</div>
{% endset %}
{{ include('@MauticCore/Components/content-block.html.twig', {
heading: 'mautic.email.contentblock.heading',
subheading: 'mautic.email.contentblock.subheading',
copy: 'mautic.email.contentblock.copy',
childContainer: childContainer,
}) }}
</div>
{% endif %}
{% endif %}

View File

@@ -0,0 +1,607 @@
{% extends isEmbedded ? '@MauticCore/Default/raw_output.html.twig' : '@MauticCore/Default/content.html.twig' %}
{% block headerTitle email.name %}
{% block mauticContent 'email' %}
{% block preHeader %}
{% if not isEmbedded %}
{{- include('@MauticCore/Helper/page_actions.html.twig', {
'item' : email,
'templateButtons' : {
'close' : securityHasEntityAccess(
permissions['email:emails:viewown'],
permissions['email:emails:viewother'],
email.getCreatedBy()
),
},
'routeBase' : 'email',
'targetLabel': 'mautic.email.emails'|trans,
'customButtons' : []
}) -}}
{% endif %}
{{ include('@MauticCore/Modules/category--inline.html.twig', {'category': email.category}) }}
{{ include('@MauticProject/Modules/projects.html.twig', {'item': email}) }}
{% endblock %}
{% set variantContent = include('@MauticCore/Variant/index.html.twig', {
'activeEntity': email,
'variants': variants,
'abTestResults': abTestResults,
'model': 'email',
'actionRoute': 'mautic_email_action',
}) %}
{% set showVariants = variantContent is defined and variantContent|trim is not empty %}
{% set translationContent = include('@MauticCore/Translation/index.html.twig',
{
'activeEntity' : email,
'translations' : translations,
'model' : 'email',
'actionRoute' : 'mautic_email_action',
}
) %}
{% set showTranslations = translationContent|trim is not empty %}
{% set emailType = email.emailType %}
{% if emailType is not defined %}
{% set emailType = 'template' %}
{% endif %}
{% set customButtons = [] %}
{% if not isEmbedded %}
{% if 'list' == emailType %}
{% set sendButton = {
'attr' : {
'data-toggle' : 'ajax',
'href' : email.isBackgroundSending() ? 'javascript:void(0);' : path('mautic_email_action', {'objectAction' : 'send', 'objectId' : email.getId()}),
},
'iconClass' : 'ri-send-plane-line',
'btnText' : 'mautic.email.send',
'primary' : true,
'priority' : 500,
} %}
{% if email.isBackgroundSending() %}
{% set sendButton = sendButton|merge({'tooltip' : 'mautic.email.send.disabled'}) %}
{% set sendButton = sendButton|merge({'attr' : {'disabled' : true}}) %}
{% endif %}
{% set customButtons = customButtons|merge([sendButton]) %}
{% endif %}
{% set sendButtons = [] %}
{% if 'list' == emailType %}
{% set scheduleButton = {
'attr': {
'class' : 'btn btn-tertiary btn-nospin',
'data-toggle': 'ajaxmodal',
'data-target': '#MauticSharedModal',
'href': path('mautic_email_action', {'objectAction': 'scheduleSend', 'objectId': email.getId()}),
'data-header': 'mautic.email.send.schedule'|trans
},
'iconClass': 'ri-calendar-schedule-line',
'btnText': 'mautic.email.send.schedule',
'primary': true,
'priority': 400
} %}
{% set customButtons = customButtons|merge([scheduleButton]) %}
{% endif %}
{% set sendExampleButton = {
'attr' : {
'id' : 'sendEmailButton',
'class' : 'btn btn-tertiary btn-nospin',
'data-toggle' : 'ajaxmodal',
'data-target' : '#MauticSharedModal',
'href' : path('mautic_email_action', {'objectAction' : 'sendExample', 'objectId' : email.getId()}),
'data-header' : 'mautic.email.send.example'|trans,
},
'iconClass' : 'ri-mail-send-line',
'btnText' : 'mautic.email.send.example',
'primary' : true,
'priority': 300
} %}
{% set customButtons = customButtons|merge([sendExampleButton]) %}
{% set heatmapButton = {
'attr' : {
'class' : 'btn btn-tertiary btn-nospin',
'data-toggle' : 'email-heatmap',
'data-email' : email.getId(),
'data-target' : '#MauticSharedModal',
'href' : '#',
'data-header' : 'mautic.email.heatmap.click_heatmap'|trans,
},
'iconClass' : 'ri-fire-line',
'btnText' : 'mautic.email.heatmap.click_heatmap'
} %}
{% set customButtons = customButtons|merge([heatmapButton]) %}
{% endif %}
{# Only show A/B test button if not already a translation of an a/b test #}
{% set allowAbTest = email.isTranslation(true) and translations['parent'].isVariant(true) ? false : true %}
{% block publishStatus %}
{% if not isEmbedded %}
{{- include('@MauticCore/Helper/publishstatus_badge.html.twig', {
'entity': email,
'status': email.getPublishUp() is not null ? 'sending' : 'available',
'sendingStatus': email.getSendingStatus(),
}) -}}
<div class="label__divider"></div>
{% include '@MauticCore/Helper/_tag.html.twig' with { tags: [
{
color: 'high-contrast',
label: emailType == 'list'
? 'mautic.email.type.list.header'
: (emailType == 'template' ? 'mautic.email.type.template.header' : type)
}
] } %}
{% if email.isVariant and not email.isVariant(true) %}
{% include '@MauticCore/Helper/_tag.html.twig' with { tags: [
{ color: 'blue', label: 'mautic.email.icon_tooltip.abtest', icon: 'ri-a-b', icon_only: true }
] } %}
{% endif %}
{% if email.isVariant(true) %}
{% include '@MauticCore/Helper/_tag.html.twig' with { tags: [
{
color: 'warm-gray',
label: 'mautic.core.variant_of'|trans({'%parent%' : variants.parent.getName()}),
icon: 'ri-organization-chart',
attributes: {
href: path('mautic_email_action', {'objectAction' : 'view', 'objectId' : variants.parent.id})
}
}
] } %}
{% endif %}
{% if email.isTranslation and not email.isTranslation(true) %}
{% include '@MauticCore/Helper/_tag.html.twig' with { tags: [
{ color: 'blue', label: 'mautic.core.icon_tooltip.translation', icon: 'ri-translate', icon_only: true }
] } %}
{% endif %}
{% if email.isTranslation(true) %}
{% include '@MauticCore/Helper/_tag.html.twig' with { tags: [
{
color: 'warm-gray',
label: 'mautic.core.translation_of'|trans({'%parent%' : translations.parent.name}),
icon: 'ri-translate',
attributes: {
href: path('mautic_email_action', {'objectAction' : 'view', 'objectId' : translations.parent.id})
}
}
] } %}
{% endif %}
{# Language #}
{% if email.language is defined and email.language is not empty %}
{% include '@MauticCore/Helper/_tag.html.twig' with {
tags: [{
label: email.language|language_name,
icon: 'ri-translate-2',
color: 'warm-gray',
attributes: {
'data-toggle': 'tooltip',
'data-placement': 'top',
'title': 'mautic.core.language'|trans
}
}]
} %}
{% endif %}
{% endif %}
{% endblock %}
{% block actions %}
{% if not isEmbedded %}
{{- include('@MauticCore/Helper/page_actions.html.twig', {
'item' : email,
'templateButtons' : {
'edit' : securityHasEntityAccess(
permissions['email:emails:editown'],
permissions['email:emails:editother'],
email.getCreatedBy(),
),
'clone' : permissions['email:emails:create'],
'abtest' : (allowAbTest and permissions['email:emails:create']),
'delete' : securityHasEntityAccess(
permissions['email:emails:deleteown'],
permissions['email:emails:deleteother'],
email.getCreatedBy()
),
},
'routeBase' : 'email',
'customButtons' : customButtons,
}) -}}
{% endif %}
{% endblock %}
{% block content %}
<!-- start: box layout -->
<div class="box-layout">
<!-- left section -->
<div class="col-md-9 height-auto">
<div>
<!-- email detail header -->
<div class="pr-md pl-md pt-lg pb-lg">
<div class="box-layout">
<div class="col-xs-10">
<div>{{ email.subject }}</div>
<div class="text-secondary">{{ emailPreview }}</div>
</div>
</div>
</div>
<!--/ email detail header -->
<!-- email detail collapseable -->
<div class="collapse pr-md pl-md" id="email-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': email}) -}}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.core.form.theme'|trans }}</span>
</td>
<td>{{ email.template }}</td>
</tr>
{% if email.fromName %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.from_name'|trans }}</span>
</td>
<td>{{ email.fromName }}</td>
</tr>
{% endif %}
{% if email.fromAddress %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.from_email'|trans }}</span>
</td>
<td>{{ email.fromAddress }}</td>
</tr>
{% endif %}
{% if email.replyToAddress %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.reply_to_email'|trans }}</span>
</td>
<td>{{ email.replyToAddress }}</td>
</tr>
{% endif %}
{% if email.bccAddress %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.bcc'|trans }}</span>
</td>
<td>{{ email.bccAddress }}</td>
</tr>
{% endif %}
{% if email.getPreheaderText() %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.preheader_text'|trans }}</span>
</td>
<td>{{ email.getPreheaderText() }}</td>
</tr>
{% endif %}
{% if email.headers %}
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.custom_headers'|trans }}</span>
</td>
<td>{{ email.headers|formatter_simple_array_to_html }}</td>
</tr>
{% endif %}
<tr>
<td width="20%">
<span class="fw-b" data-toggle="tooltip" data-placement="right" title="{{ 'mautic.email.stat.sent.details'|trans }}">{{ 'mautic.email.stat.sent'|trans }} <i class="ri-question-line"></i></span>
</td>
<td>{{ email.sentCount }}</td>
</tr>
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.stat.delivered'|trans }}</span>
</td>
<td data-email-stat-delivered-for="{{ email.id }}"><div class="spinner"><i class="ri-loader-3-line ri-spin"></i></div></td>
</tr>
<tr>
<td width="20%">
<span class="fw-b">{{ 'mautic.email.stat.read'|trans }}</span>
</td>
<td>{{ email.readCount }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!--/ email detail collapseable -->
</div>
<div>
<!-- email detail collapseable toggler -->
<div class="hr-expand nm">
<span data-toggle="tooltip" title="{{ 'mautic.core.details'|trans }}">
<a href="javascript:void(0)" class="arrow text-secondary collapsed" data-toggle="collapse" data-target="#email-details">
<span class="caret"></span> {{ 'mautic.core.details'|trans }}
</a>
</span>
</div>
<!--/ email detail collapseable toggler -->
{% set isVariant = showTranslations or showVariants ?: 0 %}
{% set dateFrom = dateRangeForm.children['date_from'].vars['data'] %}
{% set dateTo = dateRangeForm.children['date_to'].vars['data'] %}
<!-- some stats -->
<div class="pt-15 pl-15 pr-15">
<div class="row">
<div class="col-sm-12">
{% if securityIsGranted('lead:leads:viewown') %}
{{ include('@MauticCore/Modules/stat--icon.html.twig', {'stats': [
{
'title': 'mautic.email.stat.sent',
'value': email.getSentCount(true),
'tooltip': 'mautic.email.stat.sent.details',
'link': path('mautic_contact_index', {'search': ('mautic.lead.lead.searchcommand.email_sent'|trans) ~ ':' ~ email.getId()}),
'icon': 'ri-mail-unread-line'
},
{
'title': 'mautic.email.stat.read',
'value': email.getReadCount(true),
'desc': email.getReadPercentage(true) ~ '%',
'tooltip': 'mautic.email.stat.read.tooltip',
'link': path('mautic_contact_index', {'search': ('mautic.lead.lead.searchcommand.email_read'|trans) ~ ':' ~ email.getId()}),
'icon': 'ri-mail-open-line'
},
{
'title': 'mautic.email.stat.queued',
'value': email.getQueuedCount(),
'tooltip': 'mautic.email.stat.queued.tooltip',
'link': path('mautic_contact_index', {'search': ('mautic.lead.lead.searchcommand.email_queued'|trans) ~ ':' ~ email.getId()}),
'icon': 'ri-mail-send-line'
},
{
'title': 'mautic.email.stat.pending',
'value': email.getPendingCount(),
'tooltip': 'mautic.email.stat.leadcount.tooltip',
'link': path('mautic_contact_index', {'search': ('mautic.lead.lead.searchcommand.email_pending'|trans) ~ ':' ~ email.getId()}),
'icon': 'ri-more-fill'
}
]}) }}
{% endif %}
</div>
</div>
</div>
<!--/ 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.email.thead.stats'|trans }}
</a>
</li>
<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="emailGraphStats"
data-graph-url="{{ path('mautic_email_graph_stats', {'objectId' : email.id, 'isVariant' : isVariant, '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>
</div>
<div class="tab-pane bdr-w-0" id="reads-map-container"
data-map-url="{{ path('mautic_email_map_stats', {'objectId' : email.id, 'isVariant' : isVariant, '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>
</div>
{{ customContent('details.stats.graph.below', _context) }}
<!-- tabs controls -->
<ul class="nav nav-tabs nav-tabs-contained">
<li class="active">
<a href="#clicks-container" role="tab" data-toggle="tab">
{{ 'mautic.trackable.click_counts'|trans }}
</a>
</li>
<li>
<a href="#contacts-container" role="tab" data-toggle="tab">
{{ 'mautic.email.associated.contacts'|trans }}
</a>
</li>
{% if showVariants %}
<li>
<a href="#variants-container" role="tab" data-toggle="tab">
{{ 'mautic.core.variants'|trans }}
</a>
</li>
{% endif %}
{% if showTranslations %}
<li>
<a href="#translation-container" role="tab" data-toggle="tab">
{{ 'mautic.core.translations'|trans }}
</a>
</li>
{% endif %}
</ul>
<!--/ tabs controls -->
</div>
<!-- start: tab-content -->
<div class="tab-content pa-md">
<div class="tab-pane active bdr-w-0" id="clicks-container">
{{- include('@MauticPage/Trackable/click_counts.html.twig', {
'trackables' : trackables,
'entity' : email,
'channel' : 'email',
}) -}}
</div>
<div class="tab-pane bdr-w-0 page-list" id="contacts-container">
{{ contacts | raw }}
</div>
{% if showVariants %}
<!-- #variants-container -->
<div class="tab-pane bdr-w-0" id="variants-container">
{{ variantContent|raw }}
</div>
<!--/ #variants-container -->
{% endif %}
<!-- #translation-container -->
{% if showTranslations %}
<div class="tab-pane bdr-w-0" id="translation-container">
{{ translationContent|raw }}
</div>
{% endif %}
<!--/ #translation-container -->
</div>
{{ include('@MauticCore/Modules/suggested-actions.html.twig', {
'entity': email,
'routeBase': 'email',
'showVariants': showVariants,
'showTranslations': showTranslations,
'allowAbTest': allowAbTest
}) }}
</div>
<!--/ left section -->
<!-- right section -->
<div class="col-md-3 bdr-l height-auto">
<!-- preview URL -->
<div class="panel shd-none bdr-rds-0 bdr-w-0 mt-sm mb-0">
<div class="panel-heading">
<div class="panel-title">{{ 'mautic.email.preview.url'|trans }}</div>
</div>
<div class="panel-body pt-xs">
{% if previewSettingsForm.translation is defined %}
<div class="row">
<div class="form-group col-xs-12 ">
<div class="control-label">{{ 'mautic.email.preview.show.translation'|trans }}</div>
{{ form_widget(previewSettingsForm.translation) }}
</div>
</div>
{% endif %}
{% if previewSettingsForm.variant is defined %}
<div class="row">
<div class="form-group col-xs-12 ">
<div class="control-label">{{ 'mautic.email.preview.show.ab.variant'|trans }}</div>
{{ form_widget(previewSettingsForm.variant) }}
</div>
</div>
{% endif %}
{% if previewSettingsForm.contact is defined %}
<div class="row">
<div class="form-group col-xs-12 ">
<div class="control-label">{{ 'mautic.email.preview.show.contact'|trans }}</div>
{{ form_widget(previewSettingsForm.contact) }}
</div>
</div>
{% endif %}
<div class="row">
<div class="form-group col-xs-12 ">
<div class="input-group">
<div class="input-group-addon">
{{- include('@MauticCore/Helper/publishstatus_icon.html.twig', {
'item' : email,
'model' : 'email',
'query' : 'customToggle=publicPreview'
}) -}}
</div>
<input id="content_preview_url" data-route="email/preview" onclick="this.setSelectionRange(0, this.value.length);" type="text" class="form-control" readonly value="{{ previewUrl|escape }}"/>
<span class="input-group-btn">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.core.open_link',
variant: 'ghost',
icon_only: true,
icon: 'ri-external-link-line',
attributes: {
'id': 'content_preview_url_button',
'type': 'button'
},
onclick: 'window.open("' ~ previewUrl ~ '", "_blank");'
}
]
} %}
</span>
<input type="hidden" id="content_preview_settings_object_id" value="{{ email.id }}">
<input type="hidden" id="content_preview_settings_contact_id" value="">
</div>
</div>
</div>
</div>
</div>
<!-- Draft preview URL -->
{% if draftPreviewUrl is defined and draftPreviewUrl is not empty %}
<div class="panel bg-transparent shd-none bdr-rds-0 bdr-w-0 mt-sm mb-0">
<div class="panel-heading">
<div class="panel-title">{{ 'mautic.email.draft.preview.url'|trans }}</div>
</div>
<div class="panel-body pt-xs">
<div class="input-group">
<div class="input-group-addon">
{{- include('@MauticCore/Helper/publishstatus_icon.html.twig', {
'item' : email.getDraft(),
'model' : 'email.email_draft',
'query' : 'customToggle=publicPreview'
}) -}}
</div>
<input onclick="this.setSelectionRange(0, this.value.length);" type="text" class="form-control"
readonly
value="{{ draftPreviewUrl|escape }}"/>
<span class="input-group-btn">
<button class="btn btn-default btn-nospin" onclick="window.open('{{ draftPreviewUrl }}', '_blank');">
<i class="fa fa-external-link"></i>
</button>
</span>
</div>
</div>
</div>
{% endif %}
<!-- email usages -->
<div class="panel shd-none bdr-rds-0 bdr-w-0 mt-sm mb-0" data-fetch-email-usages="{{ email.id }}">
<div class="panel-heading">
<div class="panel-title">{{ 'mautic.email.usages'|trans }}</div>
</div>
<div class="panel-body pt-xs">
<i class="ri-loader-3-line ri-spin"></i>
</div>
</div>
<!-- activity feed -->
{{- include('@MauticCore/Helper/recentactivity.html.twig', {'logs': logs}) -}}
</div>
<!-- right section -->
<input name="entityId" id="entityId" type="hidden" value="{{ email.id|escape }}"/>
</div>
{% endblock %}

View File

@@ -0,0 +1,312 @@
{% form_theme form '@MauticEmail/FormTheme/Email/layout.html.twig' %}
{% extends '@MauticCore/Default/content.html.twig' %}
{% block mauticContent 'email' %}
{% set dynamicContentPrototype = form.dynamicContent.vars.prototype %}
{% set filterBlockPrototype = form.dynamicContent.children[0].filters.vars.prototype|default(null) %}
{% set filterSelectPrototype = form.dynamicContent.children[0].filters.children[0].filters.vars.prototype|default(null) %}
{% set variantParent = email.variantParent %}
{% set isExisting = email.id is not empty %}
{% set emailType = form.emailType.vars.data %}
{% set attachmentSize = attachmentSize|default(0) %}
{% set templates = {
'select' : 'select-template',
'countries' : 'country-template',
'regions' : 'region-template',
'timezones' : 'timezone-template',
'stages' : 'stage-template',
'locales' : 'locale-template',
} %}
{% set isCodeMode = (email.getTemplate() is same as 'mautic_code_mode') %}
{% set previewUrl = previewUrl|default('') %}
{% set draftPreviewUrl = draftPreviewUrl|default('') %}
{% block headerTitle %}
{% if email.id is not empty %}
{{ 'mautic.email.header.edit'|trans({'%name%': email.name}) }}
{% else %}
{{ 'mautic.email.header.new'|trans }}
{% endif %}
{% if email.variantParent %}
<div><span class="small">{{ 'mautic.core.variant_of'|trans({'%name%': email.name, '%parent%' : variantParent.name}) }}</span></div>
{% endif %}
{% endblock %}
{% block content %}
{{ form_start(form) }}
<div class="box-layout">
<div class="col-md-9 height-auto">
<div class="row">
<div class="col-xs-12">
<!-- tabs controls -->
<ul class="nav nav-tabs nav-tabs-contained">
<li class="active">
<a href="#email-container" role="tab" data-toggle="tab">{{ 'mautic.core.form.theme'|trans }}</a>
</li>
<li>
<a href="#advanced-container" role="tab" data-toggle="tab">{{ 'mautic.core.advanced'|trans }}</a>
</li>
<li id="dynamic-content-tab" {{ (isCodeMode) ? '' : 'class="hidden"' }}>
<a href="#dynamic-content-container" role="tab" data-toggle="tab">{{ 'mautic.core.dynamicContent'|trans }}</a>
</li>
{{ customContent('email.tabs', _context) }}
</ul>
<!--/ tabs controls -->
<div class="tab-content pa-md">
<div class="tab-pane fade in active bdr-w-0" id="email-container">
<div class="row">
<div class="col-md-12">{{ form_row(form.template) }}</div>
</div>
{{- include('@MauticCore/Helper/theme_select.html.twig', {
'type' : 'email',
'themes' : themes,
'active' : form.template.vars.value,
}) -}}
</div>
<div class="tab-pane fade bdr-w-0" id="advanced-container">
<div class="row">
<div class="col-md-6">
{{ form_row(form.fromName) }}
{{ form_row(form.fromAddress) }}
{{ form_row(form.replyToAddress) }}
{{ form_row(form.bccAddress) }}
{{ customContent('email.settings.advanced', _context) }}
<div>
<div class="pull-left">
{{ form_label(form.assetAttachments) }}
</div>
<div class="text-right pr-10">
<span class="label label-info"
id="attachment-size">{{ attachmentSize }}</span>
</div>
<div class="clearfix"></div>
{{ form_widget(form.assetAttachments) }}
</div>
</div>
<div class="col-md-6">
{{ form_row(form.headers) }}
</div>
<div class="col-md-6">
{{ form_row(form.useOwnerAsMailer) }}
</div>
</div>
<br/>
<div class="row hidden" id="custom-html-row">
<div class="col-md-12">
{{ form_label(form.customHtml) }}
{{ form_widget(form.customHtml) }}
</div>
</div>
<br/>
<div class="row">
<div class="col-md-12">
<div class="pull-left">
{{ form_label(form.plainText) }}
</div>
<div class="text-right pr-10">
<i class="ri-loader-3-line ri-spin ml-2 plaintext-spinner hide"></i>
<a class="small"
onclick="Mautic.autoGeneratePlaintext();">{{ 'mautic.email.plaintext.generate'|trans }}</a>
</div>
<div class="clearfix"></div>
{{ form_widget(form.plainText) }}
</div>
</div>
</div>
<div class="tab-pane fade bdr-w-0" id="dynamic-content-container">
<div class="row">
<div class="col-md-12">
<div class="row">
<div class="col-xs-3 dynamicContentFilterContainer">
<ul class="nav nav-tabs nav-tabs-contained tabs-left" id="dynamicContentTabs">
<li>
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.core.form.new',
variant: 'primary',
icon: 'ri-add-line',
attributes: {
'id': 'addNewDynamicContent',
'role': 'tab',
'class': 'mr-xs',
'type': 'button'
}
}
]
} %}
</li>
{% for dynamicContent in form.dynamicContent %}
{% set name = dynamicContent.tokenName.vars.value %}
{% set linkText = name is defined ? name : 'mautic.core.dynamicContent'|trans ~ ' ' ~ loop.index %}
<li class="{% if loop.first %}active{% endif %}">
<a role="tab" data-toggle="tab" href="#{{ dynamicContent.vars.id }}">{{ linkText }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="tab-content pa-md col-xs-9" id="dynamicContentContainer">
{% for dynamicContent in form.dynamicContent %}
{{ form_widget(dynamicContent) }}
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{{ customContent('email.tabs.content', _context) }}
</div>
</div>
</div>
</div>
<div class="col-md-3 height-auto bdr-l">
<div class="pr-lg pl-lg pt-md pb-md">
{{ form_row(form.subject) }}
{{ form_row(form.name) }}
{{ form_row(form.preheaderText) }}
{% if isVariant %}
{{ form_row(form.variantSettings) }}
{{ form_row(form.isPublished) }}
<div id="scheduleOptions">
{% if emailType == 'template' %}
{{ form_row(form.publishUp) }}
{{ form_row(form.publishDown) }}
{% else %}
{{ form_row(form.publishUp, {'label': 'mautic.core.form.sending.start_at'}) }}
{{ form_row(form.publishDown, {'label': 'mautic.core.form.sending.stop_at'}) }}
{% endif %}
</div>
{% else %}
<div id="leadList"{{ (('template' == emailType) ? ' class="hide"' : '') }}>
{{ form_row(form.lists) }}
{{ form_row(form.excludedLists) }}
</div>
{{ form_row(form.category) }}
{{ form_row(form.projects) }}
{{ form_row(form.language) }}
<div id="segmentTranslationParent"{{ (('template' == emailType) ? ' class="hide"' : '') }}>
{{ form_row(form.segmentTranslationParent) }}
</div>
<div id="templateTranslationParent"{{ (('list' == emailType) ? ' class="hide"' : '') }}>
{{ form_row(form.templateTranslationParent) }}
</div>
{% endif %}
{% if not isVariant %}
{{ form_row(form.isPublished, {
'attr': {
'data-none': 'mautic.core.form.sending_paused',
'data-start': 'mautic.core.form.sending_on_scheduled_start',
'data-both': 'mautic.core.form.sending_during_scheduled_period',
'data-end': 'mautic.core.form.available_until_scheduled_end'
}
}) }}
<div id="scheduleOptions">
{% if emailType == 'template' %}
{{ form_row(form.publishUp) }}
{{ form_row(form.publishDown) }}
{% else %}
{{ form_row(form.publishUp, {'label': 'mautic.core.form.sending.start_at'}) }}
{{ form_row(form.publishDown, {'label': 'mautic.core.form.sending.stop_at'}) }}
{% endif %}
</div>
{% endif %}
{{ form_row(form.unsubscribeForm) }}
{% if permissions['page:preference_center:viewown'] is not empty or permissions['page:preference_center:viewother'] is not empty %}
{{ form_row(form.preferenceCenter) }}
{% endif %}
<hr/>
{% include '@MauticCore/FormTheme/Fields/_utm_tags_fields.html.twig' %}
</div>
<div class="hide">
{{ form_rest(form) }}
</div>
</div>
</div>
{{ form_end(form) }}
<div id="dynamicContentPrototype" data-prototype="{{ form_widget(dynamicContentPrototype)|e }}"></div>
{% if filterBlockPrototype is instanceof('\\Symfony\\Component\\Form\\FormView') %}
<div id="filterBlockPrototype" data-prototype="{{ form_widget(filterBlockPrototype)|e }}"></div>
{% endif %}
{% if filterSelectPrototype is instanceof('\\Symfony\\Component\\Form\\FormView') %}
<div id="filterSelectPrototype" data-prototype="{{ form_widget(filterSelectPrototype)|e }}"></div>
{% endif %}
<div class="hide" id="templates">
{% for dataKey, template in templates %}
{% set attr = ('tags' == dataKey) ? ' data-placeholder="' ~ mautic.lead.tags.select_or_create|trans ~ '" data-no-results-text="' ~ mautic.lead.tags.enter_to_create|trans ~ '" data-allow-add="true" onchange="Mautic.createLeadTag(this)"' : '' %}
<select class="form-control not-chosen {{ template }}"
name="emailform[dynamicContent][__dynamicContentIndex__][filters][__dynamicContentFilterIndex__][filters][__name__][filter]"
id="emailform_dynamicContent___dynamicContentIndex___filters___dynamicContentFilterIndex___filters___name___filter"{{ attr }}>
{% if form.vars[dataKey] is defined %}
{% for value, label in form.vars[dataKey] %}
{% if label is iterable %}
<optgroup label="{{ value }}">
{% for optionValue, optionLabel in label %}
<option value="{{ optionValue }}">{{ optionLabel }}</option>
{% endfor %}
</optgroup>
{% else %}
{% if 'lists' != dataKey or (currentListId is not defined or (value != currentListId)) %}
<option value="{{ label }}">{{ value }}</option>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
</select>
{% endfor %}
</div>
{{- include('@MauticCore/Helper/builder.html.twig', {
'type' : 'email',
'isCodeMode' : isCodeMode,
'objectId' : email.sessionId,
'previewUrl' : previewUrl,
'draftPreviewUrl' : draftPreviewUrl,
}, with_context=false) -}}
{% set typeTwoDifferences = ['mautic.email.type.segment.differences.1st', 'mautic.email.type.segment.differences.2nd', 'mautic.email.type.segment.differences.3rd', 'mautic.email.type.segment.differences.4th'] %}
{% set typeOneDifferences = ['mautic.email.type.template.differences.1st', 'mautic.email.type.template.differences.2nd', 'mautic.email.type.template.differences.3rd', 'mautic.email.type.template.differences.4th'] %}
{% set type = email.emailType %}
{% if (
(
(updateSelect is not defined or (updateSelect is defined and updateSelect is empty))
and not isExisting
and not formContainsErrors(form)
and not variantParent
)
or type is empty
or (forceTypeSelection is defined and forceTypeSelection is not empty)
)
%}
{{- include('@MauticCore/Helper/form_selecttype.html.twig', {
'item' : email,
'mauticLang' : {
'newListEmail' : 'mautic.email.type.list.header',
'newTemplateEmail' : 'mautic.email.type.template.header',
},
'typePrefix' : 'email',
'cancelUrl' : 'mautic_email_index',
'header' : 'mautic.email.type.header',
'typeOneHeader' : 'mautic.email.type.template.header',
'typeOnePictogram': 'process--automation',
'typeOneTag': 'mautic.email.type.template.tag',
'typeOneDifferences' : typeOneDifferences,
'typeOneOnClick' : "Mautic.selectEmailType('template');",
'typeTwoHeader' : 'mautic.email.type.list.header',
'typeTwoPictogram': 'chart--pie',
'typeTwoTag': 'mautic.email.type.list.tag',
'typeTwoDifferences' : typeTwoDifferences,
'typeTwoOnClick' : "Mautic.selectEmailType('list');",
}) -}}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,68 @@
{% if 'list' == email.getEmailType() %}
{% set label = 'mautic.email.lead.list.comparison' %}
{% set type = 'bar' %}
{% else %}
{% set label = 'mautic.email.stats' %}
{% set type = 'line' %}
{% endif %}
{% set dateFrom = dateRangeForm.children['date_from'].vars['data'] %}
{% set dateTo = dateRangeForm.children['date_to'].vars['data'] %}
{% set actionRoute = path('mautic_email_action', {
'objectAction' : 'view',
'objectId' : email.getId(),
'daterange' : {
'date_to' : dateTo,
'date_from' : dateFrom,
}
}) %}
<div class="row">
<div class="col-sm-12">
{% if isVariant %}
<div class="text-right small" id="variant-chart-switcher">
<span>
<a data-toggle="ajax" class="btn btn-xs{% if not showAllStats %}{{ ' disabled' }}{% endif %}" href="{{ actionRoute ~ '&stats=variant' }}">
{{ 'mautic.email.variant.graph.variant'|trans }}
</a>
</span>
</span> | </span>
<span>
<a data-toggle="ajax" class="btn btn-xs{% if not showAllStats %}{{ ' disabled' }}{% endif %}" href="{{ actionRoute ~ '&stats=all' }}">
{{ 'mautic.email.variant.graph.all'|trans }}
</a>
</span>
</div>
{% endif %}
<div class="panel-body box-layout">
<div class="col-xs-12 va-m">
<h5 class="text-white dark-md fw-sb mb-xs">
<span class="ri-mail-line"></span>
{{ label|trans }}
</h5>
</div>
</div>
<div class="row">
<div class="pt-0 pl-15 pb-15 pr-15 col-xs-6 min-h-256">
{{- include('@MauticCore/Helper/chart.html.twig', {
'chartData' : stats,
'chartType' : type,
'chartHeight' : 300
})
-}}
</div>
<div class="pt-0 pl-15 pb-15 pr-15 col-xs-6 min-h-256">
{{- include('@MauticCore/Helper/chart.html.twig', {
'chartData' : statsDevices,
'chartType' : 'horizontal-bar',
'chartHeight' : 300
})
-}}
</div>
</div>
</div>
</div>
<!--/ some stats -->

View File

@@ -0,0 +1,94 @@
{% set isIndex = tmpl == 'index' %}
{% set tmpl = 'list' %}
{% extends isIndex ? '@MauticCore/Default/content.html.twig' : '@MauticCore/Default/raw_output.html.twig' %}
{% block mauticContent 'email' %}
{% block headerTitle 'mautic.email.emails'|trans %}
{% block content %}
{% if isIndex %}
<div id="page-list-wrapper" class="{% if items|length > 0 or searchValue is not empty %}panel {% endif %}panel-default">
{{- include('@MauticCore/Helper/list_toolbar.html.twig', {
'searchValue': searchValue,
'action': currentRoute,
'filters': filters,
'page_actions': {
'templateButtons': {
'new': permissions['email:emails:create']
},
'routeBase': 'email',
},
'bulk_actions': {
'routeBase': 'email',
'templateButtons': {
'delete': permissions['email:emails:deleteown'] or permissions['email:emails:deleteother']
},
'customButtons': [
{
'attr': {
'class': 'btn btn-default btn-sm btn-nospin',
'data-toggle': 'ajaxmodal',
'data-target': '#MauticSharedModal',
'href': path('mautic_email_batch_categories_view'),
'data-header': 'mautic.email.batch.categories'|trans,
},
'btnText': 'mautic.email.batch.categories'|trans,
'iconClass': 'ri-folder-line',
},
]
},
'quickFilters': [
{
'search': 'mautic.core.searchcommand.ispublished',
'label': 'mautic.core.form.available',
'tooltip': 'mautic.core.searchcommand.ispublished.description',
'icon': 'ri-check-line'
},
{
'search': 'mautic.core.searchcommand.isunpublished',
'label': 'mautic.core.form.unavailable',
'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.email.email.searchcommand.isexpired',
'label': 'mautic.core.form.sending_expired',
'tooltip': 'mautic.email.email.searchcommand.isexpired.description',
'icon': 'ri-time-line'
},
{
'search': 'mautic.email.email.searchcommand.ispending',
'label': 'mautic.core.form.scheduled_to_send',
'tooltip': 'mautic.email.email.searchcommand.ispending.description',
'icon': 'ri-timer-line'
}
]
}) -}}
<div class="page-list">
{{ include('@MauticEmail/Email/_list.html.twig') }}
</div>
</div>
{{ include('@MauticCore/Modules/protip.html.twig', {
tip: random(['mautic.protip.emails.unsubscribe', 'mautic.protip.emails.test', 'mautic.protip.emails.personalize', 'mautic.protip.emails.spam', 'mautic.protip.emails.cta'])
}) }}
{% else %}
{{ include('@MauticEmail/Email/_list.html.twig') }}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,55 @@
<!--
some stats: need more input on what type of form data to show.
delete if it is not require
-->
<div class="pa-md">
<div class="row">
<div class="col-sm-12">
{% if showVariants %}
<div class="text-right small">
<span>
{% if isVariant %}
<span data-chart="variant">{% trans %}mautic.email.variant.graph.variant{% endtrans %}</span>
{% else %}
<a data-chart="variant" href="javascript:void(0)">{% trans %}mautic.email.variant.graph.variant{% endtrans %}</a>
{% endif %}
</span>
</span> | </span>
<span>
{% if isVariant %}
<a data-chart="all" href="javascript:void(0)">{% trans %}mautic.email.variant.graph.all{% endtrans %}</a>
{% else %}
<span data-chart="all">{% trans %}mautic.email.variant.graph.all{% endtrans %}</span>
{% endif %}
</span>
</div>
{% endif %}
<div class="panel">
<div class="panel-body box-layout">
<div class="col-xs-4 va-m">
<h5 class="text-white dark-md fw-sb mb-xs">
<span class="ri-mail-line"></span>
{% trans %}mautic.email.stats{% endtrans %}
</h5>
</div>
<div class="col-xs-8 va-m">
{{- include('@MauticCore/Helper/graph_dateselect.html.twig', {
'dateRangeForm' : dateRangeForm,
'class' : 'pull-right'
})
-}}
</div>
</div>
<div class="d-flex fd-column pt-0 pl-15 pb-15 pr-15 min-h-256">
{{- include('@MauticCore/Helper/chart.html.twig', {
'chartData' : stats,
'chartType' : 'line',
'chartHeight' : 300
})
-}}
</div>
</div>
</div>
</div>
</div>
<!--/ some stats -->

View File

@@ -0,0 +1,116 @@
{%- macro row_if_exists(form, field) %}
{% if form[field] is defined %}
<div class="col-xs-12">
{{ form_row(form[field]) }}
</div>
{% endif %}
{%- endmacro %}
{% block _config_emailconfig_widget %}
{% set fields = form.children %}
{% set fieldKeys = fields|keys %}
{% form_theme form with [
'@MauticEmail/FormTheme/Config/monitored_email_widget.html.twig',
'@MauticEmail/FormTheme/Config/monitored_mailboxes_widget.html.twig',
] %}
{% if fieldKeys|filter(k => k in ['mailer_from_name', 'mailer_from_email', 'mailer_reply_to_email'])|length > 0 %}
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.email.config.header.mail'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.mail.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="row">
{{ _self.row_if_exists(fields, 'mailer_from_name') }}
{{ _self.row_if_exists(fields, 'mailer_from_email') }}
{{ _self.row_if_exists(fields, 'mailer_reply_to_email') }}
{{ _self.row_if_exists(fields, 'mailer_return_path') }}
{{ _self.row_if_exists(fields, 'mailer_address_length_limit') }}
{{ _self.row_if_exists(fields, 'mailer_is_owner') }}
{{ _self.row_if_exists(fields, 'mailer_custom_headers') }}
</div>
</div>
</div>
</div>
{% endif %}
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.email.config.header.dsn'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.dsn.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="col-xs-12">
{{ form_row(fields.mailer_dsn) }}
</div>
</div>
</div>
</div>
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.config.tab.frequency_rules'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.frequency_rules.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="col-xs-12">
{{ form_row(fields.email_frequency_number) }}
{{ form_row(fields.email_frequency_time) }}
</div>
</div>
</div>
</div>
{% if fields.monitored_email is defined %}
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.email.config.header.monitored_email'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.monitored_email.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
{% if 'imap_open' is function %}
{{ form_widget(form.monitored_email) }}
{% else %}
<div class="alert alert-info">{{ 'mautic.email.imap_extension_missing'|trans|purify }}</div>
{% endif %}
</div>
</div>
</div>
{% endif %}
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.email.config.header.message'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.message.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="row">
{{ _self.row_if_exists(fields, 'webview_text') }}
{{ _self.row_if_exists(fields, 'default_signature_text') }}
{{ _self.row_if_exists(fields, 'mailer_append_tracking_pixel') }}
{{ _self.row_if_exists(fields, 'mailer_convert_embed_images') }}
{{ _self.row_if_exists(fields, 'disable_trackable_urls') }}
{{ _self.row_if_exists(fields, 'minify_email_html') }}
{{ _self.row_if_exists(fields, 'email_draft_enabled') }}
</div>
</div>
</div>
</div>
<h4 class="fw-sb mt-48 mb-xs">{{ 'mautic.email.config.header.unsubscribe'|trans }}</h4>
<div class="text-muted small pb-md">{{ 'mautic.core.config.header.unsubscribe.description'|trans }}</div>
<div class="row">
<div class="panel panel-default mb-md">
<div class="panel-body">
<div class="row">
{{ _self.row_if_exists(fields, 'unsubscribe_text') }}
{{ _self.row_if_exists(fields, 'unsubscribe_message') }}
{{ _self.row_if_exists(fields, 'resubscribe_message') }}
{{ _self.row_if_exists(fields, 'show_contact_preferences') }}
{{ _self.row_if_exists(fields, 'show_contact_segments') }}
{{ _self.row_if_exists(fields, 'show_contact_frequency') }}
{{ _self.row_if_exists(fields, 'show_contact_pause_dates') }}
{{ _self.row_if_exists(fields, 'show_contact_categories') }}
{{ _self.row_if_exists(fields, 'show_contact_preferred_channels') }}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,16 @@
{% block monitored_email_widget %}
{% for child in form.children %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ child.vars.label|trans }}</h3>
</div>
<div class="panel-body">
{% set tooltip = translatorHasId(child.vars.label ~ '.tooltip') ? (child.vars.label ~ '.tooltip')|trans : '' %}
{% if tooltip %}
<p>{{ tooltip|purify }}</p>
{% endif %}
{{ form_widget(child) }}
</div>
</div>
{% endfor %}
{% endblock %}

View File

@@ -0,0 +1,53 @@
{% block monitored_mailboxes_widget %}
<div class="row">
{% if 'general' != mailbox %}
<div class="col-xs-12">{{ form_row(form.folder) }}</div>
<div class="col-xs-12">{{ form_row(form.override_settings) }}</div>
{% else %}
<div class="col-xs-12">{{ form_row(form.address) }}</div>
<div class="col-xs-12 pt-lg" id="{{ mailbox }}TestButtonContainer">
<div class="button_container">
{{ form_widget(form.test_connection_button) }}
<span class="ri-loader-3-line ri-spin hide"></span>
</div>
<div class="help-block"></div>
</div>
{% endif %}
</div>
{% if 'general' != mailbox %}
<div class="row">
<div class="col-xs-12">{{ form_row(form.address) }}</div>
<div class="col-xs-12 pt-lg" id="{{ mailbox }}TestButtonContainer" data-show-on='{"config_emailconfig_monitored_email_{{ mailbox }}_override_settings_1": "checked"}'>
<div class="button_container">
{{ form_widget(form.test_connection_button) }}
<span class="ri-loader-3-line ri-spin hide"></span>
</div>
<div class="help-block"></div>
</div>
</div>
{% endif %}
<div class="row">
<div class="col-xs-12">
{{ form_row(form.host) }}
</div>
<div class="col-xs-12">
{{ form_row(form.port) }}
</div>
{% if is_extension_loaded('openssl') %}
<div class="col-xs-12">
{{ form_row(form.encryption) }}
</div>
{% endif %}
</div>
<div class="row">
<div class="col-xs-12">
{{ form_row(form.user) }}
</div>
<div class="col-xs-12">
{{ form_row(form.password) }}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,188 @@
{% block _email_abtest_settings_properties_row %}
{{ form_widget(form) }}
{% endblock %}
{% block _email_variantSettings_properties_row %}
{{ form_widget(form) }}
{% endblock %}
{% block _emailform_dynamicContent_entry_content_row %}
<div class="row form-group">
<div class="col-xs-10">
{{ form_label(form) }}
</div>
<div class="col-xs-2">
{% if 'emailform_dynamicContent_0_content' is not same as id %}
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.dwc.delete_new',
variant: 'ghost',
icon_only: true,
icon: 'ri-delete-bin-line',
danger: true,
size: 'xs',
attributes: {
'class': 'remove-item as-end',
'type': 'button'
}
}
]
} %}
{% endif %}
</div>
</div>
<div class="row form-group">
<div class="col-xs-12">
{{ form_widget(form) }}
</div>
</div>
{% endblock %}
{% block _emailform_dynamicContent_entry_filters_entry_filters_entry_widget %}
{%- set isPrototype = ('__name__' == form.vars.name) %}
{%- set filterType = form.field.vars.value %}
{%- set filterGroup = form.object.vars.value %}
{%- set inGroup = form.vars.data.glue is defined and 'and' is same as form.vars.data.glue %}
{%- set objectIcon = (form.vars.data.object is defined and 'company' == form.vars.data.object) ? 'ri-building-2-line' : 'ri-user-6-fill' %}
<div class="panel {% if isPrototype or (inGroup and not first) %}in-group{% endif %}">
<div class="panel-footer {% if not isPrototype and '0' is same as form.vars.name %}hide{% endif %}">
<div class="col-sm-2 pl-0">
{{ form_widget(form.glue) }}
</div>
</div>
<div class="panel-body">
<div class="col-xs-6 col-sm-3 field-name">
<i class="object-icon fa {{ objectIcon }}" aria-hidden="true"></i>
<span>{% if isPrototype %}__label__{% else %}{{ form.parent.parent.vars.fields[filterGroup][filterType].label }}{% endif %}</span>
</div>
<div class="col-xs-6 col-sm-3 padding-none">
{{ form_widget(form.operator) }}
</div>
{% set hasErrors = (form.filter.vars.errors|length > 0 or form.display.vars.errors|length > 0) %}
<div class="col-xs-10 col-sm-5 padding-none {% if hasErrors %}has-error{% endif %}">
{{ form_widget(form.filter) }}
{{ form_errors(form.filter) }}
{{ form_widget(form.display) }}
{{ form_errors(form.display) }}
</div>
<div class="col-xs-2 col-sm-1">
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.report.report.label.removefilter',
variant: 'ghost',
icon_only: true,
icon: 'ri-delete-bin-line',
danger: true,
size: 'xs',
attributes: {
'class': 'remove-selected pull-right'
}
}
]
} %}
</div>
{{ form_widget(form.field) }}
{{ form_widget(form.type) }}
{{ form_widget(form.object) }}
</div>
</div>
{% endblock %}
{% block dynamic_content_filter_entry_widget %}
<div class="tab-pane dynamic-content-filter bdr-w-0" id="{{ form.vars.id }}">
<div class="row form-group">
<div class="col-xs-10">
{{ form_label(form.content) }}
</div>
<div class="col-xs-2">
{% if id is not same as 'emailform_dynamicContent_0_filters_0' %}
<a class="remove-item remove-filter btn btn-ghost text-danger"><i class="ri-delete-bin-line"></i></a>
{% endif %}
</div>
</div>
<div class="row form-group">
<div class="col-xs-12">
{{ form_widget(form.content) }}
</div>
</div>
<div class="row">
<div class="col-xs-7">
<label>{{ 'Filters'|trans }}</label>
</div>
<div class="col-xs-5">
<div class="form-group">
<div class="available-filters pl-0">
<select class="chosen form-control" data-mautic="available_filters">
<option value=""></option>
{% for object, field in fields %}
{% set icon = ('company' == object) ? 'ri-building-2-line' : 'ri-user-6-fill' %}
<optgroup label="{{ ('mautic.lead.' ~ object)|trans }}">
{% for value, params in field %}
{% set list = params.properties.list|default([]) %}
{% set choices = (params.properties.type is same as 'boolean') ? formFieldParseBooleanList(list)|formFieldFlipBooleanList : formFieldParseListForChoices(list) %}
{% set list = choices|json_encode %}
{% set callback = params.properties.callback|default('') %}
{% set operators = (params.operators is defined and params.operators is not empty) ? params.operators|json_encode|escape : '{}' %}
<option value="{{ value|e }}"
data-mautic="available_{{ value }}"
data-field-object="{{ object }}"
data-field-type="{{ params.properties.type }}"
data-field-list="{{ list|escape }}"
data-field-callback="{{ callback }}"
data-field-operators="{{ operators|raw }}"
class="segment-filter fa {{ icon }}">{{ params.label|trans }}</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
<div data-filter-container data-index="{{ form.filters|length }}">
{% for i, filter in form.filters %}
{% set isPrototype = ('__name__' == filter.vars.name) %}
{% if isPrototype or form.vars.fields[filter.vars.value.object][filter.vars.value.field] is defined %}
{{ form_widget(filter, {'first' : loop.first}) }}
{% endif %}
{% endfor %}
</div>
</div>
{% endblock %}
{% block dynamic_content_filter_widget %}
<div class="tab-pane dynamic-content bdr-w-0 {{ '0' == form.vars.name ? 'active' : 'fade' }}" id="{{ form.vars.id }}">
<div class="panel">
<ul class="nav nav-tabs nav-tabs-contained" id="dynamicContentFilterTabs_{{ form.vars.name }}">
<li>
<a role="tab" class="addNewDynamicContentFilter" data-index="{{ form.vars.name }}"><i class="ri-add-line text-success"></i>{{ 'mautic.core.form.new'|trans }}</a>
</li>
<li class="active">
<a data-toggle="tab" href="#emailform_dynamicContent_{{ form.vars.name }}_default" role="tab">Default</a>
</li>
{% for i, filter in form['filters'] %}
<li><a role="tab" data-toggle="tab" href="#{{ filter.vars.id }}">{{ 'mautic.core.dynamicContent.tab'|trans }} {{ loop.index }}</a></li>
{% endfor %}
</ul>
<div class="tab-content pa-md">
<div class="tab-pane bdr-w-0 active" id="emailform_dynamicContent_{{ form.vars.name }}_default">
<div class="row hidden">
<div class="col-xs-10">{{ form_row(form.tokenName) }}</div>
</div>
{{ form_row(form.content) }}
</div>
{% for filter in form.filters %}
{{ form_widget(filter) }}
{% endfor %}
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,16 @@
{% use '@MauticEmail/FormTheme/EmailSendList/emailsend_list_row.html.twig' %}
{% block email_to_user_row %}
<div class="row">
<div class="col-md-6">
{{ form_row(form.user_id) }}
</div>
<div class="col-md-6">
{{ form_row(form.to_owner) }}
</div>
</div>
{{ form_row(form.to) }}
{{ form_row(form.cc) }}
{{ form_row(form.bcc) }}
{{ form_rest(form) }}
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% block emailsend_list_row %}
<div class="row">
<div class="col-xs-{% if form.email_type is defined %}6{% else %}12{% endif %} pr-0">
{{ form_row(form.email) }}
<div class="mb-lg d-flex">
{{ form_row(form.newEmailButton) }}
{{ form_row(form.editEmailButton) }}
{{ form_row(form.previewEmailButton) }}
</div>
</div>
{% if form.email_type is defined %}
<div class="col-xs-12">
{{ form_row(form.email_type) }}
</div>
{% endif %}
{% if form.priority is defined %}
<div id="priority" class="col-xs-5 queue_hide">
{{ form_row(form.priority) }}
</div>
{% endif %}
{% if form.attempts is defined %}
<div id="attempts" class="col-xs-5 queue_hide">
{{ form_row(form.attempts) }}
</div>
{% endif %}
</div>
<div class="row">
</div>
{% endblock %}

View File

@@ -0,0 +1,32 @@
{#
- Used with the Form Action Send Email to User
#}
{% block _formaction_properties_useremail_row %}
<div class="row">
<div class="col-xs-{% if form.email_type is defined %}7{% else %}12{% endif %}">
{{ form_row(form.email) }}
</div>
{% if form.email_type is defined %}
<div class="col-xs-5">
{{ form_row(form.email_type) }}
</div>
{% endif %}
{% if form.priority is defined %}
<div id="priority" class="col-xs-5 queue_hide">
{{ form_row(form.priority) }}
</div>
{% endif %}
{% if form.attempts is defined %}
<div id="attempts" class="col-xs-5 queue_hide">
{{ form_row(form.attempts) }}
</div>
{% endif %}
</div>
<div class="row mb-5">
<div class="col-xs-12">
{{ form_row(form.newEmailButton) }}
{{ form_row(form.editEmailButton) }}
{{ form_row(form.previewEmailButton) }}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,21 @@
<div class="heatmap-legend">
<p>{{ 'mautic.email.heatmap.clicks_recorded'|trans }}<br />
<small><a href="#" data-toggle="heatmap-total" class="active">{{ 'mautic.email.heatmap.total'|trans }}</a> | <a href="#" data-toggle="heatmap-unique">{{ 'mautic.email.heatmap.unique'|trans }}</a></small></p>
<p data-heatmap-clicks>{{ totalClicks }}</p>
<p>{{ 'mautic.email.heatmap.heat_scale'|trans }}</p>
<div class="heatmap-scale-header">
<div>{{ 'mautic.email.heatmap.cold'|trans }}</div>
<div>{{ 'mautic.email.heatmap.hot'|trans }}</div>
</div>
<div class="heatmap-scale">
<div class="heatmap-scale-bar"></div>
<div class="heatmap-scale-bar"></div>
<div class="heatmap-scale-bar"></div>
<div class="heatmap-scale-bar"></div>
<div class="heatmap-scale-bar"></div>
</div>
<div class="heatmap-scale-footer">
<div>0%</div>
<div>100%</div>
</div>
</div>

View File

@@ -0,0 +1,7 @@
{% set shortcuts = {
'emails': {
's' : 'mautic.keyboard.send_example',
},
} %}
{% include '@MauticCore/Helper/keyboard_shortcuts_helper.html.twig' with {'shortcuts': shortcuts} %}

View File

@@ -0,0 +1,136 @@
{% set leadId = lead.getId() %}
{% set leadName = lead.getPrimaryIdentifier() %}
{% set channelNumber = 0 %}
<script>
function togglePreferredChannel(channel){
const status = document.getElementById(channel).checked;
const fields = [
'lead_contact_frequency_rules_lead_channels_frequency_number_' + channel,
'lead_contact_frequency_rules_lead_channels_frequency_time_' + channel,
'lead_contact_frequency_rules_lead_channels_contact_pause_start_date_' + channel,
'lead_contact_frequency_rules_lead_channels_contact_pause_end_date_' + channel
];
// disable the input fields if the main checkbox is disabled
for (let index = 0; index < fields.length; index++) {
const field = document.getElementById(fields[index]);
if (field) {
field.disabled = !status;
}
}
}
</script>
<div class="row text-left">
{{ form_start(form, {'render_rest': false}) }}
<div class="col-xs-12 col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h1 class="panel-title">{{ 'mautic.lead.message.preferences'|trans }}</h1>
</div>
<div class="panel-body">
<div class="the-price">
<h4>{{ leadName }}</h4>
<small>{{ 'mautic.lead.message.preferences.descr'|trans }}</small>
</div>
<table class="table table-hover">
{% if showContactFrequency %}
{% for key, channel in form.lead_channels.subscribed_channels.vars.choices %}
{% set contactMe = leadChannels[channel.value] is defined %}
{% set checked = contactMe ? 'checked' : '' %}
{% set channelName = getChannelLabel(channel.value)|lower %}
<tr>
<td>
<div class="text-left">
<input type="hidden" id="{{ channel.value }}-hidden"
name="lead_contact_frequency_rules[lead_channels][subscribed_channels][{{ key }}]"
value="">
<input type="checkbox" id="{{ channel.value }}"
name="lead_contact_frequency_rules[lead_channels][subscribed_channels][{{ key }}]"
onclick="togglePreferredChannel(this.value);"
value="{{ channel.value|escape }}" {{ checked }}>
<label for="{{ channel.value }}" id="is-contactable-{{ channel.value }}">
{{ 'mautic.lead.contact.me.label'|trans({'%channel%' : channelName}) }}
</label>
</div>
</td>
</tr>
{%- do form.lead_channels.subscribed_channels.setRendered(true) %}
<tr>
<td>
<div id="frequency_<?php echo $channel->value; ?>" class="text-left row">
{% if showContactFrequency %}
<div class="col-md-6" data-contact-frequency="1">
<label class="text-secondary">{{ form.lead_channels['frequency_number_' ~ channel.value].vars.label|trans }}</label>
{{ form_widget(form.lead_channels['frequency_number_' ~ channel.value]) }}
{{ form_label(form.lead_channels['frequency_time_' ~ channel.value]) }}
{{ form_widget(form.lead_channels['frequency_time_' ~ channel.value]) }}
</div>
{% endif %}
{% if showContactPauseDates %}
<div class="col-md-6" data-contact-pause-dates="1">
<label class="text-secondary">{{ 'mautic.lead.frequency.dates.label'|trans }}</label>
{{ form_widget(form.lead_channels['contact_pause_start_date_' ~ channel.value]) }}
{{ form_label(form.lead_channels['contact_pause_end_date_' ~ channel.value]) }}
{{ form_widget(form.lead_channels['contact_pause_end_date_' ~ channel.value]) }}
</div>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
{% endif %}
</table>
{% if showContactPreferredChannels %}
<hr />
<div id="preferred_channel" class="text-left">{{ form_row(form.lead_channels.preferred_channel) }}</div>
{% endif %}
{% set segmentCount = form.lead_lists is defined ? form.lead_lists.vars.choices|length : 0 %}
{% if showContactSegments and segmentCount > 0 %}
<hr />
<div id="contact-segments">
<div class="text-left">{{ form_label(form.lead_lists) }}</div>
{% for key, leadList in form.lead_lists %}
<div id="segment-{{ key }}" class="text-left">
{{ form_widget(leadList) }}
{{ form_label(leadList) }}
</div>
{% endfor %}
</div>
{% endif %}
{% set categoryCount = form.global_categories is defined ? form.global_categories.vars.choices|length : 0 %}
{% if showContactCategories and categoryCount > 0 %}
<hr />
<div id="global-categories">
<div class="text-left">{{ form_label(form.global_categories) }}</div>
{% for key, category in form.global_categories %}
<div id="category-{{ key }}" class="text-left">
{{ form_widget(category) }}
{{ form_label(category) }}
</div>
{% endfor %}
</div>
{% endif %}
{% if successMessage is defined %}
<hr />
<div id="success-message-text">
{{ successMessage }}
</div>
{% endif %}
<hr />
<div id="do-not-contact-text">
{{ 'mautic.email.unsubscribe_all.text'|trans ({'%link%' : dncUrl})|purify }}
</div>
</div>
<div class="panel-footer text-left">
{{ form_row(form.buttons.save) }}
</div>
</div>
</div>
<div class="hidden">
{{ form_rest(form) }}
</div>
{{ form_end(form) }}
</div>

View File

@@ -0,0 +1,45 @@
{% extends '@MauticCore/Default/content.html.twig' %}
{% block mauticContent 'emailSend' %}
{% block headerTitle 'mautic.email.send.list'|trans({'%name%': email.name})|purify %}
{% block content %}
<div class="row">
<div class="col-sm-offset-2 col-sm-8 col-md-offset-3 col-md-6">
<div class="ml-lg mr-lg mt-md pa-lg">
<div class="panel panel-info">
<div class="panel-body">
{{ form_start(form) }}
<div class="col-xs-offset-1 col-xs-10 col-lg-offset-2 col-lg-8">
<div class="well mt-lg">
<div class="input-group">
<span class="input-group-btn text-center">
{{- include('@MauticCore/Helper/confirm.html.twig', {
'message' : 'mautic.email.form.confirmsend'|trans({'%name%' : email.getName()}),
'confirmText' : 'mautic.email.send'|trans,
'confirmCallback' : 'submitSendForm',
'iconClass' : 'ri-send-plane-line',
'btnText' : 'mautic.email.send'|trans,
'btnClass' : 'btn btn-primary btn-send' ~ ((pending) ? '' : ' disabled')
}) -}}
</span>
</div>
<div class="text-center">
<span class="label label-primary mt-lg">
{{ 'mautic.email.send.pending'|trans ({'%count%' : pending}) }}
</span>
<div class="mt-sm">
<a class="text-danger mt-md" href="{{ path('mautic_email_action', {'objectAction' : 'view', 'objectId' : email.getId()}) }}" data-toggle="ajax">{{ 'mautic.core.form.cancel'|trans }}</a>
</div>
</div>
</div>
</div>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,89 @@
{% extends '@MauticCore/Default/content.html.twig' %}
{% block mauticContent 'emailSend' %}
{% block headerTitle 'mautic.email.send.list'|trans({'%name%': email.name})|purify %}
{% set percent = (progress[1]) ? ((progress[0] / progress[1]) * 100)|round : 100 %}
{% set id = ('inprogress' != status) ? 'emailSendProgressComplete' : 'emailSendProgress' %}
{% block content %}
<div class="row ma-lg email-send-progress" id="{{ id }}">
<div class="col-sm-offset-3 col-sm-6">
<div class="panel panel-{{ ('inprogress' != status) ? 'success' : 'danger' }}">
<div class="panel-heading">
<h4 class="panel-title">
{{ ('mautic.email.send.' ~ status)|trans({ '%subject%' : email.getSubject() })|purify }}
</h4>
</div>
<div class="panel-body">
{% if 'inprogress' != status %}
<h4>{{ 'mautic.email.send.stats'|trans({'%sent%': stats.sent, '%failed%': stats.failed}) }}</h4>
{% endif %}
<div class="progress mt-md" style="height:50px;">
<div class="progress-bar-send progress-bar progress-bar-striped{% if 'inprogress' == status %}{{ ' active' }}{% endif %}"
role="progressbar"
aria-valuenow="{{ progress[0] }}"
aria-valuemin="0"
aria-valuemax="{{ progress[1] }}"
style="width: {{ percent }}%; height: 50px;"
data-batchlimit="{{ batchlimit }}"
data-email="{{ email.id }}">
<span class="sr-only">{{ percent }}%</span>
</div>
</div>
</div>
{% if stats.failedRecipients is not empty %}
<ul class="list-group">
{% for leadId, failedEmail in stats.failedRecipients %}
<li class="list-group-item">
<a target="_new" class="text-danger" href="{{ path('mautic_contact_action', {'objectAction': 'view', 'objectId': leadId}) }}">
{{- failedEmail -}}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
<div class="panel-footer text-center">
<span class="small">
<span class="imported-count">{{ progress[0] }}</span> / <span class="total-count">{{ progress[1] }}</span>
</span>
{% if 'inprogress' == status %}
<div>
<a class="text-danger mt-md"
href="{{ path('mautic_email_action', {'objectAction': 'send', 'objectId': email.id}) }}"
data-toggle="ajax">{{ 'mautic.core.form.cancel'|trans }}</a>
</div>
{% else %}
<div>
<a class="text-success mt-md"
href="{{ path('mautic_email_action', {'objectAction': 'view', 'objectId': email.id}) }}"
data-toggle="ajax">{{ 'mautic.core.form.done'|trans }}</a>
</div>
{% endif %}
</div>
</div>
{% if 'inprogress' == status %}
{% include '@MauticCore/Helper/button.html.twig' with {
buttons: [
{
label: 'mautic.email.send.exit_screen'|trans,
variant: 'link',
icon: 'ri-information-line',
attributes: {
'data-toggle': 'popover',
'data-content': 'mautic.email.send.help_subheading_leaving'|trans,
'data-placement': 'bottom',
'data-container': 'body',
'data-title': 'mautic.email.send.help_heading_leaving'|trans,
}
}
]
} %}
{% endif %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,60 @@
{#
Variables
- class
- shortenLinkText
- headItems
- widget
- bodyItems
#}
{% set class = class|default('table') %}
{% set shortenLinkText = shortenLinkText|default(30) %}
{% set showHeaders = [
'mautic.dashboard.label.url',
'mautic.dashboard.label.unique.hit.count',
'mautic.dashboard.label.total.hit.count',
'mautic.dashboard.label.email.name',
] %}
{% set showValues = [
'url',
'unique_hits',
'hits',
'email_name',
] %}
<table class="{{ class }}">
{% if headItems is not empty %}
<thead>
<tr>
{% for headItem in headItems %}
{% if headItem in showHeaders %}
<th>{{ headItem|trans }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
{% endif %}
{% if bodyItems is not empty %}
<tbody>
{% for id, row in bodyItems %}
<tr>
{% if row is iterable %}
{% for key, item in row %}
{% if key in showValues %}
<td>
{% if 'email_name' == key %}
<a href="{{ path('mautic_email_action', {'objectAction': 'view', 'objectId': row.email_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% else %}
{{ item }}
{% endif %}
</td>
{% endif %}
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</tbody>
{% endif %}
</table>

View File

@@ -0,0 +1,90 @@
{#
Variables
- class
- shortenLinkText
- headItems
- widget
- bodyItems
#}
{% set class = class|default('table') %}
{% set shortenLinkText = shortenLinkText|default(30) %}
{% set showHeaders = [
'mautic.dashboard.label.contact.email.address',
'mautic.dashboard.label.contact.open',
'mautic.dashboard.label.contact.click',
'mautic.dashboard.label.email.name',
'mautic.dashboard.label.segment.name',
'mautic.dashboard.label.company.name',
'mautic.dashboard.label.campaign.name',
] %}
{% set showValues = [
'contact_email',
'open',
'click',
'email_name',
'segment_name',
'company_name',
'campaign_name',
] %}
<table class="{{ class }}">
{% if headItems is not empty %}
<thead>
<tr>
{% for headItem in headItems %}
{% if headItem in showHeaders %}
<th>{{ headItem|trans }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
{% endif %}
{% if bodyItems is not empty %}
<tbody>
{% for id, row in bodyItems %}
<tr>
{% if row is iterable %}
{% for key, item in row %}
{% if key in showValues %}
<td>
{% if 'contact_email' == key and row.contact_id is not empty %}
<a href="{{ path('mautic_contact_action', {'objectAction': 'view', 'objectId': row.contact_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% elseif 'email_name' == key and row.email_id is not empty %}
<a href="{{ path('mautic_email_action', {'objectAction': 'view', 'objectId': row.email_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% elseif 'segment_name' == key and row.segment_id is not empty %}
<a href="{{ path('mautic_segment_action', {'objectAction': 'view', 'objectId': row.segment_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% elseif 'company_name' == key and row.company_id is not empty %}
<a href="{{ path('mautic_company_action', {'objectAction': 'edit', 'objectId': row.company_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% elseif 'campaign_name' == key and row.campaign_id is not empty %}
<a href="{{ path('mautic_campaign_action', {'objectAction': 'view', 'objectId': row.campaign_id}) }}"
title="{{ item|e }}"
data-toggle="ajax">
{{ item|slice(0, shortenLinkText) }}
</a>
{% else %}
{{ item }}
{% endif %}
</td>
{% endif %}
{% endfor %}
{% endif %}
</tr>
{% endfor %}
</tbody>
{% endif %}
</table>

View File

@@ -0,0 +1,19 @@
{% if showMore is defined and showMore is not empty %}
<a href="{{ path('mautic_email_index', {'search' : searchString }) }}" data-toggle="ajax">
<span>{{ 'mautic.core.search.more'|trans ({ '%count%' : remaining }) }}</span>
</a>
{% else %}
<a href="{{ path('mautic_email_action', {'objectAction' : 'view', 'objectId' : item.id}) }}" data-toggle="ajax">
<span class="fw-sb">{{ item.getName() }}</span>
<span class="ml-4 mr-sm">#{{ item.getId() }}</span>
{{- include('@MauticCore/Helper/publishstatus_badge.html.twig', {
'entity': item,
'status': item.getPublishUp() is not null ? 'sending' : 'available',
'simplified': 'true'
}) -}}
<span class="pull-right" data-toggle="tooltip" title="{{ 'mautic.email.readcount'|trans }}" data-placement="left">
<i class="ri-mail-open-line"></i>
{{ item.readCount }}
</span>
</a>
{% endif %}

View File

@@ -0,0 +1,58 @@
{#
Variables
- event
- lead
#}
{% set item = event.extra is defined and event.extra is not empty ? event.extra.stat : false %}
{% if item != false %}
<p>
{% if item.isFailed is not empty and item.isFailed %}
{% if item.openDetails.bouces is defined %}
<span class="label label-warning" data-toggle="tooltip" title="{{ 'mautic.email.timeline.event.bounced'|trans }}">
{{ 'mautic.email.timeline.event.bounced'|trans }}
</span>
{% else %}
{{ 'mautic.email.timeline.event.failed'|trans }}
{% endif %}
{% elseif item.dateRead is empty %}
{{ 'mautic.email.timeline.event.not.read'|trans|purify }}
{% else %}
{{ ('mautic.email.timeline.event.' ~ event['extra']['type'])|trans({
'%date%': dateToFull(event.timestamp),
'%interval%': dateFormatRange(item.dateSent.diff(event.timestamp)),
'%sent%': dateToFull(item.dateSent),
})|purify }}
{% endif %}
{% if item.viewedInBrowser is not empty and item.viewedInBrowser %}
{{ 'mautic.email.timeline.event.viewed.in.browser'|trans }}
{% endif %}
{% if item.retryCount is not empty and item.retryCount %}
{{ 'mautic.email.timeline.event.retried'|trans({'%count%': item['retryCount']})}}
{% endif %}
{% if item.list_name is not empty %}
{{ 'mautic.email.timeline.event.list'|trans({'%list%': item['list_name']}) }}
{% endif %}
</p>
<div class="small">
{% if item.openDetails is not empty %}
<h6 class="mt-lg mb-sm"><strong>{{ 'mautic.email.timeline.open_details'|trans }}</strong></h6>
{% for key, detail in item.openDetails %}
{% if 'bounces' != key %}
{% if showMore is not defined and loop.index > 5 %}
{% set showMore = true %}
<div style="display:none">
{% endif %}
{% if loop.index > 1 %}<hr/>{% endif %}
<strong>{{ dateToText(detail['datetime'], 'UTC') }}</strong><br/>{{ detail['useragent']|e }}
{% endif %}
{% endfor %}
{% if showMore is defined %}
</div>
<a href="javascript:void(0);" class="text-center small center-block mt-xs" onclick="Mautic.toggleTimelineMoreVisiblity(mQuery(this).prev());">{{ 'mautic.core.more.show'|trans }}</a>
{% endif %}
{% endif %}
</div>
{% endif %}

View File

@@ -0,0 +1,58 @@
{% set childContainer %}
<p class="text-secondary pi-md">{{'mautic.placeholder_tokens.email_tokens.explanation'|trans}}</p>
<ul id="emailTokensAccordion" class="accordion" role="tablist" aria-multiselectable="true">
<!-- Email specific tokens -->
<li class="panel">
<a role="button" id="headingEmailTokens" class="accordion-heading collapsed" data-toggle="collapse"
data-parent="#tokensAccordion" href="#collapseEmailTokens" aria-expanded="false"
aria-controls="collapseEmailTokens">
<i class="ri-arrow-down-s-line accordion-arrow"></i>
<span class="accordion-title">{{ 'mautic.placeholder_tokens.email_tokens'|trans }}</span>
</a>
<div id="collapseEmailTokens" class="collapse accordion-wrapper" role="tabpanel"
aria-labelledby="headingEmailTokens">
<table class="table table-hover">
<thead>
<tr>
<th>{{ 'mautic.placeholder_tokens.variable_name'|trans }}</th>
<th>{{ 'mautic.placeholder_tokens.variable_syntax'|trans }}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.signature'|trans }}</td>
<td><code>{signature}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.subject'|trans }}</td>
<td><code>{subject}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.unsubscribe_text'|trans }}</td>
<td><code>{unsubscribe_text}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.unsubscribe_url'|trans }}</td>
<td><code>{unsubscribe_url}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.resubscribe_url'|trans }}</td>
<td><code>{resubscribe_url}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.webview_text'|trans }}</td>
<td><code>{webview_text}</code></td>
</tr>
<tr>
<td>{{ 'mautic.placeholder_tokens.email.webview_url'|trans }}</td>
<td><code>{webview_url}</code></td>
</tr>
</tbody>
</table>
</div>
</li>
</ul>
{% endset %}
{% include '@MauticCore/Components/content-section.html.twig' with {'heading': 'mautic.placeholder_tokens.email_specific', 'childContainer': childContainer} %}