├── .gitattributes ├── .gitignore ├── App.yaml ├── Cli ├── Api │ ├── README.md │ ├── index.js │ └── static │ │ ├── index.html │ │ └── logo_orange.png ├── Build │ ├── README.md │ ├── bundler.js │ ├── index.js │ ├── task.js │ └── webpack │ │ ├── app.dev.js │ │ ├── app.js │ │ ├── app.prod.js │ │ ├── eslint.js │ │ ├── externals.js │ │ ├── loaders │ │ ├── hot-accept-loader │ │ │ └── index.js │ │ └── i18n-loader │ │ │ └── index.js │ │ ├── plugins │ │ ├── Assets.js │ │ ├── ChunkIds.js │ │ └── ModuleIds.js │ │ ├── resolve.js │ │ ├── styles.js │ │ └── vendor.js ├── CreateAdmin │ ├── README.md │ └── index.js ├── Deploy │ ├── README.md │ ├── index.js │ └── task.js ├── Develop │ ├── README.md │ ├── index.js │ └── task.js ├── Exit │ ├── README.md │ └── index.js ├── InstallApp │ ├── README.md │ └── index.js ├── InstallDevApp │ ├── README.md │ └── index.js ├── Overrides │ ├── MultiCompiler.js │ └── index.js ├── README.md ├── ReleaseArchive │ ├── index.js │ └── task.js ├── RunTests │ └── index.js ├── ServerHelp │ └── index.js ├── Setup │ ├── host.cfg │ ├── index.js │ └── interfaces.js └── SwitchRelease │ ├── index.js │ └── task.js ├── Js ├── Backend │ ├── App.js │ ├── Assets │ │ ├── images │ │ │ ├── infinity.png │ │ │ └── logo.png │ │ └── mp-images │ │ │ ├── app-image.png │ │ │ ├── ss3.png │ │ │ └── ss5.png │ ├── Components │ │ ├── UserPermissions │ │ │ └── index.js │ │ ├── UserRoleGroups │ │ │ └── index.js │ │ ├── UserRoles │ │ │ └── index.js │ │ └── index.js │ └── Modules │ │ ├── Acl │ │ ├── Views │ │ │ ├── ApiLogsList.jsx │ │ │ ├── ApiTokensList.jsx │ │ │ ├── Components │ │ │ │ ├── AccessBox │ │ │ │ │ ├── EntityBox.jsx │ │ │ │ │ ├── MethodTooltip.jsx │ │ │ │ │ ├── ServiceBox.jsx │ │ │ │ │ ├── ToggleAccessButton.jsx │ │ │ │ │ └── styles.css │ │ │ │ ├── AddEntityModal.jsx │ │ │ │ ├── AddServiceModal.jsx │ │ │ │ ├── EntityPermissions.jsx │ │ │ │ ├── ServicePermissions.jsx │ │ │ │ ├── matchOption.js │ │ │ │ └── styles.css │ │ │ ├── Modal │ │ │ │ ├── ApiTokenModal.jsx │ │ │ │ ├── ExportModal.jsx │ │ │ │ ├── ImportModal.jsx │ │ │ │ └── SystemApiToken.jsx │ │ │ ├── UserPermissionsForm.jsx │ │ │ ├── UserPermissionsList.jsx │ │ │ ├── UserRoleGroupsForm.jsx │ │ │ ├── UserRoleGroupsList.jsx │ │ │ ├── UserRolesForm.jsx │ │ │ ├── UserRolesList.jsx │ │ │ ├── UsersForm.jsx │ │ │ ├── UsersList.jsx │ │ │ └── Views.js │ │ └── index.js │ │ ├── Dashboard │ │ ├── Views │ │ │ ├── Components │ │ │ │ └── Updates.jsx │ │ │ ├── Dashboard.jsx │ │ │ └── style.scss │ │ └── index.js │ │ ├── I18N │ │ ├── Views │ │ │ ├── LocalesList.jsx │ │ │ ├── LocalesList │ │ │ │ └── LocalesModal.jsx │ │ │ ├── TextGroupsList.jsx │ │ │ ├── TextGroupsList │ │ │ │ └── TextGroupsModal.jsx │ │ │ ├── TextsList.jsx │ │ │ ├── TextsList.scss │ │ │ ├── TextsList │ │ │ │ ├── ExportTextsModal.jsx │ │ │ │ ├── ImportTextsModal.jsx │ │ │ │ ├── ScanTextsModal.jsx │ │ │ │ └── TextsModal.jsx │ │ │ ├── TranslationsList.jsx │ │ │ ├── TranslationsList │ │ │ │ ├── ExportTranslationsModal.jsx │ │ │ │ ├── ImportTranslationsModal.jsx │ │ │ │ ├── TextRow.jsx │ │ │ │ ├── TextRow.scss │ │ │ │ ├── TranslatedTextPercentages.jsx │ │ │ │ ├── TranslatedTextPercentages.scss │ │ │ │ └── TranslationListRow │ │ │ │ │ ├── EditableTranslation.jsx │ │ │ │ │ └── EditableTranslation.scss │ │ │ └── Views.js │ │ └── index.js │ │ ├── Layout │ │ ├── Footer.js │ │ └── index.js │ │ ├── Logger │ │ ├── Views │ │ │ ├── ErrorCount.jsx │ │ │ ├── ErrorDetailsApi.jsx │ │ │ ├── ErrorDetailsJs.jsx │ │ │ ├── ErrorDetailsPhp.jsx │ │ │ ├── ErrorGroup.jsx │ │ │ ├── ListErrors.jsx │ │ │ ├── Main.jsx │ │ │ └── Views.js │ │ └── index.js │ │ └── Marketplace │ │ ├── Components │ │ ├── AppBox.jsx │ │ ├── AppDetails │ │ │ ├── Carousel.jsx │ │ │ ├── ContentBlock.jsx │ │ │ └── Sidebar.jsx │ │ ├── ForgotPasswordModal.jsx │ │ ├── InstallModal.jsx │ │ ├── RegisterModal.jsx │ │ ├── SubmitAppBox.jsx │ │ ├── UpdateModal.jsx │ │ ├── UpdateSuccessModal.jsx │ │ └── User.js │ │ ├── Views │ │ ├── AppDetails.jsx │ │ ├── Browse.jsx │ │ ├── LoginRegister.jsx │ │ ├── draft.scss │ │ └── styles.css │ │ └── index.js ├── Core │ ├── .eslintrc │ ├── App.js │ ├── Bootstrap.js │ ├── Lib │ │ ├── Api │ │ │ ├── Base.js │ │ │ ├── Endpoint.js │ │ │ ├── Response.js │ │ │ └── Uploader.js │ │ ├── Auth │ │ │ └── index.js │ │ ├── ClientStorage │ │ │ ├── LocalForage.js │ │ │ ├── Store.js │ │ │ └── index.js │ │ ├── Core │ │ │ ├── ApiComponent.js │ │ │ ├── App.js │ │ │ ├── AppModule.js │ │ │ ├── Component.js │ │ │ ├── DepsScanner.js │ │ │ ├── Dispatcher.js │ │ │ ├── Filter.js │ │ │ ├── FormComponent.js │ │ │ ├── Growl.js │ │ │ ├── LinkState.js │ │ │ ├── Menu.js │ │ │ ├── ModalComponent.js │ │ │ ├── Model.js │ │ │ ├── Module.js │ │ │ ├── ModuleLoader.js │ │ │ ├── OptionComponent.js │ │ │ ├── Page.js │ │ │ ├── View.js │ │ │ └── ViewManager.js │ │ ├── Draft │ │ │ ├── AtomicPlugin.js │ │ │ ├── BasePlugin.js │ │ │ ├── BlockTypePlugin.js │ │ │ ├── EntityPlugin.js │ │ │ ├── InlineStylePlugin.js │ │ │ └── index.js │ │ ├── Http │ │ │ ├── Http.js │ │ │ ├── Request.js │ │ │ └── Response.js │ │ ├── I18n │ │ │ ├── I18n.js │ │ │ ├── Modifiers │ │ │ │ ├── CountModifier.js │ │ │ │ ├── DateModifier.js │ │ │ │ ├── DateTimeModifier.js │ │ │ │ ├── GenderModifier.js │ │ │ │ ├── IfModifier.js │ │ │ │ ├── NumberModifier.js │ │ │ │ ├── PluralModifier.js │ │ │ │ ├── PriceModifier.js │ │ │ │ ├── TimeModifier.js │ │ │ │ └── index.js │ │ │ ├── PhpJsMap.js │ │ │ └── index.js │ │ ├── Router │ │ │ ├── AnchorClickHandler.js │ │ │ ├── Route.js │ │ │ ├── Router.js │ │ │ ├── RouterEvent.js │ │ │ └── RouterUtils.js │ │ ├── Ui │ │ │ ├── LazyLoad.js │ │ │ ├── Menu.js │ │ │ ├── Placeholder.js │ │ │ └── RootElement.js │ │ ├── Validation │ │ │ ├── ValidationError.js │ │ │ └── Validator.js │ │ ├── Webpack │ │ │ └── DllBootstrapPlugin.js │ │ ├── createComponent.js │ │ ├── index.js │ │ └── isElementOfType.js │ ├── Logger.js │ ├── TestLib │ │ └── TestSuite │ │ │ ├── Api.js │ │ │ └── Browser.js │ ├── Webiny.js │ └── webpack.vendor.js ├── Skeleton │ ├── App.js │ ├── Assets │ │ ├── fonts │ │ │ └── Fontello │ │ │ │ ├── config.json │ │ │ │ ├── fontello.eot │ │ │ │ ├── fontello.svg │ │ │ │ ├── fontello.ttf │ │ │ │ ├── fontello.woff │ │ │ │ └── fontello.woff2 │ │ ├── images │ │ │ ├── arr.png │ │ │ ├── arr_2.png │ │ │ ├── header_bg.jpg │ │ │ ├── icons.png │ │ │ ├── icons_retina.png │ │ │ ├── logo.png │ │ │ ├── logo_orange.png │ │ │ ├── public │ │ │ │ ├── bg-login.png │ │ │ │ ├── favicon.ico │ │ │ │ ├── logo_orange.png │ │ │ │ └── preloader_2.png │ │ │ ├── swich.png │ │ │ └── table_img.jpg │ │ ├── styles.scss │ │ └── styles │ │ │ └── sass │ │ │ ├── base │ │ │ ├── animations.scss │ │ │ ├── base.scss │ │ │ ├── fonts.scss │ │ │ ├── global.scss │ │ │ ├── reset.scss │ │ │ └── variables.scss │ │ │ ├── helpers │ │ │ └── _transitions.scss │ │ │ ├── partials │ │ │ ├── charts.scss │ │ │ ├── desktop-menu.scss │ │ │ ├── footer.scss │ │ │ ├── general.scss │ │ │ ├── header.scss │ │ │ ├── layout-header.scss │ │ │ ├── master-content.scss │ │ │ ├── mobile-menu.scss │ │ │ ├── modifiers.scss │ │ │ ├── navigation.scss │ │ │ ├── overwrites.scss │ │ │ └── signin.scss │ │ │ ├── vendor │ │ │ ├── fontello-codes.scss │ │ │ ├── fontello-embedded.scss │ │ │ ├── fontello-ie7-codes.scss │ │ │ ├── fontello-ie7.scss │ │ │ └── fontello.scss │ │ │ └── webiny.scss │ ├── Auth │ │ └── index.js │ ├── Components │ │ ├── Header │ │ │ └── index.js │ │ ├── Logo │ │ │ └── index.js │ │ ├── Navigation │ │ │ ├── Desktop.js │ │ │ ├── Mobile.js │ │ │ ├── index.js │ │ │ ├── styles.scss │ │ │ └── utils.js │ │ ├── Notifications │ │ │ ├── Container.js │ │ │ ├── Notification.js │ │ │ ├── NotificationModal.js │ │ │ └── Widget.js │ │ ├── UserMenu │ │ │ ├── AccountPreferences.js │ │ │ ├── Logout.js │ │ │ └── index.js │ │ └── index.js │ ├── Modules │ │ ├── Layout │ │ │ ├── Components │ │ │ │ └── Header.js │ │ │ ├── EmptyLayout.jsx │ │ │ ├── Layout.jsx │ │ │ ├── Views │ │ │ │ └── Dashboard.jsx │ │ │ └── index.js │ │ └── UserAccount │ │ │ ├── Components │ │ │ └── TwoFactorAuthConfirmation.jsx │ │ │ ├── UserAccountForm.js │ │ │ ├── UserNotificationsList.js │ │ │ └── index.js │ └── Views │ │ └── Auth │ │ ├── Forbidden.jsx │ │ ├── Login.jsx │ │ └── styles │ │ └── Login.css └── Ui │ ├── App.js │ ├── Assets │ ├── global.scss │ └── styles.scss │ ├── Components │ ├── Alert │ │ ├── Container.js │ │ ├── index.js │ │ └── styles.css │ ├── Animate │ │ ├── AnimationSets.js │ │ └── index.js │ ├── Avatar │ │ ├── index.js │ │ └── styles.css │ ├── Button │ │ ├── index.js │ │ └── styles.css │ ├── ButtonGroup │ │ ├── index.js │ │ └── styles.scss │ ├── Carousel │ │ └── index.js │ ├── ChangeConfirm │ │ └── index.js │ ├── Checkbox │ │ ├── index.js │ │ └── styles.css │ ├── CheckboxGroup │ │ ├── index.js │ │ └── styles.css │ ├── ClickConfirm │ │ └── index.js │ ├── ClickSuccess │ │ └── index.js │ ├── CodeEditor │ │ ├── index.js │ │ └── styles.css │ ├── CodeHighlight │ │ ├── index.js │ │ └── styles.scss │ ├── Copy │ │ ├── CopyButton.jsx │ │ ├── CopyInput.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Cropper │ │ ├── BaseCropper.jsx │ │ ├── InlineCropper.jsx │ │ ├── ModalCropper.jsx │ │ └── index.js │ ├── Data │ │ └── index.js │ ├── Date │ │ └── index.js │ ├── DateRange │ │ ├── index.js │ │ └── styles.scss │ ├── DateTime │ │ └── index.js │ ├── DelayedOnChange │ │ └── index.js │ ├── DownloadLink │ │ └── index.js │ ├── Downloader │ │ ├── Ideas │ │ │ ├── Dialog.jsx │ │ │ ├── Download.jsx │ │ │ ├── Element.jsx │ │ │ ├── Example.jsx │ │ │ └── Readme.md │ │ └── index.js │ ├── Draft │ │ ├── CustomViews.jsx │ │ ├── Editor.jsx │ │ ├── InlineToolbar.jsx │ │ ├── PluginBlock.jsx │ │ ├── Plugins │ │ │ ├── Alignment.jsx │ │ │ ├── Blockquote.jsx │ │ │ ├── Bold.jsx │ │ │ ├── Code.jsx │ │ │ ├── CodeBlock.jsx │ │ │ ├── ColorPicker.jsx │ │ │ ├── Heading.jsx │ │ │ ├── Image.jsx │ │ │ ├── Italic.jsx │ │ │ ├── Link.jsx │ │ │ ├── OrderedList.jsx │ │ │ ├── Table.jsx │ │ │ ├── Table │ │ │ │ ├── TabHandler.js │ │ │ │ ├── TableEditComponent.jsx │ │ │ │ └── TableShortcuts.js │ │ │ ├── ToJSON.jsx │ │ │ ├── Underline.jsx │ │ │ ├── UnorderedList.jsx │ │ │ └── Video.jsx │ │ ├── PluginsContainer.js │ │ ├── SimpleEditor.jsx │ │ ├── Toolbar.jsx │ │ ├── Toolbar │ │ │ ├── Atomic.js │ │ │ ├── BlockType.jsx │ │ │ ├── Entity.js │ │ │ └── InlineStyle.jsx │ │ ├── index.js │ │ └── styles.scss │ ├── Dropdown │ │ ├── Divider.js │ │ ├── Dropdown.js │ │ ├── Header.js │ │ ├── Link.js │ │ ├── index.js │ │ └── styles.css │ ├── Dynamic │ │ ├── Empty.jsx │ │ ├── Fieldset.jsx │ │ ├── Header.jsx │ │ ├── Row.jsx │ │ └── index.js │ ├── Email │ │ └── index.js │ ├── ExpandableList │ │ ├── Action.jsx │ │ ├── ActionSet.jsx │ │ ├── Empty.jsx │ │ ├── ExpandableList.jsx │ │ ├── Field.jsx │ │ ├── Row.jsx │ │ ├── RowDetailsContent.jsx │ │ ├── RowDetailsList.jsx │ │ ├── index.js │ │ └── styles.scss │ ├── Fieldset │ │ ├── index.js │ │ └── styles.css │ ├── File │ │ ├── index.js │ │ └── styles.css │ ├── FileReader │ │ └── index.js │ ├── Filters │ │ ├── Date.js │ │ ├── DateTime.js │ │ ├── FileSize.js │ │ ├── Number.js │ │ ├── Pluralize.js │ │ ├── Price.js │ │ ├── Time.js │ │ ├── TimeAgo.js │ │ └── index.js │ ├── Form │ │ ├── Error.js │ │ ├── Form.js │ │ ├── Loader.js │ │ └── index.js │ ├── FormGroup │ │ ├── Components │ │ │ ├── DescriptionMessage.jsx │ │ │ ├── InfoMessage.jsx │ │ │ ├── Label.jsx │ │ │ ├── Required.jsx │ │ │ ├── ValidationIcon.jsx │ │ │ └── ValidationMessage.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Gallery │ │ ├── Image.jsx │ │ ├── index.js │ │ └── styles.css │ ├── GoogleMap │ │ ├── index.js │ │ └── styles.css │ ├── Gravatar │ │ └── index.js │ ├── Grid │ │ ├── Col.jsx │ │ ├── Row.jsx │ │ └── index.js │ ├── Growl │ │ ├── DangerGrowl.js │ │ ├── Growl.jsx │ │ ├── GrowlContainer.jsx │ │ ├── InfoGrowl.js │ │ ├── SuccessGrowl.js │ │ ├── WarningGrowl.js │ │ ├── index.js │ │ └── styles.css │ ├── HtmlEditor │ │ └── index.js │ ├── Icon │ │ ├── index.js │ │ └── styles.css │ ├── IconPicker │ │ ├── icons.js │ │ └── index.js │ ├── Image │ │ ├── Preview.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Input │ │ ├── index.js │ │ └── styles.css │ ├── Label │ │ ├── index.js │ │ └── styles.css │ ├── LazyImage │ │ ├── Image.jsx │ │ ├── ImageSet.jsx │ │ └── index.js │ ├── Link │ │ ├── index.js │ │ └── styles.css │ ├── List │ │ ├── Components │ │ │ ├── ApiContainer.jsx │ │ │ ├── BaseContainer.jsx │ │ │ ├── Filters.jsx │ │ │ ├── FormFilters.jsx │ │ │ ├── ListContainerLoader.jsx │ │ │ ├── MultiActions.jsx │ │ │ ├── MultiActions │ │ │ │ ├── DeleteMultiAction.jsx │ │ │ │ ├── ModalMultiAction.jsx │ │ │ │ └── MultiAction.jsx │ │ │ ├── Pagination.jsx │ │ │ ├── StaticContainer.jsx │ │ │ └── Table │ │ │ │ ├── Actions.jsx │ │ │ │ ├── Actions │ │ │ │ ├── Action.jsx │ │ │ │ ├── DeleteAction.jsx │ │ │ │ ├── EditAction.jsx │ │ │ │ ├── EditModalAction.jsx │ │ │ │ ├── ModalAction.jsx │ │ │ │ └── RouteAction.jsx │ │ │ │ ├── Empty.jsx │ │ │ │ ├── Field.jsx │ │ │ │ ├── FieldInfo.jsx │ │ │ │ ├── Fields │ │ │ │ ├── CaseField.jsx │ │ │ │ ├── DateField.jsx │ │ │ │ ├── DateTimeField.jsx │ │ │ │ ├── FileSizeField.jsx │ │ │ │ ├── GravatarField.jsx │ │ │ │ ├── NumberField.jsx │ │ │ │ ├── PriceField.jsx │ │ │ │ ├── RowDetailsField.jsx │ │ │ │ ├── SelectRowField.jsx │ │ │ │ ├── TimeAgoField.jsx │ │ │ │ ├── TimeField.jsx │ │ │ │ └── ToggleField.jsx │ │ │ │ ├── Footer.jsx │ │ │ │ ├── Header.jsx │ │ │ │ ├── Row.jsx │ │ │ │ ├── RowDetails.jsx │ │ │ │ └── Table.jsx │ │ ├── List.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Loader │ │ ├── index.js │ │ └── styles.css │ ├── Logic │ │ ├── Hide.js │ │ ├── Show.js │ │ ├── Switch.js │ │ └── index.js │ ├── MarkdownEditor │ │ ├── index.js │ │ └── styles.scss │ ├── Modal │ │ ├── Components │ │ │ ├── Body.js │ │ │ ├── Confirmation.jsx │ │ │ ├── Content.js │ │ │ ├── Dialog.js │ │ │ ├── Footer.js │ │ │ ├── Header.js │ │ │ └── Success.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Panel │ │ ├── Body.jsx │ │ ├── Footer.jsx │ │ ├── Header.jsx │ │ ├── Panel.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Password │ │ └── index.js │ ├── Popover │ │ ├── index.js │ │ └── styles.scss │ ├── Progress │ │ ├── index.js │ │ └── styles.css │ ├── RadioGroup │ │ ├── Radio.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Search │ │ ├── index.js │ │ └── styles.css │ ├── Section │ │ ├── index.js │ │ └── styles.css │ ├── Select │ │ ├── SimpleSelect.js │ │ └── index.js │ ├── Settings │ │ └── index.js │ ├── Switch │ │ ├── index.js │ │ └── styles.css │ ├── Tabs │ │ ├── Tab.jsx │ │ ├── TabContent.jsx │ │ ├── TabHeader.jsx │ │ ├── Tabs.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Tags │ │ ├── index.js │ │ └── styles.css │ ├── Textarea │ │ ├── index.js │ │ └── styles.css │ ├── Tile │ │ ├── Body.jsx │ │ ├── Header.jsx │ │ ├── Tile.jsx │ │ ├── index.js │ │ └── styles.css │ ├── Time │ │ └── index.js │ ├── Tooltip │ │ ├── TooltipContent.js │ │ ├── index.js │ │ └── styles.css │ ├── View │ │ ├── Body.jsx │ │ ├── ChartBlock.jsx │ │ ├── DashboardComponents │ │ │ ├── HeaderCenter.jsx │ │ │ ├── HeaderLeft.jsx │ │ │ └── HeaderRight.jsx │ │ ├── DashboardView.jsx │ │ ├── Footer.jsx │ │ ├── FormView.jsx │ │ ├── Header.jsx │ │ ├── InfoBlock.jsx │ │ ├── ListView.jsx │ │ ├── View.jsx │ │ ├── index.js │ │ └── styles.css │ ├── ViewSwitcher │ │ ├── Switcher.jsx │ │ ├── View.jsx │ │ └── index.js │ ├── Wizard │ │ ├── Container.js │ │ ├── Step.js │ │ ├── Step │ │ │ ├── Actions.js │ │ │ ├── Actions │ │ │ │ ├── Action.js │ │ │ │ ├── Finish.js │ │ │ │ ├── Next.js │ │ │ │ └── Previous.js │ │ │ └── Content.js │ │ ├── Wizard.js │ │ ├── index.js │ │ └── styles.scss │ └── index.js │ └── Vendors │ ├── C3 │ ├── index.js │ └── styles.scss │ ├── CodeMirror │ ├── index.js │ └── styles.scss │ ├── Cropper │ ├── index.js │ └── styles.scss │ ├── DateTimePicker │ ├── index.js │ └── styles.scss │ ├── Draft │ ├── index.js │ └── styles.scss │ ├── Highlight │ └── index.js │ ├── Moment │ └── index.js │ ├── OwlCarousel │ ├── index.js │ └── styles.scss │ ├── Quill │ ├── index.js │ └── styles.scss │ ├── Select2 │ ├── index.js │ └── styles.scss │ └── index.js ├── LICENSE ├── Php ├── App.php ├── Bootstrap │ ├── Bootstrap.php │ ├── BootstrapEvent.php │ └── ErrorHandler.php ├── Cli │ ├── admin.php │ ├── install.php │ ├── migrate.php │ └── release.php ├── Entities │ ├── AbstractServiceUser.php │ ├── AbstractSettings.php │ ├── ApiLog.php │ ├── ApiToken.php │ ├── ApiTokenUser.php │ ├── AppNotification.php │ ├── DashboardUpdates.php │ ├── File.php │ ├── I18NLocale.php │ ├── I18NText.php │ ├── I18NTextGroup.php │ ├── Image.php │ ├── LoggerEntry.php │ ├── LoggerErrorGroup.php │ ├── Settings.php │ ├── SystemApiTokenUser.php │ ├── User.php │ ├── UserPermission.php │ ├── UserRole.php │ └── UserRoleGroup.php ├── Install │ ├── UserPermissions.json │ └── UserRoles.json ├── Lib │ ├── AbstractCli.php │ ├── Api │ │ ├── ApiContainer.php │ │ ├── ApiExpositionTrait.php │ │ ├── ApiMethod.php │ │ ├── ApiMethodException.php │ │ └── MatchedApiMethod.php │ ├── ApiCache.php │ ├── ApiCache │ │ ├── ApiCacheCallback.php │ │ └── ApiCacheEntityTrait.php │ ├── AppNotifications │ │ ├── AbstractAppNotification.php │ │ └── AppNotifications.php │ ├── Apps.php │ ├── Apps │ │ ├── AbstractApp.php │ │ ├── App.php │ │ ├── JsApp.php │ │ └── Parser │ │ │ ├── AbstractParser.php │ │ │ ├── EntityParser.php │ │ │ └── ServiceParser.php │ ├── Authorization │ │ ├── Authorization.php │ │ └── TwoFactorAuth.php │ ├── Cache.php │ ├── ClassLoader.php │ ├── Cli.php │ ├── Config.php │ ├── ConfigLoader.php │ ├── Database.php │ ├── Entity │ │ ├── AbstractEntity.php │ │ ├── Attributes │ │ │ ├── FileAttribute.php │ │ │ ├── FilesAttribute.php │ │ │ ├── ImageAttribute.php │ │ │ ├── ImagesAttribute.php │ │ │ ├── Many2ManyAttribute.php │ │ │ └── UserAttribute.php │ │ ├── EntityAttributeContainer.php │ │ ├── EntityQuery │ │ │ ├── EntityQuery.php │ │ │ ├── EntityQueryManipulator.php │ │ │ ├── Filter.php │ │ │ ├── QueryContainer.php │ │ │ └── Sorter.php │ │ ├── Event │ │ │ ├── EntityDeleteEvent.php │ │ │ └── EntityEvent.php │ │ ├── Export │ │ │ ├── CsvExportableInterface.php │ │ │ └── PdfExportableInterface.php │ │ ├── Indexes │ │ │ └── IndexContainer.php │ │ └── Validators │ │ │ └── Unique.php │ ├── Events.php │ ├── Exceptions │ │ └── AppException.php │ ├── I18N │ │ ├── Exports │ │ │ ├── AbstractExport.php │ │ │ ├── TextsExport.php │ │ │ └── TranslationsExport.php │ │ ├── I18N.php │ │ ├── I18NLocales.php │ │ ├── Modifiers │ │ │ ├── AbstractModifier.php │ │ │ ├── DateModifier.php │ │ │ ├── DateTimeModifier.php │ │ │ ├── GenderModifier.php │ │ │ ├── IfModifier.php │ │ │ ├── NumberModifier.php │ │ │ ├── PluralModifier.php │ │ │ ├── PriceModifier.php │ │ │ └── TimeModifier.php │ │ └── Parsers │ │ │ ├── AbstractParser.php │ │ │ ├── JsParser.php │ │ │ ├── PhpParser.php │ │ │ └── SmartyParser.php │ ├── Interfaces │ │ ├── PublicApiInterface.php │ │ └── UserInterface.php │ ├── Mailer.php │ ├── Notifications │ │ ├── MarketplaceNotification.php │ │ └── WebinyNotification.php │ ├── Reports │ │ ├── AbstractCsvReport.php │ │ ├── AbstractPdfReport.php │ │ ├── AbstractReport.php │ │ ├── ReportInterface.php │ │ └── ReportsArchive.php │ ├── Request.php │ ├── Response │ │ ├── AbstractResponse.php │ │ ├── ApiCacheResponse.php │ │ ├── ApiErrorResponse.php │ │ ├── ApiRawResponse.php │ │ ├── ApiResponse.php │ │ ├── CliResponse.php │ │ ├── EntityResponse.php │ │ ├── HtmlResponse.php │ │ ├── ListResponse.php │ │ ├── ResponseEvent.php │ │ └── ResponseInterface.php │ ├── Router.php │ ├── Services │ │ └── AbstractService.php │ ├── Storage.php │ ├── TemplateEngine.php │ ├── UserProvider.php │ ├── UserProvider │ │ ├── UserProviderEvent.php │ │ └── UserProviderEventHandler.php │ ├── Validators │ │ └── Password.php │ └── WebinyTrait.php ├── RequestHandlers │ ├── Api.php │ ├── ApiEvent.php │ ├── ApiException.php │ ├── ApiHandlers │ │ ├── AbstractApiHandler.php │ │ ├── ApiCacheHandler.php │ │ ├── ApiLogHandler.php │ │ ├── Discover │ │ │ ├── Postman.php │ │ │ └── Postman │ │ │ │ └── EndPoint.php │ │ ├── DiscoverHandler.php │ │ ├── EntityFlows │ │ │ ├── AbstractEntityFlow.php │ │ │ └── DefaultEntityFlow.php │ │ ├── EntityHandler.php │ │ ├── ReportHandler.php │ │ └── ServiceHandler.php │ ├── Routes.php │ └── Welcome.php ├── Services │ ├── Acl.php │ ├── AppNotifications.php │ ├── Apps.php │ ├── Entities.php │ ├── Lib │ │ ├── AppInstaller.php │ │ └── RemoteNotifications.php │ ├── Marketplace.php │ └── Services.php └── View │ ├── SmartyExtension.php │ └── View.php ├── README.md ├── Setup ├── .gitattributes ├── .gitignore ├── Configs │ ├── Base │ │ ├── Apps.yaml │ │ ├── Database.yaml │ │ ├── Js.yaml │ │ ├── Security.yaml │ │ ├── TemplateEngine.yaml │ │ └── Webiny.yaml │ ├── Environments.yaml │ ├── Local │ │ └── Webiny.yaml │ └── Production │ │ └── Webiny.yaml ├── Tests │ └── config.json └── public_html │ ├── index.php │ └── opcache.php ├── Templates ├── Backend.tpl ├── Emails │ └── ResetPassword.tpl ├── NotDeveloping.tpl └── Welcome.tpl ├── Tests └── Api │ └── Core.js ├── composer.json ├── package.json ├── webiny.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | 3 | * text=auto 4 | 5 | *.html text diff=html 6 | *.css text 7 | *.js text 8 | *.sql text 9 | *.php text 10 | *.md text 11 | *.txt text 12 | *.tpl text diff=html 13 | *.json text 14 | *.pdf diff=astextplain 15 | *.h text 16 | *.sh text 17 | *.less text 18 | *.svg text 19 | *.yml text 20 | *.xml text 21 | Makefile text 22 | Procfile text 23 | *.c text 24 | *.cfg text 25 | *.coffee text 26 | *.ini text 27 | 28 | *.png binary 29 | *.jpg binary 30 | *.gif binary 31 | *.bmp binary 32 | *.bz2 binary 33 | *.jar binary 34 | *.jpe binary 35 | *.tar.gz binary 36 | *.zip binary 37 | 38 | *.gitattributes text 39 | *.gitignore text 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Webiny 2 | node_modules/ 3 | 4 | #PHPStorm 5 | .idea/ 6 | 7 | # Mac crap 8 | .DS_Store 9 | ._.DS_Store 10 | 11 | ############ 12 | ## Windows 13 | ############ 14 | 15 | # Windows image file caches 16 | Thumbs.db 17 | 18 | # Folder config file 19 | Desktop.ini 20 | ################# 21 | ## Eclipse 22 | ################# 23 | 24 | *.pydevproject 25 | .project 26 | .metadata 27 | bin/ 28 | tmp/ 29 | *.tmp 30 | *.bak 31 | *.swp 32 | *~.nib 33 | local.properties 34 | .classpath 35 | .settings/ 36 | .loadpath 37 | 38 | # External tool builders 39 | .externalToolBuilders/ 40 | 41 | # Locally stored "Eclipse launch configurations" 42 | *.launch 43 | 44 | # CDT-specific 45 | .cproject 46 | 47 | # PDT-specific 48 | .buildpath 49 | -------------------------------------------------------------------------------- /Cli/Api/README.md: -------------------------------------------------------------------------------- 1 | # API plugin 2 | This plugin spawns an `express` server and allows you to interact with the `webiny-cli` via API calls. 3 | 4 | To create your own API method, in your CLI plugin simply attach an event handler to Webiny instance: 5 | ``` 6 | Webiny.on('your.action', ({res, data}) => { 7 | // Do something 8 | res.end(); 9 | }); 10 | ``` 11 | 12 | To register your own API middleware: 13 | ``` 14 | Webiny.on('api.middleware', ({req, res, next}) => { 15 | // Do something 16 | }); 17 | ``` 18 | 19 | Now you can trigger your handler by sending a request to: 20 | `http://your.app:8002/?action=your.action` -------------------------------------------------------------------------------- /Cli/Api/static/logo_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Cli/Api/static/logo_orange.png -------------------------------------------------------------------------------- /Cli/Build/webpack/app.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | if (process.env.NODE_ENV === 'production') { 3 | return require('./app.prod.js'); 4 | } else { 5 | return require('./app.dev.js'); 6 | } 7 | }; -------------------------------------------------------------------------------- /Cli/Build/webpack/eslint.js: -------------------------------------------------------------------------------- 1 | const Webiny = require('webiny-cli/lib/webiny'); 2 | 3 | module.exports = { 4 | // If this will not be enough we will create eslint-config-webiny package and other apps will extend it. 5 | // For now let's just work with one core .eslintrc file 6 | test: /\.(js|jsx)$/, 7 | exclude: /node_modules/, 8 | include: Webiny.projectRoot(), 9 | enforce: 'pre', 10 | use: [{ 11 | loader: 'eslint-loader', 12 | options: { 13 | configFile: Webiny.projectRoot('Apps/Webiny/Js/Core/.eslintrc') 14 | } 15 | }] 16 | }; -------------------------------------------------------------------------------- /Cli/Build/webpack/externals.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'jquery': '$' 3 | }; -------------------------------------------------------------------------------- /Cli/Build/webpack/plugins/ModuleIds.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | 3 | class ModuleIds { 4 | apply(compiler) { 5 | compiler.plugin("compilation", (compilation) => { 6 | compilation.plugin("before-module-ids", (modules) => { 7 | modules.forEach((module) => { 8 | if ((!module.id || module.id.length !== 10) && module.libIdent) { 9 | module.id = crypto.createHash('md5').update(module.libIdent({ 10 | context: compiler.options.context 11 | })).digest('hex').substr(0, 10); 12 | } 13 | }); 14 | }); 15 | }); 16 | } 17 | } 18 | 19 | module.exports = ModuleIds; 20 | -------------------------------------------------------------------------------- /Cli/CreateAdmin/README.md: -------------------------------------------------------------------------------- 1 | # CreateAdmin plugin 2 | This plugin simply creates a new admin user for your current project using given username and password. 3 | The new admin user is assigned the following roles: 4 | 5 | - `administrator` - identifies the user as an administrator. It carries no permissions. 6 | - `webiny-administrator` - manages Webiny installation. It carries no permissions. 7 | - `webiny-marketplace` - use Webiny Marketplace. 8 | - `webiny-app-notifications` - access app notifications. 9 | - `webiny-acl-api-token-manager` - manage API tokens. 10 | - `webiny-logger-manager` - manage system error logger . 11 | - `webiny-acl-user-manager` - manage users, roles and permissions. 12 | - `webiny-i18n-manager` - manage languages and translations. 13 | - `webiny-dashboard` - access the dashboard module. 14 | - `webiny-api-discoverer` - discover API using Postman. 15 | 16 | This is the set of roles included with the basic Webiny installation. 17 | Roles from other apps must be enabled manually. -------------------------------------------------------------------------------- /Cli/Deploy/README.md: -------------------------------------------------------------------------------- 1 | # Deploy plugin 2 | This plugin deploys the release archives (created by `ReleaseArchive` plugin) to a remote server of your choice via `rsync`. 3 | It is a very simple mechanism that copies, unzips, links with nginx, flushes opcache and runs the release callback on each app. 4 | 5 | Your server must be accessible via `ssh` and your `nginx` must be configured in advance to point to the appropriate root folder. 6 | See `ServerHelp` plugin for an example of folder structure. -------------------------------------------------------------------------------- /Cli/Exit/README.md: -------------------------------------------------------------------------------- 1 | # Exit plugin 2 | Creates a menu item to exit the `webiny-cli` :) -------------------------------------------------------------------------------- /Cli/Exit/index.js: -------------------------------------------------------------------------------- 1 | const Menu = require('webiny-cli/lib/menu'); 2 | const Plugin = require('webiny-cli/lib/plugin'); 3 | 4 | class Exit extends Plugin { 5 | getMenu() { 6 | return new Menu('Exit').addLineBefore().setOrder(0); 7 | } 8 | 9 | runTask() { 10 | return process.exit(0); 11 | } 12 | } 13 | 14 | Exit.task = 'exit'; 15 | 16 | module.exports = Exit; -------------------------------------------------------------------------------- /Cli/InstallApp/README.md: -------------------------------------------------------------------------------- 1 | # InstallApp plugin 2 | 3 | This plugin is used by Webiny Marketplace to install Webiny apps from packagist. 4 | 5 | NOTE: it is not intended for installing a development version of the app - only tagged (production) versions. -------------------------------------------------------------------------------- /Cli/InstallDevApp/README.md: -------------------------------------------------------------------------------- 1 | # InstallDevApp plugin 2 | 3 | This plugin is used to install a development version of an app from a git repository. 4 | It clones the `master` branch, enables the app in your `Configs/Base/Apps.yaml` and installs JS dependencies. -------------------------------------------------------------------------------- /Cli/Overrides/index.js: -------------------------------------------------------------------------------- 1 | const Plugin = require('webiny-cli/lib/plugin'); 2 | 3 | class Overrides extends Plugin { 4 | constructor(program) { 5 | super(program); 6 | 7 | // We need to override webpack `MultiCompiler` to force build execution in a chain of promises instead of parallel execution. 8 | const Module = require('module'); 9 | if (!Module.prototype.__isOverridden) { 10 | Module.prototype.__isOverridden = true; 11 | const originalRequire = Module.prototype.require; 12 | Module.prototype.require = function () { 13 | // Override MultiCompiler to force chained builds instead of parallel 14 | if (arguments[0].includes('MultiCompiler')) { 15 | return originalRequire.apply(this, [__dirname + '/MultiCompiler']); 16 | } 17 | return originalRequire.apply(this, arguments); 18 | }; 19 | } 20 | } 21 | } 22 | 23 | Overrides.task = 'overrides'; 24 | 25 | module.exports = Overrides; -------------------------------------------------------------------------------- /Cli/Setup/interfaces.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const interfaces = os.networkInterfaces(); 3 | 4 | module.exports = () => { 5 | const addresses = []; 6 | Object.keys(interfaces).forEach(iname => { 7 | interfaces[iname].forEach(iface => { 8 | if ('IPv4' !== iface.family || iface.internal !== false) { 9 | // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses 10 | return; 11 | } 12 | addresses.push({ 13 | name: iface.address + ' ' + iname, 14 | value: iface.address 15 | }); 16 | }); 17 | }); 18 | return addresses; 19 | }; -------------------------------------------------------------------------------- /Js/Backend/Assets/images/infinity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Backend/Assets/images/infinity.png -------------------------------------------------------------------------------- /Js/Backend/Assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Backend/Assets/images/logo.png -------------------------------------------------------------------------------- /Js/Backend/Assets/mp-images/app-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Backend/Assets/mp-images/app-image.png -------------------------------------------------------------------------------- /Js/Backend/Assets/mp-images/ss3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Backend/Assets/mp-images/ss3.png -------------------------------------------------------------------------------- /Js/Backend/Assets/mp-images/ss5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Backend/Assets/mp-images/ss5.png -------------------------------------------------------------------------------- /Js/Backend/Components/index.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | Webiny.registerModule( 4 | new Webiny.Module('Webiny/Backend/UserRoles', () => import('./UserRoles')), 5 | new Webiny.Module('Webiny/Backend/UserRoleGroups', () => import('./UserRoleGroups')), 6 | new Webiny.Module('Webiny/Backend/UserPermissions', () => import('./UserPermissions')) 7 | ); -------------------------------------------------------------------------------- /Js/Backend/Modules/Acl/Views/Components/matchOption.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Common function for matching classes and classIds in entity/service modal dialog 3 | */ 4 | export default ({term, option}) => { 5 | let found = false; 6 | const {data} = option; 7 | if (data.classId.toLowerCase().includes(term.toLowerCase())) { 8 | found = true; 9 | } 10 | 11 | if (data.class.toLowerCase().includes(term.toLowerCase())) { 12 | found = true; 13 | } 14 | 15 | if (found) { 16 | return option; 17 | } 18 | 19 | return null; 20 | }; -------------------------------------------------------------------------------- /Js/Backend/Modules/Acl/Views/Components/styles.css: -------------------------------------------------------------------------------- 1 | .entityPermissionsWrapper { 2 | position: relative; 3 | } 4 | 5 | .addAction { 6 | margin-bottom: 20px; 7 | } 8 | 9 | .accessBoxesWrapper { 10 | display: flex; 11 | flex-wrap: wrap; 12 | } -------------------------------------------------------------------------------- /Js/Backend/Modules/Acl/Views/Views.js: -------------------------------------------------------------------------------- 1 | import UsersForm from './UsersForm'; 2 | import UsersList from './UsersList'; 3 | import UserPermissionsForm from './UserPermissionsForm'; 4 | import UserPermissionsList from './UserPermissionsList'; 5 | import UserRolesForm from './UserRolesForm'; 6 | import UserRolesList from './UserRolesList'; 7 | import UserRoleGroupsForm from './UserRoleGroupsForm'; 8 | import UserRoleGroupsList from './UserRoleGroupsList'; 9 | import ApiTokensList from './ApiTokensList'; 10 | import ApiLogsList from './ApiLogsList'; 11 | 12 | export default { 13 | UsersList, 14 | UsersForm, 15 | UserRolesList, 16 | UserRolesForm, 17 | UserRoleGroupsList, 18 | UserRoleGroupsForm, 19 | UserPermissionsList, 20 | UserPermissionsForm, 21 | ApiTokensList, 22 | ApiLogsList 23 | }; 24 | -------------------------------------------------------------------------------- /Js/Backend/Modules/Dashboard/index.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | import React from 'react'; 3 | import Dashboard from './Views/Dashboard'; 4 | 5 | /** 6 | * @i18n.namespace Webiny.Backend.Dashboard 7 | */ 8 | class Module extends Webiny.App.Module { 9 | 10 | init() { 11 | this.name = 'Dashboard'; 12 | const role = 'webiny-dashboard'; 13 | 14 | this.registerMenus( 15 | 16 | ); 17 | 18 | this.registerRoutes( 19 | new Webiny.Route('Dashboard', '/dashboard', Dashboard, 'Dashboard').setRole(role) 20 | ); 21 | } 22 | } 23 | 24 | export default Module; -------------------------------------------------------------------------------- /Js/Backend/Modules/I18N/Views/TextsList.scss: -------------------------------------------------------------------------------- 1 | .textField { 2 | code { 3 | font-size: 10px; 4 | margin-left: 0; 5 | } 6 | h1 { 7 | display: block; 8 | font-size: 14px; 9 | padding: 0; 10 | margin: 5px 0; 11 | border: none; 12 | font-weight: normal; 13 | } 14 | } -------------------------------------------------------------------------------- /Js/Backend/Modules/I18N/Views/TranslationsList/TextRow.scss: -------------------------------------------------------------------------------- 1 | .translationListRow { 2 | code { 3 | font-size: 10px; 4 | margin-left: 8px; 5 | } 6 | h1 { 7 | display: block; 8 | font-size: 14px; 9 | padding: 0 8px; 10 | margin: 5px 0; 11 | border: none; 12 | font-weight: normal; 13 | } 14 | translations { 15 | display: block; 16 | border-top: 2px solid red; 17 | margin-top: 10px; 18 | ul { 19 | margin-bottom: 0; 20 | li { 21 | list-style: none; 22 | font-size: 14px; 23 | border-bottom: 1px solid rgb(224, 224, 224); 24 | padding: 8px; 25 | &:hover { 26 | background-color: rgba(255, 160, 130, 0.22); 27 | cursor: pointer; 28 | } 29 | &:last-child { 30 | border-bottom: none; 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Js/Backend/Modules/I18N/Views/TranslationsList/TranslatedTextPercentages.scss: -------------------------------------------------------------------------------- 1 | .translatedTextPercentages { 2 | margin-bottom: 24px; 3 | } 4 | 5 | .translatedTextPercentagesLocaleStats { 6 | margin-bottom: 10px; 7 | strong { 8 | margin-bottom: 5px; 9 | display: block; 10 | } 11 | progress-bar { 12 | display: block; 13 | background-color: #d8d8d8; 14 | position: relative; 15 | text-align: center; 16 | font-size: 12px; 17 | padding: 1px; 18 | height: 24px; 19 | bar { 20 | height: 24px; 21 | background-color: #3fbfb0; 22 | display: block; 23 | position: absolute; 24 | top: 0; 25 | left: 0; 26 | min-width: 4px; 27 | } 28 | label { 29 | height: 24px; 30 | display: block; 31 | position: absolute; 32 | width: 100%; 33 | top: 4px; 34 | left: 0; 35 | color: white; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Js/Backend/Modules/I18N/Views/TranslationsList/TranslationListRow/EditableTranslation.scss: -------------------------------------------------------------------------------- 1 | .editableTranslation { 2 | label { 3 | font-size: 13px; 4 | margin-bottom: 5px; 5 | span { 6 | color: #3FBFB0; 7 | } 8 | } 9 | textarea { 10 | min-height: initial; 11 | resize: vertical; 12 | padding: 10px; 13 | } 14 | webiny-form-container > div { 15 | margin-bottom: 0; 16 | } 17 | } 18 | 19 | .noTranslationLabel { 20 | color: #c1c1c1; 21 | } -------------------------------------------------------------------------------- /Js/Backend/Modules/I18N/Views/Views.js: -------------------------------------------------------------------------------- 1 | import LocalesList from './LocalesList'; 2 | import TextsList from './TextsList'; 3 | import TranslationsList from './TranslationsList'; 4 | import TextGroupsList from './TextGroupsList'; 5 | 6 | export default { 7 | LocalesList, 8 | TextsList, 9 | TextGroupsList, 10 | TranslationsList 11 | }; -------------------------------------------------------------------------------- /Js/Backend/Modules/Layout/index.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | import Footer from './Footer'; 3 | 4 | class Layout extends Webiny.App.Module { 5 | 6 | init() { 7 | this.name = 'Layout'; 8 | this.registerDefaultComponents({Footer}); 9 | } 10 | } 11 | 12 | export default Layout; -------------------------------------------------------------------------------- /Js/Backend/Modules/Logger/Views/ErrorCount.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class ErrorCount extends Webiny.Ui.View { 5 | 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | errorCount: this.props.count 11 | }; 12 | 13 | this.bindMethods('updateCount'); 14 | } 15 | 16 | updateCount(count) { 17 | this.setState({errorCount: count}); 18 | } 19 | 20 | } 21 | 22 | ErrorCount.defaultProps = { 23 | renderer() { 24 | return {this.state.errorCount}; 25 | } 26 | }; 27 | 28 | export default ErrorCount; -------------------------------------------------------------------------------- /Js/Backend/Modules/Logger/Views/Views.js: -------------------------------------------------------------------------------- 1 | import Main from './Main'; 2 | 3 | export default { 4 | Main 5 | }; 6 | -------------------------------------------------------------------------------- /Js/Backend/Modules/Logger/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import Views from './Views/Views'; 4 | 5 | /** 6 | * @i18n.namespace Webiny.Backend.Logger 7 | */ 8 | class Logger extends Webiny.App.Module { 9 | 10 | init() { 11 | this.name = 'Logger'; 12 | const Menu = Webiny.Ui.Menu; 13 | const role = 'webiny-logger-manager'; 14 | 15 | this.registerMenus( 16 | 17 | 18 | 19 | ); 20 | 21 | this.registerRoutes( 22 | new Webiny.Route('Logger.ListErrors', '/logger/list', Views.Main, 'Logger - List Errors').setRole(role) 23 | ); 24 | } 25 | } 26 | 27 | export default Logger; -------------------------------------------------------------------------------- /Js/Backend/Modules/Marketplace/Components/AppDetails/Carousel.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './../../Views/styles.css'; 4 | 5 | class Carousel extends Webiny.Ui.View { 6 | 7 | } 8 | 9 | Carousel.defaultProps = { 10 | renderer() { 11 | const {Carousel} = this.props; 12 | return ( 13 |
14 | 15 | {this.props.images.map(image => { 16 | return ; 17 | })} 18 | 19 |
20 | ); 21 | } 22 | }; 23 | 24 | export default Webiny.createComponent(Carousel, {styles, modules: ['Carousel']}); -------------------------------------------------------------------------------- /Js/Backend/Modules/Marketplace/Components/User.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import _ from 'lodash'; 4 | 5 | /** 6 | * @i18n.namespace Webiny.Backend.Marketplace.User 7 | */ 8 | const User = (props) => { 9 | if (!props.user) { 10 | return null; 11 | } 12 | 13 | const {Gravatar} = props; 14 | 15 | return ( 16 |
17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |

25 | {Webiny.I18n('Hi {user}!', {user: _.get(props.user, 'firstName', _.get(props.user, 'email'))})} 26 |

27 |
28 | ); 29 | }; 30 | 31 | export default Webiny.createComponent(User, {modules: ['Gravatar']}); -------------------------------------------------------------------------------- /Js/Backend/Modules/Marketplace/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import LoginRegister from './Views/LoginRegister'; 4 | import Browse from './Views/Browse'; 5 | import AppDetails from './Views/AppDetails'; 6 | 7 | /** 8 | * @i18n.namespace Webiny.Backend.Marketplace 9 | */ 10 | class Project extends Webiny.App.Module { 11 | 12 | init() { 13 | this.name = 'Marketplace'; 14 | 15 | this.registerMenus( 16 | 17 | ); 18 | 19 | this.registerRoutes( 20 | new Webiny.Route('Marketplace.LoginRegister', '/marketplace/login-register', LoginRegister, 'Marketplace'), 21 | new Webiny.Route('Marketplace.AppDetails', '/marketplace/:id', { 22 | Content: , 23 | Apps: AppDetails 24 | }, 'Marketplace'), 25 | new Webiny.Route('Marketplace.Browse', '/marketplace', Browse, 'Marketplace'), 26 | ); 27 | } 28 | } 29 | 30 | export default Project; -------------------------------------------------------------------------------- /Js/Core/App.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | import Logger from './Logger'; 4 | import ClientStorage from './Lib/ClientStorage'; 5 | import Store from './Lib/ClientStorage/Store'; 6 | import LocalForage from './Lib/ClientStorage/LocalForage'; 7 | import appendLibrary from './Lib'; 8 | import App from './Lib/Core/App'; 9 | 10 | class Core extends App { 11 | constructor() { 12 | super('Webiny.Core'); 13 | appendLibrary(Webiny); 14 | Webiny.Logger = new Logger(); 15 | Webiny.LocalStorage = new ClientStorage(new Store()); 16 | Webiny.IndexedDB = new ClientStorage(new LocalForage()); 17 | 18 | console.timeStamp('App run: Webiny.Core'); 19 | } 20 | } 21 | 22 | Webiny.registerApp(new Core()); -------------------------------------------------------------------------------- /Js/Core/Bootstrap.js: -------------------------------------------------------------------------------- 1 | (function (global) { 2 | // import Core vendors 3 | require('console-polyfill'); 4 | console.timeStamp('Bootstrap started'); 5 | const Webiny = require('webiny').default; 6 | const jquery = require('jquery'); 7 | const Promise = require('bluebird'); 8 | 9 | global.Promise = Promise; 10 | global.$ = global.jQuery = jquery; 11 | Promise.config({ 12 | cancellation: true, 13 | warnings: { 14 | wForgottenReturn: false 15 | } 16 | }); 17 | 18 | global['webinyOnRender'] = (callback) => { 19 | Webiny.onRenderCallbacks.push(callback); 20 | }; 21 | 22 | global['webinyFirstRenderDone'] = () => { 23 | return Webiny.firstRenderDone; 24 | }; 25 | 26 | 27 | require('bootstrap-sass'); 28 | 29 | if (DEVELOPMENT) { 30 | global['$Webiny'] = Webiny; 31 | } 32 | 33 | // Check if `Webiny` config exists in the global 34 | if (!global.webinyConfig) { 35 | console.error('You must define a "webinyConfig" to bootstrap your app!'); 36 | } else { 37 | Webiny.run(global.webinyConfig); 38 | } 39 | })(window); -------------------------------------------------------------------------------- /Js/Core/Lib/ClientStorage/LocalForage.js: -------------------------------------------------------------------------------- 1 | import localforage from 'localforage'; 2 | 3 | class LocalForage { 4 | constructor() { 5 | this.instance = localforage; 6 | } 7 | 8 | set(key, value) { 9 | localforage.setItem(key, value); 10 | return this; 11 | } 12 | 13 | get(key) { 14 | return localforage.getItem(key); 15 | } 16 | 17 | remove(key) { 18 | localforage.removeItem(key); 19 | return this; 20 | } 21 | 22 | clear() { 23 | localforage.clear(); 24 | return this; 25 | } 26 | } 27 | 28 | export default LocalForage; -------------------------------------------------------------------------------- /Js/Core/Lib/ClientStorage/Store.js: -------------------------------------------------------------------------------- 1 | import store from 'store'; 2 | 3 | class Store { 4 | constructor() { 5 | this.instance = store; 6 | } 7 | 8 | set(key, value) { 9 | store.set(key, value); 10 | return this; 11 | } 12 | 13 | get(key) { 14 | return store.get(key); 15 | } 16 | 17 | remove(key) { 18 | store.remove(key); 19 | return this; 20 | } 21 | 22 | clear() { 23 | store.clearAll(); 24 | return this; 25 | } 26 | } 27 | 28 | export default Store; -------------------------------------------------------------------------------- /Js/Core/Lib/ClientStorage/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ClientStorage class 3 | * Serves as an interface to given storage abstractions (adapters/drivers/bridges...call them what you like). 4 | * This way you can easily replace a library your project is using globally. 5 | */ 6 | class ClientStorage { 7 | constructor(storage) { 8 | this.storage = storage; 9 | } 10 | 11 | set(key, value) { 12 | this.storage.set(key, value); 13 | return this; 14 | } 15 | 16 | get(key) { 17 | return this.storage.get(key); 18 | } 19 | 20 | remove(key) { 21 | this.storage.remove(key); 22 | return this; 23 | } 24 | 25 | clear() { 26 | this.storage.clearAll(); 27 | return this; 28 | } 29 | } 30 | 31 | export default ClientStorage; -------------------------------------------------------------------------------- /Js/Core/Lib/Core/App.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | class App { 4 | 5 | constructor(name) { 6 | this.name = name; 7 | this.modules = []; 8 | this.onBeforeRender = _.noop; 9 | } 10 | 11 | run() { 12 | this.modules.map(m => m.init()); 13 | return Promise.resolve(this.onBeforeRender()).then(() => { 14 | console.timeStamp('App run: ' + this.name); 15 | }); 16 | } 17 | 18 | beforeRender(callback = null) { 19 | if (!_.isFunction(callback)) { 20 | return this.onBeforeRender; 21 | } 22 | 23 | this.onBeforeRender = callback; 24 | return this; 25 | } 26 | 27 | /** 28 | * Content returned from this function will be presented as Marketplace mini-onboarding in a modal dialog. 29 | * Return React content you want to see inside the dialog. 30 | * 31 | * @returns {null} 32 | */ 33 | onInstalled() { 34 | return Promise.resolve(); 35 | } 36 | } 37 | 38 | export default App; -------------------------------------------------------------------------------- /Js/Core/Lib/Core/DepsScanner.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Webiny from './../../Webiny'; 3 | 4 | class DepsScanner { 5 | scan(entry) { 6 | return this.load(entry).then(acc => console.log(acc)); 7 | } 8 | 9 | load(entry, accumulator = []) { 10 | return Webiny.import([entry]).then(modules => { 11 | const cmp = modules[entry]; 12 | if (cmp.options && cmp.options.modules) { 13 | // scan only custom dependencies 14 | let deps = Promise.resolve(accumulator); 15 | _.map(cmp.options.modules, dep => { 16 | if (_.isPlainObject(dep)) { 17 | _.each(dep, path => { 18 | if (!accumulator.includes(path)) { 19 | accumulator.push(path); 20 | } 21 | deps = deps.then(accumulator => this.load(path, accumulator)); 22 | }) 23 | } 24 | }); 25 | return deps; 26 | } 27 | return accumulator; 28 | }); 29 | } 30 | } 31 | 32 | export default DepsScanner; -------------------------------------------------------------------------------- /Js/Core/Lib/Core/Filter.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | const registeredFilters = {}; 3 | 4 | function parseFilters(filters) { 5 | if (!filters) { 6 | return {}; 7 | } 8 | const splitFilters = filters.split(','); 9 | filters = {}; 10 | splitFilters.forEach(v => { 11 | const filter = v.split(':'); 12 | const vName = filter.shift(); 13 | filters[vName] = filter; 14 | }); 15 | return filters; 16 | } 17 | 18 | function getFilter(filter) { 19 | return registeredFilters[filter]; 20 | } 21 | 22 | function Filter(value, filtersToApply) { 23 | _.forEach(parseFilters(filtersToApply), (params, filter) => { 24 | value = getFilter(filter)(value, ...params); 25 | }); 26 | return value; 27 | } 28 | 29 | Filter.getFilters = function () { 30 | return registeredFilters; 31 | }; 32 | 33 | Filter.addFilter = function addFilter(name, callable) { 34 | if (!_.has(registeredFilters[name])) { 35 | registeredFilters[name] = callable; 36 | } 37 | return this; 38 | }; 39 | 40 | export default Filter; -------------------------------------------------------------------------------- /Js/Core/Lib/Core/Model.js: -------------------------------------------------------------------------------- 1 | import Baobab from 'baobab'; 2 | 3 | export default new Baobab({}); 4 | -------------------------------------------------------------------------------- /Js/Core/Lib/Core/Module.js: -------------------------------------------------------------------------------- 1 | class Module { 2 | constructor(name, callable) { 3 | this.name = name; 4 | this.callable = callable; 5 | this.context = null; 6 | this.tags = null; 7 | } 8 | 9 | setContext(context) { 10 | this.context = context; 11 | return this; 12 | } 13 | 14 | setTags(...tags) { 15 | this.tags = tags; 16 | return this; 17 | } 18 | 19 | load() { 20 | return Promise.resolve(this.callable()); 21 | } 22 | } 23 | 24 | export default Module; -------------------------------------------------------------------------------- /Js/Core/Lib/Core/View.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Component from './Component'; 3 | 4 | class View extends Component { 5 | 6 | constructor(props) { 7 | super(props); 8 | } 9 | } 10 | 11 | View.defaultProps = _.merge({}, Component.defaultProps); 12 | 13 | export default View; 14 | -------------------------------------------------------------------------------- /Js/Core/Lib/Core/ViewManager.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Dispatcher from './Dispatcher'; 3 | 4 | class ViewManager { 5 | 6 | constructor() { 7 | this.placeholders = {}; 8 | } 9 | 10 | getContent(placeholder) { 11 | return _.get(this.placeholders, placeholder); 12 | } 13 | 14 | render(content) { 15 | this.placeholders = content; 16 | 17 | return Dispatcher.dispatch('RenderView'); 18 | } 19 | } 20 | 21 | export default new ViewManager; -------------------------------------------------------------------------------- /Js/Core/Lib/Draft/AtomicPlugin.js: -------------------------------------------------------------------------------- 1 | import BasePlugin from './BasePlugin'; 2 | 3 | class AtomicPlugin extends BasePlugin { 4 | constructor(config) { 5 | super(config); 6 | } 7 | 8 | createBlock() { 9 | throw Error('Implement "createBlock" method in your plugin class!'); 10 | } 11 | } 12 | 13 | export default AtomicPlugin; -------------------------------------------------------------------------------- /Js/Core/Lib/Draft/BlockTypePlugin.js: -------------------------------------------------------------------------------- 1 | import BasePlugin from './BasePlugin'; 2 | 3 | class BlockTypePlugin extends BasePlugin { 4 | constructor() { 5 | super(); 6 | this.block = ''; 7 | } 8 | 9 | toggleBlockType() { 10 | const editorState = this.editor.getEditorState(); 11 | this.editor.setEditorState(this.Draft.RichUtils.toggleBlockType(editorState, this.block)); 12 | } 13 | 14 | isActive() { 15 | if (this.editor.getReadOnly()) { 16 | return false; 17 | } 18 | return this.block === this.getStartBlockType(); 19 | } 20 | } 21 | 22 | export default BlockTypePlugin; -------------------------------------------------------------------------------- /Js/Core/Lib/Draft/index.js: -------------------------------------------------------------------------------- 1 | import BasePlugin from './BasePlugin'; 2 | import BlockTypePlugin from './BlockTypePlugin'; 3 | import InlineStylePlugin from './InlineStylePlugin'; 4 | import EntityPlugin from './EntityPlugin'; 5 | import AtomicPlugin from './AtomicPlugin'; 6 | 7 | export default { 8 | BasePlugin, 9 | BlockTypePlugin, 10 | InlineStylePlugin, 11 | EntityPlugin, 12 | AtomicPlugin 13 | }; -------------------------------------------------------------------------------- /Js/Core/Lib/Http/Response.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | class HttpResponse { 4 | 5 | constructor(response, request) { 6 | this.data = response.data; 7 | this.status = response.status; 8 | this.statusText = response.statusText; 9 | this.headers = response.headers; 10 | this.request = request; 11 | } 12 | 13 | getData(key, defaultValue) { 14 | return key ? _.get(this.data, key, defaultValue) : this.data; 15 | } 16 | 17 | setData(data) { 18 | this.data = data; 19 | return this; 20 | } 21 | 22 | getStatus() { 23 | return this.status; 24 | } 25 | 26 | setStatus(status) { 27 | this.status = status; 28 | return this; 29 | } 30 | 31 | getStatusText() { 32 | return this.statusText; 33 | } 34 | 35 | setStatusText(statusText) { 36 | this.statusText = statusText; 37 | return this; 38 | } 39 | 40 | getHeaders() { 41 | return this.headers; 42 | } 43 | } 44 | 45 | export default HttpResponse; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/I18n.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | import React from 'react'; 3 | import createComponent from './../createComponent'; 4 | import Component from './../Core/Component'; 5 | 6 | class I18n extends Component { 7 | } 8 | 9 | I18n.defaultProps = { 10 | textKey: '', 11 | base: '', 12 | variables: {}, 13 | renderer() { 14 | return React.createElement( 15 | 'webiny-i18n', 16 | { 17 | 'base': this.props.base, 18 | 'text-key': this.props.textKey 19 | }, 20 | Webiny.I18n.translate(this.props.base, this.props.variables, this.props.textKey) 21 | ); 22 | } 23 | }; 24 | 25 | export default createComponent(I18n, {i18n: true}); -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/CountModifier.js: -------------------------------------------------------------------------------- 1 | class CountModifier { 2 | getName() { 3 | return 'count'; 4 | } 5 | 6 | execute(value, parameters) { 7 | // Numbers can be single number or ranges. 8 | for (let i = 0; i < parameters.length; i = i + 2) { 9 | const current = parameters[i]; 10 | if (current === 'default') { 11 | return value + ' ' + parameters[i + 1]; 12 | } 13 | 14 | const numbers = current.split('-'); 15 | 16 | // If we are dealing with a numbers range, then let's check if we are in it. 17 | if (numbers.length === 2) { 18 | if (value >= numbers[0] && value <= numbers[1]) { 19 | return value + ' ' + parameters[i + 1]; 20 | } 21 | continue; 22 | } 23 | 24 | if (value === numbers[0]) { 25 | return value + ' ' + parameters[i + 1]; 26 | } 27 | } 28 | 29 | // If we didn't match any condition, let's just remove the received value. 30 | return value; 31 | } 32 | } 33 | 34 | export default CountModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/DateModifier.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class DateModifier { 4 | getName() { 5 | return 'date'; 6 | } 7 | 8 | execute(value) { 9 | return Webiny.I18n.date(value) 10 | } 11 | } 12 | 13 | export default DateModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/DateTimeModifier.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class DateTimeModifier { 4 | getName() { 5 | return 'datetime'; 6 | } 7 | 8 | execute(value) { 9 | return Webiny.I18n.datetime(value) 10 | } 11 | } 12 | 13 | export default DateTimeModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/GenderModifier.js: -------------------------------------------------------------------------------- 1 | class GenderModifier { 2 | getName() { 3 | return 'gender'; 4 | } 5 | 6 | execute(value, parameters) { 7 | return value === 'male' ? parameters[0] : parameters[1]; 8 | } 9 | } 10 | 11 | export default GenderModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/IfModifier.js: -------------------------------------------------------------------------------- 1 | class IfModifier { 2 | getName() { 3 | return 'gender'; 4 | } 5 | 6 | execute(value, parameters) { 7 | return value === parameters[0] ? parameters[1] : parameters[2] || ''; 8 | } 9 | } 10 | 11 | export default IfModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/NumberModifier.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class NumberModifier { 4 | getName() { 5 | return 'number'; 6 | } 7 | 8 | execute(value) { 9 | return Webiny.I18n.number(value) 10 | } 11 | } 12 | 13 | export default NumberModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/PluralModifier.js: -------------------------------------------------------------------------------- 1 | class PluralModifier { 2 | getName() { 3 | return 'plural'; 4 | } 5 | 6 | execute(value, parameters) { 7 | // Numbers can be single number or ranges. 8 | for (let i = 0; i < parameters.length; i = i + 2) { 9 | const current = parameters[i]; 10 | if (current === 'default') { 11 | return parameters[i + 1]; 12 | } 13 | 14 | const numbers = current.split('-'); 15 | 16 | // If we are dealing with a numbers range, then let's check if we are in it. 17 | if (numbers.length === 2) { 18 | if (value >= numbers[0] && value <= numbers[1]) { 19 | return parameters[i + 1]; 20 | } 21 | continue; 22 | } 23 | 24 | if (value === numbers[0]) { 25 | return parameters[i + 1]; 26 | } 27 | } 28 | 29 | return ''; 30 | } 31 | } 32 | 33 | export default PluralModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/PriceModifier.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class PriceModifier { 4 | getName() { 5 | return 'price'; 6 | } 7 | 8 | execute(value) { 9 | return Webiny.I18n.price(value) 10 | } 11 | } 12 | 13 | export default PriceModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/TimeModifier.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class TimeModifier { 4 | getName() { 5 | return 'time'; 6 | } 7 | 8 | execute(value) { 9 | return Webiny.I18n.time(value) 10 | } 11 | } 12 | 13 | export default TimeModifier; -------------------------------------------------------------------------------- /Js/Core/Lib/I18n/Modifiers/index.js: -------------------------------------------------------------------------------- 1 | // Built-in modifiers 2 | import CountModifiers from './CountModifier'; 3 | import GenderModifier from './GenderModifier'; 4 | import IfModifier from './IfModifier'; 5 | import PluralModifier from './PluralModifier'; 6 | import DateModifier from './DateModifier'; 7 | import DateTimeModifier from './DateTimeModifier'; 8 | import TimeModifier from './TimeModifier'; 9 | import NumberModifier from './NumberModifier'; 10 | import PriceModifier from './PriceModifier'; 11 | 12 | export default [ 13 | new CountModifiers(), 14 | new GenderModifier(), 15 | new IfModifier(), 16 | new PluralModifier(), 17 | new DateModifier(), 18 | new DateTimeModifier(), 19 | new TimeModifier(), 20 | new NumberModifier(), 21 | new PriceModifier() 22 | ]; -------------------------------------------------------------------------------- /Js/Core/Lib/Router/AnchorClickHandler.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | import _ from 'lodash'; 3 | 4 | export default (router, a, e) => { 5 | let url = a.href; 6 | 7 | // _blank links should not be intercepted 8 | if (a.target === '_blank') { 9 | return; 10 | } 11 | 12 | // Prevent scrolling to top when clicking on '#' link 13 | if (_.endsWith(url, '#')) { 14 | e.preventDefault(); 15 | return; 16 | } 17 | 18 | // Check if it's an anchor link 19 | if (url.indexOf('#') > -1) { 20 | return; 21 | } 22 | 23 | // Push state and let the Router process the rest 24 | if (url.startsWith(Webiny.Config.WebUrl) || url.startsWith('file://')) { 25 | e.preventDefault(); 26 | url = url.replace(Webiny.Config.WebUrl, '').replace('file://', ''); 27 | router.history.push(url, { 28 | title: a.getAttribute('data-document-title') || null, 29 | prevTitle: window.document.title, 30 | scrollY: a.getAttribute('data-prevent-scroll') === 'true' ? window.scrollY : false 31 | }); 32 | } 33 | }; -------------------------------------------------------------------------------- /Js/Core/Lib/Router/RouterEvent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * RouterEvent instance is passed to all Router generated processes: 3 | * - beforeStart 4 | * - routeWillChange 5 | * - routeChanged 6 | * - routeNotMatched 7 | */ 8 | class RouterEvent { 9 | constructor(route, initialRender = false) { 10 | this.route = route; 11 | this.initialRender = initialRender; 12 | this.stopped = false; 13 | this.goTo = null; 14 | this.goToParams = null; 15 | } 16 | 17 | stop() { 18 | this.stopped = true; 19 | return this; 20 | } 21 | 22 | /** 23 | * Is this an initial app render or a subsequent render (when route changes) 24 | * @returns {boolean|*} 25 | */ 26 | isInitialRender() { 27 | return this.initialRender; 28 | } 29 | 30 | isStopped() { 31 | return this.stopped; 32 | } 33 | 34 | goToRoute(route, params = null) { 35 | this.goTo = route; 36 | this.goToParams = params; 37 | return this; 38 | } 39 | } 40 | 41 | export default RouterEvent; 42 | -------------------------------------------------------------------------------- /Js/Core/Lib/Ui/LazyLoad.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Webiny from 'webiny'; 3 | import Component from './../Core/Component'; 4 | 5 | class LazyLoad extends Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | loaded: false, 11 | modules: null 12 | }; 13 | } 14 | 15 | componentWillMount() { 16 | super.componentWillMount(); 17 | Webiny.import(this.props.modules, this.props.options).then(modules => { 18 | // Finish loading and render content 19 | this.setState({loaded: true, modules}); 20 | this.props.onLoad(modules); 21 | }); 22 | } 23 | } 24 | 25 | LazyLoad.defaultProps = { 26 | modules: [], 27 | options: {}, 28 | onLoad: _.noop, 29 | renderer() { 30 | if (this.state.loaded) { 31 | try { 32 | return this.props.children(this.state.modules); 33 | } catch (e) { 34 | console.error(e); 35 | } 36 | } 37 | return null; 38 | } 39 | }; 40 | 41 | export default LazyLoad; -------------------------------------------------------------------------------- /Js/Core/Lib/Ui/Menu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Component from './../Core/Component'; 3 | 4 | class Menu extends Component { 5 | } 6 | 7 | Menu.defaultProps = { 8 | id: null, 9 | label: null, 10 | icon: null, 11 | order: 100, 12 | role: null, 13 | route: null, 14 | level: 0, 15 | overwriteExisting: false, 16 | apps: [] 17 | }; 18 | 19 | export default Menu; -------------------------------------------------------------------------------- /Js/Core/Lib/Validation/ValidationError.js: -------------------------------------------------------------------------------- 1 | class ValidationError extends Error { 2 | 3 | constructor(message, validator, value = null) { 4 | super(); 5 | this.message = message; 6 | this.validator = validator; 7 | this.value = value; 8 | } 9 | 10 | setValidator(validator) { 11 | this.validator = validator; 12 | } 13 | 14 | getMessage() { 15 | return this.message; 16 | } 17 | 18 | getValidator() { 19 | return this.validator; 20 | } 21 | 22 | getValue() { 23 | return this.value; 24 | } 25 | 26 | setMessage(message) { 27 | this.message = message; 28 | return this; 29 | } 30 | } 31 | 32 | export default ValidationError; -------------------------------------------------------------------------------- /Js/Core/Lib/Webpack/DllBootstrapPlugin.js: -------------------------------------------------------------------------------- 1 | class DllBootstrapPlugin { 2 | constructor(options) { 3 | this.options = options || {} 4 | } 5 | 6 | apply(compiler) { 7 | compiler.plugin('compilation', (compilation) => { 8 | compilation.mainTemplate.plugin('startup', (source, chunk) => { 9 | const bootstrapEntry = this.options.module; 10 | const module = chunk.mapModules(m => m).find(m => m.rawRequest === bootstrapEntry); 11 | if (module) { 12 | source = `__webpack_require__("${module.id}");\n${source}`; 13 | } 14 | 15 | return source; 16 | }) 17 | }) 18 | } 19 | } 20 | 21 | module.exports = DllBootstrapPlugin; -------------------------------------------------------------------------------- /Js/Core/TestLib/TestSuite/Api.js: -------------------------------------------------------------------------------- 1 | const chakram = require('chakram'); 2 | 3 | module.exports = { 4 | chakram 5 | }; -------------------------------------------------------------------------------- /Js/Skeleton/App.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | import 'Assets/styles.scss'; 4 | import 'Assets/images/public/bg-login.png'; 5 | import 'Assets/images/public/preloader_2.png'; 6 | import 'Assets/images/public/favicon.ico'; 7 | import 'Assets/images/public/logo_orange.png'; 8 | import UserAccount from './Modules/UserAccount'; 9 | import Layout from './Modules/Layout'; 10 | import Auth from './Auth'; 11 | import registerComponents from './Components'; 12 | 13 | class Skeleton extends Webiny.App { 14 | constructor() { 15 | super('Webiny.Skeleton'); 16 | registerComponents(); 17 | this.modules = [ 18 | new Layout(this), 19 | new UserAccount(this) 20 | ]; 21 | 22 | Webiny.Router.setDefaultRoute('Dashboard'); 23 | Webiny.Auth = new Auth(); 24 | } 25 | } 26 | 27 | Webiny.registerApp(new Skeleton()); 28 | -------------------------------------------------------------------------------- /Js/Skeleton/Assets/fonts/Fontello/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/fonts/Fontello/fontello.eot -------------------------------------------------------------------------------- /Js/Skeleton/Assets/fonts/Fontello/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/fonts/Fontello/fontello.ttf -------------------------------------------------------------------------------- /Js/Skeleton/Assets/fonts/Fontello/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/fonts/Fontello/fontello.woff -------------------------------------------------------------------------------- /Js/Skeleton/Assets/fonts/Fontello/fontello.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/fonts/Fontello/fontello.woff2 -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/arr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/arr.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/arr_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/arr_2.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/header_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/header_bg.jpg -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/icons.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/icons_retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/icons_retina.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/logo.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/logo_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/logo_orange.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/public/bg-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/public/bg-login.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/public/favicon.ico -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/public/logo_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/public/logo_orange.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/public/preloader_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/public/preloader_2.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/swich.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/swich.png -------------------------------------------------------------------------------- /Js/Skeleton/Assets/images/table_img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webiny/Webiny/38ace3baa096fe65fd2bfd7cc65adea046b14ebf/Js/Skeleton/Assets/images/table_img.jpg -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles.scss: -------------------------------------------------------------------------------- 1 | @import './styles/sass/webiny.scss'; -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/base/base.scss: -------------------------------------------------------------------------------- 1 | .master{ 2 | min-height: 100%; 3 | position: relative; 4 | overflow: hidden; 5 | } 6 | 7 | .container { 8 | max-width: 100%; 9 | } 10 | 11 | .container-no-padding { 12 | padding-left: 0 !important; 13 | padding-right: 0 !important; 14 | } 15 | 16 | .master-content { 17 | width: 100%; 18 | padding-top: 0; 19 | margin-top: 0; 20 | min-height: 100vh; 21 | 22 | @media (min-width: 768px) { 23 | background-color: $masterContentBgColor; 24 | } 25 | } 26 | 27 | .text-right { 28 | text-align: right !important; 29 | } 30 | 31 | .text-left { 32 | text-align: left !important; 33 | } 34 | 35 | .text-center { 36 | text-align: center !important; 37 | } 38 | 39 | .text-danger{ 40 | color: #CC3300; 41 | } 42 | 43 | .text-success{ 44 | color: #3FBFB0; 45 | } 46 | 47 | .text-info{ 48 | color: #3F89BF; 49 | } 50 | 51 | .text-warning{ 52 | color: #FAA32E; 53 | } 54 | 55 | .text-primary{ 56 | color: #FA5723 57 | } 58 | 59 | .text-default{ 60 | color: #333; 61 | } 62 | 63 | .no-padding { 64 | padding: 0; 65 | } -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/partials/charts.scss: -------------------------------------------------------------------------------- 1 | .line-chart { 2 | height: 265px; 3 | margin: 0 0 20px 0; 4 | padding: 0; 5 | 6 | .c3-ygrid { 7 | stroke-dasharray: 0 0; 8 | } 9 | 10 | svg{ 11 | width: 100%; 12 | } 13 | path.domain { 14 | stroke: #d5d5d5; 15 | } 16 | .tick { 17 | line { 18 | stroke: white; 19 | } 20 | } 21 | text { 22 | font-size: 11px; 23 | color: red; 24 | } 25 | .c3 path, .c3 line { 26 | display: none; 27 | } 28 | .c3-tooltip td { 29 | color: #313131; 30 | } 31 | 32 | .c3-line { 33 | stroke-width: 2px; 34 | } 35 | 36 | @media (max-width: 486px){ 37 | margin: 5px 0 0 0; 38 | } 39 | } 40 | 41 | 42 | .pie-chart { 43 | height: 265px; 44 | text { 45 | font-size: 11px; 46 | color: red; 47 | } 48 | .c3-tooltip td { 49 | color: #313131; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/partials/header.scss: -------------------------------------------------------------------------------- 1 | .master-content__header { 2 | position: relative; 3 | padding: 40px 50px; 4 | 5 | .btn { 6 | position: relative; 7 | top: 8px; 8 | } 9 | } 10 | 11 | .master-content__title-wrapper { 12 | display: inline-block; 13 | 14 | } 15 | 16 | .master-content__left { 17 | display: inline-block; 18 | } 19 | 20 | .master-content__center { 21 | 22 | @media (min-width: 1200px) { 23 | position: absolute; 24 | top: 50%; 25 | left: 50%; 26 | transform: translate(-50%, -50%); 27 | } 28 | } 29 | 30 | .master-content__right { 31 | @media (min-width: 1200px) { 32 | position: absolute; 33 | top: 50%; 34 | right: 50px; 35 | transform: translateY(-50%); 36 | } 37 | } 38 | 39 | .master-content__title { 40 | border: 0; 41 | margin: 0; 42 | } 43 | 44 | .master-content__header--with-bg { 45 | background-color: #fff; 46 | } 47 | 48 | .master-content__app-name{ 49 | color: #999; 50 | } -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/partials/master-content.scss: -------------------------------------------------------------------------------- 1 | @media (min-width: 767px) { 2 | .master-content { 3 | padding: 55px 0 100px 60px; 4 | } 5 | } 6 | 7 | .dashboard-content { 8 | padding: 50px 50px 0; 9 | } 10 | 11 | .list-content { 12 | padding: 50px 50px 0; 13 | } 14 | 15 | .container-fluid { 16 | padding: 0; 17 | } -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/partials/modifiers.scss: -------------------------------------------------------------------------------- 1 | .icon-right{ 2 | position: absolute; 3 | top: 50%; 4 | right: 25px; 5 | transform: translateY(-50%); 6 | color: $lighterFontcolor; 7 | } 8 | 9 | .list-icon{ 10 | position: absolute; 11 | top: 15px; 12 | left: 0; 13 | display: inline-block; 14 | } -------------------------------------------------------------------------------- /Js/Skeleton/Assets/styles/sass/webiny.scss: -------------------------------------------------------------------------------- 1 | @import 2 | 'vendor/fontello', 3 | 'vendor/fontello-ie7', 4 | 5 | 'helpers/transitions', 6 | 7 | 'base/variables', 8 | 'base/base', 9 | 'base/reset', 10 | 'base/fonts', 11 | 'base/animations', 12 | 'base/global', 13 | 14 | 'partials/general', 15 | //'partials/navigation', 16 | 'partials/header', 17 | 'partials/layout-header', 18 | 'partials/desktop-menu', 19 | 'partials/mobile-menu', 20 | 'partials/master-content', 21 | 'partials/footer', 22 | 'partials/charts', 23 | 'partials/modifiers', 24 | 'partials/signin', 25 | 'partials/overwrites'; -------------------------------------------------------------------------------- /Js/Skeleton/Components/Navigation/styles.scss: -------------------------------------------------------------------------------- 1 | @keyframes flickerAnimation { 2 | 0% { 3 | opacity: 1; 4 | } 5 | 50% { 6 | opacity: 0; 7 | } 8 | 100% { 9 | opacity: 1; 10 | } 11 | } 12 | 13 | @-o-keyframes flickerAnimation { 14 | 0% { 15 | opacity: 1; 16 | } 17 | 50% { 18 | opacity: 0; 19 | } 20 | 100% { 21 | opacity: 1; 22 | } 23 | } 24 | 25 | @-moz-keyframes flickerAnimation { 26 | 0% { 27 | opacity: 1; 28 | } 29 | 50% { 30 | opacity: 0; 31 | } 32 | 100% { 33 | opacity: 1; 34 | } 35 | } 36 | 37 | @-webkit-keyframes flickerAnimation { 38 | 0% { 39 | opacity: 1; 40 | } 41 | 50% { 42 | opacity: 0; 43 | } 44 | 100% { 45 | opacity: 1; 46 | } 47 | } 48 | 49 | .animateFlicker { 50 | -webkit-animation: flickerAnimation 1s infinite; 51 | -moz-animation: flickerAnimation 1s infinite; 52 | -o-animation: flickerAnimation 1s infinite; 53 | animation: flickerAnimation 1s infinite; 54 | } -------------------------------------------------------------------------------- /Js/Skeleton/Components/UserMenu/AccountPreferences.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * @i18n.namespace Webiny.Skeleton.Layout.UserMenu.AccountPreferencesMenu 6 | */ 7 | const AccountPreferencesMenu = (props) => { 8 | const {Link} = props; 9 | return ( 10 | 11 | {Webiny.I18n('Account preferences')} 12 | {Webiny.I18n('Set your account and user preferences')} 13 | 14 | ); 15 | }; 16 | 17 | export default Webiny.createComponent(AccountPreferencesMenu, {modules: ['Link']}); -------------------------------------------------------------------------------- /Js/Skeleton/Components/UserMenu/Logout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * @i18n.namespace Webiny.Skeleton.Layout.UserMenu.Logout 6 | */ 7 | const Logout = (props) => { 8 | return ( 9 |
10 | 11 | 12 | {Webiny.I18n('Log out')} 13 | 14 |
15 | ); 16 | }; 17 | 18 | export default Webiny.createComponent(Logout); -------------------------------------------------------------------------------- /Js/Skeleton/Modules/Layout/Components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | const Header = (props) => { 5 | return React.createElement(props.header); 6 | }; 7 | 8 | 9 | export default Webiny.createComponent(Header, {modules: [{header: 'Webiny/Skeleton/Header'}]}); -------------------------------------------------------------------------------- /Js/Skeleton/Modules/Layout/EmptyLayout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class EmptyLayout extends Webiny.Ui.View { 5 | 6 | } 7 | 8 | EmptyLayout.defaultProps = { 9 | renderer() { 10 | return ( 11 |
12 |
13 |
14 | 15 |
16 |
17 |
18 | ); 19 | } 20 | }; 21 | 22 | export default EmptyLayout; 23 | -------------------------------------------------------------------------------- /Js/Skeleton/Modules/Layout/Layout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * Layout is the main container that will hold all other components. 6 | * This component is the first one to render in the element. 7 | */ 8 | class Layout extends Webiny.Ui.View { 9 | 10 | } 11 | 12 | Layout.defaultProps = { 13 | renderer() { 14 | const {Navigation} = this.props; 15 | 16 | return ( 17 |
18 | 19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 | ); 28 | } 29 | }; 30 | 31 | export default Webiny.createComponent(Layout, { 32 | modules: [{ 33 | Navigation: 'Webiny/Skeleton/Navigation' 34 | }] 35 | }); 36 | -------------------------------------------------------------------------------- /Js/Skeleton/Modules/Layout/Views/Dashboard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * @i18n.namespace Webiny.Skeleton.Layout.Dashboard 6 | */ 7 | class Dashboard extends Webiny.Ui.Component { 8 | 9 | } 10 | 11 | Dashboard.defaultProps = { 12 | renderer() { 13 | return ( 14 | 15 | {(Ui) => ( 16 | 17 | 20 | 21 | )} 22 | 23 | ); 24 | } 25 | }; 26 | 27 | export default Dashboard; -------------------------------------------------------------------------------- /Js/Skeleton/Modules/Layout/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import Header from './Components/Header'; 4 | import DefaultLayout from './Layout'; 5 | import EmptyLayout from './EmptyLayout'; 6 | import Dashboard from './Views/Dashboard'; 7 | 8 | class Layout extends Webiny.App.Module { 9 | 10 | init() { 11 | this.name = 'Layout'; 12 | this.registerDefaultLayout(DefaultLayout); 13 | this.registerLayout('empty', EmptyLayout); 14 | this.registerDefaultComponents({Header}); 15 | 16 | this.registerRoutes( 17 | new Webiny.Route('Dashboard', '/', Dashboard, 'Dashboard') 18 | ); 19 | } 20 | } 21 | 22 | export default Layout; -------------------------------------------------------------------------------- /Js/Skeleton/Modules/UserAccount/index.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class Module extends Webiny.App.Module { 4 | 5 | init() { 6 | this.name = 'UserAccount'; 7 | 8 | this.registerRoutes( 9 | new Webiny.Route('Me.Notifications', '/me/notifications', () => Webiny.import('Webiny/Skeleton/UserNotificationsList'), 'My Notifications'), 10 | new Webiny.Route('Me.Account', '/me/account', () => Webiny.import('Webiny/Skeleton/UserAccountForm'), 'My Account') 11 | ); 12 | 13 | Webiny.registerModule( 14 | new Webiny.Module('Webiny/Skeleton/UserAccountForm', () => import('./UserAccountForm')), 15 | new Webiny.Module('Webiny/Skeleton/UserNotificationsList', () => import('./UserNotificationsList')) 16 | ); 17 | } 18 | } 19 | 20 | export default Module; -------------------------------------------------------------------------------- /Js/Skeleton/Views/Auth/Forbidden.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * @i18n.namespace Webiny.Skeleton.Auth.Forbidden 6 | */ 7 | class Forbidden extends Webiny.Ui.View { 8 | 9 | } 10 | 11 | Forbidden.defaultProps = { 12 | renderer() { 13 | const {Icon, View} = this.props; 14 | return ( 15 | 16 | 17 |

{this.i18n('Access Forbidden')}

18 | 19 |

20 | {this.i18n('Unfortunately, you are not allowed to see this page.')}
21 | {this.i18n('If you think this is a mistake, please contact your system administrator.')} 22 |

23 |
24 |
25 | ); 26 | } 27 | }; 28 | 29 | export default Webiny.createComponent(Forbidden, {modules: ['Icon', 'View']}); -------------------------------------------------------------------------------- /Js/Skeleton/Views/Auth/styles/Login.css: -------------------------------------------------------------------------------- 1 | .btnLogin { 2 | padding-left: 25px !important; 3 | } 4 | 5 | .btnLogin :global(.icon) { 6 | font-size: 32px; 7 | height: 20px; 8 | margin: -2px -8px 0px 0px; 9 | } -------------------------------------------------------------------------------- /Js/Ui/App.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | import 'Webiny/Ui/Assets/styles.scss'; 3 | import registerComponents from './Components'; 4 | import registerVendors from './Vendors'; 5 | 6 | class Ui extends Webiny.App { 7 | constructor() { 8 | super('Webiny.Ui'); 9 | registerComponents(); 10 | registerVendors(); 11 | console.timeStamp('App run: Webiny.Ui'); 12 | } 13 | } 14 | 15 | Webiny.registerApp(new Ui()); -------------------------------------------------------------------------------- /Js/Ui/Assets/global.scss: -------------------------------------------------------------------------------- 1 | .formGroup { 2 | margin-bottom: 15px; 3 | overflow: visible; 4 | } 5 | -------------------------------------------------------------------------------- /Js/Ui/Assets/styles.scss: -------------------------------------------------------------------------------- 1 | $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; 2 | @import '~bootstrap-sass/assets/stylesheets/bootstrap'; 3 | @import '~font-awesome/scss/font-awesome.scss'; 4 | @import '~animate.css/animate.css'; 5 | 6 | // new stuff 7 | @import 'global.scss'; -------------------------------------------------------------------------------- /Js/Ui/Components/Alert/Container.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class AlertContainer extends Webiny.Ui.Component { 5 | constructor(props) { 6 | super(props); 7 | 8 | this.state = { 9 | closed: false 10 | }; 11 | } 12 | 13 | close() { 14 | Promise.resolve(this.props.onClose()).then(() => { 15 | if (this.isMounted()) { 16 | this.setState({closed: true}); 17 | } 18 | }); 19 | } 20 | 21 | render() { 22 | if (this.state.closed) { 23 | return null; 24 | } 25 | 26 | return this.props.children(this.close.bind(this)); 27 | } 28 | } 29 | 30 | export default AlertContainer; -------------------------------------------------------------------------------- /Js/Ui/Components/Animate/AnimationSets.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import dynamics from 'dynamics.js'; 3 | 4 | class AnimationSets { 5 | static fadeIn(el, callback) { 6 | dynamics.animate(el, { 7 | opacity: 1 8 | }, { 9 | type: dynamics.spring, 10 | duration: 250, 11 | complete: callback 12 | }); 13 | } 14 | 15 | static fadeOut(el, callback) { 16 | dynamics.animate(el, { 17 | opacity: 0 18 | }, { 19 | type: dynamics.easeInOut, 20 | duration: 250, 21 | complete: callback 22 | }); 23 | } 24 | 25 | static custom(anim, el, callback) { 26 | dynamics.animate(el, anim, { 27 | type: dynamics[_.get(anim, 'ease', 'easeIn')], 28 | duration: _.get(anim, 'duration', 250), 29 | friction: _.get(anim, 'friction', null), 30 | frequency: _.get(anim, 'frequency', null), 31 | bounciness: _.get(anim, 'bounciness', null), 32 | elasticity: _.get(anim, 'elasticity', null), 33 | complete: callback 34 | }); 35 | } 36 | } 37 | 38 | export default AnimationSets; -------------------------------------------------------------------------------- /Js/Ui/Components/Avatar/styles.css: -------------------------------------------------------------------------------- 1 | .avatar { 2 | display: inline-block; 3 | text-align: center; 4 | } 5 | 6 | .uploadBtn{ 7 | margin-right: 0 !important; 8 | } 9 | 10 | .image { 11 | display: inline-block; 12 | text-align: center; 13 | max-width: 100%; 14 | height: auto; 15 | vertical-align: middle; 16 | border: none; 17 | } 18 | 19 | .placeholder { 20 | display: block; 21 | width: 132px; 22 | height: 132px; 23 | margin: 0 auto 15px; 24 | overflow: hidden; 25 | border: 2px dashed #cdcdcd; 26 | border-radius: 50%; 27 | color: #777; 28 | font-size: 44px; 29 | text-align: center; 30 | line-height: 275%; 31 | background-color: #fbfbfb; 32 | } 33 | 34 | .smallText { 35 | display: block; 36 | color: #c6c6c6; 37 | font-size: 12px; 38 | } -------------------------------------------------------------------------------- /Js/Ui/Components/ButtonGroup/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.scss'; 4 | 5 | class ButtonGroup extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | ButtonGroup.defaultProps = { 10 | className: null, 11 | renderer() { 12 | const {styles, className} = this.props; 13 | return ( 14 |
15 | {this.props.children} 16 |
17 | ); 18 | } 19 | }; 20 | 21 | export default Webiny.createComponent(ButtonGroup, {styles}); 22 | -------------------------------------------------------------------------------- /Js/Ui/Components/ButtonGroup/styles.scss: -------------------------------------------------------------------------------- 1 | .btnGroup { 2 | button, a { 3 | &:first-child:not(:last-child) { 4 | border-bottom-right-radius: 0; 5 | border-top-right-radius: 0; 6 | margin-right: 0; 7 | } 8 | 9 | &:first-child:not(:last-child):hover { 10 | box-shadow: none; 11 | } 12 | 13 | &:last-child:not(:first-child) { 14 | border-bottom-left-radius: 0; 15 | border-top-left-radius: 0; 16 | margin-left: 0px; 17 | } 18 | 19 | &:last-child:not(:first-child):hover { 20 | box-shadow: none; 21 | } 22 | 23 | &:not(:last-child):not(:first-child) { 24 | border-radius: 0; 25 | margin: 0; 26 | } 27 | } 28 | 29 | :global(button.Webiny_Ui_Button_btn) { 30 | &:hover, &:active, &:focus, &:focus:active { 31 | box-shadow: none; 32 | } 33 | } 34 | } 35 | 36 | @media (max-width: 768px) { 37 | .btnGroup { 38 | display: flex; 39 | 40 | :global(button.Webiny_Ui_Button_btn) { 41 | flex-grow: 1; 42 | } 43 | 44 | button, a { 45 | &:not(:last-child):not(:first-child) { 46 | margin-top: 10px; 47 | margin-bottom: 10px; 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Js/Ui/Components/CheckboxGroup/styles.css: -------------------------------------------------------------------------------- 1 | .disabled { 2 | opacity: 0.5; 3 | cursor: not-allowed; 4 | } -------------------------------------------------------------------------------- /Js/Ui/Components/CodeEditor/styles.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | z-index: 1; 3 | position: relative; 4 | } -------------------------------------------------------------------------------- /Js/Ui/Components/CodeHighlight/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Webiny from 'webiny'; 4 | import './styles.scss?extract'; 5 | 6 | class CodeHighlight extends Webiny.Ui.Component { 7 | constructor(props) { 8 | super(props); 9 | 10 | this.bindMethods('doHighlight'); 11 | } 12 | 13 | componentDidMount() { 14 | this.doHighlight(); 15 | } 16 | 17 | componentDidUpdate() { 18 | this.doHighlight(); 19 | } 20 | 21 | doHighlight() { 22 | this.props.hljs.highlightBlock(ReactDOM.findDOMNode(this).querySelector('pre code')); 23 | } 24 | } 25 | 26 | 27 | CodeHighlight.defaultProps = { 28 | language: 'html', 29 | renderer() { 30 | return
{this.props.children}
; 31 | } 32 | }; 33 | 34 | export default Webiny.createComponent(CodeHighlight, {modules: [{hljs: 'Webiny/Vendors/Highlight'}]}); -------------------------------------------------------------------------------- /Js/Ui/Components/CodeHighlight/styles.scss: -------------------------------------------------------------------------------- 1 | @import '~highlight.js/styles/monokai.css'; 2 | -------------------------------------------------------------------------------- /Js/Ui/Components/Copy/index.js: -------------------------------------------------------------------------------- 1 | import CopyInput from './CopyInput'; 2 | import CopyButton from './CopyButton'; 3 | 4 | export default { 5 | Input: CopyInput, 6 | Button: CopyButton 7 | }; 8 | -------------------------------------------------------------------------------- /Js/Ui/Components/Copy/styles.css: -------------------------------------------------------------------------------- 1 | .input { 2 | color: #393939; 3 | background-color: #f5f5f5; 4 | padding: 10px 15px; 5 | height: 45px; 6 | border: 1px solid #cdcdcd; 7 | width: 100%; 8 | line-height: 135%; 9 | box-shadow: none; 10 | border-radius: 0; 11 | transition: all 225ms; 12 | display: table-cell; 13 | position: relative; 14 | z-index: 2; 15 | float: left; 16 | margin-bottom: 0; 17 | font-size: 14px; 18 | font-family: "Source Sans Pro"; 19 | } 20 | 21 | /** btnCopy **/ 22 | .btnCopy { 23 | position: absolute; 24 | right: 5px; 25 | z-index: 100; 26 | height: 6px; 27 | top: 6px; 28 | line-height: 1; 29 | padding: 10px 15px 20px 15px; 30 | } 31 | 32 | .btnCopy:hover, .btnCopy:active, .btnCopy:focus { 33 | box-shadow: none; 34 | } 35 | 36 | /* make it responsive */ 37 | @media (max-width: 768px) { 38 | .input { 39 | margin-bottom: 40px; 40 | padding: 20px 15px; 41 | } 42 | 43 | .btnCopy { 44 | right: 0; 45 | top: 40px; 46 | padding: 15px; 47 | font-size: 1em; 48 | line-height: 2px; 49 | } 50 | } -------------------------------------------------------------------------------- /Js/Ui/Components/Cropper/index.js: -------------------------------------------------------------------------------- 1 | import ModalCropper from './ModalCropper'; 2 | import InlineCropper from './InlineCropper'; 3 | 4 | export default { 5 | Modal: ModalCropper, 6 | Inline: InlineCropper 7 | }; -------------------------------------------------------------------------------- /Js/Ui/Components/Downloader/Ideas/Dialog.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class Dialog extends Webiny.Ui.Component { 5 | componentDidUpdate(prevProps, prevState) { 6 | super.componentDidUpdate(prevProps, prevState); 7 | if (!prevProps.show && this.props.show) { 8 | this.refs.dialog.show(); 9 | } 10 | } 11 | } 12 | 13 | Dialog.defaultProps = { 14 | renderer() { 15 | const dialogProps = { 16 | ref: 'dialog', 17 | onHidden: this.props.onHidden 18 | }; 19 | 20 | const funcParams = { 21 | download: this.props.download 22 | }; 23 | 24 | return ( 25 | 26 | {React.cloneElement(this.props.renderDialog(funcParams), dialogProps)} 27 | 28 | ); 29 | } 30 | }; 31 | 32 | export default Dialog; -------------------------------------------------------------------------------- /Js/Ui/Components/Downloader/Ideas/Element.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class Element extends Webiny.Ui.Component { 5 | 6 | } 7 | 8 | Element.defaultProps = { 9 | renderer() { 10 | return ( 11 | 12 | {this.props.children({download: this.props.download})} 13 | 14 | ); 15 | } 16 | }; 17 | 18 | export default Element; -------------------------------------------------------------------------------- /Js/Ui/Components/Downloader/Ideas/Readme.md: -------------------------------------------------------------------------------- 1 | # Download Component 2 | - the idea is to create a `Download` component which can have `Element` and optionally a `Dialog` element 3 | - this will make component markup clearer 4 | - see `Example.jsx` for usage example -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/CustomViews.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class CustomViews extends Webiny.Ui.Component { 5 | shouldComponentUpdate(nextProps) { 6 | return nextProps.preview !== this.props.preview; 7 | } 8 | } 9 | 10 | CustomViews.defaultProps = { 11 | renderer() { 12 | const views = this.props.plugins.getCustomViews().map((view, i) => { 13 | return
{view}
; 14 | }); 15 | 16 | return ( 17 | {views} 18 | ); 19 | } 20 | }; 21 | 22 | export default CustomViews; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/Blockquote.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import BlockType from './../Toolbar/BlockType'; 4 | 5 | class BlockquotePlugin extends Webiny.Draft.BlockTypePlugin { 6 | constructor(config) { 7 | super(config); 8 | this.name = 'blockquote'; 9 | this.block = 'blockquote'; 10 | } 11 | 12 | getEditConfig() { 13 | return { 14 | toolbar: ( 15 | 16 | ) 17 | }; 18 | } 19 | } 20 | 21 | export default BlockquotePlugin; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/Bold.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import InlineStyle from './../Toolbar/InlineStyle'; 4 | 5 | class BoldPlugin extends Webiny.Draft.InlineStylePlugin { 6 | constructor(config) { 7 | super(config); 8 | this.name = 'bold'; 9 | this.style = 'BOLD'; 10 | } 11 | 12 | getEditConfig() { 13 | return { 14 | toolbar: , 15 | handleKeyCommand: (command) => { 16 | if (command === 'bold' && this.editor.getEditorState().getSelection().isCollapsed()) { 17 | return true; 18 | } 19 | } 20 | }; 21 | } 22 | } 23 | 24 | export default BoldPlugin; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/Italic.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import InlineStyle from './../Toolbar/InlineStyle'; 4 | 5 | class ItalicPlugin extends Webiny.Draft.InlineStylePlugin { 6 | constructor(config) { 7 | super(config); 8 | this.name = 'bold'; 9 | this.style = 'ITALIC'; 10 | } 11 | 12 | getEditConfig() { 13 | return { 14 | toolbar: , 15 | handleKeyCommand: (command, editor) => { 16 | if (command === 'italic' && editor.getEditorState().getSelection().isCollapsed()) { 17 | return true; 18 | } 19 | } 20 | }; 21 | } 22 | } 23 | 24 | export default ItalicPlugin; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/OrderedList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import BlockType from './../Toolbar/BlockType'; 4 | 5 | class OrderedListPlugin extends Webiny.Draft.BlockTypePlugin { 6 | constructor(config) { 7 | super(config); 8 | this.name = 'ordered-list'; 9 | this.block = 'ordered-list-item'; 10 | } 11 | 12 | getEditConfig() { 13 | return { 14 | toolbar: 15 | }; 16 | } 17 | } 18 | 19 | export default OrderedListPlugin; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/Table/TabHandler.js: -------------------------------------------------------------------------------- 1 | import Webiny from 'webiny'; 2 | 3 | class TabHandler extends Webiny.Draft.BasePlugin { 4 | constructor(config) { 5 | super(config); 6 | } 7 | 8 | getEditConfig() { 9 | return { 10 | onTab: (e) => { 11 | if (!this.editor.getReadOnly()) { 12 | return e.shiftKey ? this.config.selectPrevEditor() : this.config.selectNextEditor(); 13 | } 14 | } 15 | }; 16 | } 17 | } 18 | 19 | export default TabHandler; -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Plugins/ToJSON.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * @i18n.namespace Webiny.Ui.Draft.Plugins.ToJSONPlugin 6 | */ 7 | class ToJSONPlugin extends Webiny.Draft.BasePlugin { 8 | constructor(config) { 9 | super(config); 10 | this.name = 'toJson'; 11 | } 12 | 13 | toJSON() { 14 | const content = this.editor.getEditorState().getCurrentContent(); 15 | console.log(JSON.stringify(this.Draft.convertToRaw(content), null, 2)); 16 | } 17 | 18 | getEditConfig() { 19 | return { 20 | toolbar: ( 21 | 22 | {({Button}) => ( 23 | 26 | ); 27 | } 28 | }; 29 | 30 | export default Webiny.createComponent(Atomic, {modules: ['Button']}); -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Toolbar/BlockType.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class BlockType extends Webiny.Ui.Component { 5 | } 6 | 7 | BlockType.defaultProps = { 8 | icon: null, 9 | plugin: null, 10 | renderer() { 11 | const isActive = this.props.plugin.isActive(); 12 | const disabled = this.props.plugin.isDisabled(); 13 | const props = { 14 | style: this.props.style || {}, 15 | className: this.props.className || '', 16 | disabled, 17 | type: isActive ? 'primary' : 'default', 18 | onClick: () => this.props.plugin.toggleBlockType(), 19 | icon: this.props.icon, 20 | tooltip: this.props.tooltip 21 | }; 22 | 23 | const {Button} = this.props; 24 | 25 | return ( 26 | 28 | ); 29 | } 30 | }; 31 | 32 | export default Webiny.createComponent(Entity, {modules: ['Button']}); -------------------------------------------------------------------------------- /Js/Ui/Components/Draft/Toolbar/InlineStyle.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | class InlineStyle extends Webiny.Ui.Component { 5 | } 6 | 7 | InlineStyle.defaultProps = { 8 | icon: null, 9 | plugin: null, 10 | renderer() { 11 | const isActive = this.props.plugin.isActive(); 12 | const disabled = this.props.plugin.isDisabled(); 13 | const props = { 14 | style: this.props.style || {}, 15 | className: this.props.className || '', 16 | disabled, 17 | type: isActive ? 'primary' : 'default', 18 | onClick: () => this.props.plugin.toggleStyle(), 19 | icon: this.props.icon, 20 | tooltip: this.props.tooltip 21 | }; 22 | 23 | const {Button} = this.props; 24 | 25 | return ( 26 | 25 | )} 26 | 27 | ); 28 | } 29 | }; 30 | 31 | export default Webiny.createComponent(Header, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Modal/index.js: -------------------------------------------------------------------------------- 1 | import Dialog from './Components/Dialog'; 2 | import Content from './Components/Content'; 3 | import Header from './Components/Header'; 4 | import Body from './Components/Body'; 5 | import Footer from './Components/Footer'; 6 | import Confirmation from './Components/Confirmation'; 7 | import Success from './Components/Success'; 8 | 9 | export default { 10 | Dialog, 11 | Content, 12 | Body, 13 | Header, 14 | Footer, 15 | Confirmation, 16 | Success 17 | }; -------------------------------------------------------------------------------- /Js/Ui/Components/Panel/Body.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Body extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Body.defaultProps = { 10 | style: null, 11 | renderer() { 12 | const classes = this.classSet(this.props.styles.body, this.props.className); 13 | return
{this.props.children}
; 14 | } 15 | }; 16 | 17 | export default Webiny.createComponent(Body, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Panel/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Footer extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Footer.defaultProps = { 10 | style: {}, 11 | renderer() { 12 | const classes = this.classSet(this.props.styles.footer, this.props.className); 13 | return
{this.props.children}
; 14 | } 15 | }; 16 | 17 | export default Webiny.createComponent(Footer, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Panel/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Header extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Header.defaultProps = { 10 | title: null, 11 | icon: null, 12 | renderer() { 13 | let icon = null; 14 | if (this.props.icon) { 15 | icon = ; 16 | } 17 | 18 | const classes = this.classSet(this.props.styles.header, this.props.className); 19 | return ( 20 |
21 | {icon} {this.props.title} 22 | {this.props.children} 23 |
24 | ); 25 | } 26 | }; 27 | 28 | export default Webiny.createComponent(Header, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Panel/Panel.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Panel extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Panel.defaultProps = { 10 | renderer() { 11 | const classes = this.classSet(this.props.styles.panel, this.props.className); 12 | return
{this.props.children}
; 13 | } 14 | }; 15 | 16 | export default Webiny.createComponent(Panel, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Panel/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Body from './Body'; 3 | import Header from './Header'; 4 | import Footer from './Footer'; 5 | import Panel from './Panel'; 6 | 7 | _.assign(Panel, {Header, Body, Footer}); 8 | 9 | export default Panel; 10 | -------------------------------------------------------------------------------- /Js/Ui/Components/Popover/styles.scss: -------------------------------------------------------------------------------- 1 | .popover { 2 | border-radius: 0; 3 | padding: 0; 4 | border-color: #ccc; 5 | 6 | .popover-title { 7 | background-color: #3FBFB0; 8 | color: #fff; 9 | border-radius: 0; 10 | font-weight: 300; 11 | font-size: 1.2em; 12 | border-bottom: none; 13 | margin-top: 0px; 14 | margin-bottom: 0px; 15 | } 16 | 17 | &.bottom > .arrow:after { 18 | border-bottom-color: #3FBFB0; 19 | } 20 | &.top > .arrow:after { 21 | border-top-color: #3FBFB0; 22 | } 23 | &.right > .arrow:after { 24 | border-right-color: #3FBFB0; 25 | } 26 | &.left > .arrow:after { 27 | border-left-color: #3FBFB0; 28 | } 29 | } -------------------------------------------------------------------------------- /Js/Ui/Components/Progress/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Progress extends Webiny.Ui.Component { 6 | } 7 | 8 | Progress.defaultProps = { 9 | value: 0, 10 | renderer() { 11 | const {styles} = this.props; 12 | 13 | return ( 14 |
15 |
16 |
23 |
24 |
25 | ); 26 | } 27 | }; 28 | 29 | export default Webiny.createComponent(Progress, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/RadioGroup/styles.css: -------------------------------------------------------------------------------- 1 | .radio { 2 | display: block; 3 | background-color: transparent; 4 | color: inherit; 5 | margin-bottom: 7px; 6 | } 7 | 8 | /* hide default input */ 9 | .radio input { 10 | display: none; 11 | } 12 | 13 | .radio label:empty { 14 | padding-left: 10px; 15 | } 16 | 17 | .radio label { 18 | cursor: pointer; 19 | position: relative; 20 | padding-left: 32px; 21 | margin-right: 15px; 22 | font-weight: normal; 23 | font-size: 16px; 24 | margin-bottom: 0; 25 | } 26 | 27 | .radio.disabled label { 28 | color: #CCC; 29 | } 30 | 31 | /* radio border */ 32 | .radio label:before { 33 | content: ""; 34 | position: absolute; 35 | top: 0; 36 | left: 0; 37 | border-radius: 64px; 38 | width: 20px; 39 | height: 20px; 40 | border: 1px solid #373737; 41 | } 42 | 43 | /* check radio icon */ 44 | .radio input[type=radio]:checked + label:after, 45 | .radio input[type=checkbox]:checked + label:after { 46 | content: ""; 47 | position: absolute; 48 | top: 6px; 49 | left: 6px; 50 | border-radius: 64px; 51 | width: 8px; 52 | height: 8px; 53 | color: #8BDBED; 54 | background-color: #373737; 55 | } -------------------------------------------------------------------------------- /Js/Ui/Components/Section/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import Webiny from 'webiny'; 4 | import styles from './styles.css'; 5 | 6 | class Section extends Webiny.Ui.Component { 7 | 8 | } 9 | 10 | Section.defaultProps = { 11 | title: null, 12 | icon: null, 13 | renderer() { 14 | const {Icon, styles} = this.props; 15 | let icon = null; 16 | if (this.props.icon) { 17 | icon = ; 18 | } 19 | 20 | return ( 21 |
22 |
23 |
{icon} {this.props.title}
24 | {_.size(this.props.children) > 0 &&
{this.props.children}
} 25 |
26 |
27 | ); 28 | } 29 | }; 30 | 31 | export default Webiny.createComponent(Section, {modules: ['Icon'], styles}); 32 | -------------------------------------------------------------------------------- /Js/Ui/Components/Section/styles.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-bottom: 20px; 3 | } 4 | 5 | .header { 6 | text-align: left; 7 | border-bottom: 3px solid red; 8 | margin-bottom: 15px; 9 | /*margin-top: 25px;*/ 10 | } 11 | 12 | .wrapper .title { 13 | display: inline-block; 14 | font-weight: 600; 15 | font-size: 18px; 16 | color: #2B2B2B; 17 | margin: 15px 2px; 18 | } 19 | 20 | .container { 21 | display: inline-block; 22 | float: right; 23 | min-height: 35px; 24 | } -------------------------------------------------------------------------------- /Js/Ui/Components/Tabs/Tab.jsx: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import Webiny from 'webiny'; 3 | 4 | /** 5 | * Skeleton class for possible future upgrades 6 | */ 7 | class Tab extends Webiny.Ui.Component { 8 | 9 | } 10 | 11 | Tab.defaultProps = { 12 | onClick: _.noop 13 | }; 14 | 15 | export default Webiny.createComponent(Tab, {tab: true}); -------------------------------------------------------------------------------- /Js/Ui/Components/Tabs/TabContent.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class TabContent extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | TabContent.defaultProps = { 10 | alwaysRender: true, 11 | active: false, // "private" prop passed by Tabs component 12 | disabled: false, // "private" prop passed by Tabs component 13 | renderer() { 14 | if (!this.props.disabled && (this.props.active || this.props.alwaysRender)) { 15 | const tabClass = this.classSet( 16 | styles.pane, 17 | { 18 | [styles.paneActive]: this.props.active 19 | } 20 | ); 21 | return ( 22 |
23 | {this.props.children} 24 |
25 |
26 | ); 27 | } 28 | 29 | return null; 30 | } 31 | }; 32 | 33 | export default Webiny.createComponent(TabContent, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Tabs/index.js: -------------------------------------------------------------------------------- 1 | import Tabs from './Tabs'; 2 | import Tab from './Tab'; 3 | import TabHeader from './TabHeader'; 4 | import TabContent from './TabContent'; 5 | 6 | Tabs.Tab = Tab; 7 | Tab.Header = TabHeader; 8 | Tab.Content = TabContent; 9 | 10 | export default Tabs; 11 | -------------------------------------------------------------------------------- /Js/Ui/Components/Textarea/styles.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-bottom: 15px; 3 | position: relative; 4 | text-align: left; 5 | overflow: visible; 6 | } 7 | 8 | .textarea { 9 | min-height: 145px; 10 | line-height: 135%; 11 | padding: 20px 15px; 12 | border: 1px solid #cdcdcd; 13 | width: 100%; 14 | background-color: #fbfbfb; 15 | color: #333; 16 | box-shadow: none; 17 | border-radius: 0; 18 | transition: all 225ms; 19 | display: block; 20 | font-size: 14px; 21 | overflow: auto; 22 | z-index: 1; /* so the error message goes behind the text area */ 23 | -webkit-appearance: none; /* fixes the inner shadow on Safari (iphone) */ 24 | } 25 | 26 | :global(.inputGroup).textarea{ 27 | display: inline-block; 28 | } 29 | 30 | .textarea:focus{ 31 | background: #fff; 32 | border-color: #333; 33 | outline: none !important; 34 | box-shadow: none !important; 35 | } -------------------------------------------------------------------------------- /Js/Ui/Components/Tile/Body.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Body extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Body.defaultProps = { 10 | style: null, 11 | renderer() { 12 | const {styles} = this.props; 13 | const classes = this.classSet(styles.content, this.props.className); 14 | return
{this.props.children}
; 15 | } 16 | }; 17 | 18 | export default Webiny.createComponent(Body, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/Tile/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Header extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Header.defaultProps = { 10 | icon: null, 11 | style: null, 12 | title: null, 13 | renderer() { 14 | const {Icon, icon, styles, className} = this.props; 15 | 16 | const classes = this.classSet(styles.header, className); 17 | return ( 18 |
19 | {icon ?
: null} 20 |

{this.props.title}

21 | {this.props.children} 22 |
23 | ); 24 | } 25 | }; 26 | 27 | export default Webiny.createComponent(Header, {styles, modules: ['Icon']}); -------------------------------------------------------------------------------- /Js/Ui/Components/Tile/Tile.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Tile extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Tile.defaultProps = { 10 | className: null, 11 | type: 'default', 12 | renderer() { 13 | const {styles} = this.props; 14 | 15 | const typeClasses = { 16 | default: styles.default, 17 | primary: styles.primary, 18 | success: styles.success 19 | }; 20 | 21 | const classes = this.classSet( 22 | styles.tile, 23 | this.props.className, 24 | typeClasses[this.props.type] 25 | ); 26 | 27 | return
{this.props.children}
; 28 | } 29 | }; 30 | 31 | export default Webiny.createComponent(Tile, {styles}); 32 | -------------------------------------------------------------------------------- /Js/Ui/Components/Tile/index.js: -------------------------------------------------------------------------------- 1 | import Body from './Body'; 2 | import Header from './Header'; 3 | import Tile from './Tile'; 4 | 5 | Tile.Header = Header; 6 | Tile.Body = Body; 7 | 8 | export default Tile; -------------------------------------------------------------------------------- /Js/Ui/Components/View/Body.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class Body extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Body.defaultProps = { 10 | noPadding: false, 11 | renderer() { 12 | const {Panel, styles} = this.props; 13 | 14 | const classSet = this.classSet( 15 | styles.panelBody, 16 | { 17 | [styles.panelNoPadding]: this.props.noPadding 18 | } 19 | ); 20 | 21 | return ( 22 | 23 | {this.props.children} 24 | 25 | ); 26 | } 27 | }; 28 | 29 | export default Webiny.createComponent(Body, {modules: ['Panel'], styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/ChartBlock.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class ChartBlock extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | ChartBlock.defaultProps = { 10 | title: '', 11 | description: '', 12 | className: '', 13 | renderer() { 14 | const {styles} = this.props; 15 | 16 | let showHeader = false; 17 | if (this.props.title !== '' || this.props.description !== '') { 18 | showHeader = true; 19 | } 20 | 21 | return ( 22 |
23 |
24 |

{this.props.title}

25 |
{this.props.description}
26 |
27 |
28 | {this.props.children} 29 |
30 |
31 | ); 32 | } 33 | }; 34 | 35 | export default Webiny.createComponent(ChartBlock, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/DashboardComponents/HeaderCenter.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './../styles.css'; 4 | 5 | class HeaderCenter extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | HeaderCenter.defaultProps = { 10 | renderer() { 11 | const {styles} = this.props; 12 | 13 | return ( 14 |
15 | {this.props.children} 16 |
17 | ); 18 | } 19 | }; 20 | 21 | export default Webiny.createComponent(HeaderCenter, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/DashboardComponents/HeaderLeft.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import _ from 'lodash'; 4 | import styles from './../styles.css'; 5 | 6 | class HeaderLeft extends Webiny.Ui.Component { 7 | 8 | } 9 | 10 | HeaderLeft.defaultProps = { 11 | title: null, 12 | description: null, 13 | renderer() { 14 | const {styles} = this.props; 15 | 16 | // extract the app name 17 | const appName = _.get(Webiny.Router.getActiveRoute(), 'module.app.name', '').split('.')[0]; 18 | 19 | return ( 20 |
21 |

22 | {appName}/{this.props.title} 23 |

24 |
{this.props.description}
25 |
26 | ); 27 | } 28 | }; 29 | 30 | export default Webiny.createComponent(HeaderLeft, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/DashboardComponents/HeaderRight.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './../styles.css'; 4 | 5 | class HeaderRight extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | HeaderRight.defaultProps = { 10 | renderer() { 11 | const {styles} = this.props; 12 | 13 | return ( 14 |
15 | {this.props.children} 16 |
17 | ); 18 | } 19 | }; 20 | 21 | export default Webiny.createComponent(HeaderRight, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css' 4 | 5 | class Footer extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | Footer.defaultProps = { 10 | align: null, 11 | renderer() { 12 | const {styles} = this.props; 13 | 14 | const css = this.classSet( 15 | styles.panelFooter, 16 | this.props.align === 'right' ? 'text-right' : null, 17 | this.props.className 18 | ); 19 | 20 | const {Panel} = this.props; 21 | 22 | return ( 23 | 24 | {this.props.children} 25 | 26 | ); 27 | } 28 | }; 29 | 30 | export default Webiny.createComponent(Footer, {modules: ['Panel'], styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/InfoBlock.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import styles from './styles.css'; 4 | 5 | class InfoBlock extends Webiny.Ui.Component { 6 | 7 | } 8 | 9 | InfoBlock.defaultProps = { 10 | title: '', 11 | description: '', 12 | className: '', 13 | renderer() { 14 | 15 | let showHeader = false; 16 | if (this.props.title !== '' || this.props.description !== '') { 17 | showHeader = true; 18 | } 19 | 20 | return ( 21 |
22 | {showHeader && (
23 |

{this.props.title}

24 |
{this.props.description}
25 |
)} 26 |
27 | {this.props.children} 28 |
29 |
30 | ); 31 | } 32 | }; 33 | 34 | export default Webiny.createComponent(InfoBlock, {styles}); -------------------------------------------------------------------------------- /Js/Ui/Components/View/index.js: -------------------------------------------------------------------------------- 1 | import View from './View'; 2 | import FormView from './FormView'; 3 | import ListView from './ListView'; 4 | import DashboardView from './DashboardView'; 5 | import ChartBlock from './ChartBlock'; 6 | import InfoBlock from './InfoBlock'; 7 | import Body from './Body'; 8 | import Header from './Header'; 9 | import Footer from './Footer'; 10 | import HeaderCenter from './DashboardComponents/HeaderCenter'; 11 | 12 | View.Form = FormView; 13 | View.List = ListView; 14 | View.Dashboard = DashboardView; 15 | View.Header = Header; 16 | View.Header.Center = HeaderCenter; 17 | View.Body = Body; 18 | View.Footer = Footer; 19 | 20 | View.ChartBlock = ChartBlock; 21 | View.InfoBlock = InfoBlock; 22 | 23 | export default View; -------------------------------------------------------------------------------- /Js/Ui/Components/ViewSwitcher/index.js: -------------------------------------------------------------------------------- 1 | import ViewSwitcher from './Switcher'; 2 | import View from './View'; 3 | 4 | ViewSwitcher.View = View; 5 | 6 | export default ViewSwitcher; -------------------------------------------------------------------------------- /Js/Ui/Components/Wizard/Step.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import _ from 'lodash'; 4 | 5 | import Content from './Step/Content'; 6 | import Actions from './Step/Actions'; 7 | 8 | class Step extends Webiny.Ui.Component { 9 | } 10 | 11 | Step.defaultProps = { 12 | current: false, 13 | completed: false, 14 | title: null, 15 | name: null, 16 | onLeave: _.noop, 17 | onEnter: _.noop 18 | }; 19 | 20 | Step.Content = Content; 21 | Step.Actions = Actions; 22 | 23 | export default Step; -------------------------------------------------------------------------------- /Js/Ui/Components/Wizard/Step/Actions.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | 4 | import Next from './Actions/Next'; 5 | import Previous from './Actions/Previous'; 6 | import Action from './Actions/Action'; 7 | import Finish from './Actions/Finish'; 8 | 9 | class Actions extends Webiny.Ui.Component { 10 | } 11 | 12 | Actions.Next = Next; 13 | Actions.Previous = Previous; 14 | Actions.Action = Action; 15 | Actions.Finish = Finish; 16 | 17 | export default Actions; -------------------------------------------------------------------------------- /Js/Ui/Components/Wizard/Step/Actions/Action.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Webiny from 'webiny'; 3 | import _ from 'lodash'; 4 | 5 | class Action extends Webiny.Ui.Component { 6 | } 7 | 8 | // Receives all standard Button component props 9 | Action.defaultProps = { 10 | wizard: null, 11 | renderer() { 12 | const {Button} = this.props; 13 | return