lib/assets/javascripts/scrivito_sdk.js in scrivito_sdk-1.6.0.rc1 vs lib/assets/javascripts/scrivito_sdk.js in scrivito_sdk-1.6.0.rc2

- old
+ new

@@ -11985,10 +11985,12 @@ }.call(this)); // +// + "use strict"; if (!window.scrivito) { window.scrivito = {}; } @@ -12135,14 +12137,14 @@ scrivito.asyncMethodStub = asyncMethodStub; })(); "use strict"; (function () { - var CONVERT_TO_CAMELCASE = /_(\w)/g; + var CONVERT_TO_CAMELCASE = /(_+)(\w)/g; var CONVERT_TO_UNDERSCORE = /([A-Z])/g; - var TEST_CAMEL_CASE = /^_?[^_]+$/; + var TEST_CAMEL_CASE = /^_?(_+[A-Z0-9]|[^_])+$/; var TEST_UNDERSCORE = /^[a-z0-9_]+$/; scrivito.attributeInflection = { isUnderscore: function isUnderscore(name) { return TEST_UNDERSCORE.test(name); @@ -12157,16 +12159,310 @@ return "_" + group.toLowerCase(); }); }, camelCase: function camelCase(name) { - return name.replace(CONVERT_TO_CAMELCASE, function (match, group, index) { - return index ? group.toUpperCase() : match; + return name.replace(CONVERT_TO_CAMELCASE, function (match, underscores, nextChar, index) { + if (!index) { + return match; + } + if (nextChar.toUpperCase() === nextChar) { + return match; + } + + return "" + underscores.substr(1) + nextChar.toUpperCase(); }); } }; })(); +'use strict'; + +var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); + +(function () { + scrivito.AttributeSerializer = { + serialize: function serialize(attributes) { + var serializedAttributes = {}; + _.each(attributes, function (_ref, name) { + var _ref2 = _slicedToArray(_ref, 2); + + var value = _ref2[0]; + var attrInfo = _ref2[1]; + + var serializedName = convertCamelCasedAttributeName(name); + if (scrivito.Attribute.isSystemAttribute(serializedName)) { + serializedAttributes[serializedName] = value; + } else { + var _attrInfo = _slicedToArray(attrInfo, 2); + + var attrType = _attrInfo[0]; + var attrOptions = _attrInfo[1]; + + serializedAttributes[serializedName] = [serializeAttributeType(attrType, name), valueOrNull(serializeAttributeValue(attrType, attrOptions, value, name))]; + } + }); + + return serializedAttributes; + } + }; + + function convertCamelCasedAttributeName(name) { + if (!scrivito.attributeInflection.isCamelCase(name)) { + throw new scrivito.ArgumentError('Attribute names have to be in camel case.'); + } + + return scrivito.attributeInflection.underscore(name); + } + + function serializeAttributeType(type, name) { + switch (type) { + case 'enum': + return 'string'; + case 'float': + case 'integer': + return 'number'; + case 'multienum': + return 'stringlist'; + case 'binary': + case 'date': + case 'html': + case 'link': + case 'linklist': + case 'reference': + case 'referencelist': + case 'string': + case 'stringlist': + case 'widgetlist': + return type; + default: + throw new scrivito.ArgumentError('Attribute "' + name + '" is of unsupported type "' + type + '".'); + } + } + + function serializeAttributeValue(type, options, value, name) { + if (value === null) { + return value; + } + + switch (type) { + case 'binary': + return serializeBinaryAttributeValue(value, name); + case 'date': + return serializeDateAttributeValue(value, name); + case 'enum': + return serializeEnumAttributeValue(options, value, name); + case 'float': + return serializeFloatAttributeValue(value, name); + case 'html': + return serializeHtmlAttributeValue(value, name); + case 'integer': + return serializeIntegerAttributeValue(value, name); + case 'link': + return serializeLinkAttributeValue(value, name); + case 'linklist': + return serializeLinklistAttributeValue(value, name); + case 'multienum': + return serializeMultienumAttributeValue(options, value, name); + case 'reference': + return serializeReferenceAttributeValue(value, name); + case 'referencelist': + return serializeReferencelistAttributeValue(value, name); + case 'string': + return serializeStringAttributeValue(value, name); + case 'stringlist': + return serializeStringlistAttributeValue(value, name); + case 'widgetlist': + return serializeWidgetlistAttributeValue(value, name); + default: + throw new scrivito.InternalError('serializeAttributeValue is not implemented for "' + type + '".'); + } + } + + function valueOrNull(value) { + if ((_.isString(value) || _.isArray(value)) && _.isEmpty(value)) { + return null; + } + return value; + } + + function throwInvalidAttributeValue(value, name, expected) { + throw new scrivito.ArgumentError('Unexpected value ' + scrivito.prettyPrint(value) + ' for' + (' attribute "' + name + '". Expected: ' + expected)); + } + + function serializeBinaryAttributeValue(value, name) { + if (value instanceof scrivito.Binary) { + return { id: value.id }; + } + throwInvalidAttributeValue(value, name, 'A Binary.'); + } + + function serializeDateAttributeValue(value, name) { + if (_.isDate(value)) { + return scrivito.types.formatDateToString(value); + } + if (scrivito.types.isValidDateString(value)) { + return value; + } + throwInvalidAttributeValue(value, name, 'A Date.'); + } + + function serializeEnumAttributeValue(_ref3, value, name) { + var validValues = _ref3.validValues; + + if (_.contains(validValues, value)) { + return value; + } + + var e = 'Valid attribute values are contained in its "validValues" array [' + validValues + '].'; + throwInvalidAttributeValue(value, name, e); + } + + function serializeFloatAttributeValue(value, name) { + if (scrivito.types.isValidFloat(value)) { + return value; + } + + var invalidValue = value; + if (_.isNumber(value)) { + invalidValue = String(value); + } + throwInvalidAttributeValue(invalidValue, name, 'A Number, that is #isFinite().'); + } + + function serializeHtmlAttributeValue(value, name) { + if (_.isString(value)) { + return value; + } + throwInvalidAttributeValue(value, name, 'A String.'); + } + + function serializeIntegerAttributeValue(value, name) { + if (scrivito.types.isValidInteger(value)) { + return value; + } + throwInvalidAttributeValue(value, name, 'A Number, that is #isSafeInteger().'); + } + + function serializeLinkAttributeValue(value, name) { + if (validLinkObject(value)) { + return convertLinkToCmsApi(value); + } + throwInvalidAttributeValue(value, name, 'A Link instance.'); + } + + function serializeLinklistAttributeValue(value, name) { + if (_.isArray(value) && _.every(value, validLinkObject)) { + return _.map(value, convertLinkToCmsApi); + } + throwInvalidAttributeValue(value, name, 'An array of Link instances.'); + } + + function validLinkObject(value) { + if (value instanceof scrivito.BasicLink) { + return true; + } + + // check if value is backend compatible + if (!_.isObject(value)) { + return false; + } + var invalidKeys = _.without(_.keys(value), 'fragment', 'obj_id', 'query', 'target', 'title', 'url'); + return _.isEmpty(invalidKeys); + } + + function convertLinkToCmsApi(value) { + var backendLink = { + fragment: value.fragment, + query: value.query, + target: value.target, + title: value.title, + url: value.url + }; + backendLink.obj_id = value.objId || value.obj_id; + + return _.mapObject(backendLink, function (v) { + return v || null; + }); + } + + function serializeMultienumAttributeValue(_ref4, value, name) { + var validValues = _ref4.validValues; + + var errorMessage = 'An array with values from ' + scrivito.prettyPrint(validValues) + '.'; + + if (!_.isArray(value) || !_.every(value, _.isString)) { + throwInvalidAttributeValue(value, name, errorMessage); + } + + var forbiddenValues = _.difference(value, validValues); + if (forbiddenValues.length) { + var e = errorMessage + ' Forbidden values: ' + scrivito.prettyPrint(forbiddenValues) + '.'; + throwInvalidAttributeValue(value, name, e); + } + return value; + } + + function serializeReferenceAttributeValue(value, name) { + if (isValidReference(value)) { + return serializeSingleReferenceValue(value); + } + throwInvalidAttributeValue(value, name, 'A BasicObj or a String ID.'); + } + + function serializeReferencelistAttributeValue(value, name) { + if (isValidReferencelistValue(value)) { + return _.map(value, serializeSingleReferenceValue); + } + throwInvalidAttributeValue(value, name, 'An array with BasicObjs or String IDs.'); + } + + function serializeSingleReferenceValue(value) { + if (value instanceof scrivito.BasicObj) { + return value.id; + } + return value; + } + + function isValidReference(value) { + return _.isString(value) || value instanceof scrivito.BasicObj; + } + + function isValidReferencelistValue(value) { + return _.isArray(value) && _.every(value, function (v) { + return isValidReference(v); + }); + } + + function serializeStringAttributeValue(value, name) { + if (isValidString(value)) { + return value.toString(); + } + throwInvalidAttributeValue(value, name, 'A String.'); + } + + function serializeStringlistAttributeValue(value, name) { + if (_.isArray(value) && _.every(value, function (v) { + return isValidString(v); + })) { + return _.invoke(value, 'toString'); + } + throwInvalidAttributeValue(value, name, 'An array of strings.'); + } + + function isValidString(value) { + return _.isString(value) || _.isNumber(value); + } + + function serializeWidgetlistAttributeValue(value, name) { + if (_.isArray(value) && _.every(value, function (v) { + return v instanceof scrivito.BasicWidget; + })) { + return _.pluck(value, 'id'); + } + throwInvalidAttributeValue(value, name, 'An array of scrivito.BasicWidget instances.'); + } +})(); "use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -12238,10 +12534,47 @@ })(); })(); "use strict"; (function () { + var bufferedUpdates = []; + + var isUpdateScheduled = function isUpdateScheduled() { + return bufferedUpdates.length; + }; + + function add(callback) { + if (!isUpdateScheduled()) { + scrivito.nextTick(function () { + scrivito.modelState.withBatchedUpdates(function () { + return performUpdate(bufferedUpdates); + }); + }); + } + + bufferedUpdates.push(callback); + } + + function performUpdate(callbacks) { + bufferedUpdates = []; + + try { + callbacks.forEach(function (callback) { + return callback(); + }); + } finally { + if (isUpdateScheduled()) { + performUpdate(bufferedUpdates); + } + } + } + + scrivito.batchedStateUpdater = { add: add }; +})(); +"use strict"; + +(function () { scrivito.BinaryUtils = { isBlob: function isBlob(obj) { return !!obj && _.isNumber(obj.size) && _.isString(obj.type); }, @@ -12712,46 +13045,10 @@ return NetworkError; })(scrivito.CommunicationError); /** - * A `NotLoadedError` is thrown when data is accessed in a synchronous fashion but is not yet - * available locally. For example {@link scrivito.BasicObj.get} throws a `NotLoadedError` - * whenever a CMS object is accessed that is not yet cached in the browser. - */ - scrivito.NotLoadedError = (function (_scrivito$ScrivitoError5) { - _inherits(NotLoadedError, _scrivito$ScrivitoError5); - - /** - * The constructor is not part of the public API and should **not** be used. - */ - - function NotLoadedError(loader) { - _classCallCheck(this, NotLoadedError); - - _get(Object.getPrototypeOf(NotLoadedError.prototype), 'constructor', this).call(this, 'Data is not yet loaded. Call the instance method "load" to load data.'); - this._loader = loader; - } - - _createClass(NotLoadedError, [{ - key: 'load', - value: function load(onLoadingDone) { - var loadPromise = this._loader(); - - if (onLoadingDone) { - var done = function done() { - scrivito.nextTick(onLoadingDone); - }; - loadPromise.then(done, done); - } - } - }]); - - return NotLoadedError; - })(scrivito.ScrivitoError); - - /** * An error thrown in case a backend request from the UI * exceeds the rate limit of the backend. */ scrivito.RateLimitExceededError = (function (_scrivito$CommunicationError3) { _inherits(RateLimitExceededError, _scrivito$CommunicationError3); @@ -12770,12 +13067,12 @@ })(scrivito.CommunicationError); /** * An error thrown in case a given Scrivito resource is not found. */ - scrivito.ResourceNotFoundError = (function (_scrivito$ScrivitoError6) { - _inherits(ResourceNotFoundError, _scrivito$ScrivitoError6); + scrivito.ResourceNotFoundError = (function (_scrivito$ScrivitoError5) { + _inherits(ResourceNotFoundError, _scrivito$ScrivitoError5); /** * The constructor is not part of the public API and should **not** be used. */ @@ -12831,11 +13128,92 @@ return InterpolationError; })(scrivito.TranslationError); })(); 'use strict'; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + (function () { + var VALID_OPTIONS = ['limit', 'includeObjs']; + + var FacetQuery = (function () { + function FacetQuery(attribute, options, searchQuery) { + var _this = this; + + _classCallCheck(this, FacetQuery); + + assertValidOptions(options); + + this._requestParams = buildRequestParams(attribute, options, searchQuery); + + var subStateKey = scrivito.computeCacheKey(this._requestParams); + var modelState = scrivito.modelState.subState('facetQuery').subState(subStateKey); + + this._loadableData = new scrivito.LoadableData({ + state: modelState, + loader: function loader() { + return _this._loadData(); + } + }); + } + + _createClass(FacetQuery, [{ + key: 'result', + value: function result() { + var firstFacetResult = _.first(this._loadableData.get().facets); + + return _.map(firstFacetResult, function (rawFacetValue) { + var name = rawFacetValue.value; + var count = rawFacetValue.total; + var includedObjs = _.pluck(rawFacetValue.results, 'id'); + + return new scrivito.BasicObjFacetValue(name, count, includedObjs); + }); + } + }, { + key: '_loadData', + value: function _loadData() { + var workspaceId = scrivito.currentWorkspaceId(); + return scrivito.CmsRestApi.get('workspaces/' + workspaceId + '/objs/search', this._requestParams); + } + }]); + + return FacetQuery; + })(); + + function assertValidOptions(options) { + var _ref; + + var invalidOptions = (_ref = _).without.apply(_ref, [_.keys(options)].concat(VALID_OPTIONS)); + if (invalidOptions.length) { + throw new scrivito.ArgumentError('Invalid options: ' + (scrivito.prettyPrint(invalidOptions) + '. Valid options: ' + VALID_OPTIONS)); + } + } + + function buildRequestParams(attribute, options, searchQuery) { + var requestParams = { + facets: [{ + attribute: attribute, + limit: options.limit || 20, + include_objs: options.includeObjs || 0 + }], + size: 0 + }; + if (searchQuery && searchQuery.length) { + requestParams.query = searchQuery; + } + + return requestParams; + } + + scrivito.FacetQuery = FacetQuery; +})(); +'use strict'; + +(function () { var isDisabled = false; var connectionCounter = 0; // For test purpose only scrivito.isFetchingActive = function () { @@ -12886,11 +13264,18 @@ function onAjaxLoad(request, resolve, reject) { connectionCounter -= 1; if (request.status >= 200 && request.status < 300) { - return resolve(request.response); + var responseJSON = request.response; + + if (_.isString(responseJSON)) { + // We can't use #response here as IE11 does not handle it correctly + responseJSON = JSON.parse(request.responseText); + } + + return resolve(responseJSON); } return reject(request.response); } @@ -12955,11 +13340,11 @@ return new scrivito.Promise(function (resolve, reject) { function tryToSettle() { try { resolve(loadableFunction()); } catch (error) { - if (error instanceof scrivito.NotLoadedError) { + if (scrivito.isNotLoadedError(error)) { error.load(tryToSettle); } else { reject(error); } } @@ -13089,11 +13474,11 @@ // set the data to an error. }, { key: 'setError', value: function setError(error) { - if (error instanceof scrivito.NotLoadedError) { + if (scrivito.isNotLoadedError(error)) { // prevent setting a NotLoadedError, since that would // unravel the space-time continuum and destroy the world. var warning = new scrivito.InternalError('tried to set a Loadable to a NotLoadedError'); this._value.transitionTo(ERROR, warning, this._currentVersion()); @@ -13166,17 +13551,33 @@ } }; var versionWhenLoadingStarted = this._currentVersion(); - this._loader().then(function (result) { + var pushCallbacks = []; + var addPushCallback = function addPushCallback(callback) { + return pushCallbacks.push(callback); + }; + var runPushCallbacks = function runPushCallbacks() { + return pushCallbacks.forEach(function (callback) { + return callback(); + }); + }; + + this._loader(addPushCallback).then(function (result) { return ifUnchanged(function () { - return _this2._value.transitionTo(AVAILABLE, result, versionWhenLoadingStarted); + return scrivito.batchedStateUpdater.add(function () { + _this2._value.transitionTo(AVAILABLE, result, versionWhenLoadingStarted); + runPushCallbacks(); + }); }); }, function (error) { return ifUnchanged(function () { - return _this2._value.transitionTo(ERROR, error, versionWhenLoadingStarted); + return scrivito.batchedStateUpdater.add(function () { + _this2._value.transitionTo(ERROR, error, versionWhenLoadingStarted); + runPushCallbacks(); + }); }); }); this._value.setLoading(loadId); } @@ -13246,10 +13647,12 @@ var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } (function () { + var loadingState = {}; + var EMPTY_STATE = {}; // A wrapper around a value that is retrieved asynchronously. // This class is stateless and (almost) pure: // * it does not perform any I/O @@ -13257,19 +13660,27 @@ // * it does not keep any state itself // * state is replaced, not mutated // * it does not use Promises var LoadableValue = (function () { - // stateContainer is where the LoadableValue should store its state. + _createClass(LoadableValue, null, [{ + key: 'resetLoadingState', + value: function resetLoadingState() { + loadingState = {}; + } + // stateContainer is where the LoadableValue should store its state. + }]); + function LoadableValue(stateContainer) { _classCallCheck(this, LoadableValue); if (!stateContainer) { throw new scrivito.InternalError('LoadableValue needs stateContainer'); } this._container = stateContainer; + this._id = stateContainer.id(); } // export // store a loadId to identify the current load operation. @@ -13278,18 +13689,18 @@ // loadId may be any kind of JS object. _createClass(LoadableValue, [{ key: 'setLoading', value: function setLoading(loadId) { - this._container.set(_.extend({}, this._getState(), { loadId: loadId })); + loadingState[this._id] = loadId; } // return the current loadId. should only be called if loading. }, { key: 'getLoading', value: function getLoading() { - return this._getState().loadId; + return loadingState[this._id]; } }, { key: 'subscribe', value: function subscribe(listener) { return this._container.subscribe(listener); @@ -13310,10 +13721,11 @@ return this._getState().version; } }, { key: 'transitionTo', value: function transitionTo(status, value, version) { + delete loadingState[this._id]; this._container.set({ status: status, value: value, version: version }); } }, { key: '_getState', value: function _getState() { @@ -13335,11 +13747,11 @@ _.each(list, function (item) { try { results.push(iteratee(item)); } catch (error) { - if (error instanceof scrivito.NotLoadedError) { + if (scrivito.isNotLoadedError(error)) { errors.push(error); } else { throw error; } } @@ -13365,12 +13777,77 @@ return results; }; })(); 'use strict'; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +(function () { + /** + * A `NotLoadedError` is thrown when data is accessed in a synchronous fashion but is not yet + * available locally. For example {@link scrivito.BasicObj.get} throws a `NotLoadedError` + * whenever a CMS object is accessed that is not yet cached in the browser. + */ + + var NotLoadedError = (function (_scrivito$ScrivitoError) { + _inherits(NotLoadedError, _scrivito$ScrivitoError); + + /** + * The constructor is not part of the public API and should **not** be used. + */ + + function NotLoadedError(loader) { + _classCallCheck(this, NotLoadedError); + + _get(Object.getPrototypeOf(NotLoadedError.prototype), 'constructor', this).call(this, 'Data is not yet loaded.'); + this._loader = loader; + } + + _createClass(NotLoadedError, [{ + key: 'load', + value: function load(onLoadingDone) { + var loadPromise = this._loader(); + + if (onLoadingDone) { + var done = function done() { + scrivito.nextTick(onLoadingDone); + }; + loadPromise.then(done, done); + } + } + + // this getter has an extravagant name, in order to avoid name clashes + }, { + key: 'scrivitoPrivateIsNotLoadedError', + get: function get() { + return true; + } + }]); + + return NotLoadedError; + })(scrivito.ScrivitoError); + + function isNotLoadedError(error) { + // using duck-typing instead of "instanceof", so that these errors + // can be recognized across javascript (iframe) boundaries. + return error.scrivitoPrivateIsNotLoadedError; + } + + // export + scrivito.NotLoadedError = NotLoadedError; + scrivito.isNotLoadedError = isNotLoadedError; +})(); +'use strict'; + +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } @@ -14153,10 +14630,15 @@ key: 'fetch', value: function fetch(_id) { scrivito.asyncMethodStub(); } }, { + key: 'fetchIncludingDeleted', + value: function fetchIncludingDeleted(_id) { + scrivito.asyncMethodStub(); + } + }, { key: 'get', value: function get(idOrList) { var _this = this; if (_.isArray(idOrList)) { @@ -14477,11 +14959,11 @@ } }, { key: 'lastChanged', get: function get() { if (this._current._last_changed) { - return scrivito.parseDate(this._current._last_changed); + return scrivito.types.parseStringToDate(this._current._last_changed); } return null; } }, { @@ -14520,12 +15002,12 @@ } }, { key: 'children', get: function get() { if (this.path) { - var iterator = scrivito.BasicObj.where('_parent_path', 'equals', this.path).iterator(); - return scrivito.iterable.collectValuesFromIterator(iterator); + var iterable = scrivito.BasicObj.all().and('_parent_path', 'equals', this.path); + return scrivito.iterable.collectValuesFromIterator(iterable.iterator()); } return []; } }, { @@ -14581,11 +15063,12 @@ return BasicObj; })(scrivito.BasicAttributeContent); scrivito.provideAsyncClassMethods(scrivito.BasicObj, { - get: 'fetch' + get: 'fetch', + getIncludingDeleted: 'fetchIncludingDeleted' }); scrivito.provideAsyncInstanceMethods(scrivito.BasicObj, { getParent: 'fetchParent' }); @@ -14658,10 +15141,48 @@ function throwObjNotFound(id) { throw new scrivito.ResourceNotFoundError('Obj with id "' + id + '" not found.'); } })(); +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +(function () { + var BasicObjFacetValue = (function () { + function BasicObjFacetValue(name, count, includedObjs) { + _classCallCheck(this, BasicObjFacetValue); + + this._name = name; + this._count = count; + this._includedObjs = includedObjs; + } + + _createClass(BasicObjFacetValue, [{ + key: "includedObjs", + value: function includedObjs() { + return scrivito.BasicObj.get(this._includedObjs); + } + }, { + key: "name", + get: function get() { + return this._name; + } + }, { + key: "count", + get: function get() { + return this._count; + } + }]); + + return BasicObjFacetValue; + })(); + + scrivito.BasicObjFacetValue = BasicObjFacetValue; +})(); 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } @@ -14805,10 +15326,18 @@ // For test purpose only. value: function getBatchSize() { return this._batchSize; } }, { + key: 'facet', + value: function facet(attribute) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var facetQuery = new scrivito.FacetQuery(attribute, options, this._query); + return facetQuery.result(); + } + }, { key: 'params', get: function get() { return this._params; } }, { @@ -15702,10 +16231,81 @@ return value; } }); } })(); +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +(function () { + /** + * Instances of this class represent the result of a faceted search. + */ + + var ObjFacetValue = (function () { + function ObjFacetValue(registry, basicObjFacetValue) { + _classCallCheck(this, ObjFacetValue); + + this._registry = registry; + this._basicObjFacetValue = basicObjFacetValue; + } + + /** + * The name of this ObjFacetValue, i.e. the value of the attribute. + * + * Example: If you do faceting using the attribute `color`, + * you might receive an `ObjFacetValue` with the name `yellow`, + * another one with the name `green` and so on. + * + * @type {String} + */ + + _createClass(ObjFacetValue, [{ + key: "includedObjs", + + /** + * The Objs that were included in this search. + * + * If you did not specify `includeObjs` in your facet options, an empty array is returned. + * The Objs are ordered by relevance. + * + * @throws {scrivito.NotLoadedError} If some of the data is not yet loaded. + * @return {Array<Obj>} + */ + value: function includedObjs() { + var response = this._basicObjFacetValue.includedObjs(); + return scrivito.wrapInAppClass(this._registry, response); + } + }, { + key: "name", + get: function get() { + return this._basicObjFacetValue.name; + } + + /** + * Total number of Objs available that have this value. + * + * Note that this refers to all Objs, not just the Objs included in this search. + * Also note that the count is approximate. + * + * @type {Number} + */ + }, { + key: "count", + get: function get() { + return this._basicObjFacetValue.count; + } + }]); + + return ObjFacetValue; + })(); + + scrivito.ObjFacetValue = ObjFacetValue; +})(); 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; @@ -15723,10 +16323,14 @@ } return iterable; } + function wrap(response) { + return scrivito.wrapInAppClass(registry, response); + } + /** * The base class for CMS objects. * * * A CMS object is a collection of properties and their values, as defined @@ -15747,33 +16351,59 @@ _get(Object.getPrototypeOf(Obj.prototype), 'constructor', this).apply(this, arguments); } _createClass(Obj, [{ - key: 'destroy', + key: 'isBinary', /** + * This method indicates whether the Obj represents binary data. Binaries are + * handled differently in that they are not rendered using the normal layout + * but sent as a file. Examples of binary resources are Images or PDFs. + * + * Every Obj that has a `blob` attribute of the `binary` type is + * considered a binary + * + * @returns {Boolean} `true` if this Obj represents a binary resource. + */ + value: function isBinary() { + var blobTypeInfo = this.constructor._scrivitoPrivateSchema.attributes.blob; + return blobTypeInfo === 'binary'; + } + + /** * Destroy this CMS object in the current Workspace. */ + }, { + key: 'destroy', value: function destroy() { this._scrivitoPrivateContent.destroy(); } /** * Access widgets by their ids * + * Returns `null` if no matching Widget exists. + * * @param {String} id - the widget's id - * @returns {scrivito.Widget} + * @returns {?Widget} */ }, { key: 'widget', value: function widget(id) { - var widget = this._scrivitoPrivateContent.widget(id); + return wrap(this._scrivitoPrivateContent.widget(id)); + } - if (widget) { - return scrivito.wrapInAppClass(registry, widget); - } + /** + * Returns all {@link Widget widgets} of the given CMS object. + * + * @returns {Widget[]} + */ + }, { + key: 'widgets', + value: function widgets() { + return wrap(this._scrivitoPrivateContent.widgets()); } }, { key: 'lastChanged', /** @@ -15794,10 +16424,69 @@ get: function get() { return this._scrivitoPrivateContent.path; } /** + * Returns the {@link Obj} that is the parent of this Obj. + * Returns `null` if the obj has no `path` or is the root Obj. + * + * Throws a {@link scrivito.NotLoadedError} if the parent is not yet loaded. + * + * @type {?Obj} + */ + }, { + key: 'parent', + get: function get() { + return wrap(this._scrivitoPrivateContent.parent); + } + + /** + * Returns an Array of all the ancestor {@link Obj Objs}, starting at the + * root and ending at the parent of this object. + * + * Throws a {@link scrivito.NotLoadedError} if the ancestors have not yet been loaded. + * + * @type {Obj[]} + */ + }, { + key: 'ancestors', + get: function get() { + return wrap(this._scrivitoPrivateContent.ancestors); + } + + /** + * Returns a list of all {@link Obj Objs} that link to this Obj. + * + * This includes all CMS objects in which at least one `html`, + * `link`, `linklist`, `reference` or `referencelist` attribute links to this CMS object. + * + * Attributes inside {@link Widget Widgets} are considered, too. + * + * Throws a {@link scrivito.NotLoadedError} if the backlinks have not yet been loaded. + * + * @type {Obj[]} + */ + }, { + key: 'backlinks', + get: function get() { + return wrap(this._scrivitoPrivateContent.backlinks); + } + + /** + * Returns a list of all child {@link Obj Objs}. + * + * Throws a {@link scrivito.NotLoadedError} if the children have not yet been loaded. + * + * @type {Obj[]} + */ + }, { + key: 'children', + get: function get() { + return wrap(this._scrivitoPrivateContent.children); + } + + /** * The permalink of the CMS object * @type {?String} */ }, { key: 'permalink', @@ -15826,10 +16515,38 @@ return scrivito.wrapInAppClass(registry, instance); } /** + * Get a given Obj by its `path`. + * + * Returns `null` if no matching Obj exists. + * + * @param {String} path - The path of the Obj + * @returns {?Obj} + */ + }, { + key: 'getByPath', + value: function getByPath(path) { + return wrap(scrivito.BasicObj.getByPath(path)); + } + + /** + * Get a given Obj by its `permalink`. + * + * Returns `null` if no matching Obj exists. + * + * @param {String} permalink - The permalink of the Obj + * @returns {?Obj} + */ + }, { + key: 'getByPermalink', + value: function getByPermalink(permalink) { + return wrap(scrivito.BasicObj.getByPermalink(permalink)); + } + + /** * Returns an {@link ObjSearchIterable} of all {@link Obj}s. * @return {ObjSearchIterable} */ }, { key: 'all', @@ -15891,13 +16608,11 @@ } attributes._objClass = appClassName; var attributesWithTypeInfo = scrivito.AttributeContentFactory.prepareAttributes(attributes, schema, appClassName); - var basicObj = scrivito.BasicObj.create(attributesWithTypeInfo); - - return scrivito.wrapInAppClass(registry, basicObj); + return wrap(scrivito.BasicObj.create(attributesWithTypeInfo)); } }]); return Obj; })(scrivito.AttributeContentFactory(registry)); @@ -15909,11 +16624,11 @@ })(); "use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +var _get = function get(_x3, _x4, _x5) { var _again = true; _function: while (_again) { var object = _x3, property = _x4, receiver = _x5; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x3 = parent; _x4 = property; _x5 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } @@ -15986,11 +16701,11 @@ * * ✘ "Some" (not exact value) * * **`starts_with`** * - * The `starts_with` is intended for programmatic comparions of string values. + * The `starts_with` is intended for programmatic comparisons of string values. * * The `starts_with` operator has a precision limit: * Only prefixes of up to 20 characters are guaranteed to be matched. * If you supply a prefix of more than 20 characters, the additional characters may be ignored. * @@ -16232,10 +16947,49 @@ key: "andNot", value: function andNot(field, operator, value) { var unwrappedValue = scrivito.unwrapAppClassValues(value); return _get(Object.getPrototypeOf(ObjSearchIterable.prototype), "andNot", this).call(this, field, operator, unwrappedValue); } + + /** + * Perform a faceted search over one attribute to retrieve structured results for + * individual values of this attribute. + * + * Applicable to attributes of the following types: `string`, `stringlist`, `enum` and + * `multienum`. + * + * Please note that there is a precision limit for faceting: Only the first 50 characters + * of a string are guaranteed to be considered for faceting. If two string values have the + * same first 50 characters, they may be grouped into the same facet value. + * + * @param {String} attribute The name of an attribute. + * @param {Object} [option={}] - The options to facet a request with. + * @param {Number} option.limit - The maximum number of unique values to return. + * Defaults to `20`. + * @param {Number} option.includeObjs - The number of Objs to fetch for each unique value. + * Defaults to `0`. + * + * @throws {scrivito.ArgumentError} If an invalid option is given. + * @throws {scrivito.NotLoadedError} If some of the data is not yet loaded. + * @throws {scrivito.ClientError} If the maximum number of results has been exceeded. + * The number of results is limited to 100 with respect to the facets themselves + * and the included Objs. + * + * @return {Array<scrivito.ObjFacetValue>} A list of unique values that were found for the + * given attribute name. The list is ordered by frequency, i.e. values occurring more + * frequently come first. + */ + }, { + key: "facet", + value: function facet(attribute) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var result = _get(Object.getPrototypeOf(ObjSearchIterable.prototype), "facet", this).call(this, attribute, options); + return _.map(result, function (facetValue) { + return new scrivito.ObjFacetValue(registry, facetValue); + }); + } }]); return ObjSearchIterable; })(scrivito.BasicObjSearchIterable); @@ -16244,10 +16998,12 @@ scrivito.ObjSearchIterableFactory = ObjSearchIterableFactory; })(); 'use strict'; +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } @@ -16307,10 +17063,41 @@ var attributesWithTypeInfo = scrivito.AttributeContentFactory.prepareAttributes(attributes, schema, appClassName); this._scrivitoPrivateContent = new scrivito.BasicWidget(attributesWithTypeInfo); } + /** + * The CMS object the widget is contained in + * @type {Obj} + */ + + _createClass(Widget, [{ + key: 'copy', + + /** + * Create a copy of a {@link Widget}. + * + * The copy will have all the attributes of the original widget including its widgets. + * Its attributes can be accessed only after it has been stored in a `widgetlist` field + * of an {@link Obj}, since initially the copy is not stored in such a field. + * + * @return {Widget} a copy of the widget + */ + value: function copy() { + var appClass = registry.widgetClassFor(this.objClass); + var basicWidget = this._scrivitoPrivateContent.copy(); + + return scrivito.buildAppClassInstance(basicWidget, appClass); + } + }, { + key: 'obj', + get: function get() { + var basicObj = this._scrivitoPrivateContent.obj; + return scrivito.wrapInAppClass(registry, basicObj); + } + }]); + return Widget; })(scrivito.AttributeContentFactory(registry)); return Widget; } @@ -16372,13 +17159,15 @@ _classCallCheck(this, ObjData); this._loadableData = new scrivito.LoadableData({ state: state, - loader: function loader() { + loader: function loader(push) { return scrivito.ObjRetrieval.retrieveObj(_this._id).then(function (data) { - scrivito.ObjReplication.get(_this._id).notifyBackendState(data); + push(function () { + return _this._replication().notifyBackendState(data); + }); return data; }); } }); this._id = id; @@ -16564,87 +17353,123 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } (function () { scrivito.ObjQueryBatch = (function () { + _createClass(ObjQueryBatch, null, [{ + key: "firstBatchFor", + value: function firstBatchFor(params, batchSize) { + return new ObjQueryBatch(params, batchSize); + } + + // the constructor should only be called internally, + // i.e. by ObjQueryBatch itself + }]); + + function ObjQueryBatch(params, batchSize) { + var previousBatch = arguments.length <= 2 || arguments[2] === undefined ? undefined : arguments[2]; + + _classCallCheck(this, ObjQueryBatch); + + this._params = params; + this._batchSize = batchSize; + + if (previousBatch) { + this._index = previousBatch.index + 1; + this._continuation = previousBatch.continuationForNextBatch(); + this._previousBatch = previousBatch; + } else { + // First batch + this._index = 0; + } + } + + // throws NotLoadedError if not available + _createClass(ObjQueryBatch, [{ key: "objIds", - - // throws NotLoadedError if not available value: function objIds() { return this._response().results; } // returns the next batch or undefined if this is the last batch // throws NotLoadedError if not available }, { key: "nextBatch", value: function nextBatch() { - var continuation = this._response().continuation; - - if (continuation) { - return new ObjQueryBatch(this._params, this._batchSize, continuation); + if (this.continuationForNextBatch()) { + return new ObjQueryBatch(this._params, this._batchSize, this); } } - - // the constructor should only be called internally, - // i.e. by ObjQueryBatch itself - }], [{ - key: "firstBatchFor", - value: function firstBatchFor(params, batchSize) { - return new ObjQueryBatch(params, batchSize); + }, { + key: "continuationForNextBatch", + value: function continuationForNextBatch() { + return this._response().continuation; } - }]); - - function ObjQueryBatch(params, batchSize, continuation) { - _classCallCheck(this, ObjQueryBatch); - - this._params = params; - this._continuation = continuation; - this._batchSize = batchSize; - } - - _createClass(ObjQueryBatch, [{ + }, { key: "_response", value: function _response() { return this._data().get(); } }, { key: "_data", value: function _data() { var _this = this; - var paramsWithContinuation = _.extend({}, this._params, { continuation: this._continuation }); + var paramsWithIndex = _.extend({}, this._params, { index: this._index }); + var key = scrivito.ObjQueryStore.computeCacheKey(paramsWithIndex); - var key = scrivito.ObjQueryStore.computeCacheKey(paramsWithContinuation); - return new scrivito.LoadableData({ state: scrivito.ObjQueryStore.stateContainer().subState(key), loader: function loader() { return _this._load(); }, invalidation: function invalidation() { - return scrivito.ObjReplication.getWorkspaceVersion(); + return _this._version(); } }); } }, { key: "_load", value: function _load() { - var batchSpecificParams = { - size: this._batchSize, - continuation: this._continuation - }; + var _this2 = this; - var requestParams = _.extend({}, this._params, batchSpecificParams); + return this._fetchContinuation().then(function (continuation) { + var batchSpecificParams = { size: _this2._batchSize, continuation: continuation }; - return scrivito.ObjQueryRetrieval.retrieve(requestParams).then(function (response) { - preloadObjData(response.results); + var requestParams = _.extend({}, _this2._params, batchSpecificParams); - return response; + return scrivito.ObjQueryRetrieval.retrieve(requestParams).then(function (response) { + preloadObjData(response.results); + + return response; + }); }); } + }, { + key: "_fetchContinuation", + value: function _fetchContinuation() { + var _this3 = this; + + if (this._previousBatch) { + return scrivito.loadAsync(function () { + return _this3._previousBatch.continuationForNextBatch(); + }); + } + + return scrivito.Promise.resolve(); + } + }, { + key: "_version", + value: function _version() { + return this._continuation + "|" + scrivito.ObjReplication.getWorkspaceVersion(); + } + }, { + key: "index", + get: function get() { + return this._index; + } }]); return ObjQueryBatch; })(); @@ -16786,17 +17611,22 @@ return workspaceVersion; } }]); function ObjReplication(id) { + var _this = this; + _classCallCheck(this, ObjReplication); this._id = id; this._replicationActive = false; this._scheduledReplication = false; this._currentRequestDeferred = null; this._nextRequestDeferred = null; + this._performThrottledReplication = scrivito.throttle(function () { + return _this._performReplication(); + }, 1000); } _createClass(ObjReplication, [{ key: 'notifyLocalState', value: function notifyLocalState(localState) { @@ -16856,21 +17686,21 @@ }); } }, { key: '_startReplication', value: function _startReplication() { - var _this = this; + var _this2 = this; if (!_.isEmpty(diff(this._backendState, this._localState))) { if (!this._replicationActive) { if (!this._scheduledReplication) { this._scheduledReplication = true; this._initDeferredForRequest(); writeStarted(this._currentRequestDeferred.promise); scrivito.nextTick(function () { - return _this._performReplication(); + return _this2._performThrottledReplication(); }); } } else { if (!this._nextRequestDeferred) { this._nextRequestDeferred = new scrivito.Deferred(); @@ -16884,29 +17714,29 @@ } } }, { key: '_performReplication', value: function _performReplication() { - var _this2 = this; + var _this3 = this; var localState = this._localState; var patch = diff(this._backendState, this._localState); this._scheduledReplication = false; this._replicationActive = true; this._replicatePatchToBackend(patch).then(function (backendState) { - _this2._handleBackendUpdate(localState, backendState); - _this2._currentRequestDeferred.resolve(_this2._id); - _this2._currentRequestDeferred = null; - _this2._replicationActive = false; + _this3._handleBackendUpdate(localState, backendState); + _this3._currentRequestDeferred.resolve(_this3._id); + _this3._currentRequestDeferred = null; + _this3._replicationActive = false; - _this2._startReplication(); + _this3._startReplication(); }, function (error) { - _this2._currentRequestDeferred.reject(error); - _this2._currentRequestDeferred = null; - _this2._replicationActive = false; + _this3._currentRequestDeferred.reject(error); + _this3._currentRequestDeferred = null; + _this3._replicationActive = false; }); } }, { key: '_replicatePatchToBackend', value: function _replicatePatchToBackend(patch) { @@ -17530,10 +18360,12 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } (function () { + var treeIdCounter = 0; + // abstract interface for managing state var AbstractStateStore = (function () { function AbstractStateStore() { _classCallCheck(this, AbstractStateStore); @@ -17555,10 +18387,17 @@ key: 'set', value: function set(_newState) { throw scrivito.InternalError('implement in subclass'); } + // get a string that uniquely identifies this state + }, { + key: 'id', + value: function id() { + throw scrivito.InternalError('implement in subclass'); + } + // subscribe to changes to state // the listener will be called at least once after each state change. // returns a function that should be invoked to unsubscribe. // proper unsubscription is important to avoid leaking memory. }, { @@ -17621,11 +18460,13 @@ function StateTree() { _classCallCheck(this, StateTree); _get(Object.getPrototypeOf(StateTree.prototype), 'constructor', this).call(this); + this._id = (treeIdCounter++).toString(); this._listeners = Immutable.Set(); + this._batchUpdates = false; } // a node of a state tree. // does not actually keep state, but provides // access scoped to a subtree of a StateTree. @@ -17637,15 +18478,23 @@ } }, { key: 'set', value: function set(newState) { this._state = newState; - this._listeners.forEach(function (listener) { - return listener(); - }); + + if (!this._batchUpdates) { + this._listeners.forEach(function (listener) { + return listener(); + }); + } } }, { + key: 'id', + value: function id() { + return this._id; + } + }, { key: 'subscribe', value: function subscribe(listener) { var _this = this; if (!listener) { @@ -17656,11 +18505,32 @@ return function () { _this._listeners = _this._listeners.remove(listener); }; } + }, { + key: 'withBatchedUpdates', + value: function withBatchedUpdates(fn) { + if (this._batchUpdates) { + throw new scrivito.InternalError('#withBatchedUpdates can not be nested'); + } + var stateBeforeBatchUpdate = this._state; + + try { + this._batchUpdates = true; + fn(); + } finally { + this._batchUpdates = false; + if (stateBeforeBatchUpdate !== this._state) { + this._listeners.forEach(function (listener) { + return listener(); + }); + } + } + } + // For test purpose only. }, { key: 'listenerCount', value: function listenerCount() { return this._listeners.size; @@ -17704,10 +18574,19 @@ key: 'set', value: function set(newState) { this._parentState.setSubState(this._key, newState); } }, { + key: 'id', + value: function id() { + // first convert backslash to double-backslash + // then convert slash to backslash-slash + var escapedKey = this._key.replace(/\\/g, '\\\\').replace(/\//g, '\\/'); + + return this._parentState.id() + '/' + escapedKey; + } + }, { key: 'subscribe', value: function subscribe(listener) { var _this2 = this; if (!listener) { @@ -17733,10 +18612,26 @@ scrivito.StateTree = StateTree; // singleton instance, to be used by the data layer scrivito.modelState = new StateTree(); })(); +"use strict"; + +(function () { + var shouldBypassThrottle = false; + + function throttle(fn, ms, options) { + return shouldBypassThrottle ? fn : _.throttle(fn, ms, options); + } + + function bypassThrottle() { + shouldBypassThrottle = true; + } + + scrivito.throttle = throttle; + scrivito.bypassThrottle = bypassThrottle; +})(); 'use strict'; var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); (function () { @@ -17815,11 +18710,11 @@ if (!scrivito.types.isValidDateString(value)) { throw new scrivito.InternalError("The value is not a valid ISO date time: \"" + value + "\""); } - return scrivito.parseDate(value); + return scrivito.types.parseStringToDate(value); }, parseStringToDate: function parseStringToDate(dateString) { if (!dateString) { return; @@ -17916,6 +18811,482 @@ return value; } scrivito.wrapInAppClass = wrapInAppClass; scrivito.unwrapAppClassValues = unwrapAppClassValues; + scrivito.buildAppClassInstance = buildAppClassInstance; +})(); +"use strict"; + +(function () { + scrivito.React = {}; +})(); +'use strict'; + +(function () { + var PropTypes = { + oneOfRealmType: function oneOfRealmType() { + for (var _len = arguments.length, typeNames = Array(_len), _key = 0; _key < _len; _key++) { + typeNames[_key] = arguments[_key]; + } + + return function (props, propName, componentName) { + var propValue = props[propName]; + var realm = scrivito.currentRealm(); + + if (!_.any(typeNames, function (name) { + return propValue instanceof (realm[name] || scrivito[name]); + })) { + return new scrivito.ArgumentError('Component "' + componentName + '" received prop "' + propName + '"' + (' with invalid value "' + propValue + '".') + (' Valid are instances of ' + formatRealmTypes(typeNames) + '.')); + } + }; + } + }; + + function formatRealmTypes(typeNames) { + return _.map(typeNames, function (typeName) { + return '"scrivito.' + typeName + '"'; + }).join(', '); + } + + scrivito.PropTypes = PropTypes; +})(); +(function () { + function createReactClass(params) { + var shouldRenderLoader = params.shouldRenderLoader; + var render = params.render; + var componentDidMount = params.componentDidMount; + var componentWillUnmount = params.componentWillUnmount; + + var unsubscribeModelState = undefined; + + return React.createClass(_.extend(params, { + componentDidMount: function () { + var _this = this; + + unsubscribeModelState = scrivito.modelState.subscribe(function () { + if (_this.isMounted()) { + _this.forceUpdate(); + } + }); + + if (componentDidMount) { + componentDidMount.apply(this); + } + }, + + componentWillUnmount: function () { + unsubscribeModelState(); + + if (componentWillUnmount) { + componentWillUnmount.apply(this); + } + }, + + render: function () { + var _this2 = this; + + var handleError = function (error) { + scrivito.nextTick(function () { + throw error; + }); + return shouldRenderLoader ? React.createElement(scrivito.LoaderError, null) : null; + }; + + try { + return scrivito.LoadableData.withEventualConsistency(function () { + return render.apply(_this2); + }); + } catch (error) { + if (error instanceof scrivito.NotLoadedError) { + try { + error.load(); + } catch (error) { + return handleError(error); + } + + if (this.renderWhileLoading) { + return this.renderWhileLoading(); + } + + return shouldRenderLoader ? React.createElement(scrivito.Loader, null) : null; + } + + return handleError(error); + } + } + })); + } + + scrivito.createReactClass = createReactClass; +})(); +"use strict"; + +(function () { + function changeLocation(newLocation) { + window.location = newLocation; + } + + // For test purpose only. + scrivito.changeLocation = changeLocation; +})(); +"use strict"; + +(function () { + var registry = {}; + + var componentRegistry = { + provideComponentClass: function provideComponentClass(appClass, componentClass) { + registry[appClass._scrivitoPrivateSchema.name] = componentClass; + }, + + getComponentClass: function getComponentClass(appClass) { + return registry[appClass._scrivitoPrivateSchema.name]; + }, + + // For test purpose only. + clear: function clear() { + registry = {}; + } + }; + + scrivito.componentRegistry = componentRegistry; +})(); +(function () { + var Content = scrivito.createReactClass({ + displayName: 'scrivito.React.Content', + + propTypes: { + content: scrivito.PropTypes.oneOfRealmType('Obj', 'Widget'), + + attribute: function (props, propName, componentName) { + var validationError = React.PropTypes.string.isRequired(props, propName, componentName); + + if (validationError) { + return validationError; + } + + var attributeName = props[propName]; + + if (/^_/.test(attributeName)) { + return new scrivito.ArgumentError('Component "scrivito.React.Content" received prop "attribute" with invalid value: ' + ('"' + attributeName + '" is a system attribute. Only custom attributes are allowed.')); + } + }, + + tag: React.PropTypes.string + }, + + getDefaultProps: function () { + return { tag: 'div' }; + }, + + render: function () { + var schema = this.props.content.constructor._scrivitoPrivateSchema; + + var attributeName = this.props.attribute; + var attributeType = schema.attributes[attributeName]; + + if (!attributeType) { + throw new scrivito.ArgumentError('Component "scrivito.React.Content" received prop "attribute" with invalid value: ' + ('Attribute "' + attributeName + '" is not defined for content specified in prop "content".')); + } + + var attributeValue = this.props.content.get(attributeName); + + switch (attributeType) { + case 'html': + return this._renderHtml(attributeValue); + case 'string': + return this._renderString(attributeValue); + case 'widgetlist': + return this._renderWidgetlist(attributeValue); + } + + return this._renderContent({ children: this.props.children }); + }, + + _renderHtml: function (attributeValue) { + if (this.props.children) { + return this._renderContent({ children: this.props.children }); + } + + var props = { dangerouslySetInnerHTML: { __html: attributeValue } }; + return this._renderContent({ props: props }); + }, + + _renderString: function (attributeValue) { + return this._renderContent({ children: this.props.children || attributeValue }); + }, + + _renderWidgetlist: function (attributeValue) { + var children = attributeValue.map(function (widget) { + return React.createElement(Widget, { key: widget.id, widget: widget }); + }); + return this._renderContent({ children: children }); + }, + + _renderContent: function (_ref) { + var props = _ref.props; + var children = _ref.children; + + return React.createElement(this.props.tag, _.extend(this._customProps(), props), children); + }, + + _customProps: function () { + return _.omit(this.props, 'content', 'attribute', 'tag'); + } + }); + + var Widget = scrivito.createReactClass({ + render: function () { + var widget = this.props.widget; + var componentClass = scrivito.componentRegistry.getComponentClass(widget.constructor); + + if (!componentClass) { + throw new scrivito.ArgumentError('No component registered for widget class "' + widget.objClass + '".'); + } + + return React.createElement( + 'div', + null, + React.createElement(componentClass, { widget: this.props.widget }) + ); + } + }); + + scrivito.React.Content = Content; +})(); +(function () { + var CurrentPage = scrivito.createReactClass({ + displayName: 'scrivito.React.CurrentPage', + + render: function () { + var currentPage = scrivito.currentPage(); + + if (!currentPage) { + return null; + } + + var appClass = currentPage.constructor; + var componentClass = scrivito.componentRegistry.getComponentClass(appClass); + + if (!componentClass) { + return null; + } + + return React.createElement(componentClass, { page: currentPage }); + } + }); + + scrivito.React.CurrentPage = CurrentPage; +})(); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +(function () { + var Image = scrivito.createReactClass({ + displayName: 'scrivito.React.Image', + + propTypes: { + src: scrivito.PropTypes.oneOfRealmType('Obj', 'Binary'), + attribute: React.PropTypes.string + }, + + getDefaultProps: function () { + return { attribute: 'blob' }; + }, + + render: function () { + var url = this._binary().url; + var htmlOptions = _.omit(this.props, 'src', 'attribute'); + + return React.createElement('img', _extends({ src: url }, htmlOptions)); + }, + + _binary: function () { + if (this.props.src instanceof scrivito.Binary) { + return this.props.src; + } + + var schema = this.props.src.constructor._scrivitoPrivateSchema; + var attributeType = schema.attributes[this.props.attribute]; + + if (!attributeType) { + throw new scrivito.ScrivitoError('Component "scrivito.React.Image" received prop "src"' + (' with an instance of "scrivito.Obj" missing attribute "' + this.props.attribute + '".')); + } + + if (attributeType === 'reference') { + var target = this.props.src.get(this.props.attribute); + + if (target) { + return target.get('blob'); + } + } + + if (attributeType === 'binary') { + return this.props.src.get(this.props.attribute); + } + + throw new scrivito.ScrivitoError('Component "scrivito.React.Image" received prop "src"' + (' with an instance of "scrivito.Obj", whose attribute "' + this.props.attribute + '"') + (' is of invalid type "' + attributeType + '".') + ' Valid attribute types are "binary" and "reference".'); + } + }); + + scrivito.React.Image = Image; +})(); +var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + +(function () { + var Link = scrivito.createReactClass({ + displayName: 'scrivito.React.Link', + + propTypes: { + to: scrivito.PropTypes.oneOfRealmType('Obj', 'Link') + }, + + render: function () { + var htmlOptions = _.omit(this.props, 'to'); + + return React.createElement( + 'a', + _extends({ href: '#', onClick: this._onClick }, htmlOptions), + this.props.children + ); + }, + + _onClick: function (e) { + e.preventDefault(); + scrivito.navigateTo(this.props.to); + } + }); + + scrivito.React.Link = Link; +})(); +'use strict'; + +(function () { + var state = scrivito.modelState.subState('currentPage'); + + function currentPage() { + var objId = state.get(); + + if (objId) { + try { + return scrivito.currentRealm().Obj.get(objId); + } catch (error) { + if (error instanceof scrivito.NotLoadedError) { + error.load(); + return null; + } + + throw error; + } + } + + return null; + } + + function navigateTo(target) { + if (!target) { + throw new scrivito.ArgumentError('Missing target.'); + } + + if (target instanceof scrivito.currentRealm().Obj) { + if (target.isBinary()) { + scrivito.changeLocation(target.get('blob').url); + } else { + state.set(target.id); + } + + return; + } + + if (target instanceof scrivito.currentRealm().Link) { + if (target.isExternal()) { + scrivito.changeLocation(target.url); + } else { + state.set(target.obj.id); + } + + return; + } + + throw new scrivito.ArgumentError('Target is invalid. Valid targets are instances of "scrivito.Obj" or "scrivito.Link".'); + } + + scrivito.currentPage = currentPage; + scrivito.navigateTo = navigateTo; +})(); +"use strict"; + +(function () { + var currentRealm = undefined; + + function getCurrentRealm() { + return currentRealm || window.scrivito; + } + + function setCurrentRealm(realm) { + currentRealm = realm; + } + + scrivito.currentRealm = getCurrentRealm; + scrivito.setCurrentRealm = setCurrentRealm; +})(); +'use strict'; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +(function () { + function createComponent(componentSpec) { + if (typeof componentSpec === 'function') { + return scrivito.createReactClass({ + render: function render() { + return componentSpec(this.props); + } + }); + } + + return scrivito.createReactClass(componentSpec); + } + + function provideComponent(appClass, componentSpec) { + if (componentSpec.propTypes) { + throw new scrivito.ArgumentError('Custom props is not allowed when providing a component.'); + } + + var componentClass = createComponentForAppClass(appClass, componentSpec); + scrivito.componentRegistry.provideComponentClass(appClass, componentClass); + } + + function createComponentForAppClass(appClass, componentSpec) { + var Obj = scrivito.currentRealm().Obj; + var Widget = scrivito.currentRealm().Widget; + + var propName = undefined; + var propType = undefined; + + if (appClass.prototype instanceof Obj) { + propName = 'page'; + propType = Obj; + } else if (appClass.prototype instanceof Widget) { + propName = 'widget'; + propType = Widget; + } else { + throw new scrivito.ArgumentError(appClass + ' is not a valid application class.'); + } + + var propTypes = _defineProperty({}, propName, React.PropTypes.instanceOf(propType).isRequired); + + if (typeof componentSpec === 'function') { + return scrivito.createReactClass({ + propTypes: propTypes, + + render: function render() { + return componentSpec(this.props[propName]); + } + }); + } + + return scrivito.createReactClass(_.extend(componentSpec, { propTypes: propTypes })); + } + + scrivito.createComponent = createComponent; + scrivito.provideComponent = provideComponent; })();