| 1 |
import eventBus from "../eventBus.js"; |
| 2 |
import ApiMixin from '../Api/ApiMixin.js'; |
| 3 |
import {validate} from "../Plugins/Validation.js"; |
| 4 |
import {loadStart, loadEnd} from "../Plugins/Loader.js"; |
| 5 |
const template = ` |
| 6 |
<!-- Create Group Modal --> |
| 7 |
<div v-if="openCreateGroupModal" class="woo-ml-wizard-modal" id="wooMlWizardCreateGroupModal" role="dialog" data-testid="create-group-modal"> |
| 8 |
<div class="woo-ml-wizard-modal-parent"> |
| 9 |
<div class="woo-ml-wizard-modal-container"> |
| 10 |
<div class="woo-ml-wizard-modal-content"> |
| 11 |
<div class="woo-ml-wizard-modal-header"> |
| 12 |
<h2>Create new group</h2> |
| 13 |
<span @click="openCreateGroupModal = false" class="close"></span> |
| 14 |
</div> |
| 15 |
<div class="woo-ml-wizard-modal-body"> |
| 16 |
<div class="create-group-input"> |
| 17 |
<input ref="wooMlCreateGroup" type="text" name="createGroup" placeholder="Enter group name" v-model="createGroupName" class="" data-testid="create-group-name-input"> |
| 18 |
</div> |
| 19 |
<div class="modal-button-ml"> |
| 20 |
<button @click="openCreateGroupModal = false" type="button" class="btn-secondary-ml woo-ml-close" style="margin-right: 12px;">Close</button> |
| 21 |
<button @click="createGroup" ref="createGroup" type="button" class="btn-primary-ml" data-testid="create-group-submit-btn"><span class="woo-ml-button-text">Create group</span></button> |
| 22 |
</div> |
| 23 |
</div> |
| 24 |
</div> |
| 25 |
</div> |
| 26 |
</div> |
| 27 |
</div> |
| 28 |
<!-- Create Group Modal --> |
| 29 |
|
| 30 |
<!-- Sync Resources Modal --> |
| 31 |
<div v-if="openSyncModal" class="woo-ml-wizard-modal" id="wooMlSyncModal" role="dialog"> |
| 32 |
<div class="woo-ml-wizard-modal-parent"> |
| 33 |
<div class="woo-ml-wizard-modal-container"> |
| 34 |
<div class="woo-ml-wizard-modal-content woo-ml-text-center"> |
| 35 |
<div class="woo-ml-wizard-modal-header"> |
| 36 |
<h2>Synchronizing subscribers</h2> |
| 37 |
</div> |
| 38 |
<p style="line-height: 1.75rem; font-size: 14px; text-align: left; margin-bottom: 24px;"> |
| 39 |
This initial import will send product details, product categories, and customer data to MailerLite. It will also enable real-time synchronization on future updates. Please note that only subscribers who opt-in to receive email marketing will be added. |
| 40 |
</p> |
| 41 |
<div class="progress-box"> |
| 42 |
<div class="progress"> |
| 43 |
<div id="wooMlWizardProgress" :style="{ width: progressPercentage + '%' }"></div> |
| 44 |
</div> |
| 45 |
<div style=" text-align: center; "><span id="progressPercentage">{{ progressPercentage }}%</span></div> |
| 46 |
</div> |
| 47 |
<h4>Total resources to sync: {{ remainingUntrackedResources }}</h4> |
| 48 |
<div class="woo-ml-wizard-modal-body"> |
| 49 |
<div class="modal-button-ml"> |
| 50 |
<button @click="openSyncModal = false" type="button" class="btn-secondary-ml">Cancel</button> |
| 51 |
</div> |
| 52 |
</div> |
| 53 |
</div> |
| 54 |
</div> |
| 55 |
</div> |
| 56 |
</div> |
| 57 |
<!-- Sync Resources Modal --> |
| 58 |
|
| 59 |
<!-- Cancel Sync Resources Modal --> |
| 60 |
<div v-if="openCancelSyncModal" class="woo-ml-wizard-modal" id="wooMlCancelSyncModal" role="dialog"> |
| 61 |
<div class="woo-ml-wizard-modal-parent"> |
| 62 |
<div class="woo-ml-wizard-modal-container"> |
| 63 |
<div class="woo-ml-wizard-modal-content woo-ml-text-center"> |
| 64 |
<div class="woo-ml-wizard-modal-header"> |
| 65 |
<h2>Terminate import</h2> |
| 66 |
</div> |
| 67 |
<p style="line-height: 1.75rem; font-size: 14px; text-align: left; margin-bottom: 0;"> |
| 68 |
Are you sure you want to stop the import process? The import will be reset, and the progress made so far will be lost. Click 'Terminate' if you wish to continue. |
| 69 |
</p> |
| 70 |
<div class="woo-ml-wizard-modal-body"> |
| 71 |
<div class="modal-button-ml"> |
| 72 |
<button @click="openCancelSyncModal = false" type="button" class="btn-secondary-ml" style="margin-right: 12px;">Close</button> |
| 73 |
<button id="confirmCancelSync" type="button" class="btn-danger-ml" style="margin-right: 12px;"><span class="woo-ml-button-text">Terminate</span></button> |
| 74 |
</div> |
| 75 |
</div> |
| 76 |
</div> |
| 77 |
</div> |
| 78 |
</div> |
| 79 |
</div> |
| 80 |
<!-- Cancel Sync Resources Modal --> |
| 81 |
|
| 82 |
<!-- Reset Integration Modal --> |
| 83 |
<div v-if="openResetModal" class="woo-ml-wizard-modal" id="wooMlResetIntegrationModal" role="dialog"> |
| 84 |
<div class="woo-ml-wizard-modal-parent"> |
| 85 |
<div class="woo-ml-wizard-modal-container"> |
| 86 |
<div class="woo-ml-wizard-modal-content woo-ml-text-center"> |
| 87 |
<div class="woo-ml-wizard-modal-header"> |
| 88 |
<h2>Reset integration</h2> |
| 89 |
</div> |
| 90 |
<p style="line-height: 1.75rem; font-size: 14px; text-align: left; margin-bottom: 0;"> |
| 91 |
Are you sure you want to reset the integration? Click 'Reset' if you wish to continue. |
| 92 |
</p> |
| 93 |
<div class="woo-ml-wizard-modal-body"> |
| 94 |
<div class="modal-button-ml"> |
| 95 |
<form id="resetIntegration" method="post"> |
| 96 |
<!-- wp_nonce_field('ml_reset_integration'); --> |
| 97 |
<input type="hidden" name="resetIntegration"/> |
| 98 |
<button @click="openResetModal = false" type="button" class="btn-secondary-ml" style="margin-right: 12px;">Close</button> |
| 99 |
<button @click.prevent="resetIntegration" ref="resetIntegration" id="resetIntegrationBtn" class="btn-danger-ml" style="margin-right: 12px;"><span class="woo-ml-button-text">Reset</span></button> |
| 100 |
</form> |
| 101 |
</div> |
| 102 |
</div> |
| 103 |
</div> |
| 104 |
</div> |
| 105 |
</div> |
| 106 |
</div> |
| 107 |
<!-- Reset Integration Modal --> |
| 108 |
|
| 109 |
<!-- Reset Integration Modal --> |
| 110 |
<div v-if="openDebugLogModal" class="woo-ml-wizard-modal" id="openDebugLogModal" role="dialog"> |
| 111 |
<div class="woo-ml-wizard-modal-parent"> |
| 112 |
<div class="woo-ml-wizard-modal-container"> |
| 113 |
<div class="woo-ml-wizard-modal-content woo-ml-text-center"> |
| 114 |
<div class="woo-ml-wizard-modal-header"> |
| 115 |
<h2>Debug logs</h2> |
| 116 |
<p style="line-height: 1.75rem; font-size: 14px; text-align: left; margin-bottom: 0;"> |
| 117 |
In case you have problems with our application's performance, please click 'Copy to clipboard' and share the logs with our support team using <a href="https://www.mailerlite.com/contact-us?category=integrations-api" target="_blank" class="settings-label-medium">this contact form</a>. |
| 118 |
</p> |
| 119 |
</div> |
| 120 |
<div class="woo-ml-wizard-modal-body"> |
| 121 |
<input type="text" v-model="searchLogs" @input="highlightSearch" placeholder="Search logs..." /> |
| 122 |
<pre class="woo-mailerlite-log-container" ref="debugLogLines"> |
| 123 |
<div v-for="(line, index) in filteredLogs" :key="index" v-html="highlightSearch(line)"></div> |
| 124 |
</pre> |
| 125 |
<div class="modal-button-ml"> |
| 126 |
<button @click="openDebugLogModal = false" type="button" class="btn-secondary-ml" style="margin-right: 12px;">Close</button> |
| 127 |
<button @click="copyDebugLogToClipboard" type="button" class="btn-primary-ml no-icon-tooltip-ml" style="margin-right: 12px;"><span class="no-icon-tooltip-ml-text">Copied</span><span class="woo-ml-button-text">{{this.copyMessage !== '' ? this.copyMessage : 'Copy to clipboard'}}</span></button> |
| 128 |
</div> |
| 129 |
</div> |
| 130 |
</div> |
| 131 |
</div> |
| 132 |
</div> |
| 133 |
</div> |
| 134 |
<!-- Reset Integration Modal --> |
| 135 |
`; |
| 136 |
|
| 137 |
const Modals = { |
| 138 |
template, |
| 139 |
mixins: [ApiMixin], |
| 140 |
data() { |
| 141 |
return { |
| 142 |
totalTrackedResources: 0, |
| 143 |
totalUntrackedResources: 100, |
| 144 |
openCreateGroupModal: false, |
| 145 |
openSyncModal: false, |
| 146 |
openCancelSyncModal: false, |
| 147 |
openResetModal: false, |
| 148 |
openDebugLogModal: false, |
| 149 |
progressPercentage: 0, |
| 150 |
intervalId: null, |
| 151 |
createGroupName: "", |
| 152 |
filteredLogs: [], |
| 153 |
searchLogs: "", |
| 154 |
copyMessage: "", |
| 155 |
resetSyncButtonRef: null, |
| 156 |
} |
| 157 |
}, |
| 158 |
computed: { |
| 159 |
remainingUntrackedResources() { |
| 160 |
return this.totalUntrackedResources - this.totalTrackedResources; |
| 161 |
}, |
| 162 |
}, |
| 163 |
mounted() { |
| 164 |
eventBus.on('show-create-group-modal', (data) => { |
| 165 |
this.openCreateGroupModal = true |
| 166 |
}); |
| 167 |
eventBus.on('show-sync-modal', (data) => { |
| 168 |
this.openSyncModal = true |
| 169 |
|
| 170 |
// TODO - send sync to background and continue setup |
| 171 |
this.simProgress() |
| 172 |
}); |
| 173 |
eventBus.on('show-cancel-sync-modal', (data) => { |
| 174 |
this.openCancelSyncModal = true |
| 175 |
}); |
| 176 |
eventBus.on('show-reset-modal', (ref) => { |
| 177 |
this.openResetModal = true |
| 178 |
}); |
| 179 |
eventBus.on('show-debug-modal', async (ref) => { |
| 180 |
try { |
| 181 |
loadStart(ref); |
| 182 |
const data = await this.getDebugLog() |
| 183 |
if (data.success) { |
| 184 |
this.debugLogs = data.log ? data.log.split('\n') : "No Logs Found" |
| 185 |
this.filteredLogs = [...this.debugLogs]; |
| 186 |
this.openDebugLogModal = true |
| 187 |
} else { |
| 188 |
eventBus.emit('alert-event', { error: 'An error occurred' }); |
| 189 |
} |
| 190 |
loadEnd(ref); |
| 191 |
} catch (err) { |
| 192 |
this.isLoading = false |
| 193 |
eventBus.emit('alert-event', { error: 'An error occurred' }); |
| 194 |
loadEnd(ref); |
| 195 |
} |
| 196 |
}); |
| 197 |
}, |
| 198 |
methods: { |
| 199 |
simProgress() { |
| 200 |
if (this.intervalId) return; |
| 201 |
this.progressPercentage = 0; |
| 202 |
this.totalTrackedResources = 0; |
| 203 |
|
| 204 |
this.intervalId = setInterval(() => { |
| 205 |
if (this.totalTrackedResources < this.totalUntrackedResources) { |
| 206 |
this.totalTrackedResources += 10; |
| 207 |
|
| 208 |
this.progressPercentage = Math.round( |
| 209 |
(this.totalTrackedResources / this.totalUntrackedResources) * 100 |
| 210 |
); |
| 211 |
} else { |
| 212 |
clearInterval(this.intervalId); // stop once it reaches 100 |
| 213 |
this.intervalId = null; |
| 214 |
|
| 215 |
// move to settings and close modal |
| 216 |
eventBus.emit('wizard-step-event', 2) |
| 217 |
this.openSyncModal = false |
| 218 |
} |
| 219 |
}, 500); |
| 220 |
}, |
| 221 |
async createGroup() { |
| 222 |
loadStart(this.$refs.createGroup); |
| 223 |
const groupNameValid = validate(this.$refs.wooMlCreateGroup, ['required', 'minLength:3'], { |
| 224 |
required: 'Group name is required.', |
| 225 |
}); |
| 226 |
if (groupNameValid) { |
| 227 |
const response = await this.createGroupApi(this.createGroupName) |
| 228 |
if (response.success) { |
| 229 |
eventBus.emit('trigger-group-created', response.data) |
| 230 |
} |
| 231 |
} |
| 232 |
loadEnd(this.$refs.createGroup); |
| 233 |
this.openCreateGroupModal = false |
| 234 |
}, |
| 235 |
resetIntegration() { |
| 236 |
eventBus.emit('reset-integration'); |
| 237 |
}, |
| 238 |
filterLogs() { |
| 239 |
const term = this.searchLogs.toLowerCase(); |
| 240 |
this.filteredLogs = this.debugLogs.filter(line => |
| 241 |
line.toLowerCase().includes(term) |
| 242 |
); |
| 243 |
}, |
| 244 |
// Highlight search term in logs |
| 245 |
highlightSearch(line) { |
| 246 |
if (!this.searchLogs) return line; |
| 247 |
if (typeof line !== 'string') return line; |
| 248 |
const term = this.searchLogs.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); // Escape special characters |
| 249 |
const regex = new RegExp(`(${term})`, 'gi'); |
| 250 |
return line.replace(regex, '<span class="woo-mailerlite-log-highlight">$1</span>'); |
| 251 |
}, |
| 252 |
copyDebugLogToClipboard() { |
| 253 |
if (navigator.clipboard && window.isSecureContext) { |
| 254 |
// Modern method (HTTPS only) |
| 255 |
navigator.clipboard.writeText(this.filteredLogs.join('\n')).then(() => { |
| 256 |
this.copyMessage = 'Copied!'; |
| 257 |
setTimeout(() => { |
| 258 |
this.copyMessage = ""; |
| 259 |
}, 2000); |
| 260 |
}).catch(err => { |
| 261 |
}); |
| 262 |
} else { |
| 263 |
const textarea = document.createElement("textarea"); |
| 264 |
textarea.value = this.filteredLogs.join('\n'); |
| 265 |
document.body.appendChild(textarea); |
| 266 |
textarea.select(); |
| 267 |
document.execCommand("copy"); |
| 268 |
document.body.removeChild(textarea); |
| 269 |
this.copyMessage = 'Copied!'; |
| 270 |
setTimeout(() => { |
| 271 |
this.copyMessage = ""; |
| 272 |
}, 2000); |
| 273 |
} |
| 274 |
}, |
| 275 |
} |
| 276 |
}; |
| 277 |
|
| 278 |
export default Modals; |
| 279 |
|