diff --git a/.flowconfig b/.flowconfig index ff3af704ab8..5c0b0fc92d9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -24,7 +24,7 @@ module.name_mapper='^webiny-\(.*\)/types$' -> '/packages/webiny-\1 module.name_mapper='^webiny-api/?\(.*\)$' -> '/packages/webiny-api/src/\1' module.name_mapper='^webiny-api-cms/?\(.*\)$' -> '/packages/webiny-api-cms/src/\1' module.name_mapper='^webiny-app/?\(.*\)$' -> '/packages/webiny-app/src/\1' -module.name_mapper='^webiny-app-admin/?\(.*\)$' -> '/packages/webiny-app-admin/src/\1' +module.name_mapper='^webiny-admin/?\(.*\)$' -> '/packages/webiny-admin/src/\1' module.name_mapper='^webiny-app-cms/?\(.*\)$' -> '/packages/webiny-app-cms/src/\1' module.name_mapper='^webiny-cms-editor/?\(.*\)$' -> '/packages/webiny-cms-editor/src/\1' module.name_mapper='^webiny-ui/?\(.*\)$' -> '/packages/webiny-ui/src/\1' @@ -39,18 +39,25 @@ module.name_mapper='^webiny-file-storage/?\(.*\)$' -> '/packages/w module.name_mapper='^webiny-form/?\(.*\)$' -> '/packages/webiny-form/src/\1' module.name_mapper='^webiny-i18n-react/?\(.*\)$' -> '/packages/webiny-i18n-react/src/\1' module.name_mapper='^webiny-i18n/?\(.*\)$' -> '/packages/webiny-i18n/src/\1' +module.name_mapper='^webiny-install/?\(.*\)$' -> '/packages/webiny-install/src/\1' module.name_mapper='^webiny-jimp/?\(.*\)$' -> '/packages/webiny-jimp/src/\1' module.name_mapper='^webiny-load-assets/?\(.*\)$' -> '/packages/webiny-load-assets/src/\1' module.name_mapper='^webiny-model/?\(.*\)$' -> '/packages/webiny-model/src/\1' module.name_mapper='^webiny-mysql-connection/?\(.*\)$' -> '/packages/webiny-mysql-connection/src/\1' module.name_mapper='^webiny-plugins/?\(.*\)$' -> '/packages/webiny-plugins/src/\1' module.name_mapper='^webiny-react-router/?\(.*\)$' -> '/packages/webiny-react-router/src/\1' +module.name_mapper='^webiny-api-security/?\(.*\)$' -> '/packages/webiny-api-security/src/\1' +module.name_mapper='^webiny-app-security/?\(.*\)$' -> '/packages/webiny-app-security/src/\1' module.name_mapper='^webiny-service-manager/?\(.*\)$' -> '/packages/webiny-service-manager/src/\1' module.name_mapper='^webiny-sql-table-mysql/?\(.*\)$' -> '/packages/webiny-sql-table-mysql/src/\1' module.name_mapper='^webiny-sql-table-sync/?\(.*\)$' -> '/packages/webiny-sql-table-sync/src/\1' module.name_mapper='^webiny-sql-table/?\(.*\)$' -> '/packages/webiny-sql-table/src/\1' module.name_mapper='^webiny-storybook-utils/?\(.*\)$' -> '/packages/webiny-storybook-utils/src/\1' module.name_mapper='^webiny-validation/?\(.*\)$' -> '/packages/webiny-validation/src/\1' +module.name_mapper='^webiny-integration-cookie-policy/?\(.*\)$' -> '/addons/webiny-integration-cookie-policy/src/\1' +module.name_mapper='^webiny-integration-google-tag-manager/?\(.*\)$' -> '/addons/webiny-integration-google-tag-manager/src/\1' +module.name_mapper='^webiny-integration-mailchimp/?\(.*\)$' -> '/addons/webiny-integration-mailchimp/src/\1' +module.name_mapper='^webiny-integration-typeform/?\(.*\)$' -> '/addons/webiny-integration-typeform/src/\1' [strict] diff --git a/.travis.yml b/.travis.yml index ec26e226b11..a7d5ee5236d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,12 @@ jobs: include: - stage: test script: yarn build && yarn test:build - - stage: release + - stage: release-core if: branch = "master" AND type = "push" script: yarn build && yarn release + - stage: release-addons + if: branch = "master" AND type = "push" + script: yarn build && yarn release-addons notifications: slack: on_success: change diff --git a/addons/webiny-integration-cookie-policy/.babelrc b/addons/webiny-integration-cookie-policy/.babelrc new file mode 100644 index 00000000000..c9af31ab896 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/.babelrc @@ -0,0 +1,25 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "browsers": ["last 2 versions", "safari >= 7"] + } + }], + "@babel/preset-react", + "@babel/preset-flow" + ], + "plugins": [ + ["babel-plugin-emotion", { "autoLabel": true }], + ["@babel/plugin-proposal-object-rest-spread", {"useBuiltIns": true}], + ["@babel/plugin-transform-runtime"], + ["@babel/plugin-proposal-class-properties"], + ["babel-plugin-named-asset-import", { + "loaderMap": { + "svg": { + "ReactComponent": "@svgr/webpack![path]" + } + } + }] + ] +} + diff --git a/packages/webiny-app-admin/.eslintrc.js b/addons/webiny-integration-cookie-policy/.eslintrc.js similarity index 100% rename from packages/webiny-app-admin/.eslintrc.js rename to addons/webiny-integration-cookie-policy/.eslintrc.js diff --git a/addons/webiny-integration-cookie-policy/README.md b/addons/webiny-integration-cookie-policy/README.md new file mode 100644 index 00000000000..8fcf39b888b --- /dev/null +++ b/addons/webiny-integration-cookie-policy/README.md @@ -0,0 +1,42 @@ +# webiny-integration-cookie-policy + +Renders a simple cookie policy info banner. Powered by Cookie Consent (https://cookieconsent.insites.com/). + +## Installation +`yarn add webiny-integration-cookie policy` + +## Setup +To setup, you must register a set of plugins. For more information on plugins, please visit Webiny documentation. + +#### API +``` +import cookiePolicyPlugins from "webiny-integration-cookie-policy/plugins/api" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(cookiePolicyPlugins); +``` + +Exposes necessary GraphQL fields for updating integration settings. + + +#### Admin +``` +import cookiePolicyPlugins from "webiny-integration-cookie-policy/plugins/admin" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(cookiePolicyPlugins); +``` + +Enables management of cookie policy settings, which can be accessed via Settings section in the main menu. Here you +can edit things like banner position, colors and labels. + + +#### Site +``` +import cookiePolicyPlugins from "webiny-integration-cookie-policy/plugins/render" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(cookiePolicyPlugins); +``` + +Renders cookie policy banner. Use in your public website. \ No newline at end of file diff --git a/addons/webiny-integration-cookie-policy/index.js b/addons/webiny-integration-cookie-policy/index.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/webiny-integration-cookie-policy/package.json b/addons/webiny-integration-cookie-policy/package.json new file mode 100644 index 00000000000..6475ba8a7c1 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/package.json @@ -0,0 +1,34 @@ +{ + "name": "webiny-integration-cookie-policy", + "version": "0.0.0", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/webiny/webiny-js.git" + }, + "author": "Adrian Smijulj", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "react": "^16.4.0", + "react-dom": "^16.4.0" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@svgr/webpack": "^2.1.1", + "babel-plugin-module-resolver": "^3.1.1", + "babel-plugin-named-asset-import": "^1.0.0-next.3e165448" + }, + "scripts": { + "build": "babel src -d ${DEST:-build} --source-maps --copy-files", + "flow-copy-source": "flow-copy-source src ${DEST:-build}", + "postbuild": "yarn flow-copy-source" + } +} diff --git a/addons/webiny-integration-cookie-policy/src/plugins/admin/components/CookiePolicySettings.js b/addons/webiny-integration-cookie-policy/src/plugins/admin/components/CookiePolicySettings.js new file mode 100644 index 00000000000..1c639fce3f6 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/admin/components/CookiePolicySettings.js @@ -0,0 +1,248 @@ +// @flow +import * as React from "react"; +import { Form } from "webiny-form"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { Switch } from "webiny-ui/Switch"; +import { Input } from "webiny-ui/Input"; +import { ColorPicker } from "webiny-ui/ColorPicker"; +import { ButtonSecondary, ButtonPrimary } from "webiny-ui/Button"; +import { Query, Mutation } from "react-apollo"; +import { withSnackbar } from "webiny-admin/components"; +import { RadioGroup, Radio } from "webiny-ui/Radio"; +import graphql from "./graphql"; +import showCookiePolicy from "./../../utils/showCookiePolicy"; + +import { + SimpleForm, + SimpleFormFooter, + SimpleFormContent, + SimpleFormHeader +} from "webiny-admin/components/Views/SimpleForm"; + +const positionOptions = [ + { id: "bottom", name: "Bottom" }, + { id: "top", name: "Top" }, + { id: "bottom-left", name: "Floating left" }, + { id: "bottom-right", name: "Floating right" } +]; + +const CookiePolicySettings = ({ showSnackbar }) => { + return ( + + {({ data }) => ( + + {update => ( +
{ + await update({ + variables: { + data: data.cookiePolicy + } + }); + showSnackbar("Settings updated successfully."); + }} + > + {({ Bind, form, data }) => ( + + + { + if (!aaa) { + form.submit(); + } + }} + > + + + + {data.cookiePolicy && data.cookiePolicy.enabled ? ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {({ + onChange, + getValue + }) => ( + + {positionOptions.map( + ({ + id, + name + }) => ( + + ) + )} + + )} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + showCookiePolicy({ + ...data.cookiePolicy, + // Official bug fix. + messagelink: + '{{message}} {{link}}', + dismissOnTimeout: 5000, + cookie: { + expiryDays: 0.00000001 + } + }); + }} + > + Preview + +   + + Save + + + + ) : null} + + )} +
+ )} +
+ )} +
+ ); +}; + +export default withSnackbar()(CookiePolicySettings); diff --git a/addons/webiny-integration-cookie-policy/src/plugins/admin/components/graphql.js b/addons/webiny-integration-cookie-policy/src/plugins/admin/components/graphql.js new file mode 100644 index 00000000000..7a82eb3fad4 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/admin/components/graphql.js @@ -0,0 +1,44 @@ +// @flow +import gql from "graphql-tag"; + +const fields = /* GraphQL */ ` + { + enabled + position + content { + href + message + dismiss + link + } + palette { + popup { + background + text + } + button { + background + text + } + } + } +`; + +const graphql = { + query: gql` + query getSettings { + settings { + cookiePolicy ${fields} + } + } + `, + mutation: gql` + mutation updateSettings($data: CookiePolicySettingsInput) { + settings { + cookiePolicy(data: $data) ${fields} + } + } + ` +}; + +export default graphql; diff --git a/addons/webiny-integration-cookie-policy/src/plugins/admin/index.js b/addons/webiny-integration-cookie-policy/src/plugins/admin/index.js new file mode 100644 index 00000000000..6ef33215c20 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/admin/index.js @@ -0,0 +1,31 @@ +// @flow +import * as React from "react"; +import CookiePolicySettings from "./components/CookiePolicySettings"; +import type { SettingsPluginType } from "webiny-admin/types"; +import { hasRoles } from "webiny-app-security"; +import { SecureRoute } from "webiny-app-security/components"; + +const roles = ["cms-settings"]; + +export default ([ + { + type: "settings", + name: "settings-cookie-policy", + settings: { + show: () => hasRoles(roles), + type: "integration", + name: "Cookie Policy", + component: ( + + + + ), + route: { + name: "Settings.CookiePolicy", + path: "/cookie-policy", + title: "Cookie Policy", + group: undefined + } + } + } +]: Array); diff --git a/addons/webiny-integration-cookie-policy/src/plugins/api/index.js b/addons/webiny-integration-cookie-policy/src/plugins/api/index.js new file mode 100644 index 00000000000..306b05b2f35 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/api/index.js @@ -0,0 +1,150 @@ +// @flow +import { Model } from "webiny-model"; +import { settingsFactory } from "webiny-api/entities"; +import { hasScope } from "webiny-api-security"; + +class ColorsModel extends Model { + constructor() { + super(); + this.attr("background").char(); + this.attr("text").char(); + } +} + +class PaletteModel extends Model { + constructor() { + super(); + this.attr("popup").model(ColorsModel); + this.attr("button").model(ColorsModel); + } +} +class ContentModel extends Model { + constructor() { + super(); + this.attr("href").char(); + this.attr("message").char(); + this.attr("dismiss").char(); + this.attr("link").char(); + } +} + +class CookiePolicySettingsModel extends Model { + constructor() { + super(); + this.attr("enabled").boolean(); + this.attr("position") + .char() + .setValidators("in:bottom:top:bottom-left:bottom-right") + .setDefaultValue("bottom"); + this.attr("palette").model(PaletteModel); + this.attr("content").model(ContentModel); + } +} + +export default [ + { + name: "graphql-schema-settings-cookie-policy", + type: "graphql", + typeDefs: ``, + resolvers: {}, + security: { + shield: { + SettingsQuery: { + cookiePolicy: hasScope("cms:settings") + }, + SettingsMutation: { + cookiePolicy: hasScope("cms:settings") + } + } + } + }, + { + name: "schema-settings-cookie-policy", + type: "schema-settings", + namespace: "cookiePolicy", + typeDefs: /* GraphQL */ ` + type CookiePolicySettings { + enabled: Boolean + policyLink: String + position: String + palette: CookiePolicySettingsPalette + content: CookiePolicySettingsContent + } + + type CookiePolicySettingsContent { + href: String + message: String + dismiss: String + link: String + } + + type CookiePolicySettingsPaletteColors { + background: String + text: String + } + + type CookiePolicySettingsPalette { + popup: CookiePolicySettingsPaletteColors + button: CookiePolicySettingsPaletteColors + } + + input CookiePolicySettingsInput { + enabled: Boolean + position: String + palette: CookiePolicySettingsPaletteInput + content: CookiePolicySettingsContentInput + } + + input CookiePolicySettingsPaletteColorsInput { + background: String + text: String + } + + input CookiePolicySettingsPaletteInput { + popup: CookiePolicySettingsPaletteColorsInput + button: CookiePolicySettingsPaletteColorsInput + } + + input CookiePolicySettingsContentInput { + href: String + message: String + dismiss: String + link: String + } + + extend type SettingsQuery { + cookiePolicy: CookiePolicySettings + } + + extend type SettingsMutation { + cookiePolicy(data: CookiePolicySettingsInput): CookiePolicySettings + } + `, + entity: ({ + cookiePolicy: { + entities: { CookiePolicySettings } + } + }: Object) => CookiePolicySettings + }, + { + type: "entity", + name: "entity-cookie-policy-settings", + namespace: "cookiePolicy", + entity: { + name: "CookiePolicySettings", + factory: (...args: Array) => { + return class CookiePolicySettings extends settingsFactory(...args) { + static key = "cookie-policy"; + + data: Object; + load: Function; + + constructor() { + super(); + this.attr("data").model(CookiePolicySettingsModel); + } + }; + } + } + } +]; diff --git a/addons/webiny-integration-cookie-policy/src/plugins/render/graphql.js b/addons/webiny-integration-cookie-policy/src/plugins/render/graphql.js new file mode 100644 index 00000000000..5866a9bc37f --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/render/graphql.js @@ -0,0 +1,31 @@ +// @flow +import gql from "graphql-tag"; + +const graphql = gql` + query getSettings { + settings { + cookiePolicy { + content { + href + message + dismiss + link + } + enabled + position + palette { + popup { + background + text + } + button { + background + text + } + } + } + } + } +`; + +export default graphql; diff --git a/addons/webiny-integration-cookie-policy/src/plugins/render/index.js b/addons/webiny-integration-cookie-policy/src/plugins/render/index.js new file mode 100644 index 00000000000..83ebb8c79e1 --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/render/index.js @@ -0,0 +1,38 @@ +// @flow +import * as React from "react"; +import { Query } from "react-apollo"; +import query from "./graphql"; +import showCookiePolicy from "./../utils/showCookiePolicy"; + +class CookiePolicy extends React.Component<*> { + componentDidMount() { + const { settings } = this.props; + if (settings && settings.enabled !== true) { + return; + } + + showCookiePolicy(settings); + } + + render() { + return null; + } +} + +export default [ + { + type: "module-render", + name: "module-render-cookie-policy", + component: ( + + {({ data, loading }) => { + if (loading) { + return null; + } + + return ; + }} + + ) + } +]; diff --git a/addons/webiny-integration-cookie-policy/src/plugins/utils/showCookiePolicy.js b/addons/webiny-integration-cookie-policy/src/plugins/utils/showCookiePolicy.js new file mode 100644 index 00000000000..746c7f7b8bb --- /dev/null +++ b/addons/webiny-integration-cookie-policy/src/plugins/utils/showCookiePolicy.js @@ -0,0 +1,23 @@ +// @flow +import load from "webiny-load-assets"; + +const prepareParams = (params: Object) => { + const prepared = { content: {}, ...params }; + + if (!prepared.content.href) { + prepared.showLink = false; + } + + return prepared; +}; + +const showCookiePolicy = async (params: Object) => { + await load( + "//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css", + "//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js" + ); + + window.cookieconsent.initialise(prepareParams(params)); +}; + +export default showCookiePolicy; diff --git a/addons/webiny-integration-google-tag-manager/.babelrc b/addons/webiny-integration-google-tag-manager/.babelrc new file mode 100644 index 00000000000..c9af31ab896 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/.babelrc @@ -0,0 +1,25 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "browsers": ["last 2 versions", "safari >= 7"] + } + }], + "@babel/preset-react", + "@babel/preset-flow" + ], + "plugins": [ + ["babel-plugin-emotion", { "autoLabel": true }], + ["@babel/plugin-proposal-object-rest-spread", {"useBuiltIns": true}], + ["@babel/plugin-transform-runtime"], + ["@babel/plugin-proposal-class-properties"], + ["babel-plugin-named-asset-import", { + "loaderMap": { + "svg": { + "ReactComponent": "@svgr/webpack![path]" + } + } + }] + ] +} + diff --git a/addons/webiny-integration-google-tag-manager/.eslintrc.js b/addons/webiny-integration-google-tag-manager/.eslintrc.js new file mode 100644 index 00000000000..2b20e7ffa64 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/.eslintrc.js @@ -0,0 +1,33 @@ +module.exports = { + parser: "babel-eslint", + extends: ["eslint:recommended", "plugin:react/recommended"], + plugins: ["flowtype"], + env: { + mocha: true, + commonjs: true, + node: true, + es6: true + }, + parserOptions: { + ecmaVersion: 6, + sourceType: "module" + }, + rules: { + "flowtype/define-flow-type": 1, + "react/prop-types": 0 + }, + settings: { + react: { + pragma: "React", // Pragma to use, default to "React" + version: "16.0", // React version, default to the latest React stable release + flowVersion: "0.63" // Flow version + }, + flowtype: { + onlyFilesWithFlowAnnotation: true + } + }, + globals: { + window: true, + document: true + } +}; diff --git a/addons/webiny-integration-google-tag-manager/README.md b/addons/webiny-integration-google-tag-manager/README.md new file mode 100644 index 00000000000..0f1a55db05e --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/README.md @@ -0,0 +1,42 @@ +# webiny-integration-google-tag-manager + +Initializes Google Tag Manager (https://marketingplatform.google.com/about/tag-manager/). + +## Installation +`yarn add webiny-integration-google-tag-manager` + +## Setup +To setup, you must register a set of plugins. For more information on plugins, please visit Webiny documentation. + +#### API +``` +import gtmPlugins from "webiny-integration-google-tag-manager/plugins/api" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(gtmPlugins); +``` + +Exposes necessary GraphQL fields for updating integration settings. + + +#### Admin +``` +import gtmPlugins from "webiny-integration-google-tag-manager/plugins/admin" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(gtmPlugins); +``` + +Enables management of GTM settings, which can be accessed via Settings section in the main menu. You will paste +your GTM "Container ID" here (this is required in order for the integration to work properly). + + +#### Site +``` +import gtmPlugins from "webiny-integration-google-tag-manager/plugins/render" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(gtmPlugins); +``` + +Initializes Google Tag Manager. Use in your public website. \ No newline at end of file diff --git a/addons/webiny-integration-google-tag-manager/index.js b/addons/webiny-integration-google-tag-manager/index.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/webiny-integration-google-tag-manager/package.json b/addons/webiny-integration-google-tag-manager/package.json new file mode 100644 index 00000000000..ddc85e3f8ef --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/package.json @@ -0,0 +1,36 @@ +{ + "name": "webiny-integration-google-tag-manager", + "version": "0.0.0", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/webiny/webiny-js.git" + }, + "author": "Adrian Smijulj", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@svgr/webpack": "^2.1.1", + "babel-plugin-module-resolver": "^3.1.1", + "babel-plugin-named-asset-import": "^1.0.0-next.3e165448" + }, + "peerDependencies": { + "react": "^16.4.0", + "react-dom": "^16.4.0" + }, + "scripts": { + "build": "babel src -d ${DEST:-build} --source-maps --copy-files", + "flow-copy-source": "flow-copy-source src ${DEST:-build}", + "postbuild": "yarn flow-copy-source" + } +} diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/GoogleTagManagerSettings.js b/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/GoogleTagManagerSettings.js new file mode 100644 index 00000000000..0ce02e493b2 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/GoogleTagManagerSettings.js @@ -0,0 +1,93 @@ +// @flow +import * as React from "react"; +import { Form } from "webiny-form"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { Switch } from "webiny-ui/Switch"; +import { ButtonPrimary } from "webiny-ui/Button"; +import { Query, Mutation } from "react-apollo"; +import { withSnackbar } from "webiny-admin/components"; +import { Input } from "webiny-ui/Input"; +import graphql from "./graphql"; + +import { + SimpleForm, + SimpleFormFooter, + SimpleFormContent, + SimpleFormHeader +} from "webiny-admin/components/Views/SimpleForm"; + +const GoogleTagManagerSettings = ({ showSnackbar }) => { + return ( + + {({ data }) => ( + + {update => ( +
{ + await update({ + variables: { + data: data.googleTagManager + } + }); + showSnackbar("Settings updated successfully."); + }} + > + {({ Bind, form, data }) => ( + + + { + if (!aaa) { + form.submit(); + } + }} + > + + + + {data.googleTagManager && data.googleTagManager.enabled ? ( + <> + + + + + + + + + + + + + + + + Save + + + + ) : null} + + )} +
+ )} +
+ )} +
+ ); +}; + +export default withSnackbar()(GoogleTagManagerSettings); diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/graphql.js b/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/graphql.js new file mode 100644 index 00000000000..22ab5f03ff6 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/admin/components/graphql.js @@ -0,0 +1,28 @@ +// @flow +import gql from "graphql-tag"; + +const fields = /* GraphQL */ ` + { + enabled + code + } +`; + +const graphql = { + query: gql` + query getSettings { + settings { + googleTagManager ${fields} + } + } + `, + mutation: gql` + mutation updateSettings($data: GoogleTagManagerSettingsInput) { + settings { + googleTagManager(data: $data) ${fields} + } + } + ` +}; + +export default graphql; diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/admin/index.js b/addons/webiny-integration-google-tag-manager/src/plugins/admin/index.js new file mode 100644 index 00000000000..36e19ac4dd0 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/admin/index.js @@ -0,0 +1,31 @@ +// @flow +import * as React from "react"; +import GoogleTagManagerSettings from "./components/GoogleTagManagerSettings"; +import type { SettingsPluginType } from "webiny-admin/types"; +import { hasRoles } from "webiny-app-security"; +import { SecureRoute } from "webiny-app-security/components"; + +const roles = ["cms-settings"]; + +export default ([ + { + type: "settings", + name: "settings-google-tag-manager", + settings: { + show: () => hasRoles(roles), + type: "integration", + name: "Google Tag Manager", + component: ( + + + + ), + route: { + name: "Settings.GoogleTagManager", + path: "/google-tag-manager", + title: "Google Tag Manager", + group: undefined + } + } + } +]: Array); diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/api/index.js b/addons/webiny-integration-google-tag-manager/src/plugins/api/index.js new file mode 100644 index 00000000000..06bca237a5b --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/api/index.js @@ -0,0 +1,81 @@ +// @flow +import { Model } from "webiny-model"; +import { settingsFactory } from "webiny-api/entities"; +import { hasScope } from "webiny-api-security"; + +class GoogleTagManagerSettingsModel extends Model { + constructor() { + super(); + this.attr("enabled").boolean(); + this.attr("code").char(); + } +} + +export default [ + { + name: "graphql-schema-settings-google-tag-manager", + type: "graphql", + typeDefs: ``, + resolvers: {}, + security: { + shield: { + SettingsQuery: { + googleTagManager: hasScope("cms:settings") + }, + SettingsMutation: { + googleTagManager: hasScope("cms:settings") + } + } + } + }, + { + type: "schema-settings", + name: "schema-settings-google-tag-manager", + namespace: "googleTagManager", + typeDefs: /* GraphQL */ ` + type GoogleTagManagerSettings { + enabled: Boolean + code: String + } + + input GoogleTagManagerSettingsInput { + enabled: Boolean + code: String + } + + extend type SettingsQuery { + googleTagManager: GoogleTagManagerSettings + } + + extend type SettingsMutation { + googleTagManager(data: GoogleTagManagerSettingsInput): GoogleTagManagerSettings + } + `, + entity: ({ + googleTagManager: { + entities: { GoogleTagManagerSettings } + } + }: Object) => GoogleTagManagerSettings + }, + { + type: "entity", + name: "entity-google-tag-manager-settings", + namespace: "googleTagManager", + entity: { + name: "GoogleTagManagerSettings", + factory: (...args: Array) => { + return class GoogleTagManagerSettings extends settingsFactory(...args) { + static key = "google-tag-manager"; + + data: Object; + load: Function; + + constructor() { + super(); + this.attr("data").model(GoogleTagManagerSettingsModel); + } + }; + } + } + } +]; diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/render/graphql.js b/addons/webiny-integration-google-tag-manager/src/plugins/render/graphql.js new file mode 100644 index 00000000000..8abd310b429 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/render/graphql.js @@ -0,0 +1,15 @@ +// @flow +import gql from "graphql-tag"; + +const graphql = gql` + query getSettings { + settings { + googleTagManager { + enabled + code + } + } + } +`; + +export default graphql; diff --git a/addons/webiny-integration-google-tag-manager/src/plugins/render/index.js b/addons/webiny-integration-google-tag-manager/src/plugins/render/index.js new file mode 100644 index 00000000000..e413f02cc10 --- /dev/null +++ b/addons/webiny-integration-google-tag-manager/src/plugins/render/index.js @@ -0,0 +1,60 @@ +// @flow +import * as React from "react"; +import { Query } from "react-apollo"; +import query from "./graphql"; + +class GoogleTagManager extends React.Component<*> { + componentDidMount() { + const { settings } = this.props; + if (settings && settings.enabled !== true) { + return; + } + + if (window.dataLayer) { + return; + } + + document.querySelector("body").prepend( + new window.DOMParser().parseFromString( + ``, + "text/xml" + ).firstChild + ); + + (function(w, d, s, l, i) { + w[l] = w[l] || []; + w[l].push({ "gtm.start": new Date().getTime(), event: "gtm.js" }); + var f = d.getElementsByTagName(s)[0], + j = d.createElement(s), + dl = l != "dataLayer" ? "&l=" + l : ""; + j.async = true; + j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl; + f.parentNode.insertBefore(j, f); + })(window, document, "script", "dataLayer", settings.code); + } + + render() { + return null; + } +} + +export default [ + { + type: "module-render", + name: "module-render-google-tag-manager", + component: ( + + {({ data, loading }) => { + if (loading) { + return null; + } + + return ; + }} + + ) + } +]; diff --git a/addons/webiny-integration-mailchimp/.babelrc b/addons/webiny-integration-mailchimp/.babelrc new file mode 100644 index 00000000000..c9af31ab896 --- /dev/null +++ b/addons/webiny-integration-mailchimp/.babelrc @@ -0,0 +1,25 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "browsers": ["last 2 versions", "safari >= 7"] + } + }], + "@babel/preset-react", + "@babel/preset-flow" + ], + "plugins": [ + ["babel-plugin-emotion", { "autoLabel": true }], + ["@babel/plugin-proposal-object-rest-spread", {"useBuiltIns": true}], + ["@babel/plugin-transform-runtime"], + ["@babel/plugin-proposal-class-properties"], + ["babel-plugin-named-asset-import", { + "loaderMap": { + "svg": { + "ReactComponent": "@svgr/webpack![path]" + } + } + }] + ] +} + diff --git a/addons/webiny-integration-mailchimp/.eslintrc.js b/addons/webiny-integration-mailchimp/.eslintrc.js new file mode 100644 index 00000000000..2b20e7ffa64 --- /dev/null +++ b/addons/webiny-integration-mailchimp/.eslintrc.js @@ -0,0 +1,33 @@ +module.exports = { + parser: "babel-eslint", + extends: ["eslint:recommended", "plugin:react/recommended"], + plugins: ["flowtype"], + env: { + mocha: true, + commonjs: true, + node: true, + es6: true + }, + parserOptions: { + ecmaVersion: 6, + sourceType: "module" + }, + rules: { + "flowtype/define-flow-type": 1, + "react/prop-types": 0 + }, + settings: { + react: { + pragma: "React", // Pragma to use, default to "React" + version: "16.0", // React version, default to the latest React stable release + flowVersion: "0.63" // Flow version + }, + flowtype: { + onlyFilesWithFlowAnnotation: true + } + }, + globals: { + window: true, + document: true + } +}; diff --git a/addons/webiny-integration-mailchimp/README.md b/addons/webiny-integration-mailchimp/README.md new file mode 100644 index 00000000000..9aa0a5dff55 --- /dev/null +++ b/addons/webiny-integration-mailchimp/README.md @@ -0,0 +1,99 @@ +# webiny-integration-mailchimp + +Render Mailchimp newsletter signup form. + +## Installation +`yarn add webiny-integration-mailchimp` + +## Setup +To setup, you must register a set of plugins. For more information on plugins, please visit Webiny documentation. + +#### API +``` +import mailchimpPlugins from "webiny-integration-mailchimp/plugins/api" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(...mailchimpPlugins); +``` + +Exposes necessary GraphQL fields that handle integration settings and newsletter signup form submits. + +#### Admin + +##### 1. Register plugins + +``` +import mailchimpPlugins from "webiny-integration-mailchimp/plugins/admin" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(...mailchimpPlugins); +``` + +Enables management of Mailchimp settings, which can be accessed via Settings section in the main menu. You will paste +your Mailchimp API key here (this is required in order for the integration to work properly). + +Additionally, this will also register Mailchimp element in CMS editor, which will enable you to insert +newsletter signup forms in your pages. The element will be registered under the "Form" element category. + +##### 2. Register newsletter signup form component +To complete the admin setup, register one or more newsletter signup forms. Registration is done via CMS theme. +For example in `demo-theme/src/index.js`: + +``` +import * as React from "react"; +import { MailchimpDefaultForm } from "webiny-integration-mailchimp/render/components"; + +export default { + fonts: { + ... + }, + colors: { + ... + }, + elements: { + pagesList: { + ... + }, + mailchimp: { + components: [ + { + name: "default", + title: "Default page list", + component: MailchimpDefaultForm + }, + { + name: "custom", + title: "Custom page list", + component: (props: *) => { + const { Bind, submit } = props; + return ( +
+ + + + Submit +
+ ); + } + } + ] + } + }, + styles: { + ... + } +}; +``` + +Use `Bind` component to bind form elements and `submit` callback to submit the form. + +#### Site +``` +import mailchimpPlugins from "webiny-integration-mailchimp/plugins/render" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(mailchimpPlugins); +``` + +Enables Mailchimp newsletter signup form render in your public website. + diff --git a/addons/webiny-integration-mailchimp/index.js b/addons/webiny-integration-mailchimp/index.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/webiny-integration-mailchimp/package.json b/addons/webiny-integration-mailchimp/package.json new file mode 100644 index 00000000000..b17a5c72df6 --- /dev/null +++ b/addons/webiny-integration-mailchimp/package.json @@ -0,0 +1,39 @@ +{ + "name": "webiny-integration-mailchimp", + "version": "0.0.0", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/webiny/webiny-js.git" + }, + "author": "Adrian Smijulj", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "classnames": "^2.2.6", + "mailchimp-api-v3": "^1.12.1", + "react-emotion": "^9.2.4" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@svgr/webpack": "^2.1.1", + "babel-plugin-module-resolver": "^3.1.1", + "babel-plugin-named-asset-import": "^1.0.0-next.3e165448" + }, + "peerDependencies": { + "react": "^16.4.0", + "react-dom": "^16.4.0" + }, + "scripts": { + "build": "babel src -d ${DEST:-build} --source-maps --copy-files", + "flow-copy-source": "flow-copy-source src ${DEST:-build}", + "postbuild": "yarn flow-copy-source" + } +} diff --git a/addons/webiny-integration-mailchimp/src/components/MailchimpDefaultForm.js b/addons/webiny-integration-mailchimp/src/components/MailchimpDefaultForm.js new file mode 100644 index 00000000000..ccaf087b29c --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/components/MailchimpDefaultForm.js @@ -0,0 +1,57 @@ +// @flow +import * as React from "react"; +import { Input } from "webiny-ui/Input"; +import { ButtonPrimary } from "webiny-ui/Button"; +import { css } from "react-emotion"; +import classnames from "classnames"; + +const wrapper = css({ + display: "flex", + justifyContent: "space-between" +}); + +class MailchimpDefaultForm extends React.Component< + *, + { processing: boolean, message: React.Node } +> { + state = { + processing: false, + message: null + }; + + render() { + const { Bind, submit } = this.props; + return ( +
+
+ + + + { + this.setState({ processing: true }); + + await submit({ + onSuccess: () => { + this.setState({ processing: false }); + }, + onError: err => { + this.setState({ processing: false }); + this.setState({ message: err }); + } + }); + + this.setState({ processing: false }); + }} + > + Submit + +
+ {this.state.message &&
{this.state.message}
} +
+ ); + } +} + +export default MailchimpDefaultForm; diff --git a/addons/webiny-integration-mailchimp/src/components/index.js b/addons/webiny-integration-mailchimp/src/components/index.js new file mode 100644 index 00000000000..af4f0bc068a --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/components/index.js @@ -0,0 +1,2 @@ +// @flow +export { default as MailchimpDefaultForm } from "./MailchimpDefaultForm"; diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElement.js b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElement.js new file mode 100644 index 00000000000..ed3b492e90e --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElement.js @@ -0,0 +1,66 @@ +// @flow +import * as React from "react"; +import { pure } from "recompose"; +import { withCms } from "webiny-app-cms/context"; +import { ElementRoot } from "webiny-app-cms/render/components/ElementRoot"; +import { Form } from "webiny-form"; +import { Mutation } from "react-apollo"; +import gql from "graphql-tag"; + +const mutation = gql` + mutation addToList($email: String!, $list: String!) { + mailchimp { + addToList(email: $email, list: $list) { + error { + message + } + } + } + } +`; + +const MailchimpElement = pure((props: Object) => { + const { element, cms } = props; + const { component: selected } = element.settings; + const component = cms.theme.elements.mailchimp.components.find(cmp => cmp.name === selected); + + let render = Nothing selected.; + if (component) { + const Component = component.component; + render = ( + + {update => { + return ( +
+ {form => { + return ( + { + await form.submit(); + await update({ + variables: form.data + }); + }} + /> + ); + }} + + ); + }} +
+ ); + } + + return ( + + {render} + + ); +}); + +export default withCms()(MailchimpElement); diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElementAdvancedSettings.js b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElementAdvancedSettings.js new file mode 100644 index 00000000000..ba90071b9ae --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpElementAdvancedSettings.js @@ -0,0 +1,94 @@ +// @flow +import * as React from "react"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { withCms } from "webiny-app-cms/context"; +import MailchimpElement from "./MailchimpElement"; +import { AutoComplete } from "webiny-ui/AutoComplete"; +import { Query } from "react-apollo"; +import gql from "graphql-tag"; +import { get } from "lodash"; + +const MailchimpElementAdvancedSettings = ({ cms, Bind }: Object) => { + return ( + + + + + {({ data }) => ( + + {({ value: id, onChange }) => { + const options = get(data, "mailchimp.listLists.data", []).map( + ({ id, name }) => { + return { id, name }; + } + ); + + const value = options.find(item => item.id === id); + + return ( + + ); + }} + + )} + + + + {({ onChange, value: name }) => { + const options = cms.theme.elements.mailchimp.components.map( + ({ name, title }) => { + return { name, title }; + } + ); + + const value = options.find(item => item.name === name); + + return ( + + ); + }} + + + + + + + {({ value }) => ( +
+ +
+ )} +
+
+
+
+ ); +}; + +export default withCms()(MailchimpElementAdvancedSettings); diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpSettings.js b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpSettings.js new file mode 100644 index 00000000000..ad2e7fcfd2e --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/components/MailchimpSettings.js @@ -0,0 +1,86 @@ +// @flow +import * as React from "react"; +import { Form } from "webiny-form"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { Switch } from "webiny-ui/Switch"; +import { Input } from "webiny-ui/Input"; +import { ButtonPrimary } from "webiny-ui/Button"; +import { Query, Mutation } from "react-apollo"; +import { withSnackbar } from "webiny-admin/components"; +import graphql from "./graphql"; + +import { + SimpleForm, + SimpleFormFooter, + SimpleFormContent, + SimpleFormHeader +} from "webiny-admin/components/Views/SimpleForm"; + +const MailchimpSettings = ({ showSnackbar }) => { + return ( + + {({ data }) => ( + + {update => ( +
{ + await update({ + variables: { + data: data.mailchimp + } + }); + showSnackbar("Settings updated successfully."); + }} + > + {({ Bind, form, data }) => ( + + + { + if (!aaa) { + form.submit(); + } + }} + > + + + + {data.mailchimp && data.mailchimp.enabled ? ( + <> + + + + + + + + + + + + + + + + Save + + + + ) : null} + + )} +
+ )} +
+ )} +
+ ); +}; + +export default withSnackbar()(MailchimpSettings); diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/components/graphql.js b/addons/webiny-integration-mailchimp/src/plugins/admin/components/graphql.js new file mode 100644 index 00000000000..b9acd6407dc --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/components/graphql.js @@ -0,0 +1,28 @@ +// @flow +import gql from "graphql-tag"; + +const fields = /* GraphQL */ ` + { + enabled + apiKey + } +`; + +const graphql = { + query: gql` + query getSettings { + settings { + mailchimp ${fields} + } + } + `, + mutation: gql` + mutation updateSettings($data: MailchimpSettingsInput) { + settings { + mailchimp(data: $data) ${fields} + } + } + ` +}; + +export default graphql; diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/index.js b/addons/webiny-integration-mailchimp/src/plugins/admin/index.js new file mode 100644 index 00000000000..b43ee98c4ba --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/index.js @@ -0,0 +1,73 @@ +// @flow +import React from "react"; +import { Tab } from "webiny-ui/Tabs"; +import MailchimpSettings from "./components/MailchimpSettings"; +import MailchimpElementAdvancedSettings from "./components/MailchimpElementAdvancedSettings"; +import MailchimpElement from "./components/MailchimpElement"; +import { hasRoles } from "webiny-app-security"; +import { SecureRoute } from "webiny-app-security/components"; + +import render from "./../render"; + +const roles = ["cms-settings"]; + +export default [ + ...render, + { + name: "cms-element-mailchimp", + type: "cms-element", + toolbar: { + title: "Mailchimp", + group: "cms-element-group-form", + preview() { + return A Mailchimp sample; + } + }, + settings: ["cms-element-settings-delete", "", "cms-element-settings-height"], + target: ["cms-element-column", "cms-element-row", "cms-element-list-item"], + onCreate: "open-settings", + render({ element }: Object) { + return ; + }, + create() { + return { + type: "cms-element-mailchimp", + elements: [], + data: {}, + settings: {} + }; + } + }, + { + name: "cms-element-advanced-settings-mailchimp", + type: "cms-element-advanced-settings", + element: "cms-element-mailchimp", + render(props: Object) { + return ( + + + + ); + } + }, + { + type: "settings", + name: "settings-mailchimp", + settings: { + show: () => hasRoles(roles), + type: "integration", + name: "Mailchimp", + component: ( + + + + ), + route: { + name: "Settings.Mailchimp", + path: "/mailchimp", + title: "Mailchimp", + group: undefined + } + } + } +]; diff --git a/addons/webiny-integration-mailchimp/src/plugins/admin/round-text_format-24px.svg b/addons/webiny-integration-mailchimp/src/plugins/admin/round-text_format-24px.svg new file mode 100644 index 00000000000..220fd4882fc --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/admin/round-text_format-24px.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/addons/webiny-integration-mailchimp/src/plugins/api/index.js b/addons/webiny-integration-mailchimp/src/plugins/api/index.js new file mode 100644 index 00000000000..089b15a6400 --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/api/index.js @@ -0,0 +1,196 @@ +// @flow +import { Model } from "webiny-model"; +import { settingsFactory } from "webiny-api/entities"; +import { dummyResolver } from "webiny-api/graphql"; +import { ListErrorResponse, ListResponse, Response, ErrorResponse } from "webiny-api/graphql"; +import Mailchimp from "mailchimp-api-v3"; +import { hasScope } from "webiny-api-security"; + +class MailchimpSettingsModel extends Model { + constructor() { + super(); + this.attr("enabled").boolean(); + this.attr("apiKey").char(); + } +} + +export default [ + { + name: "schema-settings-mailchimp", + type: "schema-settings", + namespace: "mailchimp", + typeDefs: /* GraphQL */ ` + type MailchimpSettings { + enabled: Boolean + apiKey: String + } + + input MailchimpSettingsInput { + enabled: Boolean + apiKey: String + } + + extend type SettingsQuery { + mailchimp: MailchimpSettings + } + + extend type SettingsMutation { + mailchimp(data: MailchimpSettingsInput): MailchimpSettings + } + `, + entity: ({ + mailchimp: { + entities: { MailchimpSettings } + } + }: Object) => MailchimpSettings + }, + { + type: "entity", + name: "entity-mailchimp-settings", + namespace: "mailchimp", + entity: { + name: "MailchimpSettings", + factory: (...args: Array) => { + return class MailchimpSettings extends settingsFactory(...args) { + static key = "mailchimp"; + + data: Object; + load: Function; + + constructor() { + super(); + this.attr("data").model(MailchimpSettingsModel); + } + }; + } + } + }, + { + type: "graphql", + name: "graphql-mailchimp", + namespace: "mailchimp", + security: { + shield: { + SettingsQuery: { + mailchimp: hasScope("cms:settings") + }, + SettingsMutation: { + mailchimp: hasScope("cms:settings") + }, + MailchimpQuery: { + listLists: hasScope("cms:editor") + }, + MailchimpMutation: { + addToList: hasScope("cms:editor") + } + } + }, + typeDefs: () => [ + /* GraphQL */ ` + type AddToListResponse { + error: Error + } + + type MailchimpMutation { + # Add a new member to members list. + addToList(list: String!, email: String!): AddToListResponse + } + + type Mutation { + mailchimp: MailchimpMutation + } + + type List { + id: String + name: String + } + + type ListsResponse { + data: [List] + meta: ListMeta + error: Error + } + + type MailchimpQuery { + listLists: ListsResponse + } + + type Query { + mailchimp: MailchimpQuery + } + ` + ], + resolvers: () => [ + { + Query: { + mailchimp: dummyResolver + }, + Mutation: { + mailchimp: dummyResolver + }, + MailchimpQuery: { + listLists: async ( + _: any, + args: Object, + { mailchimp: { entities } }: Object + ) => { + const { MailchimpSettings } = entities; + const settings = await MailchimpSettings.load(); + const mailchimp = new Mailchimp(settings.data.apiKey); + + try { + const { lists } = await mailchimp.get({ + path: `/lists/` + }); + + const output = lists.map(item => ({ + id: item.id, + name: item.name + })); + + return new ListResponse(output); + } catch (e) { + return new ListErrorResponse(e); + } + } + }, + MailchimpMutation: { + addToList: async ( + _: any, + { list: listId, email }: Object, + { mailchimp: { entities } }: Object + ) => { + const { MailchimpSettings } = entities; + const settings = await MailchimpSettings.load(); + const mailchimp = new Mailchimp(settings.data.apiKey); + + try { + const list = await mailchimp.get({ + path: `/lists/${listId}` + }); + + await mailchimp.post({ + path: `/lists/${listId}/members`, + body: { + email_address: email, + status: list.double_optin ? "pending" : "subscribed" + } + }); + + return new Response(); + } catch (e) { + return new ErrorResponse({ + code: e.status, + message: e.title, + data: { + detail: e.detail, + type: e.type + } + }); + } + } + } + } + ] + } +]; diff --git a/addons/webiny-integration-mailchimp/src/plugins/render/components/RenderMailchimpForm.js b/addons/webiny-integration-mailchimp/src/plugins/render/components/RenderMailchimpForm.js new file mode 100644 index 00000000000..5c8d176da70 --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/render/components/RenderMailchimpForm.js @@ -0,0 +1,80 @@ +// @flow +import { get } from "lodash"; +import gql from "graphql-tag"; +import { Form } from "webiny-form"; +import { Mutation } from "react-apollo"; +import React from "react"; + +const mutation = gql` + mutation addToList($email: String!, $list: String!) { + mailchimp { + addToList(email: $email, list: $list) { + error { + message + } + } + } + } +`; + +const RenderMailchimpForm = (props: *) => { + const { element, theme } = props; + const { component: selected } = element.settings; + const component = theme.elements.mailchimp.components.find(cmp => cmp.name === selected); + + if (component) { + const Component = component.component; + const style = { width: "100%", ...get(props, "element.settings.style") }; + return ( +
+ + {update => ( +
+ {({ form, data }) => { + return ( + void, + onSuccess?: () => void + }) => { + const isValid = await form.validate(); + if (!isValid) { + return; + } + + const response = await update({ + variables: { + ...data, + list: element.settings.list + } + }); + + const error = get( + response, + "data.mailchimp.addToList.error" + ); + + if (error) { + onError && onError(error.message); + } else { + onSuccess && onSuccess(); + } + }} + /> + ); + }} + + )} +
+
+ ); + } + + return null; +}; + +export default RenderMailchimpForm; diff --git a/addons/webiny-integration-mailchimp/src/plugins/render/index.js b/addons/webiny-integration-mailchimp/src/plugins/render/index.js new file mode 100644 index 00000000000..257d0c4a7ee --- /dev/null +++ b/addons/webiny-integration-mailchimp/src/plugins/render/index.js @@ -0,0 +1,15 @@ +// @flow +import React from "react"; +import type { RenderElementPluginType } from "webiny-app-cms/types"; +import RenderMailchimpForm from "./components/RenderMailchimpForm"; + +export default ([ + { + name: "cms-render-element-mailchimp", + type: "cms-render-element", + element: "cms-element-mailchimp", + render(props: *) { + return ; + } + } +]: Array); diff --git a/addons/webiny-integration-typeform/.babelrc.js b/addons/webiny-integration-typeform/.babelrc.js new file mode 100644 index 00000000000..bff5e207793 --- /dev/null +++ b/addons/webiny-integration-typeform/.babelrc.js @@ -0,0 +1 @@ +module.exports = require("webiny-rewire/babel/preset"); \ No newline at end of file diff --git a/addons/webiny-integration-typeform/.eslintrc.js b/addons/webiny-integration-typeform/.eslintrc.js new file mode 100644 index 00000000000..2b20e7ffa64 --- /dev/null +++ b/addons/webiny-integration-typeform/.eslintrc.js @@ -0,0 +1,33 @@ +module.exports = { + parser: "babel-eslint", + extends: ["eslint:recommended", "plugin:react/recommended"], + plugins: ["flowtype"], + env: { + mocha: true, + commonjs: true, + node: true, + es6: true + }, + parserOptions: { + ecmaVersion: 6, + sourceType: "module" + }, + rules: { + "flowtype/define-flow-type": 1, + "react/prop-types": 0 + }, + settings: { + react: { + pragma: "React", // Pragma to use, default to "React" + version: "16.0", // React version, default to the latest React stable release + flowVersion: "0.63" // Flow version + }, + flowtype: { + onlyFilesWithFlowAnnotation: true + } + }, + globals: { + window: true, + document: true + } +}; diff --git a/addons/webiny-integration-typeform/README.md b/addons/webiny-integration-typeform/README.md new file mode 100644 index 00000000000..c60b2f544ad --- /dev/null +++ b/addons/webiny-integration-typeform/README.md @@ -0,0 +1,32 @@ +# webiny-integration-typeform + +Render Typeform form in your pages. + +## Installation +`yarn add webiny-integration-typeform` + +## Setup +To setup, you must register a set of plugins. For more information on plugins, please visit Webiny documentation. + +#### Admin + +``` +import typeformPlugins from "webiny-integration-typeform/plugins/admin" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(typeformPlugins); +``` + +Registers Typeform element in CMS editor, which will enable you to embed forms in your pages. +The element will be registered under the "Form" element category. + +#### Site +``` +import typeformPlugins from "webiny-integration-typeform/plugins/render" +import { registerPlugins } from "webiny-plugins"; + +registerPlugins(typeformPlugins); +``` + +Enables Typeform form render in your public website. + diff --git a/addons/webiny-integration-typeform/index.js b/addons/webiny-integration-typeform/index.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/webiny-integration-typeform/package.json b/addons/webiny-integration-typeform/package.json new file mode 100644 index 00000000000..04e85ee0d91 --- /dev/null +++ b/addons/webiny-integration-typeform/package.json @@ -0,0 +1,36 @@ +{ + "name": "webiny-integration-typeform", + "version": "0.0.0", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/webiny/webiny-js.git" + }, + "author": "Adrian Smijulj", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "@babel/preset-react": "^7.0.0", + "@svgr/webpack": "^2.1.1", + "babel-plugin-module-resolver": "^3.1.1", + "babel-plugin-named-asset-import": "^1.0.0-next.3e165448" + }, + "peerDependencies": { + "react": "^16.4.0", + "react-dom": "^16.4.0" + }, + "scripts": { + "build": "babel src types.js -d ${DEST:-build} --source-maps --copy-files --ignore types.js", + "flow-copy-source": "flow-copy-source src ${DEST:-build}", + "postbuild": "yarn flow-copy-source" + } +} diff --git a/addons/webiny-integration-typeform/src/plugins/admin/TypeFormEmbed.js b/addons/webiny-integration-typeform/src/plugins/admin/TypeFormEmbed.js new file mode 100644 index 00000000000..373011d03e4 --- /dev/null +++ b/addons/webiny-integration-typeform/src/plugins/admin/TypeFormEmbed.js @@ -0,0 +1,20 @@ +// @flow +import React from "react"; +import { connect } from "webiny-app-cms/editor/redux"; +import { compose } from "recompose"; +import { getElement } from "webiny-app-cms/editor/selectors"; + +const TypeFormEmbed = (props: { element: Object }) => { + const { source } = props.element.data; + if (!source || !source.url) { + return You must configure your embed in the settings!; + } + + return ', + type: "video", + thumbnail_width: 480, + thumbnail_url: + "https://i.ytimg.com/vi/jG7dSXcfVqE/hqdefault.jpg", + title: "DO WHAT YOU CAN'T", + height: 270, + source: { + url: "https://www.youtube.com/watch?v=jG7dSXcfVqE" + } + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-youtube" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a2b71a0b03c70b7ce8142_m9ijqcfqykr.png", + size: 58576, + src: "/files/cms-element-5c2a2b71a0b03c70b7ce8142_m9ijqcfqykr.png", + type: "image/png", + meta: { width: 1000, height: 675 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content15.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content15.js new file mode 100644 index 00000000000..7e418580f24 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content15.js @@ -0,0 +1,534 @@ +export default { + id: "5c2a31e0a0b03c7257e8e1ca", + name: "Content #15", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 15, top: 15, right: 15, bottom: 15, left: 15 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + padding: { + desktop: { all: 15, top: 15, right: 15, bottom: 15, left: 15 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-background)" }, + border: { width: 1, radius: 10 }, + verticalAlign: "center", + shadow: { color: "var(--webiny-cms-theme-background)", blur: "2" } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 90, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + }, + { + object: "inline", + type: "link", + data: { + href: + "https://www.webiny.com/", + newTab: true + }, + nodes: [ + { + object: "text", + leaves: [ + { + object: + "leaf", + text: + "Space The Final Frontier", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + }, + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 10 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Shure’s Music Phone Adapter (MPA) is our favorite ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 0 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "angle-right"], + svg: + '', + width: "15" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 15, top: 15, right: 15, bottom: 15, left: 15 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 15, top: 15, right: 15, bottom: 15, left: 15 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-background)" }, + border: { width: 1, radius: 10 }, + verticalAlign: "center", + shadow: { color: "var(--webiny-cms-theme-background)", blur: "2" } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 90, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + }, + { + object: "inline", + type: "link", + data: { + href: + "https://www.webiny.com/", + newTab: true + }, + nodes: [ + { + object: "text", + leaves: [ + { + object: + "leaf", + text: + "Beyond The Naked Eye", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + }, + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 10 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Shure’s Music Phone Adapter (MPA) is our favorite ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 0 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "angle-right"], + svg: + '', + width: "15" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a31e0a0b03c7257e8e1ca_ml2jqcgq9pl.png", + size: 19111, + src: "/files/cms-element-5c2a31e0a0b03c7257e8e1ca_ml2jqcgq9pl.png", + type: "image/png", + meta: { width: 1000, height: 158 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content2.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content2.js new file mode 100644 index 00000000000..609902039d4 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content2.js @@ -0,0 +1,570 @@ +export default { + id: "5c27c7c6a0b03cd30e21c851", + name: "Content #2", + type: "block", + content: { + data: { + settings: { + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { top: 15, right: 15, bottom: 15, left: 15 } + }, + padding: { all: 0 }, + width: { value: "1000px" } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Profiles Of The Powerful Advertising ", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + }, + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Exec Steve Grasse", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + advanced: true, + desktop: { bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.3, + settings: { + margin: { advanced: true, desktop: { right: 10 } }, + padding: { desktop: { all: 10 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { advanced: true, desktop: { bottom: 5 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "image-placeholder_15bdjq9trsoh.svg", + type: "image/svg+xml", + size: 3140, + src: + "/files/image-placeholder_15bdjq9trsoh.svg" + }, + settings: { + margin: { + advanced: true, + mobile: { bottom: 15 } + }, + padding: { all: 0 } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { top: 5, right: 5 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "image-placeholder_15bvjq9ts6mv.svg", + type: "image/svg+xml", + size: 3140, + src: + "/files/image-placeholder_15bvjq9ts6mv.svg" + }, + settings: { + margin: { + advanced: true, + mobile: { bottom: 15 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { left: 5, top: 5 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "image-placeholder_15c7jq9tsaag.svg", + type: "image/svg+xml", + size: 3140, + src: + "/files/image-placeholder_15c7jq9tsaag.svg" + }, + settings: { + margin: { + advanced: true, + mobile: { bottom: 15 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 66.69, + settings: { + margin: { advanced: true, desktop: { left: 10 } }, + padding: { + desktop: { all: 10, top: 10, right: 10, bottom: 10, left: 10 } + }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Beyond The Naked Eye", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "For business professionals caught between high OEM price and mediocre print and graphic output, there’s a solution", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 10, bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Moon Gazing", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Do you want to download free song for ipod? If so, reading this article could save you from getting in to a lot of trouble! ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 10, bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Astronomy Or Astrology", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Having a baby can be a nerve wracking experience for new parents – not the nine months of pregnancy, I’m talking about after the infant is brought home from the hospital", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 10, bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c27c7c6a0b03cd30e21c851_15otjq9uirp1.png", + size: 74069, + src: "/files/cms-element-5c27c7c6a0b03cd30e21c851_15otjq9uirp1.png", + type: "image/png", + meta: { width: 1000, height: 519 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content3.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content3.js new file mode 100644 index 00000000000..1886d4b3bc1 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content3.js @@ -0,0 +1,423 @@ +export default { + id: "5c28e1b24527ee1c69754907", + name: "Content #3", + type: "block", + content: { + data: { + settings: { + margin: { + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 }, + advanced: true, + desktop: { top: 25, bottom: 25 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + width: { value: "1000px" } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 50, left: 50 }, + mobile: { bottom: 15 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_teaching_f1cm_1dgxjqarr6hu.svg", + type: "image/svg+xml", + size: 27415, + src: "/files/undraw_teaching_f1cm_1dgxjqarr6hu.svg", + width: "", + title: "", + alt: "", + height: "200", + align: "center" + }, + settings: { + margin: { + advanced: true, + desktop: { bottom: 25 }, + mobile: { bottom: 15 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Teaching", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Sunt eu minim voluptate sit aute consectetur do aute minim minim ipsum. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + all: 0, + advanced: true, + desktop: { bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "primaryColorText", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [] + } + ] + }, + { + object: "inline", + type: "link", + data: { + href: "https://www.webiny.com/" + }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Learn More", + marks: [] + } + ] + } + ] + }, + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 50, right: 50 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_meditating_0nae_1dhejqars1z0.svg", + type: "image/svg+xml", + size: 24229, + src: "/files/undraw_meditating_0nae_1dhejqars1z0.svg", + width: "", + title: "", + alt: "", + height: "200", + align: "center" + }, + settings: { + margin: { + advanced: true, + mobile: { bottom: 15 }, + desktop: { bottom: 25 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Meditating", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Excepteur deserunt deserunt do nisi adipisicing ullamco aute incididunt enim. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 20 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "primaryColorText", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [] + } + ] + }, + { + object: "inline", + type: "link", + data: { + href: "https://www.webiny.com/" + }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Learn More", + marks: [] + } + ] + } + ] + }, + { + object: "text", + leaves: [ + { + object: "leaf", + text: "", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28e1b24527ee1c69754907_5m0jqb1hnhv.png", + size: 53184, + src: "/files/cms-element-5c28e1b24527ee1c69754907_5m0jqb1hnhv.png", + type: "image/png", + meta: { width: 1000, height: 363 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content4.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content4.js new file mode 100644 index 00000000000..b7694f03ea3 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content4.js @@ -0,0 +1,242 @@ +export default { + id: "5c28e598a0b03c1e2bf51a03", + name: "Content #4", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Stu Unger Rise And Fall Of A Poker Genius", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h2", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Myspace Layouts ", + marks: [] + } + ] + } + ] + }, + { + object: "block", + type: "h2", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "The Missing Element", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { advanced: true, desktop: { top: 15, bottom: 25 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + image: { + name: "image-placeholder_5t1jqb1vbil.svg", + type: "image/svg+xml", + size: 3140, + src: "/files/image-placeholder_5t1jqb1vbil.svg", + width: "550", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { advanced: true, mobile: { top: 15, bottom: 15 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Id ea et id proident enim tempor ullamco anim elit nisi quis. Ea dolore est nisi magna est non anim sunt exercitation sunt eu non commodo. Dolore labore duis velit aliquip ullamco laborum officia et.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 25, right: 200, left: 200, bottom: 25 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + id: ["fas", "chevron-circle-right"], + svg: + '', + width: "12", + position: "right" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28e598a0b03c1e2bf51a03_5yijqb231x8.png", + size: 63669, + src: "/files/cms-element-5c28e598a0b03c1e2bf51a03_5yijqb231x8.png", + type: "image/png", + meta: { width: 1000, height: 759 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content5.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content5.js new file mode 100644 index 00000000000..2eb28c6ddf2 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content5.js @@ -0,0 +1,231 @@ +export default { + id: "5c28ee3ea0b03c293dcc7a78", + name: "Content #5", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: {}, + elements: [ + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { right: 50 } }, + padding: { mobile: { all: 0 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "star"], + color: "var(--webiny-cms-theme-text-primary)", + svg: + '' + }, + settings: { + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + advanced: true, + mobile: { bottom: 15 } + }, + padding: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + horizontalAlignFlex: "center", + horizontalAlign: "left" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "What If They Let You Run The Hubble", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { advanced: true, desktop: { top: 25, bottom: 25 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + id: ["fas", "chevron-circle-right"], + svg: + '', + position: "right", + width: "12" + }, + settings: { + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + padding: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + horizontalAlignFlex: "flex-start" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 50 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "There is a moment in the life of any aspiring astronomer that it is time to buy that first telescope. It’s exciting to think about setting up your own viewing station whether that is on the deck of your home or having.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { advanced: true, desktop: { top: 45 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28ee3ea0b03c293dcc7a78_858jqb3eic9.png", + size: 33817, + src: "/files/cms-element-5c28ee3ea0b03c293dcc7a78_858jqb3eic9.png", + type: "image/png", + meta: { width: 1000, height: 212 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content6.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content6.js new file mode 100644 index 00000000000..a03822b73f2 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content6.js @@ -0,0 +1,298 @@ +export default { + id: "5c28f1f1a0b03c2a75aa50f3", + name: "Content #6", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 50 }, + mobile: { bottom: 15 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_mobile_life_381t_8bzjqb3ucwi.svg", + type: "image/svg+xml", + size: 15269, + src: "/files/undraw_mobile_life_381t_8bzjqb3ucwi.svg" + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 50 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "gift"], + svg: + '', + color: "var(--webiny-cms-theme-primary)" + }, + settings: { + margin: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + advanced: true, + mobile: { bottom: 15 } + }, + padding: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 0, + left: 0 + } + }, + horizontalAlignFlex: "center", + horizontalAlign: "left" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "What If They Let You Run The Hubble", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "There is a moment in the life of any aspiring astronomer that it is time to buy that first telescope. It’s exciting to think about setting up your own viewing station whether that is on the deck of your home or having.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 0, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + width: { value: "250px" } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 10 }, + mobile: { right: 50, bottom: 15, left: 50 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "Appstore_89djqb3p38k.svg", + type: "image/svg+xml", + size: 14377, + src: "/files/Appstore_89djqb3p38k.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 10 }, + mobile: { right: 50, left: 50 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "GooglePlay_89rjqb3pati.svg", + type: "image/svg+xml", + size: 9800, + src: "/files/GooglePlay_89rjqb3pati.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28f1f1a0b03c2a75aa50f3_8dwjqb3yt7t.png", + size: 72969, + src: "/files/cms-element-5c28f1f1a0b03c2a75aa50f3_8dwjqb3yt7t.png", + type: "image/png", + meta: { width: 1000, height: 351 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content7.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content7.js new file mode 100644 index 00000000000..dbb33357b78 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content7.js @@ -0,0 +1,202 @@ +export default { + id: "5c28f705a0b03c2c477f3d4d", + name: "Content #7", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 0, right: 50 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "What If They Let You Run The Hubble", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "There is a moment in the life of any aspiring astronomer that it is time to buy that first telescope. It’s exciting to think about setting up your own viewing station whether that is on the deck of your home or having.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 0, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + image: { + name: "logo-set-small_8frjqb41mgk.svg", + type: "image/svg+xml", + size: 12766, + src: "/files/logo-set-small_8frjqb41mgk.svg", + width: "200", + title: "", + alt: "", + height: "", + align: "left" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "flex-end" + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 0, left: 50 }, + mobile: { bottom: 15 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center", + horizontalAlign: "left" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_map_1r69_8ndjqb4ksje.svg", + type: "image/svg+xml", + size: 6591, + src: "/files/undraw_map_1r69_8ndjqb4ksje.svg", + width: "300", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { advanced: true, mobile: { top: 15 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28f705a0b03c2c477f3d4d_8qujqb4qo0y.png", + size: 54752, + src: "/files/cms-element-5c28f705a0b03c2c477f3d4d_8qujqb4qo0y.png", + type: "image/png", + meta: { width: 1000, height: 307 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content8.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content8.js new file mode 100644 index 00000000000..036c4107787 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content8.js @@ -0,0 +1,404 @@ +export default { + id: "5c28f984a0b03c2d354b30a4", + name: "Content #8", + type: "block", + content: { + data: { + settings: { + animation: { name: "fade-up" }, + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + advanced: true, + desktop: { right: 50, left: 0 }, + mobile: { bottom: 15 } + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center", + horizontalAlign: "left" + } + }, + elements: [ + { + data: { + image: { + name: "hummans-template-1_8vujqb51kzg.svg", + type: "image/svg+xml", + size: 26692, + src: "/files/hummans-template-1_8vujqb51kzg.svg", + width: "350", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 50, right: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "What If They Let You Run The Hubble", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "There is a moment in the life of any aspiring astronomer that it is time to buy that first telescope. It’s exciting to think about setting up your own viewing station whether that is on the deck of your home or having.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 0, bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { right: 15 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Computer Hardware", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + margin: { + advanced: true, + desktop: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Your business, and pay a lot less for an external IT professional to help you when you need it.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + margin: { + advanced: true, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { advanced: true, desktop: { left: 15 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Choosing The Best", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + margin: { + advanced: true, + desktop: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "According to the research firm Frost & Sullivan, the estimated size of the North American used test", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c28f984a0b03c2d354b30a4_8xgjqb54cu2.png", + size: 100358, + src: "/files/cms-element-5c28f984a0b03c2d354b30a4_8xgjqb54cu2.png", + type: "image/png", + meta: { width: 1000, height: 492 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/content9.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content9.js new file mode 100644 index 00000000000..5e5c13272dd --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/content9.js @@ -0,0 +1,247 @@ +export default { + id: "5c29048aa0b03c3d5f5e9861", + name: "Content #9", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Webiny ", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + }, + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Content Management System", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 50 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.33, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + animation: { name: "fade-up" } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_user_flow_vr6w_bxbjqb6nqbl.svg", + type: "image/svg+xml", + size: 29770, + src: "/files/undraw_user_flow_vr6w_bxbjqb6nqbl.svg", + width: "250", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + animation: { name: "fade-up", delay: "300" } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_static_assets_rpm6(1)_bxqjqb6nwmz.svg", + type: "image/svg+xml", + size: 36759, + src: "/files/undraw_static_assets_rpm6(1)_bxqjqb6nwmz.svg", + width: "250", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + animation: { name: "fade-up", delay: "600" } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_mobile_browsers_lib5_by2jqb6o1ez.svg", + type: "image/svg+xml", + size: 100300, + src: "/files/undraw_mobile_browsers_lib5_by2jqb6o1ez.svg", + width: "250", + title: "", + alt: "", + height: "", + align: "center" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c29048aa0b03c3d5f5e9861_c4ejqb6sue0.png", + size: 85893, + src: "/files/cms-element-5c29048aa0b03c3d5f5e9861_c4ejqb6sue0.png", + type: "image/png", + meta: { width: 1000, height: 343 } + }, + category: "cms-block-category-content" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature1.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature1.js new file mode 100644 index 00000000000..e79ad1531d1 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature1.js @@ -0,0 +1,669 @@ +export default { + id: "5c2a32f9a0b03c72b4ae8151", + name: "Feature #1", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 1", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 3", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 4", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 5", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 6", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a32f9a0b03c72b4ae8151_mnnjqcgwalx.png", + size: 37445, + src: "/files/cms-element-5c2a32f9a0b03c72b4ae8151_mnnjqcgwalx.png", + type: "image/png", + meta: { width: 1000, height: 330 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature10.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature10.js new file mode 100644 index 00000000000..db9732f2e01 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature10.js @@ -0,0 +1,642 @@ +export default { + id: "5c2a64dea0b03c8409063d4e", + name: "Feature #10", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 50, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 35.69999999999989, + settings: { + animation: { name: "fade" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "X_phyjqcn5v5x.svg", + type: "image/svg+xml", + size: 7286, + src: "/files/X_phyjqcn5v5x.svg", + height: "600", + title: "", + alt: "", + width: "", + align: "center" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 64.3, + settings: { + margin: { + desktop: { all: 0, right: 0, left: 40 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + settings: { + animation: { name: "fade-up", delay: "0" }, + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 15.04, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "start" + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "chrome"], + svg: + '', + color: "rgba(240, 190, 127, 1)", + width: "50" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 84.95999999999998, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 4", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Labore reprehenderit Lorem nostrud ex esse magna sint officia deserunt veniam Lorem consectetur ullamco dolor. Nulla consequat ea exercitation pariatur id. Dolore incididunt ut sint aute." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + animation: { name: "fade-up", delay: "250" }, + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 15.04000000000002, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "start" + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "firefox"], + svg: + '', + color: "rgba(66, 148, 136, 1)", + width: "60" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 84.95999999999998, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 5", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Labore reprehenderit Lorem nostrud ex esse magna sint officia deserunt veniam Lorem consectetur ullamco dolor. Nulla consequat ea exercitation pariatur id. Dolore incididunt ut sint aute." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + animation: { name: "fade-up", delay: "500" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 15.06000000000003, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "safari"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "60" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 84.93999999999997, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 6", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 13 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Do velit culpa cupidatat aliqua veniam occaecat veniam veniam ex. Ex quis eu id dolore. Non aliquip sint dolore ipsum ullamco nisi esse." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a64dea0b03c8409063d4e_q2wjqcoi1u3.png", + size: 115836, + src: "/files/cms-element-5c2a64dea0b03c8409063d4e_q2wjqcoi1u3.png", + type: "image/png", + meta: { width: 1000, height: 604 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature11.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature11.js new file mode 100644 index 00000000000..34c085a107c --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature11.js @@ -0,0 +1,433 @@ +export default { + id: "5c2a66eca0b03c854eec58c9", + name: "Feature #11", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 50, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h4", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Deserunt et magna consequat ullamco exercitation sunt do sunt ipsum anim est duis Lorem. Non ex aliquip commodo adipisicing fugiat aliquip ut sint non pariatur elit. ", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 25.059999999999974, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "start" + } + }, + elements: [ + { + data: { + icon: { + color: "var(--webiny-cms-theme-primary)", + svg: + '', + id: ["fas", "star"], + width: "80" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "justify" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 74.94000000000003, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Consectetur cupidatat incididunt velit velit. Elit incididunt sint magna Lorem elit ex ipsum consequat. Eiusmod eu sit Lorem aliquip non ipsum cillum voluptate deserunt Lorem exercitation.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 75.14000000000003, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Consectetur cupidatat incididunt velit velit. Elit incididunt sint magna Lorem elit ex ipsum consequat. Eiusmod eu sit Lorem aliquip non ipsum cillum voluptate deserunt Lorem exercitation.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 24.859999999999975, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + verticalAlign: "start" + } + }, + elements: [ + { + data: { + icon: { + color: "var(--webiny-cms-theme-secondary)", + svg: + '', + id: ["fas", "map-marker-alt"], + width: "70" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "right" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + animation: { name: "fade" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "X_phyjqcn5v5x.svg", + type: "image/svg+xml", + size: 7286, + src: "/files/X_phyjqcn5v5x.svg", + height: "500", + title: "", + width: "" + }, + settings: { + horizontalAlign: "right", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a66eca0b03c854eec58c9_qbxjqcotbx7.png", + size: 98813, + src: "/files/cms-element-5c2a66eca0b03c854eec58c9_qbxjqcotbx7.png", + type: "image/png", + meta: { width: 1000, height: 519 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature12.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature12.js new file mode 100644 index 00000000000..ccc65e5defa --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature12.js @@ -0,0 +1,516 @@ +export default { + id: "5c2a6a78a0b03c866f58d8f5", + name: "Feature #12", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Webiny CMS", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Occaecat nisi voluptate laborum laborum irure aliquip voluptate dolor aute exercitation exercitation. Voluptate sit deserunt nisi dolor sunt. Consectetur irure ad anim exercitation ea ipsum incididunt voluptate nulla incididunt voluptate." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, top: 0, right: 100, bottom: 0, left: 0 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "bg-1_qfgjqcp2um2.svg", + type: "image/svg+xml", + size: 4745, + src: "/files/bg-1_qfgjqcp2um2.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature One", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nulla eu ullamco occaecat adipisicing pariatur sunt mollit ad eiusmod consequat. Lorem officia ullamco eiusmod duis. Nostrud velit veniam enim ex aliqua.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 50, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "bg-2_qgjjqcp4wvp.svg", + type: "image/svg+xml", + size: 2155, + src: "/files/bg-2_qgjjqcp4wvp.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Two", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nulla eu ullamco occaecat adipisicing pariatur sunt mollit ad eiusmod consequat. Lorem officia ullamco eiusmod duis. Nostrud velit veniam enim ex aliqua.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, left: 100 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "bg-3_qj8jqcpc0ad.svg", + type: "image/svg+xml", + size: 6777, + src: "/files/bg-3_qj8jqcpc0ad.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Three", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nulla eu ullamco occaecat adipisicing pariatur sunt mollit ad eiusmod consequat. Lorem officia ullamco eiusmod duis. Nostrud velit veniam enim ex aliqua.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a6a78a0b03c866f58d8f5_qjyjqcpcsk3.png", + size: 98201, + src: "/files/cms-element-5c2a6a78a0b03c866f58d8f5_qjyjqcpcsk3.png", + type: "image/png", + meta: { width: 1000, height: 465 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature13.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature13.js new file mode 100644 index 00000000000..72bdc8d8843 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature13.js @@ -0,0 +1,640 @@ +export default { + id: "5c2a73b8a0b03c881190553d", + name: "Feature #13", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 25, left: 15, right: 15, bottom: 25 }, + desktop: { top: 100, left: 0, right: 0, bottom: 100 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } }, + background: { image: { src: null } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Webiny CMS", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 20, left: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "4", + vertical: "2", + horizontal: "0", + spread: "2" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-primary)" + } + } + }, + elements: [ + { + data: { + icon: { + id: ["far", "star"], + svg: + '' + }, + settings: { + margin: { + desktop: { all: 0, bottom: 14 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature One", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-primary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 10, left: 10 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "4", + vertical: "2", + horizontal: "0", + spread: "2" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-primary)" + } + } + }, + elements: [ + { + data: { + icon: { + id: ["far", "star"], + svg: + '' + }, + settings: { + margin: { + desktop: { all: 0, bottom: 14 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Two", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-primary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 0, left: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "4", + vertical: "2", + horizontal: "0", + spread: "2" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-primary)" + } + } + }, + elements: [ + { + data: { + icon: { + id: ["far", "star"], + svg: + '' + }, + settings: { + margin: { + desktop: { all: 0, bottom: 14 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Three", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-primary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a73b8a0b03c881190553d_qvkjqcqrjog.png", + size: 53723, + src: "/files/cms-element-5c2a73b8a0b03c881190553d_qvkjqcqrjog.png", + type: "image/png", + meta: { width: 1000, height: 529 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature14.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature14.js new file mode 100644 index 00000000000..4977c1c9286 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature14.js @@ -0,0 +1,656 @@ +export default { + id: "5c2a76bea0b03c89968233ab", + name: "Feature #14", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Webiny CMS", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_mobile_browsers_lib5_r4ajqcr4ofq.svg", + type: "image/svg+xml", + size: 100300, + src: "/files/undraw_mobile_browsers_lib5_r4ajqcr4ofq.svg", + height: "300", + title: "", + width: "" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature One", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Pariatur sit nisi aute sit excepteur ad sunt. Adipisicing elit laborum aute aute in eu magna voluptate labore culpa tempor culpa aliquip reprehenderit. Exercitation aute do cupidatat mollit consectetur qui culpa." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "simple", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, left: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Two", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Pariatur sit nisi aute sit excepteur ad sunt. Adipisicing elit laborum aute aute in eu magna voluptate labore culpa tempor culpa aliquip reprehenderit. Exercitation aute do cupidatat mollit consectetur qui culpa." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "simple", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, right: 0, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlign: "left" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_static_assets_rpm6(1)_r5djqcr6qmb.svg", + type: "image/svg+xml", + size: 36759, + src: "/files/undraw_static_assets_rpm6(1)_r5djqcr6qmb.svg", + height: "300", + title: "", + width: "" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_mobile_life_381t_r5sjqcr7604.svg", + type: "image/svg+xml", + size: 15269, + src: "/files/undraw_mobile_life_381t_r5sjqcr7604.svg", + height: "300", + title: "", + width: "" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature Three", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Pariatur sit nisi aute sit excepteur ad sunt. Adipisicing elit laborum aute aute in eu magna voluptate labore culpa tempor culpa aliquip reprehenderit. Exercitation aute do cupidatat mollit consectetur qui culpa." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "simple", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a76bea0b03c89968233ab_r6djqcr8553.png", + size: 205497, + src: "/files/cms-element-5c2a76bea0b03c89968233ab_r6djqcr8553.png", + type: "image/png", + meta: { width: 1000, height: 988 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature2.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature2.js new file mode 100644 index 00000000000..c8724051ab2 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature2.js @@ -0,0 +1,546 @@ +export default { + id: "5c2a3719a0b03c74cfe743bf", + name: "Feature #2", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 1", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 3", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 4", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a3719a0b03c74cfe743bf_n2mjqchixgn.png", + size: 42476, + src: "/files/cms-element-5c2a3719a0b03c74cfe743bf_n2mjqchixgn.png", + type: "image/png", + meta: { width: 1000, height: 400 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature3.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature3.js new file mode 100644 index 00000000000..b2b4490e15b --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature3.js @@ -0,0 +1,580 @@ +export default { + id: "5c2a3e6da0b03c772f71f2b1", + name: "Feature #3", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 25, left: 15, right: 15, bottom: 25 }, + desktop: { top: 100, left: 0, right: 0, bottom: 100 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } }, + background: { image: { src: "/files/bg-1_n3wjqchkdl4.svg" } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3White", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Webiny CMS", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 20, left: 0 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "2", + vertical: "2", + horizontal: "0" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-secondary)" + } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 1", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-secondary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 10, left: 10 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "2", + vertical: "2", + horizontal: "0" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-secondary)" + } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-secondary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, bottom: 15, right: 0, left: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 15, top: 15, right: 15, bottom: 15, left: 15 } + }, + background: { color: "var(--webiny-cms-theme-surface)" }, + shadow: { + color: "var(--webiny-cms-theme-background)", + blur: "2", + vertical: "2", + horizontal: "0" + }, + border: { + width: 5, + radius: 5, + settings: "solid", + borders: { right: false, bottom: false, left: false }, + color: "var(--webiny-cms-theme-secondary)" + } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "outline-secondary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a3e6da0b03c772f71f2b1_njijqcin4s6.png", + size: 147481, + src: "/files/cms-element-5c2a3e6da0b03c772f71f2b1_njijqcin4s6.png", + type: "image/png", + meta: { width: 1000, height: 478 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature4.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature4.js new file mode 100644 index 00000000000..9fbc12a046a --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature4.js @@ -0,0 +1,725 @@ +export default { + id: "5c2a4063a0b03c79300dbe63", + name: "Feature #4", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_server_status_5pbv_nwijqciww87.svg", + type: "image/svg+xml", + size: 22885, + src: "/files/undraw_server_status_5pbv_nwijqciww87.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 25, + left: 25 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 1", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 25, + left: 25 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 2", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 25, + left: 25 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 3", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 25, + left: 25 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 4", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a4063a0b03c79300dbe63_nxrjqcixwcf.png", + size: 82746, + src: "/files/cms-element-5c2a4063a0b03c79300dbe63_nxrjqcixwcf.png", + type: "image/png", + meta: { width: 1000, height: 448 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature5.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature5.js new file mode 100644 index 00000000000..407a26b713a --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature5.js @@ -0,0 +1,530 @@ +export default { + id: "5c2a4331a0b03c7b862a9470", + name: "Feature #5", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, bottom: 25, right: 25, left: 25 }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 0, + right: 0, + left: 0 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 25, + left: 0 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "left" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 1", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { + all: 0, + bottom: 25, + right: 9, + left: 25 + }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 2", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Aute reprehenderit cupidatat aliqua pariatur sit exercitation exercitation consequat nostrud. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_to_do_list_a49b_od0jqcjbscy.svg", + type: "image/svg+xml", + size: 33363, + src: "/files/undraw_to_do_list_a49b_od0jqcjbscy.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a4331a0b03c7b862a9470_oedjqcjda8o.png", + size: 85456, + src: "/files/cms-element-5c2a4331a0b03c7b862a9470_oedjqcjda8o.png", + type: "image/png", + meta: { width: 1000, height: 395 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature6.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature6.js new file mode 100644 index 00000000000..c20f95b58dc --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature6.js @@ -0,0 +1,468 @@ +export default { + id: "5c2a5816a0b03c7fd639aea1", + name: "Feature #6", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "puzzle-piece"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "48" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Plugins", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button, component or functionality in Webiny is a plugin. Benefits of such a system are that you can fully customize it and extend it to fit your needs.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 10, left: 10 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "sitemap"], + svg: + '', + color: "var(--webiny-cms-theme-primary)" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Page Revisions", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Never lose sight of who changed what. Have a time machine for your content. Be able to go back and restore previous versions of a page, or quickly test between multiple revisions.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, left: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "paint-roller"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "40" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Easy Theming", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 15, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Days of complex template engines, file includes and special variable tags are over. Building a theme for Webiny is nothing more than plain old (S)CSS. For a designer, this means a minimal learning curve.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a5816a0b03c7fd639aea1_p91jqcmjx8v.png", + size: 52481, + src: "/files/cms-element-5c2a5816a0b03c7fd639aea1_p91jqcmjx8v.png", + type: "image/png", + meta: { width: 1000, height: 329 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature7.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature7.js new file mode 100644 index 00000000000..47177d61bb6 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature7.js @@ -0,0 +1,918 @@ +export default { + id: "5c2a5a5aa0b03c807c4797d2", + name: "Feature #7", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "layer-group"], + svg: + '', + color: "rgba(107, 99, 242, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 1", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "map-marker-alt"], + svg: + '', + color: "rgba(236, 110, 82, 1)", + width: "25" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "cloud"], + svg: + '', + color: "rgba(83, 132, 237, 1)", + width: "48" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 3", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "chrome"], + svg: + '', + color: "rgba(244, 194, 67, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 4", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "firefox"], + svg: + '', + color: "rgba(66, 148, 136, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 5", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 10, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "safari"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 23.34, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 6", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a5a5aa0b03c807c4797d2_pdnjqcmwcy4.png", + size: 43373, + src: "/files/cms-element-5c2a5a5aa0b03c807c4797d2_pdnjqcmwcy4.png", + type: "image/png", + meta: { width: 1000, height: 344 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature8.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature8.js new file mode 100644 index 00000000000..0f1dc582433 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature8.js @@ -0,0 +1,846 @@ +export default { + id: "5c2a5beaa0b03c80ecdc05c3", + name: "Feature #8", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Features", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 25 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "layer-group"], + svg: + '', + color: "rgba(107, 99, 242, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 1", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "map-marker-alt"], + svg: + '', + color: "rgba(236, 110, 82, 1)", + width: "25" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 2", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 3, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "cloud"], + svg: + '', + color: "rgba(83, 132, 237, 1)", + width: "48" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 3", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 13 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "chrome"], + svg: + '', + color: "rgba(244, 194, 67, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 4", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "firefox"], + svg: + '', + color: "rgba(66, 148, 136, 1)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlign: "center" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 5", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "safari"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "35" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Feature 6", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 3, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a5beaa0b03c80ecdc05c3_pgrjqcn4xt6.png", + size: 45915, + src: "/files/cms-element-5c2a5beaa0b03c80ecdc05c3_pgrjqcn4xt6.png", + type: "image/png", + meta: { width: 1000, height: 411 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature9.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature9.js new file mode 100644 index 00000000000..3f0eda6425a --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/feature9.js @@ -0,0 +1,1131 @@ +export default { + id: "5c2a617ca0b03c826f4f87b6", + name: "Feature #9", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 50, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + }, + animation: { name: "fade-up" } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "layer-group"], + svg: + '', + color: "rgba(107, 99, 246, 1)", + width: "35" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "right" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 1", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + }, + animation: { name: "fade-up", delay: "250" } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fas", "map-marker-alt"], + svg: + '', + color: "rgba(236, 110, 82, 1)", + width: "25" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "right" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 2", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + animation: { name: "fade-up", delay: "500" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + svg: + '', + id: ["fas", "cloud"], + color: "rgba(83, 132, 237, 1)", + width: "48" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "right" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 3", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 13 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "right" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + animation: { name: "fade" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "X_phyjqcn5v5x.svg", + type: "image/svg+xml", + size: 7286, + src: "/files/X_phyjqcn5v5x.svg" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 33.33, + settings: { + margin: { + desktop: { all: 0, right: 0, left: 40 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + settings: { + animation: { name: "fade-up" }, + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "chrome"], + svg: + '', + color: "rgba(244, 194, 67, 1)", + width: "35" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "left" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 4", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + animation: { name: "fade-up", delay: "250" }, + margin: { + desktop: { all: 0, bottom: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "firefox"], + svg: + '', + color: "rgba(66, 148, 136, 1)", + width: "35" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "justify" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "justify" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 5", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 3, + left: 0, + right: 0, + bottom: 15 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + }, + { + data: { + settings: { + animation: { name: "fade-up", delay: "500" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { + desktop: { all: 0, right: 20 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + icon: { + id: ["fab", "safari"], + svg: + '', + color: "var(--webiny-cms-theme-primary)", + width: "35" + }, + settings: { + margin: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + }, + horizontalAlign: "justify" + } + }, + elements: [], + type: "cms-element-icon" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h6", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Feature 6", + marks: [ + { + object: + "mark", + type: + "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 13 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Nobody likes a closed system, that’s why almost every button.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { + top: 0, + left: 0, + right: 0, + bottom: 15 + }, + desktop: { + top: 0, + left: 0, + right: 0, + bottom: 25 + }, + advanced: true + }, + padding: { + desktop: { all: 0 }, + mobile: { all: 0 } + } + } + }, + elements: [], + type: "cms-element-text" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2a617ca0b03c826f4f87b6_prijqcnzhzs.png", + size: 107579, + src: "/files/cms-element-5c2a617ca0b03c826f4f87b6_prijqcnzhzs.png", + type: "image/png", + meta: { width: 1000, height: 660 } + }, + category: "cms-block-category-features" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header1.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header1.js new file mode 100644 index 00000000000..864748cfa66 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header1.js @@ -0,0 +1,239 @@ +export default { + id: "5c2b5025a0b03caa0e00212d", + name: "Header #1", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 50, left: 0, right: 0, bottom: 50 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h2", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "The Basics Of Renewable Energy", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Amet esse quis enim culpa enim amet sit ex ipsum ea deserunt adipisicing officia. Non reprehenderit proident magna anim irure cillum. Cupidatat fugiat laboris cillum et eiusmod veniam." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { + desktop: { + all: 0, + top: 0, + right: 0, + bottom: 25, + left: 0 + }, + mobile: { all: 0, bottom: 15 }, + advanced: true + }, + border: { + color: "var(--webiny-cms-theme-background)", + width: 1, + radius: 0, + settings: "solid", + borders: { + right: false, + bottom: true, + left: false, + top: false + } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "button", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Learn More", + marks: [] + } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + position: "right", + id: ["fas", "chevron-right"], + svg: + '', + width: "10" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 50, + settings: { + margin: { + desktop: { all: 0, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + image: { + name: "undraw_wind_turbine_x2k4_xkfjqdobeei.svg", + type: "image/svg+xml", + size: 20936, + src: "/files/undraw_wind_turbine_x2k4_xkfjqdobeei.svg" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b5025a0b03caa0e00212d_xl9jqdod0e2.png", + size: 70602, + src: "/files/cms-element-5c2b5025a0b03caa0e00212d_xl9jqdod0e2.png", + type: "image/png", + meta: { width: 1000, height: 428 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header2.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header2.js new file mode 100644 index 00000000000..452c82ea1b2 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header2.js @@ -0,0 +1,219 @@ +export default { + id: "5c2b5f49a0b03cba4b21c45f", + name: "Header #2", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { + mobile: { all: 10 }, + desktop: { all: 0, top: 25, bottom: 25 }, + advanced: true + }, + height: { fullHeight: true, value: "100%" }, + verticalAlign: "center", + horizontalAlignFlex: "center", + background: { + image: { src: "/files/architecture-1846684_1920-min_10lujqdqhae9.png" } + } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + width: { value: "600px" } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h1White", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Hotels How To Get ", + marks: [] + } + ] + } + ] + }, + { + object: "block", + type: "h1White", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Free Gifts", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 0 }, + desktop: { top: 0, left: 0, right: 0, bottom: 0 }, + advanced: true + }, + padding: { + desktop: { + all: 25, + bottom: 25, + top: 25, + right: 25, + left: 25 + }, + mobile: { + all: 15, + top: 15, + right: 15, + bottom: 15, + left: 15 + }, + advanced: false + }, + background: { color: "rgba(0, 0, 0, 0.75)" } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraphWhite", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Complex project management experience. When selecting an offshore software development company, ensure that they have", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { + desktop: { + all: 25, + bottom: 25, + top: 25, + right: 25, + left: 25 + }, + mobile: { + all: 15, + top: 15, + right: 15, + bottom: 15, + left: 15 + }, + advanced: false + }, + background: { color: "rgba(15, 15, 15, 0.75)" } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + image: { + name: "58px_10jrjqdqchjd.svg", + type: "image/svg+xml", + size: 1823, + src: "/files/58px_10jrjqdqchjd.svg", + width: "50", + title: "", + height: "" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b5f49a0b03cba4b21c45f_10sqjqdqo39k.png", + size: 1199469, + src: "/files/cms-element-5c2b5f49a0b03cba4b21c45f_10sqjqdqo39k.png", + type: "image/png", + meta: { width: 1000, height: 597 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header3.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header3.js new file mode 100644 index 00000000000..128d4100452 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header3.js @@ -0,0 +1,237 @@ +export default { + id: "5c2b6193a0b03cbb400dfe6f", + name: "Header #3", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 25, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { mobile: { all: 10 }, desktop: { all: 0 } } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 52.10000000000003, + settings: { + margin: { + desktop: { all: 0, right: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + verticalAlign: "center" + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Using Banner Stands ", + marks: [] + } + ] + } + ] + }, + { + object: "block", + type: "h3", + data: { align: "left" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "to Increase Trade Show Traffic", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "paragraph", + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Commodo sit do enim elit. Veniam fugiat irure occaecat nulla elit do anim enim labore eiusmod veniam est. Incididunt eu do est proident cillum irure ex enim." + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "button", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Play Video", + marks: [] + } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + position: "right", + id: ["fas", "play-circle"], + svg: + '', + width: "14" + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + }, + { + data: { + width: 47.89999999999997, + settings: { + margin: { + desktop: { all: 0, left: 50 }, + mobile: { all: 0 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "X_10yjjqdqyejr.svg", + type: "image/svg+xml", + size: 7286, + src: "/files/X_10yjjqdqyejr.svg", + height: "500", + title: "", + width: "" + }, + settings: { + horizontalAlign: "center", + margin: { + desktop: { all: 0 }, + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + advanced: true + }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b6193a0b03cbb400dfe6f_10zjjqdr0nl2.png", + size: 84406, + src: "/files/cms-element-5c2b6193a0b03cbb400dfe6f_10zjjqdr0nl2.png", + type: "image/png", + meta: { width: 1000, height: 477 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header4.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header4.js new file mode 100644 index 00000000000..e751334142f --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header4.js @@ -0,0 +1,235 @@ +export default { + id: "5c2b69bca0b03cbe22aedc7e", + name: "Header #4", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + mobile: { top: 15, left: 15, right: 15, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 0 }, + advanced: true + }, + padding: { + mobile: { all: 10 }, + desktop: { all: 0, top: 25, bottom: 25 }, + advanced: true + }, + height: { fullHeight: true, value: "100%" }, + verticalAlign: "center", + horizontalAlignFlex: "center", + background: { + image: { src: "/files/background-1462755_1920-min_11b2jqdrh62g.png" } + } + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + width: { value: "650px" } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + animation: { name: "fade-up" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { + desktop: { all: 20, top: 20, right: 20, bottom: 20, left: 20 }, + mobile: { all: 0 } + }, + background: { color: "rgba(255, 255, 255, 0.5)" }, + border: { width: 1, radius: 5 }, + shadow: { + color: "var(--webiny-cms-theme-background)", + horizontal: "2", + vertical: "2", + blur: "34", + spread: "0" + } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h3", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Anatomy or Astrology", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 0 }, + desktop: { top: 0, left: 0, right: 0, bottom: 0 }, + advanced: true + }, + padding: { + desktop: { + all: 25, + bottom: 25, + top: 25, + right: 25, + left: 25 + }, + mobile: { + all: 15, + top: 15, + right: 15, + bottom: 15, + left: 15 + }, + advanced: false + }, + background: { color: "transparent" } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "paragraph", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "If you are in the market for a computer, there are a number of factors", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { + mobile: { top: 0, left: 0, right: 0, bottom: 15 }, + desktop: { top: 0, left: 0, right: 0, bottom: 25 }, + advanced: true + }, + padding: { + desktop: { + all: 25, + bottom: 25, + top: 25, + right: 25, + left: 25 + }, + mobile: { + all: 15, + top: 15, + right: 15, + bottom: 15, + left: 15 + }, + advanced: false + }, + background: { color: "transparent" } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + nodes: [ + { + object: "block", + type: "button", + nodes: [ + { + object: "text", + leaves: [ + { object: "leaf", text: "Click me" } + ] + } + ] + } + ] + } + }, + type: "primary", + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + horizontalAlignFlex: "center" + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b69bca0b03cbe22aedc7e_11k1jqds9fba.png", + size: 980072, + src: "/files/cms-element-5c2b69bca0b03cbe22aedc7e_11k1jqds9fba.png", + type: "image/png", + meta: { width: 1000, height: 597 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header5.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header5.js new file mode 100644 index 00000000000..c9fb11a633a --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header5.js @@ -0,0 +1,236 @@ +export default { + id: "5c2b6f97a0b03cc004e8f774", + name: "Header #5", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + advanced: true, + desktop: { top: 50, bottom: 0 }, + mobile: { top: 15, right: 15, bottom: 15, left: 15 } + }, + verticalAlign: "end" + } + }, + elements: [ + { + data: { settings: { margin: { all: 15 }, padding: { all: 15 } } }, + elements: [ + { + data: { + width: 100, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h1", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "The Glossary Of Telescopes", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h5", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "HubbleSite - Out of the ordinary...out of this world.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { all: 20 }, + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { top: 15, bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Sit sunt adipisicing id ipsum voluptate. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "button", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Play Video", + marks: [] + } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + id: ["fas", "play"], + svg: + '', + position: "right", + width: "12" + }, + settings: { + horizontalAlignFlex: "center", + margin: { + advanced: true, + desktop: { bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-button" + }, + { + data: { + image: { + name: "browser-mock-cutout_11wrjqdt4cav.svg", + type: "image/svg+xml", + size: 3937, + src: "/files/browser-mock-cutout_11wrjqdt4cav.svg" + }, + settings: { + horizontalAlign: "center", + margin: { advanced: true, desktop: { bottom: 0 } } + } + }, + elements: [], + type: "cms-element-image" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b6f97a0b03cc004e8f774_11xfjqdt5jud.png", + size: 98365, + src: "/files/cms-element-5c2b6f97a0b03cc004e8f774_11xfjqdt5jud.png", + type: "image/png", + meta: { width: 1000, height: 720 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/header6.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header6.js new file mode 100644 index 00000000000..a15bc7a250b --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/header6.js @@ -0,0 +1,246 @@ +export default { + id: "5c2b717fa0b03cc06940f946", + name: "Header #6", + type: "block", + content: { + data: { + settings: { + width: { value: "1000px" }, + margin: { + advanced: true, + desktop: { top: 50, bottom: 0 }, + mobile: { top: 15, right: 15, bottom: 15, left: 15 } + }, + verticalAlign: "end" + } + }, + elements: [ + { + data: { + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + width: 100, + settings: { + animation: { name: "fade-up" }, + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [ + { + data: { + image: { + name: "undraw_upload_87y9_11zjjqdtdlou.svg", + type: "image/svg+xml", + size: 49860, + src: "/files/undraw_upload_87y9_11zjjqdtdlou.svg", + height: "400", + title: "", + width: "" + }, + settings: { + horizontalAling: "center", + margin: { advanced: true, desktop: { bottom: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-image" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h1", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "The Glossary Of Telescopes", + marks: [ + { + object: "mark", + type: "bold", + data: {} + } + ] + } + ] + } + ] + } + ] + } + }, + settings: { + margin: { desktop: { all: 0 }, mobile: { all: 0 } }, + padding: { desktop: { all: 0 }, mobile: { all: 0 } } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "h5", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "HubbleSite - Out of the ordinary...out of this world.", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { top: 25, bottom: 25 }, + mobile: { top: 15, bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "description", + data: { align: "center" }, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: + "Sit sunt adipisicing id ipsum voluptate. ", + marks: [] + } + ] + } + ] + } + ] + } + }, + settings: { + padding: { desktop: { all: 0 }, mobile: { all: 0 } }, + margin: { + advanced: true, + desktop: { bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-text" + }, + { + data: { + text: { + object: "value", + document: { + object: "document", + data: {}, + nodes: [ + { + object: "block", + type: "button", + data: {}, + nodes: [ + { + object: "text", + leaves: [ + { + object: "leaf", + text: "Play Video", + marks: [] + } + ] + } + ] + } + ] + } + }, + type: "simple", + icon: { + id: ["fas", "play"], + svg: + '', + position: "right", + width: "12" + }, + settings: { + horizontalAlignFlex: "center", + margin: { + advanced: true, + desktop: { bottom: 25 }, + mobile: { bottom: 15 } + } + } + }, + elements: [], + type: "cms-element-button" + } + ], + type: "cms-element-column" + } + ], + type: "cms-element-row" + } + ], + type: "cms-element-block" + }, + preview: { + name: "cms-element-5c2b717fa0b03cc06940f946_1208jqdtg08a.png", + size: 106768, + src: "/files/cms-element-5c2b717fa0b03cc06940f946_1208jqdtg08a.png", + type: "image/png", + meta: { width: 1000, height: 695 } + }, + category: "cms-block-category-header" +}; diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/58px_10jrjqdqchjd.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/58px_10jrjqdqchjd.svg new file mode 100644 index 00000000000..a3a24d5faf9 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/58px_10jrjqdqchjd.svg @@ -0,0 +1,32 @@ + + + + Buttons / Round / 58px + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/GooglePlay_89rjqb3pati.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/GooglePlay_89rjqb3pati.svg new file mode 100644 index 00000000000..fe60e4b7bfc --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/GooglePlay_89rjqb3pati.svg @@ -0,0 +1,24 @@ + + + + Buttons / Light Text / Store / Google Play + Created with Sketch. + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/Wireframe_136yjq9o84uo.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/Wireframe_136yjq9o84uo.svg new file mode 100644 index 00000000000..ed9c0bd5a9b --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/Wireframe_136yjq9o84uo.svg @@ -0,0 +1,263 @@ + + + + Scene/Wireframe + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_10yjjqdqyejr.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_10yjjqdqyejr.svg new file mode 100644 index 00000000000..b4a4e056978 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_10yjjqdqyejr.svg @@ -0,0 +1,51 @@ + + + + Devices / iPhone / X + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_phyjqcn5v5x.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_phyjqcn5v5x.svg new file mode 100644 index 00000000000..b4a4e056978 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/X_phyjqcn5v5x.svg @@ -0,0 +1,51 @@ + + + + Devices / iPhone / X + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/background-1462755_1920-min_11b2jqdrh62g.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/background-1462755_1920-min_11b2jqdrh62g.png new file mode 100644 index 00000000000..55ae0626eb2 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/background-1462755_1920-min_11b2jqdrh62g.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_3l9jq6iolsj.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_3l9jq6iolsj.svg new file mode 100644 index 00000000000..5777a468489 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_3l9jq6iolsj.svg @@ -0,0 +1,18 @@ + + + + Oval + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_n3wjqchkdl4.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_n3wjqchkdl4.svg new file mode 100644 index 00000000000..be6ba64302e --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-1_n3wjqchkdl4.svg @@ -0,0 +1,30 @@ + + + + bg1 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_k7xjq8418m8.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_k7xjq8418m8.svg new file mode 100644 index 00000000000..6f2297cdfbe --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_k7xjq8418m8.svg @@ -0,0 +1,19 @@ + + + + Oval + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_l3kjqce811p.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_l3kjqce811p.svg new file mode 100644 index 00000000000..2a65c9a81a9 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-2_l3kjqce811p.svg @@ -0,0 +1,17 @@ + + + + bg2 + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_kqzjqcdp19p.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_kqzjqcdp19p.svg new file mode 100644 index 00000000000..86636e28247 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_kqzjqcdp19p.svg @@ -0,0 +1,17 @@ + + + + Oval + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_qj8jqcpc0ad.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_qj8jqcpc0ad.svg new file mode 100644 index 00000000000..97597442be3 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg-3_qj8jqcpc0ad.svg @@ -0,0 +1,34 @@ + + + + bg3 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg1_o7xjq8cvx9o.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg1_o7xjq8cvx9o.svg new file mode 100644 index 00000000000..be6ba64302e --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/bg1_o7xjq8cvx9o.svg @@ -0,0 +1,30 @@ + + + + bg1 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/browser-mock-cutout_11wrjqdt4cav.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/browser-mock-cutout_11wrjqdt4cav.svg new file mode 100644 index 00000000000..6244e3bcc72 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/browser-mock-cutout_11wrjqdt4cav.svg @@ -0,0 +1,42 @@ + + + + Browser mock + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a4f6a0b03cc8a7641802_13mujq9p7qyy.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a4f6a0b03cc8a7641802_13mujq9p7qyy.png new file mode 100644 index 00000000000..2270abddec8 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a4f6a0b03cc8a7641802_13mujq9p7qyy.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a54ca0b03cc8d9e32fcf_13o8jq9p9lnj.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a54ca0b03cc8d9e32fcf_13o8jq9p9lnj.png new file mode 100644 index 00000000000..10070b47afc Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a54ca0b03cc8d9e32fcf_13o8jq9p9lnj.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a580a0b03cc916a07ba7_13pxjq9papfc.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a580a0b03cc916a07ba7_13pxjq9papfc.png new file mode 100644 index 00000000000..2380501e9da Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a580a0b03cc916a07ba7_13pxjq9papfc.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a637a0b03cc957af63d0_13rqjq9pemos.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a637a0b03cc957af63d0_13rqjq9pemos.png new file mode 100644 index 00000000000..cacc4475565 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a637a0b03cc957af63d0_13rqjq9pemos.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a674a0b03cc97f75b0e4_13sujq9pfxjg.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a674a0b03cc97f75b0e4_13sujq9pfxjg.png new file mode 100644 index 00000000000..ed1c44114e4 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a674a0b03cc97f75b0e4_13sujq9pfxjg.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9b0a0b03cca5047aecd_13ynjq9pxoic.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9b0a0b03cca5047aecd_13ynjq9pxoic.png new file mode 100644 index 00000000000..9613a8e98ef Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9b0a0b03cca5047aecd_13ynjq9pxoic.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9f2a0b03cca7a7e097b_13ztjq9pz3ck.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9f2a0b03cca7a7e097b_13ztjq9pz3ck.png new file mode 100644 index 00000000000..7b38a508aa0 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27a9f2a0b03cca7a7e097b_13ztjq9pz3ck.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa25a0b03cca9d24a68b_140sjq9q06nh.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa25a0b03cca9d24a68b_140sjq9q06nh.png new file mode 100644 index 00000000000..eeed6492479 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa25a0b03cca9d24a68b_140sjq9q06nh.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa6da0b03ccad1fc57c2_1428jq9q1qjn.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa6da0b03ccad1fc57c2_1428jq9q1qjn.png new file mode 100644 index 00000000000..62539acc81c Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa6da0b03ccad1fc57c2_1428jq9q1qjn.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa9ba0b03ccaf5c75cc8_6eijqgy10e1.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa9ba0b03ccaf5c75cc8_6eijqgy10e1.png new file mode 100644 index 00000000000..16067ffe636 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aa9ba0b03ccaf5c75cc8_6eijqgy10e1.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aacaa0b03ccb18372e40_1447jq9q3qat.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aacaa0b03ccb18372e40_1447jq9q3qat.png new file mode 100644 index 00000000000..b237834a099 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27aacaa0b03ccb18372e40_1447jq9q3qat.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27c7c6a0b03cd30e21c851_15otjq9uirp1.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27c7c6a0b03cd30e21c851_15otjq9uirp1.png new file mode 100644 index 00000000000..1d9b089e5a5 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c27c7c6a0b03cd30e21c851_15otjq9uirp1.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e1b24527ee1c69754907_5m0jqb1hnhv.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e1b24527ee1c69754907_5m0jqb1hnhv.png new file mode 100644 index 00000000000..8425702f64e Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e1b24527ee1c69754907_5m0jqb1hnhv.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e598a0b03c1e2bf51a03_5yijqb231x8.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e598a0b03c1e2bf51a03_5yijqb231x8.png new file mode 100644 index 00000000000..e83a92d4f84 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28e598a0b03c1e2bf51a03_5yijqb231x8.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28ee3ea0b03c293dcc7a78_858jqb3eic9.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28ee3ea0b03c293dcc7a78_858jqb3eic9.png new file mode 100644 index 00000000000..93d119499c5 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28ee3ea0b03c293dcc7a78_858jqb3eic9.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f1f1a0b03c2a75aa50f3_8dwjqb3yt7t.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f1f1a0b03c2a75aa50f3_8dwjqb3yt7t.png new file mode 100644 index 00000000000..5193108d74a Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f1f1a0b03c2a75aa50f3_8dwjqb3yt7t.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f705a0b03c2c477f3d4d_8qujqb4qo0y.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f705a0b03c2c477f3d4d_8qujqb4qo0y.png new file mode 100644 index 00000000000..158f9b8ed7b Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f705a0b03c2c477f3d4d_8qujqb4qo0y.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f984a0b03c2d354b30a4_8xgjqb54cu2.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f984a0b03c2d354b30a4_8xgjqb54cu2.png new file mode 100644 index 00000000000..4387fc663e5 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c28f984a0b03c2d354b30a4_8xgjqb54cu2.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29048aa0b03c3d5f5e9861_c4ejqb6sue0.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29048aa0b03c3d5f5e9861_c4ejqb6sue0.png new file mode 100644 index 00000000000..dee74efbd74 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29048aa0b03c3d5f5e9861_c4ejqb6sue0.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29075aa0b03c3e562f40a6_cb9jqb78ab6.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29075aa0b03c3e562f40a6_cb9jqb78ab6.png new file mode 100644 index 00000000000..58662b71c17 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c29075aa0b03c3e562f40a6_cb9jqb78ab6.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2918aea0b03c430ebc1e22_d8tjqb9vcvq.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2918aea0b03c430ebc1e22_d8tjqb9vcvq.png new file mode 100644 index 00000000000..fbb99f08c90 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2918aea0b03c430ebc1e22_d8tjqb9vcvq.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a1f70a0b03c6a2d3bc73c_kyzjqcdx3bm.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a1f70a0b03c6a2d3bc73c_kyzjqcdx3bm.png new file mode 100644 index 00000000000..31bc1fe39bb Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a1f70a0b03c6a2d3bc73c_kyzjqcdx3bm.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2363a0b03c6c45b5523b_ldwjqceirwd.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2363a0b03c6c45b5523b_ldwjqceirwd.png new file mode 100644 index 00000000000..a9349fb437b Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2363a0b03c6c45b5523b_ldwjqceirwd.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2a1da0b03c7026ebe52d_m5hjqcfjos6.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2a1da0b03c7026ebe52d_m5hjqcfjos6.png new file mode 100644 index 00000000000..269ea908457 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2a1da0b03c7026ebe52d_m5hjqcfjos6.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2b71a0b03c70b7ce8142_m9ijqcfqykr.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2b71a0b03c70b7ce8142_m9ijqcfqykr.png new file mode 100644 index 00000000000..9e4d9180420 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a2b71a0b03c70b7ce8142_m9ijqcfqykr.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a31e0a0b03c7257e8e1ca_ml2jqcgq9pl.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a31e0a0b03c7257e8e1ca_ml2jqcgq9pl.png new file mode 100644 index 00000000000..9ab072adba1 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a31e0a0b03c7257e8e1ca_ml2jqcgq9pl.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a32f9a0b03c72b4ae8151_mnnjqcgwalx.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a32f9a0b03c72b4ae8151_mnnjqcgwalx.png new file mode 100644 index 00000000000..bd6e4f480c2 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a32f9a0b03c72b4ae8151_mnnjqcgwalx.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3719a0b03c74cfe743bf_n2mjqchixgn.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3719a0b03c74cfe743bf_n2mjqchixgn.png new file mode 100644 index 00000000000..e1d9196de8d Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3719a0b03c74cfe743bf_n2mjqchixgn.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3e6da0b03c772f71f2b1_njijqcin4s6.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3e6da0b03c772f71f2b1_njijqcin4s6.png new file mode 100644 index 00000000000..5c0476e79bc Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a3e6da0b03c772f71f2b1_njijqcin4s6.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4063a0b03c79300dbe63_nxrjqcixwcf.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4063a0b03c79300dbe63_nxrjqcixwcf.png new file mode 100644 index 00000000000..9b734b39397 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4063a0b03c79300dbe63_nxrjqcixwcf.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4331a0b03c7b862a9470_oedjqcjda8o.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4331a0b03c7b862a9470_oedjqcjda8o.png new file mode 100644 index 00000000000..ab3d2df2afb Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a4331a0b03c7b862a9470_oedjqcjda8o.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5816a0b03c7fd639aea1_p91jqcmjx8v.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5816a0b03c7fd639aea1_p91jqcmjx8v.png new file mode 100644 index 00000000000..b35a28bb927 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5816a0b03c7fd639aea1_p91jqcmjx8v.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5a5aa0b03c807c4797d2_pdnjqcmwcy4.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5a5aa0b03c807c4797d2_pdnjqcmwcy4.png new file mode 100644 index 00000000000..9a08c79568b Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5a5aa0b03c807c4797d2_pdnjqcmwcy4.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5beaa0b03c80ecdc05c3_pgrjqcn4xt6.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5beaa0b03c80ecdc05c3_pgrjqcn4xt6.png new file mode 100644 index 00000000000..73f239bec46 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a5beaa0b03c80ecdc05c3_pgrjqcn4xt6.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a617ca0b03c826f4f87b6_prijqcnzhzs.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a617ca0b03c826f4f87b6_prijqcnzhzs.png new file mode 100644 index 00000000000..17b8da10a29 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a617ca0b03c826f4f87b6_prijqcnzhzs.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a64dea0b03c8409063d4e_q2wjqcoi1u3.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a64dea0b03c8409063d4e_q2wjqcoi1u3.png new file mode 100644 index 00000000000..8f91e7200fc Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a64dea0b03c8409063d4e_q2wjqcoi1u3.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a66eca0b03c854eec58c9_qbxjqcotbx7.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a66eca0b03c854eec58c9_qbxjqcotbx7.png new file mode 100644 index 00000000000..ea0376e5f2f Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a66eca0b03c854eec58c9_qbxjqcotbx7.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a6a78a0b03c866f58d8f5_qjyjqcpcsk3.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a6a78a0b03c866f58d8f5_qjyjqcpcsk3.png new file mode 100644 index 00000000000..fd0e4273f9c Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a6a78a0b03c866f58d8f5_qjyjqcpcsk3.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a73b8a0b03c881190553d_qvkjqcqrjog.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a73b8a0b03c881190553d_qvkjqcqrjog.png new file mode 100644 index 00000000000..7e1d56392de Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a73b8a0b03c881190553d_qvkjqcqrjog.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a76bea0b03c89968233ab_r6djqcr8553.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a76bea0b03c89968233ab_r6djqcr8553.png new file mode 100644 index 00000000000..b5696044545 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2a76bea0b03c89968233ab_r6djqcr8553.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5025a0b03caa0e00212d_xl9jqdod0e2.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5025a0b03caa0e00212d_xl9jqdod0e2.png new file mode 100644 index 00000000000..64c4e8ad65e Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5025a0b03caa0e00212d_xl9jqdod0e2.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5f49a0b03cba4b21c45f_10sqjqdqo39k.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5f49a0b03cba4b21c45f_10sqjqdqo39k.png new file mode 100644 index 00000000000..1035eab0c47 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b5f49a0b03cba4b21c45f_10sqjqdqo39k.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6193a0b03cbb400dfe6f_10zjjqdr0nl2.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6193a0b03cbb400dfe6f_10zjjqdr0nl2.png new file mode 100644 index 00000000000..feb37dead17 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6193a0b03cbb400dfe6f_10zjjqdr0nl2.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b69bca0b03cbe22aedc7e_11k1jqds9fba.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b69bca0b03cbe22aedc7e_11k1jqds9fba.png new file mode 100644 index 00000000000..0e7cd2f74e4 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b69bca0b03cbe22aedc7e_11k1jqds9fba.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6f97a0b03cc004e8f774_11xfjqdt5jud.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6f97a0b03cc004e8f774_11xfjqdt5jud.png new file mode 100644 index 00000000000..f2dd3720265 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b6f97a0b03cc004e8f774_11xfjqdt5jud.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b717fa0b03cc06940f946_1208jqdtg08a.png b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b717fa0b03cc06940f946_1208jqdtg08a.png new file mode 100644 index 00000000000..b7281b220b3 Binary files /dev/null and b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/cms-element-5c2b717fa0b03cc06940f946_1208jqdtg08a.png differ diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/hummans-template-1_8vujqb51kzg.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/hummans-template-1_8vujqb51kzg.svg new file mode 100644 index 00000000000..895d6ec0b14 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/hummans-template-1_8vujqb51kzg.svg @@ -0,0 +1,99 @@ + + + + Group 3 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_146fjq9q90jt.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_146fjq9q90jt.svg new file mode 100644 index 00000000000..8ef1e62172d --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_146fjq9q90jt.svg @@ -0,0 +1,27 @@ + + + + Pic + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_15c7jq9tsaag.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_15c7jq9tsaag.svg new file mode 100644 index 00000000000..8ef1e62172d --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_15c7jq9tsaag.svg @@ -0,0 +1,27 @@ + + + + Pic + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_5t1jqb1vbil.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_5t1jqb1vbil.svg new file mode 100644 index 00000000000..8ef1e62172d --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/image-placeholder_5t1jqb1vbil.svg @@ -0,0 +1,27 @@ + + + + Pic + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/phone-desktop_13fojq9otp2v.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/phone-desktop_13fojq9otp2v.svg new file mode 100644 index 00000000000..13877246b39 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/phone-desktop_13fojq9otp2v.svg @@ -0,0 +1,109 @@ + + + + phone-desktop + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/sitting-1_l4ijq87wlrw.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/sitting-1_l4ijq87wlrw.svg new file mode 100644 index 00000000000..36ff6933b80 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/sitting-1_l4ijq87wlrw.svg @@ -0,0 +1,36 @@ + + + + humaaans/sitting-1 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_map_1r69_8ndjqb4ksje.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_map_1r69_8ndjqb4ksje.svg new file mode 100644 index 00000000000..c32971939f9 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_map_1r69_8ndjqb4ksje.svg @@ -0,0 +1 @@ +map \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_meditating_0nae_1dhejqars1z0.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_meditating_0nae_1dhejqars1z0.svg new file mode 100644 index 00000000000..d388e38430c --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_meditating_0nae_1dhejqars1z0.svg @@ -0,0 +1 @@ +meditating \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_browsers_lib5_by2jqb6o1ez.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_browsers_lib5_by2jqb6o1ez.svg new file mode 100644 index 00000000000..4a66fed943d --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_browsers_lib5_by2jqb6o1ez.svg @@ -0,0 +1 @@ +mobile browsers \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_life_381t_r5sjqcr7604.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_life_381t_r5sjqcr7604.svg new file mode 100644 index 00000000000..b5e41ca3ac5 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_mobile_life_381t_r5sjqcr7604.svg @@ -0,0 +1 @@ +mobile life \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_server_status_5pbv_nwijqciww87.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_server_status_5pbv_nwijqciww87.svg new file mode 100644 index 00000000000..37f6157f310 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_server_status_5pbv_nwijqciww87.svg @@ -0,0 +1 @@ +server status \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_to_do_list_a49b_od0jqcjbscy.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_to_do_list_a49b_od0jqcjbscy.svg new file mode 100644 index 00000000000..c0a6138a8a6 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_to_do_list_a49b_od0jqcjbscy.svg @@ -0,0 +1 @@ +to do list \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_upload_87y9_11zjjqdtdlou.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_upload_87y9_11zjjqdtdlou.svg new file mode 100644 index 00000000000..0feab6307d3 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_upload_87y9_11zjjqdtdlou.svg @@ -0,0 +1 @@ +upload \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wind_turbine_x2k4_xkfjqdobeei.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wind_turbine_x2k4_xkfjqdobeei.svg new file mode 100644 index 00000000000..3f299b1a5b6 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wind_turbine_x2k4_xkfjqdobeei.svg @@ -0,0 +1 @@ +wind turbine \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wireframing_nxyi_m4hjqcfh1t9.svg b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wireframing_nxyi_m4hjqcfh1t9.svg new file mode 100644 index 00000000000..12511fbe6be --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/images/undraw_wireframing_nxyi_m4hjqcfh1t9.svg @@ -0,0 +1 @@ +wireframing \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/blocks/index.js b/packages/webiny-api-cms/src/install/plugins/importData/blocks/index.js new file mode 100644 index 00000000000..63d6e9887d4 --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/blocks/index.js @@ -0,0 +1,51 @@ +// @flowIgnore +// NOTE: THIS FILE IS AUTO-GENERATED. MANUAL CHANGES OF THIS FILE WILL BE LOST! + +import callToAction1 from "./callToAction1"; +import callToAction2 from "./callToAction2"; +import callToAction3 from "./callToAction3"; +import callToAction4 from "./callToAction4"; +import callToAction5 from "./callToAction5"; +import callToAction11 from "./callToAction11"; +import callToAction6 from "./callToAction6"; +import callToAction7 from "./callToAction7"; +import callToAction8 from "./callToAction8"; +import callToAction9 from "./callToAction9"; +import callToAction10 from "./callToAction10"; +import content2 from "./content2"; +import content3 from "./content3"; +import content4 from "./content4"; +import content5 from "./content5"; +import content6 from "./content6"; +import content7 from "./content7"; +import content8 from "./content8"; +import content9 from "./content9"; +import content10 from "./content10"; +import content1 from "./content1"; +import content11 from "./content11"; +import content12 from "./content12"; +import content13 from "./content13"; +import content14 from "./content14"; +import content15 from "./content15"; +import feature1 from "./feature1"; +import feature2 from "./feature2"; +import feature3 from "./feature3"; +import feature4 from "./feature4"; +import feature5 from "./feature5"; +import feature6 from "./feature6"; +import feature7 from "./feature7"; +import feature8 from "./feature8"; +import feature9 from "./feature9"; +import feature10 from "./feature10"; +import feature11 from "./feature11"; +import feature12 from "./feature12"; +import feature13 from "./feature13"; +import feature14 from "./feature14"; +import header1 from "./header1"; +import header2 from "./header2"; +import header3 from "./header3"; +import header4 from "./header4"; +import header5 from "./header5"; +import header6 from "./header6"; + +export default [callToAction1, callToAction2, callToAction3, callToAction4, callToAction5, callToAction11, callToAction6, callToAction7, callToAction8, callToAction9, callToAction10, content2, content3, content4, content5, content6, content7, content8, content9, content10, content1, content11, content12, content13, content14, content15, feature1, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10, feature11, feature12, feature13, feature14, header1, header2, header3, header4, header5, header6]; \ No newline at end of file diff --git a/packages/webiny-api-cms/src/install/plugins/importData/createDefaultBlocks.js b/packages/webiny-api-cms/src/install/plugins/importData/createDefaultBlocks.js new file mode 100644 index 00000000000..4787b0fea7b --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/importData/createDefaultBlocks.js @@ -0,0 +1,20 @@ +// @flow +import blocks from "./blocks"; +import fs from "fs-extra"; + +const createDefaultBlocks = async (context: Object) => { + const { Element } = context.cms.entities; + + for (let i = 0; i < blocks.length; i++) { + let data = blocks[i]; + const element = new Element(); + element.populate(data); + await element.save(); + } + + // Copy images. + const pwd: string = (process.cwd(): any); + await fs.copy(`${__dirname}/blocks/images`, pwd + "/static"); +}; + +export default createDefaultBlocks; diff --git a/packages/webiny-api-cms/src/install/importData/createDefaultPages.js b/packages/webiny-api-cms/src/install/plugins/importData/createDefaultPages.js similarity index 71% rename from packages/webiny-api-cms/src/install/importData/createDefaultPages.js rename to packages/webiny-api-cms/src/install/plugins/importData/createDefaultPages.js index f9d04ad203a..c25ef8e3dd4 100644 --- a/packages/webiny-api-cms/src/install/importData/createDefaultPages.js +++ b/packages/webiny-api-cms/src/install/plugins/importData/createDefaultPages.js @@ -11,8 +11,8 @@ const createDefaultPage = async ({ page, data, category }) => { return page; }; -const createDefaultPages = async (context: Object, { categories }: Object) => { - const { Page, CmsSettings } = context.cms.entities; +const createDefaultPages = async (context: Object, { categories, cmsSettings }: Object) => { + const { Page } = context.cms.entities; // Create default pages - demo blog, error, not found and homepage and also assign to settings. const demoBlogPage = new Page(); @@ -22,28 +22,25 @@ const createDefaultPages = async (context: Object, { categories }: Object) => { }); await demoBlogPage.save(); - const cmsSettings = new CmsSettings(); cmsSettings.data = { pages: { - home: await createDefaultPage({ + home: (await createDefaultPage({ page: new Page(), data: homepage, category: categories.static - }), - error: await createDefaultPage({ + })).id, + error: (await createDefaultPage({ page: new Page(), data: error, category: categories.static - }), - notFound: await createDefaultPage({ + })).id, + notFound: (await createDefaultPage({ page: new Page(), data: notFound, category: categories.static - }) + })).id } }; - - await cmsSettings.save(); }; export default createDefaultPages; diff --git a/packages/webiny-api-cms/src/install/importData/staticPages/error.js b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/error.js similarity index 94% rename from packages/webiny-api-cms/src/install/importData/staticPages/error.js rename to packages/webiny-api-cms/src/install/plugins/importData/staticPages/error.js index e3049450c43..82313f72d8c 100644 --- a/packages/webiny-api-cms/src/install/importData/staticPages/error.js +++ b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/error.js @@ -15,12 +15,12 @@ export default { { id: "E0j-dyOuLN", data: {}, - settings: { style: { margin: "15px", padding: "15px" } }, + settings: { style: { margin: { all: 15 }, padding: { all: 15 } } }, elements: [ { id: "iwpwZYraMw", data: { width: 100 }, - settings: { style: { margin: "20px" } }, + settings: { style: { margin: { all: 20 } } }, elements: [ { id: "zACl76J1b", @@ -53,7 +53,7 @@ export default { } } }, - settings: { style: { padding: "20px" } }, + settings: { style: { padding: { all: 20 } } }, elements: [], path: "0.0.0.0.0", type: "cms-element-text" diff --git a/packages/webiny-api-cms/src/install/importData/staticPages/homepage.js b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/homepage.js similarity index 95% rename from packages/webiny-api-cms/src/install/importData/staticPages/homepage.js rename to packages/webiny-api-cms/src/install/plugins/importData/staticPages/homepage.js index a3d72321257..e013b5d1f76 100644 --- a/packages/webiny-api-cms/src/install/importData/staticPages/homepage.js +++ b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/homepage.js @@ -15,12 +15,12 @@ export default { { id: "UZokAR6zY1", data: {}, - settings: { style: { margin: "15px", padding: "15px" } }, + settings: { style: { margin: { all: 15 }, padding: { all: 15 } } }, elements: [ { id: "drTPk0cxrj", data: { width: 100 }, - settings: { style: { margin: "20px" } }, + settings: { style: { margin: { all: 20 } } }, elements: [ { id: "sJdFiErPh", @@ -53,7 +53,7 @@ export default { } } }, - settings: { style: { padding: "20px" } }, + settings: { style: { padding: { all: 20 } } }, elements: [], path: "0.0.0.0.0", type: "cms-element-text" diff --git a/packages/webiny-api-cms/src/install/importData/staticPages/index.js b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/index.js similarity index 100% rename from packages/webiny-api-cms/src/install/importData/staticPages/index.js rename to packages/webiny-api-cms/src/install/plugins/importData/staticPages/index.js diff --git a/packages/webiny-api-cms/src/install/importData/staticPages/notFound.js b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/notFound.js similarity index 94% rename from packages/webiny-api-cms/src/install/importData/staticPages/notFound.js rename to packages/webiny-api-cms/src/install/plugins/importData/staticPages/notFound.js index 38cbcd8440d..b6ba16445e7 100644 --- a/packages/webiny-api-cms/src/install/importData/staticPages/notFound.js +++ b/packages/webiny-api-cms/src/install/plugins/importData/staticPages/notFound.js @@ -15,12 +15,12 @@ export default { { id: "iistOL3GKZ", data: {}, - settings: { style: { margin: "15px", padding: "15px" } }, + settings: { style: { margin: { all: 15 }, padding: { all: 15 } } }, elements: [ { id: "ggMbocBr7D", data: { width: 100 }, - settings: { style: { margin: "20px" } }, + settings: { style: { margin: { all: 20 } } }, elements: [ { id: "JPlQoYwQG", @@ -53,7 +53,7 @@ export default { } } }, - settings: { style: { padding: "20px" } }, + settings: { style: { padding: { all: 20 } } }, elements: [], path: "0.0.0.0.0", type: "cms-element-text" diff --git a/packages/webiny-api-cms/src/install/index.js b/packages/webiny-api-cms/src/install/plugins/index.js similarity index 79% rename from packages/webiny-api-cms/src/install/index.js rename to packages/webiny-api-cms/src/install/plugins/index.js index 860330dfc20..aa7354dc14c 100644 --- a/packages/webiny-api-cms/src/install/index.js +++ b/packages/webiny-api-cms/src/install/plugins/index.js @@ -1,8 +1,6 @@ // @flow -import { addPlugin } from "webiny-plugins"; import { type InstallPluginType } from "webiny-install/types"; - -import plugins from "../plugins"; +import { general, seo, social } from "webiny-api-cms/plugins/pageSettings"; import createMySQLTables from "./createMySQLTables"; import importData from "./importData"; @@ -14,10 +12,9 @@ const plugin: InstallPluginType = { description: "Webiny CMS is a powerful content management system (CMS)." }, install: async context => { - addPlugin(...plugins); await createMySQLTables(); await importData(context); } }; -addPlugin(plugin); +export default [plugin, general, seo, social]; diff --git a/packages/webiny-api-cms/src/install/setupEntities.js b/packages/webiny-api-cms/src/install/plugins/setupEntities.js similarity index 51% rename from packages/webiny-api-cms/src/install/setupEntities.js rename to packages/webiny-api-cms/src/install/plugins/setupEntities.js index 345a9da30ab..b790b5f3528 100644 --- a/packages/webiny-api-cms/src/install/setupEntities.js +++ b/packages/webiny-api-cms/src/install/plugins/setupEntities.js @@ -1,11 +1,11 @@ // @flow -import { categoryFactory } from "./../entities/Category.entity"; -import { menuFactory } from "./../entities/Menu.entity"; -import { pageFactory } from "./../entities/Page.entity"; -import { tagFactory } from "./../entities/Tag.entity"; -import { tags2PagesFactory } from "./../entities/Tags2Pages.entity"; -import { elementFactory } from "./../entities/Element.entity"; -import { cmsSettingsFactory } from "./../entities/CmsSettings.entity"; +import { categoryFactory } from "./../../entities/Category.entity"; +import { menuFactory } from "./../../entities/Menu.entity"; +import { pageFactory } from "./../../entities/Page.entity"; +import { tagFactory } from "./../../entities/Tag.entity"; +import { tags2PagesFactory } from "./../../entities/Tags2Pages.entity"; +import { elementFactory } from "./../../entities/Element.entity"; +import { cmsSettingsFactory } from "./../../entities/CmsSettings.entity"; export default (context: Object) => { context.cms = { entities: {} }; diff --git a/packages/webiny-api-cms/src/install/plugins/tables/index.js b/packages/webiny-api-cms/src/install/plugins/tables/index.js new file mode 100644 index 00000000000..d784693e34a --- /dev/null +++ b/packages/webiny-api-cms/src/install/plugins/tables/index.js @@ -0,0 +1,7 @@ +// @flow +export { default as PageTable } from "../../../entities/Page.mysql"; +export { default as MenuTable } from "../../../entities/Menu.mysql"; +export { default as CategoryTable } from "../../../entities/Category.mysql"; +export { default as TagTable } from "../../../entities/Tag.mysql"; +export { default as Tags2Pages } from "../../../entities/Tags2Pages.mysql"; +export { default as ElementTable } from "../../../entities/Element.mysql"; diff --git a/packages/webiny-api-cms/src/install/tables/mysqlTable.js b/packages/webiny-api-cms/src/install/plugins/tables/mysqlTable.js similarity index 100% rename from packages/webiny-api-cms/src/install/tables/mysqlTable.js rename to packages/webiny-api-cms/src/install/plugins/tables/mysqlTable.js diff --git a/packages/webiny-api-cms/src/install/tables/index.js b/packages/webiny-api-cms/src/install/tables/index.js deleted file mode 100644 index aae5bd326ee..00000000000 --- a/packages/webiny-api-cms/src/install/tables/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @flow -export { default as PageTable } from "../../entities/Page.mysql"; -export { default as MenuTable } from "../../entities/Menu.mysql"; -export { default as CategoryTable } from "../../entities/Category.mysql"; -export { default as TagTable } from "../../entities/Tag.mysql"; -export { default as Tags2Pages } from "../../entities/Tags2Pages.mysql"; -export { default as ElementTable } from "../../entities/Element.mysql"; diff --git a/packages/webiny-api-cms/src/plugins/graphql.js b/packages/webiny-api-cms/src/plugins/graphql.js index d1745cc2e83..0efd3e35a83 100644 --- a/packages/webiny-api-cms/src/plugins/graphql.js +++ b/packages/webiny-api-cms/src/plugins/graphql.js @@ -1,6 +1,7 @@ // @flow import { getPlugins } from "webiny-plugins"; import { dummyResolver } from "webiny-api/graphql"; +import { hasScope } from "webiny-api-security"; import page from "./graphql/Page"; import category from "./graphql/Category"; @@ -49,5 +50,49 @@ export default { menu.resolvers, tag.resolvers, ...getPlugins("cms-schema").map(pl => pl.resolvers) - ] + ], + security: { + shield: { + CmsQuery: { + getMenu: hasScope("cms:menu:crud"), + listMenus: hasScope("cms:menu:crud"), + getTag: hasScope("cms:tag:crud"), + listTags: hasScope("cms:tag:crud"), + getCategory: hasScope("cms:category:crud"), + listCategories: hasScope("cms:category:crud"), + listPages: hasScope("cms:page:crud"), + listElements: hasScope("cms:element:crud"), + oembedData: hasScope("cms:oembed:read") + }, + CmsMutation: { + createMenu: hasScope("cms:menu:crud"), + updateMenu: hasScope("cms:menu:crud"), + deleteMenu: hasScope("cms:menu:crud"), + createTag: hasScope("cms:tag:crud"), + updateTag: hasScope("cms:tag:crud"), + deleteTag: hasScope("cms:tag:crud"), + createCategory: hasScope("cms:category:crud"), + updateCategory: hasScope("cms:category:crud"), + deleteCategory: hasScope("cms:category:crud"), + + createPage: hasScope("cms:page:crud"), + deletePage: hasScope("cms:page:crud"), + + createRevisionFrom: hasScope("cms:page:revision:create"), + updateRevision: hasScope("cms:page:revision:update"), + publishRevision: hasScope("cms:page:revision:publish"), + deleteRevision: hasScope("cms:page:revision:delete"), + + createElement: hasScope("cms:element:crud"), + updateElement: hasScope("cms:element:crud"), + deleteElement: hasScope("cms:element:crud") + }, + SettingsQuery: { + cms: hasScope("cms:settings") + }, + SettingsMutation: { + cms: hasScope("cms:settings") + } + } + } }; diff --git a/packages/webiny-api-cms/src/plugins/graphql/Page.js b/packages/webiny-api-cms/src/plugins/graphql/Page.js index 5f1fc7da43e..91988290a32 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/Page.js +++ b/packages/webiny-api-cms/src/plugins/graphql/Page.js @@ -6,7 +6,8 @@ import { resolveGet, resolveList } from "webiny-api/graphql"; -import UserType from "webiny-api/plugins/graphql/User"; +import { Response } from "webiny-api/graphql/responses"; +import UserType from "webiny-api-security/plugins/graphql/User"; import createRevisionFrom from "./pageResolvers/createRevisionFrom"; import listPages from "./pageResolvers/listPages"; import listPublishedPages from "./pageResolvers/listPublishedPages"; @@ -50,18 +51,23 @@ export default { id: ID name: String type: String - group: String + category: String content: JSON - keywords: [String] preview: File } input ElementInput { name: String! type: String! - group: String + category: String content: JSON! - keywords: [String] + preview: FileInput + } + + input UpdateElementInput { + name: String + category: String + content: JSON preview: FileInput } @@ -128,7 +134,7 @@ export default { sort: String ): PageResponse - getPublishedPage(url: String!): PageResponse + getPublishedPage(id: String, url: String): PageResponse # Returns page set as home page (managed in CMS settings). getHomePage: PageResponse @@ -144,6 +150,7 @@ export default { perPage: Int sort: JSON search: String + parent: String ): PageListResponse listPublishedPages( @@ -155,7 +162,7 @@ export default { perPage: Int ): PageListResponse - listElements: ElementListResponse + listElements(perPage: Int): ElementListResponse oembedData( url: String! @@ -200,10 +207,17 @@ export default { data: ElementInput! ): ElementResponse + updateElement( + id: ID! + data: UpdateElementInput! + ): ElementResponse + # Delete element deleteElement( id: ID! ): DeleteResponse + + updateImageSize: DeleteResponse }, ` ], @@ -211,11 +225,11 @@ export default { CmsQuery: { getPage: resolveGet(pageFetcher), listPages: listPages(pageFetcher), - listPublishedPages: listPublishedPages, - getPublishedPage: getPublishedPage, - getHomePage: getHomePage, - getNotFoundPage: getNotFoundPage, - getErrorPage: getErrorPage, + listPublishedPages, + getPublishedPage, + getHomePage, + getNotFoundPage, + getErrorPage, listElements: resolveList(elementFetcher), oembedData: oembed }, @@ -238,8 +252,19 @@ export default { deleteRevision: resolveDelete(pageFetcher), // Creates a new element createElement: resolveCreate(elementFetcher), + // Updates an element + updateElement: resolveUpdate(elementFetcher), // Deletes an element - deleteElement: resolveDelete(elementFetcher) + deleteElement: resolveDelete(elementFetcher), + /* TODO: remove this resolver before release! */ + updateImageSize: async (_, args, ctx) => { + const Element = ctx.cms.entities.Element; + const elements = await Element.find({ perPage: 100 }); + elements.forEach(async el => { + await el.updateImage(); + }); + return new Response(true); + } }, Page: { createdBy: resolveUser("createdBy"), diff --git a/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/getMenuBySlug.js b/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/getMenuBySlug.js index 8d190ff64b5..aacd1223003 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/getMenuBySlug.js +++ b/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/getMenuBySlug.js @@ -1,6 +1,7 @@ // @flow -import type { Entity } from "webiny-entity"; +import { Entity } from "webiny-entity"; import { Response, ErrorResponse } from "webiny-api/graphql/responses"; +import prepareMenuItems from "./prepareMenuItems"; type EntityFetcher = (context: Object) => Class; @@ -19,5 +20,10 @@ export default (entityFetcher: EntityFetcher) => async ( message: "Menu not found." }); } - return new Response(entity); + + return new Response({ + id: entity.id, + title: entity.title, + items: prepareMenuItems({ entity, context }) + }); }; diff --git a/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/prepareMenuItems.js b/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/prepareMenuItems.js new file mode 100644 index 00000000000..fd876dc0a6e --- /dev/null +++ b/packages/webiny-api-cms/src/plugins/graphql/menuResolvers/prepareMenuItems.js @@ -0,0 +1,133 @@ +// @flow +import { Entity } from "webiny-entity"; +import { cloneDeep } from "lodash"; +import listPublishedPagesSql from "../pageResolvers/listPublishedPages.sql"; + +const applyCleanup = async items => { + if (!Array.isArray(items)) { + return; + } + + for (let i = 0; i < items.length; i++) { + if (items[i].__cleanup__) { + items.splice(i, 1); + i--; + continue; + } + + const { title, children, url, id, type } = items[i]; + items[i] = { title, url, children, id, type }; + + await applyCleanup(items[i].children); + } +}; + +const applyModifier = async ({ items, modifier, context }) => { + if (!Array.isArray(items)) { + return; + } + + for (let i = 0; i < items.length; i++) { + let item = items[i]; + await modifier({ item, context }); + + await applyModifier({ items: item.children, modifier, context }); + } +}; + +const prepareItems = async ({ + items, + modifiers, + context = {} +}: { + items: ?Array, + modifiers: Array, + context?: Object +}) => { + for (let i = 0; i < modifiers.length; i++) { + let modifier = modifiers[i]; + await applyModifier({ items, modifier, context }); + } + + // Cleanup empty items. + await applyCleanup(items); +}; + +export default async ({ entity: menu, context: graphqlContext }: Object) => { + const items = cloneDeep(menu.items); + + // Each modifier is recursively applied to all items. + await prepareItems({ + items, + modifiers: [ + ({ item, context }) => { + switch (item.type) { + case "cms-menu-item-page": { + if (!context.distinctParents) { + context.distinctParents = { + loaded: false, + data: {} + }; + } + + // "item.page" actually represents "parent" value. This is because once we have parent, we can + // more easily load the right child page (we just need to search published pages in this case). + if (Entity.isId(item.page) && !context.distinctParents.data[item.page]) { + context.distinctParents.data[item.page] = null; + } + break; + } + } + }, + async ({ context, item }) => { + switch (item.type) { + case "cms-menu-item-page": { + if (!context.distinctParents.loaded) { + const ids = Object.keys(context.distinctParents.data); + + const sql = await listPublishedPagesSql( + { parent: ids }, + graphqlContext + ); + + await Entity.getDriver() + .getConnection() + .query(sql.query, sql.values) + .then(results => { + for (let i = 0; i < results.length; i++) { + let { title, url, parent: id } = results[i]; + context.distinctParents.data[id] = { id, title, url }; + } + }); + } + + const page = context.distinctParents.data[item.page]; + if (page) { + Object.assign(item, page); + } else { + item.__cleanup__ = true; + } + + break; + } + case "cms-menu-item-page-list": { + const { category, sortBy, sortDir } = item; + + const sql = await listPublishedPagesSql( + { category, sort: { [sortBy]: sortDir } }, + graphqlContext + ); + + item.children = await Entity.getDriver() + .getConnection() + .query(sql.query, sql.values); + + break; + } + } + } + ] + }); + + return items; +}; diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getErrorPage.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getErrorPage.js index fafff0e0c0f..831f63744fe 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getErrorPage.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getErrorPage.js @@ -1,18 +1,10 @@ // @flow -import { Response, ErrorResponse } from "webiny-api/graphql/responses"; +import getPublishedPage from "./getPublishedPage"; export default async (root: any, args: Object, context: Object) => { const { CmsSettings } = context.cms.entities; - const settings = await CmsSettings.load(); - const page = await settings.get("data.pages.error"); - - if (!page) { - return new ErrorResponse({ - code: "NOT_FOUND", - message: "The requested page was not found!" - }); - } + const parent = await settings.get("data.pages.error"); - return new Response(page); + return getPublishedPage(root, { ...args, parent }, context); }; diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getHomePage.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getHomePage.js index 103a4a45659..29f6693a405 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getHomePage.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getHomePage.js @@ -1,18 +1,10 @@ // @flow -import { Response, ErrorResponse } from "webiny-api/graphql/responses"; +import getPublishedPage from "./getPublishedPage"; export default async (root: any, args: Object, context: Object) => { const { CmsSettings } = context.cms.entities; - const settings = await CmsSettings.load(); - const page = await settings.get("data.pages.home"); - - if (!page) { - return new ErrorResponse({ - code: "NOT_FOUND", - message: "The requested page was not found!" - }); - } + const parent = await settings.get("data.pages.home"); - return new Response(page); + return getPublishedPage(root, { ...args, parent }, context); }; diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getNotFoundPage.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getNotFoundPage.js index 2361dba44c6..a2ca53ed938 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getNotFoundPage.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getNotFoundPage.js @@ -1,18 +1,10 @@ // @flow -import { Response, ErrorResponse } from "webiny-api/graphql/responses"; +import getPublishedPage from "./getPublishedPage"; export default async (root: any, args: Object, context: Object) => { const { CmsSettings } = context.cms.entities; - const settings = await CmsSettings.load(); - const page = await settings.get("data.pages.notFound"); - - if (!page) { - return new ErrorResponse({ - code: "NOT_FOUND", - message: "The requested page was not found!" - }); - } + const parent = await settings.get("data.pages.notFound"); - return new Response(page); + return getPublishedPage(root, { ...args, parent }, context); }; diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getPublishedPage.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getPublishedPage.js index b1878accb26..50a1981d4bc 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getPublishedPage.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/getPublishedPage.js @@ -1,10 +1,19 @@ // @flow import { Response, ErrorResponse } from "webiny-api/graphql/responses"; +import listPublishedPagesSql from "./listPublishedPages.sql"; export default async (root: any, args: Object, context: Object) => { - const { Page } = context.cms.entities; + if (!args.parent && !args.url) { + return new ErrorResponse({ + code: "NOT_FOUND", + message: "Page parent or URL missing." + }); + } - const page = await Page.findOne({ query: { published: true, url: args.url } }); + // We utilize the same query used for listing published pages (single source of truth = less maintenance). + const sql = listPublishedPagesSql({ ...args, perPage: 1 }, context); + const { Page } = context.cms.entities; + const [page] = await Page.find({ sql }); if (!page) { return new ErrorResponse({ diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPages.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPages.js index 29bfc7b7faa..adeaa7cefe9 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPages.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPages.js @@ -12,10 +12,15 @@ export default (entityFetcher: EntityFetcher) => async ( ) => { const entityClass = entityFetcher(context); - const { page = 1, perPage = 10, sort = null, search = null } = args; + const { page = 1, perPage = 10, sort = null, search = null, parent = null } = args; const variables = []; let where = "WHERE 1=1"; + if (parent) { + where += ` AND parent = ?`; + variables.push(parent); + } + if (search) { where += ` AND MATCH (title) AGAINST (? IN BOOLEAN MODE)`; variables.push(search); diff --git a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPublishedPages.sql.js b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPublishedPages.sql.js index c2c2bfa7fdb..b5194d563e1 100644 --- a/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPublishedPages.sql.js +++ b/packages/webiny-api-cms/src/plugins/graphql/pageResolvers/listPublishedPages.sql.js @@ -1,33 +1,87 @@ // @flow export default (args: Object, context: Object) => { - const { Page, Category, Tag, Tags2Pages } = context.cms; + const { Page, Category, Tag, Tags2Pages } = context.cms.entities; const { page = 1, perPage = 10, category = null, + parent = null, + id = null, + url = null, sort = null, tags = null, tagsRule = null } = args; - const variables = []; - const categorySlug = !Category.isId(category); + // 1. Tables const tables = [ `${Page.storageClassId} as p`, // If category slug is given, we need to join the table to find the appropriate record category && categorySlug ? `${Category.storageClassId} as c` : null ].filter(Boolean); + // 2. "ORDER BY" + let orderBy = ""; + if (sort && Object.keys(sort).length) { + orderBy = + "ORDER BY " + + Object.keys(sort) + .map(key => `${key} ${sort[key] > 0 ? "ASC" : "DESC"}`) + .join(", "); + } + + // 3. "WHERE" + const tagsOperator = tagsRule === "ALL" ? " AND " : " OR "; + + const where = ["p.published = 1"]; + const variables = []; + + if (parent) { + if (Array.isArray(parent)) { + where.push(`AND p.parent IN (${parent.map(() => "?").join(",")})`); + variables.push(...parent); + } else { + where.push(`AND p.parent = ?`); + variables.push(parent); + } + } + + if (id) { + if (Array.isArray(id)) { + where.push(`AND p.id IN (${id.map(() => "?").join(",")})`); + variables.push(...id); + } else { + where.push(`AND p.id = ?`); + variables.push(id); + } + } + + if (url) { + if (Array.isArray(url)) { + where.push(`AND p.url IN (${url.map(() => "?").join(",")})`); + variables.push(...url); + } else { + where.push(`AND p.url = ?`); + variables.push(url); + } + } + if (category) { variables.push(category); + // If category slug is provided - join and and find by slug. + if (categorySlug) { + where.push(`AND p.category = c.id AND c.slug = ?`); + } else { + // If category ID is provided, we just use the ID directly. + where.push(`AND p.category = ?`); + } } - let tagConditions = null; if (tags && tags.length) { - tagConditions = tags.map((t, i) => { + const tagConditions = tags.map((t, i) => { tables.push(`${Tag.storageClassId} as t${i}`); tables.push(`${Tags2Pages.storageClassId} as t2p${i}`); variables.push(t); @@ -37,40 +91,26 @@ export default (args: Object, context: Object) => { `)` ); }); - } - let orderBy = ""; - if (sort && Object.keys(sort).length) { - orderBy = - "ORDER BY " + - Object.keys(sort) - .map(key => `${key} ${sort[key] > 0 ? "ASC" : "DESC"}`) - .join(", "); + if (tagConditions.length > 0) { + where.push(`AND (${tagConditions.join(tagsOperator)})`); + } } - const tagsOperator = tagsRule === "ALL" ? " AND " : " OR "; let query = [ "SELECT SQL_CALC_FOUND_ROWS p.*", `FROM ${tables.join(", ")}`, - `WHERE 1=1`, - // If category slug is provided - join and and find by slug. - category && categorySlug ? `AND p.category = c.id AND c.slug = ?` : "", - // If category ID is provided, we just use the ID directly. - category && !categorySlug ? `AND p.category = ?` : "", - // Only get published pages. - // `AND p.published = 1`, - tagConditions && tagConditions.length ? `AND (${tagConditions.join(tagsOperator)})` : "", + `WHERE`, + ...where, "GROUP BY p.id", orderBy, "LIMIT ? OFFSET ?" ]; - const sql = { + return { query: query.join(" "), values: [...variables, perPage, (page - 1) * perPage] }; - - return sql; }; /* EXAMPLE OF A FINAL QUERY diff --git a/packages/webiny-api-cms/src/plugins/index.js b/packages/webiny-api-cms/src/plugins/index.js index 77c5792ecc5..02c3c155d1c 100644 --- a/packages/webiny-api-cms/src/plugins/index.js +++ b/packages/webiny-api-cms/src/plugins/index.js @@ -6,4 +6,4 @@ import entities from "./entities"; import settings from "./settings"; import graphql from "./graphql"; -export default [...general, ...seo, ...social, ...entities, graphql, ...settings]; +export default [general, seo, social, entities, graphql, settings]; diff --git a/packages/webiny-api-cms/src/plugins/settings/index.js b/packages/webiny-api-cms/src/plugins/settings/index.js index f8fae5910b4..784fb04e3d6 100644 --- a/packages/webiny-api-cms/src/plugins/settings/index.js +++ b/packages/webiny-api-cms/src/plugins/settings/index.js @@ -7,27 +7,49 @@ export default [ type: "schema-settings", namespace: "cms", typeDefs: /* GraphQL */ ` + type CmsSocialMedia { + facebook: String + twitter: String + instagram: String + } + type CmsSettings { + name: String + favicon: File + logo: File + domain: String + social: CmsSocialMedia pages: CmsSettingsPages } type CmsSettingsPages { - home: CmsDefaultPage - notFound: CmsDefaultPage - error: CmsDefaultPage + home: ID + notFound: ID + error: ID } type CmsDefaultPage { id: String + parent: String title: String } + input CmsSocialMediaInput { + facebook: String + twitter: String + instagram: String + } + input CmsDefaultPageInput { id: String title: String } input CmsSettingsInput { + name: String + favicon: FileInput + logo: FileInput + social: CmsSocialMediaInput pages: CmsSettingsPagesInput } diff --git a/packages/webiny-api-security/.babelrc b/packages/webiny-api-security/.babelrc new file mode 100644 index 00000000000..9f74feaa181 --- /dev/null +++ b/packages/webiny-api-security/.babelrc @@ -0,0 +1,24 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "node": "8.10" + } + }], + "@babel/preset-flow", + "@babel/preset-react" + ], + "plugins": [ + ["@babel/plugin-proposal-object-rest-spread", {"useBuiltIns": true}], + ["@babel/plugin-transform-runtime"], + ["@babel/plugin-proposal-class-properties"], + ["babel-plugin-dynamic-import-node"], + ["babel-plugin-named-asset-import", { + "loaderMap": { + "svg": { + "ReactComponent": "@svgr/webpack![path]" + } + } + }] + ] +} \ No newline at end of file diff --git a/packages/webiny-api-security/LICENSE b/packages/webiny-api-security/LICENSE new file mode 100644 index 00000000000..4ed84603792 --- /dev/null +++ b/packages/webiny-api-security/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Webiny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/webiny-api-security/README.md b/packages/webiny-api-security/README.md new file mode 100644 index 00000000000..d174af05c93 --- /dev/null +++ b/packages/webiny-api-security/README.md @@ -0,0 +1,13 @@ +# Webiny API + +Express middleware to quickly build powerful REST APIs. + +It provides support for running multiple apps, both 3rd party and the ones you create. +In combination with `webiny-entity` library it makes development of business applications a breeze. + +We are developing this with `serverless` in mind so you will not be limited by your server (or the lack of one :)). + +Integration with your existing node apps will also be seamless as long as you support the standard middleware function signature: `(req, res, next)`. + +## Usage +Docs coming before the first official release. diff --git a/packages/webiny-api-security/index.js b/packages/webiny-api-security/index.js new file mode 100644 index 00000000000..990a77ff938 --- /dev/null +++ b/packages/webiny-api-security/index.js @@ -0,0 +1,2 @@ +// @flow +export * from "./src"; diff --git a/packages/webiny-api-security/package.json b/packages/webiny-api-security/package.json new file mode 100644 index 00000000000..acd8a2ae88b --- /dev/null +++ b/packages/webiny-api-security/package.json @@ -0,0 +1,51 @@ +{ + "name": "webiny-api-security", + "version": "0.0.0", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/webiny/webiny-js.git" + }, + "contributors": [ + "Pavel Denisjuk ", + "Sven Al Hamad ", + "Adrian Smijulj " + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "@svgr/webpack": "^4.1.0", + "bcryptjs": "^2.4.3", + "graphql-shield": "^5.1.0", + "invariant": "^2.2.4", + "jsonwebtoken": "^8.2.2", + "lodash": "^4.17.4", + "md5": "^2.2.1", + "webiny-plugins": "0.0.0", + "webiny-sql-table-mysql": "0.0.0", + "webiny-sql-table-sync": "0.0.0" + }, + "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "@babel/preset-flow": "^7.0.0", + "babel-plugin-dynamic-import-node": "^2.0.0" + }, + "optionalDependencies": { + "fsevents": "^1.2.4" + }, + "scripts": { + "build": "babel src -d ${DEST:-build} --source-maps --copy-files", + "flow-copy-source": "flow-copy-source src ${DEST:-build}", + "postbuild": "yarn flow-copy-source" + }, + "svgo": { + "plugins": { + "removeViewBox": false + } + } +} diff --git a/packages/webiny-api/src/entities/File.model.js b/packages/webiny-api-security/src/entities/File.model.js similarity index 100% rename from packages/webiny-api/src/entities/File.model.js rename to packages/webiny-api-security/src/entities/File.model.js diff --git a/packages/webiny-api/src/entities/Group.entity.js b/packages/webiny-api-security/src/entities/Group.entity.js similarity index 78% rename from packages/webiny-api/src/entities/Group.entity.js rename to packages/webiny-api-security/src/entities/Group.entity.js index 093441b0206..5578fbc8b89 100644 --- a/packages/webiny-api/src/entities/Group.entity.js +++ b/packages/webiny-api-security/src/entities/Group.entity.js @@ -6,13 +6,14 @@ export class Group extends Entity { name: string; slug: string; description: string; + system: boolean; roles: Promise>; } Group.classId = "SecurityGroup"; Group.storageClassId = "Security_Groups"; -export function groupFactory({ user = {}, api: { entities } }: Object) { +export function groupFactory({ user = {}, security: { entities } }: Object) { return class extends Group { constructor() { super(); @@ -28,6 +29,7 @@ export function groupFactory({ user = {}, api: { entities } }: Object) { .setOnce(); this.attr("description").char(); + this.attr("system").boolean(); this.attr("roles") .entities(entities.Role, "entity") @@ -39,6 +41,12 @@ export function groupFactory({ user = {}, api: { entities } }: Object) { throw Error(`Group with slug "${this.slug}" already exists.`); } }); + + this.on("beforeDelete", async () => { + if (this.system) { + throw Error(`Cannot delete system role.`); + } + }); } }; } diff --git a/packages/webiny-api/src/entities/Group.mysql.js b/packages/webiny-api-security/src/entities/Group.mysql.js similarity index 84% rename from packages/webiny-api/src/entities/Group.mysql.js rename to packages/webiny-api-security/src/entities/Group.mysql.js index b56bea8c5bd..a5be031b432 100644 --- a/packages/webiny-api/src/entities/Group.mysql.js +++ b/packages/webiny-api-security/src/entities/Group.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "webiny-api"; class Group extends MySQLTable { constructor() { @@ -17,7 +17,6 @@ class Group extends MySQLTable { this.column("slug") .varChar(50) .setNotNull(); - this.column("permissions").text(); } } diff --git a/packages/webiny-api/src/entities/Groups2Entities.entity.js b/packages/webiny-api-security/src/entities/Groups2Entities.entity.js similarity index 88% rename from packages/webiny-api/src/entities/Groups2Entities.entity.js rename to packages/webiny-api-security/src/entities/Groups2Entities.entity.js index 889000d5090..375700c15fe 100644 --- a/packages/webiny-api/src/entities/Groups2Entities.entity.js +++ b/packages/webiny-api-security/src/entities/Groups2Entities.entity.js @@ -11,7 +11,7 @@ export class Groups2Entities extends Entity { Groups2Entities.classId = "SecurityGroups2Entities"; Groups2Entities.storageClassId = "Security_Groups2Entities"; -export function groups2entitiesFactory({ api: { entities } }: Object) { +export function groups2entitiesFactory({ security: { entities } }: Object) { return class extends Groups2Entities { constructor() { super(); diff --git a/packages/webiny-api/src/entities/Groups2Entities.mysql.js b/packages/webiny-api-security/src/entities/Groups2Entities.mysql.js similarity index 79% rename from packages/webiny-api/src/entities/Groups2Entities.mysql.js rename to packages/webiny-api-security/src/entities/Groups2Entities.mysql.js index 07fcf69a147..c1c7d0e9d0f 100644 --- a/packages/webiny-api/src/entities/Groups2Entities.mysql.js +++ b/packages/webiny-api-security/src/entities/Groups2Entities.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "webiny-api"; class Groups2Entities extends MySQLTable { constructor() { @@ -15,4 +15,4 @@ class Groups2Entities extends MySQLTable { Groups2Entities.setName("Security_Groups2Entities"); -export default Groups2Entities; \ No newline at end of file +export default Groups2Entities; diff --git a/packages/webiny-api/src/entities/Role.entity.js b/packages/webiny-api-security/src/entities/Role.entity.js similarity index 82% rename from packages/webiny-api/src/entities/Role.entity.js rename to packages/webiny-api-security/src/entities/Role.entity.js index b31686b1349..8fa7cb57710 100644 --- a/packages/webiny-api/src/entities/Role.entity.js +++ b/packages/webiny-api-security/src/entities/Role.entity.js @@ -5,6 +5,7 @@ export class Role extends Entity { createdBy: ?string; name: string; slug: string; + system: string; description: string; scopes: Array; } @@ -26,6 +27,7 @@ export function roleFactory({ user = {} }: Object) { .setOnce(); this.attr("description").char(); + this.attr("system").boolean(); this.attr("scopes").array(); @@ -36,6 +38,12 @@ export function roleFactory({ user = {} }: Object) { throw Error(`Role with slug "${this.slug}" already exists.`); } }); + + this.on("beforeDelete", async () => { + if (this.system) { + throw Error(`Cannot delete system role.`); + } + }); } }; } diff --git a/packages/webiny-api/src/entities/Role.mysql.js b/packages/webiny-api-security/src/entities/Role.mysql.js similarity index 79% rename from packages/webiny-api/src/entities/Role.mysql.js rename to packages/webiny-api-security/src/entities/Role.mysql.js index 92385469658..3aeb09ce61c 100644 --- a/packages/webiny-api/src/entities/Role.mysql.js +++ b/packages/webiny-api-security/src/entities/Role.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "webiny-api"; class Role extends MySQLTable { constructor() { @@ -11,6 +11,9 @@ class Role extends MySQLTable { this.column("description") .varChar(200) .setNotNull(); + this.column("system") + .tinyInt(1) + .setDefault(0); this.column("slug") .varChar(50) .setNotNull(); diff --git a/packages/webiny-api/src/entities/Roles2Entities.entity.js b/packages/webiny-api-security/src/entities/Roles2Entities.entity.js similarity index 88% rename from packages/webiny-api/src/entities/Roles2Entities.entity.js rename to packages/webiny-api-security/src/entities/Roles2Entities.entity.js index a87d10054df..260016025ca 100644 --- a/packages/webiny-api/src/entities/Roles2Entities.entity.js +++ b/packages/webiny-api-security/src/entities/Roles2Entities.entity.js @@ -11,7 +11,7 @@ export class Roles2Entities extends Entity { Roles2Entities.classId = "SecurityRoles2Entities"; Roles2Entities.storageClassId = "Security_Roles2Entities"; -export function roles2entitiesFactory({ api: { entities } }: Object) { +export function roles2entitiesFactory({ security: { entities } }: Object) { return class extends Roles2Entities { constructor() { super(); diff --git a/packages/webiny-api/src/entities/Roles2Entities.mysql.js b/packages/webiny-api-security/src/entities/Roles2Entities.mysql.js similarity index 87% rename from packages/webiny-api/src/entities/Roles2Entities.mysql.js rename to packages/webiny-api-security/src/entities/Roles2Entities.mysql.js index d1635a32c63..238f83e569a 100644 --- a/packages/webiny-api/src/entities/Roles2Entities.mysql.js +++ b/packages/webiny-api-security/src/entities/Roles2Entities.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "webiny-api"; class Roles2Entities extends MySQLTable { constructor() { diff --git a/packages/webiny-api/src/entities/User.entity.js b/packages/webiny-api-security/src/entities/User.entity.js similarity index 51% rename from packages/webiny-api/src/entities/User.entity.js rename to packages/webiny-api-security/src/entities/User.entity.js index e4d55674848..c94d40544d6 100644 --- a/packages/webiny-api/src/entities/User.entity.js +++ b/packages/webiny-api-security/src/entities/User.entity.js @@ -5,7 +5,12 @@ import { Entity } from "webiny-entity"; import type { Group } from "./Group.entity"; import type { Role } from "./Role.entity"; import FileModel from "./File.model"; -import { loadEntityScopes } from "./utils"; + +type AccessType = { + scopes: Array, + roles: Array, + fullAccess: boolean +}; export class User extends Entity { email: string; @@ -18,15 +23,20 @@ export class User extends Entity { groups: Promise>; roles: Promise>; scopes: Promise>; + access: Promise; } User.classId = "SecurityUser"; User.storageClassId = "Security_Users"; -export function userFactory({ api: { entities } }: Object) { +export function userFactory({ security: { entities } }: Object) { return class extends User { + __access: ?AccessType; constructor() { super(); + // Once we load access attribute, we cache it here. + this.__access = null; + this.attr("email") .char() .setValidators("required,email") @@ -78,10 +88,56 @@ export function userFactory({ api: { entities } }: Object) { .entities(entities.Group, "entity") .setUsing(entities.Groups2Entities, "group"); - this.attr("scopes") - .array() - .setDynamic(() => { - return loadEntityScopes.call(this); + /** + * Returns all scopes and roles. + */ + this.attr("access") + .object() + .setDynamic(async () => { + if (this.__access) { + return this.__access; + } + + const access = { + scopes: [], + roles: [], + fullAccess: false + }; + + const groups = await this.groups; + // Get scopes via `groups` relation + for (let i = 0; i < groups.length; i++) { + const group = groups[i]; + const roles = await group.roles; + for (let j = 0; j < roles.length; j++) { + const role = roles[j]; + !access.roles.includes(role.slug) && access.roles.push(role.slug); + role.scopes.forEach(scope => { + !access.scopes.includes(scope) && access.scopes.push(scope); + }); + } + } + + // Get scopes via `roles` relation + const roles = await this.roles; + for (let j = 0; j < roles.length; j++) { + const role = roles[j]; + !access.roles.includes(role.slug) && access.roles.push(role.slug); + role.scopes.forEach(scope => { + !access.scopes.includes(scope) && access.scopes.push(scope); + }); + } + + // If full access, no need to send any scopes / roles. + access.fullAccess = access.roles.includes("full-access"); + if (access.fullAccess) { + access.scopes = []; + access.roles = []; + } + + this.__access = access; + + return access; }); } }; diff --git a/packages/webiny-api/src/entities/User.mysql.js b/packages/webiny-api-security/src/entities/User.mysql.js similarity index 91% rename from packages/webiny-api/src/entities/User.mysql.js rename to packages/webiny-api-security/src/entities/User.mysql.js index 525fef464d3..245c0eed495 100644 --- a/packages/webiny-api/src/entities/User.mysql.js +++ b/packages/webiny-api-security/src/entities/User.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "webiny-api"; class UserTable extends MySQLTable { constructor() { diff --git a/packages/webiny-api/src/entities/UserSettings.entity.js b/packages/webiny-api-security/src/entities/UserSettings.entity.js similarity index 88% rename from packages/webiny-api/src/entities/UserSettings.entity.js rename to packages/webiny-api-security/src/entities/UserSettings.entity.js index 0ba0eccb282..af04cb3b87c 100644 --- a/packages/webiny-api/src/entities/UserSettings.entity.js +++ b/packages/webiny-api-security/src/entities/UserSettings.entity.js @@ -1,6 +1,6 @@ // @flow import invariant from "invariant"; -import { settingsFactory as Settings } from "./Settings.entity"; +import { settingsFactory as Settings } from "webiny-api/entities/Settings.entity"; export function userSettingsFactory({ user }: Object) { class UserSettings extends Settings({ user }) { diff --git a/packages/webiny-api-security/src/entities/index.js b/packages/webiny-api-security/src/entities/index.js new file mode 100644 index 00000000000..953ee033c9d --- /dev/null +++ b/packages/webiny-api-security/src/entities/index.js @@ -0,0 +1,7 @@ +// @flow +export { userFactory } from "webiny-api-security/entities/User.entity"; +export { groupFactory } from "webiny-api-security/entities/Group.entity"; +export { groups2entitiesFactory } from "webiny-api-security/entities/Groups2Entities.entity"; +export { roleFactory } from "webiny-api-security/entities/Role.entity"; +export { roles2entitiesFactory } from "webiny-api-security/entities/Roles2Entities.entity"; +export { userSettingsFactory } from "webiny-api-security/entities/UserSettings.entity"; diff --git a/packages/webiny-api-security/src/index.js b/packages/webiny-api-security/src/index.js new file mode 100644 index 00000000000..56833037745 --- /dev/null +++ b/packages/webiny-api-security/src/index.js @@ -0,0 +1,2 @@ +// @flow +export * from "./scopes"; diff --git a/packages/webiny-api/src/install/createMySQLTables.js b/packages/webiny-api-security/src/install/plugins/createMySQLTables.js similarity index 70% rename from packages/webiny-api/src/install/createMySQLTables.js rename to packages/webiny-api-security/src/install/plugins/createMySQLTables.js index 8ddf0054381..fc8683887bb 100644 --- a/packages/webiny-api/src/install/createMySQLTables.js +++ b/packages/webiny-api-security/src/install/plugins/createMySQLTables.js @@ -3,12 +3,10 @@ import MySQLTable from "./tables/mysqlTable"; import type { MySQLDriver } from "webiny-sql-table-mysql"; import { Sync } from "webiny-sql-table-sync"; import { - ApiTokenTable, GroupTable, Groups2EntitiesTable, Roles2EntitiesTable, RoleTable, - SettingsTable, UserTable } from "./tables"; @@ -16,15 +14,7 @@ export default async (config: Object) => { const driver: MySQLDriver = (MySQLTable.getDriver(): any); driver.setConnection(config.entity.driver.getConnection()); - const tables = [ - UserTable, - ApiTokenTable, - GroupTable, - RoleTable, - SettingsTable, - Groups2EntitiesTable, - Roles2EntitiesTable - ]; + const tables = [UserTable, GroupTable, RoleTable, Groups2EntitiesTable, Roles2EntitiesTable]; const sync = new Sync({ tables, diff --git a/packages/webiny-api-security/src/install/plugins/data/fullAccessRole.js b/packages/webiny-api-security/src/install/plugins/data/fullAccessRole.js new file mode 100644 index 00000000000..669e78bf22b --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/data/fullAccessRole.js @@ -0,0 +1,9 @@ +// @flow +export default { + name: "Full Access", + slug: "full-access", + system: true, + description: + "This role gives full access to all available resources. Be careful to whom you assign this role!", + scopes: [] +}; diff --git a/packages/webiny-api-security/src/install/plugins/data/index.js b/packages/webiny-api-security/src/install/plugins/data/index.js new file mode 100644 index 00000000000..3cdb9c65531 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/data/index.js @@ -0,0 +1,5 @@ +// @flow +export { default as securityFullAccessGroup } from "./securityFullAccessGroup"; +export { default as fullAccessRole } from "./fullAccessRole"; +export { default as superAdminUser } from "./superAdminUser"; +export { default as roles } from "./roles"; diff --git a/packages/webiny-api-security/src/install/plugins/data/roles.js b/packages/webiny-api-security/src/install/plugins/data/roles.js new file mode 100644 index 00000000000..d476eb2eb24 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/data/roles.js @@ -0,0 +1,24 @@ +// @flow +export default [ + { + name: "Security - Roles", + description: "Allows management of roles.", + slug: "security-roles", + scopes: ["security:role:crud"], + system: true + }, + { + name: "Security - Groups", + description: "Allows management of groups.", + slug: "security-groups", + scopes: ["security:group:crud"], + system: true + }, + { + name: "Security - Users", + description: "Allows management of users.", + slug: "security-users", + scopes: ["security:user:crud"], + system: true + } +]; diff --git a/packages/webiny-api-security/src/install/plugins/data/securityFullAccessGroup.js b/packages/webiny-api-security/src/install/plugins/data/securityFullAccessGroup.js new file mode 100644 index 00000000000..2acee28f903 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/data/securityFullAccessGroup.js @@ -0,0 +1,7 @@ +// @flow +export default { + name: "Security - Full Access", + description: "Grants access to users, roles and groups.", + system: true, + slug: "security-full-access" +}; diff --git a/packages/webiny-api-security/src/install/plugins/data/superAdminUser.js b/packages/webiny-api-security/src/install/plugins/data/superAdminUser.js new file mode 100644 index 00000000000..0fd05471a46 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/data/superAdminUser.js @@ -0,0 +1,7 @@ +// @flow +export default { + firstName: "John", + lastName: "Doe", + password: "12345678", + email: "admin@webiny.com" +}; diff --git a/packages/webiny-api-security/src/install/plugins/importData.js b/packages/webiny-api-security/src/install/plugins/importData.js new file mode 100644 index 00000000000..50db6b311c0 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/importData.js @@ -0,0 +1,20 @@ +// @flow +import setupEntities from "./setupEntities"; +import * as data from "./data"; + +export default async (context: Object) => { + setupEntities(context); + const { User, Role, Group } = context.security.entities; + + const user = new User(); + + const fullAccess = new Role(); + await fullAccess.populate(data.fullAccessRole).save(); + + await user.populate({ ...data.superAdminUser, roles: [fullAccess] }).save(); + + context.user = user; + + const group = new Group(); + await group.populate({ ...data.securityFullAccessGroup, roles: data.roles }).save(); +}; diff --git a/packages/webiny-api/src/install/index.js b/packages/webiny-api-security/src/install/plugins/index.js similarity index 77% rename from packages/webiny-api/src/install/index.js rename to packages/webiny-api-security/src/install/plugins/index.js index d85ca812b4f..2119bbe2661 100644 --- a/packages/webiny-api/src/install/index.js +++ b/packages/webiny-api-security/src/install/plugins/index.js @@ -2,15 +2,14 @@ import { Entity } from "webiny-entity"; import createMySQLTables from "./createMySQLTables"; import importData from "./importData"; -import { addPlugin } from "webiny-plugins"; import { type InstallPluginType } from "webiny-install/types"; const plugin: InstallPluginType = { type: "install", - name: "install-api", + name: "install-security", meta: { - name: "Webiny API", - description: "Foundation of the Webiny platform." + name: "Webiny Security", + description: "A complete layer for securing your app / GraphQL." }, install: async context => { const { config } = context; @@ -26,4 +25,4 @@ const plugin: InstallPluginType = { } }; -addPlugin(plugin); +export default [plugin]; diff --git a/packages/webiny-api-security/src/install/plugins/setupEntities.js b/packages/webiny-api-security/src/install/plugins/setupEntities.js new file mode 100644 index 00000000000..329f6bfb860 --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/setupEntities.js @@ -0,0 +1,17 @@ +// @flow +import { userFactory } from "./../../entities/User.entity"; +import { groupFactory } from "./../../entities/Group.entity"; +import { groups2entitiesFactory } from "./../../entities/Groups2Entities.entity"; +import { roleFactory } from "./../../entities/Role.entity"; +import { roles2entitiesFactory } from "./../../entities/Roles2Entities.entity"; +import { userSettingsFactory } from "./../../entities/UserSettings.entity"; + +export default (context: Object) => { + context.security = { entities: {} }; + context.security.entities.User = userFactory(context); + context.security.entities.Group = groupFactory(context); + context.security.entities.Role = roleFactory(context); + context.security.entities.Groups2Entities = groups2entitiesFactory(context); + context.security.entities.Roles2Entities = roles2entitiesFactory(context); + context.security.entities.UserSettings = userSettingsFactory(context); +}; diff --git a/packages/webiny-api-security/src/install/plugins/tables/index.js b/packages/webiny-api-security/src/install/plugins/tables/index.js new file mode 100644 index 00000000000..b19f1b2f61a --- /dev/null +++ b/packages/webiny-api-security/src/install/plugins/tables/index.js @@ -0,0 +1,6 @@ +// @flow +export { default as GroupTable } from "../../../entities/Group.mysql"; +export { default as Groups2EntitiesTable } from "../../../entities/Groups2Entities.mysql"; +export { default as RoleTable } from "../../../entities/Role.mysql"; +export { default as Roles2EntitiesTable } from "../../../entities/Roles2Entities.mysql"; +export { default as UserTable } from "../../../entities/User.mysql"; diff --git a/packages/webiny-api/src/install/tables/mysqlTable.js b/packages/webiny-api-security/src/install/plugins/tables/mysqlTable.js similarity index 53% rename from packages/webiny-api/src/install/tables/mysqlTable.js rename to packages/webiny-api-security/src/install/plugins/tables/mysqlTable.js index 87497864a33..0a67edd01e6 100644 --- a/packages/webiny-api/src/install/tables/mysqlTable.js +++ b/packages/webiny-api-security/src/install/plugins/tables/mysqlTable.js @@ -1,4 +1,4 @@ // @flow -import { MySQLTable as BaseMySQLTable } from "../.."; +import { MySQLTable as BaseMySQLTable } from "webiny-api"; export default class MySQLTable extends BaseMySQLTable {} diff --git a/packages/webiny-api/src/lambda/authenticate.js b/packages/webiny-api-security/src/plugins/authentication/authenticate.js similarity index 75% rename from packages/webiny-api/src/lambda/authenticate.js rename to packages/webiny-api-security/src/plugins/authentication/authenticate.js index 862f981bc04..ba28ebe6fd5 100644 --- a/packages/webiny-api/src/lambda/authenticate.js +++ b/packages/webiny-api-security/src/plugins/authentication/authenticate.js @@ -1,9 +1,7 @@ // @flow -import { JwtToken } from "../security/jwtToken"; +import { JwtToken } from "./jwtToken"; export default async (config: Object, event: Object, context: Object) => { - // Try decoding JWT - // We must do it here since `ApolloServer` does not allow an async context function let token = (event.headers.Authorization || "").replace("Bearer ", ""); let user = null; if (token !== "" && event.httpMethod === "POST") { diff --git a/packages/webiny-api-security/src/plugins/authentication/index.js b/packages/webiny-api-security/src/plugins/authentication/index.js new file mode 100644 index 00000000000..be5318de4e4 --- /dev/null +++ b/packages/webiny-api-security/src/plugins/authentication/index.js @@ -0,0 +1,3 @@ +// @flow +export { default as authenticate } from "./authenticate"; +export { JwtTokenError, JwtToken } from "./jwtToken"; diff --git a/packages/webiny-api/src/security/jwtToken.js b/packages/webiny-api-security/src/plugins/authentication/jwtToken.js similarity index 100% rename from packages/webiny-api/src/security/jwtToken.js rename to packages/webiny-api-security/src/plugins/authentication/jwtToken.js diff --git a/packages/webiny-api-security/src/plugins/entities.js b/packages/webiny-api-security/src/plugins/entities.js new file mode 100644 index 00000000000..9254153914c --- /dev/null +++ b/packages/webiny-api-security/src/plugins/entities.js @@ -0,0 +1,65 @@ +// @flow +import { type EntityPluginType } from "webiny-api/types"; +import * as entities from "webiny-api-security/entities"; + +const group: EntityPluginType = { + name: "entity-group", + type: "entity", + namespace: "security", + entity: { + name: "Group", + factory: entities.groupFactory + } +}; + +const groups2entities: EntityPluginType = { + name: "entity-groups-2-entities", + type: "entity", + namespace: "security", + entity: { + name: "Groups2Entities", + factory: entities.groups2entitiesFactory + } +}; + +const role: EntityPluginType = { + name: "entity-role", + type: "entity", + namespace: "security", + entity: { + name: "Role", + factory: entities.roleFactory + } +}; + +const roles2entities: EntityPluginType = { + name: "entity-roles-2-entities", + type: "entity", + namespace: "security", + entity: { + name: "Roles2Entities", + factory: entities.roles2entitiesFactory + } +}; + +const user: EntityPluginType = { + name: "entity-user", + type: "entity", + namespace: "security", + entity: { + name: "User", + factory: entities.userFactory + } +}; + +const userSettings: EntityPluginType = { + name: "entity-user-settings", + type: "entity", + namespace: "security", + entity: { + name: "UserSettings", + factory: entities.userSettingsFactory + } +}; + +export default [group, groups2entities, role, roles2entities, user, userSettings]; diff --git a/packages/webiny-api-security/src/plugins/graphql.js b/packages/webiny-api-security/src/plugins/graphql.js new file mode 100644 index 00000000000..4dc657726ac --- /dev/null +++ b/packages/webiny-api-security/src/plugins/graphql.js @@ -0,0 +1,80 @@ +// @flow +import { dummyResolver } from "webiny-api/graphql"; +import role from "./graphql/Role"; +import group from "./graphql/Group"; +import user from "./graphql/User"; +import { type PluginType } from "webiny-api/types"; +import { getRegisteredScopes, hasScope } from "webiny-api-security"; + +export default ([ + { + type: "graphql", + name: "graphql-security", + namespace: "security", + typeDefs: () => [ + user.typeDefs, + user.typeExtensions, + role.typeDefs, + role.typeExtensions, + group.typeDefs, + group.typeExtensions, + /* GraphQL */ ` + type SecurityQuery { + # Returns all scopes that were registered throughout the schema. + scopes: [String] + } + + type SecurityMutation { + _empty: String + } + + type Query { + security: SecurityQuery + } + + type Mutation { + security: SecurityMutation + } + ` + ], + resolvers: () => [ + { + Query: { + security: dummyResolver + }, + Mutation: { + security: dummyResolver + }, + SecurityQuery: { + scopes: getRegisteredScopes + } + }, + group.resolvers, + role.resolvers, + user.resolvers + ], + security: { + shield: { + SecurityQuery: { + getGroup: hasScope("security:group:crud"), + listGroups: hasScope("security:group:crud"), + getRole: hasScope("security:role:crud"), + listRoles: hasScope("security:role:crud"), + getUser: hasScope("security:user:crud"), + listUsers: hasScope("security:user:crud") + }, + SecurityMutation: { + createGroup: hasScope("security:group:crud"), + updateGroup: hasScope("security:group:crud"), + deleteGroup: hasScope("security:group:crud"), + createRole: hasScope("security:role:crud"), + updateRole: hasScope("security:role:crud"), + deleteRole: hasScope("security:role:crud"), + createUser: hasScope("security:user:crud"), + updateUser: hasScope("security:user:crud"), + deleteUser: hasScope("security:user:crud") + } + } + } + } +]: Array); diff --git a/packages/webiny-api/src/plugins/graphql/Group.js b/packages/webiny-api-security/src/plugins/graphql/Group.js similarity index 97% rename from packages/webiny-api/src/plugins/graphql/Group.js rename to packages/webiny-api-security/src/plugins/graphql/Group.js index 6232bbcf55d..8ebb09fafc1 100644 --- a/packages/webiny-api/src/plugins/graphql/Group.js +++ b/packages/webiny-api-security/src/plugins/graphql/Group.js @@ -9,7 +9,7 @@ import { import Role from "./Role"; -const groupFetcher = ctx => ctx.api.entities.Group; +const groupFetcher = ctx => ctx.security.entities.Group; export default { typeDefs: () => [ diff --git a/packages/webiny-api/src/plugins/graphql/Role.js b/packages/webiny-api-security/src/plugins/graphql/Role.js similarity index 97% rename from packages/webiny-api/src/plugins/graphql/Role.js rename to packages/webiny-api-security/src/plugins/graphql/Role.js index c51b3410bce..7e997938749 100644 --- a/packages/webiny-api/src/plugins/graphql/Role.js +++ b/packages/webiny-api-security/src/plugins/graphql/Role.js @@ -7,7 +7,7 @@ import { resolveUpdate } from "webiny-api/graphql"; -const roleFetcher = ctx => ctx.api.entities.Role; +const roleFetcher = ctx => ctx.security.entities.Role; export default { typeDefs: () => [ diff --git a/packages/webiny-api/src/plugins/graphql/User.js b/packages/webiny-api-security/src/plugins/graphql/User.js similarity index 56% rename from packages/webiny-api/src/plugins/graphql/User.js rename to packages/webiny-api-security/src/plugins/graphql/User.js index 6d534bb0bc8..8ada1fe12e6 100644 --- a/packages/webiny-api/src/plugins/graphql/User.js +++ b/packages/webiny-api-security/src/plugins/graphql/User.js @@ -13,8 +13,8 @@ import resolveUpdateCurrentUser from "./userResolvers/updateCurrentUser"; import resolveGetCurrentUserSettings from "./userResolvers/getCurrentUserSettings"; import resolveUpdateCurrentUserSettings from "./userResolvers/updateCurrentUserSettings"; -const userFetcher = ctx => ctx.api.entities.User; -const userSettingsFetcher = ctx => ctx.api.entities.UserSettings; +const userFetcher = ctx => ctx.security.entities.User; +const userSettingsFetcher = ctx => ctx.security.entities.UserSettings; import Role from "./Role"; import Group from "./Group"; @@ -23,85 +23,85 @@ export default { typeDefs: () => [ Role.typeDefs, Group.typeDefs, + /* GraphQL */ ` + type Avatar { + name: String + size: Int + type: String + src: String + } + + type UserLogin { + token: String + expiresOn: Int + user: User + } + + type UserAccess { + scopes: [String] + roles: [String] + fullAccess: Boolean + } + + type User { + id: ID + email: String + firstName: String + lastName: String + fullName: String + gravatar: String + avatar: File + enabled: Boolean + groups: [Group] + roles: [Role] + scopes: [String] + access: UserAccess + createdOn: DateTime + } + + # Contains user settings by specific key, ex: search-filters. + type UserSettings { + key: String + data: JSON + } + + # This input type is used by administrators to update other user's accounts + input UserInput { + email: String + password: String + firstName: String + lastName: String + avatar: FileInput + enabled: Boolean + groups: [ID] + roles: [ID] + } + + # This input type is used by the user who is updating his own account + input CurrentUserInput { + email: String + firstName: String + lastName: String + avatar: FileInput + password: String + } + + type UserResponse { + data: User + error: Error + } + + type UserListResponse { + data: [User] + meta: ListMeta + error: Error + } + + type UserLoginResponse { + data: UserLogin + error: Error + } ` - type Avatar { - name: String - size: Int - type: String - src: String - } - - input AvatarInput { - name: String - size: Int - type: String - src: String - } - - type UserLogin { - token: String - expiresOn: Int - user: User - } - - type User { - id: ID - email: String - firstName: String - lastName: String - fullName: String - gravatar: String - avatar: Avatar - enabled: Boolean - groups: [Group] - roles: [Role] - scopes: [String] - createdOn: DateTime - } - - "Contains user settings by specific key, ex: search-filters." - type UserSettings { - key: String - data: JSON - } - - # This input type is used by administrators to update other user's accounts - input UserInput { - email: String - password: String - firstName: String - lastName: String - avatar: AvatarInput - enabled: Boolean - groups: [ID] - roles: [ID] - } - - # This input type is used by the user who is updating his own account - input CurrentUserInput { - email: String - firstName: String - lastName: String - avatar: AvatarInput - password: String - } - - type UserResponse { - data: User - error: Error - } - - type UserListResponse { - data: [User] - meta: ListMeta - error: Error - } - - type UserLoginResponse { - data: UserLogin - error: Error - } - ` ], typeExtensions: ` extend type SecurityQuery { diff --git a/packages/webiny-api/src/plugins/graphql/userResolvers/getCurrentUser.js b/packages/webiny-api-security/src/plugins/graphql/userResolvers/getCurrentUser.js similarity index 100% rename from packages/webiny-api/src/plugins/graphql/userResolvers/getCurrentUser.js rename to packages/webiny-api-security/src/plugins/graphql/userResolvers/getCurrentUser.js diff --git a/packages/webiny-api/src/plugins/graphql/userResolvers/getCurrentUserSettings.js b/packages/webiny-api-security/src/plugins/graphql/userResolvers/getCurrentUserSettings.js similarity index 100% rename from packages/webiny-api/src/plugins/graphql/userResolvers/getCurrentUserSettings.js rename to packages/webiny-api-security/src/plugins/graphql/userResolvers/getCurrentUserSettings.js diff --git a/packages/webiny-api/src/plugins/graphql/userResolvers/loginUser.js b/packages/webiny-api-security/src/plugins/graphql/userResolvers/loginUser.js similarity index 88% rename from packages/webiny-api/src/plugins/graphql/userResolvers/loginUser.js rename to packages/webiny-api-security/src/plugins/graphql/userResolvers/loginUser.js index 0114396aab9..2d753a12e69 100644 --- a/packages/webiny-api/src/plugins/graphql/userResolvers/loginUser.js +++ b/packages/webiny-api-security/src/plugins/graphql/userResolvers/loginUser.js @@ -2,7 +2,7 @@ import bcrypt from "bcryptjs"; import util from "util"; import { Response, ErrorResponse } from "webiny-api/graphql"; -import { JwtToken } from "../../../security/jwtToken"; +import { JwtToken } from "../../authentication/jwtToken"; import type { Entity } from "webiny-entity"; type EntityFetcher = (context: Object) => Class; @@ -40,9 +40,14 @@ export default (entityFetcher: EntityFetcher) => async ( } const jwt = new JwtToken({ secret: context.config.security.token.secret }); + const access = await user.access; const token = await jwt.encode( // $FlowFixMe - instance that will be validated will have "password" attribute. - { id: user.id, type: "user", scopes: await user.scopes }, + { + id: user.id, + type: "user", + access + }, // 2147483647 = maximum value of unix timestamp (year 2038). 2147483647 ); diff --git a/packages/webiny-api/src/plugins/graphql/userResolvers/updateCurrentUser.js b/packages/webiny-api-security/src/plugins/graphql/userResolvers/updateCurrentUser.js similarity index 100% rename from packages/webiny-api/src/plugins/graphql/userResolvers/updateCurrentUser.js rename to packages/webiny-api-security/src/plugins/graphql/userResolvers/updateCurrentUser.js diff --git a/packages/webiny-api/src/plugins/graphql/userResolvers/updateCurrentUserSettings.js b/packages/webiny-api-security/src/plugins/graphql/userResolvers/updateCurrentUserSettings.js similarity index 100% rename from packages/webiny-api/src/plugins/graphql/userResolvers/updateCurrentUserSettings.js rename to packages/webiny-api-security/src/plugins/graphql/userResolvers/updateCurrentUserSettings.js diff --git a/packages/webiny-api-security/src/plugins/index.js b/packages/webiny-api-security/src/plugins/index.js new file mode 100644 index 00000000000..bf7ce14396c --- /dev/null +++ b/packages/webiny-api-security/src/plugins/index.js @@ -0,0 +1,6 @@ +// @flow +import entities from "./entities"; +import graphql from "./graphql"; +import security from "./security"; + +export default [entities, graphql, security]; diff --git a/packages/webiny-api-security/src/plugins/security.js b/packages/webiny-api-security/src/plugins/security.js new file mode 100644 index 00000000000..d23c6742846 --- /dev/null +++ b/packages/webiny-api-security/src/plugins/security.js @@ -0,0 +1,37 @@ +// @flow +import type { PluginType } from "webiny-plugins/types"; +import authenticate from "./authentication/authenticate"; +import { getPlugins } from "webiny-plugins"; +import { shield } from "graphql-shield"; +import { get } from "lodash"; + +export default ([ + { + type: "graphql-middleware", + name: "graphql-middleware-shield", + middleware: ({ config }) => { + // If "security.enabled" was set to false, only then we exit. + if (get(config, "security.enabled") === false) { + return []; + } + + const middleware = []; + getPlugins("graphql").forEach(plugin => { + const { security } = plugin; + if (!security) { + return true; + } + + security.shield && + middleware.push( + shield(security.shield, { + debug: true + }) + ); + }); + + return middleware; + } + }, + { type: "security", name: "security", authenticate } +]: Array); diff --git a/packages/webiny-api-security/src/scopes.js b/packages/webiny-api-security/src/scopes.js new file mode 100644 index 00000000000..912a018df5b --- /dev/null +++ b/packages/webiny-api-security/src/scopes.js @@ -0,0 +1,52 @@ +// @flow +import { rule } from "graphql-shield"; +/** + * Contains a list of all registered scopes throughout GraphQL Schema. + * @type {Array} + */ +export const __scopes = ({ + registered: [] +}: { + registered: Array +}); + +export const hasScope = (scope: string) => { + registerScopes(scope); + return rule()(async (parent, args, ctx) => { + if (!ctx.user) { + return false; + } + + const access = await ctx.user.access; + if (access.fullAccess) { + return true; + } + + return access.scopes.includes(scope); + }); +}; + +export const hasRole = (role: string) => { + return rule()(async (parent, args, ctx) => { + if (!ctx.user) { + return false; + } + + const access = await ctx.user.access; + if (access.fullAccess) { + return true; + } + + return access.roles.includes(role); + }); +}; + +export const registerScopes = (...scopes: Array) => { + scopes.forEach(scope => { + __scopes.registered.includes(scope) === false && __scopes.registered.push(scope); + }); +}; + +export const getRegisteredScopes = () => { + return __scopes.registered; +}; diff --git a/packages/webiny-api-security/src/types.js b/packages/webiny-api-security/src/types.js new file mode 100644 index 00000000000..5250b4ba572 --- /dev/null +++ b/packages/webiny-api-security/src/types.js @@ -0,0 +1,6 @@ +// @flow +import type { PluginType } from "webiny-plugins/types"; + +export type SecurityPluginType = PluginType & { + authenticate: Function +}; diff --git a/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/getGeneralSettings.js b/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/getGeneralSettings.js deleted file mode 100644 index 141bd408d21..00000000000 --- a/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/getGeneralSettings.js +++ /dev/null @@ -1,23 +0,0 @@ -// @flow -import { Response, ErrorResponse } from "webiny-api/graphql/responses"; -import { type IGeneralSettings } from "./../../../entities/GeneralSettings.entity"; - -type EntityFetcher = (context: Object) => IGeneralSettings; - -export default (entityFetcher: EntityFetcher) => async ( - root: any, - args: Object, - context: Object -) => { - const generalSettingsClass = entityFetcher(context); - - const settings = await generalSettingsClass.load(); - if (!settings) { - return new ErrorResponse({ - code: "NOT_FOUND", - message: "Settings not found." - }); - } - - return new Response(settings.data); -}; diff --git a/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/updateGeneralSettings.js b/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/updateGeneralSettings.js deleted file mode 100644 index 4800e85f68e..00000000000 --- a/packages/webiny-api/src/dataSource/typeDefs/generalSettingsResolvers/updateGeneralSettings.js +++ /dev/null @@ -1,25 +0,0 @@ -// @flow -import type { Entity } from "webiny-entity"; -import { Response, ErrorResponse } from "webiny-api/graphql/responses"; - -type EntityFetcher = (context: Object) => Class; - -export default (entityFetcher: EntityFetcher) => async ( - root: any, - { data }: Object, - context: Object -) => { - const generalSettingsClass = entityFetcher(context); - - const settings = await generalSettingsClass.load(); - if (!settings) { - return new ErrorResponse({ - code: "NOT_FOUND", - message: "Settings not found." - }); - } - - settings.data = data; - await settings.save(); - return new Response(settings.data); -}; diff --git a/packages/webiny-api/src/entities/ApiToken.entity.js b/packages/webiny-api/src/entities/ApiToken.entity.js deleted file mode 100644 index 12de11bae24..00000000000 --- a/packages/webiny-api/src/entities/ApiToken.entity.js +++ /dev/null @@ -1,78 +0,0 @@ -// @flow -import { Entity } from "webiny-entity"; -import { JwtToken } from "../security/jwtToken"; -import type { Group } from "./Group.entity"; -import type { Role } from "./Role.entity"; -import { loadEntityScopes } from "./utils"; - -export interface IApiToken extends Entity { - name: string; - token: string; - description: string; - groups: Promise>; - roles: Promise>; - scopes: Promise>; - generateJWT(): Promise; -} - -export function apiTokenFactory({ - user = {}, - config, - api: { entities } -}: Object): Class { - return class extends Entity { - static classId = "SecurityApiToken"; - static storageClassId = "Security_ApiTokens"; - - name: string; - token: string; - description: string; - groups: Promise>; - roles: Promise>; - scopes: Promise>; - - constructor() { - super(); - - this.attr("createdBy") - .char() - .setDefaultValue(user.id); - this.attr("name").char(); - this.attr("token").char(); - this.attr("description").char(); - - this.attr("roles") - .entities(entities.Role, "entity") - .setUsing(entities.Roles2Entities, "role"); - - this.attr("groups") - .entities(entities.Group, "entity") - .setUsing(entities.Groups2Entities, "group"); - - this.attr("scopes") - .array() - .setDynamic(() => { - return loadEntityScopes.call(this); - }); - } - - /*async save(...args): Promise { - const createToken = !this.isExisting(); - await super.save(...args); - - if (createToken) { - // 2147483647 = maximum value of unix timestamp (year 2038). - const token = new JwtToken({ secret: config.security.token.secret }); - this.token = await token.encode({ id: this.id, type: "apiToken" }, 2147483647); - await super.save(); - } - }*/ - - async generateJWT(): Promise { - // 2147483647 = maximum value of unix timestamp (year 2038). - const token = new JwtToken({ secret: config.security.token.secret }); - this.token = await token.encode({ id: this.id, type: "apiToken" }, 2147483647); - await super.save(); - } - }; -} diff --git a/packages/webiny-api/src/entities/ApiToken.mysql.js b/packages/webiny-api/src/entities/ApiToken.mysql.js deleted file mode 100644 index ffcff8ed830..00000000000 --- a/packages/webiny-api/src/entities/ApiToken.mysql.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -import MySQLTable from "../install/tables/mysqlTable"; - -class ApiTokenTable extends MySQLTable { - constructor() { - super(); - this.column("createdBy").char(24); - this.column("name").char(50); - this.column("token").text(); - this.column("description").varChar(255); - } -} - -ApiTokenTable.setName("Security_ApiTokens"); - -export default ApiTokenTable; diff --git a/packages/webiny-api/src/entities/GeneralSettings.entity.js b/packages/webiny-api/src/entities/GeneralSettings.entity.js deleted file mode 100644 index b7ff6906417..00000000000 --- a/packages/webiny-api/src/entities/GeneralSettings.entity.js +++ /dev/null @@ -1,45 +0,0 @@ -// @flow -import { Entity } from "webiny-entity"; -import { Model } from "webiny-model"; -import { settingsFactory } from "./Settings.entity"; -import FileModel from "./File.model"; - -export interface IGeneralSettings extends Entity { - data: Object; - load: Function; -} - -class SocialMedia extends Model { - constructor() { - super(); - this.attr("facebook").char(); - this.attr("twitter").char(); - this.attr("instagram").char(); - } -} - -class GeneralSettingsModel extends Model { - constructor() { - super(); - this.attr("name").char(); - this.attr("favicon").model(FileModel); - this.attr("logo").model(FileModel); - this.attr("social").model(SocialMedia); - } -} - -export function generalSettingsFactory(...args: Array): Class { - class GeneralSettings extends settingsFactory(...args) { - static key = "general"; - - data: Object; - load: Function; - - constructor() { - super(); - this.attr("data").model(GeneralSettingsModel); - } - } - - return GeneralSettings; -} diff --git a/packages/webiny-api/src/entities/Settings.mysql.js b/packages/webiny-api/src/entities/Settings.mysql.js index ce962f28028..54638f10d3f 100644 --- a/packages/webiny-api/src/entities/Settings.mysql.js +++ b/packages/webiny-api/src/entities/Settings.mysql.js @@ -1,5 +1,5 @@ // @flow -import MySQLTable from "../install/tables/mysqlTable"; +import { MySQLTable } from "./.."; class SettingsTable extends MySQLTable { constructor() { diff --git a/packages/webiny-api/src/entities/index.js b/packages/webiny-api/src/entities/index.js index 2407494cef5..ca7cf59698d 100644 --- a/packages/webiny-api/src/entities/index.js +++ b/packages/webiny-api/src/entities/index.js @@ -1,10 +1,2 @@ // @flow -export { userFactory } from "webiny-api/entities/User.entity"; -export { apiTokenFactory } from "webiny-api/entities/ApiToken.entity"; -export { groupFactory } from "webiny-api/entities/Group.entity"; -export { groups2entitiesFactory } from "webiny-api/entities/Groups2Entities.entity"; -export { roleFactory } from "webiny-api/entities/Role.entity"; -export { roles2entitiesFactory } from "webiny-api/entities/Roles2Entities.entity"; export { settingsFactory } from "webiny-api/entities/Settings.entity"; -export { generalSettingsFactory } from "webiny-api/entities/GeneralSettings.entity"; -export { userSettingsFactory } from "webiny-api/entities/UserSettings.entity"; diff --git a/packages/webiny-api/src/entities/utils.js b/packages/webiny-api/src/entities/utils.js deleted file mode 100644 index 049c9ae42cd..00000000000 --- a/packages/webiny-api/src/entities/utils.js +++ /dev/null @@ -1,25 +0,0 @@ -export async function loadEntityScopes() { - // TODO: rebuild scopes catalogue for the user when a Group is updated or assigned to the user, - // or a Role is updated or assigned to the user to avoid digging through everything each time we need to access user scopes - // (as we do now to get things going) - "we'll do it later" ™ - const scopes = []; - const groups = await this.groups; - // Get scopes via `groups` relation - for (let i = 0; i < groups.length; i++) { - const group = groups[i]; - const roles = await group.roles; - for (let j = 0; j < roles.length; j++) { - const role = roles[j]; - role.scopes.forEach(scope => scopes.push(scope)); - } - } - - // Get scopes via `roles` relation - const roles = await this.roles; - for (let j = 0; j < roles.length; j++) { - const role = roles[j]; - role.scopes.forEach(scope => scopes.push(scope)); - } - - return [...new Set(scopes)]; -} \ No newline at end of file diff --git a/packages/webiny-api/src/graphql/crudResolvers.js b/packages/webiny-api/src/graphql/crudResolvers.js index 2818b721fb0..98cf1c4aa6f 100644 --- a/packages/webiny-api/src/graphql/crudResolvers.js +++ b/packages/webiny-api/src/graphql/crudResolvers.js @@ -10,7 +10,7 @@ type EntityFetcher = (context: Object) => Class; const notFound = (id?: string) => new ErrorResponse({ code: "NOT_FOUND", - message: id ? `Entity with id "${id}" was not found!` : "Entity not found!" + message: id ? `Record "${id}" not found!` : "Record not found!" }); export const resolveGet = (entityFetcher: EntityFetcher) => async ( @@ -134,8 +134,16 @@ export const resolveDelete = (entityFetcher: EntityFetcher) => async ( return notFound(args.id); } - await entity.delete(); - return new Response(true); + return entity + .delete() + .then(() => new Response(true)) + .catch( + e => + new ErrorResponse({ + code: e.code, + message: e.message + }) + ); }; const resolveMap = { diff --git a/packages/webiny-api/src/graphql/schema/genericTypes.js b/packages/webiny-api/src/graphql/schema/genericTypes.js index 4c64ae1a84a..17da47fdc5c 100644 --- a/packages/webiny-api/src/graphql/schema/genericTypes.js +++ b/packages/webiny-api/src/graphql/schema/genericTypes.js @@ -34,7 +34,8 @@ export const genericTypes = () => { name: String size: Int type: String - src: String + src: String, + meta: JSON } input FileInput { @@ -42,6 +43,7 @@ export const genericTypes = () => { size: Int type: String src: String + meta: JSON } ` ]; diff --git a/packages/webiny-api/src/graphql/schema/index.js b/packages/webiny-api/src/graphql/schema/index.js index 7bd305c04b2..924ae3f2d1f 100644 --- a/packages/webiny-api/src/graphql/schema/index.js +++ b/packages/webiny-api/src/graphql/schema/index.js @@ -61,22 +61,13 @@ export function prepareSchema() { const dataSources = getPlugins("graphql"); const schemas = mapSourcesToExecutableSchemas(dataSources); - const securityScopes = [ - ...new Set(dataSources.reduce((res, item) => res.concat(item.scopes || []), [])) - ]; const sourcesWithStitching = dataSources.filter(source => source.stitching); const linkTypeDefs = sourcesWithStitching.map(source => source.stitching.linkTypeDefs); const resolvers = sourcesWithStitching.map(source => source.stitching.resolvers); const schema = mergeSchemas({ schemas: [...Object.values(schemas), ...linkTypeDefs], - resolvers: { - ...resolvers, - // Add all scopes to the schema - SecurityQuery: { - scopes: () => securityScopes - } - } + resolvers }); return { diff --git a/packages/webiny-api/src/index.js b/packages/webiny-api/src/index.js index 6acb7d5a701..72b7d4ec0e1 100644 --- a/packages/webiny-api/src/index.js +++ b/packages/webiny-api/src/index.js @@ -1,9 +1,3 @@ // @flow -import { addPlugin } from "webiny-plugins"; -import apiPlugins from "./plugins"; - -// Register required core plugins. -addPlugin(...apiPlugins); - export { createHandler } from "./lambda/lambda"; export { default as MySQLTable } from "./mysql"; diff --git a/packages/webiny-api/src/install/importData.js b/packages/webiny-api/src/install/importData.js deleted file mode 100644 index 099e4ff62ad..00000000000 --- a/packages/webiny-api/src/install/importData.js +++ /dev/null @@ -1,31 +0,0 @@ -// @flow -import setupEntities from "./setupEntities"; - -export default async (context: Object) => { - setupEntities(context); - const { User, Role } = context.api.entities; - - const user = new User(); - - const superAdminRole = new Role(); - superAdminRole.populate({ - name: "Super Admin", - slug: "super-admin", - description: - "This role gives super admin privileges. Be careful when assigning this role to users!", - scopes: ["superadmin"] - }); - - await superAdminRole.save(); - - user.populate({ - firstName: "John", - lastName: "Doe", - password: "12345678", - email: "admin@webiny.com", - roles: [superAdminRole] - }); - - await user.save(); - context.user = user; -}; diff --git a/packages/webiny-api/src/install/plugins/createMySQLTables.js b/packages/webiny-api/src/install/plugins/createMySQLTables.js new file mode 100644 index 00000000000..28b127c3749 --- /dev/null +++ b/packages/webiny-api/src/install/plugins/createMySQLTables.js @@ -0,0 +1,22 @@ +// @flow +import MySQLTable from "./tables/mysqlTable"; +import type { MySQLDriver } from "webiny-sql-table-mysql"; +import { Sync } from "webiny-sql-table-sync"; +import { + SettingsTable, +} from "./tables"; + +export default async (config: Object) => { + const driver: MySQLDriver = (MySQLTable.getDriver(): any); + driver.setConnection(config.entity.driver.getConnection()); + + const tables = [ + SettingsTable, + ]; + + const sync = new Sync({ + tables, + drop: true + }); + await sync.execute(); +}; diff --git a/packages/webiny-api/src/install/plugins/index.js b/packages/webiny-api/src/install/plugins/index.js new file mode 100644 index 00000000000..f37faae858d --- /dev/null +++ b/packages/webiny-api/src/install/plugins/index.js @@ -0,0 +1,18 @@ +// @flow +import createMySQLTables from "./createMySQLTables"; +import { type InstallPluginType } from "webiny-install/types"; + +const plugin: InstallPluginType = { + type: "install", + name: "install-api", + meta: { + name: "Webiny API", + description: "Foundation of the Webiny platform." + }, + install: async (context: Object) => { + const { config } = context; + await createMySQLTables(config); + } +}; + +export default [plugin]; diff --git a/packages/webiny-api/src/install/plugins/tables/index.js b/packages/webiny-api/src/install/plugins/tables/index.js new file mode 100644 index 00000000000..867c0853453 --- /dev/null +++ b/packages/webiny-api/src/install/plugins/tables/index.js @@ -0,0 +1,2 @@ +// @flow +export { default as SettingsTable } from "../../../entities/Settings.mysql"; diff --git a/packages/webiny-api/src/install/plugins/tables/mysqlTable.js b/packages/webiny-api/src/install/plugins/tables/mysqlTable.js new file mode 100644 index 00000000000..0a67edd01e6 --- /dev/null +++ b/packages/webiny-api/src/install/plugins/tables/mysqlTable.js @@ -0,0 +1,4 @@ +// @flow +import { MySQLTable as BaseMySQLTable } from "webiny-api"; + +export default class MySQLTable extends BaseMySQLTable {} diff --git a/packages/webiny-api/src/install/setupEntities.js b/packages/webiny-api/src/install/setupEntities.js deleted file mode 100644 index 6b5b2c7c303..00000000000 --- a/packages/webiny-api/src/install/setupEntities.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow -import { userFactory } from "./../entities/User.entity"; -import { apiTokenFactory } from "./../entities/ApiToken.entity"; -import { groupFactory } from "./../entities/Group.entity"; -import { groups2entitiesFactory } from "./../entities/Groups2Entities.entity"; -import { roleFactory } from "./../entities/Role.entity"; -import { roles2entitiesFactory } from "./../entities/Roles2Entities.entity"; -import { userSettingsFactory } from "./../entities/UserSettings.entity"; - -export default context => { - context.api = { entities: {} }; - context.api.entities.User = userFactory(context); - context.api.entities.ApiToken = apiTokenFactory(context); - context.api.entities.Group = groupFactory(context); - context.api.entities.Role = roleFactory(context); - context.api.entities.Groups2Entities = groups2entitiesFactory(context); - context.api.entities.Roles2Entities = roles2entitiesFactory(context); - context.api.entities.UserSettings = userSettingsFactory(context); -}; diff --git a/packages/webiny-api/src/install/tables/index.js b/packages/webiny-api/src/install/tables/index.js deleted file mode 100644 index 12bb80a08fe..00000000000 --- a/packages/webiny-api/src/install/tables/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -export { default as ApiTokenTable } from "../../entities/ApiToken.mysql"; -export { default as GroupTable } from "../../entities/Group.mysql"; -export { default as Groups2EntitiesTable } from "../../entities/Groups2Entities.mysql"; -export { default as RoleTable } from "../../entities/Role.mysql"; -export { default as Roles2EntitiesTable} from "../../entities/Roles2Entities.mysql"; -export { default as SettingsTable } from "../../entities/Settings.mysql"; -export { default as UserTable } from "../../entities/User.mysql"; diff --git a/packages/webiny-api/src/lambda/lambda.js b/packages/webiny-api/src/lambda/lambda.js index 9a43722f28e..ae11630c9a8 100644 --- a/packages/webiny-api/src/lambda/lambda.js +++ b/packages/webiny-api/src/lambda/lambda.js @@ -1,15 +1,36 @@ // @flow import { ApolloServer } from "apollo-server-lambda"; import { applyMiddleware } from "graphql-middleware"; +import type { GraphQLMiddlewarePluginType } from "webiny-api/types"; import { prepareSchema, createGraphqlRunner } from "../graphql/schema"; import setup from "./setup"; -import authenticate from "./authenticate"; +import { getPlugins } from "webiny-plugins"; -const setupHandler = async (config: Object) => { +const createApolloHandler = async (config: Object) => { await setup(config); let { schema, context } = prepareSchema(); - schema = config.middleware ? applyMiddleware(schema, ...config.middleware) : schema; + const registeredMiddleware: Array = []; + + const middlewarePlugins = getPlugins("graphql-middleware"); + for (let i = 0; i < middlewarePlugins.length; i++) { + let plugin = middlewarePlugins[i]; + const middleware = + typeof plugin.middleware === "function" + ? await plugin.middleware({ context, config }) + : plugin.middleware; + if (Array.isArray(middleware)) { + registeredMiddleware.push(...middleware); + } else { + registeredMiddleware.push(middleware); + } + } + + config.middleware && registeredMiddleware.push(config.middleware); + + if (registeredMiddleware.length) { + schema = applyMiddleware(schema, ...registeredMiddleware); + } const apollo = new ApolloServer({ schema, @@ -60,7 +81,7 @@ export const createHandler = (config: Object = {}) => { const response = await new Promise(async (resolve, reject) => { if (!handler) { try { - handler = await setupHandler(config); + handler = await createApolloHandler(config); } catch (e) { if (process.env.NODE_ENV === "development") { console.log(e); // eslint-disable-line @@ -69,10 +90,14 @@ export const createHandler = (config: Object = {}) => { } } - try { - await authenticate(config, event, context); - } catch (error) { - return resolve(getErrorResponse(error)); + const securityPlugins = getPlugins("security"); + for (let i = 0; i < securityPlugins.length; i++) { + let securityPlugin = securityPlugins[i]; + try { + await securityPlugin.authenticate(config, event, context); + } catch (e) { + return resolve(getErrorResponse(e)); + } } handler(event, context, (error, data) => { diff --git a/packages/webiny-api/src/plugins/entities.js b/packages/webiny-api/src/plugins/entities.js index 01e6009e8fc..4378809479d 100644 --- a/packages/webiny-api/src/plugins/entities.js +++ b/packages/webiny-api/src/plugins/entities.js @@ -2,56 +2,6 @@ import { type EntityPluginType } from "webiny-api/types"; import * as entities from "webiny-api/entities"; -const apiToken: EntityPluginType = { - name: "entity-api-token", - type: "entity", - namespace: "api", - entity: { - name: "ApiToken", - factory: entities.apiTokenFactory - } -}; - -const group: EntityPluginType = { - name: "entity-group", - type: "entity", - namespace: "api", - entity: { - name: "Group", - factory: entities.groupFactory - } -}; - -const groups2entities: EntityPluginType = { - name: "entity-groups-2-entities", - type: "entity", - namespace: "api", - entity: { - name: "Groups2Entities", - factory: entities.groups2entitiesFactory - } -}; - -const role: EntityPluginType = { - name: "entity-role", - type: "entity", - namespace: "api", - entity: { - name: "Role", - factory: entities.roleFactory - } -}; - -const roles2entities: EntityPluginType = { - name: "entity-roles-2-entities", - type: "entity", - namespace: "api", - entity: { - name: "Roles2Entities", - factory: entities.roles2entitiesFactory - } -}; - const settings: EntityPluginType = { name: "entity-settings", type: "entity", @@ -62,44 +12,4 @@ const settings: EntityPluginType = { } }; -const user: EntityPluginType = { - name: "entity-user", - type: "entity", - namespace: "api", - entity: { - name: "User", - factory: entities.userFactory - } -}; - -const userSettings: EntityPluginType = { - name: "entity-user-settings", - type: "entity", - namespace: "api", - entity: { - name: "UserSettings", - factory: entities.userSettingsFactory - } -}; - -const generalSettings: EntityPluginType = { - name: "entity-general-settings", - type: "entity", - namespace: "api", - entity: { - name: "GeneralSettings", - factory: entities.generalSettingsFactory - } -}; - -export default [ - apiToken, - group, - groups2entities, - role, - roles2entities, - settings, - user, - userSettings, - generalSettings -]; +export default [settings]; diff --git a/packages/webiny-api/src/plugins/graphql.js b/packages/webiny-api/src/plugins/graphql.js index 75ad1fac77a..6cb37a447f4 100644 --- a/packages/webiny-api/src/plugins/graphql.js +++ b/packages/webiny-api/src/plugins/graphql.js @@ -1,9 +1,5 @@ // @flow import { dummyResolver } from "../graphql"; -import role from "./graphql/Role"; -import group from "./graphql/Group"; -import user from "./graphql/User"; -import apiToken from "./graphql/ApiToken"; import { getPlugins } from "webiny-plugins"; import { type GraphQLSchemaPluginType } from "webiny-api/types"; @@ -11,59 +7,37 @@ export default ({ type: "graphql", name: "graphql-api", namespace: "api", - scopes: ["superadmin", "users:read", "users:write"], - typeDefs: () => [ - user.typeDefs, - user.typeExtensions, - role.typeDefs, - role.typeExtensions, - group.typeDefs, - group.typeExtensions, - apiToken.typeDefs, - ...getPlugins("schema-settings").map(pl => pl.typeDefs), - /* GraphQL */ ` - type SecurityQuery { - scopes: [String] - } - - type SecurityMutation { - _empty: String - } - - type SettingsQuery { - _empty: String - } + typeDefs: () => { + return [ + /* GraphQL */ ` + type SettingsQuery { + _empty: String + } - type SettingsMutation { - _empty: String - } + type SettingsMutation { + _empty: String + } - type Query { - security: SecurityQuery - settings: SettingsQuery - } + type Query { + settings: SettingsQuery + } - type Mutation { - security: SecurityMutation - settings: SettingsMutation - } - ` - ], + type Mutation { + settings: SettingsMutation + } + `, + ...getPlugins("schema-settings").map(pl => pl.typeDefs) + ]; + }, resolvers: () => [ { Query: { - security: dummyResolver, settings: dummyResolver }, Mutation: { - security: dummyResolver, settings: dummyResolver } }, - apiToken.resolvers, - group.resolvers, - role.resolvers, - user.resolvers, ...getPlugins("schema-settings").map(plugin => { return { SettingsQuery: { @@ -86,7 +60,12 @@ export default ({ if (!settings) { settings = new entityClass(); } - settings.data = data; + + if (!settings.data) { + settings.data = {}; + } + + settings.data.populate(data); await settings.save(); return settings.data; diff --git a/packages/webiny-api/src/plugins/graphql/ApiToken.js b/packages/webiny-api/src/plugins/graphql/ApiToken.js deleted file mode 100644 index 65a070ca2ba..00000000000 --- a/packages/webiny-api/src/plugins/graphql/ApiToken.js +++ /dev/null @@ -1,89 +0,0 @@ -// @flow -import { - resolveCreate, - resolveDelete, - resolveGet, - resolveList, - resolveUpdate -} from "webiny-api/graphql"; - -const apiTokenFetcher = ctx => ctx.api.entities.ApiToken; - -export default { - typeDefs: () => [ - ` - type ApiToken { - id: ID - name: String - token: String - description: String - createdOn: String - groups: [Group] - roles: [Role] - scopes: [String] - } - - input ApiTokenInput { - name: String - description: String - groups: [ID] - roles: [ID] - } - - type ApiTokenListResponse { - data: [ApiToken] - meta: ListMeta - error: Error - } - - type ApiTokenResponse { - data: ApiToken - error: Error - }`, - `extend type SecurityQuery { - getApiToken( - id: ID - where: JSON - sort: String - ): ApiTokenResponse - - listApiTokens( - page: Int - perPage: Int - where: JSON - sort: JSON - search: SearchInput - ): ApiTokenListResponse - } - - extend type SecurityMutation { - createApiToken( - data: ApiTokenInput! - ): ApiTokenResponse - - updateApiToken( - id: ID! - data: ApiTokenInput! - ): ApiTokenResponse - - deleteApiToken( - id: ID! - ): DeleteResponse - }` - ], - resolvers: { - SecurityQuery: { - getApiToken: resolveGet(apiTokenFetcher), - listApiTokens: resolveList(apiTokenFetcher) - }, - SecurityMutation: { - createApiToken: async (...args: Array) => { - const res = await resolveCreate(apiTokenFetcher)(...args); - await res.data.generateJWT(); - return res; - }, - updateApiToken: resolveUpdate(apiTokenFetcher), - deleteApiToken: resolveDelete(apiTokenFetcher) - } - } -}; diff --git a/packages/webiny-api/src/plugins/index.js b/packages/webiny-api/src/plugins/index.js index 7f4b85c4592..1a3248098af 100644 --- a/packages/webiny-api/src/plugins/index.js +++ b/packages/webiny-api/src/plugins/index.js @@ -2,6 +2,5 @@ import graphqlContextEntities from "./graphqlContextEntities"; import entities from "./entities"; import graphql from "./graphql"; -import generalSettings from "./settings/generalSettings"; -export default [...entities, graphql, graphqlContextEntities, generalSettings]; +export default [graphqlContextEntities, entities, graphql]; diff --git a/packages/webiny-api/src/plugins/settings/generalSettings.js b/packages/webiny-api/src/plugins/settings/generalSettings.js deleted file mode 100644 index b32bcdc5af0..00000000000 --- a/packages/webiny-api/src/plugins/settings/generalSettings.js +++ /dev/null @@ -1,49 +0,0 @@ -// @flow -import { type SettingsPluginType } from "webiny-api/types"; -export default ([ - { - name: "schema-settings-general", - type: "schema-settings", - namespace: "general", - typeDefs: ` - type CmsSocialMedia { - facebook: String - twitter: String - instagram: String - } - - input CmsSocialMediaInput { - facebook: String - twitter: String - instagram: String - } - - type GeneralSettings { - name: String - favicon: File - logo: File - social: CmsSocialMedia - } - - input GeneralSettingsInput { - name: String - favicon: FileInput - logo: FileInput - social: CmsSocialMediaInput - } - - extend type SettingsQuery { - general: GeneralSettings - } - - extend type SettingsMutation { - general(data: GeneralSettingsInput): GeneralSettings - } - `, - entity: ({ - api: { - entities: { GeneralSettings } - } - }) => GeneralSettings - } -]: Array); diff --git a/packages/webiny-api/src/security/index.js b/packages/webiny-api/src/security/index.js deleted file mode 100644 index d1dc4136012..00000000000 --- a/packages/webiny-api/src/security/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { JwtToken, JwtTokenError } from "./jwtToken"; diff --git a/packages/webiny-api/src/types.js b/packages/webiny-api/src/types.js index 1f2467e57ac..05111f86c8b 100644 --- a/packages/webiny-api/src/types.js +++ b/packages/webiny-api/src/types.js @@ -14,10 +14,14 @@ export type EntityPluginType = PluginType & { export type GraphQLSchemaPluginType = PluginType & { namespace: string, - typedefs: Array | (() => Array), + typeDefs: *, resolvers: Object | (() => Object) }; +export type GraphQLMiddlewarePluginType = PluginType & { + middleware: () => Object +}; + export type GraphQLContextPluginType = PluginType & { apply: (context: Object) => any }; diff --git a/packages/webiny-app-admin/index.js b/packages/webiny-app-admin/index.js deleted file mode 100644 index a1314ea9aca..00000000000 --- a/packages/webiny-app-admin/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export { app, Theme } from "./src"; diff --git a/packages/webiny-app-admin/src/app.js b/packages/webiny-app-admin/src/app.js deleted file mode 100644 index 9b25f9a9ea1..00000000000 --- a/packages/webiny-app-admin/src/app.js +++ /dev/null @@ -1,209 +0,0 @@ -// @flow -import React from "react"; -import { i18n } from "webiny-app/i18n"; -import { addPlugin, getPlugins } from "webiny-plugins"; -import plugins from "webiny-app-admin/presets/default"; -import { ReactComponent as SecurityIcon } from "./assets/images/icons/baseline-security-24px.svg"; -import { ReactComponent as SettingsIcon } from "./assets/images/icons/round-settings-24px.svg"; -import Roles from "./views/Roles"; -import Users from "./views/Users"; -import ApiTokens from "./views/ApiTokens"; -import Groups from "./views/Groups"; -import Account from "./views/Account"; -import AdminLayout from "webiny-app-admin/components/Layouts/AdminLayout"; -import type { SettingsPluginType } from "webiny-app-admin/types"; - -const t = i18n.namespace("Admin.App"); -const securityManager = "webiny-security-manager"; - -export default () => { - addPlugin(...plugins); - - addPlugin({ - type: "webiny-init", - name: "webiny-init-settings", - callback() { - // Settings - // Apps / integrations can register settings plugins and add menu items like the following. - let settingsPlugins: Array = getPlugins("settings"); - - settingsPlugins.forEach((sp: SettingsPluginType) => { - addPlugin({ - type: "route", - name: "route-settings-" + sp.name, - route: { - ...sp.settings.route, - path: "/settings" + sp.settings.route.path, - render() { - return {sp.settings.component}; - } - } - }); - }); - - const sortedSettingsPlugins = { - apps: settingsPlugins.filter(sp => sp.settings.type === "app"), - integrations: settingsPlugins.filter(sp => sp.settings.type === "integration"), - other: settingsPlugins.filter( - sp => !["app", "integration"].includes(sp.settings.type) - ) - }; - - addPlugin({ - type: "menu", - name: "menu-settings", - render({ Menu }) { - return ( - }> - {sortedSettingsPlugins.apps.length > 0 && ( - - {sortedSettingsPlugins.apps.map(sp => ( - - ))} - - )} - - {sortedSettingsPlugins.integrations.length > 0 && ( - - {sortedSettingsPlugins.integrations.map(sp => ( - - ))} - - )} - - {sortedSettingsPlugins.other.length > 0 && ( - - {sortedSettingsPlugins.other.map(sp => ( - - ))} - - )} - - ); - } - }); - } - }); - - // Add menu plugin - addPlugin({ - name: "security-menu", - type: "menu", - render({ Menu }) { - return ( - }> - - - - - - - - - - ); - } - }); - - addPlugin({ - name: "route-roles", - type: "route", - route: { - name: "Roles", - path: "/roles", - title: "Security - Roles", - render() { - return ( - - - - ); - }, - group: securityManager - } - }); - - addPlugin({ - name: "route-groups", - type: "route", - route: { - name: "Groups", - path: "/groups", - title: "Security - Groups", - render() { - return ( - - - - ); - }, - group: securityManager - } - }); - - addPlugin({ - name: "route-users", - type: "route", - route: { - name: "Users", - path: "/users", - title: "Security - Users", - render() { - return ( - - - - ); - }, - group: securityManager - } - }); - - addPlugin({ - name: "route-api-tokens", - type: "route", - route: { - name: "ApiTokens", - path: "/api-tokens", - title: "Security - Identities - API Tokens", - render() { - return ( - - - - ); - }, - group: securityManager - } - }); - - addPlugin({ - name: "route-account", - type: "route", - route: { - name: "Account", - path: "/account", - title: "Account", - render() { - return ( - - - - ); - }, - group: securityManager - } - }); -}; diff --git a/packages/webiny-app-admin/src/assets/icons/round-account_circle-24px.svg b/packages/webiny-app-admin/src/assets/icons/round-account_circle-24px.svg deleted file mode 100644 index 3dc9261676e..00000000000 --- a/packages/webiny-app-admin/src/assets/icons/round-account_circle-24px.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/webiny-app-admin/src/plugins/GlobalSearch/index.js b/packages/webiny-app-admin/src/plugins/GlobalSearch/index.js deleted file mode 100644 index 182e1c80f3f..00000000000 --- a/packages/webiny-app-admin/src/plugins/GlobalSearch/index.js +++ /dev/null @@ -1,23 +0,0 @@ -//@flow -import React from "react"; -import SearchBar from "./SearchBar"; -import type { GlobalSearch, HeaderMiddlePlugin } from "webiny-app-admin/types"; - -export const globalSearch: HeaderMiddlePlugin = { - name: "global-search", - type: "header-middle", - render() { - return ; - } -}; - -// Additional sections in global search. -export const globalSearchUsers: GlobalSearch = { - type: "global-search", - name: "global-search-users", - route: "Users", - label: "Users", - search: { - fields: ["firstName", "lastName", "email"] - } -}; diff --git a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/icons/round-ballot-24px.svg b/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/icons/round-ballot-24px.svg deleted file mode 100644 index 4a56c9a8a47..00000000000 --- a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/icons/round-ballot-24px.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - diff --git a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/index.js b/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/index.js deleted file mode 100644 index 001f1d61d41..00000000000 --- a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow -import * as React from "react"; -import GeneralSettings from "./components/GeneralSettings"; -import type { SettingsPluginType } from "webiny-app-admin/types"; - -export default ({ - type: "settings", - name: "settings-general-settings", - settings: { - type: "other", - name: "General settings", - component: , - route: { - name: "Settings.GeneralSettings", - path: "/general", - title: "General Settings", - group: undefined - } - } -}: SettingsPluginType); diff --git a/packages/webiny-app-admin/src/plugins/Settings/index.js b/packages/webiny-app-admin/src/plugins/Settings/index.js deleted file mode 100644 index 4dd76d88bf3..00000000000 --- a/packages/webiny-app-admin/src/plugins/Settings/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { default as generalSettings } from "./GeneralSettings"; diff --git a/packages/webiny-app-admin/src/plugins/UserMenu/index.js b/packages/webiny-app-admin/src/plugins/UserMenu/index.js deleted file mode 100644 index 96746d06b1a..00000000000 --- a/packages/webiny-app-admin/src/plugins/UserMenu/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import UserMenu from "./UserMenu"; - -export default { - name: "header-user-menu", - type: "header-right", - render() { - return ; - } -}; \ No newline at end of file diff --git a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/SignOut.js b/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/SignOut.js deleted file mode 100644 index e0f272a939f..00000000000 --- a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/SignOut.js +++ /dev/null @@ -1,19 +0,0 @@ -//@flow -import React from "react"; -import { ReactComponent as SignOutIcon } from "webiny-app-admin/assets/icons/round-lock_open-24px.svg"; -import { ListItem, ListItemGraphic } from "webiny-ui/List"; -import { Icon } from "webiny-ui/Icon"; -import { withSecurity } from "webiny-app-admin/components"; - -const SignOut = (props: Object) => { - return ( - props.security.logout()}> - - } /> - - Sign out - - ); -}; - -export default withSecurity()(SignOut); \ No newline at end of file diff --git a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/index.js b/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/index.js deleted file mode 100644 index 7748f697f1d..00000000000 --- a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/SignOut/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import SignOut from "./SignOut"; - -export default { - name: "user-menu-sign-out", - type: "header-user-menu", - render() { - return ; - } -}; \ No newline at end of file diff --git a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserImage/index.js b/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserImage/index.js deleted file mode 100644 index eb24397b920..00000000000 --- a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserImage/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import UserImage from "./UserImage"; - -export default { - name: "user-menu-handle", - type: "header-user-menu-handle", - render() { - return ; - } -}; \ No newline at end of file diff --git a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserInfo/index.js b/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserInfo/index.js deleted file mode 100644 index 3c0e0d6208a..00000000000 --- a/packages/webiny-app-admin/src/plugins/UserMenu/plugins/UserInfo/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import UserInfo from "./UserInfo"; - -export default { - name: "user-menu-user-info", - type: "header-user-menu", - render() { - return ; - } -}; \ No newline at end of file diff --git a/packages/webiny-app-admin/src/presets/default.js b/packages/webiny-app-admin/src/presets/default.js deleted file mode 100644 index 6c0702314a0..00000000000 --- a/packages/webiny-app-admin/src/presets/default.js +++ /dev/null @@ -1,49 +0,0 @@ -// @flow -// Layout plug -import Header from "webiny-app-admin/plugins/Header"; -import Footer from "webiny-app-admin/plugins/Footer"; -import Content from "webiny-app-admin/plugins/Content"; -import snackbar from "webiny-app-admin/plugins/Snackbar"; -import dialog from "webiny-app-admin/plugins/Dialog"; - -// Header plugins -import Menu from "webiny-app-admin/plugins/Menu"; -import Logo from "webiny-app-admin/plugins/Logo"; -import UserMenu from "webiny-app-admin/plugins/UserMenu"; -import { globalSearch, globalSearchUsers } from "webiny-app-admin/plugins/GlobalSearch"; -import { generalSettings } from "webiny-app-admin/plugins/Settings"; - -// User menu plugins -import UserInfo from "webiny-app-admin/plugins/UserMenu/plugins/UserInfo"; -import UserImage from "webiny-app-admin/plugins/UserMenu/plugins/UserImage"; -import DarkMode from "webiny-app-admin/plugins/UserMenu/plugins/DarkMode"; -import Help from "webiny-app-admin/plugins/UserMenu/plugins/Help"; -import SendFeedback from "webiny-app-admin/plugins/UserMenu/plugins/Feedback"; -import SignOut from "webiny-app-admin/plugins/UserMenu/plugins/SignOut"; -import createDivider from "webiny-app-admin/plugins/UserMenu/plugins/Divider"; - -export default [ - // Layout plugins - Header, - Content, - snackbar("layout"), - snackbar("empty-layout"), - dialog("layout"), - dialog("empty-layout"), - Footer, - // Header plugins - Menu, - Logo, - UserMenu, - globalSearch, - generalSettings, - globalSearchUsers, - // UserMenu plugins - UserImage, - UserInfo, - DarkMode, - Help, - SendFeedback, - createDivider(), - SignOut -]; diff --git a/packages/webiny-app-admin/src/security/index.js b/packages/webiny-app-admin/src/security/index.js deleted file mode 100644 index 1ced91f0759..00000000000 --- a/packages/webiny-app-admin/src/security/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { default as createAuthLink } from "./createAuthLink"; -export { default as Security, SecurityConsumer } from "./Security"; diff --git a/packages/webiny-app-admin/src/views/ApiTokens.js b/packages/webiny-app-admin/src/views/ApiTokens.js deleted file mode 100644 index eb2ef63638d..00000000000 --- a/packages/webiny-app-admin/src/views/ApiTokens.js +++ /dev/null @@ -1,77 +0,0 @@ -// @flow -import * as React from "react"; -import { get } from "dot-prop-immutable"; -import { pick } from "lodash"; -import { i18n } from "webiny-app/i18n"; -import { withCrud, type WithCrudProps } from "webiny-app-admin/components"; -import { CompactView, LeftPanel, RightPanel } from "webiny-app-admin/components/Views/CompactView"; -import FloatingActionButton from "webiny-app-admin/components/FloatingActionButton"; -import ApiTokensDataList from "./ApiTokens/ApiTokensDataList"; -import ApiTokensForm from "./ApiTokens/ApiTokensForm"; -import { - createApiToken, - deleteApiToken, - loadApiToken, - loadApiTokens, - updateApiToken -} from "./ApiTokens/graphql"; - -const t = i18n.namespace("Security.ApiTokens"); - -const ApiTokens = ({ formProps, listProps, router }: WithCrudProps) => { - return ( - - - - - - - - - - router.goToRoute({ - params: { id: null }, - merge: true - }) - } - /> - - ); -}; - -export default withCrud({ - list: { - get: { - query: loadApiTokens, - variables: { sort: { savedOn: -1 } }, - response: data => get(data, "security.tokens") - }, - delete: { - mutation: deleteApiToken, - response: data => data.security.deleteApiToken, - snackbar: data => t`API token {name} deleted.`({ name: data.name }) - } - }, - form: { - get: { - query: loadApiToken, - response: data => get(data, "security.token") - }, - save: { - create: createApiToken, - update: updateApiToken, - response: data => get(data, "security.token"), - variables: form => { - return { - data: { - ...pick(form, ["name", "description"]), - roles: (form.roles || []).map(x => x.id), - groups: (form.groups || []).map(x => x.id) - } - }; - }, - snackbar: data => t`API token {name} saved successfully.`({ name: data.name }) - } - } -})(ApiTokens); diff --git a/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensDataList.js b/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensDataList.js deleted file mode 100644 index 5303cbea179..00000000000 --- a/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensDataList.js +++ /dev/null @@ -1,76 +0,0 @@ -// @flow -import * as React from "react"; -import { i18n } from "webiny-app/i18n"; -import type { WithCrudListProps } from "webiny-app-admin/components"; -import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; -import { - DataList, - List, - ListItem, - ListItemText, - ListItemTextSecondary, - ListItemMeta -} from "webiny-ui/List"; -import { DeleteIcon } from "webiny-ui/List/DataList/icons"; - -const t = i18n.namespace("Security.ApiTokensDataList"); - -const ApiTokensDataList = ({ deleteRecord, dataList, router }: WithCrudListProps) => { - return ( - - {({ data }) => ( - - {data.map(item => ( - - { - router.goToRoute({ - merge: true, - params: { id: item.id } - }); - }} - > - {item.name} - {item.description} - - - - {({ showConfirmation }) => ( - - showConfirmation(() => deleteRecord(item)) - } - /> - )} - - - - ))} - - )} - - ); -}; - -export default ApiTokensDataList; diff --git a/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensForm.js b/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensForm.js deleted file mode 100644 index 09a222d9ae5..00000000000 --- a/packages/webiny-app-admin/src/views/ApiTokens/ApiTokensForm.js +++ /dev/null @@ -1,78 +0,0 @@ -// @flow -import * as React from "react"; -import { i18n } from "webiny-app/i18n"; -import { Grid, Cell } from "webiny-ui/Grid"; -import { Input } from "webiny-ui/Input"; -import { ButtonPrimary } from "webiny-ui/Button"; -import { Form } from "webiny-form"; -import GroupsAutoComplete from "./../Components/GroupsAutoComplete"; -import RolesAutoComplete from "./../Components/RolesAutoComplete"; - -import { - SimpleForm, - SimpleFormFooter, - SimpleFormContent -} from "webiny-app-admin/components/Views/SimpleForm"; - -const t = i18n.namespace("Security.ApiTokensForm"); - -const ApiTokensForm = ({ data, onSubmit, invalidFields }: Object) => { - return ( -
- {({ form, Bind }) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {t`Save API token`} - - - - )} -
- ); -}; -export default ApiTokensForm; diff --git a/packages/webiny-app-admin/src/views/ApiTokens/graphql.js b/packages/webiny-app-admin/src/views/ApiTokens/graphql.js deleted file mode 100644 index b5adf69e73f..00000000000 --- a/packages/webiny-app-admin/src/views/ApiTokens/graphql.js +++ /dev/null @@ -1,104 +0,0 @@ -// @flow -import gql from "graphql-tag"; - -const fields = ` - id token name description groups { id name } roles { id name } -`; - -export const loadApiTokens = gql` - query LoadApiTokens( - $where: JSON - $sort: JSON - $page: Int - $perPage: Int - $search: SearchInput - ) { - security { - tokens: listApiTokens( - where: $where - sort: $sort - page: $page - perPage: $perPage - search: $search - ) { - data { - id - name - description - createdOn - } - meta { - totalCount - to - from - nextPage - previousPage - } - } - } - } -`; - -export const loadApiToken = gql` - query LoadApiToken($id: ID!) { - security { - token: getApiToken(id: $id){ - data { - ${fields} - } - error { - code - message - } - } - } - } -`; - -export const createApiToken = gql` - mutation CreateApiToken($data: ApiTokenInput!){ - security { - token: createApiToken(data: $data) { - data { - ${fields} - } - error { - code - message - data - } - } - } - } -`; - -export const updateApiToken = gql` - mutation UpdateApiToken($id: ID!, $data: ApiTokenInput!){ - security { - token: updateApiToken(id: $id, data: $data) { - data { - ${fields} - } - error { - code - message - data - } - } - } - } -`; - -export const deleteApiToken = gql` - mutation DeleteApiToken($id: ID!) { - security { - deleteApiToken(id: $id) { - data - error { - code - message - } - } - } - } -`; diff --git a/packages/webiny-app-cms/index.js b/packages/webiny-app-cms/index.js index 46e7f7c0456..990a77ff938 100644 --- a/packages/webiny-app-cms/index.js +++ b/packages/webiny-app-cms/index.js @@ -1 +1,2 @@ // @flow +export * from "./src"; diff --git a/packages/webiny-app-cms/package.json b/packages/webiny-app-cms/package.json index 538ea4a1760..9452bfd0fe4 100644 --- a/packages/webiny-app-cms/package.json +++ b/packages/webiny-app-cms/package.json @@ -16,6 +16,7 @@ "@fortawesome/free-solid-svg-icons": "^5.5.0", "@fortawesome/react-fontawesome": "^0.1.3", "@svgr/webpack": "^4.1.0", + "aos": "^2.3.4", "dot-prop-immutable": "^1.4.0", "downshift": "^2.1.1", "dynamics.js": "^1.1.5", @@ -47,8 +48,7 @@ "slugify": "^1.2.9", "timeago-react": "^2.0.0", "uniqid": "^5.0.3", - "webfontloader": "^1.6.28", - "webiny-plugins": "0.0.0" + "webfontloader": "^1.6.28" }, "devDependencies": { "@babel/cli": "^7.0.0", @@ -62,12 +62,16 @@ "babel-plugin-emotion": "^9.2.8", "babel-plugin-lodash": "^3.3.4", "babel-plugin-module-resolver": "^3.1.1", - "babel-plugin-named-asset-import": "^1.0.0-next.3e165448", - "webiny-ui": "0.0.0" + "babel-plugin-named-asset-import": "^1.0.0-next.3e165448" }, "peerDependencies": { "react": "^16.6.0", - "react-dom": "^16.6.0" + "react-dom": "^16.6.0", + "react-helmet": "^5.2.0", + "webiny-app": "0.0.0", + "webiny-app-security": "0.0.0", + "webiny-plugins": "0.0.0", + "webiny-ui": "0.0.0" }, "scripts": { "build": "babel src -d ${DEST:-build} --source-maps --copy-files", diff --git a/packages/webiny-app-cms/src/admin/app.js b/packages/webiny-app-cms/src/admin/app.js deleted file mode 100644 index e348112a7a7..00000000000 --- a/packages/webiny-app-cms/src/admin/app.js +++ /dev/null @@ -1,99 +0,0 @@ -// @flow -import React from "react"; -import "react-sortable-tree/style.css"; -import { i18n } from "webiny-app/i18n"; -import { addPlugin } from "webiny-plugins"; -import AdminLayout from "webiny-app-admin/components/Layouts/AdminLayout"; -import editorPlugins from "webiny-app-cms/editor/presets/default"; -import renderPlugins from "webiny-app-cms/render/presets/default"; -import { ReactComponent as PagesIcon } from "./assets/round-ballot-24px.svg"; -import plugins from "./plugins"; -import Categories from "./views/Categories/Categories"; -import Menus from "./views/Menus/Menus"; -import Pages from "./views/Pages/Pages"; -import Editor from "./views/Pages/Editor"; - -const t = i18n.namespace("Cms.Admin.Menu"); - -export default () => { - // CMS plugins - addPlugin(...editorPlugins, ...renderPlugins, ...plugins); - - // Navigation plugin - addPlugin({ - name: "cms-menu", - type: "menu", - render({ Menu }) { - return ( - }> - - - - - - - ); - } - }); - - addPlugin({ - name: "route-cms-categories", - type: "route", - route: { - name: "Cms.Categories", - path: "/cms/categories", - render() { - return ( - - - - ); - } - } - }); - - addPlugin({ - name: "route-cms-menus", - type: "route", - route: { - name: "Cms.Menus", - path: "/cms/menus", - exact: true, - render() { - return ( - - - - ); - } - } - }); - - addPlugin({ - name: "route-cms-pages", - type: "route", - route: { - name: "Cms.Pages", - path: "/cms/pages", - render() { - return ( - - - - ); - } - } - }); - - addPlugin({ - name: "route-cms-editor", - type: "route", - route: { - name: "Cms.Editor", - path: "/cms/editor/:id", - render() { - return ; - } - } - }); -}; diff --git a/packages/webiny-app-cms/src/admin/assets/add.svg b/packages/webiny-app-cms/src/admin/assets/add.svg index db268839dfd..3d4615c7e33 100644 --- a/packages/webiny-app-cms/src/admin/assets/add.svg +++ b/packages/webiny-app-cms/src/admin/assets/add.svg @@ -1,16 +1,5 @@ - - - - - - - - - - - - - - + + + + + \ No newline at end of file diff --git a/packages/webiny-app-cms/src/admin/assets/round-arrow_drop_down-24px.svg b/packages/webiny-app-cms/src/admin/assets/round-arrow_drop_down-24px.svg new file mode 100644 index 00000000000..d2a91682bb2 --- /dev/null +++ b/packages/webiny-app-cms/src/admin/assets/round-arrow_drop_down-24px.svg @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/packages/webiny-app-cms/src/admin/components/index.js b/packages/webiny-app-cms/src/admin/components/index.js index bf88b2fc37d..8938e881103 100644 --- a/packages/webiny-app-cms/src/admin/components/index.js +++ b/packages/webiny-app-cms/src/admin/components/index.js @@ -5,4 +5,5 @@ export { default as createElementPlugin } from "./withSavedElements/createElemen export { SimpleTagsMultiAutoComplete, TagsMultiAutoComplete } from "./TagsMultiAutoComplete"; export { default as CategoriesAutoComplete } from "./CategoriesAutoComplete"; export { default as createBlockPlugin } from "./withSavedElements/createBlockPlugin"; +export { default as withCmsSettings } from "./withCmsSettings"; export type { WithPageDetailsProps } from "./withPageDetails"; diff --git a/packages/webiny-app-cms/src/admin/components/withCmsSettings.js b/packages/webiny-app-cms/src/admin/components/withCmsSettings.js new file mode 100644 index 00000000000..bd394c0c70e --- /dev/null +++ b/packages/webiny-app-cms/src/admin/components/withCmsSettings.js @@ -0,0 +1,39 @@ +// @flow +import { compose, withHandlers, mapProps } from "recompose"; +import { graphql } from "react-apollo"; +import gql from "graphql-tag"; +import getPagePreviewUrl from "./withCmsSettings/getPagePreviewUrl"; +import { get } from "lodash"; + +export default () => + compose( + graphql( + gql` + { + settings { + cms { + domain + } + } + } + `, + { + name: "cmsSettings" + } + ), + withHandlers({ + getPagePreviewUrl: ({ cmsSettings }) => (page: Object) => { + const domain = get(cmsSettings, "settings.cms.domain"); + return getPagePreviewUrl({ page, domain }); + } + }), + mapProps(({ getPagePreviewUrl, cmsSettings, ...rest }) => { + return { + ...rest, + cmsSettings: { + data: get(cmsSettings, "settings.cms"), + getPagePreviewUrl + } + }; + }) + ); diff --git a/packages/webiny-app-cms/src/admin/components/withCmsSettings/getPagePreviewUrl.js b/packages/webiny-app-cms/src/admin/components/withCmsSettings/getPagePreviewUrl.js new file mode 100644 index 00000000000..112c4731e4e --- /dev/null +++ b/packages/webiny-app-cms/src/admin/components/withCmsSettings/getPagePreviewUrl.js @@ -0,0 +1,18 @@ +// @flow +import { trimEnd } from "lodash"; + +export default ({ page: { url, id }, domain }: Object) => { + if (!domain) { + return url; + } + + let previewUrl = "//"; + + // Removes protocol from the beggining of the URL. + previewUrl += domain.replace(/(^\w+:|^)\/\//, ""); + + previewUrl = trimEnd(previewUrl, "/"); + previewUrl += url; + previewUrl += "?preview=" + id; + return previewUrl; +}; diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/EditElementDialog.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/EditElementDialog.js new file mode 100644 index 00000000000..9e95673715b --- /dev/null +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/EditElementDialog.js @@ -0,0 +1,92 @@ +// @flow +import React from "react"; +import { compose, shouldUpdate } from "recompose"; +import { css } from "emotion"; +import { getPlugin } from "webiny-plugins"; +import { + Dialog, + DialogHeader, + DialogHeaderTitle, + DialogBody, + DialogFooter, + DialogFooterButton, + DialogCancel +} from "webiny-ui/Dialog"; +import { Input } from "webiny-ui/Input"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { Form } from "webiny-form"; +import styled from "react-emotion"; + +const narrowDialog = css({ + ".mdc-dialog__surface": { + width: 600, + minWidth: 600 + } +}); + +const PreviewBox = styled("div")({ + width: 500, + minHeight: 250, + border: "1px solid var(--mdc-theme-on-background)", + backgroundColor: "#fff", // this must always be white + display: "flex", + justifyContent: "center", + alignItems: "center", + img: { + maxHeight: 500, + maxWidth: 500 + } +}); + +type Props = { + open: boolean, + plugin: string, + onClose: Function, + onSubmit: Function +}; + +const EditElementDialog = (props: Props) => { + const { open, onClose, onSubmit, plugin: pluginName } = props; + + const plugin = getPlugin(pluginName); + + return ( + + {plugin && ( +
+ {({ submit, Bind }) => ( + + + Update {plugin.title} + + + + + + + + + + + + {plugin.toolbar.preview()} + + + + + Cancel + Save + + + )} +
+ )} +
+ ); +}; + +export default compose( + shouldUpdate((props, nextProps) => { + return props.open !== nextProps.open; + }) +)(EditElementDialog); diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/Title.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/Title.js index 1dd9f29496a..5931315e1d1 100644 --- a/packages/webiny-app-cms/src/admin/components/withSavedElements/Title.js +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/Title.js @@ -1,35 +1,72 @@ // @flow import * as React from "react"; import { graphql } from "react-apollo"; -import { compose, withHandlers } from "recompose"; +import { compose, withHandlers, withState } from "recompose"; import styled from "react-emotion"; -import { removePlugin } from "webiny-plugins"; +import { unregisterPlugin } from "webiny-plugins"; import { Typography } from "webiny-ui/Typography"; import { IconButton } from "webiny-ui/Button"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import { withConfirmation, type WithConfirmationProps } from "webiny-ui/ConfirmationDialog"; import { ReactComponent as DeleteIcon } from "webiny-app-cms/editor/assets/icons/close.svg"; +import { ReactComponent as EditIcon } from "webiny-app-cms/editor/assets/icons/edit.svg"; import { deleteElement } from "./graphql"; +import EditElementDialog from "./EditElementDialog"; +import createElementPlugin from "webiny-app-cms/admin/components/withSavedElements/createElementPlugin"; +import { updateElement } from "./graphql"; -const Icon = styled("div")({ +const EditIconWrapper = styled("div")({ position: "absolute", top: 0, - right: 15 + right: 48 +}); +const DeleteIconWrapper = styled("div")({ + position: "absolute", + top: 0, + right: 16 }); type Props = WithConfirmationProps & { title: string, - onDelete: Function + plugin: string, + refresh: Function, + deleteElement: Function, + updateElement: Function, + editDialogOpened: Function, + openEditDialog: Function }; -const Title = ({ title, onDelete }: Props) => { +const Title = (props: Props) => { + const { + plugin: pluginName, + deleteElement, + title, + updateElement, + editDialogOpened, + openEditDialog + } = props; + return ( - - {title} - - } onClick={onDelete} /> - - + <> + + {title} + <> + + } onClick={() => openEditDialog(true)} /> + {" "} + openEditDialog(false)} + /> + + + + } onClick={deleteElement} /> + + + ); }; @@ -43,16 +80,18 @@ export default compose( ) })), withSnackbar(), + withState("editDialogOpened", "openEditDialog", false), graphql(deleteElement, { name: "deleteElement" }), + graphql(updateElement, { name: "updateElement" }), withHandlers({ - onDelete: ({ + deleteElement: ({ id, title, plugin, showConfirmation, showSnackbar, deleteElement, - onDelete + refresh }) => () => { showConfirmation(async () => { const { data: res } = await deleteElement({ @@ -64,11 +103,9 @@ export default compose( return showSnackbar(error.message); } - removePlugin(plugin); + unregisterPlugin(plugin); - if (typeof onDelete === "function") { - onDelete(); - } + refresh(); showSnackbar( @@ -76,6 +113,42 @@ export default compose( ); }); + }, + updateElement: ({ + id, + showSnackbar, + updateElement, + openEditDialog, + refresh + }) => async plugin => { + const { title: name } = plugin; + const response = await updateElement({ + variables: { + id, + data: { name } + } + }); + + const { error, data } = response.data.cms.updateElement; + if (error) { + openEditDialog(false); + setTimeout(() => { + // For better UX, success message is shown after 300ms has passed. + showSnackbar(error.message); + }, 300); + + return; + } + + // This will replace previously registered block plugin. + createElementPlugin(data); + openEditDialog(false); + refresh(); + + setTimeout(() => { + // For better UX, success message is shown after 300ms has passed. + showSnackbar("Element " + plugin.title + " successfully saved."); + }, 300); } }) )(Title); diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/createBlockPlugin.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/createBlockPlugin.js index 7c75c2cf779..7b3f963e619 100644 --- a/packages/webiny-app-cms/src/admin/components/withSavedElements/createBlockPlugin.js +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/createBlockPlugin.js @@ -1,31 +1,41 @@ // @flow import React from "react"; import cloneDeep from "lodash/cloneDeep"; -import { addPlugin } from "webiny-plugins"; +import { registerPlugins } from "webiny-plugins"; +import { Image } from "webiny-ui/Image"; type Element = { id: string, name: string, type: string, + category: string, content: Object, - keywords: Array, preview: { - src: string + src: string, + width: number, + height: number } }; export default (el: Element) => { - addPlugin({ + registerPlugins({ + id: el.id, name: "cms-saved-block-" + el.id, type: "cms-block", + title: el.name, + category: el.category, tags: ["saved"], - keywords: el.keywords || [], + image: el.preview, create() { - return cloneDeep(el.content); + return cloneDeep({ ...el.content, source: el.id }); }, preview() { return ( - {el.name} + {el.name} ); } }); diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/createElementPlugin.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/createElementPlugin.js index 541a2acd204..4d4a666f5a0 100644 --- a/packages/webiny-app-cms/src/admin/components/withSavedElements/createElementPlugin.js +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/createElementPlugin.js @@ -1,7 +1,7 @@ // @flow import React from "react"; import cloneDeep from "lodash/cloneDeep"; -import { addPlugin, getPlugin } from "webiny-plugins"; +import { registerPlugins, getPlugin } from "webiny-plugins"; import Title from "./Title"; type Element = { @@ -9,7 +9,6 @@ type Element = { name: string, type: string, content: Object, - keywords: Array, preview: { src: string } @@ -23,13 +22,14 @@ export default (el: Element) => { const name = "cms-saved-element-" + el.id; - addPlugin({ + registerPlugins({ name, + title: el.name, type: "cms-element", target: rootPlugin.target, toolbar: { title({ refresh }) { - return ; + return <Title plugin={name} title={el.name} id={el.id} refresh={refresh} />; }, group: "cms-element-group-saved", preview() { @@ -37,7 +37,7 @@ export default (el: Element) => { <img src={el.preview.src} alt={el.name} - style={{ width: 227, height: "auto" }} + style={{ width: 227, height: "auto", backgroundColor: "#fff" }} /> ); } diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/graphql.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/graphql.js index 0c5b86c73bf..eaf1d3bb837 100644 --- a/packages/webiny-app-cms/src/admin/components/withSavedElements/graphql.js +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/graphql.js @@ -14,3 +14,25 @@ export const deleteElement = gql` } } `; + +export const updateElement = gql` + mutation updateElement($id: ID!, $data: UpdateElementInput!) { + cms { + updateElement(id: $id, data: $data) { + data { + id + name + type + category + content + preview { + src + } + } + error { + message + } + } + } + } +`; diff --git a/packages/webiny-app-cms/src/admin/components/withSavedElements/withSavedElements.js b/packages/webiny-app-cms/src/admin/components/withSavedElements/withSavedElements.js index 49ff32ad587..8a4c9a6188b 100644 --- a/packages/webiny-app-cms/src/admin/components/withSavedElements/withSavedElements.js +++ b/packages/webiny-app-cms/src/admin/components/withSavedElements/withSavedElements.js @@ -5,6 +5,8 @@ import { listElements } from "webiny-app-cms/admin/graphql/pages"; import createElementPlugin from "./createElementPlugin"; import createBlockPlugin from "./createBlockPlugin"; +let elementsAdded = false; + export const withSavedElements = () => graphql(listElements, { props: ({ data }) => { @@ -13,13 +15,16 @@ export const withSavedElements = () => } const elements = get(data, "cms.elements.data"); - elements.forEach(el => { - if (el.type === "element") { - createElementPlugin(el); - } else { - createBlockPlugin(el); - } - }); + if (!elementsAdded) { + elements.forEach(el => { + if (el.type === "element") { + createElementPlugin(el); + } else { + createBlockPlugin(el); + } + }); + elementsAdded = true; + } return { elements }; } diff --git a/packages/webiny-app-cms/src/admin/graphql/pages.js b/packages/webiny-app-cms/src/admin/graphql/pages.js index eeabef4542e..b66cb7471b1 100644 --- a/packages/webiny-app-cms/src/admin/graphql/pages.js +++ b/packages/webiny-app-cms/src/admin/graphql/pages.js @@ -136,21 +136,22 @@ export const deletePage = gql` } `; -const elementFields = ` +const elementFields = /*GraphQL*/ ` id name type +category content -keywords preview { src + meta } `; export const listElements = gql` query CmsListElements { cms { - elements: listElements { + elements: listElements(perPage: 1000) { data { ${elementFields} } @@ -171,3 +172,16 @@ export const createElement = gql` } } `; + +export const updateElement = gql` + mutation CmsUpdateElement($id: ID!, $data: UpdateElementInput!) { + cms { + element: updateElement(id: $id, data: $data) { + data { + ${elementFields} + } + ${error} + } + } + } +`; diff --git a/packages/webiny-app-cms/src/admin/index.js b/packages/webiny-app-cms/src/admin/index.js deleted file mode 100644 index 0808d49f2b4..00000000000 --- a/packages/webiny-app-cms/src/admin/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { default as app } from "./app"; diff --git a/packages/webiny-app-cms/src/admin/plugins/globalSearch/index.js b/packages/webiny-app-cms/src/admin/plugins/globalSearch/index.js index e134b24d135..d92ab6a9fe0 100644 --- a/packages/webiny-app-cms/src/admin/plugins/globalSearch/index.js +++ b/packages/webiny-app-cms/src/admin/plugins/globalSearch/index.js @@ -1,5 +1,5 @@ //@flow -import type { GlobalSearch } from "webiny-app-admin/types"; +import type { GlobalSearch } from "webiny-admin/types"; // Additional sections in global search. diff --git a/packages/webiny-app-cms/src/admin/plugins/index.js b/packages/webiny-app-cms/src/admin/plugins/index.js index 6773d533ccf..e26ac692e92 100644 --- a/packages/webiny-app-cms/src/admin/plugins/index.js +++ b/packages/webiny-app-cms/src/admin/plugins/index.js @@ -7,14 +7,22 @@ import icons from "./icons"; import menuItems from "./menuItems"; import globalSearch from "./globalSearch"; import settings from "./settings"; +import editorPlugins from "webiny-app-cms/editor/presets/default"; +import renderPlugins from "webiny-app-cms/render/presets/default"; +import routes from "./routes"; +import menus from "./menus"; export default [ - ...header, + header, revisionContent, - ...previewContent, + previewContent, pageRevisions, icons, - ...menuItems, - ...globalSearch, - ...settings + menuItems, + globalSearch, + settings, + editorPlugins, + renderPlugins, + routes, + menus ]; diff --git a/packages/webiny-app-cms/src/admin/plugins/menuItems/page/PagesAutoComplete.js b/packages/webiny-app-cms/src/admin/plugins/menuItems/page/PagesAutoComplete.js index a9dffb80e83..a7996bd10d2 100644 --- a/packages/webiny-app-cms/src/admin/plugins/menuItems/page/PagesAutoComplete.js +++ b/packages/webiny-app-cms/src/admin/plugins/menuItems/page/PagesAutoComplete.js @@ -7,12 +7,14 @@ import gql from "graphql-tag"; import { get } from "lodash"; import { Query } from "react-apollo"; -const loadPage = gql` - query LoadPage($id: ID!) { +// We utilize the same "listPages" GraphQL field. +const getPage = gql` + query listPages($parent: String) { cms { - getPage(id: $id) { + pages: listPages(parent: $parent) { data { - id + parent + published title } } @@ -20,12 +22,13 @@ const loadPage = gql` } `; -const loadPages = gql` - query LoadPages($search: String) { +const listPages = gql` + query listPages($search: String) { cms { pages: listPages(search: $search) { data { - id + parent + published title } } @@ -34,16 +37,29 @@ const loadPages = gql` `; const PagesAutoComplete = props => ( - <Query skip={!props.value} variables={{ id: props.value }} query={loadPage}> - {({ data }) => ( - <AutoComplete {...props} textProp={"title"} value={get(data, "cms.getPage.data")} /> - )} + <Query skip={!props.value} variables={{ parent: props.value }} query={getPage}> + {({ data }) => { + const value = get(data, "cms.pages.data.0"); + return ( + <AutoComplete + {...props} + description={ + value && + !value.published && + "Warning: page is not published, it will not be visible in the menu." + } + valueProp={"parent"} + textProp={"title"} + value={value} + /> + ); + }} </Query> ); export default compose( withAutoComplete({ response: data => get(data, "cms.pages"), - query: loadPages + query: listPages }) )(PagesAutoComplete); diff --git a/packages/webiny-app-cms/src/admin/plugins/menus.js b/packages/webiny-app-cms/src/admin/plugins/menus.js new file mode 100644 index 00000000000..8fe3cf988dd --- /dev/null +++ b/packages/webiny-app-cms/src/admin/plugins/menus.js @@ -0,0 +1,32 @@ +// @flow +import React from "react"; +import { ReactComponent as PagesIcon } from "webiny-app-cms/admin/assets/round-ballot-24px.svg"; +import { hasRoles } from "webiny-app-security"; + +export default [ + { + name: "cms-menu", + type: "menu", + render({ Menu }: Object) { + const { menus, categories, editor }: Object = (hasRoles({ + menus: ["cms-menus"], + categories: ["cms-categories"], + editor: ["cms-editor"] + }): any); + + if (menus || categories || editor) { + return ( + <Menu label={`Content`} icon={<PagesIcon />}> + <Menu label={`Pages`}> + {categories && <Menu label={`Categories`} route="Cms.Categories" />} + {editor && <Menu label={`Pages`} route="Cms.Pages" />} + {menus && <Menu label={`Menus`} route="Cms.Menus" />} + </Menu> + </Menu> + ); + } + + return null; + } + } +]; diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/Header.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/Header.js index 54f2947e2da..f26ce948366 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/Header.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/Header.js @@ -19,20 +19,17 @@ const headerTitle = css({ } }); -const headerActions = css({ - "&.mdc-layout-grid": { - borderBottom: "1px solid var(--mdc-theme-on-background)", - height: 50, - padding: "3px 5px 0 25px", - background: "var(--mdc-theme-surface)", - ".right": { - textAlign: "right" - } - } +const pageTitle = css({ + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis" }); -const pageVersion = css({ - color: "var(--mdc-theme-text-secondary-on-background)" +const headerActions = css({ + justifyContent: "flex-end", + marginRight: "-15px", + display: "flex", + alignItems: "center" }); type Props = WithPageDetailsProps; @@ -41,22 +38,11 @@ const PageActions = ({ pageDetails, pageDetails: { page } }: Props) => { return ( <React.Fragment> <Grid className={headerTitle}> - <Cell span={12}> - <Typography use="headline5"> - {page.title}{" "} - <span className={pageVersion}> - (v - {page.version}) - </span> - </Typography> - <br /> + <Cell span={8} className={pageTitle}> + <Typography use="headline5">{page.title}</Typography> </Cell> - </Grid> - <Grid className={headerActions}> - <Cell span={6}> + <Cell span={4} className={headerActions}> {renderPlugins("cms-page-details-header-left", { pageDetails })} - </Cell> - <Cell span={6} className={"right"}> {renderPlugins("cms-page-details-header-right", { pageDetails })} </Cell> </Grid> diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/deletePage/DeletePage.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/deletePage/DeletePage.js index 6608aefe104..45958289899 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/deletePage/DeletePage.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/deletePage/DeletePage.js @@ -4,7 +4,7 @@ import { compose, withHandlers } from "recompose"; import dot from "dot-prop-immutable"; import { graphql } from "react-apollo"; import { withRouter } from "webiny-app/components"; -import { withDialog, withSnackbar } from "webiny-app-admin/components"; +import { withDialog, withSnackbar } from "webiny-admin/components"; import { IconButton } from "webiny-ui/Button"; import { Tooltip } from "webiny-ui/Tooltip"; import { withConfirmation, type WithConfirmationProps } from "webiny-ui/ConfirmationDialog"; diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/EditRevision.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/EditRevision.js index d80998ee1da..b2c0bbd3d07 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/EditRevision.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/EditRevision.js @@ -1,26 +1,76 @@ +// @flow import React from "react"; import { withRouter, type WithRouterProps } from "webiny-app/components"; import { type WithPageDetailsProps } from "webiny-app-cms/admin/components"; import { IconButton } from "webiny-ui/Button"; import { Tooltip } from "webiny-ui/Tooltip"; +import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; import { ReactComponent as EditIcon } from "webiny-app-cms/admin/assets/edit.svg"; +import withRevisionHandlers from "../../pageRevisions/withRevisionHandlers"; +import { compose } from "recompose"; +import { createRevisionFrom } from "webiny-app-cms/admin/graphql/pages"; +import { graphql } from "react-apollo"; +import { withSnackbar, type WithSnackbarProps } from "webiny-admin/components"; +import { ReactComponent as CreateRevision } from "./icons/round-add-24px.svg"; -type Props = WithPageDetailsProps & WithRouterProps; +type Props = WithPageDetailsProps & WithRouterProps & { gqlCreate: Function } & WithSnackbarProps; + +const EditRevision = ({ pageDetails: { page }, router, gqlCreate, showSnackbar }: Props) => { + const unpublishedRevision = page.revisions.find(item => !item.published && !item.locked); + if (unpublishedRevision) { + return ( + <Tooltip content={"Edit"} placement={"top"}> + <IconButton + icon={<EditIcon />} + onClick={() => + router.goToRoute({ + name: "Cms.Editor", + params: { id: unpublishedRevision.id } + }) + } + /> + </Tooltip> + ); + } -const EditRevision = ({ pageDetails: { page }, router }: Props) => { return ( - <Tooltip content={"Edit"} placement={"top"}> - <IconButton - icon={<EditIcon />} - onClick={() => - router.goToRoute({ - name: "Cms.Editor", - params: { id: page.id } - }) - } - /> + <Tooltip content={"New draft"} placement={"top"}> + <ConfirmationDialog + title="Create new draft" + message="You are about to create a new draft, do you want to continue?" + > + {({ showConfirmation }) => ( + <IconButton + icon={<CreateRevision />} + onClick={() => { + const [latestRevision] = page.revisions; + + showConfirmation(async () => { + const { data: res } = await gqlCreate({ + variables: { revision: latestRevision.id } + }); + const { data, error } = res.cms.revision; + + if (error) { + return showSnackbar(error.message); + } + + router.goToRoute({ + name: "Cms.Editor", + params: { id: data.id } + }); + }); + }} + /> + )} + </ConfirmationDialog> </Tooltip> ); }; -export default withRouter()(EditRevision); +export default compose( + withSnackbar(), + graphql(createRevisionFrom, { name: "gqlCreate" }), + withRouter(), + withRevisionHandlers +)(EditRevision); diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/icons/round-add-24px.svg b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/icons/round-add-24px.svg new file mode 100644 index 00000000000..127d9cec8c9 --- /dev/null +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/editRevision/icons/round-add-24px.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path fill="none" d="M0 0h24v24H0V0z"/> + <path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4 11h-3v3c0 .55-.45 1-1 1s-1-.45-1-1v-3H8c-.55 0-1-.45-1-1s.45-1 1-1h3V8c0-.55.45-1 1-1s1 .45 1 1v3h3c.55 0 1 .45 1 1s-.45 1-1 1z"/> +</svg> \ No newline at end of file diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/revisionSelector/RevisionSelector.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/revisionSelector/RevisionSelector.js index fc5931fce63..898addcadcb 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/revisionSelector/RevisionSelector.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/header/revisionSelector/RevisionSelector.js @@ -1,28 +1,61 @@ +//@flow import React from "react"; import { css } from "emotion"; import { withRouter, type WithRouterProps } from "webiny-app/components"; import { type WithPageDetailsProps } from "webiny-app-cms/admin/components"; -import { Select } from "webiny-ui/Select"; +import { ButtonDefault } from "webiny-ui/src/Button"; +import { Icon } from "webiny-ui/src/Icon"; +import { ReactComponent as DownButton } from "webiny-app-cms/admin/assets/round-arrow_drop_down-24px.svg"; +import { MenuItem } from "@rmwc/menu"; +import { Typography } from "webiny-ui/Typography"; +import { Menu } from "webiny-ui/Menu"; -const smallSelect = css({ - maxWidth: 200 +const buttonStyle = css({ + "&.mdc-button": { + color: "var(--mdc-theme-text-primary-on-background) !important" + } +}); + +const menuList = css({ + ".mdc-list-item": { + flexDirection: "column", + justifyContent: "center", + alignItems: "baseline", + textAlign: "left" + } }); type Props = WithPageDetailsProps & WithRouterProps; const RevisionSelector = ({ router, pageDetails: { page } }: Props) => { return ( - <Select - value={page.id} - onChange={id => router.goToRoute({ params: { id } })} - className={smallSelect} + <Menu + className={menuList} + onSelect={evt => + router.goToRoute({ + params: { id: page.revisions[evt.detail.index].id }, + merge: true + }) + } + handle={ + <ButtonDefault className={buttonStyle}> + v{page.version} <Icon icon={<DownButton />} /> + </ButtonDefault> + } > - {page.revisions.map(({ id, version }) => ( - <option key={id} value={id}> - Revision #{version} - </option> - ))} - </Select> + {page.revisions.map(rev => { + let status = "draft"; + if (rev.published) status = "published"; + if (rev.locked && !rev.published) status = "locked"; + + return ( + <MenuItem key={rev.id}> + <Typography use={"body2"}>v{rev.version}</Typography> + <Typography use={"caption"}>({status})</Typography> + </MenuItem> + ); + })} + </Menu> ); }; diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/Revision.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/Revision.js index b7f1c93a430..107b83d717c 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/Revision.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/Revision.js @@ -1,6 +1,6 @@ // @flow import React from "react"; -import { compose, withProps, withState, withHandlers } from "recompose"; +import { compose } from "recompose"; import { css } from "emotion"; import TimeAgo from "timeago-react"; import { @@ -15,7 +15,7 @@ import { IconButton } from "webiny-ui/Button"; import { Icon } from "webiny-ui/Icon"; import { MenuItem, Menu, MenuDivider } from "webiny-ui/Menu"; import { withRouter } from "webiny-app/components"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; import { Tooltip } from "webiny-ui/Tooltip"; import { withPageDetails, type WithPageDetailsProps } from "webiny-app-cms/admin/components"; @@ -24,6 +24,12 @@ import { ReactComponent as LockIcon } from "webiny-app-cms/admin/assets/lock.svg import { ReactComponent as BeenHereIcon } from "webiny-app-cms/admin/assets/beenhere.svg"; import { ReactComponent as GestureIcon } from "webiny-app-cms/admin/assets/gesture.svg"; import withRevisionHandlers from "./withRevisionHandlers"; +import { withCmsSettings } from "webiny-app-cms/admin/components"; +import { ReactComponent as AddIcon } from "webiny-app-cms/admin/assets/add.svg"; +import { ReactComponent as EditIcon } from "webiny-app-cms/admin/assets/edit.svg"; +import { ReactComponent as PublishIcon } from "webiny-app-cms/admin/assets/round-publish-24px.svg"; +import { ReactComponent as DeleteIcon } from "webiny-app-cms/admin/assets/delete.svg"; +import { ReactComponent as PreviewIcon } from "webiny-app-cms/admin/assets/visibility.svg"; type RevisionProps = WithPageDetailsProps & { rev: Object, @@ -31,11 +37,18 @@ type RevisionProps = WithPageDetailsProps & { editRevision: Function, deleteRevision: Function, publishRevision: Function, - submitCreateRevision: Function + submitCreateRevision: Function, + cmsSettings: { getPagePreviewUrl: Function } }; const primaryColor = css({ color: "var(--mdc-theme-primary)" }); +const revisionsMenu = css({ + width: 250, + right: -105, + left: "auto !important" +}); + const getIcon = (rev: Object) => { switch (true) { case rev.locked && !rev.published: @@ -56,14 +69,15 @@ const getIcon = (rev: Object) => { } }; -const Revision = ({ - rev, - pageDetails: { page }, - createRevision, - editRevision, - deleteRevision, - publishRevision -}: RevisionProps) => { +const Revision = (props: RevisionProps) => { + const { + rev, + createRevision, + editRevision, + deleteRevision, + publishRevision, + cmsSettings: { getPagePreviewUrl } + } = props; const { icon, text: tooltipText } = getIcon(rev); return ( @@ -72,7 +86,7 @@ const Revision = ({ message={<span>Are you sure you want to delete this revision?</span>} > {({ showConfirmation }) => ( - <ListItem style={{ overflow: "visible" }}> + <ListItem> <ListItemGraphic> <Tooltip content={tooltipText} placement={"bottom"}> {icon} @@ -86,16 +100,49 @@ const Revision = ({ </ListItemTextSecondary> </ListItemText> <ListItemMeta> - <Menu handle={<IconButton icon={<MoreVerticalIcon />} />}> - <MenuItem onClick={createRevision}>New</MenuItem> - <MenuItem onClick={editRevision}>Edit</MenuItem> + <Menu + handle={<IconButton icon={<MoreVerticalIcon />} />} + className={revisionsMenu} + openSide={"left"} + > + <MenuItem onClick={createRevision}> + <ListItemGraphic> + <Icon icon={<AddIcon />} /> + </ListItemGraphic> + New from current + </MenuItem> + {!rev.locked && ( + <MenuItem onClick={editRevision}> + <ListItemGraphic> + <Icon icon={<EditIcon />} /> + </ListItemGraphic> + Edit + </MenuItem> + )} + {!rev.published && ( - <MenuItem onClick={() => publishRevision(rev)}>Publish</MenuItem> + <MenuItem onClick={() => publishRevision(rev)}> + <ListItemGraphic> + <Icon icon={<PublishIcon />} /> + </ListItemGraphic> + Publish + </MenuItem> )} + + <MenuItem onClick={() => window.open(getPagePreviewUrl(rev), "_blank")}> + <ListItemGraphic> + <Icon icon={<PreviewIcon />} /> + </ListItemGraphic> + Preview + </MenuItem> + {!rev.locked && ( <React.Fragment> <MenuDivider /> <MenuItem onClick={() => showConfirmation(deleteRevision)}> + <ListItemGraphic> + <Icon icon={<DeleteIcon />} /> + </ListItemGraphic> Delete </MenuItem> </React.Fragment> @@ -112,5 +159,6 @@ export default compose( withRouter(), withSnackbar(), withPageDetails(), - withRevisionHandlers + withRevisionHandlers, + withCmsSettings() )(Revision); diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/RevisionsList.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/RevisionsList.js index 9ae18c05af8..bb01f6b28f2 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/RevisionsList.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/RevisionsList.js @@ -10,6 +10,10 @@ type RevisionsProps = WithPageDetailsProps; const listWrapper = css({ margin: 25, + display: "flex", + flexDirection: "column", + overflow: "scroll", + maxHeight: "calc(100vh - 160px)", ".mdc-list .mdc-list-item": { borderBottom: "1px solid var(--mdc-theme-on-background)" }, diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/withRevisionHandlers.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/withRevisionHandlers.js index 35c0fbc568e..abb83ba0e69 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/withRevisionHandlers.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/pageRevisions/withRevisionHandlers.js @@ -26,7 +26,7 @@ export default compose( }, deleteRevision: ({ rev, - pageDetails: { page, revisions }, + pageDetails: { page }, gqlDelete, showSnackbar, router diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/PagePreview.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/PagePreview.js new file mode 100644 index 00000000000..301c8dfb7cf --- /dev/null +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/PagePreview.js @@ -0,0 +1,68 @@ +//@flow +import * as React from "react"; +import { css } from "emotion"; +import styled from "react-emotion"; +import { Typography } from "webiny-ui/src/Typography"; +import { Select } from "webiny-ui/src/Select"; +import RenderElement from "webiny-app-cms/render/components/Element"; +import Zoom from "./Zoom"; + +const pageInnerWrapper = css({ + overflowY: "scroll", + overflowX: "hidden", + height: "calc(100vh - 230px)", + position: "relative", + ".webiny-cms-page-document": { + transform: "scale(var(--webiny-cms-page-preview-scale))" + } +}); + +const PagePreviewToolbar = styled("div")({ + position: "sticky", + bottom: 0, + height: 30, + paddingLeft: 15, + color: "var(--mdc-theme-text-secondary-on-background)", + borderTop: "1px solid var(--mdc-theme-on-background)", + backgroundColor: "var(--mdc-theme-background)", + width: "100%", + transform: "translateZ(0)", + display: "flex", + overflow: "hidden", + select: { + fontSize: 14, + color: "var(--mdc-theme-text-secondary-on-background)", + width: 75 + } +}); + +type Props = { + pageDetails: Object +}; + +const PagePreview = ({ pageDetails }: Props) => { + return ( + <Zoom> + {({ zoom, setZoom }) => ( + <div + className={pageInnerWrapper} + style={{ "--webiny-cms-page-preview-scale": zoom }} + > + <RenderElement element={pageDetails.page.content} /> + <PagePreviewToolbar> + <span> + <Typography use={"overline"}>Zoom: </Typography> + </span> + <Select value={zoom.toString()} onChange={setZoom}> + <option value={"1"}>100%</option> + <option value={"0.75"}>75%</option> + <option value={"0.5"}>50%</option> + </Select> + </PagePreviewToolbar> + </div> + )} + </Zoom> + ); +}; + +export default PagePreview; diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/Zoom.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/Zoom.js new file mode 100644 index 00000000000..265a5fe3e9b --- /dev/null +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/Zoom.js @@ -0,0 +1,53 @@ +// @flow +import * as React from "react"; +import store from "store"; +import observe from "store/plugins/observe"; +store.addPlugin(observe); + +const LOCAL_STORAGE_KEY = "webiny_cms_page_zoom"; + +type State = { + zoom: number +}; + +class Zoom extends React.Component<*, State> { + constructor() { + super(); + + this.state = { + zoom: this.getZoomLevel() + }; + } + + componentDidMount() { + store.observe(LOCAL_STORAGE_KEY, async (zoom: string) => { + this.setState({ zoom: parseFloat(zoom) }); + }); + } + + setZoomLevel = (zoom: number) => { + store.set(LOCAL_STORAGE_KEY, zoom); + }; + + getZoomLevel = () => { + let zoom = store.get(LOCAL_STORAGE_KEY); + if (!zoom) { + switch (true) { + case window.innerWidth < 1600: + return 0.75; + case window.innerWidth < 1200: + return 0.5; + default: + return 1; + } + } + + return zoom; + }; + + render() { + return this.props.children({ zoom: this.state.zoom, setZoom: this.setZoomLevel }); + } +} + +export default Zoom; diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/index.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/index.js index 767e4ffcce5..bca22810702 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/index.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/previewContent/index.js @@ -3,9 +3,9 @@ import * as React from "react"; import { renderPlugins } from "webiny-app/plugins"; import type { CmsPageDetailsPluginType, WithPageDetailsProps } from "webiny-app-cms/types"; import { Tab } from "webiny-ui/Tabs"; -import RenderElement from "webiny-app-cms/render/components/Element"; import styled from "react-emotion"; import { Elevation } from "webiny-ui/Elevation"; +import PagePreview from "./PagePreview"; const RenderBlock = styled("div")({ position: "relative", @@ -16,12 +16,6 @@ const RenderBlock = styled("div")({ padding: 25 }); -const PageInnerWrapper = styled("div")({ - overflow: "scroll", - height: "calc(100vh - 265px)", - position: "relative" -}); - export default ([ { name: "cms-page-details-revision-content-preview", @@ -44,11 +38,7 @@ export default ([ name: "cms-page-details-revision-render", type: "cms-page-details-revision-content-preview", render({ pageDetails }: WithPageDetailsProps) { - return ( - <PageInnerWrapper> - <RenderElement element={pageDetails.page.content} /> - </PageInnerWrapper> - ); + return <PagePreview pageDetails={pageDetails} />; } } ]: Array<CmsPageDetailsPluginType>); diff --git a/packages/webiny-app-cms/src/admin/plugins/pageDetails/utils/withPublishRevisionHandler.js b/packages/webiny-app-cms/src/admin/plugins/pageDetails/utils/withPublishRevisionHandler.js index 1a0d1cc44bb..7eb85831223 100644 --- a/packages/webiny-app-cms/src/admin/plugins/pageDetails/utils/withPublishRevisionHandler.js +++ b/packages/webiny-app-cms/src/admin/plugins/pageDetails/utils/withPublishRevisionHandler.js @@ -3,7 +3,7 @@ import React from "react"; import { compose, withHandlers } from "recompose"; import { set } from "dot-prop-immutable"; import { graphql } from "react-apollo"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import { publishRevision, getPage } from "webiny-app-cms/admin/graphql/pages"; export default (prop: string) => { diff --git a/packages/webiny-app-cms/src/admin/plugins/routes.js b/packages/webiny-app-cms/src/admin/plugins/routes.js new file mode 100644 index 00000000000..3cb7916fee6 --- /dev/null +++ b/packages/webiny-app-cms/src/admin/plugins/routes.js @@ -0,0 +1,91 @@ +// @flow +import React from "react"; +import AdminLayout from "webiny-admin/components/Layouts/AdminLayout"; +import Categories from "webiny-app-cms/admin/views/Categories/Categories"; +import Menus from "webiny-app-cms/admin/views/Menus/Menus"; +import Pages from "webiny-app-cms/admin/views/Pages/Pages"; +import Editor from "webiny-app-cms/admin/views/Pages/Editor"; +import { SecureRoute } from "webiny-app-security/components"; +import Helmet from "react-helmet"; + +export default [ + { + name: "route-cms-categories", + type: "route", + route: { + name: "Cms.Categories", + path: "/cms/categories", + render() { + return ( + <SecureRoute roles={["cms-categories"]}> + <Helmet> + <title>CMS - Categories + + + + + + ); + } + } + }, + { + name: "route-cms-menus", + type: "route", + route: { + name: "Cms.Menus", + path: "/cms/menus", + exact: true, + render() { + return ( + + + CMS - Menus + + + + + + ); + } + } + }, + { + name: "route-cms-pages", + type: "route", + route: { + name: "Cms.Pages", + path: "/cms/pages", + render() { + return ( + + + CMS - Pages + + + + + + ); + } + } + }, + { + name: "route-cms-editor", + type: "route", + route: { + name: "Cms.Editor", + path: "/cms/editor/:id", + render() { + return ( + + + CMS - Edit page + + + + ); + } + } + } +]; diff --git a/packages/webiny-app-cms/src/admin/plugins/settings/components/CmsSettings.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/CmsSettings.js index bffc859116c..538986391db 100644 --- a/packages/webiny-app-cms/src/admin/plugins/settings/components/CmsSettings.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/components/CmsSettings.js @@ -4,7 +4,7 @@ import { Form } from "webiny-form"; import { Grid, Cell } from "webiny-ui/Grid"; import { ButtonPrimary } from "webiny-ui/Button"; import { Query, Mutation } from "react-apollo"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import graphql from "./graphql"; import PagesAutoComplete from "./PagesAutoComplete"; @@ -13,7 +13,7 @@ import { SimpleFormFooter, SimpleFormContent, SimpleFormHeader -} from "webiny-app-admin/components/Views/SimpleForm"; +} from "webiny-admin/components/Views/SimpleForm"; const CmsSettings = ({ showSnackbar }) => { return ( diff --git a/packages/webiny-app-cms/src/admin/plugins/settings/components/PagesAutoComplete.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/PagesAutoComplete.js index ceb8a199831..1f6b6a20c63 100644 --- a/packages/webiny-app-cms/src/admin/plugins/settings/components/PagesAutoComplete.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/components/PagesAutoComplete.js @@ -5,13 +5,30 @@ import { withAutoComplete } from "webiny-app/components"; import { compose } from "recompose"; import gql from "graphql-tag"; import { get } from "lodash"; +import { Query } from "react-apollo"; -const loadPages = gql` - query LoadPages($search: String) { +// We utilize the same "listPages" GraphQL field. +const getPage = gql` + query listPages($parent: String) { + cms { + pages: listPages(parent: $parent) { + data { + parent + published + title + } + } + } + } +`; + +const listPages = gql` + query listPages($search: String) { cms { pages: listPages(search: $search) { data { - id + parent + published title } } @@ -19,11 +36,26 @@ const loadPages = gql` } `; -const PagesAutoComplete = props => ; +const PagesAutoComplete = props => ( + + {({ data }) => { + const value = get(data, "cms.pages.data.0"); + return ( + + ); + }} + +); export default compose( withAutoComplete({ response: data => get(data, "cms.pages"), - query: loadPages + query: listPages }) )(PagesAutoComplete); diff --git a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/GeneralSettings.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/GeneralSettings.js similarity index 94% rename from packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/GeneralSettings.js rename to packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/GeneralSettings.js index 7fff7f00c97..46307779e84 100644 --- a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/GeneralSettings.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/GeneralSettings.js @@ -6,7 +6,7 @@ import { Input } from "webiny-ui/Input"; import { ButtonPrimary } from "webiny-ui/Button"; import Image from "./Image"; import { Query, Mutation } from "react-apollo"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import graphql from "./graphql"; import { @@ -14,7 +14,7 @@ import { SimpleFormFooter, SimpleFormContent, SimpleFormHeader -} from "webiny-app-admin/components/Views/SimpleForm"; +} from "webiny-admin/components/Views/SimpleForm"; const GeneralSettings = ({ showSnackbar }) => { return ( @@ -27,7 +27,7 @@ const GeneralSettings = ({ showSnackbar }) => { onSubmit={async data => { await update({ variables: { - data: data.general + data: data.cms } }); showSnackbar("Settings updated successfully."); @@ -41,7 +41,7 @@ const GeneralSettings = ({ showSnackbar }) => { - + { - + - + @@ -65,7 +65,7 @@ const GeneralSettings = ({ showSnackbar }) => { @@ -73,7 +73,7 @@ const GeneralSettings = ({ showSnackbar }) => { @@ -81,7 +81,7 @@ const GeneralSettings = ({ showSnackbar }) => { diff --git a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/Image.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/Image.js similarity index 100% rename from packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/Image.js rename to packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/Image.js diff --git a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/graphql.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/graphql.js similarity index 77% rename from packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/graphql.js rename to packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/graphql.js index 7f3ac141ab8..9c3850c88a7 100644 --- a/packages/webiny-app-admin/src/plugins/Settings/GeneralSettings/components/graphql.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/components/generalSettings/graphql.js @@ -22,14 +22,14 @@ const graphql = { query: gql` query getSettings { settings { - general ${fields} + cms ${fields} } } `, mutation: gql` - mutation updateSettings($data: GeneralSettingsInput) { + mutation updateSettings($data: CmsSettingsInput) { settings { - general(data: $data) ${fields} + cms(data: $data) ${fields} } } ` diff --git a/packages/webiny-app-cms/src/admin/plugins/settings/components/graphql.js b/packages/webiny-app-cms/src/admin/plugins/settings/components/graphql.js index b6b8fb57a5e..a57b59e03e3 100644 --- a/packages/webiny-app-cms/src/admin/plugins/settings/components/graphql.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/components/graphql.js @@ -4,18 +4,9 @@ import gql from "graphql-tag"; const fields = /* GraphQL */ ` { pages { - home { - id - title - } - notFound { - id - title - } - error { - id - title - } + home + notFound + error } } `; diff --git a/packages/webiny-app-cms/src/admin/plugins/settings/index.js b/packages/webiny-app-cms/src/admin/plugins/settings/index.js index 7a3e20ce325..84deb99b36c 100644 --- a/packages/webiny-app-cms/src/admin/plugins/settings/index.js +++ b/packages/webiny-app-cms/src/admin/plugins/settings/index.js @@ -1,21 +1,51 @@ // @flow import * as React from "react"; import CmsSettings from "./components/CmsSettings"; -import type { SettingsPluginType } from "webiny-app-admin/types"; +import GeneralSettings from "./components/generalSettings/GeneralSettings"; +import type { SettingsPluginType } from "webiny-admin/types"; +import { hasRoles } from "webiny-app-security"; +import { SecureRoute } from "webiny-app-security/components"; export default ([ { type: "settings", name: "settings-cms", settings: { + show: () => { + return hasRoles(["cms-settings", "cms-editor"]); + }, type: "app", name: "CMS", - component: , + component: ( + + + + ), route: { name: "Settings.Cms", path: "/cms", - title: "CMS", - group: undefined + title: "CMS" + } + } + }, + { + type: "settings", + name: "settings-general-settings", + settings: { + show: () => { + return hasRoles(["cms-settings"]); + }, + type: "other", + name: "General settings", + component: ( + + + + ), + route: { + name: "Settings.GeneralSettings", + path: "/general", + title: "General Settings" } } } diff --git a/packages/webiny-app-cms/src/admin/views/Categories/Categories.js b/packages/webiny-app-cms/src/admin/views/Categories/Categories.js index 5df237b5ad9..e1b300dd160 100644 --- a/packages/webiny-app-cms/src/admin/views/Categories/Categories.js +++ b/packages/webiny-app-cms/src/admin/views/Categories/Categories.js @@ -3,9 +3,9 @@ import * as React from "react"; import { get } from "dot-prop-immutable"; import { pick } from "lodash"; import { i18n } from "webiny-app/i18n"; -import { withCrud, type WithCrudProps } from "webiny-app-admin/components"; -import { CompactView, LeftPanel, RightPanel } from "webiny-app-admin/components/Views/CompactView"; -import FloatingActionButton from "webiny-app-admin/components/FloatingActionButton"; +import { withCrud, type WithCrudProps } from "webiny-admin/components"; +import { CompactView, LeftPanel, RightPanel } from "webiny-admin/components/Views/CompactView"; +import FloatingActionButton from "webiny-admin/components/FloatingActionButton"; import CategoriesDataList from "./CategoriesDataList"; import CategoriesForm from "./CategoriesForm"; diff --git a/packages/webiny-app-cms/src/admin/views/Categories/CategoriesDataList.js b/packages/webiny-app-cms/src/admin/views/Categories/CategoriesDataList.js index bf5d505c186..fd746d1f446 100644 --- a/packages/webiny-app-cms/src/admin/views/Categories/CategoriesDataList.js +++ b/packages/webiny-app-cms/src/admin/views/Categories/CategoriesDataList.js @@ -1,7 +1,7 @@ // @flow import * as React from "react"; import { i18n } from "webiny-app/i18n"; -import type { WithCrudListProps } from "webiny-app-admin/components"; +import type { WithCrudListProps } from "webiny-admin/components"; import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; import { DeleteIcon } from "webiny-ui/List/DataList/icons"; import { diff --git a/packages/webiny-app-cms/src/admin/views/Categories/CategoriesForm.js b/packages/webiny-app-cms/src/admin/views/Categories/CategoriesForm.js index 821606cb675..5e560e95e45 100644 --- a/packages/webiny-app-cms/src/admin/views/Categories/CategoriesForm.js +++ b/packages/webiny-app-cms/src/admin/views/Categories/CategoriesForm.js @@ -6,13 +6,13 @@ import { Grid, Cell } from "webiny-ui/Grid"; import { Input } from "webiny-ui/Input"; import { Select } from "webiny-ui/Select"; import { ButtonPrimary } from "webiny-ui/Button"; -import type { WithCrudFormProps } from "webiny-app-admin/components"; +import type { WithCrudFormProps } from "webiny-admin/components"; import { withCms, type WithCmsPropsType } from "webiny-app-cms/context"; import { SimpleForm, SimpleFormFooter, SimpleFormContent -} from "webiny-app-admin/components/Views/SimpleForm"; +} from "webiny-admin/components/Views/SimpleForm"; import { categoryUrlValidator } from "./validators"; const t = i18n.namespace("Cms.CategoriesForm"); diff --git a/packages/webiny-app-cms/src/admin/views/Menus/Menus.js b/packages/webiny-app-cms/src/admin/views/Menus/Menus.js index 7cddab4770b..8651fa75d82 100644 --- a/packages/webiny-app-cms/src/admin/views/Menus/Menus.js +++ b/packages/webiny-app-cms/src/admin/views/Menus/Menus.js @@ -3,9 +3,9 @@ import * as React from "react"; import { get } from "dot-prop-immutable"; import { pick } from "lodash"; import { i18n } from "webiny-app/i18n"; -import { withCrud, type WithCrudProps } from "webiny-app-admin/components"; -import { CompactView, LeftPanel, RightPanel } from "webiny-app-admin/components/Views/CompactView"; -import FloatingActionButton from "webiny-app-admin/components/FloatingActionButton"; +import { withCrud, type WithCrudProps } from "webiny-admin/components"; +import { CompactView, LeftPanel, RightPanel } from "webiny-admin/components/Views/CompactView"; +import FloatingActionButton from "webiny-admin/components/FloatingActionButton"; import MenusDataList from "./MenusDataList"; import MenusForm from "./MenusForm"; @@ -61,7 +61,7 @@ export default withCrud({ variables: data => ({ data: pick(data, ["items", "title", "slug", "description"]) }), - snackbar: data => t`Menu {name} saved successfully.`({ name: data.name }) + snackbar: data => t`Menu {name} saved successfully.`({ name: data.title }) } } })(Menus); diff --git a/packages/webiny-app-cms/src/admin/views/Menus/MenusDataList.js b/packages/webiny-app-cms/src/admin/views/Menus/MenusDataList.js index 4436db996b8..b29c4d13f2c 100644 --- a/packages/webiny-app-cms/src/admin/views/Menus/MenusDataList.js +++ b/packages/webiny-app-cms/src/admin/views/Menus/MenusDataList.js @@ -1,7 +1,7 @@ // @flow import * as React from "react"; import { i18n } from "webiny-app/i18n"; -import type { WithCrudListProps } from "webiny-app-admin/components"; +import type { WithCrudListProps } from "webiny-admin/components"; import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; import { DeleteIcon } from "webiny-ui/List/DataList/icons"; import { diff --git a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm.js b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm.js index 92915768eef..d1be4184896 100644 --- a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm.js +++ b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm.js @@ -6,12 +6,12 @@ import { Grid, Cell } from "webiny-ui/Grid"; import { Input } from "webiny-ui/Input"; import { ButtonPrimary } from "webiny-ui/Button"; import MenuItems from "./MenusForm/MenuItems"; -import type { WithCrudFormProps } from "webiny-app-admin/components"; +import type { WithCrudFormProps } from "webiny-admin/components"; import { SimpleForm, SimpleFormFooter, SimpleFormContent -} from "webiny-app-admin/components/Views/SimpleForm"; +} from "webiny-admin/components/Views/SimpleForm"; const t = i18n.namespace("Cms.MenusForm"); type Props = WithCrudFormProps; diff --git a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems.js b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems.js index ca814588e04..56b7c6ba546 100644 --- a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems.js +++ b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems.js @@ -25,6 +25,11 @@ const menuItems = css({ width: 170 }); +const MenuHolder = styled("div")({ + textAlign: "center", + color: "var(--mdc-theme-text-primary-on-background)" +}); + const AddMenu = styled("div")({ width: 180, margin: "25px auto 0 auto" @@ -86,7 +91,7 @@ class MenuItems extends React.Component { {!currentMenuItem && ( <> -
+ To build your menu you need to create menu items! Begin by clicking the "Add menu item" button @@ -113,7 +118,7 @@ class MenuItems extends React.Component {
- + )} {currentMenuItem && ( diff --git a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems/MenuItemRenderer.css b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems/MenuItemRenderer.css index a3e16381cea..2a2061fbcf9 100644 --- a/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems/MenuItemRenderer.css +++ b/packages/webiny-app-cms/src/admin/views/Menus/MenusForm/MenuItems/MenuItemRenderer.css @@ -341,4 +341,7 @@ .rst__rtl.rst__lineChildren::after { right: 50%; left: initial; +} +.rst__lineHalfHorizontalRight::before, .rst__lineFullVertical::after, .rst__lineHalfVerticalTop::after, .rst__lineHalfVerticalBottom::after, .rst__lineChildren::after{ + background-color: var(--mdc-theme-on-surface); } \ No newline at end of file diff --git a/packages/webiny-app-cms/src/admin/views/Pages/Editor.js b/packages/webiny-app-cms/src/admin/views/Pages/Editor.js index f14ea13c64e..9aa71d24e10 100644 --- a/packages/webiny-app-cms/src/admin/views/Pages/Editor.js +++ b/packages/webiny-app-cms/src/admin/views/Pages/Editor.js @@ -10,11 +10,13 @@ import { withRouter } from "webiny-app/components"; import { Query, withApollo } from "react-apollo"; import { getPage } from "webiny-app-cms/admin/graphql/pages"; import { withSavedElements } from "webiny-app-cms/admin/components"; -import Snackbar from "webiny-app-admin/plugins/Snackbar/Snackbar"; +import Snackbar from "webiny-admin/plugins/Snackbar/Snackbar"; +import { withSnackbar } from "webiny-admin/components"; + import { Typography } from "webiny-ui/Typography"; import { LoadingEditor, LoadingTitle } from "./EditorStyled.js"; import editorMock from "webiny-app-cms/admin/assets/editor-mock.png"; - +import { get } from "lodash"; const getEmptyData = (page = {}, revisions = []) => { return { ui: { @@ -32,9 +34,23 @@ const getEmptyData = (page = {}, revisions = []) => { let pageSet = null; -const Editor = ({ renderEditor, router }: Object) => { +const Editor = ({ renderEditor, router, showSnackbar }: Object) => { return ( - + { + const error = get(data, "cms.page.error.message"); + if (error) { + router.goToRoute({ + name: "Cms.Pages", + params: { id: null }, + merge: true + }); + showSnackbar(error); + } + }} + > {renderEditor} ); @@ -43,6 +59,7 @@ const Editor = ({ renderEditor, router }: Object) => { export default compose( withApollo, withRouter(), + withSnackbar(), withSavedElements(), withHandlers({ // eslint-disable-next-line react/display-name @@ -62,6 +79,10 @@ export default compose( ); } + if (!get(data, "cms.page.data")) { + return null; + } + if (!redux.store) { redux.initStore({}, { client }); } diff --git a/packages/webiny-app-cms/src/admin/views/Pages/PageDetails.js b/packages/webiny-app-cms/src/admin/views/Pages/PageDetails.js index ad55d215242..197ab275be7 100644 --- a/packages/webiny-app-cms/src/admin/views/Pages/PageDetails.js +++ b/packages/webiny-app-cms/src/admin/views/Pages/PageDetails.js @@ -12,12 +12,16 @@ import { getPage } from "webiny-app-cms/admin/graphql/pages"; import editorMock from "webiny-app-cms/admin/assets/editor-mock.png"; import { LoadingEditor, LoadingTitle } from "./EditorStyled.js"; import { PageDetailsProvider, PageDetailsConsumer } from "../../components/PageDetailsContext"; +import { ElementAnimation } from "webiny-app-cms/render/components"; +import { withSnackbar, type WithSnackbarProps } from "webiny-admin/components"; +import { get } from "lodash"; -type Props = WithRouterProps & { - pageId: string, - page: Object, - loading: boolean -}; +type Props = WithRouterProps & + WithSnackbarProps & { + pageId: string, + page: Object, + loading: boolean + }; const EmptySelect = styled("div")({ width: "100%", @@ -44,19 +48,36 @@ const DetailsContainer = styled("div")({ } }); -const PageDetails = ({ pageId }: Props) => { +const EmptyPageDetails = () => { + return ( + + + Select a page on the left side, or click the green button to create a new one. + + + ); +}; + +const PageDetails = ({ pageId, router, showSnackbar }: Props) => { if (!pageId) { - return ( - - - Select a page on the left side, or click the green button to create a new one. - - - ); + return ; } return ( - + { + const error = get(data, "cms.page.error.message"); + if (error) { + router.goToRoute({ + params: { id: null }, + merge: true + }); + showSnackbar(error); + } + }} + > {({ data, loading }) => { if (loading) { return ( @@ -74,19 +95,26 @@ const PageDetails = ({ pageId }: Props) => { } const details = { page: loading ? {} : data.cms.page.data, loading }; + if (!details.page) { + return ; + } return ( - - - - {pageDetails => ( - - {renderPlugins("cms-page-details", { pageDetails })} - - )} - - - + + {({ refresh }) => ( + + + + {pageDetails => ( + + {renderPlugins("cms-page-details", { pageDetails })} + + )} + + + + )} + ); }} @@ -95,6 +123,7 @@ const PageDetails = ({ pageId }: Props) => { export default compose( withRouter(), + withSnackbar(), withProps(({ router }) => ({ pageId: router.getQuery("id") })) diff --git a/packages/webiny-app-cms/src/admin/views/Pages/Pages.js b/packages/webiny-app-cms/src/admin/views/Pages/Pages.js index e34fc9e12a0..b4399b06ca6 100644 --- a/packages/webiny-app-cms/src/admin/views/Pages/Pages.js +++ b/packages/webiny-app-cms/src/admin/views/Pages/Pages.js @@ -2,10 +2,10 @@ import * as React from "react"; import { compose, withHandlers } from "recompose"; import { graphql } from "react-apollo"; -import { CompactView, LeftPanel, RightPanel } from "webiny-app-admin/components/Views/CompactView"; -import FloatingActionButton from "webiny-app-admin/components/FloatingActionButton"; +import { CompactView, LeftPanel, RightPanel } from "webiny-admin/components/Views/CompactView"; +import FloatingActionButton from "webiny-admin/components/FloatingActionButton"; import { withRouter, withDataList, type WithRouterProps } from "webiny-app/components"; -import { withSnackbar, type WithSnackbarProps } from "webiny-app-admin/components"; +import { withSnackbar, type WithSnackbarProps } from "webiny-admin/components"; import PagesDataList from "./PagesDataList"; import PageDetails from "./PageDetails"; import CategoriesDialog from "./CategoriesDialog"; diff --git a/packages/webiny-app-cms/src/editor/actions/actions.js b/packages/webiny-app-cms/src/editor/actions/actions.js index 61645683dda..25b2b2dbca2 100644 --- a/packages/webiny-app-cms/src/editor/actions/actions.js +++ b/packages/webiny-app-cms/src/editor/actions/actions.js @@ -2,7 +2,7 @@ import invariant from "invariant"; import dotProp from "dot-prop-immutable"; import gql from "graphql-tag"; -import { isEqual, pick, debounce, cloneDeep } from "lodash"; +import { isEqual, pick, debounce, cloneDeep, merge as _merge } from "lodash"; import { createAction, addMiddleware, @@ -18,27 +18,25 @@ import { import { updateChildPaths } from "webiny-app-cms/editor/utils"; import undoable from "./history"; -export const PREFIX = "[CMS]"; -export const DRAG_START = `${PREFIX} Drag start`; -export const DRAG_END = `${PREFIX} Drag end`; -export const ELEMENT_CREATED = `${PREFIX} Element created`; -export const ELEMENT_DROPPED = `${PREFIX} Element dropped`; -export const TOGGLE_PLUGIN = `${PREFIX} Toggle plugin`; -export const DEACTIVATE_PLUGIN = `${PREFIX} Deactivate plugin`; -export const FOCUS_SLATE_EDITOR = `${PREFIX} Focus slate editor`; -export const BLUR_SLATE_EDITOR = `${PREFIX} Blur slate editor`; -export const HIGHLIGHT_ELEMENT = `${PREFIX} Highlight element`; -export const ACTIVATE_ELEMENT = `${PREFIX} Activate element`; -export const DEACTIVATE_ELEMENT = `${PREFIX} Deactivate element`; -export const UPDATE_ELEMENT = `${PREFIX} Update element`; -export const DELETE_ELEMENT = `${PREFIX} Delete element`; -export const FLATTEN_ELEMENTS = `${PREFIX} Flatten elements`; -export const SET_TMP = `${PREFIX} Set tmp`; -export const SETUP_EDITOR = `${PREFIX} Setup editor`; -export const UPDATE_REVISION = `${PREFIX} Update revision`; -export const SAVING_REVISION = `${PREFIX} Save revision`; -export const START_SAVING = `${PREFIX} Started saving`; -export const FINISH_SAVING = `${PREFIX} Finished saving`; +export const DRAG_START = `Drag start`; +export const DRAG_END = `Drag end`; +export const ELEMENT_CREATED = `Element created`; +export const ELEMENT_DROPPED = `Element dropped`; +export const TOGGLE_PLUGIN = `Toggle plugin`; +export const DEACTIVATE_PLUGIN = `Deactivate plugin`; +export const FOCUS_SLATE_EDITOR = `Focus slate editor`; +export const BLUR_SLATE_EDITOR = `Blur slate editor`; +export const HIGHLIGHT_ELEMENT = `Highlight element`; +export const ACTIVATE_ELEMENT = `Activate element`; +export const DEACTIVATE_ELEMENT = `Deactivate element`; +export const UPDATE_ELEMENT = `Update element`; +export const DELETE_ELEMENT = `Delete element`; +export const FLATTEN_ELEMENTS = `Flatten elements`; +export const SETUP_EDITOR = `Setup editor`; +export const UPDATE_REVISION = `Update revision`; +export const SAVING_REVISION = `Save revision`; +export const START_SAVING = `Started saving`; +export const FINISH_SAVING = `Finished saving`; /***************** HISTORY REDUCER *****************/ const horStatePath = "page.content"; @@ -91,11 +89,6 @@ addReducer( ); /***************** EDITOR ACTIONS *****************/ -export const setTmp = createAction(SET_TMP); -addReducer([SET_TMP], "tmp", (state, action) => { - return dotProp.set(state, action.payload.key, action.payload.value); -}); - addReducer([SETUP_EDITOR], null, (state, action) => { return { ...state, ...action.payload }; }); @@ -191,12 +184,15 @@ addReducer( return "page.content." + action.payload.element.path.replace(/\./g, ".elements.").slice(2); }, (state, action) => { - const { element } = action.payload; + const { element, merge = false } = action.payload; if (element.elements && typeof element.elements[0] === "string") { delete element["elements"]; } updateChildPaths(element); - return { ...state, ...element }; + if (!merge) { + return { ...state, ...element }; + } + return _merge({}, state, element); } ); @@ -211,6 +207,7 @@ addMiddleware([DELETE_ELEMENT], ({ store, next, action }) => { let parent = getParentElementWithChildren(state, element.id); // Remove child from parent + // $FlowFixMe const index = parent.elements.findIndex(el => el.id === element.id); parent = dotProp.delete(parent, "elements." + index); store.dispatch(updateElement({ element: parent })); @@ -290,10 +287,10 @@ const flattenContent = el => { return els; }; -// TODO: remove elements flattening addReducer([FLATTEN_ELEMENTS], "elements", (state, action) => { return action.payload; }); + addMiddleware( [UPDATE_ELEMENT, DELETE_ELEMENT, "@@redux-undo/UNDO", "@@redux-undo/REDO", "@@redux-undo/INIT"], ({ store, next, action }) => { diff --git a/packages/webiny-app-cms/src/editor/assets/icons/edit.svg b/packages/webiny-app-cms/src/editor/assets/icons/edit.svg new file mode 100644 index 00000000000..77ebdee629d --- /dev/null +++ b/packages/webiny-app-cms/src/editor/assets/icons/edit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/webiny-app-cms/src/editor/components/DropZone/Center.js b/packages/webiny-app-cms/src/editor/components/DropZone/Center.js index 27f7f2ba276..528a0ef4114 100644 --- a/packages/webiny-app-cms/src/editor/components/DropZone/Center.js +++ b/packages/webiny-app-cms/src/editor/components/DropZone/Center.js @@ -48,9 +48,11 @@ const Center = pure(({ type, onDrop, children, active, highlight }: Props) => { return ( {({ isOver, isDroppable }) => ( - - {children} - +
+ + {children} + +
)}
); diff --git a/packages/webiny-app-cms/src/editor/components/DropZone/Horizontal.js b/packages/webiny-app-cms/src/editor/components/DropZone/Horizontal.js index 1a28b3c9ce4..f54eb7d8abc 100644 --- a/packages/webiny-app-cms/src/editor/components/DropZone/Horizontal.js +++ b/packages/webiny-app-cms/src/editor/components/DropZone/Horizontal.js @@ -6,7 +6,7 @@ import { pure } from "recompose"; const InnerDiv = styled("div")({ height: 5, - width: "calc(100% - 50px)", + width: "100%", //"calc(100% - 50px)", zIndex: 3, borderRadius: 5, boxSizing: "border-box", @@ -16,17 +16,19 @@ const InnerDiv = styled("div")({ const OuterDiv = pure( styled("div")( { - height: 20, + //height: 20, margin: 0, padding: 0, width: "100%", zIndex: 10, backgroundColor: "transparent", position: "absolute", - display: "flex" + display: "flex", + justifyContent: "center" }, props => ({ - alignItems: props.below ? "flex-end" : "flex-start", + //alignItems: props.below ? "flex-end" : "flex-start", + [props.below ? "bottom" : "top"]: 0, //[props.below ? "bottom" : "top"]: 0, [InnerDiv]: { backgroundColor: props.isOver @@ -49,9 +51,20 @@ const Horizontal = pure(({ below, onDrop, isVisible, type }: Props) => { return ( {({ isOver }) => ( - - - +
+ + + +
)}
); diff --git a/packages/webiny-app-cms/src/editor/components/DropZone/Vertical.js b/packages/webiny-app-cms/src/editor/components/DropZone/Vertical.js index d520dc694b0..23ed538507c 100644 --- a/packages/webiny-app-cms/src/editor/components/DropZone/Vertical.js +++ b/packages/webiny-app-cms/src/editor/components/DropZone/Vertical.js @@ -4,7 +4,7 @@ import { pure } from "recompose"; import styled from "react-emotion"; import Droppable from "./../Droppable"; -const InnerDiv = styled("div")({ +const InnerDivVertical = styled("div")({ position: "absolute", width: 5, height: "100%", @@ -13,7 +13,7 @@ const InnerDiv = styled("div")({ display: "none" }); -const OuterDiv = pure( +const OuterDivVertical = pure( styled("div")( { position: "absolute", @@ -26,7 +26,7 @@ const OuterDiv = pure( props => ({ [props.last ? "right" : "left"]: -2, textAlign: props.last ? "right" : "left", - [InnerDiv]: { + [InnerDivVertical]: { backgroundColor: props.isOver ? "var(--mdc-theme-primary)" : "var(--mdc-theme-secondary)", @@ -48,9 +48,20 @@ const Vertical = pure(({ last, onDrop, isVisible, type }: Props) => { return ( {({ isOver }) => ( - - - +
+ + + +
)}
); diff --git a/packages/webiny-app-cms/src/editor/components/Droppable.js b/packages/webiny-app-cms/src/editor/components/Droppable.js index 3f57cf899f5..76ebb33fc17 100644 --- a/packages/webiny-app-cms/src/editor/components/Droppable.js +++ b/packages/webiny-app-cms/src/editor/components/Droppable.js @@ -1,5 +1,4 @@ // @flow -import React from "react"; import { DropTarget } from "react-dnd"; import { compose, pure } from "recompose"; import { connect } from "webiny-app-cms/editor/redux"; @@ -34,11 +33,7 @@ const Droppable = pure( return null; } - return connectDropTarget( -
- {children({ isDragging, isOver, isDroppable: isDroppable(item) })} -
- ); + return connectDropTarget(children({ isDragging, isOver, isDroppable: isDroppable(item) })); } ); diff --git a/packages/webiny-app-cms/src/editor/components/Editor/Content.js b/packages/webiny-app-cms/src/editor/components/Editor/Content.js index 1fd02a26d37..4601f5b756b 100644 --- a/packages/webiny-app-cms/src/editor/components/Editor/Content.js +++ b/packages/webiny-app-cms/src/editor/components/Editor/Content.js @@ -12,7 +12,11 @@ import Element from "webiny-app-cms/editor/components/Element"; import { Elevation } from "webiny-ui/Elevation"; const ContentContainer = styled("div")(({ theme }) => ({ - backgroundColor: get(theme, "colors.background") + backgroundColor: get(theme, "colors.background"), + ".webiny-cms-page-document": { + overflowY: "visible", // cuts off the block selector tooltip + overflowX: "visible" + } })); const contentContainerWrapper = css({ @@ -20,7 +24,7 @@ const contentContainerWrapper = css({ padding: 0, position: "absolute", width: "calc(100vw - 115px)", - overflow: "visible", + //overflow: "hidden", // cuts off the block selector tooltip top: 0, boxSizing: "border-box", zIndex: 1 diff --git a/packages/webiny-app-cms/src/editor/components/Editor/Toolbar.js b/packages/webiny-app-cms/src/editor/components/Editor/Toolbar.js index 45b967a6b79..91d6384b03e 100644 --- a/packages/webiny-app-cms/src/editor/components/Editor/Toolbar.js +++ b/packages/webiny-app-cms/src/editor/components/Editor/Toolbar.js @@ -27,7 +27,7 @@ const ToolbarContainer = styled("div")({ top: 64, height: "calc(100vh - 68px)", backgroundColor: "var(--mdc-theme-surface)", - boxShadow: "1px 0px 5px 0px rgba(128,128,128,1)", + boxShadow: "1px 0px 5px 0px var(--mdc-theme-on-background)", zIndex: 3 }); @@ -108,6 +108,7 @@ const Toolbar = ({ activePluginsTop }: Object) => { .map(plugin => ( {plugin.renderDrawer()} diff --git a/packages/webiny-app-cms/src/editor/components/Element.js b/packages/webiny-app-cms/src/editor/components/Element.js index 3d1987e05cd..49668cfd741 100644 --- a/packages/webiny-app-cms/src/editor/components/Element.js +++ b/packages/webiny-app-cms/src/editor/components/Element.js @@ -53,6 +53,7 @@ const Element = pure( if (!plugin) { return null; } + return ( {state => ( diff --git a/packages/webiny-app-cms/src/editor/components/Element/ElementStyled.js b/packages/webiny-app-cms/src/editor/components/Element/ElementStyled.js index 6a4b0beef3c..0bd40febf08 100644 --- a/packages/webiny-app-cms/src/editor/components/Element/ElementStyled.js +++ b/packages/webiny-app-cms/src/editor/components/Element/ElementStyled.js @@ -10,9 +10,9 @@ export const typeStyle = css({ position: "absolute", cursor: "pointer", display: "flex", - top: -20, + top: 0, //-22, boxSizing: "border-box", - right: 0, + right: 0, //-2, fontSize: 10, padding: 0, color: "#fff", @@ -61,8 +61,9 @@ export const ElementContainer = pure( content: "''", position: "absolute", zIndex: -1, - top: 0, - left: 0, + padding: 2, + top: -2, + left: -2, width: "100%", height: "100%", boxShadow: highlight ? "inset 0px 0px 0px 2px " + color : "none", @@ -78,15 +79,17 @@ export const ElementContainer = pure( } }, "> .innerWrapper": { - width: "100%" + width: "100%", + height: "100%", // note "auto" fixes the odd hover bug which resizes the column, but causes a bug with column vertical align + boxSizing: "border-box" }, "> .innerWrapper > .type": { display: highlight ? "block" : "none", width: !active ? "100%" : "100px", height: !active ? "100%" : "25px", - [!active ? "left" : "right"]: 0, + [!active ? "left" : "right"]: -2, position: "absolute", - top: 0, + top: -22, //0, zIndex: 10, transition: "background-color 0.2s", ".background": { @@ -97,7 +100,7 @@ export const ElementContainer = pure( width: "100%", height: "100%", cursor: "pointer", - top: 0, + top: 22, left: 0, transition: "background-color 0.2s" }, diff --git a/packages/webiny-app-cms/src/editor/components/OEmbed.js b/packages/webiny-app-cms/src/editor/components/OEmbed.js index cca95c4242a..8697dce93cf 100644 --- a/packages/webiny-app-cms/src/editor/components/OEmbed.js +++ b/packages/webiny-app-cms/src/editor/components/OEmbed.js @@ -9,7 +9,7 @@ import { set } from "dot-prop-immutable"; import gql from "graphql-tag"; import { graphql } from "react-apollo"; import { updateElement } from "webiny-app-cms/editor/actions"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; function appendSDK(props) { const { sdk, global, element } = props; diff --git a/packages/webiny-app-cms/src/editor/components/Slate/Slate.js b/packages/webiny-app-cms/src/editor/components/Slate/Slate.js index 648bbc1631d..d76298d545d 100644 --- a/packages/webiny-app-cms/src/editor/components/Slate/Slate.js +++ b/packages/webiny-app-cms/src/editor/components/Slate/Slate.js @@ -1,7 +1,6 @@ // @flow import React from "react"; import ReactDOM from "react-dom"; -import styled from "react-emotion"; import { connect } from "webiny-app-cms/editor/redux"; import { compose, pure } from "recompose"; import { get } from "lodash"; @@ -14,11 +13,6 @@ import { createValue } from "./index"; import Menu from "./Menu"; -const EditorStyle = styled("div")({ - fontSize: "1.2em", - lineHeight: "150%" -}); - class SlateEditor extends React.Component<*, *> { static defaultProps = { exclude: [] @@ -102,8 +96,9 @@ class SlateEditor extends React.Component<*, *> { // Position menu container const rect = this.getSelectionRect(); - menuContainer.style.position = "absolute"; - menuContainer.style.top = rect.top + "px"; + menuContainer.style.position = "fixed"; + menuContainer.style.zIndex = "500"; + menuContainer.style.top = rect.top - 20 + "px"; menuContainer.style.left = rect.left + "px"; menuContainer.style.width = rect.width + "px"; menuContainer.style.height = rect.height + "px"; @@ -142,22 +137,20 @@ class SlateEditor extends React.Component<*, *> { render() { return ( - - {!this.state.readOnly && this.renderFloatingMenu()} - - + {!this.state.readOnly && this.renderFloatingMenu()} + ); } diff --git a/packages/webiny-app-cms/src/editor/components/withOEmbedData.js b/packages/webiny-app-cms/src/editor/components/withOEmbedData.js index b054bcc509d..632f37a0029 100644 --- a/packages/webiny-app-cms/src/editor/components/withOEmbedData.js +++ b/packages/webiny-app-cms/src/editor/components/withOEmbedData.js @@ -1,6 +1,6 @@ import { withApollo } from "react-apollo"; import { compose, withHandlers } from "recompose"; -import { withSnackbar } from "webiny-app-admin/components"; +import { withSnackbar } from "webiny-admin/components"; import gql from "graphql-tag"; const oembedQuery = gql` diff --git a/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlockPreview.js b/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlockPreview.js index 90ea69517d9..ea24270f956 100644 --- a/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlockPreview.js +++ b/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlockPreview.js @@ -1,41 +1,88 @@ // @flow import * as React from "react"; -import { ButtonFloating } from "webiny-ui/Button"; +import { ButtonFloating, IconButton } from "webiny-ui/Button"; import { Elevation } from "webiny-ui/Elevation"; import { ReactComponent as AddIcon } from "webiny-app-cms/editor/assets/icons/add.svg"; import * as Styled from "./StyledComponents"; +import { Typography } from "webiny-ui/Typography"; +import { ReactComponent as EditIcon } from "./icons/round-edit-24px.svg"; +import { ConfirmationDialog } from "webiny-ui/ConfirmationDialog"; +import { ReactComponent as DeleteIcon } from "./icons/round-close-24px.svg"; +import { Tooltip } from "webiny-ui/Tooltip"; +import { isEqual } from "lodash"; class BlockPreview extends React.Component<*> { shouldComponentUpdate(props: Object) { - return props.plugin.name !== this.props.plugin.name; + return !isEqual(props.plugin, this.props.plugin); } render() { - const { plugin, addBlockToContent, deactivatePlugin } = this.props; - + const { + plugin, + addBlockToContent, + deactivatePlugin, + onEdit, + onDelete, + loadImage + } = this.props; + return ( - - - - - - { - addBlockToContent(plugin); - !e.shiftKey && - deactivatePlugin({ - name: "cms-search-blocks-bar" - }); - }} - icon={} - /> - - - - {plugin.preview()} - - + + + + + { + addBlockToContent(plugin); + !e.shiftKey && + deactivatePlugin({ + name: "cms-search-blocks-bar" + }); + }} + icon={} + /> + + {onDelete && ( + + + {({ showConfirmation }) => ( + <> + {plugin.id ? ( + } + onClick={() => showConfirmation(onDelete)} + /> + ) : ( + + } /> + + )} + + )} + + + )} + + {onEdit && ( + + {plugin.id ? ( + } onClick={onEdit} /> + ) : ( + + } /> + + )} + + )} + + {plugin.preview()} + + {plugin.title} + ); } diff --git a/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlocksList.js b/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlocksList.js new file mode 100644 index 00000000000..6a436553d57 --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/blockEditing/BlocksList.js @@ -0,0 +1,75 @@ +// @flow +import * as React from "react"; +import { get } from "lodash"; +import { List, WindowScroller } from "react-virtualized"; +import BlockPreview from "./BlockPreview"; + +const listWidth = 800; + +class BlocksList extends React.Component<*, *> { + state = { listHeight: 0 }; + + getRowHeight = ({ index }: Object) => { + let height = get(this.props.blocks[index], "image.meta.height", 50); + let width = get(this.props.blocks[index], "image.meta.width", 50); + + if (width > listWidth) { + let downscaleRatio = width / listWidth; + height = height / downscaleRatio; + } + + return height + 100; + }; + + renderRow = ({ index, key, style }: Object) => { + const { blocks, onEdit, onDelete, deactivatePlugin, addBlock } = this.props; + + const plugin = blocks[index]; + + return ( +
+ onEdit(plugin)} + onDelete={() => onDelete(plugin)} + addBlockToContent={addBlock} + deactivatePlugin={deactivatePlugin} + /> +
+ ); + }; + + render() { + const { blocks } = this.props; + + const rightPanelElement = document.getElementById("webiny-secondary-view-right-panel"); + if (!rightPanelElement) { + return null; + } + + return ( + + {({ isScrolling, registerChild, onChildScroll, scrollTop }) => ( +
+
+ +
+
+ )} +
+ ); + } +} + +export default BlocksList; diff --git a/packages/webiny-app-cms/src/editor/plugins/blockEditing/EditBlockDialog.js b/packages/webiny-app-cms/src/editor/plugins/blockEditing/EditBlockDialog.js new file mode 100644 index 00000000000..8e1dc8cc39a --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/blockEditing/EditBlockDialog.js @@ -0,0 +1,111 @@ +// @flow +import React from "react"; +import { compose, shouldUpdate } from "recompose"; +import { css } from "emotion"; +import { getPlugins } from "webiny-plugins"; +import { + Dialog, + DialogHeader, + DialogHeaderTitle, + DialogBody, + DialogFooter, + DialogFooterButton, + DialogCancel +} from "webiny-ui/Dialog"; +import { Input } from "webiny-ui/Input"; +import { Select } from "webiny-ui/Select"; +import { Grid, Cell } from "webiny-ui/Grid"; +import { Form } from "webiny-form"; +import styled from "react-emotion"; + +const narrowDialog = css({ + ".mdc-dialog__surface": { + width: 600, + minWidth: 600 + } +}); + +const PreviewBox = styled("div")({ + width: 500, + minHeight: 250, + border: "1px solid var(--mdc-theme-on-background)", + backgroundColor: "#fff", // this must always be white + display: "flex", + justifyContent: "center", + alignItems: "center", + img: { + maxHeight: 500, + maxWidth: 500 + } +}); + +type Props = { + open: boolean, + plugin: ?Object, + onClose: Function, + onSubmit: Function +}; + +const EditBlockDialog = (props: Props) => { + const { open, onClose, onSubmit, plugin } = props; + + const blockCategoriesOptions = getPlugins("cms-block-category").map((item: Object) => ({ + value: item.name, + label: item.title + })); + + return ( + + {plugin && ( +
+ {({ data, submit, Bind }) => ( + + + Update {plugin.title} + + + + + + + + + + {data.type === "cms-block" && ( + <> + + + + , + center: , + right: , + justify: +}; + +const HorizontalAlignAction = ({ element, children, alignElement, align }: Object) => { + const plugin = getPlugin(element.type); + if (!plugin) { + return null; + } + + return React.cloneElement(children, { onClick: alignElement, icon: icons[align] }); +}; + +const defaultOptions = { alignments: ["left", "center", "right", "justify"] }; + +export default compose( + connect( + state => ({ element: getActiveElement(state) }), + { updateElement } + ), + withProps(({ element }) => ({ + align: get(element, "data.settings.horizontalAlign") || "left" + })), + withHandlers({ + alignElement: ({ + updateElement, + element, + align, + options: { alignments } = defaultOptions + }) => { + return () => { + const types = Object.keys(icons).filter(key => alignments.includes(key)); + + const nextAlign = types[types.indexOf(align) + 1] || "left"; + + updateElement({ + element: set(element, "data.settings.horizontalAlign", nextAlign) + }); + }; + } + }) +)(HorizontalAlignAction); diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/AlignAction.js b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/HorizontalAlignFlex.js similarity index 74% rename from packages/webiny-app-cms/src/editor/plugins/elementSettings/align/AlignAction.js rename to packages/webiny-app-cms/src/editor/plugins/elementSettings/align/HorizontalAlignFlex.js index 5f00e313e21..b1da78c207f 100644 --- a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/AlignAction.js +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/HorizontalAlignFlex.js @@ -9,18 +9,16 @@ import { getActiveElement } from "webiny-app-cms/editor/selectors"; import { get } from "dot-prop-immutable"; import { ReactComponent as AlignCenterIcon } from "webiny-app-cms/editor/assets/icons/format_align_center.svg"; import { ReactComponent as AlignLeftIcon } from "webiny-app-cms/editor/assets/icons/format_align_left.svg"; -import { ReactComponent as AlignJustifyIcon } from "webiny-app-cms/editor/assets/icons/format_align_justify.svg"; import { ReactComponent as AlignRightIcon } from "webiny-app-cms/editor/assets/icons/format_align_right.svg"; // Icons map for dynamic render const icons = { - left: , + "flex-start": , center: , - right: , - justify: + "flex-end": }; -const CloneAction = ({ element, children, alignElement, align }: Object) => { +const HorizontalAlignActionFlex = ({ element, children, alignElement, align }: Object) => { const plugin = getPlugin(element.type); if (!plugin) { return null; @@ -34,18 +32,20 @@ export default compose( state => ({ element: getActiveElement(state) }), { updateElement } ), - withProps(({ element }) => ({ align: get(element, "settings.style.textAlign") || "left" })), + withProps(({ element }) => ({ + align: get(element, "data.settings.horizontalAlignFlex") || "flex-start" + })), withHandlers({ alignElement: ({ updateElement, element, align }) => { return () => { const alignments = Object.keys(icons); - const nextAlign = alignments[alignments.indexOf(align) + 1] || "left"; + const nextAlign = alignments[alignments.indexOf(align) + 1] || "flex-start"; updateElement({ - element: set(element, "settings.style.textAlign", nextAlign) + element: set(element, "data.settings.horizontalAlignFlex", nextAlign) }); }; } }) -)(CloneAction); +)(HorizontalAlignActionFlex); diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/VerticalAlignAction.js b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/VerticalAlignAction.js new file mode 100644 index 00000000000..943d02ba28e --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/VerticalAlignAction.js @@ -0,0 +1,51 @@ +// @flow +import * as React from "react"; +import { connect } from "webiny-app-cms/editor/redux"; +import { compose, withHandlers, withProps } from "recompose"; +import { getPlugin } from "webiny-plugins"; +import { set } from "dot-prop-immutable"; +import { updateElement } from "webiny-app-cms/editor/actions"; +import { getActiveElement } from "webiny-app-cms/editor/selectors"; +import { get } from "dot-prop-immutable"; +import { ReactComponent as AlignCenterIcon } from "./icons/round-border_horizontal-24px.svg"; +import { ReactComponent as AlignTopIcon } from "./icons/round-border_top-24px.svg"; +import { ReactComponent as AlignBottomIcon } from "./icons/round-border_bottom-24px.svg"; + +// Icons map for dynamic render +const icons = { + start: , + center: , + end: +}; + +const VerticalAlignAction = ({ element, children, alignElement, align }: Object) => { + const plugin = getPlugin(element.type); + if (!plugin) { + return null; + } + + return React.cloneElement(children, { onClick: alignElement, icon: icons[align] }); +}; + +export default compose( + connect( + state => ({ element: getActiveElement(state) }), + { updateElement } + ), + withProps(({ element }) => ({ + align: get(element, "data.settings.verticalAlign") || "start" + })), + withHandlers({ + alignElement: ({ updateElement, element, align }) => { + return () => { + const alignments = Object.keys(icons); + + const nextAlign = alignments[alignments.indexOf(align) + 1] || "start"; + + updateElement({ + element: set(element, "data.settings.verticalAlign", nextAlign) + }); + }; + } + }) +)(VerticalAlignAction); diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_bottom-24px.svg b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_bottom-24px.svg new file mode 100644 index 00000000000..ab2ddb4b4ee --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_bottom-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_horizontal-24px.svg b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_horizontal-24px.svg new file mode 100644 index 00000000000..3d85ea758a7 --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_horizontal-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_top-24px.svg b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_top-24px.svg new file mode 100644 index 00000000000..05a59285952 --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/icons/round-border_top-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/index.js b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/index.js index 6a23a839b03..9c3359763de 100644 --- a/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/index.js +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/align/index.js @@ -1,16 +1,42 @@ //@flow import React from "react"; import Action from "../components/Action"; -import AlignAction from "./AlignAction"; +import HorizontalAlignAction from "./HorizontalAlignAction"; +import HorizontalAlignFlexAction from "./HorizontalAlignFlex"; +import VerticalAlignAction from "./VerticalAlignAction"; -export default { - name: "cms-element-settings-align", - type: "cms-element-settings", - renderAction() { - return ( - - - - ); +export default [ + { + name: "cms-element-settings-horizontal-align", + type: "cms-element-settings", + renderAction({ options }: Object) { + return ( + + + + ); + } + }, + { + name: "cms-element-settings-horizontal-align-flex", + type: "cms-element-settings", + renderAction() { + return ( + + + + ); + } + }, + { + name: "cms-element-settings-vertical-align", + type: "cms-element-settings", + renderAction() { + return ( + + + + ); + } } -}; +]; diff --git a/packages/webiny-app-cms/src/editor/plugins/elementSettings/animation/AnimationSettings.js b/packages/webiny-app-cms/src/editor/plugins/elementSettings/animation/AnimationSettings.js new file mode 100644 index 00000000000..2c5a1fa67ac --- /dev/null +++ b/packages/webiny-app-cms/src/editor/plugins/elementSettings/animation/AnimationSettings.js @@ -0,0 +1,145 @@ +//@flow +import React from "react"; +import { connect } from "webiny-app-cms/editor/redux"; +import { compose } from "recompose"; +import { get, isEqual } from "lodash"; +import { Tabs, Tab } from "webiny-ui/Tabs"; +import { getActiveElement } from "webiny-app-cms/editor/selectors"; +import withUpdateHandlers from "../components/withUpdateHandlers"; +import Footer from "../components/Footer"; +import Select from "../components/Select"; +import Input from "../components/Input"; +import DurationInput from "../components/SliderWithInput"; +import { ReactComponent as TimerIcon } from "./icons/round-av_timer-24px.svg"; + +import ElementAnimation from "webiny-app-cms/render/components/ElementAnimation"; + +type Props = Object & { + value: Object | number +}; + +const DATA_NAMESPACE = "data.settings.animation"; + +const Settings = ({ title, advanced, getUpdateValue, getUpdatePreview }: Props) => { + return ( + + + + + + {advanced && ( + <> + } + valueKey={DATA_NAMESPACE + ".duration"} + updateValue={getUpdateValue("duration")} + updatePreview={getUpdatePreview("duration")} + /> + + + + + + + )} +