@webiny/app-headless-cms 5.18.2-beta.0 → 5.19.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/admin/contexts/Cms/index.js +5 -2
  2. package/admin/plugins/apiInformation/index.js +7 -3
  3. package/admin/plugins/definitions/CmsEditorFieldValidatorFileTypePlugin.d.ts +21 -0
  4. package/admin/plugins/definitions/CmsEditorFieldValidatorFileTypePlugin.js +61 -0
  5. package/admin/plugins/definitions/CmsFieldValidatorFileTypePlugin.d.ts +10 -0
  6. package/admin/plugins/definitions/CmsFieldValidatorFileTypePlugin.js +36 -0
  7. package/admin/plugins/fieldRenderers/file/File.d.ts +12 -11
  8. package/admin/plugins/fieldRenderers/file/File.js +19 -15
  9. package/admin/plugins/fieldRenderers/file/fileField.js +17 -12
  10. package/admin/plugins/fieldRenderers/file/fileFields.js +16 -20
  11. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesAutocomplete.js +17 -7
  12. package/admin/plugins/fieldRenderers/ref/components/createEntryUrl.d.ts +5 -0
  13. package/admin/plugins/fieldRenderers/ref/components/createEntryUrl.js +5 -0
  14. package/admin/plugins/fieldRenderers/ref/components/renderItem.d.ts +7 -1
  15. package/admin/plugins/fieldRenderers/ref/components/renderItem.js +6 -2
  16. package/admin/plugins/fieldRenderers/ref/components/useReference.js +2 -2
  17. package/admin/plugins/fieldRenderers/ref/components/useReferences.js +1 -1
  18. package/admin/plugins/fieldValidators/patternPlugins/lowerCaseSpace.d.ts +3 -0
  19. package/admin/plugins/fieldValidators/patternPlugins/lowerCaseSpace.js +9 -0
  20. package/admin/plugins/fieldValidators/patternPlugins/upperCaseSpace.d.ts +3 -0
  21. package/admin/plugins/fieldValidators/patternPlugins/upperCaseSpace.js +9 -0
  22. package/admin/plugins/fields/file.js +15 -1
  23. package/admin/plugins/fields/ref.js +3 -2
  24. package/admin/plugins/transformers/dateTransformer.js +114 -20
  25. package/admin/plugins/validators/patternPlugins/lowerCaseSpace.d.ts +10 -0
  26. package/admin/plugins/validators/patternPlugins/lowerCaseSpace.js +9 -0
  27. package/admin/plugins/validators/patternPlugins/upperCaseSpace.d.ts +10 -0
  28. package/admin/plugins/validators/patternPlugins/upperCaseSpace.js +9 -0
  29. package/admin/views/contentEntries/ContentEntriesList.js +2 -2
  30. package/admin/views/contentEntries/ContentEntry/ContentEntryContext.js +7 -1
  31. package/admin/views/contentEntries/ContentEntry/cache.js +4 -1
  32. package/admin/views/contentEntries/hooks/useContentEntriesList.d.ts +1 -1
  33. package/admin/views/contentEntries/hooks/useContentEntriesList.js +2 -2
  34. package/package.json +17 -16
  35. package/types.d.ts +2 -1
@@ -1,9 +1,12 @@
1
1
  import React from "react";
2
2
  import { useI18N } from "@webiny/app-i18n/hooks/useI18N";
3
3
  import { CircularProgress } from "@webiny/ui/Progress";
4
+ import { config as appConfig } from "@webiny/app/config";
4
5
  export var CmsContext = /*#__PURE__*/React.createContext(null);
5
6
  var apolloClientsCache = {};
6
7
  export function CmsProvider(props) {
8
+ var apiUrl = appConfig.getKey("API_URL", process.env.REACT_APP_API_URL);
9
+
7
10
  var _useI18N = useI18N(),
8
11
  getCurrentLocale = _useI18N.getCurrentLocale;
9
12
 
@@ -15,7 +18,7 @@ export function CmsProvider(props) {
15
18
 
16
19
  if (currentLocale && !apolloClientsCache[currentLocale]) {
17
20
  apolloClientsCache[currentLocale] = props.createApolloClient({
18
- uri: "".concat(process.env.REACT_APP_API_URL, "/cms/manage/").concat(currentLocale)
21
+ uri: "".concat(apiUrl, "/cms/manage/").concat(currentLocale)
19
22
  });
20
23
  }
21
24
 
@@ -23,7 +26,7 @@ export function CmsProvider(props) {
23
26
  getApolloClient: function getApolloClient(locale) {
24
27
  if (!apolloClientsCache[locale]) {
25
28
  apolloClientsCache[locale] = props.createApolloClient({
26
- uri: "".concat(process.env.REACT_APP_API_URL, "/cms/manage/").concat(locale)
29
+ uri: "".concat(apiUrl, "/cms/manage/").concat(locale)
27
30
  });
28
31
  }
29
32
 
@@ -1,12 +1,14 @@
1
1
  var manageQuery = "# Webiny Headless CMS Manage API\n#\n# This API controls all the operations within the Headless CMS module.\n# Use it to manage content, create and modify content models and more.\n# Explore the schema for details.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content model groups:\n{\n listContentModelGroups {\n data {\n name\n icon\n slug\n }\n }\n}\n";
2
2
  var readQuery = "# Webiny Headless CMS Read API\n#\n# This is the API to use in your 3rd party apps to read your content.\n# It returns only content that has been published.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content models:\n{\n listContentModels {\n data {\n name\n modelId\n }\n }\n}\n";
3
3
  var previewQuery = "# Webiny Headless CMS Preview API\n#\n# This is the API to use in your 3rd party apps to preview content.\n# It returns the latest content revision, regardless of whether it was published or not.\n#\n# Note: to use the API outside of the playground, you will need to provide an API key via the Authorization header.\n#\n# Example query - list content models:\n{\n listContentModels {\n data {\n name\n }\n }\n}\n";
4
+ import { config as appConfig } from "@webiny/app/config";
4
5
  var plugins = [{
5
6
  type: "graphql-playground-tab",
6
7
  name: "graphql-playground-tab-manage",
7
8
  tab: function tab(_ref) {
8
9
  var locale = _ref.locale,
9
10
  identity = _ref.identity;
11
+ var apiUrl = appConfig.getKey("API_URL", process.env.REACT_APP_API_URL);
10
12
 
11
13
  if (!identity.getPermission("cms.endpoint.manage")) {
12
14
  return null;
@@ -14,7 +16,7 @@ var plugins = [{
14
16
 
15
17
  return {
16
18
  name: "Headless CMS - Manage API",
17
- endpoint: process.env.REACT_APP_API_URL + "/cms/manage/" + locale,
19
+ endpoint: apiUrl + "/cms/manage/" + locale,
18
20
  headers: {},
19
21
  query: manageQuery
20
22
  };
@@ -25,6 +27,7 @@ var plugins = [{
25
27
  tab: function tab(_ref2) {
26
28
  var locale = _ref2.locale,
27
29
  identity = _ref2.identity;
30
+ var apiUrl = appConfig.getKey("API_URL", process.env.REACT_APP_API_URL);
28
31
 
29
32
  if (!identity.getPermission("cms.endpoint.read")) {
30
33
  return null;
@@ -32,7 +35,7 @@ var plugins = [{
32
35
 
33
36
  return {
34
37
  name: "Headless CMS - Read API",
35
- endpoint: process.env.REACT_APP_API_URL + "/cms/read/" + locale,
38
+ endpoint: apiUrl + "/cms/read/" + locale,
36
39
  headers: {},
37
40
  query: readQuery
38
41
  };
@@ -43,6 +46,7 @@ var plugins = [{
43
46
  tab: function tab(_ref3) {
44
47
  var locale = _ref3.locale,
45
48
  identity = _ref3.identity;
49
+ var apiUrl = appConfig.getKey("API_URL", process.env.REACT_APP_API_URL);
46
50
 
47
51
  if (!identity.getPermission("cms.endpoint.preview")) {
48
52
  return null;
@@ -50,7 +54,7 @@ var plugins = [{
50
54
 
51
55
  return {
52
56
  name: "Headless CMS - Preview API",
53
- endpoint: process.env.REACT_APP_API_URL + "/cms/preview/" + locale,
57
+ endpoint: apiUrl + "/cms/preview/" + locale,
54
58
  headers: {},
55
59
  query: previewQuery
56
60
  };
@@ -0,0 +1,21 @@
1
+ import { Plugin } from "@webiny/plugins/Plugin";
2
+ export interface Config {
3
+ name: string;
4
+ message: string;
5
+ label: string;
6
+ }
7
+ export interface Settings {
8
+ fileType: "all" | "image" | "document" | string;
9
+ }
10
+ export declare class CmsEditorFieldValidatorFileTypePlugin extends Plugin {
11
+ static readonly type: string;
12
+ private readonly config;
13
+ private _settings;
14
+ set settings(settings: Settings);
15
+ get settings(): Settings;
16
+ constructor(config: Config);
17
+ getName(): string;
18
+ getLabel(): string;
19
+ getMessage(): string;
20
+ private setSettings;
21
+ }
@@ -0,0 +1,61 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _createSuper from "@babel/runtime/helpers/createSuper";
6
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
7
+ import { Plugin } from "@webiny/plugins/Plugin";
8
+ export var CmsEditorFieldValidatorFileTypePlugin = /*#__PURE__*/function (_Plugin) {
9
+ _inherits(CmsEditorFieldValidatorFileTypePlugin, _Plugin);
10
+
11
+ var _super = _createSuper(CmsEditorFieldValidatorFileTypePlugin);
12
+
13
+ function CmsEditorFieldValidatorFileTypePlugin(config) {
14
+ var _this;
15
+
16
+ _classCallCheck(this, CmsEditorFieldValidatorFileTypePlugin);
17
+
18
+ _this = _super.call(this);
19
+
20
+ _defineProperty(_assertThisInitialized(_this), "config", void 0);
21
+
22
+ _defineProperty(_assertThisInitialized(_this), "_settings", void 0);
23
+
24
+ _this.config = config;
25
+ return _this;
26
+ }
27
+
28
+ _createClass(CmsEditorFieldValidatorFileTypePlugin, [{
29
+ key: "settings",
30
+ get: function get() {
31
+ return this._settings;
32
+ },
33
+ set: function set(settings) {
34
+ this.setSettings(settings);
35
+ }
36
+ }, {
37
+ key: "getName",
38
+ value: function getName() {
39
+ return this.config.name;
40
+ }
41
+ }, {
42
+ key: "getLabel",
43
+ value: function getLabel() {
44
+ return this.config.label;
45
+ }
46
+ }, {
47
+ key: "getMessage",
48
+ value: function getMessage() {
49
+ return this.config.message;
50
+ }
51
+ }, {
52
+ key: "setSettings",
53
+ value: function setSettings(settings) {
54
+ this._settings = settings;
55
+ }
56
+ }]);
57
+
58
+ return CmsEditorFieldValidatorFileTypePlugin;
59
+ }(Plugin);
60
+
61
+ _defineProperty(CmsEditorFieldValidatorFileTypePlugin, "type", "cms-editor-field-validator-fileType");
@@ -0,0 +1,10 @@
1
+ import { Plugin } from "@webiny/plugins/Plugin";
2
+ export interface Config {
3
+ name: string;
4
+ }
5
+ export declare class CmsFieldValidatorFileTypePlugin extends Plugin {
6
+ static readonly type: string;
7
+ private readonly config;
8
+ constructor(config: Config);
9
+ getName(): string;
10
+ }
@@ -0,0 +1,36 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _createSuper from "@babel/runtime/helpers/createSuper";
6
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
7
+ import { Plugin } from "@webiny/plugins/Plugin";
8
+ export var CmsFieldValidatorFileTypePlugin = /*#__PURE__*/function (_Plugin) {
9
+ _inherits(CmsFieldValidatorFileTypePlugin, _Plugin);
10
+
11
+ var _super = _createSuper(CmsFieldValidatorFileTypePlugin);
12
+
13
+ function CmsFieldValidatorFileTypePlugin(config) {
14
+ var _this;
15
+
16
+ _classCallCheck(this, CmsFieldValidatorFileTypePlugin);
17
+
18
+ _this = _super.call(this);
19
+
20
+ _defineProperty(_assertThisInitialized(_this), "config", void 0);
21
+
22
+ _this.config = config;
23
+ return _this;
24
+ }
25
+
26
+ _createClass(CmsFieldValidatorFileTypePlugin, [{
27
+ key: "getName",
28
+ value: function getName() {
29
+ return this.config.name;
30
+ }
31
+ }]);
32
+
33
+ return CmsFieldValidatorFileTypePlugin;
34
+ }(Plugin);
35
+
36
+ _defineProperty(CmsFieldValidatorFileTypePlugin, "type", "cms-model-field-validator-fileType");
@@ -1,14 +1,15 @@
1
- /// <reference types="react" />
2
- declare function File(props: any): JSX.Element;
3
- declare namespace File {
4
- var defaultProps: {
5
- validation: {
6
- isValid: any;
7
- };
8
- styles: {
9
- width: string;
10
- height: string;
11
- };
1
+ import React from "react";
2
+ export interface Props {
3
+ url: string;
4
+ onRemove: Function;
5
+ placeholder: string;
6
+ styles?: Record<string, any>;
7
+ showFileManager?: Function;
8
+ validation?: {
9
+ isValid?: boolean;
10
+ message?: string;
12
11
  };
12
+ description?: string;
13
13
  }
14
+ declare const File: React.FunctionComponent<Props>;
14
15
  export default File;
@@ -3,6 +3,7 @@ import { Image } from "@webiny/app/components";
3
3
  import * as Ui from "@webiny/ui/ImageUpload";
4
4
  import { createRenderImagePreview, imageExtensions } from "./utils";
5
5
  import fileIcon from "../../fields/icons/round_insert_drive_file-24px.svg";
6
+ import { FormElementMessage } from "@webiny/ui/FormElementMessage";
6
7
  var imagePreviewProps = {
7
8
  transform: {
8
9
  width: 300
@@ -13,13 +14,23 @@ var imagePreviewProps = {
13
14
  objectFit: "cover"
14
15
  }
15
16
  };
17
+ var defaultStyles = {
18
+ width: "100%",
19
+ height: "auto"
20
+ };
21
+ var defaultValidation = {
22
+ isValid: null,
23
+ message: null
24
+ };
16
25
 
17
- function File(props) {
26
+ var File = function File(props) {
18
27
  var url = props.url,
19
28
  onRemove = props.onRemove,
20
29
  placeholder = props.placeholder,
21
- styles = props.styles,
22
- showFileManager = props.showFileManager;
30
+ showFileManager = props.showFileManager,
31
+ description = props.description;
32
+ var styles = props.styles || defaultStyles;
33
+ var validation = props.validation || defaultValidation;
23
34
  var isImage = useCallback(function (url) {
24
35
  return imageExtensions.some(function (extension) {
25
36
  return url.includes(extension);
@@ -48,7 +59,7 @@ function File(props) {
48
59
  return defaultRenderImagePreview;
49
60
  };
50
61
 
51
- return /*#__PURE__*/React.createElement(Ui.Image, {
62
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Ui.Image, {
52
63
  renderImagePreview: renderImagePreview(url),
53
64
  style: styles,
54
65
  value: url ? {
@@ -60,16 +71,9 @@ function File(props) {
60
71
  containerStyle: {
61
72
  height: "auto"
62
73
  }
63
- });
64
- }
65
-
66
- File.defaultProps = {
67
- validation: {
68
- isValid: null
69
- },
70
- styles: {
71
- width: "100%",
72
- height: "auto"
73
- }
74
+ }), validation.isValid === false && /*#__PURE__*/React.createElement(FormElementMessage, {
75
+ error: true
76
+ }, validation.message || "Invalid value."), validation.isValid !== false && description && /*#__PURE__*/React.createElement(FormElementMessage, null, description));
74
77
  };
78
+
75
79
  export default File;
@@ -1,6 +1,6 @@
1
1
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
2
 
3
- var _templateObject, _templateObject2, _templateObject3;
3
+ var _templateObject, _templateObject2;
4
4
 
5
5
  import React from "react";
6
6
  import { i18n } from "@webiny/app/i18n";
@@ -25,32 +25,37 @@ var plugin = {
25
25
  getBind = _ref2.getBind,
26
26
  Label = _ref2.Label;
27
27
  var Bind = getBind();
28
+ var imagesOnly = field.settings && field.settings.imagesOnly;
28
29
  return /*#__PURE__*/React.createElement(Grid, null, /*#__PURE__*/React.createElement(Cell, {
29
30
  span: 12
30
- }, /*#__PURE__*/React.createElement(Label, null, field.label), /*#__PURE__*/React.createElement(Bind, null, function (_ref3) {
31
- var value = _ref3.value,
32
- onChange = _ref3.onChange;
31
+ }, /*#__PURE__*/React.createElement(Label, null, field.label), /*#__PURE__*/React.createElement(Bind, null, function (bind) {
32
+ var value = bind.value,
33
+ onChange = bind.onChange;
33
34
  return /*#__PURE__*/React.createElement(FileManager, {
34
- multiple: false
35
- }, function (_ref4) {
36
- var showFileManager = _ref4.showFileManager;
35
+ multiple: false,
36
+ images: imagesOnly
37
+ }, function (_ref3) {
38
+ var showFileManager = _ref3.showFileManager;
37
39
 
38
40
  var selectFile = function selectFile() {
39
41
  showFileManager(function (newFile) {
40
- if (newFile !== null) {
41
- onChange(newFile.src);
42
+ if (newFile === null) {
43
+ return;
42
44
  }
45
+
46
+ onChange(newFile.src);
43
47
  });
44
48
  };
45
49
 
46
- return /*#__PURE__*/React.createElement(File, {
50
+ return /*#__PURE__*/React.createElement(File, Object.assign({}, bind, {
47
51
  url: value,
48
52
  onRemove: function onRemove() {
49
53
  return onChange(null);
50
54
  },
51
55
  showFileManager: selectFile,
52
- placeholder: t(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["Select a file\""])))
53
- });
56
+ placeholder: field.placeholderText,
57
+ description: field.helpText
58
+ }));
54
59
  });
55
60
  }), field.helpText && /*#__PURE__*/React.createElement(FormElementMessage, null, field.helpText)));
56
61
  }
@@ -11,7 +11,6 @@ import { imageWrapperStyles } from "./utils";
11
11
  import { FileManager } from "@webiny/app-admin/components";
12
12
  import styled from "@emotion/styled";
13
13
  import File from "./File";
14
- import { FormElementMessage } from "@webiny/ui/FormElementMessage";
15
14
  var t = i18n.ns("app-headless-cms/admin/fields/file");
16
15
  var FileUploadWrapper = /*#__PURE__*/styled("div", {
17
16
  target: "eq80mh0",
@@ -32,16 +31,17 @@ function FieldRenderer(_ref) {
32
31
  Label = _ref.Label,
33
32
  field = _ref.field;
34
33
  var Bind = getBind();
35
- return /*#__PURE__*/React.createElement(Bind, null, function (_ref2) {
36
- var value = _ref2.value,
37
- onChange = _ref2.onChange,
38
- validation = _ref2.validation;
34
+ var imagesOnly = field.settings && field.settings.imagesOnly;
35
+ return /*#__PURE__*/React.createElement(Bind, null, function (bind) {
36
+ var value = bind.value,
37
+ onChange = bind.onChange;
39
38
  return /*#__PURE__*/React.createElement(FileUploadWrapper, {
40
39
  className: imageWrapperStyles
41
40
  }, /*#__PURE__*/React.createElement(FileManager, {
42
- multiple: true
43
- }, function (_ref3) {
44
- var showFileManager = _ref3.showFileManager;
41
+ multiple: true,
42
+ images: imagesOnly
43
+ }, function (_ref2) {
44
+ var showFileManager = _ref2.showFileManager;
45
45
 
46
46
  var selectFiles = function selectFiles() {
47
47
  var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1;
@@ -80,16 +80,12 @@ function FieldRenderer(_ref) {
80
80
  }));
81
81
  }), /*#__PURE__*/React.createElement(Cell, {
82
82
  span: 3
83
- }, /*#__PURE__*/React.createElement(File, {
83
+ }, /*#__PURE__*/React.createElement(File, Object.assign({}, bind, {
84
84
  showFileManager: function showFileManager() {
85
85
  return selectFiles();
86
86
  },
87
87
  placeholder: t(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["Select a file\""])))
88
- })), validation.isValid === false && /*#__PURE__*/React.createElement(Cell, {
89
- span: 12
90
- }, /*#__PURE__*/React.createElement(FormElementMessage, {
91
- error: true
92
- }, validation.message)));
88
+ }))));
93
89
  }));
94
90
  });
95
91
  }
@@ -110,14 +106,14 @@ var plugin = {
110
106
  rendererName: "file-inputs",
111
107
  name: t(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["File Inputs"]))),
112
108
  description: t(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["Enables selecting multiple files via File Manager."]))),
113
- canUse: function canUse(_ref4) {
114
- var field = _ref4.field;
109
+ canUse: function canUse(_ref3) {
110
+ var field = _ref3.field;
115
111
  return field.type === "file" && field.multipleValues;
116
112
  },
117
- render: function render(_ref5) {
118
- var field = _ref5.field,
119
- getBind = _ref5.getBind,
120
- Label = _ref5.Label;
113
+ render: function render(_ref4) {
114
+ var field = _ref4.field,
115
+ getBind = _ref4.getBind,
116
+ Label = _ref4.Label;
121
117
  return /*#__PURE__*/React.createElement(FieldRenderer, {
122
118
  field: field,
123
119
  getBind: getBind,
@@ -1,6 +1,6 @@
1
1
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
2
 
3
- var _templateObject, _templateObject2;
3
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
4
4
 
5
5
  import React from "react";
6
6
  import debounce from "lodash/debounce";
@@ -9,8 +9,10 @@ import { i18n } from "@webiny/app/i18n";
9
9
  import { Link } from "@webiny/react-router";
10
10
  import { useReference } from "./useReference";
11
11
  import { renderItem } from "./renderItem";
12
+ import { createEntryUrl } from "./createEntryUrl";
12
13
  var t = i18n.ns("app-headless-cms/admin/fields/ref");
13
- var label = t(_templateObject || (_templateObject = _taggedTemplateLiteral(["Selected content entry is not published. Make sure to {publishItLink} before publishing the main content entry."])));
14
+ var unpublishedLabel = t(_templateObject || (_templateObject = _taggedTemplateLiteral(["Selected content entry is not published. Make sure to {publishItLink} before publishing the main content entry."])));
15
+ var publishedLabel = t(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["Selected content entry is published. You can view it {here}."])));
14
16
 
15
17
  function ContentEntriesAutocomplete(_ref) {
16
18
  var bind = _ref.bind,
@@ -26,14 +28,22 @@ function ContentEntriesAutocomplete(_ref) {
26
28
  loading = _useReference.loading,
27
29
  onChange = _useReference.onChange;
28
30
 
29
- var unpublishedEntryInfo = null;
31
+ var entryInfo = null;
30
32
 
31
33
  if (value && !value.published) {
32
- var link = "/cms/content-entries/".concat(value.modelId, "?id=").concat(encodeURIComponent(value.id));
33
- unpublishedEntryInfo = label({
34
+ var link = createEntryUrl(value);
35
+ entryInfo = unpublishedLabel({
34
36
  publishItLink: /*#__PURE__*/React.createElement(Link, {
35
37
  to: link
36
- }, t(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["publish it"]))))
38
+ }, t(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["publish it"]))))
39
+ });
40
+ } else if (value) {
41
+ var _link = createEntryUrl(value);
42
+
43
+ entryInfo = publishedLabel({
44
+ here: /*#__PURE__*/React.createElement(Link, {
45
+ to: _link
46
+ }, t(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["here"]))))
37
47
  });
38
48
  }
39
49
 
@@ -44,7 +54,7 @@ function ContentEntriesAutocomplete(_ref) {
44
54
  value: value ? value.id : null,
45
55
  options: options,
46
56
  label: field.label,
47
- description: /*#__PURE__*/React.createElement(React.Fragment, null, field.helpText, unpublishedEntryInfo),
57
+ description: /*#__PURE__*/React.createElement(React.Fragment, null, field.helpText, entryInfo),
48
58
  onInput: debounce(function (search) {
49
59
  return setSearch(search);
50
60
  }, 250)
@@ -0,0 +1,5 @@
1
+ export interface Params {
2
+ id: string;
3
+ modelId: string;
4
+ }
5
+ export declare const createEntryUrl: ({ modelId, id }: Params) => string;
@@ -0,0 +1,5 @@
1
+ export var createEntryUrl = function createEntryUrl(_ref) {
2
+ var modelId = _ref.modelId,
3
+ id = _ref.id;
4
+ return "/cms/content-entries/".concat(modelId, "?id=").concat(encodeURIComponent(id));
5
+ };
@@ -1,2 +1,8 @@
1
1
  /// <reference types="react" />
2
- export declare const renderItem: (item: any) => JSX.Element;
2
+ export interface Props {
3
+ name: string;
4
+ modelName: string;
5
+ modelId: string;
6
+ id: string;
7
+ }
8
+ export declare const renderItem: (props: Props) => JSX.Element;
@@ -1,14 +1,18 @@
1
1
  import React from "react";
2
2
  import styled from "@emotion/styled";
3
3
  import { Typography } from "@webiny/ui/Typography";
4
+ import { createEntryUrl } from "./createEntryUrl";
5
+ import { Link } from "@webiny/react-router";
4
6
  var ModelId = /*#__PURE__*/styled("span", {
5
7
  target: "ejkg0kv0",
6
8
  label: "ModelId"
7
9
  })({
8
10
  color: "var(--mdc-theme-text-secondary-on-background) !important"
9
11
  });
10
- export var renderItem = function renderItem(item) {
12
+ export var renderItem = function renderItem(props) {
11
13
  return /*#__PURE__*/React.createElement(Typography, {
12
14
  use: "body2"
13
- }, item.name, /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(ModelId, null, "Model: ", item.modelName));
15
+ }, /*#__PURE__*/React.createElement(Link, {
16
+ to: createEntryUrl(props)
17
+ }, props.name), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(ModelId, null, "Model: ", props.modelName));
14
18
  };
@@ -176,7 +176,7 @@ export var useReference = function useReference(_ref) {
176
176
  variables: {
177
177
  entry: {
178
178
  modelId: value.modelId,
179
- entryId: value.entryId
179
+ id: value.id
180
180
  }
181
181
  }
182
182
  }).then(function (res) {
@@ -205,7 +205,7 @@ export var useReference = function useReference(_ref) {
205
205
  });
206
206
  return bind.onChange({
207
207
  modelId: entry.modelId,
208
- entryId: entry.id
208
+ id: entry.id
209
209
  });
210
210
  }
211
211
 
@@ -156,7 +156,7 @@ export var useReferences = function useReferences(_ref) {
156
156
  bind.onChange(values.map(function (item) {
157
157
  return {
158
158
  modelId: item.modelId,
159
- entryId: item.id
159
+ id: item.id
160
160
  };
161
161
  }));
162
162
  }, []); // Format options for the Autocomplete component.
@@ -0,0 +1,3 @@
1
+ import { CmsEditorFieldValidatorPatternPlugin } from "../../../../types";
2
+ declare const _default: CmsEditorFieldValidatorPatternPlugin;
3
+ export default _default;
@@ -0,0 +1,9 @@
1
+ export default {
2
+ type: "cms-editor-field-validator-pattern",
3
+ name: "cms-editor-field-validator-pattern-lower-case-space",
4
+ pattern: {
5
+ message: "Only lower case characters and space are allowed.",
6
+ name: "lowerCaseSpace",
7
+ label: "Lower case + space"
8
+ }
9
+ };
@@ -0,0 +1,3 @@
1
+ import { CmsEditorFieldValidatorPatternPlugin } from "../../../../types";
2
+ declare const _default: CmsEditorFieldValidatorPatternPlugin;
3
+ export default _default;
@@ -0,0 +1,9 @@
1
+ export default {
2
+ type: "cms-editor-field-validator-pattern",
3
+ name: "cms-editor-field-validator-pattern-upper-case-space",
4
+ pattern: {
5
+ message: "Only upper case characters and space are allowed.",
6
+ name: "upperCaseSpace",
7
+ label: "Upper case + space"
8
+ }
9
+ };
@@ -1,10 +1,12 @@
1
1
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
2
 
3
- var _templateObject, _templateObject2, _templateObject3;
3
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5;
4
4
 
5
5
  import React from "react";
6
6
  import { ReactComponent as FileIcon } from "@svgr/webpack!./icons/round_insert_drive_file-24px.svg";
7
7
  import { i18n } from "@webiny/app/i18n";
8
+ import { Cell, Grid } from "@webiny/ui/Grid";
9
+ import { Radio } from "@webiny/ui/Radio";
8
10
  var t = i18n.ns("app-headless-cms/admin/fields");
9
11
  var plugin = {
10
12
  type: "cms-editor-field-type",
@@ -15,6 +17,7 @@ var plugin = {
15
17
  description: t(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["Images, videos and other files."]))),
16
18
  icon: /*#__PURE__*/React.createElement(FileIcon, null),
17
19
  validators: ["required"],
20
+ listValidators: ["minLength", "maxLength"],
18
21
  allowMultipleValues: true,
19
22
  allowPredefinedValues: false,
20
23
  multipleValuesLabel: t(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["Use as a list of files or an image gallery"]))),
@@ -26,6 +29,17 @@ var plugin = {
26
29
  name: ""
27
30
  }
28
31
  };
32
+ },
33
+ renderSettings: function renderSettings(_ref) {
34
+ var Bind = _ref.form.Bind;
35
+ return /*#__PURE__*/React.createElement(Grid, null, /*#__PURE__*/React.createElement(Cell, {
36
+ span: 12
37
+ }, /*#__PURE__*/React.createElement(Bind, {
38
+ name: "settings.imagesOnly"
39
+ }, /*#__PURE__*/React.createElement(Radio, {
40
+ label: t(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["Images only"]))),
41
+ description: t(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["Allow only images to be selected"])))
42
+ }))));
29
43
  }
30
44
  }
31
45
  };
@@ -21,7 +21,8 @@ var plugin = {
21
21
  name: "cms-editor-field-type-ref",
22
22
  field: {
23
23
  type: "ref",
24
- validators: [],
24
+ validators: ["required"],
25
+ listValidators: ["minLength", "maxLength"],
25
26
  label: t(_templateObject || (_templateObject = _taggedTemplateLiteral(["Reference"]))),
26
27
  description: t(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["Reference existing content entries. For example, a book can reference one or more authors."]))),
27
28
  icon: /*#__PURE__*/React.createElement(RefIcon, null),
@@ -136,7 +137,7 @@ var plugin = {
136
137
  graphql: {
137
138
  queryField:
138
139
  /* GraphQL */
139
- "\n {\n modelId\n entryId\n }\n "
140
+ "\n {\n modelId\n id\n }\n "
140
141
  }
141
142
  }
142
143
  };
@@ -1,14 +1,117 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  import WebinyError from "@webiny/error";
2
3
 
3
- var transformDate = function transformDate(value, type) {
4
- if (type === "date") {
5
- return value.substr(0, 10);
4
+ var throwTransformError = function throwTransformError(params) {
5
+ var type = params.type,
6
+ value = params.value,
7
+ error = params.ex;
8
+ throw new WebinyError("Could not transform value to a date.", "TRANSFORM_ERROR", {
9
+ error: error,
10
+ type: type,
11
+ value: value
12
+ });
13
+ };
14
+
15
+ var dateOnly = function dateOnly(value) {
16
+ try {
17
+ var date = new Date(value).toISOString();
18
+ return date.substr(0, 10);
19
+ } catch (ex) {
20
+ throwTransformError({
21
+ ex: ex,
22
+ value: value,
23
+ type: "date"
24
+ });
6
25
  }
26
+ };
7
27
 
8
- return value;
28
+ var extractTimeZone = function extractTimeZone(value) {
29
+ var result;
30
+
31
+ if (value.includes("+")) {
32
+ result = value.split("+");
33
+ } else {
34
+ result = value.split("-");
35
+ }
36
+
37
+ if (!result || result.length !== 2) {
38
+ throw new WebinyError("Could not determine time and timezone out of given value.", "TIME_ZONE_ERROR", {
39
+ value: value
40
+ });
41
+ }
42
+
43
+ return result;
9
44
  };
10
45
 
11
- var excludeTypesTransformation = ["time", "dateTimeWithTimezone"];
46
+ var extractTime = function extractTime(value) {
47
+ if (value.includes(":") === false) {
48
+ throw new WebinyError("Time value is missing : separators.", "TIME_ERROR", {
49
+ value: value
50
+ });
51
+ }
52
+
53
+ var result = value.split(":");
54
+
55
+ if (result.length === 3) {
56
+ return value;
57
+ } else if (result.length === 2) {
58
+ return "".concat(value, ":00");
59
+ }
60
+ };
61
+
62
+ var dateTimeWithTimezone = function dateTimeWithTimezone(value) {
63
+ if (value.includes("T") === false) {
64
+ return value;
65
+ }
66
+
67
+ var _value$split = value.split("T"),
68
+ _value$split2 = _slicedToArray(_value$split, 2),
69
+ initialDate = _value$split2[0],
70
+ initialTimeZone = _value$split2[1];
71
+
72
+ var date;
73
+
74
+ try {
75
+ var dateObj = new Date(initialDate);
76
+ date = dateObj.toISOString().substr(0, 10);
77
+ } catch (ex) {
78
+ throw new WebinyError("Could not transform received date into Date object.", "DATE_TRANSFORM_ERROR", {
79
+ value: value,
80
+ date: initialDate,
81
+ time: initialTimeZone
82
+ });
83
+ }
84
+
85
+ var _extractTimeZone = extractTimeZone(initialTimeZone),
86
+ _extractTimeZone2 = _slicedToArray(_extractTimeZone, 1),
87
+ initialTime = _extractTimeZone2[0];
88
+
89
+ var time = extractTime(initialTime);
90
+ return value.replace(initialDate, date).replace(initialTime, time);
91
+ };
92
+
93
+ var dateTimeWithoutTimezone = function dateTimeWithoutTimezone(value) {
94
+ if (value.includes(" ") === false) {
95
+ return value;
96
+ }
97
+
98
+ try {
99
+ return new Date("".concat(value.replace(" ", "T"), ".000Z")).toISOString();
100
+ } catch (ex) {
101
+ throwTransformError({
102
+ ex: ex,
103
+ value: value,
104
+ type: "dateTimeWithoutTimezone"
105
+ });
106
+ }
107
+ };
108
+
109
+ var transformers = {
110
+ time: null,
111
+ date: dateOnly,
112
+ dateTimeWithoutTimezone: dateTimeWithoutTimezone,
113
+ dateTimeWithTimezone: dateTimeWithTimezone
114
+ };
12
115
  export default (function () {
13
116
  return {
14
117
  type: "cms-field-value-transformer",
@@ -21,24 +124,15 @@ export default (function () {
21
124
  if (!value) {
22
125
  console.log("Field \"".concat(field.fieldId, "\" has no value."));
23
126
  return null;
24
- } else if (excludeTypesTransformation.includes(type) === true) {
25
- return value;
26
- } else if (type === "dateTimeWithoutTimezone" && value.includes(" ")) {
27
- /**
28
- * Need to replace space and add .000Z to datetime value because it can look like: 2021-02-02 16:34:56
29
- */
30
- value = "".concat(value.replace(" ", "T"), ".000Z");
31
127
  }
32
128
 
33
- try {
34
- var result = new Date(value).toISOString();
35
- return transformDate(result, type);
36
- } catch (ex) {
37
- throw new WebinyError("Could not transform \"".concat(value, "\" to a date."), "TRANSFORM_ERROR", {
38
- message: ex.message,
39
- code: ex.code
40
- });
129
+ var transform = transformers[type];
130
+
131
+ if (!transform) {
132
+ return value;
41
133
  }
134
+
135
+ return transform(value);
42
136
  }
43
137
  };
44
138
  });
@@ -0,0 +1,10 @@
1
+ declare const _default: {
2
+ type: string;
3
+ name: string;
4
+ pattern: {
5
+ name: string;
6
+ regex: string;
7
+ flags: string;
8
+ };
9
+ };
10
+ export default _default;
@@ -0,0 +1,9 @@
1
+ export default {
2
+ type: "cms-model-field-validator-pattern",
3
+ name: "cms-model-field-validator-pattern-lower-case-space",
4
+ pattern: {
5
+ name: "lowerCaseSpace",
6
+ regex: "^([a-z\\s]+)$",
7
+ flags: ""
8
+ }
9
+ };
@@ -0,0 +1,10 @@
1
+ declare const _default: {
2
+ type: string;
3
+ name: string;
4
+ pattern: {
5
+ name: string;
6
+ regex: string;
7
+ flags: string;
8
+ };
9
+ };
10
+ export default _default;
@@ -0,0 +1,9 @@
1
+ export default {
2
+ type: "cms-model-field-validator-pattern",
3
+ name: "cms-model-field-validator-pattern-upper-case-space",
4
+ pattern: {
5
+ name: "upperCaseSpace",
6
+ regex: "^([A-Z\\s]+)$",
7
+ flags: ""
8
+ }
9
+ };
@@ -55,7 +55,7 @@ var listItemMinHeight = /*#__PURE__*/css({
55
55
  var ContentEntriesList = function ContentEntriesList() {
56
56
  var _useContentEntriesLis = useContentEntriesList(),
57
57
  contentModel = _useContentEntriesLis.contentModel,
58
- entryId = _useContentEntriesLis.entryId,
58
+ id = _useContentEntriesLis.id,
59
59
  loading = _useContentEntriesLis.loading,
60
60
  canCreate = _useContentEntriesLis.canCreate,
61
61
  onCreate = _useContentEntriesLis.onCreate,
@@ -159,7 +159,7 @@ var ContentEntriesList = function ContentEntriesList() {
159
159
  return /*#__PURE__*/React.createElement(UIList.ListItem, {
160
160
  key: item.id,
161
161
  className: listItemMinHeight,
162
- selected: item.id === entryId
162
+ selected: item.id === id
163
163
  }, /*#__PURE__*/React.createElement(UIList.ListItemText, {
164
164
  onClick: editEntry(item)
165
165
  }, item.meta.title || "Untitled", /*#__PURE__*/React.createElement(UIList.ListItemTextSecondary, null, t(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["Last modified: {time}."])))({
@@ -7,6 +7,7 @@ import { useSnackbar } from "@webiny/app-admin/hooks/useSnackbar";
7
7
  import * as GQL from "../../../graphql/contentEntries";
8
8
  import { useQuery } from "../../../hooks";
9
9
  import { useContentEntries } from "../hooks/useContentEntries";
10
+ import { parseIdentifier } from "@webiny/utils";
10
11
  export var Context = /*#__PURE__*/React.createContext(null);
11
12
  export var Provider = function Provider(_ref) {
12
13
  var children = _ref.children;
@@ -37,7 +38,12 @@ export var Provider = function Provider(_ref) {
37
38
  var query = new URLSearchParams(location.search);
38
39
  var contentId = query.get("id");
39
40
  var revisionId = contentId ? decodeURIComponent(contentId) : null;
40
- var entryId = revisionId ? revisionId.split("#")[0] : null;
41
+ var entryId = null;
42
+
43
+ if (revisionId) {
44
+ var result = parseIdentifier(revisionId);
45
+ entryId = result ? result.id : null;
46
+ }
41
47
 
42
48
  var _useMemo = useMemo(function () {
43
49
  return {
@@ -4,6 +4,7 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  import dotProp from "dot-prop-immutable";
5
5
  import orderBy from "lodash/orderBy";
6
6
  import * as GQL from "../../../graphql/contentEntries";
7
+ import { parseIdentifier } from "@webiny/utils";
7
8
  /*
8
9
  * We need to preserve the order of entries with new entry addition
9
10
  * because we're not re-fetching the list but updating it directly inside cache.
@@ -89,7 +90,9 @@ export var removeEntryFromListCache = function removeEntryFromListCache(model, c
89
90
  return;
90
91
  }
91
92
 
92
- var entryId = revision.id.split("#")[0];
93
+ var _parseIdentifier = parseIdentifier(revision.id),
94
+ entryId = _parseIdentifier.id;
95
+
93
96
  var index = content.data.findIndex(function (item) {
94
97
  return item.id.startsWith(entryId);
95
98
  });
@@ -8,7 +8,7 @@ export declare function useContentEntriesList(): {
8
8
  label: string;
9
9
  value: string;
10
10
  }[];
11
- entryId: string;
11
+ id: string;
12
12
  loading: boolean;
13
13
  data: any;
14
14
  loadMore: () => void;
@@ -35,7 +35,7 @@ export function useContentEntriesList() {
35
35
  var baseUrl = "/cms/content-entries/".concat(contentModel.modelId); // Get entry ID and search query (if any)
36
36
 
37
37
  var query = new URLSearchParams(location.search);
38
- var entryId = query.get("id");
38
+ var id = query.get("id");
39
39
  var searchQuery = query.get("search");
40
40
  var updateSearch = useCallback(debounce(function (_ref) {
41
41
  var filter = _ref.filter,
@@ -138,7 +138,7 @@ export function useContentEntriesList() {
138
138
  listQueryVariables: listQueryVariables,
139
139
  setListQueryVariables: setListQueryVariables,
140
140
  sorters: sorters,
141
- entryId: entryId,
141
+ id: id,
142
142
  loading: loading,
143
143
  data: filterByStatus(get(data, "content.data", []), listQueryVariables.status),
144
144
  loadMore: loadMore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-headless-cms",
3
- "version": "5.18.2-beta.0",
3
+ "version": "5.19.0-beta.0",
4
4
  "main": "index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,18 +24,19 @@
24
24
  "@fortawesome/react-fontawesome": "0.1.16",
25
25
  "@svgr/webpack": "4.3.3",
26
26
  "@types/react": "16.14.2",
27
- "@webiny/app": "5.18.2-beta.0",
28
- "@webiny/app-admin": "5.18.2-beta.0",
29
- "@webiny/app-graphql-playground": "5.18.2-beta.0",
30
- "@webiny/app-i18n": "5.18.2-beta.0",
31
- "@webiny/app-plugin-admin-welcome-screen": "5.18.2-beta.0",
32
- "@webiny/app-security": "5.18.2-beta.0",
33
- "@webiny/error": "5.18.2-beta.0",
34
- "@webiny/form": "5.18.2-beta.0",
35
- "@webiny/plugins": "5.18.2-beta.0",
36
- "@webiny/react-router": "5.18.2-beta.0",
37
- "@webiny/ui": "5.18.2-beta.0",
38
- "@webiny/validation": "5.18.2-beta.0",
27
+ "@webiny/app": "5.19.0-beta.0",
28
+ "@webiny/app-admin": "5.19.0-beta.0",
29
+ "@webiny/app-graphql-playground": "5.19.0-beta.0",
30
+ "@webiny/app-i18n": "5.19.0-beta.0",
31
+ "@webiny/app-plugin-admin-welcome-screen": "5.19.0-beta.0",
32
+ "@webiny/app-security": "5.19.0-beta.0",
33
+ "@webiny/error": "5.19.0-beta.0",
34
+ "@webiny/form": "5.19.0-beta.0",
35
+ "@webiny/plugins": "5.19.0-beta.0",
36
+ "@webiny/react-router": "5.19.0-beta.0",
37
+ "@webiny/ui": "5.19.0-beta.0",
38
+ "@webiny/utils": "5.19.0-beta.0",
39
+ "@webiny/validation": "5.19.0-beta.0",
39
40
  "apollo-cache": "1.3.5",
40
41
  "apollo-client": "2.6.10",
41
42
  "apollo-link": "1.2.14",
@@ -66,8 +67,8 @@
66
67
  "@babel/preset-env": "^7.5.5",
67
68
  "@babel/preset-react": "^7.0.0",
68
69
  "@babel/preset-typescript": "^7.8.3",
69
- "@webiny/cli": "^5.18.2-beta.0",
70
- "@webiny/project-utils": "^5.18.2-beta.0",
70
+ "@webiny/cli": "^5.19.0-beta.0",
71
+ "@webiny/project-utils": "^5.19.0-beta.0",
71
72
  "babel-plugin-emotion": "^9.2.8",
72
73
  "babel-plugin-lodash": "^3.3.4",
73
74
  "babel-plugin-module-resolver": "^4.1.0",
@@ -105,5 +106,5 @@
105
106
  ]
106
107
  }
107
108
  },
108
- "gitHead": "11c2c5bdeb0cdc0262e75bd4cfe156a468abcd6c"
109
+ "gitHead": "6c834e0b356e9099800f4094f2023b05b951d8ea"
109
110
  }
package/types.d.ts CHANGED
@@ -316,6 +316,7 @@ export interface CmsEditorFieldValidatorPlugin extends Plugin {
316
316
  label: string;
317
317
  description: string;
318
318
  defaultMessage: string;
319
+ defaultSettings?: Record<string, any>;
319
320
  renderSettings?: (props: {
320
321
  field: CmsEditorField;
321
322
  Bind: BindComponent;
@@ -356,7 +357,7 @@ export interface CmsModelFieldValidatorPlugin extends Plugin {
356
357
  type: "cms-model-field-validator";
357
358
  validator: {
358
359
  name: string;
359
- validate: (value: any, validator: CmsFieldValidator) => Promise<any>;
360
+ validate: (value: any, validator: CmsFieldValidator | any) => Promise<any>;
360
361
  };
361
362
  }
362
363
  /**