feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run

- Base: wintercms/winter branch 1.2 (full framework)
- Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS
- Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication
- Partials: hero (offline-first), features, modes (offline/nube toggle),
  screenshots, pricing (3 planes), comparison, FAQ, CTA
- Plugin VivesPOS.Site with ContactForm
- Dockerfile: PHP 8.2 Apache, port 80, healthcheck
- Added winter/wn-pages, blog, sitemap, seo plugins
- Active theme set to vivespos
This commit is contained in:
2026-08-21 19:29:00 -06:00
commit 1f72193a64
3266 changed files with 531480 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<h4 class="modal-title"><?= e(trans('backend::lang.import_export.column_preview')) ?></h4>
</div>
<div class="modal-body">
<p>
<?= e(trans('backend::lang.import_export.column')) ?>:
<strong><?= $columnName ?></strong>
</p>
<div class="list-preview">
<div class="control-simplelist is-divided is-scrollable size-small" data-control="simplelist">
<ul>
<?php foreach ($columnData as $sample): ?>
<li class="wn-icon-file-o">
<?= e($sample) ?>
</li>
<?php endforeach ?>
</ul>
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>

View File

@@ -0,0 +1,9 @@
<div class="export-behavior">
<?= $exportFormatFormWidget->render() ?>
<?php if ($exportOptionsFormWidget): ?>
<?= $exportOptionsFormWidget->render() ?>
<?php endif ?>
</div>

View File

@@ -0,0 +1,9 @@
<div class="import-behavior">
<?= $importUploadFormWidget->render() ?>
<?php if ($importOptionsFormWidget): ?>
<?= $importOptionsFormWidget->render() ?>
<?php endif ?>
</div>

View File

@@ -0,0 +1,27 @@
<div class="export-columns" id="exportColumns">
<div class="control-simplelist with-checkboxes is-sortable" data-control="simplelist">
<ul>
<?php foreach ($exportColumns as $key => $column): ?>
<li>
<div class="checkbox custom-checkbox">
<input
type="hidden"
name="export_columns[]"
value="<?= $key ?>" />
<input
id="<?= $this->getId('exportCheckbox-'.$key) ?>"
name="visible_columns[<?= $key ?>]"
value="1"
checked="checked"
type="checkbox" />
<label
class="choice"
for="<?= $this->getId('exportCheckbox-'.$key) ?>">
<?= e(trans($column)) ?>
</label>
</div>
</li>
<?php endforeach ?>
</ul>
</div>
</div>

View File

@@ -0,0 +1,50 @@
<div id="exportFormPopup">
<?php if (!$this->fatalError): ?>
<?= Form::open(['id' => 'exportForm']) ?>
<div class="modal-header">
<h4 class="modal-title"><?= e(trans('backend::lang.import_export.export_progress')) ?></h4>
</div>
<div id="exportContainer">
<div class="modal-body">
<div class="loading-indicator-container">
<p>&nbsp;</p>
<div class="loading-indicator transparent">
<div><?= e(trans('backend::lang.import_export.processing')) ?></div>
<span></span>
</div>
</div>
<p>&nbsp;</p>
</div>
</div>
<?= Form::close() ?>
<script>
$('#exportFormPopup').on('popupComplete', function() {
$.wn.exportBehavior.processExport()
})
</script>
<?php else: ?>
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<h4 class="modal-title"><?= e(trans('backend::lang.import_export.export_error')) ?></h4>
</div>
<div class="modal-body">
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>
<?php endif ?>
</div>

View File

@@ -0,0 +1,34 @@
<?php if (!$this->fatalError): ?>
<div class="modal-body">
<p>
<?= e(trans('backend::lang.import_export.processing_successful_line1')) ?>
<?= e(trans('backend::lang.import_export.processing_successful_line2')) ?>
</p>
</div>
<div class="modal-footer">
<a
href="<?= $returnUrl ?>"
class="btn btn-success"
data-dismiss="popup">
<?= e(trans('backend::lang.form.complete')) ?>
</a>
</div>
<script> window.location = '<?= $fileUrl ?>' </script>
<?php else: ?>
<div class="modal-body">
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>
<?php endif ?>

View File

@@ -0,0 +1,23 @@
<div class="import-db-columns" id="importDbColumns">
<ul>
<?php foreach ($importDbColumns as $column => $label): ?>
<?php
$isRequired = $this->importIsColumnRequired($column);
$iconName = $isRequired ? 'icon-asterisk' : 'icon-link';
?>
<li
class="<?= $isRequired ? 'is-required' : '' ?>"
data-column-name="<?= e($column) ?>">
<span>
<i class="column-icon <?= $iconName ?>"></i>
<?= e(trans($label)) ?>
</span>
<input type="hidden" data-column-match-input />
</li>
<?php endforeach ?>
</ul>
</div>
<script>
$.wn.importBehavior.bindColumnSorting()
</script>

View File

@@ -0,0 +1,44 @@
<div class="import-file-columns" id="importFileColumns">
<?php if ($importFileColumns): ?>
<ul>
<?php foreach ($importFileColumns as $index => $column): ?>
<li data-column-id="<?= $index ?>">
<div class="import-column-name">
<span>
<i class="column-success-icon text-success icon-check"></i>
<a
href="javascript:;"
class="column-ignore-button"
data-toggle="tooltip"
data-delay="300"
data-placement="right"
title="<?= e(trans('backend::lang.import_export.ignore_this_column')) ?>"
onclick="$.wn.importBehavior.ignoreFileColumn(this)"
>
<i class="icon-close"></i>
</a>
<a
href="javascript:;"
class="column-label"
onclick="$.wn.importBehavior.loadFileColumnSample(this)"
>
<?= e($column) ?>
</a>
</span>
</div>
<div class="import-column-bindings">
<ul data-empty-text="<?= e(trans('backend::lang.import_export.drop_column_here')) ?>"></ul>
</div>
</li>
<?php endforeach ?>
</ul>
<?php else: ?>
<p class="upload-prompt">
<?= e(trans('backend::lang.import_export.upload_valid_csv')) ?>
</p>
<?php endif ?>
</div>
<script>
$.wn.importBehavior.bindColumnSorting()
</script>

View File

@@ -0,0 +1,50 @@
<div id="importFormPopup">
<?php if (!$this->fatalError): ?>
<?= Form::open(['id' => 'importForm']) ?>
<div class="modal-header">
<h4 class="modal-title"><?= e(trans('backend::lang.import_export.import_progress')) ?></h4>
</div>
<div id="importContainer">
<div class="modal-body">
<div class="loading-indicator-container">
<p>&nbsp;</p>
<div class="loading-indicator transparent">
<div><?= e(trans('backend::lang.import_export.processing')) ?></div>
<span></span>
</div>
</div>
<p>&nbsp;</p>
</div>
</div>
<?= Form::close() ?>
<script>
$('#importFormPopup').on('popupComplete', function() {
$.wn.importBehavior.processImport()
})
</script>
<?php else: ?>
<div class="modal-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<h4 class="modal-title"><?= e(trans('backend::lang.import_export.import_error')) ?></h4>
</div>
<div class="modal-body">
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>
<?php endif ?>
</div>

View File

@@ -0,0 +1,107 @@
<?php if (!$this->fatalError): ?>
<div class="modal-body">
<div class="scoreboard">
<div data-control="toolbar">
<div class="scoreboard-item title-value">
<h4><?= e(trans('backend::lang.import_export.created')) ?></h4>
<p><?= $importResults->created ?></p>
</div>
<div class="scoreboard-item title-value">
<h4><?= e(trans('backend::lang.import_export.updated')) ?></h4>
<p><?= $importResults->updated ?></p>
</div>
<?php if ($importResults->skippedCount): ?>
<div class="scoreboard-item title-value">
<h4><?= e(trans('backend::lang.import_export.skipped')) ?></h4>
<p><?= $importResults->skippedCount ?></p>
</div>
<?php endif ?>
<?php if ($importResults->warningCount): ?>
<div class="scoreboard-item title-value">
<h4><?= e(trans('backend::lang.import_export.warnings')) ?></h4>
<p><?= $importResults->warningCount ?></p>
</div>
<?php endif ?>
<div class="scoreboard-item title-value">
<h4><?= e(trans('backend::lang.import_export.errors')) ?></h4>
<p><?= $importResults->errorCount ?></p>
</div>
</div>
</div>
<?php if ($importResults->hasMessages): ?>
<?php
$tabs = [
'skipped' => trans('backend::lang.import_export.skipped_rows'),
'warnings' => trans('backend::lang.import_export.warnings'),
'errors' => trans('backend::lang.import_export.errors'),
];
if (!$importResults->skippedCount) {
unset($tabs['skipped']);
}
if (!$importResults->warningCount) {
unset($tabs['warnings']);
}
if (!$importResults->errorCount) {
unset($tabs['errors']);
}
?>
<div class="control-tabs secondary-tabs" data-control="tab">
<ul class="nav nav-tabs">
<?php $count = 0; foreach ($tabs as $code => $tab): ?>
<li class="<?= $count++ == 0 ? 'active' : '' ?>">
<a href="#importTab<?= $code ?>">
<?= $tab ?>
</a>
</li>
<?php endforeach ?>
</ul>
<div class="tab-content">
<?php $count = 0; foreach ($tabs as $code => $tab): ?>
<div class="tab-pane <?= $count++ == 0 ? 'active' : '' ?>">
<div class="list-preview">
<div class="control-simplelist is-divided is-scrollable size-small" data-control="simplelist">
<ul>
<?php foreach ($importResults->{$code} as $row => $message): ?>
<li>
<strong><?= e(trans('backend::lang.import_export.row', ['row' => $row + $sourceIndexOffset])) ?></strong>
- <?= e($message) ?>
</li>
<?php endforeach ?>
</ul>
</div>
</div>
</div>
<?php endforeach ?>
</div>
</div>
<?php endif ?>
</div>
<div class="modal-footer">
<a
href="<?= $returnUrl ?>"
class="btn btn-success"
data-dismiss="popup">
<?= e(trans('backend::lang.form.complete')) ?>
</a>
</div>
<?php else: ?>
<div class="modal-body">
<p class="flash-message static error"><?= e($this->fatalError) ?></p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-default"
data-dismiss="popup">
<?= e(trans('backend::lang.form.close')) ?>
</button>
</div>
<?php endif ?>

View File

@@ -0,0 +1,16 @@
<div data-control="toolbar">
<a
href="javascript:;"
id="showIgnoredColumnsButton"
class="btn btn-sm btn-secondary wn-icon-eye disabled"
onclick="$.wn.importBehavior.showIgnoredColumns()">
<?= e(trans('backend::lang.import_export.show_ignored_columns')) ?>
</a>
<a
href="javascript:;"
id="autoMatchColumnsButton"
class="btn btn-sm btn-secondary wn-icon-bullseye"
onclick="$.wn.importBehavior.autoMatchColumns()">
<?= e(trans('backend::lang.import_export.auto_match_columns')) ?>
</a>
</div>

View File

@@ -0,0 +1,58 @@
# ===================================
# Field Definitions
# ===================================
fields:
step1_section:
label: backend::lang.import_export.export_output_format
type: section
format_preset:
label: backend::lang.import_export.file_format
type: dropdown
default: standard
options:
standard: backend::lang.import_export.standard_format
custom: backend::lang.import_export.custom_format
span: left
format_delimiter:
label: backend::lang.import_export.delimiter_char
default: ','
span: left
trigger:
action: show
condition: value[custom]
field: format_preset
format_enclosure:
label: backend::lang.import_export.enclosure_char
span: auto
default: '"'
trigger:
action: show
condition: value[custom]
field: format_preset
format_escape:
label: backend::lang.import_export.escape_char
span: auto
default: '\'
trigger:
action: show
condition: value[custom]
field: format_preset
step2_section:
label: backend::lang.import_export.select_columns
type: section
export_columns:
label: backend::lang.import_export.columns
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_export_columns.php
span: left
step3_section:
label: backend::lang.import_export.set_export_options
type: section

View File

@@ -0,0 +1,95 @@
# ===================================
# Field Definitions
# ===================================
fields:
step1_section:
label: backend::lang.import_export.upload_csv_file
type: section
import_file:
label: backend::lang.import_export.import_file
type: fileupload
mode: file
span: left
fileTypes: csv
useCaption: false
format_preset:
label: backend::lang.import_export.file_format
type: dropdown
default: standard
options:
standard: backend::lang.import_export.standard_format
custom: backend::lang.import_export.custom_format
span: right
format_delimiter:
label: backend::lang.import_export.delimiter_char
default: ','
span: left
trigger:
action: show
condition: value[custom]
field: format_preset
format_enclosure:
label: backend::lang.import_export.enclosure_char
span: auto
default: '"'
trigger:
action: show
condition: value[custom]
field: format_preset
format_escape:
label: backend::lang.import_export.escape_char
span: auto
default: '\'
trigger:
action: show
condition: value[custom]
field: format_preset
format_encoding:
label: backend::lang.import_export.encoding_format
span: auto
default: UTF-8
type: dropdown
trigger:
action: show
condition: value[custom]
field: format_preset
first_row_titles:
label: backend::lang.import_export.first_row_contains_titles
comment: backend::lang.import_export.first_row_contains_titles_desc
type: checkbox
default: true
span: left
step2_section:
label: backend::lang.import_export.match_columns
type: section
column_control_panel:
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_toolbar.php
import_file_columns:
label: backend::lang.import_export.file_columns
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.php
dependsOn: [import_file, first_row_titles, format_delimiter, format_enclosure, format_escape, format_encoding]
span: left
import_db_columns:
label: backend::lang.import_export.database_fields
type: partial
path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.php
dependsOn: [import_file, first_row_titles, format_delimiter, format_enclosure, format_escape, format_encoding]
span: right
step3_section:
label: backend::lang.import_export.set_import_options
type: section