feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run
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:
412
modules/system/assets/ui/js/inspector.wrapper.base.js
Normal file
412
modules/system/assets/ui/js/inspector.wrapper.base.js
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* Inspector wrapper base class.
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
|
||||
// NAMESPACES
|
||||
// ============================
|
||||
|
||||
if ($.wn.inspector === undefined)
|
||||
$.wn.inspector = {}
|
||||
|
||||
if ($.wn.inspector.wrappers === undefined)
|
||||
$.wn.inspector.wrappers = {}
|
||||
|
||||
// CLASS DEFINITION
|
||||
// ============================
|
||||
|
||||
var Base = $.wn.foundation.base,
|
||||
BaseProto = Base.prototype
|
||||
|
||||
var BaseWrapper = function($element, sourceWrapper, options) {
|
||||
this.$element = $element
|
||||
|
||||
this.options = $.extend({}, BaseWrapper.DEFAULTS, typeof options == 'object' && options)
|
||||
this.switched = false
|
||||
this.configuration = null
|
||||
|
||||
Base.call(this)
|
||||
|
||||
if (!sourceWrapper) {
|
||||
if (!this.triggerShowingAndInit()) {
|
||||
// this.init() is called inside triggerShowing()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.surface = null
|
||||
this.title = null
|
||||
this.description = null
|
||||
}
|
||||
else {
|
||||
this.surface = sourceWrapper.surface
|
||||
this.title = sourceWrapper.title
|
||||
this.description = sourceWrapper.description
|
||||
|
||||
sourceWrapper = null
|
||||
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
|
||||
BaseWrapper.prototype = Object.create(BaseProto)
|
||||
BaseWrapper.prototype.constructor = Base
|
||||
|
||||
BaseWrapper.prototype.dispose = function() {
|
||||
if (!this.switched) {
|
||||
this.$element.removeClass('inspector-open')
|
||||
this.setInspectorVisibleFlag(false)
|
||||
|
||||
this.$element.trigger('hidden.oc.inspector')
|
||||
}
|
||||
|
||||
if (this.surface !== null && this.surface.options.onGetInspectableElement === this.proxy(this.onGetInspectableElement)) {
|
||||
this.surface.options.onGetInspectableElement = null
|
||||
}
|
||||
|
||||
this.surface = null
|
||||
this.$element = null
|
||||
this.title = null
|
||||
this.description = null
|
||||
this.configuration = null
|
||||
|
||||
BaseProto.dispose.call(this)
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.init = function() {
|
||||
// Wrappers can create a new surface or inject an existing
|
||||
// surface to the UI they manage.
|
||||
//
|
||||
// If there is no surface provided in the wrapper constructor,
|
||||
// the wrapper first loads the Inspector configuration and values
|
||||
// and then calls the createSurfaceAndUi() method with all information
|
||||
// required for creating a new Inspector surface and UI.
|
||||
|
||||
if (!this.surface) {
|
||||
this.loadConfiguration()
|
||||
}
|
||||
else {
|
||||
this.adoptSurface()
|
||||
}
|
||||
|
||||
this.$element.addClass('inspector-open')
|
||||
}
|
||||
|
||||
//
|
||||
// Helper methods
|
||||
//
|
||||
|
||||
BaseWrapper.prototype.getElementValuesInput = function() {
|
||||
return this.$element.find('> input[data-inspector-values]')
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.normalizePropertyCode = function(code, configuration) {
|
||||
var lowerCaseCode = code.toLowerCase()
|
||||
|
||||
for (var index in configuration) {
|
||||
var propertyInfo = configuration[index]
|
||||
|
||||
if (propertyInfo.property.toLowerCase() == lowerCaseCode) {
|
||||
return propertyInfo.property
|
||||
}
|
||||
}
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.isExternalParametersEditorEnabled = function() {
|
||||
return this.$element.closest('[data-inspector-external-parameters]').length > 0
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.initSurface = function(containerElement, properties, values) {
|
||||
var options = this.$element.data() || {}
|
||||
|
||||
options.enableExternalParameterEditor = this.isExternalParametersEditorEnabled()
|
||||
options.onGetInspectableElement = this.proxy(this.onGetInspectableElement)
|
||||
|
||||
this.surface = new $.wn.inspector.surface(
|
||||
containerElement,
|
||||
properties,
|
||||
values,
|
||||
$.wn.inspector.helpers.generateElementUniqueId(this.$element.get(0)),
|
||||
options)
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.isLiveUpdateEnabled = function() {
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
// Wrapper API
|
||||
//
|
||||
|
||||
BaseWrapper.prototype.createSurfaceAndUi = function(properties, values) {
|
||||
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.setInspectorVisibleFlag = function(value) {
|
||||
this.$element.data('oc.inspectorVisible', value)
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.adoptSurface = function() {
|
||||
this.surface.options.onGetInspectableElement = this.proxy(this.onGetInspectableElement)
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.cleanupAfterSwitch = function() {
|
||||
this.switched = true
|
||||
this.dispose()
|
||||
}
|
||||
|
||||
//
|
||||
// Values
|
||||
//
|
||||
|
||||
BaseWrapper.prototype.loadValues = function(configuration) {
|
||||
var $valuesField = this.getElementValuesInput()
|
||||
|
||||
if ($valuesField.length > 0) {
|
||||
var valuesStr = $.trim($valuesField.val())
|
||||
|
||||
try {
|
||||
return valuesStr.length === 0 ? {} : JSON.parse(valuesStr)
|
||||
}
|
||||
catch (err) {
|
||||
throw new Error('Error parsing Inspector field values. ' + err)
|
||||
}
|
||||
}
|
||||
|
||||
var values = {},
|
||||
attributes = this.$element.get(0).attributes
|
||||
|
||||
for (var i=0, len = attributes.length; i < len; i++) {
|
||||
var attribute = attributes[i],
|
||||
matches = []
|
||||
|
||||
if (matches = attribute.name.match(/^data-property-(.*)$/)) {
|
||||
// Important - values contained in data-property-xxx attributes are
|
||||
// considered strings and never parsed with JSON. The use of the
|
||||
// data-property-xxx attributes is very limited - they're only
|
||||
// used in Pages for creating snippets from partials, where properties
|
||||
// are created with a table UI widget, which doesn't allow creating
|
||||
// properties of any complex types.
|
||||
//
|
||||
// There is no a technically reliable way to determine when a string
|
||||
// is a JSON data or a regular string. Users can enter a value
|
||||
// like [10], which is a proper JSON value, but meant to be a string.
|
||||
//
|
||||
// One possible way to resolve it, if to check the property type loaded
|
||||
// from the configuration and see if the corresponding editor expects
|
||||
// complex data.
|
||||
|
||||
var normalizedPropertyName = this.normalizePropertyCode(matches[1], configuration)
|
||||
values[normalizedPropertyName] = attribute.value
|
||||
}
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.applyValues = function(liveUpdateMode) {
|
||||
var $valuesField = this.getElementValuesInput(),
|
||||
values = liveUpdateMode ?
|
||||
this.surface.getValidValues() :
|
||||
this.surface.getValues()
|
||||
|
||||
if (liveUpdateMode) {
|
||||
// In the live update mode, when only valid values are applied,
|
||||
// we don't want to change all other values (invalid properties).
|
||||
|
||||
var existingValues = this.loadValues(this.configuration)
|
||||
|
||||
for (var property in values) {
|
||||
if (values[property] !== $.wn.inspector.invalidProperty) {
|
||||
existingValues[property] = values[property]
|
||||
}
|
||||
}
|
||||
|
||||
// Properties that use settings like ignoreIfPropertyEmpty could
|
||||
// be removed from the list returned by getValidValues(). Removed
|
||||
// properties should be removed from the result list.
|
||||
|
||||
var filteredValues = {}
|
||||
|
||||
for (var property in existingValues) {
|
||||
if (values.hasOwnProperty(property)) {
|
||||
filteredValues[property] = existingValues[property]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
values = filteredValues
|
||||
}
|
||||
|
||||
if ($valuesField.length > 0) {
|
||||
$valuesField.val(JSON.stringify(values))
|
||||
}
|
||||
else {
|
||||
for (var property in values) {
|
||||
var value = values[property]
|
||||
|
||||
if ($.isArray(value) ||$.isPlainObject(value)) {
|
||||
throw new Error('Inspector data-property-xxx attributes do not support complex values. Property: ' + property)
|
||||
}
|
||||
|
||||
this.$element.attr('data-property-' + property, value)
|
||||
}
|
||||
}
|
||||
|
||||
// In the live update mode the livechange event is triggered
|
||||
// regardless of whether Surface properties match or don't match
|
||||
// the original properties of the inspectable element. Without it
|
||||
// there could be undesirable side effects.
|
||||
|
||||
if (liveUpdateMode) {
|
||||
this.$element.trigger('livechange')
|
||||
}
|
||||
else {
|
||||
var hasChanges = false
|
||||
|
||||
if (this.isLiveUpdateEnabled()) {
|
||||
var currentValues = this.loadValues(this.configuration)
|
||||
|
||||
// If the Inspector setup supports the live update mode,
|
||||
// evaluate changes as a difference between the current element
|
||||
// properties and internal properties stored in the Surface.
|
||||
// If there is no differences, the properties have already
|
||||
// been applied with a preceding live update.
|
||||
hasChanges = this.surface.hasChanges(currentValues)
|
||||
}
|
||||
else {
|
||||
hasChanges = this.surface.hasChanges()
|
||||
}
|
||||
|
||||
if (hasChanges) {
|
||||
this.$element.trigger('change')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Configuration
|
||||
//
|
||||
|
||||
BaseWrapper.prototype.loadConfiguration = function() {
|
||||
var configString = this.$element.data('inspector-config'),
|
||||
result = {
|
||||
properties: {},
|
||||
title: null,
|
||||
description: null
|
||||
}
|
||||
|
||||
result.title = this.$element.data('inspector-title')
|
||||
result.description = this.$element.data('inspector-description')
|
||||
|
||||
if (configString !== undefined) {
|
||||
result.properties = this.parseConfiguration(configString)
|
||||
|
||||
this.configurationLoaded(result)
|
||||
return
|
||||
}
|
||||
|
||||
var $configurationField = this.$element.find('> input[data-inspector-config]')
|
||||
|
||||
if ($configurationField.length > 0) {
|
||||
result.properties = this.parseConfiguration($configurationField.val())
|
||||
|
||||
this.configurationLoaded(result)
|
||||
return
|
||||
}
|
||||
|
||||
var $form = this.$element.closest('form'),
|
||||
data = this.$element.data(),
|
||||
self = this
|
||||
|
||||
$.wn.stripeLoadIndicator.show()
|
||||
$form.request('onGetInspectorConfiguration', {
|
||||
data: data
|
||||
}).done(function inspectorConfigurationRequestDoneClosure(data) {
|
||||
self.onConfigurartionRequestDone(data, result)
|
||||
}).always(function() {
|
||||
$.wn.stripeLoadIndicator.hide()
|
||||
})
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.parseConfiguration = function(configuration) {
|
||||
if (!$.isArray(configuration) && !$.isPlainObject(configuration)) {
|
||||
if ($.trim(configuration) === 0) {
|
||||
return {}
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(configuration)
|
||||
}
|
||||
catch(err) {
|
||||
throw new Error('Error parsing Inspector configuration. ' + err)
|
||||
}
|
||||
}
|
||||
else {
|
||||
return configuration
|
||||
}
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.configurationLoaded = function(configuration) {
|
||||
var values = this.loadValues(configuration.properties)
|
||||
|
||||
this.title = configuration.title
|
||||
this.description = configuration.description
|
||||
this.configuration = configuration
|
||||
|
||||
this.createSurfaceAndUi(configuration.properties, values)
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.onConfigurartionRequestDone = function(data, result) {
|
||||
result.properties = this.parseConfiguration(data.configuration.properties)
|
||||
|
||||
if (data.configuration.title !== undefined) {
|
||||
result.title = data.configuration.title
|
||||
}
|
||||
|
||||
if (data.configuration.description !== undefined) {
|
||||
result.description = data.configuration.description
|
||||
}
|
||||
|
||||
this.configurationLoaded(result)
|
||||
}
|
||||
|
||||
//
|
||||
// Events
|
||||
//
|
||||
|
||||
BaseWrapper.prototype.triggerShowingAndInit = function() {
|
||||
var e = $.Event('showing.oc.inspector')
|
||||
|
||||
this.$element.trigger(e, [{callback: this.proxy(this.init)}])
|
||||
if (e.isDefaultPrevented()) {
|
||||
this.$element = null
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if (!e.isPropagationStopped()) {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.triggerHiding = function() {
|
||||
var hidingEvent = $.Event('hiding.oc.inspector'),
|
||||
values = this.surface.getValues()
|
||||
|
||||
this.$element.trigger(hidingEvent, [{values: values}])
|
||||
return !hidingEvent.isDefaultPrevented();
|
||||
}
|
||||
|
||||
BaseWrapper.prototype.onGetInspectableElement = function() {
|
||||
return this.$element
|
||||
}
|
||||
|
||||
BaseWrapper.DEFAULTS = {
|
||||
containerSupported: false
|
||||
}
|
||||
|
||||
$.wn.inspector.wrappers.base = BaseWrapper
|
||||
}(window.jQuery);
|
||||
Reference in New Issue
Block a user