first commit

This commit is contained in:
sujan
2024-08-06 18:06:00 +05:45
commit a2fa49071a
2745 changed files with 391199 additions and 0 deletions

View File

@ -0,0 +1,70 @@
<div id="modal-api" class="modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fa-solid fa-cog"></i> {{ heading_title }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="form-api">
<div class="alert alert-info"><i class="fa-solid fa-info-circle"></i> {{ text_signup }}</div>
<div class="mb-3">
<label for="input-username" class="form-label">{{ entry_username }}</label> <input type="text" name="opencart_username" value="" placeholder="{{ entry_username }}" id="input-username" class="form-control"/>
<div id="error-username" class="invalid-feedback"></div>
</div>
<div class="mb-3">
<label for="input-secret" class="form-label">{{ entry_secret }}</label> <textarea name="opencart_secret" placeholder="{{ entry_secret }}" rows="8" id="input-secret" class="form-control"></textarea>
<div id="error-secret" class="invalid-feedback"></div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="submit" form="form-api" id="button-save" class="btn btn-primary"><i class="fa-solid fa-floppy-disk"></i> {{ button_save }}</button>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#form-api').on('submit', function(e) {
e.preventDefault();
$.ajax({
url: 'index.php?route=marketplace/api.save&user_token={{ user_token }}',
type: 'post',
dataType: 'json',
data: $('#form-api').serialize(),
beforeSend: function() {
$('#button-save').button('loading');
},
complete: function() {
$('#button-save').button('reset');
},
success: function(json) {
console.log(json);
$('.alert-dismissible').remove();
$('.invalid-feedback').removeClass('d-block');
if (json['error']) {
if (json['error']['warning']) {
$('#modal-api .modal-body').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error']['warning'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
for (key in json['error']) {
$('#input-' + key.replaceAll('_', '-')).addClass('is-invalid').find('.form-control, .form-select, .form-check-input, .form-check-label').addClass('is-invalid');
$('#error-' + key.replaceAll('_', '-')).html(json['error'][key]).addClass('d-block');
}
}
if (json['success']) {
$('#modal-api .modal-body').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
window.location.reload();
}
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
//--></script>

View File

@ -0,0 +1,103 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end">
<button type="submit" form="form-cron" formaction="{{ delete }}" data-bs-toggle="tooltip" title="{{ button_delete }}" onclick="return confirm('{{ text_confirm }}');" class="btn btn-danger"><i class="fa-regular fa-trash-can"></i></button>
</div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
<div class="card mb-3">
<div class="card-header"><i class="fa-solid fa-question-circle"></i> {{ text_instruction }}</div>
<div class="card-body">
<p>{{ text_cron_1 }}</p>
<p>{{ text_cron_2 }}</p>
<div class="mb-3">
<div class="input-group">
<div class="input-group-text">{{ entry_cron }}</div>
<input type="text" value="wget &quot;{{ cron }}&quot; --read-timeout=5400" id="input-cron" class="form-control"/>
<button type="button" id="button-copy" data-bs-toggle="tooltip" title="{{ button_copy }}" class="btn btn-light"><i class="fa-regular fa-copy"></i></button>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header"><i class="fa-solid fa-list"></i> {{ text_list }}</div>
<div id="cron" class="card-body">{{ list }}</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#cron').on('click', 'thead a, .pagination a', function (e) {
e.preventDefault();
$('#cron').load(this.href);
});
$('#cron').on('click', '.btn-success, .btn-warning, .btn-danger', function () {
var element = this;
$.ajax({
url: $(element).val(),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#cron').load($('#form-cron').attr('data-oc-load'));
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
$('#cron').on('click', '.btn-info', function () {
var element = this;
$('#modal-cron').remove();
html = '<div id="modal-cron" class="modal">';
html += ' <div class="modal-dialog">';
html += ' <div class="modal-content">';
html += ' <div class="modal-header">';
html += ' <h5 class="modal-title">{{ text_info|escape('js') }}</h5>';
html += ' <button type="button" class="btn-close" data-bs-dismiss="modal"></button>';
html += ' </div>';
html += ' <div class="modal-body">';
html += ' <div class="mb-3">';
html += ' <label for="input-description" class="form-label">{{ entry_description|escape('js') }}</label>';
html += ' <textarea placeholder="{{ entry_description|escape('js') }}" id="input-description" rows="5" class="form-control" disabled>' + $(element).attr('data-oc-description') + '</textarea>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += '</div>';
$('body').append(html);
var modal = new bootstrap.Modal(document.querySelector('#modal-cron'));
modal.show();
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,46 @@
<form id="form-cron" method="post" data-oc-toggle="ajax" data-oc-load="{{ action }}" data-oc-target="#cron">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td class="text-center" style="width: 1px;"><input type="checkbox" onclick="$('input[name*=\'selected\']').prop('checked', $(this).prop('checked'));" class="form-check-input"/></td>
<td class="text-start"><a href="{{ sort_code }}"{% if sort == 'code' %} class="{{ order|lower }}"{% endif %}>{{ column_code }}</a></td>
<td class="text-start"><a href="{{ sort_cycle }}"{% if sort == 'cycle' %} class="{{ order|lower }}"{% endif %}>{{ column_cycle }}</a></td>
<td class="text-start"><a href="{{ sort_action }}"{% if sort == 'action' %} class="{{ order|lower }}"{% endif %}>{{ column_action }}</a></td>
<td class="text-start d-none d-lg-table-cell"><a href="{{ sort_date_added }}"{% if sort == 'date_added' %} class="{{ order|lower }}"{% endif %}>{{ column_date_added }}</a></td>
<td class="text-start d-none d-lg-table-cell"><a href="{{ sort_date_modified }}"{% if sort == 'date_modified' %} class="{{ order|lower }}"{% endif %}>{{ column_date_modified }}</a></td>
<td class="text-end">{{ column_action }}</td>
</tr>
</thead>
<tbody>
{% if crons %}
{% for cron in crons %}
<tr>
<td class="text-center"><input type="checkbox" name="selected[]" value="{{ cron.cron_id }}" class="form-check-input"/></td>
<td class="text-start">{{ cron.code }}</td>
<td class="text-start">{{ cron.cycle }}</td>
<td class="text-start">{{ cron.action }}</td>
<td class="text-start d-none d-lg-table-cell">{{ cron.date_added }}</td>
<td class="text-start d-none d-lg-table-cell">{{ cron.date_modified }}</td>
<td class="text-end text-nowrap"><button type="button" data-oc-description="{{ cron.description }}" data-oc-trigger="{{ cron.trigger }}" data-oc-action="{{ cron.action }}" class="btn btn-info"><i class="fa-solid fa-info-circle"></i></button>
<button type="button" value="{{ cron.run }}" data-bs-toggle="tooltip" title="{{ button_run }}" class="btn btn-warning"><i class="fa-solid fa-play"></i></button>
{% if not cron.status %}
<button type="button" value="{{ cron.enable }}" data-bs-toggle="tooltip" title="{{ button_enable }}" class="btn btn-success"><i class="fa-solid fa-plus-circle"></i></button>
{% else %}
<button type="button" value="{{ cron.disable }}" data-bs-toggle="tooltip" title="{{ button_disable }}" class="btn btn-danger"><i class="fa-solid fa-minus-circle"></i></button>
{% endif %}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="text-center" colspan="7">{{ text_no_results }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm-6 text-start">{{ pagination }}</div>
<div class="col-sm-6 text-end">{{ results }}</div>
</div>
</form>

View File

@ -0,0 +1,99 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end">
<button type="submit" form="form-event" formaction="{{ delete }}" data-bs-toggle="tooltip" title="{{ button_delete }}" onclick="return confirm('{{ text_confirm }}');" class="btn btn-danger"><i class="fa-regular fa-trash-can"></i></button>
</div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
<div class="alert alert-info"><i class="fa-solid fa-info-circle"></i> {{ text_event }}</div>
<div class="card">
<div class="card-header"><i class="fa-solid fa-list"></i> {{ text_list }}</div>
<div id="event" class="card-body">{{ list }}</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#event').on('click', 'thead a, .pagination a', function (e) {
e.preventDefault();
$('#event').load(this.href);
});
$('#event').on('click', '.btn-success, .btn-danger', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).val(),
type: 'post',
data: $('#event input[name=\'selected[]\']:checked'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#event').load($('#form-event').attr('data-oc-load'));
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
$('#event').on('click', '.btn-info', function () {
var element = this;
$('#modal-event').remove();
html = '<div id="modal-event" class="modal">';
html += ' <div class="modal-dialog">';
html += ' <div class="modal-content">';
html += ' <div class="modal-header">';
html += ' <h5 class="modal-title">{{ text_info|escape('js') }}</h5>';
html += ' <button type="button" class="btn-close" data-bs-dismiss="modal"></button>';
html += ' </div>';
html += ' <div class="modal-body">';
html += ' <div class="mb-3">';
html += ' <label for="input-description" class="form-label">{{ entry_description|escape('js') }}</label> <textarea placeholder="{{ entry_description|escape('js') }}" id="input-description" rows="5" class="form-control" disabled>' + $(element).attr('data-oc-description') + '</textarea>';
html += ' </div>';
html += ' <div class="mb-3">';
html += ' <label for="input-trigger" class="form-label">{{ entry_trigger|escape('js') }}</label> <textarea placeholder="{{ entry_trigger|escape('js') }}" id="input-trigger" class="form-control" disabled>' + $(element).attr('data-oc-trigger') + '</textarea>';
html += ' </div>';
html += ' <div class="mb-3">';
html += ' <label for="input-action" class="form-label">{{ entry_action|escape('js') }}</label> <textarea placeholder="{{ entry_action|escape('js') }}" id="input-action" class="form-control" disabled>' + $(element).attr('data-oc-action') + '</textarea>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += '</div>';
$('body').append(html);
var modal = new bootstrap.Modal(document.querySelector('#modal-event'));
modal.show();
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,39 @@
<form id="form-event" method="post" data-oc-toggle="ajax" data-oc-load="{{ action }}" data-oc-target="#event">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td class="text-center" style="width: 1px;"><input type="checkbox" onclick="$('input[name*=\'selected\']').prop('checked', $(this).prop('checked'));" class="form-check-input"/></td>
<td class="text-start"><a href="{{ sort_code }}"{% if sort == 'code' %} class="{{ order|lower }}"{% endif %}>{{ column_code }}</a></td>
<td class="text-end d-none d-lg-table-cell"><a href="{{ sort_sort_order }}"{% if sort == 'sort_order' %} class="{{ order|lower }}"{% endif %}>{{ column_sort_order }}</a></td>
<td class="text-end">{{ column_action }}</td>
</tr>
</thead>
<tbody>
{% if events %}
{% for event in events %}
<tr>
<td class="text-center"><input type="checkbox" name="selected[]" value="{{ event.event_id }}" class="form-check-input"/></td>
<td class="text-start">{{ event.code }}</td>
<td class="text-end d-none d-lg-table-cell">{{ event.sort_order }}</td>
<td class="text-end text-nowrap"><button type="button" data-oc-description="{{ event.description }}" data-oc-trigger="{{ event.trigger }}" data-oc-action="{{ event.action }}" class="btn btn-info"><i class="fa-solid fa-info-circle"></i></button>
{% if not event.status %}
<button type="button" value="{{ event.enable }}" data-bs-toggle="tooltip" title="{{ button_enable }}" class="btn btn-success"><i class="fa-solid fa-plus-circle"></i></button>
{% else %}
<button type="button" value="{{ event.disable }}" data-bs-toggle="tooltip" title="{{ button_disable }}" class="btn btn-danger"><i class="fa-solid fa-minus-circle"></i></button>
{% endif %}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="text-center" colspan="4">{{ text_no_results }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm-6 text-start">{{ pagination }}</div>
<div class="col-sm-6 text-end">{{ results }}</div>
</div>
</form>

View File

@ -0,0 +1,199 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
<div class="card">
<div class="card-header"><i class="fa-solid fa-puzzle-piece"></i> {{ text_list }}</div>
<div class="card-body">
<fieldset>
<legend>{{ text_type }}</legend>
<div class="card bg-light">
<div class="card-body">
<div class="input-group">
<select name="type" id="input-type" class="form-select">
{% for category in categories %}
<option value="{{ category.href }}"{% if type == category.code %} selected{% endif %}>{{ category.text }}</option>
{% endfor %}
</select>
<div class="input-group-text"><i class="fa-solid fa-filter"></i>&nbsp;{{ text_filter }}</div>
</div>
</div>
</div>
</fieldset>
<div id="extension">{{ extension }}</div>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#input-type').on('change', function () {
$.ajax({
url: $(this).val(),
dataType: 'html',
beforeSend: function () {
$('.fa-filter').addClass('fa-circle-notch fa-spin');
$('.fa-filter').removeClass('fa-filter');
$('#input-type').prop('disabled', true);
},
complete: function () {
$('.fa-circle-notch').addClass('fa-filter');
$('.fa-circle-notch').removeClass('fa-circle-notch fa-spin');
$('#input-type').prop('disabled', false);
},
success: function (html) {
$('#extension').html(html);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Download promotion extension
$('#extension').on('click', '#recommended .btn-primary', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('value'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#extension').before('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div></div>');
}
if (json['success']) {
$('#extension').before('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
// Manually build the url so no need to refresh extensions and can trigger install
// Once the extension is downloaded we trigger the installer
$(element).parent().find('.dropdown-menu').html('<a href="index.php?route=marketplace/installer.install&user_token={{ user_token }}&extension_install_id=' + json['extension_install_id'] + '" class="dropdown-item"><i class="fa-solid fa-plus-circle fa-fw"></i> {{ text_install }}</a> <a href="index.php?route=marketplace/installer.delete&user_token={{ user_token }}&extension_install_id=' + json['extension_install_id'] + '" class="dropdown-item"><i class="fa-regular fa-trash-can fa-fw"></i> {{ text_delete }}</a>');
$(element).parent().find('.dropdown-item:first').trigger('click');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
$(element).button('reset');
}
});
});
// Download dropdown
$('#extension').on('click', '.dropdown-item', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'json',
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#extension').before('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div></div>');
}
if (json['success']) {
$('#extension').before('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#extension').load($('#input-type').val());
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Install
$('#extension').on('click', '.btn-success', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('loading');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#input-type').trigger('change');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Uninstall / Delete
$('#extension').on('click', '.btn-danger, .btn-outline-danger', function (e) {
e.preventDefault();
if (confirm('{{ text_confirm }}')) {
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#input-type').trigger('change');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,210 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end"><button type="button" id="button-upload" data-bs-toggle="tooltip" title="{{ button_upload }}" class="btn btn-primary"><i class="fa-solid fa-upload"></i></button></div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
<div class="card">
<div class="card-header"><i class="fa-solid fa-puzzle-piece"></i> {{ heading_title }}</div>
<div class="card-body">
<fieldset>
<legend>{{ text_progress }}</legend>
<div class="row mb-3">
<label class="col-sm-2 col-form-label">{{ entry_progress }}</label>
<div class="col-sm-10 mt-2">
<div class="progress">
<div id="progress-bar" class="progress-bar" style="width: 0%;"></div>
</div>
<div id="progress-text"></div>
</div>
</div>
</fieldset>
<fieldset>
<legend>{{ text_installed }}</legend>
<div id="extension">{{ list }}</div>
</fieldset>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#extension').on('click', 'thead a, .pagination a', function (e) {
e.preventDefault();
$('#extension').load(this.href);
});
// Upload
$('#button-upload').on('click', function () {
var element = this;
if (!$('#button-upload').prop('disabled')) {
$('#form-upload').remove();
$('body').prepend('<form enctype="multipart/form-data" id="form-upload" style="display: none;"><input type="file" name="file"/></form>');
$('#form-upload input[name=\'file\']').trigger('click');
$('#form-upload input[name=\'file\']').on('change', function () {
if ((this.files[0].size / 1024) > {{ config_file_max_size }}) {
$(this).val('');
alert('{{ error_upload_size }}');
}
if (!this.files[0].name.endsWith('.ocmod.zip')) {
$(this).val('');
alert('{{ error_filetype }}');
}
});
if (typeof timer != 'undefined') {
clearInterval(timer);
}
timer = setInterval(function () {
if ($('#form-upload input[name=\'file\']').val() !== '') {
clearInterval(timer);
$.ajax({
url: 'index.php?route=marketplace/installer.upload&user_token={{ user_token }}',
type: 'post',
data: new FormData($('#form-upload')[0]),
dataType: 'json',
cache: false,
contentType: false,
processData: false,
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#extension').load('index.php?route=marketplace/installer.list&user_token={{ user_token }}');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
}, 500);
}
});
// Install
$('#extension').on('click', '.btn-success, .btn-warning', function (e) {
e.preventDefault();
var element = this;
$(element).button('loading');
var next = $(element).attr('href');
$('#progress-bar').removeClass('bg-danger bg-success').css('width', '0%');
$('#progress-text').html('');
var installer = function () {
return $.ajax({
url: next,
dataType: 'json',
success: function (json) {
console.log(json);
$('.alert-dismissible').remove();
if (json['error']) {
$('#progress-bar').addClass('bg-danger');
$('#progress-text').html('<div class="text-danger">' + json['error'] + '</div>');
$(element).button('reset');
}
if (json['text']) {
$('#progress-bar').addClass('bg-success');
$('#progress-text').html('<div class="text-success">' + json['text'] + '</div>');
}
if (json['success']) {
$('#progress-bar').addClass('bg-success').css('width', '100%');
$('#progress-text').html('<div class="text-success">' + json['success'] + '</div>');
$(element).button('reset');
$('#extension').load('index.php?route=marketplace/installer.list&user_token={{ user_token }}');
}
if (json['next']) {
next = json['next'];
chain.attach(installer);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
$(element).button('reset');
}
});
};
chain.attach(installer);
});
// Delete
$('#extension').on('click', '.btn-danger', function (e) {
e.preventDefault();
var element = this;
if (confirm('{{ text_confirm }}')) {
$.ajax({
url: $(element).attr('href'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
console.log(json);
$('.alert-dismissible').remove();
if (json['error']) {
$('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#extension').load('index.php?route=marketplace/installer.list&user_token={{ user_token }}');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,46 @@
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td class="text-start"><a href="{{ sort_name }}"{% if sort == 'name' %} class="{{ order|lower }}"{% endif %}>{{ column_name }}</a></td>
<td class="text-start"><a href="{{ sort_version }}"{% if sort == 'version' %} class="{{ order|lower }}"{% endif %}>{{ column_version }}</a></td>
<td class="text-start"><a href="{{ sort_date_added }}"{% if sort == 'date_added' %} class="{{ order|lower }}"{% endif %}>{{ column_date_added }}</a></td>
<td class="text-end" style="min-width: 105px;">{{ column_action }}</td>
</tr>
</thead>
<tbody>
{% if extensions %}
{% for extension in extensions %}
<tr>
<td class="text-start">
{% if extension.link %}
<a href="{{ extension.link }}" target="_blank">{{ extension.name }}</a>
{% else %}
{{ extension.name }}
{% endif %}
</td>
<td class="text-start align-text-top">{{ extension.version }}</td>
<td class="text-start align-text-top">{{ extension.date_added }}</td>
<td class="text-end align-text-top text-nowrap">
{% if not extension.status %}
<a href="{{ extension.install }}" data-bs-toggle="tooltip" title="{{ button_install }}" class="btn btn-success"><i class="fa-solid fa-plus-circle"></i></a>
<a href="{{ extension.delete }}" data-bs-toggle="tooltip" title="{{ button_delete }}" class="btn btn-danger"><i class="fa-regular fa-trash-can"></i></a>
{% else %}
<a href="{{ extension.uninstall }}" data-bs-toggle="tooltip" title="{{ button_uninstall }}" class="btn btn-warning"><i class="fa-solid fa-minus-circle"></i></a>
<button type="button" data-bs-toggle="tooltip" title="{{ button_delete }}" class="btn btn-danger" disabled><i class="fa-regular fa-trash-can"></i></button>
{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="text-center" colspan="4">{{ text_no_results }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm-6 text-start">{{ pagination }}</div>
<div class="col-sm-6 text-end">{{ results }}</div>
</div>

View File

@ -0,0 +1,42 @@
{% if comments %}
{% for comment in comments %}
<div id="comment-{{ comment.extension_comment_id }}" class="media">
<img src="{{ comment.image }}" alt="{{ comment.member }}" title="{{ comment.member }}" class="me-3 rounded-circle"/>
<div class="media-body">
<h5 class="mt-0">{{ comment.member }} <span>{{ comment.date_added }}</span></h5>
<p>{{ comment.comment }}</p>
<div class="reply">
<div> {% if comment.reply %}
{% for reply in comment.reply %}
<div class="media">
<img src="{{ reply.image }}" alt="{{ reply.member }}" title="{{ reply.member }}" class="me-3 rounded-circle"/>
<div class="media-body">
<h5 class="mt-0">{{ reply.member }} <span>{{ reply.date_added }}</h5>
<p>{{ reply.comment }}</p>
</div>
</div>
{% endfor %}
{% if comment.next %}
<div class="text-center"><a href="{{ comment.next }}" class="btn btn-block">{{ text_more }}</a></div>
{% endif %}
{% endif %}<a href="{{ comment.refresh }}" class="reply-refresh hide">{{ text_refresh }}</a></div>
</div>
<p class="text-end">
<button type="button" class="btn btn-link btn-sm">{{ button_reply }}</button>
</p>
<div class="reply-input-box" style="display: none;">
<div class="media">
<div class="media-body">
<div class="mb-3">
<label for="input-comment-{{ comment.extension_comment_id }}">{{ text_comment_add }}</label> <textarea name="comment" placeholder="{{ text_write }}" id="input-comment-{{ comment.extension_comment_id }}" class="form-control"></textarea>
</div>
<div class="text-end"><a href="{{ comment.add }}" class="btn btn-primary btn-sm">{{ button_comment }}</a></div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
<br/>
<div class="text-center">{{ pagination }}</div>
{% endif %}

View File

@ -0,0 +1,32 @@
<table class="table table-bordered">
<thead>
<td>{{ text_name }}</td>
<td>{{ text_date_added }}</td>
<td class="text-end">{{ text_action }}</td>
</thead>
<tbody>
{% if downloads %}
{% for download in downloads %}
<tr>
<td>{{ download.name }}</td>
<td>{{ download.date_added }}</td>
<td class="text-end">
<div class="dropdown">
<div class="btn-group">
<button type="button" value="{{ download.download }}" class="btn btn-primary"{% if not download.download %} disabled{% endif %}><i class="fa-solid fa-download"></i> {{ button_download }}</button>
<button type="button" data-bs-toggle="dropdown" class="btn btn-outline-dark dropdown-toggle dropdown-toggle-split"><i class="fa-solid fa-caret-down"></i></button>
<div class="dropdown-menu dropdown-menu-end">
<a href="{{ download.install }}" class="dropdown-item{% if not download.install %} disabled{% endif %}"><i class="fa-solid fa-plus-circle fa-fw"></i> {{ text_install }}</a> <a href="{{ download.uninstall }}" class="dropdown-item{% if not download.uninstall %} disabled{% endif %}"><i class="fa-solid fa-minus-circle fa-fw"></i> {{ text_uninstall }}</a> <a href="{{ download.delete }}" class="dropdown-item{% if not download.delete %} disabled{% endif %}"><i class="fa-regular fa-trash-can fa-fw"></i> {{ text_delete }}</a>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="3" class="text-center">{{ text_no_results }}</td>
</tr>
{% endif %}
</tbody>
</table>

View File

@ -0,0 +1,456 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end">
{% if signature %}
<button type="button" id="button-api" data-bs-toggle="tooltip" title="{{ button_api }}" class="btn btn-info"><i class="fa-solid fa-cog"></i></button>
{% else %}
<button type="button" id="button-api" data-bs-toggle="tooltip" title="{{ button_api }}" data-placement="left" class="btn btn-danger"><i class="fa-solid fa-triangle-exclamation"></i></button>
{% endif %}
<a href="{{ back }}" data-bs-toggle="tooltip" title="{{ button_back }}" class="btn btn-light"><i class="fa-solid fa-reply"></i></a>
</div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div id="marketplace-extension-info" class="container-fluid">
{% if error_warning %}
<div class="alert alert-danger"><i class="fa-solid fa-circle-exclamation"></i> {{ error_warning }}</div>
{% endif %}
<div class="card">
<div class="card-header"><i class="fa-solid fa-puzzle-piece"></i> {{ name }}</div>
<div class="card-body">
<div class="row extension-info">
<div class="col-md-8 col-lg-9">
{% if banner %}
<div id="banner" class="text-center img-thumbnail mb-3"><img src="{{ banner }}" title="{{ name }}" alt="{{ name }}" class="img-fluid"/></div>
{% endif %}
<div class="row thumbnails">
{% for image in images %}
<div class="col-4 col-md-3 col-lg-2 mb-3"><a href="{{ image.popup }}"><img src="{{ image.thumb }}" alt="{{ image.name }}" title="{{ image.name }}" class="img-fluid img-thumbnail"/></a></div>
{% endfor %}
</div>
<ul class="nav nav-tabs">
<li class="nav-item"><a href="#tab-description" class="nav-link active" data-bs-toggle="tab">{{ tab_general }}</a></li>
<li class="nav-item"><a href="#tab-documentation" class="nav-link" data-bs-toggle="tab">{{ tab_documentation }}</a></li>
<li class="nav-item"><a href="#tab-download" class="nav-link" data-bs-toggle="tab">{{ tab_download }}</a></li>
<li class="nav-item"><a href="#tab-comment" class="nav-link" data-bs-toggle="tab">{{ tab_comment }} ({{ comment_total }})</a></li>
</ul>
<div class="tab-content">
<div id="tab-description" class="tab-pane fade show active">{{ description }}</div>
<div id="tab-documentation" class="tab-pane fade">{{ documentation }}</div>
<div id="tab-download" class="tab-pane fade">
<fieldset>
<legend>{{ text_available }}</legend>
<div id="download"></div>
</fieldset>
</div>
<div id="tab-comment" class="tab-pane">
<fieldset>
<legend>{{ text_comment_add }}</legend>
<div class="mb-3">
<textarea name="comment" rows="5" placeholder="{{ text_write }}" id="input-history-comment" class="form-control"></textarea>
</div>
<div class="text-end">
<button type="button" id="button-comment" class="btn btn-primary">{{ button_comment }}</button>
</div>
</fieldset>
<br/>
<fieldset>
<legend>{{ text_comment }}</legend>
<div id="comment"></div>
</fieldset>
</div>
</div>
</div>
<div class="col-md-4 col-lg-3">
<div id="buy" class="card mb-3">
<div class="card-body">
{% if license == '1' and not purchased %}
<button type="button" id="button-buy" class="btn btn-success btn-lg btn-block">{{ button_purchase }}</button>
{% endif %}
<div id="price" class="row">
<div class="col-lg-5"><strong>{{ text_price }}</strong></div>
<div class="col-lg-7 text-end">{% if license %}
{{ price }}
{% else %}
{{ text_free }}
{% endif %}
</div>
</div>
<hr>
<ul class="list-check">
<li>{{ text_partner }}</li>
<li>{{ text_support }}</li>
<li>{{ text_documentation }}</li>
</ul>
<hr>
<div class="row">
<div class="col-md-5"><strong>{{ text_rating }}</strong></div>
<div class="col-md-7 text-end">{% for i in 1..5 %}
{% if rating < i %}
<i class="fa-regular fa-star"></i>
{% else %}
<i class="fa-solid fa-star"></i>
{% endif %}
{% endfor %} ({{ rating_total }})
</div>
</div>
<hr>
<div class="row">
<div class="col-md-5"><strong>{{ text_compatibility }}</strong></div>
<div class="col-md-7 text-end">{{ compatibility }}</div>
</div>
<hr>
<div class="row">
<div class="col-md-5"><strong>{{ text_date_modified }}</strong></div>
<div class="col-md-7 text-end">{{ date_modified }}</div>
</div>
<hr>
<div class="row">
<div class="col-md-5"><strong>{{ text_date_added }}</strong></div>
<div class="col-md-7 text-end">{{ date_added }}</div>
</div>
</div>
</div>
<div id="sales" class="card mb-3">
<div class="card-body"><i class="fa-solid fa-shopping-cart"></i> <strong>{{ sales }}</strong> {{ text_sales }}</div>
</div>
<div id="sales" class="card mb-3">
<div class="card-body"><i class="fa-solid fa-download"></i> <strong>{{ downloaded }}</strong> {{ text_downloaded }}</div>
</div>
<div class="card mb-3">
<div class="card-body">
<div class="media">
<img src="{{ member_image }}" alt="{{ member_username }}" title="{{ member_username }}" class="me-3 rounded-circle">
<div class="media-body">
<h5 class="mt-0"><a href="{{ filter_member }}">{{ member_username }}</a></h5>
<small>{{ text_member_since }} {{ member_date_added }}</small>
</div>
</div>
<br/>
<a href="{{ filter_member }}" class="btn btn-primary btn-lg btn-block">{{ button_view_all }}</a> <a href="https://www.opencart.com/index.php?route=support/seller&amp;extension_id={{ extension_id }}" target="_blank" class="btn btn-outline-secondary btn-lg btn-block">{{ button_support }}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#button-api').on('click', function (e) {
$('#modal-api').remove();
$.ajax({
url: 'index.php?route=marketplace/api&user_token={{ user_token }}',
dataType: 'html',
beforeSend: function () {
$('#button-api').button('loading');
},
complete: function () {
$('#button-api').button('reset');
},
success: function (html) {
$('body').append(html);
$('#modal-api').modal('show');
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
//--></script>
<script type="text/javascript"><!--
$('#button-buy').on('click', function (e) {
e.preventDefault();
$('#modal-purchase').remove();
html = '<div id="modal-purchase" class="modal">';
html += ' <div class="modal-dialog">';
html += ' <div class="modal-content">';
html += ' <div class="modal-header">';
html += ' <h5 class="modal-title">{{ text_purchase|escape('js') }}</h5>';
html += ' <button type="button" class="btn-close" data-bs-dismiss="modal"></button>';
html += ' </div>';
html += ' <div class="modal-body">';
html += ' <p>{{ text_pin|escape('js') }}</p>';
html += ' <p>{{ text_secure|escape('js') }}</p>';
html += ' <div class="mb-3">';
html += ' <label for="input-pin">{{ entry_pin|escape('js') }}</label>';
html += ' <input type="password" name="pin" value="" placeholder="{{ entry_pin|escape('js') }}" id="input-pin" class="form-control"/>';
html += ' </div>';
html += ' <div class="mb-3 text-end">';
html += ' <div class="text-end"><a href="https://www.opencart.com/index.php?route=support/contact" class="btn btn-light btn-lg" target="_blank">{{ button_forgot_pin|escape('js') }}</a></div>';
html += ' <button type="button" id="button-purchase" class="btn btn-primary btn-lg">{{ button_purchase|escape('js') }}</button>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += ' </div>';
html += '</div>';
$('body').append(html);
$('#modal-purchase').modal('show');
});
$('body').on('click', '#modal-purchase #button-purchase', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: 'index.php?route=marketplace/marketplace.purchase&user_token={{ user_token }}&extension_id={{ extension_id }}',
type: 'post',
data: $('#input-pin'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#modal-purchase .modal-body').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#modal-purchase').modal('hide');
$('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#download').load('index.php?route=marketplace/marketplace.extension&user_token={{ user_token }}&extension_id={{ extension_id }}');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Download
$('#download').load('index.php?route=marketplace/marketplace.extension&user_token={{ user_token }}&extension_id={{ extension_id }}');
$('#tab-download').on('click', '.btn-primary', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).val(),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#download').before('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div></div>');
}
if (json['success']) {
$('#download').before('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
$('#tab-download').on('click', '.dropdown-item', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#download').before('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div></div>');
}
if (json['success']) {
$('#download').before('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#download').load('index.php?route=marketplace/marketplace.extension&user_token={{ user_token }}&extension_id={{ extension_id }}');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Comment
$('#comment').on('click', '.pagination a', function (e) {
e.preventDefault();
$('#comment').load(this.href);
});
$('#comment').load('index.php?route=marketplace/marketplace.comment&user_token={{ user_token }}&extension_id={{ extension_id }}');
// Add comment
$('#button-comment').on('click', function () {
$.ajax({
url: 'index.php?route=marketplace/marketplace.addComment&user_token={{ user_token }}&extension_id={{ extension_id }}',
type: 'post',
dataType: 'json',
data: 'comment=' + encodeURIComponent($('#input-history-comment').val()),
beforeSend: function () {
$('#button-comment').button('loading');
},
complete: function () {
$('#button-comment').button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#tab-comment').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#tab-comment').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#comment').load('index.php?route=marketplace/marketplace.comment&user_token={{ user_token }}&extension_id={{ extension_id }}');
$('#input-history-comment').val('');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Next replies
$('#comment').on('click', '.btn-block', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'html',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (html) {
$(element).parent().parent().parent().append(html);
$(element).parent().remove();
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Reply
$('#comment').on('click', '.btn-link', function (e) {
e.preventDefault();
$(this).parent().parent().find('.reply-input-box').toggle();
});
// Add reply
$('#comment').on('click', '.btn-primary', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
type: 'post',
dataType: 'json',
data: 'comment=' + encodeURIComponent($(element).parents('.reply-input-box').find('textarea[name=\'comment\']').val()),
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$(element).parents('.reply-input-box').before('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$(element).parents('.reply-input-box').before('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$(element).parents('.reply-input-box').parents('.media').find('.reply-refresh').last().trigger('click');
$(element).parents('.reply-input-box').find('textarea[name=\'comment\']').val('');
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
// Refresh
$('#comment').on('click', '.reply-refresh', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).attr('href'),
dataType: 'html',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (html) {
$(element).parent().replaceWith(html);
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
$(document).ready(function () {
$('.thumbnails').magnificPopup({
type: 'image',
delegate: 'a',
gallery: {
enabled: true
}
});
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,189 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end">
{% if signature %}
<button type="button" id="button-api" data-bs-toggle="tooltip" title="{{ button_api }}" class="btn btn-info"><i class="fa-solid fa-cog"></i></button>
{% else %}
<button type="button" id="button-api" data-bs-toggle="tooltip" title="{{ button_api }}" data-placement="left" class="btn btn-danger"><i class="fa-solid fa-triangle-exclamation"></i></button>
{% endif %}
</div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
{% if error_warning %}
<div class="alert alert-danger"><i class="fa-solid fa-triangle-exclamation"></i> {{ error_warning }}</div>
{% endif %}
<div class="card">
<div class="card-header"><i class="fa-solid fa-puzzle-piece"></i> {{ text_list }}</div>
<div class="card-body">
<div class="card bg-light">
<div class="card-body">
<div id="extension-filter" class="input-group dropdown">
<input type="text" name="filter_search" value="{{ filter_search }}" placeholder="{{ text_search }}" id="input-search" class="form-control"/>
{% for category in categories %}
{% if category.value == filter_category %}
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">{{ text_category }} ({{ category.text }}) <i class="fa-solid fa-caret-down"></i></button>
{% endif %}
{% endfor %}
<div class="dropdown-menu dropdown-menu-end">
{% for category in categories %}
<a href="{{ category.href }}" class="dropdown-item">{{ category.text }}</a>
{% endfor %}
</div>
<button type="button" id="button-filter" data-bs-toggle="tooltip" title="{{ button_filter }}" class="btn btn-primary"><i class="fa-solid fa-filter"></i></button>
</div>
<input type="hidden" name="filter_category_id" value="{{ filter_category_id }}" class="form-control"/> <input type="hidden" name="filter_download_id" value="{{ filter_download_id }}" class="form-control"/> <input type="hidden" name="filter_rating" value="{{ filter_rating }}" class="form-control"/> <input type="hidden" name="filter_license" value="{{ filter_license }}" class="form-control"/> <input type="hidden" name="filter_partner" value="{{ filter_partner }}" class="form-control"/> <input type="hidden" name="sort" value="{{ sort }}" class="form-control"/>
</div>
</div>
<br/>
<div class="row mb-4">
<div class="col-sm-auto me-sm-auto mb-2 mb-lg-0">
<div class="btn-group">{% for license in licenses %}
{% if license.value == filter_license %}<a href="{{ license.href }}" class="btn btn-light active">{{ license.text }}</a>{% else %}<a href="{{ license.href }}" class="btn btn-light">{{ license.text }}</a>{% endif %}
{% endfor %}</div>
</div>
<div class="col-xl-3 col-lg-5 col-sm-auto">
<div class="input-group float-end">
<div class="input-group-text"><i class="fa-solid fa-arrow-down-short-wide"></i></div>
<select onchange="location = this.value;" class="form-select">
{% for sorts in sorts %}
<option value="{{ sorts.href }}"{% if sorts.value == sort %} selected{% endif %}>{{ sorts.text }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div>
{% if promotions %}
<h3>{{ text_featured }}</h3>
<div class="row">
{% for extension in promotions %}
{% if extension %}
<div class="col-lg-3 col-md-4 col-sm-6 col-12">
<section>
<div class="extension-preview text-center">
<a href="{{ extension.href }}">
<div class="extension-description">
</div>
<img src="{{ extension.image }}" alt="{{ extension.name }}" title="{{ extension.name }}" class="img-fluid"/></a>
</div>
<div class="extension-name">
<h4><a href="{{ extension.href }}">{{ extension.name }}</a></h4>
{{ extension.price }}</div>
<div class="extension-rate">
<div class="row">
<div class="col-6">{% for i in 1..5 %}
{% if extension.rating < i %}<i class="fa-regular fa-star"></i>{% else %}<i class="fa-solid fa-star"></i>{% endif %}
{% endfor %}</div>
<div class="col-6">
<div class="text-end">{{ extension.rating_total }} {{ text_reviews }}</div>
</div>
</div>
</div>
</section>
</div>
{% endif %}
{% endfor %}
</div>
<hr/>
{% endif %}
{% if extensions %}
<div class="row">
{% for extension in extensions %}
{% if extension %}
<div class="col-lg-3 col-md-4 col-sm-6 col-12">
<section>
<div class="extension-preview text-center"><a href="{{ extension.href }}">
<div class="extension-description"></div>
<img src="{{ extension.image }}" alt="{{ extension.name }}" title="{{ extension.name }}" class="img-fluid"/></a></div>
<div class="extension-name">
<h4><a href="{{ extension.href }}">{{ extension.name }}</a></h4>
{{ extension.price }}</div>
<div class="extension-rate">
<div class="row">
<div class="col-6">{% for i in 1..5 %}
{% if extension.rating < i %}<i class="fa-regular fa-star"></i>{% else %}<i class="fa-solid fa-star"></i>{% endif %}
{% endfor %}</div>
<div class="col-6">
<div class="text-end">{{ extension.rating_total }} {{ text_reviews }}</div>
</div>
</div>
</div>
</section>
</div>
{% endif %}
{% endfor %}</div>
{% else %}
<p class="text-center">{{ text_no_results }}</p>
{% endif %}
</div>
<div class="row">
<div class="col-sm-12 text-center">{{ pagination }}</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#button-api').on('click', function (e) {
$('#modal-api').remove();
$.ajax({
url: 'index.php?route=marketplace/api&user_token={{ user_token }}',
dataType: 'html',
beforeSend: function () {
$('#button-api').button('loading');
},
complete: function () {
$('#button-api').button('reset');
},
success: function (html) {
$('body').append(html);
$('#modal-api').modal('show');
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
//--></script>
<script type="text/javascript"><!--
$('#button-filter').on('click', function (e) {
var url = 'index.php?route=marketplace/marketplace&user_token={{ user_token }}';
var input = $('#extension-filter :input');
for (i = 0; i < input.length; i++) {
if ($(input[i]).val() !== '') {
url += '&' + $(input[i]).attr('name') + '=' + $(input[i]).val()
}
}
download();
location = url;
});
$('#input-search').keydown(function (e) {
if (e.keyCode == 13) {
e.preventDefault();
$('#button-filter').trigger('click');
}
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,17 @@
<div>
{% if replies %}
{% for reply in replies %}
<div class="media">
<div class="media-left"><img src="{{ reply.image }}" alt="{{ reply.member }}" title="{{ reply.member }}" class="media-object"/></div>
<div class="media-body">
<p class="media-heading">{{ reply.member }} <span>{{ reply.date_added }}</span></p>
<p>{{ reply.comment }}</p>
</div>
</div>
{% endfor %}
{% if next %}
<div class="text-center"><a href="{{ next }}" class="btn btn-block">{{ text_more }}</a></div>
{% endif %}
{% endif %}
<a href="{{ refresh }}" class="reply-refresh hide">{{ button_refresh }}</a>
</div>

View File

@ -0,0 +1,37 @@
{% if banner %}
<div class="text-center">{{ banner }}</div>
<br/>
{% endif %}
{% if extensions %}
<fieldset id="recommended">
<legend>{{ text_recommended }}</legend>
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td class="text-start">{{ column_name }}</td>
<td class="text-end">{{ column_action }}</td>
</tr>
</thead>
<tbody>
{% for extension in extensions %}
<tr>
<td class="text-start"><a href="{{ extension.href }}">{{ extension.name }}</a></td>
<td class="text-end">
<div class="dropdown">
<div class="btn-group">
<button type="button" value="{{ extension.download }}" data-bs-toggle="tooltip" title="{{ button_download }}" class="btn btn-primary"{% if not extension.download %} disabled{% endif %}><i class="fa-solid fa-download"></i></button>
<button type="button" data-bs-toggle="dropdown" class="btn btn-outline-dark dropdown-toggle dropdown-toggle-split"><i class="fa-solid fa-caret-down"></i></button>
<div class="dropdown-menu dropdown-menu-end">
<a href="{{ extension.install }}" class="dropdown-item{% if not extension.install %} disabled{% endif %}"><i class="fa-solid fa-plus-circle fa-fw"></i> {{ text_install }}</a> <a href="{{ extension.delete }}" class="dropdown-item{% if not extension.delete %} disabled{% endif %}"><i class="fa-regular fa-trash-can fa-fw"></i> {{ text_delete }}</a>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</fieldset>
{% endif %}

View File

@ -0,0 +1,63 @@
{{ header }}{{ column_left }}
<div id="content">
<div class="page-header">
<div class="container-fluid">
<div class="float-end">
<button type="submit" form="form-startup" formaction="{{ delete }}" data-bs-toggle="tooltip" title="{{ button_delete }}" onclick="return confirm('{{ text_confirm }}');" class="btn btn-danger"><i class="fa-regular fa-trash-can"></i></button>
</div>
<h1>{{ heading_title }}</h1>
<ol class="breadcrumb">
{% for breadcrumb in breadcrumbs %}
<li class="breadcrumb-item"><a href="{{ breadcrumb.href }}">{{ breadcrumb.text }}</a></li>
{% endfor %}
</ol>
</div>
</div>
<div class="container-fluid">
<div class="card">
<div class="card-header"><i class="fa-solid fa-list"></i> {{ text_list }}</div>
<div id="startup" class="card-body">{{ list }}</div>
</div>
</div>
</div>
<script type="text/javascript"><!--
$('#startup').on('click', 'thead a, .pagination a', function (e) {
e.preventDefault();
$('#startup').load(this.href);
});
$('#startup').on('click', '.btn-success, .btn-danger', function (e) {
e.preventDefault();
var element = this;
$.ajax({
url: $(element).val(),
dataType: 'json',
beforeSend: function () {
$(element).button('loading');
},
complete: function () {
$(element).button('reset');
},
success: function (json) {
$('.alert-dismissible').remove();
if (json['error']) {
$('#alert').after('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
}
if (json['success']) {
$('#alert').after('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-check-circle"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>');
$('#startup').load($('#form-startup').attr('data-oc-load'));
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
});
//--></script>
{{ footer }}

View File

@ -0,0 +1,40 @@
<form id="form-startup" method="post" data-oc-toggle="ajax" data-oc-load="{{ action }}" data-oc-target="#startup">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<td class="text-center" style="width: 1px;"><input type="checkbox" onclick="$('input[name*=\'selected\']').prop('checked', $(this).prop('checked'));" class="form-check-input"/></td>
<td class="text-start"><a href="{{ sort_code }}"{% if sort == 'code' %} class="{{ order|lower }}"{% endif %}>{{ column_code }}</a></td>
<td class="text-start"><a href="{{ sort_action }}"{% if sort == 'action' %} class="{{ order|lower }}"{% endif %}>{{ column_action }}</a></td>
<td class="text-end"><a href="{{ sort_sort_order }}"{% if sort == 'sort_order' %} class="{{ order|lower }}"{% endif %}>{{ column_sort_order }}</a></td>
<td class="text-end">{{ column_action }}</td>
</tr>
</thead>
<tbody>
{% if startups %}
{% for startup in startups %}
<tr>
<td class="text-center"><input type="checkbox" name="selected[]" value="{{ startup.startup_id }}" class="form-check-input"/></td>
<td class="text-start">{{ startup.code }}</td>
<td class="text-start">{{ startup.action }}</td>
<td class="text-end">{{ startup.sort_order }}</td>
<td class="text-end">{% if not startup.status %}
<button type="button" value="{{ startup.enable }}" data-bs-toggle="tooltip" title="{{ button_enable }}" class="btn btn-success"><i class="fa-solid fa-plus-circle"></i></button>
{% else %}
<button type="button" value="{{ startup.disable }}" data-bs-toggle="tooltip" title="{{ button_disable }}" class="btn btn-danger"><i class="fa-solid fa-minus-circle"></i></button>
{% endif %}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td class="text-center" colspan="5">{{ text_no_results }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm-6 text-start">{{ pagination }}</div>
<div class="col-sm-6 text-end">{{ results }}</div>
</div>
</form>