Skip to content

Commit c098b60

Browse files
author
heathdutton
committed
[ENG-119] Initial codemirror support for raw body.
Includes a bunch of JS hardening. Apply buttons no longer cause it to lock down.
1 parent 6352db0 commit c098b60

13 files changed

+134
-135
lines changed

Assets/build/contactclient.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/build/contactclient.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/js/00.type.js

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,48 @@
11
// Logic for the payload type switch.
22
Mautic.contactclientType = function () {
33

4-
if (typeof window.contactclientTypeLoaded === 'undefined') {
5-
window.contactclientTypeLoaded = true;
6-
// Trigger payload tab visibility based on contactClient type.
7-
mQuery('input[name="contactclient[type]"]').change(function () {
8-
var val = mQuery('input[name="contactclient[type]"]:checked').val();
9-
if (val === 'api') {
10-
mQuery('#payload-tab').removeClass('hide');
11-
mQuery('.row.api_payload').removeClass('hide');
12-
mQuery('.row.file_payload').addClass('hide');
4+
// Trigger payload tab visibility based on contactClient type.
5+
mQuery('input[name="contactclient[type]"]').change(function () {
6+
var val = mQuery('input[name="contactclient[type]"]:checked').val();
7+
if (val === 'api') {
8+
mQuery('#payload-tab').removeClass('hide');
9+
mQuery('.row.api_payload').removeClass('hide');
10+
mQuery('.row.file_payload').addClass('hide');
1311

14-
// Mautic.contactclientApiPayload();
15-
Mautic.contactclientApiPayloadPre();
16-
}
17-
else if (val === 'file') {
18-
mQuery('#payload-tab').removeClass('hide');
19-
mQuery('.row.api_payload').addClass('hide');
20-
mQuery('.row.file_payload').removeClass('hide');
12+
// Mautic.contactclientApiPayload();
13+
Mautic.contactclientApiPayloadPre();
14+
}
15+
else if (val === 'file') {
16+
mQuery('#payload-tab').removeClass('hide');
17+
mQuery('.row.api_payload').addClass('hide');
18+
mQuery('.row.file_payload').removeClass('hide');
19+
20+
Mautic.contactclientFilePayload();
21+
}
22+
else {
23+
mQuery('#payload-tab').addClass('hide');
24+
}
25+
}).first().parent().parent().find('label.active input:first').trigger('change');
2126

22-
Mautic.contactclientFilePayload();
27+
// Hide the right column when Payload tab is open to give more room for
28+
// table entry.
29+
var activeTab = '#details';
30+
mQuery('.contactclient-tab').click(function () {
31+
var thisTab = mQuery(this).attr('href');
32+
if (thisTab !== activeTab) {
33+
activeTab = thisTab;
34+
if (activeTab === '#payload') {
35+
// Expanded view.
36+
mQuery('.contactclient-left').addClass('col-md-12').removeClass('col-md-9');
37+
mQuery('.contactclient-right').addClass('hide');
2338
}
2439
else {
25-
mQuery('#payload-tab').addClass('hide');
26-
}
27-
}).first().parent().parent().find('label.active input:first').trigger('change');
28-
29-
// Hide the right column when Payload tab is open to give more room for
30-
// table entry.
31-
var activeTab = '#details';
32-
mQuery('.contactclient-tab').click(function () {
33-
var thisTab = mQuery(this).attr('href');
34-
if (thisTab !== activeTab) {
35-
activeTab = thisTab;
36-
if (activeTab === '#payload') {
37-
// Expanded view.
38-
mQuery('.contactclient-left').addClass('col-md-12').removeClass('col-md-9');
39-
mQuery('.contactclient-right').addClass('hide');
40-
}
41-
else {
42-
// Standard view.
43-
mQuery('.contactclient-left').removeClass('col-md-12').addClass('col-md-9');
44-
mQuery('.contactclient-right').removeClass('hide');
45-
}
40+
// Standard view.
41+
mQuery('.contactclient-left').removeClass('col-md-12').addClass('col-md-9');
42+
mQuery('.contactclient-right').removeClass('hide');
4643
}
47-
});
48-
}
44+
}
45+
});
4946
};
5047

5148
Mautic.contactclientTypeChange = function (t) {

Assets/js/02.json_editor.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,28 @@ JSONEditor.defaults.options.expand_height = true;
164164

165165
// Custom validators.
166166
JSONEditor.defaults.custom_validators.push(function (schema, value, path) {
167+
// When a textarea with option "codemirror" is true, render codemirror.
168+
if (schema.format === 'textarea' && typeof schema.options !== 'undefined' && schema.options.codemirror === true) {
169+
mQuery('textarea[name=\'' + path.replace('root.', 'root[').split('.').join('][') + ']\']:first:visible:not(.codemirror-checked)').each(function () {
170+
var $input = mQuery(this);
171+
editor = CodeMirror.fromTextArea($input[0], {
172+
// mode: {
173+
// name: 'javascript',
174+
// json: true
175+
// },
176+
theme: 'material',
177+
gutters: ['CodeMirror-lint-markers'],
178+
// lint: 'json',
179+
lintOnChange: true,
180+
matchBrackets: true,
181+
autoCloseBrackets: true,
182+
lineNumbers: true,
183+
extraKeys: {'Ctrl-Space': 'autocomplete'},
184+
lineWrapping: true
185+
});
186+
}).addClass('codemirror-checked');
187+
}
188+
// Annual/fixed date support.
167189
var errors = [];
168190
if (schema.format === 'datestring') {
169191
if (!/^[0-9|yY]{4}-[0-9]{1,2}-[0-9]{1,2}$/.test(value) && !/^[0-9]{1,2}-[0-9]{1,2}$/.test(value)) {

Assets/js/03.api_payload.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
// API Payload field.
22
// API Payload JSON Schema.
33
Mautic.contactclientApiPayloadPre = function () {
4-
var $apiPayload = mQuery('#contactclient_api_payload');
5-
if (typeof window.contactclientApiPayloadPreoaded === 'undefined' && $apiPayload.length) {
6-
7-
window.contactclientApiPayloadPreoaded = true;
4+
var $apiPayload = mQuery('#contactclient_api_payload:first:not(.hide)');
5+
if ($apiPayload.length) {
86

97
var tokenSource = 'plugin:mauticContactClient:getTokens';
108
if (typeof window.JSONEditor.tokenCache === 'undefined') {
@@ -35,10 +33,8 @@ Mautic.contactclientApiPayloadPre = function () {
3533
};
3634
Mautic.contactclientApiPayload = function () {
3735

38-
var $apiPayload = mQuery('#contactclient_api_payload');
39-
if (typeof window.contactclientApiPayloadLoaded === 'undefined' && $apiPayload.length) {
40-
41-
window.contactclientApiPayloadLoaded = true;
36+
var $apiPayload = mQuery('#contactclient_api_payload:first:not(.hide)');
37+
if ($apiPayload.length) {
4238

4339
var apiPayloadCodeMirror,
4440
apiPayloadJSONEditor;

Assets/js/04.exclusive.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Exclusive field.
22
Mautic.contactclientExclusive = function () {
3-
var $exclusive = mQuery('#contactclient_exclusive');
4-
if (typeof window.contactclientExclusiveLoaded === 'undefined' && $exclusive.length) {
5-
6-
window.contactclientExclusiveLoaded = true;
3+
var $exclusive = mQuery('#contactclient_exclusive:not(.hide):first');
4+
if ($exclusive.length) {
75

86
var exclusiveJSONEditor;
97

Assets/js/06.filter.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// @todo - Filtering field.
22
Mautic.contactclientFilter = function () {
3-
var $filter = mQuery('#contactclient_filter');
4-
if (typeof window.contactclientFilterLoaded === 'undefined' && $filter.length) {
3+
var $filter = mQuery('#contactclient_filter:not(.hide):first');
4+
if ($filter.length) {
5+
56

6-
window.contactclientFilterLoaded = true;
77
}
88
};

Assets/js/07.limits.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Limits field.
22
Mautic.contactclientLimits = function () {
3-
var $limits = mQuery('#contactclient_limits');
4-
if (typeof window.contactclientLimitsLoaded === 'undefined' && $limits.length) {
5-
6-
window.contactclientLimitsLoaded = true;
3+
var $limits = mQuery('#contactclient_limits:not(.hide):first');
4+
if ($limits.length) {
75

86
var limitsJSONEditor;
97

Assets/js/08.schedule.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
// Schedule - Hours of Operation.
22
Mautic.contactclientSchedule = function () {
33

4-
var $scheduleHoursTarget = mQuery('#contactclient_schedule_hours_widget:first'),
5-
$scheduleHoursSource = mQuery('#contactclient_schedule_hours:first');
6-
if (typeof window.contactclientScheduleLoaded === 'undefined' && $scheduleHoursTarget.length && $scheduleHoursSource.length) {
7-
8-
window.contactclientScheduleLoaded = true;
4+
var $scheduleHoursTarget = mQuery('#contactclient_schedule_hours_widget:not(.hide):first'),
5+
$scheduleHoursSource = mQuery('#contactclient_schedule_hours:not(.hide):first');
6+
if ($scheduleHoursTarget.length && $scheduleHoursSource.length) {
97

108
var operationTime = $scheduleHoursSource.val();
119
if (operationTime.length) {

Assets/js/10.timeline.js

Lines changed: 52 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,65 @@
11
Mautic.contactclientTimelineOnLoad = function (container, response) {
22

3-
if (typeof window.contactclientTimelineLoaded === 'undefined') {
4-
5-
window.contactclientTimelineLoaded = true;
6-
7-
var codeMirror = function ($el) {
8-
if (!$el.hasClass('codemirror-active')) {
9-
var $textarea = $el.find('textarea.codeMirror-yaml');
10-
if ($textarea.length) {
11-
CodeMirror.fromTextArea($textarea[0], {
12-
mode: 'yaml',
13-
theme: 'material',
14-
gutters: [],
15-
lineNumbers: false,
16-
lineWrapping: true,
17-
readOnly: true
18-
});
19-
}
20-
$el.addClass('codemirror-active');
21-
}
22-
};
23-
mQuery('#contactclient-timeline a[data-activate-details=\'all\']').on('click', function () {
24-
if (mQuery(this).find('span').first().hasClass('fa-level-down')) {
25-
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').each(function () {
26-
var detailsId = mQuery(this).data('activate-details'),
27-
$details = mQuery('#timeline-details-' + detailsId);
28-
if (detailsId && $details.length) {
29-
$details.removeClass('hide');
30-
codeMirror($details);
31-
mQuery(this).addClass('active');
32-
}
33-
});
34-
mQuery(this).find('span').first().removeClass('fa-level-down').addClass('fa-level-up');
35-
}
36-
else {
37-
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').each(function () {
38-
var detailsId = mQuery(this).data('activate-details'),
39-
$details = mQuery('#timeline-details-' + detailsId);
40-
if (detailsId && $details.length) {
41-
$details.addClass('hide');
42-
mQuery(this).removeClass('active');
43-
}
3+
var codeMirror = function ($el) {
4+
if (!$el.hasClass('codemirror-active')) {
5+
var $textarea = $el.find('textarea.codeMirror-yaml');
6+
if ($textarea.length) {
7+
CodeMirror.fromTextArea($textarea[0], {
8+
mode: 'yaml',
9+
theme: 'material',
10+
gutters: [],
11+
lineNumbers: false,
12+
lineWrapping: true,
13+
readOnly: true
4414
});
45-
mQuery(this).find('span').first().removeClass('fa-level-up').addClass('fa-level-down');
4615
}
47-
});
48-
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').on('click', function () {
49-
var detailsId = mQuery(this).data('activate-details');
50-
if (detailsId && mQuery('#timeline-details-' + detailsId).length) {
51-
var activateDetailsState = mQuery(this).hasClass('active'),
16+
$el.addClass('codemirror-active');
17+
}
18+
};
19+
mQuery('#contactclient-timeline a[data-activate-details=\'all\']').on('click', function () {
20+
if (mQuery(this).find('span').first().hasClass('fa-level-down')) {
21+
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').each(function () {
22+
var detailsId = mQuery(this).data('activate-details'),
5223
$details = mQuery('#timeline-details-' + detailsId);
53-
54-
if (activateDetailsState) {
55-
$details.addClass('hide');
56-
mQuery(this).removeClass('active');
57-
}
58-
else {
24+
if (detailsId && $details.length) {
5925
$details.removeClass('hide');
6026
codeMirror($details);
6127
mQuery(this).addClass('active');
6228
}
63-
}
64-
});
29+
});
30+
mQuery(this).find('span').first().removeClass('fa-level-down').addClass('fa-level-up');
31+
}
32+
else {
33+
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').each(function () {
34+
var detailsId = mQuery(this).data('activate-details'),
35+
$details = mQuery('#timeline-details-' + detailsId);
36+
if (detailsId && $details.length) {
37+
$details.addClass('hide');
38+
mQuery(this).removeClass('active');
39+
}
40+
});
41+
mQuery(this).find('span').first().removeClass('fa-level-up').addClass('fa-level-down');
42+
}
43+
});
44+
mQuery('#contactclient-timeline a[data-activate-details!=\'all\']').on('click', function () {
45+
var detailsId = mQuery(this).data('activate-details');
46+
if (detailsId && mQuery('#timeline-details-' + detailsId).length) {
47+
var activateDetailsState = mQuery(this).hasClass('active'),
48+
$details = mQuery('#timeline-details-' + detailsId);
6549

66-
if (response && typeof response.timelineCount !== 'undefined') {
67-
mQuery('#TimelineCount').html(response.timelineCount);
50+
if (activateDetailsState) {
51+
$details.addClass('hide');
52+
mQuery(this).removeClass('active');
53+
}
54+
else {
55+
$details.removeClass('hide');
56+
codeMirror($details);
57+
mQuery(this).addClass('active');
58+
}
6859
}
60+
});
61+
62+
if (response && typeof response.timelineCount !== 'undefined') {
63+
mQuery('#TimelineCount').html(response.timelineCount);
6964
}
7065
};

0 commit comments

Comments
 (0)