diff --git a/app/_config/elements.yml b/app/_config/elements.yml
index 97741da..99c30da 100644
--- a/app/_config/elements.yml
+++ b/app/_config/elements.yml
@@ -3,6 +3,7 @@ Name: webapp-elemental
After:
- elemental
- elemental-list
+ - elementalvirtual
---
Page:
diff --git a/app/client/src/js/_components/_ui.form.basics.js b/app/client/src/js/_components/_ui.form.basics.js
index a8a661a..d5e05b1 100644
--- a/app/client/src/js/_components/_ui.form.basics.js
+++ b/app/client/src/js/_components/_ui.form.basics.js
@@ -2,6 +2,7 @@ import 'bootstrap-select/js/bootstrap-select';
import $ from 'jquery';
import Events from "../_events";
+import SpinnerUI from './_ui.spinner';
const FormBasics = (($) => {
// Constants
@@ -56,6 +57,10 @@ const FormBasics = (($) => {
}
});
+ $element.on('submit', (e) => {
+ SpinnerUI.show();
+ });
+
$element.addClass(`${NAME}-active`);
$element.trigger(Events.FORM_INIT_BASICS);
}
diff --git a/app/client/src/js/_components/_ui.form.croppie.js b/app/client/src/js/_components/_ui.form.croppie.js
new file mode 100644
index 0000000..47107dd
--- /dev/null
+++ b/app/client/src/js/_components/_ui.form.croppie.js
@@ -0,0 +1,189 @@
+"use strict";
+
+import $ from 'jquery';
+
+import Events from '../_events';
+import SpinnerUI from './_ui.spinner';
+
+import 'croppie/croppie.js';
+import 'exif-js/exif.js';
+
+const CroppieUI = (($) => {
+
+ const NAME = 'jsCroppieUI';
+ const DATA_KEY = NAME;
+
+ const G = window;
+ const D = document;
+
+ const jqteOptions = {
+ color: false,
+ fsize: false,
+ funit: 'em',
+ format: false,
+ rule: false,
+ source: false,
+ sub: false,
+ sup: false,
+ };
+
+ class CroppieUI {
+
+ constructor(element) {
+ const ui = this;
+ const $el = $(element);
+
+ ui._element = element;
+ $el.data(DATA_KEY, this);
+
+ ui.input = $el.find('input[type="file"]');
+ //ui.inputData = $('');
+
+ ui.width = ui.input.data('width');
+ ui.height = ui.input.data('height');
+
+ $el.append('
');
+ //$el.append(ui.inputData);
+
+ ui.uploadCrop = $el.find('.cropper-container');
+
+ const ratio = ui.width / (ui.uploadCrop.width() - 32);
+ ui.uploadCrop.croppie({
+ enableExif: true,
+ enforceBoundary: false,
+ viewport: {
+ width: ui.width / ratio,
+ height: ui.height / ratio,
+ }
+ });
+
+ ui.uploadCrop.hide();
+
+ ui.input.on('change', (e) => {
+ this.readFile(e.currentTarget);
+ });
+ }
+
+ readFile(input) {
+ const ui = this;
+ const $el = $(ui._element);
+ const $form = $el.closest('form');
+
+ if (input.files && input.files[0]) {
+ const reader = new FileReader();
+
+ reader.onload = (e) => {
+ ui.uploadCrop.addClass('ready');
+ ui.uploadCrop.croppie('bind', {
+ url: e.target.result
+ });
+
+ ui.uploadCrop.show();
+ }
+
+ reader.readAsDataURL(input.files[0]);
+
+ $form.on('submit', (e) => {
+ //$(input).val('');
+ SpinnerUI.show();
+
+ ui.uploadCrop.croppie('result', {
+ type: 'blob',
+ size: {
+ width: ui.width,
+ height: ui.height
+ },
+ format: 'png'
+ }).then((blob) => {
+ const form = e.currentTarget;
+ const data = new FormData(form);
+ const name = $(input).attr('name');
+
+ data.delete('BackURL');
+ data.delete(name);
+ data.append(name, blob, name + '-image.png');
+ data.append('ajax', '1');
+
+ $.ajax({
+ url: $(form).attr('action'),
+ data: data,
+ processData: false,
+ contentType: false,
+ type: $(form).attr('method'),
+ success: function(data) {
+ let IS_JSON = false;
+ try {
+ IS_JSON = true;
+ const json = $.parseJSON(data);
+ } catch (e) {
+ IS_JSON = false;
+ }
+
+ if (IS_JSON && typeof json === 'object') {
+ for (let k in json) {
+ $form.find('select[name="' + k + '"],input[name="' + k + '"],textarea[name="' + k + '"]').setError(true, json[k]);
+ }
+
+ if (typeof json['status'] !== 'undefined' && json['status'] === 'success') {
+ if (typeof json['link'] !== 'undefined') {
+ G.location = json['link'];
+ } else {
+ G.location.reload(false);
+ }
+ }
+ } else {
+ G.location.reload(false);
+ }
+
+ SpinnerUI.hide();
+ $(G).trigger(Events.AJAX);
+ }
+ });
+
+ //ui.inputData.val(data);
+
+ });
+
+ e.preventDefault();
+ });
+
+ } else {
+ console.log('Sorry - your browser doesn\'t support the FileReader API');
+ }
+ }
+
+ static dispose() {
+ console.log(`Destroying: ${NAME}`);
+ }
+
+ static _jQueryInterface() {
+ return this.each((i, el) => {
+ // attach functionality to element
+ const $el = $(el);
+ let data = $el.data(DATA_KEY);
+
+ if (!data) {
+ data = new CroppieUI(el);
+ $el.data(DATA_KEY, data);
+ }
+ });
+ }
+ }
+
+ // jQuery interface
+ $.fn[NAME] = CroppieUI._jQueryInterface;
+ $.fn[NAME].Constructor = CroppieUI;
+ $.fn[NAME].noConflict = () => {
+ $.fn[NAME] = JQUERY_NO_CONFLICT;
+ return CroppieUI._jQueryInterface;
+ };
+
+ // auto-apply
+ $(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
+ $('.field.croppie').jsCroppieUI();
+ });
+
+ return CroppieUI;
+})($);
+
+export default CroppieUI;
diff --git a/app/client/src/js/_components/_ui.form.datetime.js b/app/client/src/js/_components/_ui.form.datetime.js
index e4037ae..31ba3ff 100644
--- a/app/client/src/js/_components/_ui.form.datetime.js
+++ b/app/client/src/js/_components/_ui.form.datetime.js
@@ -23,29 +23,35 @@ const DatetimeUI = (($) => {
};
class DatetimeUI {
- constructor(element) {
+ constructor(el) {
const ui = this;
- const $element = $(element);
+ const $el = $(el);
- $element.data(DATA_KEY, this);
- ui._element = element;
+ ui._el = el;
// datepicker
- if ($element.hasClass('date')) {
- const defaultDate = ($element.attr('name').toLowerCase().indexOf('end') !== -1) ?
+ if ($el.hasClass('date') || $el.attr('type') === 'date') {
+ const defaultDate = ($el.attr('name').toLowerCase().indexOf('end') !== -1) ?
'+4d' :
'+3d';
- $element.attr('readonly', 'true');
- $element.datepicker($.extend(datepickerOptions, {
- defaultViewDate: defaultDate
+ $el.attr('readonly', 'true');
+ $el.datepicker($.extend(datepickerOptions, {
+ defaultViewDate: defaultDate,
+ multidate: $el.data('multidate'),
}));
} else
// timepicker
- if ($element.hasClass('time')) {
- $element.attr('readonly', 'true');
- $element.timepicker();
+ if ($el.hasClass('time') || $el.attr('type') === 'time') {
+ $el.attr('readonly', 'true');
+ $el.timepicker({
+ defaultTime: $el.data('default-time'),
+ icons: {
+ up: 'fas fa-chevron-up',
+ down: 'fas fa-chevron-down'
+ }
+ });
}
}
@@ -56,12 +62,12 @@ const DatetimeUI = (($) => {
static _jQueryInterface() {
return this.each(function() {
// attach functionality to element
- const $elementement = $(this);
- let data = $elementement.data(DATA_KEY);
+ const $el = $(this);
+ let data = $el.data(DATA_KEY);
if (!data) {
data = new DatetimeUI(this);
- $elementement.data(DATA_KEY, data);
+ $el.data(DATA_KEY, data);
}
});
}
@@ -77,7 +83,7 @@ const DatetimeUI = (($) => {
// auto-apply
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
- $('input.date, input.time').jsDatetimeUI();
+ $('input.date, input.time,input[type="date"], input[type="time"]').jsDatetimeUI();
});
return DatetimeUI;
diff --git a/app/client/src/js/_components/_ui.map.api.js b/app/client/src/js/_components/_ui.map.api.js
index cdf501b..b124dcd 100644
--- a/app/client/src/js/_components/_ui.map.api.js
+++ b/app/client/src/js/_components/_ui.map.api.js
@@ -25,6 +25,7 @@ const MapAPI = (($) => {
this._element = element;
const $element = $(this._element);
const geojson = $element.data('geojson');
+
const center = [
($element.data('lng') ? $element.data('lng') : $BODY.data('default-lng')),
($element.data('lat') ? $element.data('lat') : $BODY.data('default-lat')),
@@ -33,6 +34,7 @@ const MapAPI = (($) => {
closeOnClick: false,
className: 'popup'
});
+
currentStyle = this.getStyle();
mapBoxGL.accessToken = $element.data('key');
diff --git a/app/src/Extensions/ElementRows.php b/app/src/Extensions/ElementRows.php
index c68969e..c6f4944 100644
--- a/app/src/Extensions/ElementRows.php
+++ b/app/src/Extensions/ElementRows.php
@@ -10,6 +10,7 @@ namespace Site\Extensions;
use DNADesign\ElementalList\Model\ElementList;
use SilverStripe\Core\Config\Config;
+use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\DropdownField;
use SilverStripe\ORM\DataExtension;
use SilverStripe\Forms\FieldList;
@@ -33,7 +34,11 @@ class ElementRows extends DataExtension
{
parent::updateCMSFields($fields);
+ // move available globaly to main tab
+ $fields->removeByName('AvailableGlobally');
+
$tab = $fields->findOrMakeTab('Root.Main');
+ $tab->push(CheckboxField::create('AvailableGlobally'));
// container type
if ($this->isRoot()) {
@@ -46,6 +51,9 @@ class ElementRows extends DataExtension
$fields->removeByName('ContainerType');
}
+ // site-specific
+ $fields->removeByName('ContainerType');
+
// column size
if ($this->isColumn()) {
$sizes = $this->owner->dbObject('Size');
diff --git a/app/templates/Includes/SiteWideMessage.ss b/app/templates/Includes/SiteWideMessage.ss
index 5d54809..9ddf8be 100644
--- a/app/templates/Includes/SiteWideMessage.ss
+++ b/app/templates/Includes/SiteWideMessage.ss
@@ -1,10 +1,10 @@
<% if $SiteWideMessage %>
- <% with $SiteWideMessage %>
-
- {$Message}
-
-
- <% end_with %>
+ <% with $SiteWideMessage %>
+
+ {$Message}
+
+
+ <% end_with %>
<% end_if %>