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:
222
modules/system/assets/js/snowboard/extras/DataConfig.js
Normal file
222
modules/system/assets/js/snowboard/extras/DataConfig.js
Normal file
@@ -0,0 +1,222 @@
|
||||
import PluginBase from '../abstracts/PluginBase';
|
||||
|
||||
/**
|
||||
* Data configuration provider.
|
||||
*
|
||||
* Provides a mechanism for passing configuration data through an element's data attributes. This
|
||||
* is generally used for widgets or UI interactions to configure them.
|
||||
*
|
||||
* @copyright 2022 Winter.
|
||||
* @author Ben Thomson <git@alfreido.com>
|
||||
*/
|
||||
export default class DataConfig extends PluginBase {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param {PluginBase} instance
|
||||
* @param {HTMLElement} element
|
||||
* @param {Object} localConfig
|
||||
*/
|
||||
construct(instance, element, localConfig) {
|
||||
if (instance instanceof PluginBase === false) {
|
||||
throw new Error('You must provide a Snowboard plugin to enable data configuration');
|
||||
}
|
||||
if (element instanceof HTMLElement === false) {
|
||||
throw new Error('Data configuration can only be extracted from HTML elements');
|
||||
}
|
||||
|
||||
this.instance = instance;
|
||||
this.element = element;
|
||||
this.localConfig = localConfig || {};
|
||||
this.instanceConfig = {};
|
||||
this.acceptedConfigs = {};
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config for this instance.
|
||||
*
|
||||
* If the `config` parameter is unspecified, returns the entire configuration.
|
||||
*
|
||||
* @param {string} config
|
||||
*/
|
||||
get(config) {
|
||||
if (config === undefined) {
|
||||
return this.instanceConfig;
|
||||
}
|
||||
|
||||
if (this.instanceConfig[config] !== undefined) {
|
||||
return this.instanceConfig[config];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the config for this instance.
|
||||
*
|
||||
* This allows you to override, at runtime, any configuration value as necessary.
|
||||
*
|
||||
* @param {string} config
|
||||
* @param {any} value
|
||||
* @param {boolean} persist
|
||||
*/
|
||||
set(config, value, persist) {
|
||||
if (config === undefined) {
|
||||
throw new Error('You must provide a configuration key to set');
|
||||
}
|
||||
|
||||
this.instanceConfig[config] = value;
|
||||
|
||||
if (persist === true) {
|
||||
this.element.dataset[config] = value;
|
||||
this.localConfig[config] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the configuration from the element.
|
||||
*
|
||||
* This will allow you to make changes to the data config on a DOM level and re-apply them
|
||||
* to the config on the JavaScript side.
|
||||
*/
|
||||
refresh() {
|
||||
this.acceptedConfigs = this.getAcceptedConfigs();
|
||||
this.instanceConfig = this.processConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the available configurations that can be set through the data config.
|
||||
*
|
||||
* If an instance has an `acceptAllDataConfigs` property, set to `true`, then all data
|
||||
* attributes will be available as configuration values. This can be a security concern, so
|
||||
* tread carefully.
|
||||
*
|
||||
* Otherwise, available configurations will be determined by the keys available in an object
|
||||
* returned by a `defaults()` method in the instance.
|
||||
*
|
||||
* @returns {string[]|boolean}
|
||||
*/
|
||||
getAcceptedConfigs() {
|
||||
if (
|
||||
this.instance.acceptAllDataConfigs !== undefined
|
||||
&& this.instance.acceptAllDataConfigs === true
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
this.instance.defaults !== undefined
|
||||
&& typeof this.instance.defaults === 'function'
|
||||
&& typeof this.instance.defaults() === 'object'
|
||||
) {
|
||||
return Object.keys(this.instance.defaults());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default values for the instance.
|
||||
*
|
||||
* This will be an empty object if the instance either does not have a `defaults()` method, or
|
||||
* the method itself does not return an object.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
getDefaults() {
|
||||
if (
|
||||
this.instance.defaults !== undefined
|
||||
&& typeof this.instance.defaults === 'function'
|
||||
&& typeof this.instance.defaults() === 'object'
|
||||
) {
|
||||
return this.instance.defaults();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the configuration.
|
||||
*
|
||||
* Loads up the defaults, then populates it with any configuration values provided by the data
|
||||
* attributes, based on the rules of the accepted configurations.
|
||||
*
|
||||
* This configuration object is then cached and available through `config.get()` calls.
|
||||
*
|
||||
* @returns {object}
|
||||
*/
|
||||
processConfig() {
|
||||
const config = this.getDefaults();
|
||||
|
||||
if (this.acceptedConfigs === false) {
|
||||
return config;
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
for (const key in this.element.dataset) {
|
||||
if (this.acceptedConfigs === true || this.acceptedConfigs.includes(key)) {
|
||||
config[key] = this.coerceValue(this.element.dataset[key]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in this.localConfig) {
|
||||
if (this.acceptedConfigs === true || this.acceptedConfigs.includes(key)) {
|
||||
config[key] = this.localConfig[key];
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerces configuration values for JavaScript.
|
||||
*
|
||||
* Takes the string value returned from the data attribute and coerces it into a more suitable
|
||||
* type for JavaScript processing.
|
||||
*
|
||||
* @param {*} value
|
||||
* @returns {*}
|
||||
*/
|
||||
coerceValue(value) {
|
||||
const stringValue = String(value);
|
||||
|
||||
// Null value
|
||||
if (stringValue === 'null') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Undefined value
|
||||
if (stringValue === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Base64 value
|
||||
if (stringValue.startsWith('base64:')) {
|
||||
const base64str = stringValue.replace(/^base64:/, '');
|
||||
const decoded = atob(base64str);
|
||||
return this.coerceValue(decoded);
|
||||
}
|
||||
|
||||
// Boolean value
|
||||
if (['true', 'yes'].includes(stringValue.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
if (['false', 'no'].includes(stringValue.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Numeric value
|
||||
if (/^[-+]?[0-9]+(\.[0-9]+)?$/.test(stringValue)) {
|
||||
return Number(stringValue);
|
||||
}
|
||||
|
||||
// JSON value
|
||||
try {
|
||||
return this.snowboard.jsonParser().parse(stringValue);
|
||||
} catch (e) {
|
||||
return (stringValue === '') ? true : stringValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user