├── .dockerignore ├── .editorconfig ├── .github ├── dependabot.yml ├── help.adoc ├── pr-labeler.yml ├── release.yml └── workflows │ ├── build.yml │ ├── commit-message-check-format.yml │ ├── crowdin-download.yml │ ├── crowdin-upload.yml │ ├── labeler.yml │ ├── list-dependencies.yml │ ├── merge-branches.yml │ ├── publish-artefacts.yml │ ├── push_to_subtree.yml │ ├── release-uid.yml │ ├── report-changes-on-artifact-builder.yml │ └── update-version.yml ├── .gitignore ├── .idea └── jsLinters │ └── eslint.xml ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .run ├── Start Backend.run.xml └── Start Frontend.run.xml ├── .sdkmanrc ├── CONTRIBUTING.MD ├── Dockerfile ├── LICENSE ├── README.md ├── UI-Designer.svg ├── backend ├── README.md ├── contract │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── bonitasoft │ │ │ └── web │ │ │ └── designer │ │ │ └── model │ │ │ └── contract │ │ │ ├── AbstractContractInput.java │ │ │ ├── BusinessDataReference.java │ │ │ ├── Contract.java │ │ │ ├── ContractInput.java │ │ │ ├── ContractInputContainer.java │ │ │ ├── ContractInputVisitor.java │ │ │ ├── DataReference.java │ │ │ ├── EditMode.java │ │ │ ├── LeafContractInput.java │ │ │ ├── NodeContractInput.java │ │ │ └── databind │ │ │ └── ContractDeserializer.java │ │ └── test │ │ └── java │ │ └── org │ │ └── bonitasoft │ │ └── web │ │ └── designer │ │ └── model │ │ └── contract │ │ ├── builders │ │ ├── ContractBuilder.java │ │ └── ContractInputBuilder.java │ │ └── databind │ │ └── ContractDeserializerTest.java ├── copyright │ ├── copyright.txt │ └── copyright.xml ├── pom.xml └── webapp │ ├── pom.xml │ └── src │ ├── main │ ├── groovy │ │ ├── dependencies-adoc.groovy │ │ └── templates │ │ │ └── dependencies.adoc.hbs │ ├── java │ │ └── org │ │ │ └── bonitasoft │ │ │ └── web │ │ │ └── designer │ │ │ ├── Main.java │ │ │ ├── config │ │ │ ├── DesignerConfig.java │ │ │ ├── DesignerInitializerException.java │ │ │ ├── WebMvcConfiguration.java │ │ │ └── WebSocketConfig.java │ │ │ ├── controller │ │ │ ├── AssetResource.java │ │ │ ├── BonitaExceptionHandler.java │ │ │ ├── ConfigurationResource.java │ │ │ ├── ExportController.java │ │ │ ├── FragmentResource.java │ │ │ ├── ImportController.java │ │ │ ├── MigrationResource.java │ │ │ ├── PageResource.java │ │ │ ├── PreviewController.java │ │ │ ├── RequestMappingUtils.java │ │ │ ├── ResourceControllerAdvice.java │ │ │ ├── ResponseHeadersHelper.java │ │ │ ├── UiGenerationResource.java │ │ │ ├── WidgetResource.java │ │ │ ├── WorkspaceResource.java │ │ │ ├── preview │ │ │ │ └── PreservingCookiePathProxyServlet.java │ │ │ └── utils │ │ │ │ ├── HttpFile.java │ │ │ │ ├── MimeType.java │ │ │ │ └── UnZipper.java │ │ │ ├── generator │ │ │ ├── Formatter.java │ │ │ ├── mapping │ │ │ │ ├── ContractInputDataHandler.java │ │ │ │ ├── ContractInputToWidgetMapper.java │ │ │ │ ├── ContractInputVisitorImpl.java │ │ │ │ ├── ContractToContainerMapper.java │ │ │ │ ├── ContractToPageMapper.java │ │ │ │ ├── DimensionFactory.java │ │ │ │ ├── FormScope.java │ │ │ │ ├── data │ │ │ │ │ ├── BusinessData.java │ │ │ │ │ ├── BusinessDataLazyRef.java │ │ │ │ │ ├── BusinessQueryData.java │ │ │ │ │ ├── BusinessQueryDataFactory.java │ │ │ │ │ ├── ContextData.java │ │ │ │ │ ├── FormInputData.java │ │ │ │ │ ├── FormInputVisitor.java │ │ │ │ │ ├── FormOutputData.java │ │ │ │ │ ├── FormOutputVisitor.java │ │ │ │ │ ├── OutputProperty.java │ │ │ │ │ ├── StringUtil.java │ │ │ │ │ ├── SubmitErrorsListData.java │ │ │ │ │ ├── TaskData.java │ │ │ │ │ └── TaskIdData.java │ │ │ │ ├── dataManagement │ │ │ │ │ ├── BusinessDataToWidgetMapper.java │ │ │ │ │ ├── BusinessObject.java │ │ │ │ │ ├── BusinessObjectContainer.java │ │ │ │ │ ├── BusinessObjectDataHandler.java │ │ │ │ │ ├── BusinessObjectVisitorImpl.java │ │ │ │ │ ├── DataManagementGenerator.java │ │ │ │ │ ├── NodeBusinessObjectInput.java │ │ │ │ │ ├── WidgetDescription.java │ │ │ │ │ └── databind │ │ │ │ │ │ └── BusinessObjectDeserializer.java │ │ │ │ └── strategy │ │ │ │ │ ├── CaseOverviewPageCreationStrategy.java │ │ │ │ │ ├── PageCreationStrategy.java │ │ │ │ │ ├── ProcessInstantiationFormCreationStrategy.java │ │ │ │ │ └── TaskFormCreationStrategy.java │ │ │ └── parametrizedWidget │ │ │ │ ├── AbstractParametrizedWidget.java │ │ │ │ ├── Alignment.java │ │ │ │ ├── ButtonAction.java │ │ │ │ ├── ButtonStyle.java │ │ │ │ ├── ButtonWidget.java │ │ │ │ ├── CheckboxWidget.java │ │ │ │ ├── DatePickerWidget.java │ │ │ │ ├── DateTimePickerWidget.java │ │ │ │ ├── FileUploadWidget.java │ │ │ │ ├── FileViewerWidget.java │ │ │ │ ├── InputType.java │ │ │ │ ├── InputTypeResolver.java │ │ │ │ ├── InputWidget.java │ │ │ │ ├── LabelParametrizedWidget.java │ │ │ │ ├── LabelPosition.java │ │ │ │ ├── Labeled.java │ │ │ │ ├── LinkWidget.java │ │ │ │ ├── ParameterConstants.java │ │ │ │ ├── ParametrizedDataManagementWidgetFactory.java │ │ │ │ ├── ParametrizedWidget.java │ │ │ │ ├── ParametrizedWidgetFactory.java │ │ │ │ ├── Requirable.java │ │ │ │ ├── SelectWidget.java │ │ │ │ ├── TableWidget.java │ │ │ │ ├── TextWidget.java │ │ │ │ ├── TitleWidget.java │ │ │ │ ├── Valuable.java │ │ │ │ ├── Widget.java │ │ │ │ ├── WidgetContainer.java │ │ │ │ └── WidgetProperty.java │ │ │ ├── migration │ │ │ └── MigrationConfig.java │ │ │ └── studio │ │ │ └── workspace │ │ │ ├── RestClient.java │ │ │ └── StudioHealthCheck.java │ └── resources │ │ ├── application-studio.properties │ │ ├── application.properties │ │ ├── banner.txt │ │ ├── i18n │ │ ├── lang-template-es-ES.po │ │ ├── lang-template-fr-FR.po │ │ ├── lang-template-ja-JP.po │ │ └── lang-template-pt-BR.po │ │ └── logback.xml │ └── test │ ├── java │ └── org │ │ └── bonitasoft │ │ └── web │ │ └── designer │ │ ├── builder │ │ └── BusinessObjectBuilder.java │ │ ├── config │ │ └── UiDesignerPropertiesTest.java │ │ ├── controller │ │ ├── ErrorMessageTest.java │ │ ├── ExportControllerTest.java │ │ ├── FakeResource.java │ │ ├── FakeService.java │ │ ├── FragmentResourceTest.java │ │ ├── ImportControllerTest.java │ │ ├── MigrationResourceFragmentTest.java │ │ ├── MigrationResourceTest.java │ │ ├── PageResourceTest.java │ │ ├── PreviewControllerTest.java │ │ ├── ResourceControllerAdviceTest.java │ │ ├── UiGenerationResourceTest.java │ │ ├── WidgetResourceTest.java │ │ └── utils │ │ │ ├── HttpFileTest.java │ │ │ ├── MimeTypeTest.java │ │ │ └── UnZipperTest.java │ │ ├── generator │ │ ├── FormatterTest.java │ │ ├── assertions │ │ │ ├── AbstractParametrizedWidgetAssert.java │ │ │ ├── ButtonWidgetAssert.java │ │ │ ├── DatePickerWidgetAssert.java │ │ │ ├── DateTimePickerWidgetAssert.java │ │ │ ├── InputWidgetAssert.java │ │ │ └── TitleWidgetAssert.java │ │ ├── mapping │ │ │ ├── ContractInputToWidgetMapperTest.java │ │ │ ├── ContractInputVisitorImplTest.java │ │ │ ├── ContractToContainerMapperTest.java │ │ │ ├── ContractToPageMapperTest.java │ │ │ ├── DimensionFactoryTest.java │ │ │ ├── FormInputVisitorTest.java │ │ │ ├── FormOutputVisitorTest.java │ │ │ ├── data │ │ │ │ ├── BusinessQueryDataFactoryTest.java │ │ │ │ ├── BusinessQueryDataTest.java │ │ │ │ └── SubmitErrorsListDataTest.java │ │ │ └── dataManagement │ │ │ │ ├── BusinessDataToWidgetMapperTest.java │ │ │ │ ├── BusinessObjectVisitorImplTest.java │ │ │ │ └── databind │ │ │ │ └── BusinessObjectDeserializerTest.java │ │ └── parametrizedWidget │ │ │ ├── AttributeInputTypeResolverTest.java │ │ │ ├── FileUploadWidgetTest.java │ │ │ ├── InputWidgetTest.java │ │ │ ├── ParametrizedDataManagementWidgetFactoryTest.java │ │ │ ├── ParametrizedWidgetFactoryTest.java │ │ │ ├── TextWidgetTest.java │ │ │ └── TitleWidgetTest.java │ │ ├── studio │ │ └── workspace │ │ │ ├── RestClientTest.java │ │ │ └── StudioHealthCheckTest.java │ │ └── utils │ │ ├── TestWebMvcConfigurationSupport.java │ │ └── UIDesignerMockMvcBuilder.java │ └── resources │ ├── config │ └── application.properties │ ├── generator │ └── resource.js │ ├── logback-test.xml │ ├── org │ └── bonitasoft │ │ └── web │ │ └── designer │ │ └── controller │ │ └── utils │ │ ├── azipFile.zip │ │ └── notAzipFile.txt │ ├── page-with-variables │ └── page-with-variables.json │ ├── tmpWorkspace │ └── pages │ │ └── ma-page │ │ └── js │ │ └── widgets-abc123.min.js │ └── workspace │ ├── fragments │ └── person │ │ ├── person.js │ │ └── person.json │ ├── pages │ └── ma-page │ │ ├── assets │ │ └── js │ │ │ └── timeshift.js │ │ └── ma-page.json │ └── widgets │ └── pbLabel │ ├── assets │ └── css │ │ └── my-css-1.0.0.css │ ├── pbLabel.js │ └── pbLabel.json ├── crowdin.yml ├── frontend ├── .editorconfig ├── .eslintrc ├── README.md ├── app │ ├── css │ │ └── icons.css │ ├── favicon.ico │ ├── img │ │ ├── container.svg │ │ ├── customwidgets.svg │ │ ├── datamodel.svg │ │ ├── designer.svg │ │ ├── expression.svg │ │ ├── formContainer.svg │ │ ├── forms.svg │ │ ├── fragments.svg │ │ ├── graph.svg │ │ ├── layouts.svg │ │ ├── logo.svg │ │ ├── pages.svg │ │ ├── switchWidgetFeature.jpg │ │ ├── tabsContainer.svg │ │ └── widgets.svg │ ├── index.html │ ├── js │ │ ├── _.module.js │ │ ├── app.config.js │ │ ├── assets │ │ │ ├── _.module.js │ │ │ ├── asset-edit-popup.html │ │ │ ├── asset-edit-popup.js │ │ │ ├── asset-popup.controller.js │ │ │ ├── asset-popup.html │ │ │ ├── asset-preview-popup.controller.js │ │ │ ├── asset-preview-popup.html │ │ │ ├── assets-type.filter.js │ │ │ ├── assets.controller.js │ │ │ ├── assets.filter.js │ │ │ ├── assets.less │ │ │ ├── assets.service.js │ │ │ ├── error-management.service.js │ │ │ ├── generic-asset-form.html │ │ │ ├── help-popup.html │ │ │ ├── l10n-asset-form.html │ │ │ ├── malformed-json-error-message.html │ │ │ ├── page-assets.html │ │ │ ├── table │ │ │ │ ├── asset-section.controller.js │ │ │ │ ├── asset-section.directive.js │ │ │ │ └── asset-section.html │ │ │ └── widget-assets.html │ │ ├── common │ │ │ ├── directives │ │ │ │ ├── _.module.js │ │ │ │ ├── ace-editor.directive.js │ │ │ │ ├── alert-content.directive.js │ │ │ │ ├── alerts.directive.js │ │ │ │ ├── alerts.html │ │ │ │ ├── artifact-name-validation.html │ │ │ │ ├── artifact-name-validation.js │ │ │ │ ├── autofocus.directive.js │ │ │ │ ├── bo-enter.directive.js │ │ │ │ ├── compile-template.directive.js │ │ │ │ ├── confirm-on-exit.js │ │ │ │ ├── expand-modal.directive.js │ │ │ │ ├── expand-modal.tpl.html │ │ │ │ ├── file-download.js │ │ │ │ ├── file-input-change.directive.js │ │ │ │ ├── identicon.directive.js │ │ │ │ ├── include-replace.js │ │ │ │ ├── save-indicator │ │ │ │ │ ├── save-indicator.directive.js │ │ │ │ │ ├── save-indicator.html │ │ │ │ │ └── save-indicator.less │ │ │ │ ├── search │ │ │ │ │ ├── search.directive.js │ │ │ │ │ ├── search.html │ │ │ │ │ └── search.less │ │ │ │ └── splitter │ │ │ │ │ ├── splitter.directive.js │ │ │ │ │ ├── splitter.html │ │ │ │ │ └── splitter.less │ │ │ ├── filters │ │ │ │ ├── _.module.js │ │ │ │ └── mustachify.filter.js │ │ │ ├── repositories │ │ │ │ ├── _.module.js │ │ │ │ ├── asset-repository.service.js │ │ │ │ ├── configuration.service.js │ │ │ │ ├── data-management.service.js │ │ │ │ ├── fragment-repository.service.js │ │ │ │ ├── import-repository.service.js │ │ │ │ ├── page-repository.service.js │ │ │ │ ├── repositories.service.js │ │ │ │ ├── repository.service.js │ │ │ │ ├── ui-generation.service.js │ │ │ │ └── widget-repository.service.js │ │ │ └── services │ │ │ │ ├── _.module.js │ │ │ │ ├── ace-data-completer.service.js │ │ │ │ ├── alerts.service.js │ │ │ │ ├── arrays.service.js │ │ │ │ ├── clock.service.js │ │ │ │ ├── error-interceptor.service.js │ │ │ │ ├── history.service.js │ │ │ │ ├── key-binding.service.js │ │ │ │ ├── migration.service.js │ │ │ │ ├── resolutions.service.js │ │ │ │ └── utils.service.js │ │ ├── confirm-delete │ │ │ ├── _module.js │ │ │ ├── confirm-delete-popup.html │ │ │ └── confirm-delete.controller.js │ │ ├── confirm-popup │ │ │ ├── _module.js │ │ │ ├── confirm-migrate-popup.html │ │ │ ├── confirm-popup-not-again.controller.js │ │ │ └── confirm-popup.controller.js │ │ ├── custom-widget │ │ │ ├── _.module.js │ │ │ ├── create-property.html │ │ │ ├── custom-widget-editor.controller.js │ │ │ ├── custom-widget-editor.html │ │ │ ├── help-l10n.directive.js │ │ │ ├── help-l10n.html │ │ │ ├── help-popup.html │ │ │ ├── property-editor-popup.controller.js │ │ │ ├── save-as-popup.controller.js │ │ │ └── save-as-popup.html │ │ ├── editor │ │ │ ├── _.module.js │ │ │ ├── bottom-panel │ │ │ │ ├── _.module.js │ │ │ │ ├── bottom-panel.directive.js │ │ │ │ ├── bottom-panel.html │ │ │ │ ├── bottom-panel.less │ │ │ │ ├── data-panel │ │ │ │ │ ├── _.module.js │ │ │ │ │ ├── api-examples.service.js │ │ │ │ │ ├── business-data-update.service.js │ │ │ │ │ ├── data-management-filter-popup.controller.js │ │ │ │ │ ├── data-management-filter-popup.html │ │ │ │ │ ├── data-popup.controller.js │ │ │ │ │ ├── data-popup.html │ │ │ │ │ ├── data-type.service.js │ │ │ │ │ ├── data.controller.js │ │ │ │ │ ├── data.html │ │ │ │ │ ├── data.less │ │ │ │ │ ├── exposable-data.directive.js │ │ │ │ │ ├── exposable-data.html │ │ │ │ │ ├── help-popup.html │ │ │ │ │ ├── query-selector-edition.html │ │ │ │ │ ├── query-selector.html │ │ │ │ │ └── valid-json.directive.js │ │ │ │ ├── tab-factory.service.js │ │ │ │ └── web-resources-panel │ │ │ │ │ ├── _module.js │ │ │ │ │ ├── bonitaWebResource.service.js │ │ │ │ │ ├── help-popup.html │ │ │ │ │ ├── web-resource-popup.html │ │ │ │ │ ├── webResources-panel.controller.js │ │ │ │ │ └── webResources-panel.html │ │ │ ├── common │ │ │ │ ├── _.module.js │ │ │ │ ├── artifact-naming-validator.service.js │ │ │ │ ├── components.service.js │ │ │ │ └── properties.service.js │ │ │ ├── editor.config.js │ │ │ ├── editor.controller.js │ │ │ ├── editor.html │ │ │ ├── editor.less │ │ │ ├── editor.service.js │ │ │ ├── header │ │ │ │ ├── _.module.js │ │ │ │ ├── convert-popup.controller.js │ │ │ │ ├── convert-popup.html │ │ │ │ ├── export-popup.controller.js │ │ │ │ ├── export-popup.html │ │ │ │ ├── header.controller.js │ │ │ │ ├── header.html │ │ │ │ ├── header.less │ │ │ │ ├── help │ │ │ │ │ ├── _.module.js │ │ │ │ │ ├── help-migration.directive.js │ │ │ │ │ ├── help-migration.html │ │ │ │ │ ├── help-popup.html │ │ │ │ │ └── open-help.directive.js │ │ │ │ ├── metadata-popup.controller.js │ │ │ │ ├── metadata-popup.html │ │ │ │ ├── migrationReport │ │ │ │ │ ├── migration-report-popup.controller.html │ │ │ │ │ └── migration-report-popup.controller.js │ │ │ │ ├── save-as-popup.controller.js │ │ │ │ └── save-as-popup.html │ │ │ ├── palette │ │ │ │ ├── _.module.js │ │ │ │ ├── data-model-help-popup.html │ │ │ │ ├── editor-palette-directive.js │ │ │ │ ├── editor-palette-filters.js │ │ │ │ ├── editor-palette.html │ │ │ │ ├── palette-model.directive.js │ │ │ │ ├── palette-model.html │ │ │ │ ├── palette-widget.directive.js │ │ │ │ ├── palette-widget.html │ │ │ │ └── palette.service.js │ │ │ ├── properties-panel │ │ │ │ ├── _.module.js │ │ │ │ ├── bond │ │ │ │ │ ├── constant.html │ │ │ │ │ ├── expression.html │ │ │ │ │ ├── interpolation.html │ │ │ │ │ └── variable.html │ │ │ │ ├── common-properties-template.html │ │ │ │ ├── component-properties-template.html │ │ │ │ ├── container-properties-template.html │ │ │ │ ├── container-repeat-content-tip.html │ │ │ │ ├── field │ │ │ │ │ ├── boolean.html │ │ │ │ │ ├── choice-grouped.html │ │ │ │ │ ├── choice.html │ │ │ │ │ ├── collection.html │ │ │ │ │ ├── float.html │ │ │ │ │ ├── html.html │ │ │ │ │ ├── integer.html │ │ │ │ │ └── text.html │ │ │ │ ├── fragment │ │ │ │ │ ├── fragment-data-binding-field.controller.js │ │ │ │ │ ├── fragment-data-binding-field.directive.js │ │ │ │ │ ├── fragment-data-binding-field.html │ │ │ │ │ ├── fragment-properties-template.html │ │ │ │ │ ├── fragment-save-popup.controller.js │ │ │ │ │ └── fragment-save-popup.html │ │ │ │ ├── help │ │ │ │ │ ├── bidirectional-bond-help.html │ │ │ │ │ ├── constant-bond-help.html │ │ │ │ │ ├── description-bond-help.html │ │ │ │ │ ├── dynamic-bond-help.html │ │ │ │ │ ├── interpolation-bond-help.html │ │ │ │ │ └── property-bond-help.html │ │ │ │ ├── modal-container-properties-template.html │ │ │ │ ├── properties-panel-action-menu-template.html │ │ │ │ ├── properties-panel.html │ │ │ │ ├── properties-panel.less │ │ │ │ ├── property-field.controller.js │ │ │ │ ├── property-field.directive.js │ │ │ │ ├── property-field.html │ │ │ │ ├── property-panel-action-menu.controller.js │ │ │ │ ├── property-typeahead.directive.js │ │ │ │ ├── property-typeahead.html │ │ │ │ ├── tab-container-properties-template.html │ │ │ │ └── widgetHelpTemplate.html │ │ │ └── whiteboard │ │ │ │ ├── _.module.js │ │ │ │ ├── component-highlighter.directive.js │ │ │ │ ├── component-id.service.js │ │ │ │ ├── component-mover.controller.js │ │ │ │ ├── component-mover.directive.js │ │ │ │ ├── component-mover.html │ │ │ │ ├── component-scope-builder.service.js │ │ │ │ ├── component-template.html │ │ │ │ ├── component-utils.service.js │ │ │ │ ├── component.directive.js │ │ │ │ ├── component.html │ │ │ │ ├── container-template.html │ │ │ │ ├── container.controller.js │ │ │ │ ├── container.directive.js │ │ │ │ ├── container.html │ │ │ │ ├── data.filter.js │ │ │ │ ├── drop-zone.directive.js │ │ │ │ ├── form-container-template.html │ │ │ │ ├── form-container.directive.js │ │ │ │ ├── form-container.html │ │ │ │ ├── fragment-preview │ │ │ │ ├── component-preview.directive.js │ │ │ │ ├── container-preview.directive.js │ │ │ │ ├── container-preview.html │ │ │ │ ├── form-container-preview.directive.js │ │ │ │ ├── form-container-preview.html │ │ │ │ ├── modal-container-preview.directive.js │ │ │ │ ├── modal-container-preview.html │ │ │ │ ├── tabs-container-preview.directive.js │ │ │ │ └── tabs-container-preview.html │ │ │ │ ├── fragment-template.html │ │ │ │ ├── fragment.directive.js │ │ │ │ ├── fragment.html │ │ │ │ ├── fragment.service.js │ │ │ │ ├── modal-container-template.html │ │ │ │ ├── modal-container.directive.js │ │ │ │ ├── modal-container.html │ │ │ │ ├── page-element-factory.service.js │ │ │ │ ├── switchComponent │ │ │ │ ├── assets │ │ │ │ │ └── bo-switch-config.1.0.1.es5.min.js │ │ │ │ ├── not-supported-browser-popup.html │ │ │ │ ├── switch-component-popup.controller.js │ │ │ │ └── switch-component-popup.html │ │ │ │ ├── tabs-container-template.html │ │ │ │ ├── tabs-container.controller.js │ │ │ │ ├── tabs-container.directive.js │ │ │ │ ├── tabs-container.html │ │ │ │ ├── uiTranslate.filter.js │ │ │ │ ├── whiteboard-component-wrapper.service.js │ │ │ │ └── whiteboard.service.js │ │ ├── home │ │ │ ├── _.module.js │ │ │ ├── artifact-factory.service.js │ │ │ ├── artifact-list │ │ │ │ ├── alert-deletion-notpossible-popup.html │ │ │ │ ├── artifact-list.directive.js │ │ │ │ ├── artifact-list.html │ │ │ │ ├── artifact-list.less │ │ │ │ ├── artifact-tooltip-template.html │ │ │ │ ├── confirm-deletion-popup.html │ │ │ │ ├── deletion-popup.controller.js │ │ │ │ ├── favorite-button.directive.js │ │ │ │ └── favorite-button.html │ │ │ ├── artifact-store.service.js │ │ │ ├── create │ │ │ │ ├── create-popover.html │ │ │ │ ├── create.less │ │ │ │ ├── home-create.directive.js │ │ │ │ └── home-create.html │ │ │ ├── help-popup.controller.js │ │ │ ├── help-popup.html │ │ │ ├── home.controller.js │ │ │ ├── home.html │ │ │ ├── home.less │ │ │ └── import │ │ │ │ ├── home-import.directive.js │ │ │ │ ├── home-import.html │ │ │ │ ├── import-error-message.html │ │ │ │ ├── import-error-messages.service.js │ │ │ │ ├── import-popover.html │ │ │ │ ├── import-report-item-list.directive.js │ │ │ │ ├── import-report-item-list.html │ │ │ │ ├── import-report-popup.controller.js │ │ │ │ ├── import-report-popup.html │ │ │ │ ├── import-success-message.controller.js │ │ │ │ ├── import-success-message.html │ │ │ │ ├── import.less │ │ │ │ ├── import.module.js │ │ │ │ └── import.service.js │ │ ├── i18n │ │ │ ├── _.module.js │ │ │ ├── i18n.service.js │ │ │ ├── language-picker.directive.js │ │ │ ├── language-picker.html │ │ │ └── preview-localized-iframe.directive.js │ │ ├── navbar-toggle │ │ │ ├── navbar-toggle.directive.js │ │ │ ├── navbar-toggle.html │ │ │ └── navbar-toggle.less │ │ ├── preview │ │ │ ├── _.module.js │ │ │ ├── app-selector │ │ │ │ ├── _.module.js │ │ │ │ ├── app-selector.directive.js │ │ │ │ ├── app-selector.html │ │ │ │ └── app-selector.service.js │ │ │ ├── open-preview.directive.js │ │ │ ├── open-preview.html │ │ │ ├── preview.controller.js │ │ │ ├── preview.html │ │ │ ├── preview.less │ │ │ └── web-socket.service.js │ │ ├── resolutions │ │ │ ├── _.module.js │ │ │ ├── resolutions-bar.directive.js │ │ │ └── resolutions-bar.html │ │ └── routes.js │ └── less │ │ ├── alerts.less │ │ ├── animations.less │ │ ├── drop-row.less │ │ ├── drop-zone.less │ │ ├── file-upload.less │ │ ├── forms.less │ │ ├── fragment.less │ │ ├── help.less │ │ ├── main.less │ │ ├── modal.less │ │ ├── palette.less │ │ ├── panelheader.less │ │ ├── popover.less │ │ ├── sidebar.less │ │ ├── theme-colour.less │ │ ├── tooltip.less │ │ ├── variables.less │ │ ├── widget-editor.less │ │ ├── widget.less │ │ └── workspace.less ├── assembly.xml ├── gulp │ ├── assets.js │ ├── build.js │ ├── bundle.js │ ├── config.js │ ├── dev.js │ ├── e2e.js │ ├── index.js │ ├── serve.js │ └── test.js ├── gulpfile.js ├── licences │ └── fonts │ │ └── OFL.txt ├── package.json ├── pom.xml ├── test │ ├── e2e │ │ ├── config │ │ │ ├── _.module.js │ │ │ ├── e2e.config.js │ │ │ ├── e2ehelper.service.js │ │ │ ├── fixtures.assets.js │ │ │ ├── fixtures.fragments.js │ │ │ ├── fixtures.pages.js │ │ │ └── fixtures.widgets.js │ │ ├── pages │ │ │ ├── asset-panel.page.js │ │ │ ├── data-panel.page.js │ │ │ ├── edit-local-asset-popup.page.js │ │ │ ├── editor.page.js │ │ │ ├── home.page.js │ │ │ ├── preview.page.js │ │ │ ├── utils.js │ │ │ └── widget-editor.page.js │ │ ├── polyfill │ │ │ └── dnd.js │ │ ├── protractor.conf.js │ │ └── spec │ │ │ ├── asset.spec.js │ │ │ ├── confirm-on-exit.spec.js │ │ │ ├── custom-widget-editor.spec.js │ │ │ ├── custom-widgets.spec.js │ │ │ ├── data.spec.js │ │ │ ├── editor-menu.spec.js │ │ │ ├── editor.spec.js │ │ │ ├── fragments.spec.js │ │ │ ├── home.spec.js │ │ │ ├── internationalisation.spec.js │ │ │ ├── move-components.spec.js │ │ │ ├── move-containers.spec.js │ │ │ ├── move-form-container.js │ │ │ ├── move-fragments.spec.js │ │ │ ├── move-rows.spec.js │ │ │ ├── move-tab-containers.spec.js │ │ │ ├── preview.spec.js │ │ │ ├── properties-panel-action-menu.spec.js │ │ │ ├── resources │ │ │ ├── karma.png │ │ │ ├── localization.json │ │ │ ├── newVacation-localization.json │ │ │ └── protractor.png │ │ │ └── tabs.spec.js │ ├── karma.conf.js │ └── unit │ │ ├── app.run.spec.js │ │ ├── assets │ │ ├── asset-edit-popup.controller.spec.js │ │ ├── asset-popup.controller.spec.js │ │ ├── asset-preview-popup.controller.spec.js │ │ ├── assets-type.filter.spec.js │ │ ├── assets.controller.spec.js │ │ ├── assets.filter.spec.js │ │ ├── assets.service.spec.js │ │ ├── error-management.service.spec.js │ │ └── table │ │ │ └── asset-section.controller.spec.js │ │ ├── common │ │ ├── directives │ │ │ ├── ace-editor.directive.spec.js │ │ │ ├── alert-content.directive.spec.js │ │ │ ├── alerts.directive.spec.js │ │ │ ├── artifact-name-validation.spec.js │ │ │ ├── autofocus.directive.spec.js │ │ │ ├── compile-template.directive.spec.js │ │ │ ├── expand-modal.directive.spec.js │ │ │ ├── file-download.spec.js │ │ │ ├── identicon.directive.spec.js │ │ │ ├── include-replace.directive.spec.js │ │ │ ├── save-indicator │ │ │ │ └── save-indicator.directive.spec.js │ │ │ └── search │ │ │ │ └── search.directive.spec.js │ │ ├── filters │ │ │ └── mustachify.filter.spec.js │ │ ├── repositories │ │ │ ├── asset-repository.service.spec.js │ │ │ ├── data-management.service.specs.js │ │ │ ├── fragment-repository.service.spec.js │ │ │ ├── import-repository.service.spec.js │ │ │ ├── page-repository.service.spec.js │ │ │ ├── repositories.service.spec.js │ │ │ └── widget-repository.service.spec.js │ │ └── services │ │ │ ├── ace-data-completer.service.spec.js │ │ │ ├── alerts.service.spec.js │ │ │ ├── arrays.service.spec.js │ │ │ ├── browser-history.service.spec.js │ │ │ ├── error-interceptor.service.spec.js │ │ │ ├── migration.service.spec.js │ │ │ ├── resolutions.service.spec.js │ │ │ └── utils.service.spec.js │ │ ├── custom-widget │ │ ├── custom-widget-editor.controller.spec.js │ │ └── property-editor-popup.controller.spec.js │ │ ├── editor │ │ ├── bottom-panel │ │ │ ├── bottom-panel.directive.spec.js │ │ │ ├── data-panel │ │ │ │ ├── data-management-filter-popup.controller.spec.js │ │ │ │ ├── data-popup.controller.spec.js │ │ │ │ ├── data-type.service.spec.js │ │ │ │ ├── data.controller.spec.js │ │ │ │ ├── exposable-data.directive.spec.js │ │ │ │ └── valid-json.directive.spec.js │ │ │ ├── tab-factory.service.spec.js │ │ │ └── web-resources-panel │ │ │ │ ├── web-resources-panel.spec.js │ │ │ │ └── web-resources-popup.spec.js │ │ ├── common │ │ │ ├── artifact-naming-validator.service.spec.js │ │ │ ├── component.service.spec.js │ │ │ └── properties.service.spec.js │ │ ├── editor.controller.spec.js │ │ ├── editor.service.spec.js │ │ ├── menu-bar │ │ │ ├── header.controller.spec.js │ │ │ └── open-help.directive.spec.js │ │ ├── palette │ │ │ ├── editor-palette-filters.spec.js │ │ │ ├── editor-palette.spec.js │ │ │ ├── palette-widget.directive.spec.js │ │ │ └── palette.service.spec.js │ │ ├── properties-panel │ │ │ ├── fragment │ │ │ │ ├── fragment-data-binding-field.controller.spec.js │ │ │ │ ├── fragment-data-binding-field.directive.spec.js │ │ │ │ ├── fragment-save-popup.controller.spec.js │ │ │ │ └── property-panel-action-menu.controller.spec.js │ │ │ ├── property-field.controller.spec.js │ │ │ ├── property-field.directive.spec.js │ │ │ └── property-typeahead.directive.spec.js │ │ └── whiteboard │ │ │ ├── component-id.service.spec.js │ │ │ ├── component-mover.controller.spec.js │ │ │ ├── component-mover.directive.spec.js │ │ │ ├── component-scope-builder.service.spec.js │ │ │ ├── component-utils.service.spec.js │ │ │ ├── component.directive.spec.js │ │ │ ├── container.controller.spec.js │ │ │ ├── container.directive.spec.js │ │ │ ├── data.filter.spec.js │ │ │ ├── drop-zone.directive.spec.js │ │ │ ├── form-container.directive.spec.js │ │ │ ├── fragment.directive.spec.js │ │ │ ├── fragment.service.spec.js │ │ │ ├── fragmentPreview │ │ │ ├── component-preview.directive.spec.js │ │ │ ├── container-preview.directive.spec.js │ │ │ └── tabs-container-preview.directive.spec.js │ │ │ ├── input-with-label.spec.js │ │ │ ├── modal-container.directive.spec.js │ │ │ ├── page-element-factory.service.spec.js │ │ │ ├── switchComponent │ │ │ ├── switch-component-popup.controller.spec.js │ │ │ ├── widgets-mock.js │ │ │ └── widgetsFrom-mock.js │ │ │ ├── tabs-container.controller.spec.js │ │ │ ├── tabs-container.directive.spec.js │ │ │ ├── whiteboard-component-wrapper.service.spec.js │ │ │ └── whiteboard.service.spec.js │ │ ├── home │ │ ├── artifact-list │ │ │ └── artifact-list.spec.js │ │ ├── artifact-store.service.spec.js │ │ ├── create │ │ │ └── home-create.directive.spec.js │ │ ├── deletion-popup.controller.spec.js │ │ ├── favorite-button.directive.spec.js │ │ ├── file-input-change.directive.spec.js │ │ ├── home.controller.spec.js │ │ └── import │ │ │ ├── home-import.directive.spec.js │ │ │ ├── import-error-messages.service.spec.js │ │ │ ├── import-report-item-list.directive.spec.js │ │ │ ├── import-report-popup.controller.spec.js │ │ │ ├── import-success-message.controller.spec.js │ │ │ ├── import-success-message.template.spec.js │ │ │ └── import.service.spec.js │ │ ├── i18n │ │ ├── i18n.service.spec.js │ │ ├── lang-select.directive.spec.js │ │ └── preview-iframe.directive.spec.js │ │ ├── preview │ │ ├── app-selector │ │ │ ├── app-selector.directive.spec.js │ │ │ └── app-selector.service.spec.js │ │ ├── open-preview.directive.spec.js │ │ └── preview.controller.spec.js │ │ ├── resolutions │ │ └── resolutions-bar.directive.spec.js │ │ ├── routes │ │ └── app.config.spec.js │ │ └── utils │ │ ├── builders │ │ ├── ContainerElementBuilder.js │ │ ├── FormContainerElementBuilder.js │ │ ├── TabContainerElementBuilder.js │ │ ├── TabsContainerElementBuilder.js │ │ └── WidgetElementBuilder.js │ │ ├── matchers.js │ │ ├── modal-container-structure.mock.js │ │ ├── modalInstance.mock.js │ │ ├── page.mock.js │ │ ├── tab-container-structure.mock.js │ │ └── web-socket.mock.js └── yarn.lock ├── img └── WysiwygUIDEditor.png ├── infrastructure ├── README.adoc ├── next-patch-version.sh └── update-version.sh ├── mvnw ├── mvnw.cmd ├── package.json ├── pom.xml ├── server.sh └── tests ├── README.md ├── gulpfile.js ├── package.json ├── pom.xml ├── protractor.conf.js ├── src └── test │ ├── fixtures │ ├── fragment-testImport.zip │ ├── greeeen.jpg │ ├── middleware │ │ ├── api-user.middleware.js │ │ ├── fileupload.middleware.js │ │ ├── server.js │ │ └── users.js │ ├── page-testImport.zip │ └── widget-testImport.zip │ ├── resources │ ├── fragments │ │ └── c8290d5b-166b-4fc0-a775-689480f7127a │ │ │ ├── c8290d5b-166b-4fc0-a775-689480f7127a.js │ │ │ └── c8290d5b-166b-4fc0-a775-689480f7127a.json │ ├── pages │ │ ├── autocomplete │ │ │ ├── assets │ │ │ │ └── css │ │ │ │ │ └── style.css │ │ │ └── autocomplete.json │ │ ├── buttonAddRemove │ │ │ └── buttonAddRemove.json │ │ ├── chart │ │ │ └── chart.json │ │ ├── checkbox │ │ │ └── checkbox.json │ │ ├── datatable │ │ │ └── datatable.json │ │ ├── datePicker │ │ │ └── datePicker.json │ │ ├── dateTimePicker │ │ │ ├── assets │ │ │ │ └── css │ │ │ │ │ └── style.css │ │ │ └── dateTimePicker.json │ │ ├── empty │ │ │ └── empty.json │ │ ├── fileviewer │ │ │ ├── assets │ │ │ │ ├── css │ │ │ │ │ └── style.css │ │ │ │ └── js │ │ │ │ │ └── widgets-c426271c01fa04d1d046004b69fe0442635f4816.min.js │ │ │ └── fileviewer.json │ │ ├── formContainer │ │ │ └── formContainer.json │ │ ├── image │ │ │ ├── assets │ │ │ │ └── img │ │ │ │ │ └── bonitaLogo.png │ │ │ └── image.json │ │ ├── input │ │ │ └── input.json │ │ ├── pageWithFragment │ │ │ └── pageWithFragment.json │ │ ├── repeatContainer │ │ │ └── repeatContainer.json │ │ ├── repeatInputWithValidation │ │ │ ├── assets │ │ │ │ ├── css │ │ │ │ │ └── style.css │ │ │ │ └── json │ │ │ │ │ └── localization.json │ │ │ └── repeatInputWithValidation.json │ │ ├── select │ │ │ └── select.json │ │ ├── table │ │ │ └── table.json │ │ ├── tabsContainer │ │ │ ├── assets │ │ │ │ └── css │ │ │ │ │ └── style.css │ │ │ └── tabsContainer.json │ │ ├── textarea │ │ │ └── textarea.json │ │ └── upload │ │ │ └── upload.json │ └── widgets │ │ └── customButton │ │ ├── customButton.js │ │ └── customButton.json │ └── spec │ ├── designer │ ├── editor.spec.js │ └── home.spec.js │ └── pages │ ├── autoComplete.spec.js │ ├── button.spec.js │ ├── chart.spec.js │ ├── checkbox.spec.js │ ├── datatable.spec.js │ ├── datePicker.spec.js │ ├── dateTimePicker.spec.js │ ├── fileviewer.spec.js │ ├── form-container.spec.js │ ├── fragment.spec.js │ ├── image.spec.js │ ├── input.spec.js │ ├── repeatContainer.spec.js │ ├── repeatInputWithValidation.spec.js │ ├── select.spec.js │ ├── table.spec.js │ ├── tabs-container.spec.js │ ├── textarea.spec.js │ └── upload.spec.js └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !backend/webapp/target/*.jar 3 | 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | 13 | [*.js] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [*.json] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [*.html] 22 | indent_style = space 23 | indent_size = 4 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | 9 | # Maintain dependencies for GitHub Actions 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | groups: 15 | production-dependencies: 16 | dependency-type: "production" 17 | development-dependencies: 18 | dependency-type: "development" 19 | 20 | # Maintain dependencies for maven 21 | - package-ecosystem: "maven" 22 | directory: "/" 23 | target-branch: dev 24 | schedule: 25 | interval: "daily" 26 | groups: 27 | production-dependencies: 28 | dependency-type: "production" 29 | development-dependencies: 30 | dependency-type: "development" -------------------------------------------------------------------------------- /.github/pr-labeler.yml: -------------------------------------------------------------------------------- 1 | enhancement: ['feat/*, chore/*'] 2 | defect: 'defect/*' 3 | bug: 'fix/*' 4 | github_actions: 'ci/*' 5 | ignore-for-release-notes: '*/update-translations' 6 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | exclude: 3 | labels: 4 | - dependencies 5 | - github_actions 6 | - ignore-for-release-notes 7 | categories: 8 | - title: New Features 🎉 9 | labels: 10 | - enhancement 11 | - title: Defects 🧐 12 | labels: 13 | - defect 14 | - title: Bug fixes 🛠 15 | labels: 16 | - bug 17 | - title: Technical updates 🔧 18 | labels: 19 | - dependencies 20 | - title: Other Changes 21 | labels: 22 | - "*" 23 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | - master 8 | - release-* 9 | - 1.* 10 | pull_request: 11 | branches: 12 | - dev 13 | - master 14 | - release-* 15 | - 1.* 16 | 17 | # Allows you to run this workflow manually from the Actions tab 18 | workflow_dispatch: 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-24.04 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | - name: Setup Java 27 | uses: actions/setup-java@v4 28 | with: 29 | java-version: 17 30 | distribution: temurin 31 | cache: maven 32 | 33 | - name: Build and tests 34 | run: ./mvnw -B clean verify -Pe2e,integration-test 35 | 36 | - name: Send message to Slack channel 37 | if: ${{ failure() && (github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/master') }} 38 | uses: bonitasoft/notify-slack-action@v1 39 | with: 40 | keeper-secret-config: ${{ secrets.KSM_CONFIG }} 41 | channel-id: ${{ vars.UID_SLACK_CHANNEL_ID }} 42 | message: ":x: Build on branch ${{github.ref}} failed in UI-Designer." 43 | -------------------------------------------------------------------------------- /.github/workflows/commit-message-check-format.yml: -------------------------------------------------------------------------------- 1 | name: Commit Message format check 2 | 3 | on: 4 | pull_request_target: 5 | # trigger when the PR title changes 6 | types: [ opened, edited, reopened ] 7 | 8 | jobs: 9 | pr-title: 10 | runs-on: ubuntu-24.04 11 | permissions: 12 | pull-requests: write # post comments when the PR title doesn't match the "Conventional Commits" rules 13 | steps: 14 | - name: Check Pull Request title 15 | uses: bonitasoft/actions/packages/pr-title-conventional-commits@v3 -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | pull_request: 4 | types: [opened] 5 | 6 | permissions: 7 | contents: read 8 | 9 | jobs: 10 | pr-labeler: 11 | permissions: 12 | contents: read 13 | pull-requests: write 14 | runs-on: ubuntu-24.04 15 | steps: 16 | - uses: TimonVS/pr-labeler-action@v5 17 | with: 18 | repo-token: ${{ secrets.GITHUB_TOKEN }} 19 | -------------------------------------------------------------------------------- /.github/workflows/merge-branches.yml: -------------------------------------------------------------------------------- 1 | name: Merge branches 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | from: 6 | description: Merge branch 7 | default: "master" 8 | required: true 9 | target: 10 | description: into 11 | default: "dev" 12 | required: true 13 | jobs: 14 | merge-branches: 15 | runs-on: ubuntu-24.04 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Merge ${{ github.event.inputs.from }} -> ${{ github.event.inputs.target }} 19 | uses: devmasx/merge-branch@1.4.0 20 | with: 21 | type: now 22 | from_branch: ${{ github.event.inputs.from }} 23 | target_branch: ${{ github.event.inputs.target }} 24 | github_token: ${{ secrets.BONITA_CI_PAT }} 25 | - name: Send message to Slack channel 26 | if: ${{ failure()}} 27 | uses: bonitasoft/notify-slack-action@v1 28 | with: 29 | keeper-secret-config: ${{ secrets.KSM_CONFIG }} 30 | channel-id: ${{ vars.UID_SLACK_CHANNEL_ID }} 31 | message: ":x: Merge ${{ github.event.inputs.from }} into ${{ github.event.inputs.target }} failed." 32 | -------------------------------------------------------------------------------- /.github/workflows/push_to_subtree.yml: -------------------------------------------------------------------------------- 1 | name: Push to community subtree 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | ref: 7 | type: string 8 | description: The git ref to push to subtree, can be a branch refs/heads/dev or a tag refs/tags/10.0.0 9 | ref_name: 10 | description: The git ref name to push to subtree, can be a branch dev or a tag 10.0.0 11 | type: string 12 | push: 13 | branches: 14 | - 'dev' 15 | 16 | jobs: 17 | push-subtree: 18 | runs-on: ubuntu-24.04 19 | steps: 20 | - uses: actions/checkout@v4 21 | with: 22 | token: ${{ secrets.BONITA_CI_PAT }} 23 | ref: ${{ github.event.inputs.ref || github.ref }} 24 | fetch-depth: 0 25 | 26 | - name: Push to subtree 27 | run: | 28 | git config remote.public.url >&- || git remote add public https://github.com/bonitasoft/bonita-ui-designer.git 29 | git push public ${{ github.event.inputs.ref_name || github.ref_name }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | .classpath 4 | .project 5 | .settings/ 6 | *.log 7 | logs/ 8 | 9 | node_modules/ 10 | target/ 11 | logs/ 12 | *.log 13 | .extract/ 14 | 15 | backend/webapp/node/ 16 | backend/webapp/src/main/webapp/i18n/*.json 17 | backend/webapp/src/test/resources/i18n/*.json 18 | 19 | frontend/node/ 20 | frontend/build/ 21 | frontend/Chrome_* 22 | frontend/ui-designer-frontend-bower-dependencies.json 23 | frontend/ui-designer-frontend-yarn-dependencies.json 24 | frontend/ui-designer-frontend-dependencies.json 25 | tests/build/ 26 | 27 | *-dependencies.json 28 | 29 | tests/build/ 30 | tests/node/ 31 | *.swp 32 | node/ 33 | 34 | -------------------------------------------------------------------------------- /.idea/jsLinters/eslint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | -------------------------------------------------------------------------------- /.run/Start Backend.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | -------------------------------------------------------------------------------- /.run/Start Frontend.run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.sdkmanrc: -------------------------------------------------------------------------------- 1 | # Enable auto-env through the sdkman_auto_env config 2 | # Add key=value pairs of SDKs to use below 3 | # activate this env via the command : sdk env 4 | #java=21.0.0.r11-grl 5 | java=11.0.11.hs-adpt 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.MD: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | We are pleased to receive any kind of contribution (issues, pull requests, suggestions ...). 4 | 5 | #### Commit message format 6 | 7 | Here is the expected commit format, please follow it, we rely on it to [automatically generate the changelog](https://github.com/lob/generate-changelog#usage): 8 | 9 | ``` 10 | type(category): description [flags] 11 | 12 | < commit description > 13 | ``` 14 | 15 | Where `type` is one of the following: 16 | 17 | - `breaking` 18 | - `build` 19 | - `ci` 20 | - `chore` 21 | - `docs` 22 | - `feat` 23 | - `fix` 24 | - `other` 25 | - `perf` 26 | - `refactor` 27 | - `revert` 28 | - `style` 29 | - `test` 30 | 31 | Where `flags` is an optional comma-separated list of one or more of the following (must be surrounded in square brackets): 32 | 33 | - `breaking`: alters `type` to be a breaking change 34 | 35 | And `category` can be anything of your choice. If you use a type not found in the list (but it still follows the same format of the message), it'll be grouped under `other`. 36 | 37 | #### Tests 38 | 39 | Ensure that your contribution is correctly tested: 40 | 41 | - Any update must be tested, at least through unit tests. 42 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # image to create a standalone ui-designer 2 | # to build, use `docker build -t bonita/ui-designer .` 3 | # to run on random port, use `docker run -p 8080 bonita/ui-designer` 4 | # to run on a fixed port, 8000 for example, use `docker run -p 8000:8080 bonita/ui-designer` 5 | FROM openjdk:11-jre-slim 6 | EXPOSE 8080 7 | WORKDIR /data 8 | ADD ./backend/webapp/target/ui-designer-1.20.0-SNAPSHOT.jar /data/ui-designer.jar 9 | CMD java -jar ui-designer.jar -Ddesigner.experimental=true 10 | -------------------------------------------------------------------------------- /backend/contract/src/main/java/org/bonitasoft/web/designer/model/contract/ContractInputContainer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.model.contract; 16 | 17 | import java.util.List; 18 | 19 | public interface ContractInputContainer { 20 | 21 | List getInput(); 22 | 23 | void addInput(ContractInput childInput); 24 | } 25 | -------------------------------------------------------------------------------- /backend/contract/src/main/java/org/bonitasoft/web/designer/model/contract/ContractInputVisitor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.model.contract; 16 | 17 | public interface ContractInputVisitor { 18 | 19 | void visit(NodeContractInput contractInput); 20 | 21 | void visit(LeafContractInput contractInput); 22 | } 23 | -------------------------------------------------------------------------------- /backend/contract/src/main/java/org/bonitasoft/web/designer/model/contract/EditMode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.model.contract; 16 | 17 | 18 | public enum EditMode { 19 | 20 | CREATE,EDIT 21 | 22 | } 23 | -------------------------------------------------------------------------------- /backend/copyright/copyright.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015 Bonitasoft S.A. 2 | Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 2.0 of the License, or 6 | (at your option) any later version. 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | You should have received a copy of the GNU General Public License 12 | along with this program. If not, see . 13 | -------------------------------------------------------------------------------- /backend/copyright/copyright.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /** 5 | * 6 | */ 7 | 8 | 9 | (\s|\t)*/\*.*$ 10 | .*\*/(\s|\t)*$ 11 | false 12 | true 13 | false 14 | 15 | 16 | -------------------------------------------------------------------------------- /backend/webapp/src/main/groovy/templates/dependencies.adoc.hbs: -------------------------------------------------------------------------------- 1 | = Bonita-ui-designer {{project.version}} dependencies for Bonita {{bonitaMinorVersion}} 2 | 3 | {{#if mavenDeps}} 4 | == UI-Designer Backend dependencies 5 | :description: List all backend dependencies used by Bonita-ui-designer 6 | 7 | |=== 8 | | Name |Version | Licenses 9 | 10 | {{#each mavenDeps}} 11 | | {{artifactId}} ({{groupId}}) | {{version}} | {{#each licenses}}{{url}}[{{name}}] {{/each}} 12 | 13 | {{/each}} 14 | |=== 15 | {{/if}} 16 | 17 | {{#if nodeDeps}} 18 | == UI-Designer frontend dependencies 19 | 20 | |=== 21 | | Name | Version | Licenses 22 | 23 | {{#each nodeDeps}} 24 | | {{name}} | {{version}} | {{#each licenses}}{{.}} {{/each}} 25 | {{/each}} 26 | |=== 27 | {{/if}} 28 | Note: The angular version 1.8.x is a "dependency" of angular-filter. In fact, this package does not use this dependency, 29 | so UI Designer does not embed angular 1.8.x 30 | 31 | {{#if pageDeps}} 32 | == Living application page dependencies 33 | 34 | |=== 35 | | Name | Version | Licenses 36 | 37 | {{#each pageDeps}} 38 | | {{name}} | {{version}} | {{#each licenses}}{{.}} {{/each}} 39 | {{/each}} 40 | |=== 41 | {{/if}} 42 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/controller/BonitaExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.controller; 16 | 17 | public interface BonitaExceptionHandler { 18 | } 19 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/Formatter.java: -------------------------------------------------------------------------------- 1 | package org.bonitasoft.web.designer.generator; 2 | 3 | import static java.lang.String.join; 4 | import static org.apache.commons.lang3.StringUtils.capitalize; 5 | 6 | public class Formatter { 7 | 8 | public static final String BY_UPPER_CASE_LETTER = "(?=\\p{Upper})"; 9 | public static final String TO_REPLACE = "((?<=[a-z])(?=[A-Z]))|((?<=[A-Z])(?=[A-Z][a-z]))"; 10 | 11 | public static String toDisplayName(String name) { 12 | String displayName = ""; 13 | if (name != null) { 14 | var words = name.split(BY_UPPER_CASE_LETTER); 15 | displayName = capitalize(join(" ", words)) 16 | .replaceAll(TO_REPLACE, " "); 17 | } 18 | return displayName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/mapping/FormScope.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.mapping; 16 | 17 | public enum FormScope { 18 | 19 | PROCESS, TASK, OVERVIEW 20 | 21 | } 22 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/mapping/strategy/PageCreationStrategy.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.mapping.strategy; 16 | 17 | import org.bonitasoft.web.designer.model.contract.Contract; 18 | import org.bonitasoft.web.designer.model.page.Page; 19 | 20 | public interface PageCreationStrategy { 21 | 22 | Page create(String name, Contract contract); 23 | } 24 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/Labeled.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | public interface Labeled { 18 | 19 | void setLabelWidth(int width); 20 | 21 | void setLabel(String label); 22 | } 23 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/ParametrizedWidget.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | public interface ParametrizedWidget extends ParameterConstants { 18 | 19 | String getWidgetId(); 20 | 21 | Integer getDimension(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/Requirable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | public interface Requirable { 18 | 19 | void setRequired(boolean required); 20 | } 21 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/Valuable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | public interface Valuable { 18 | 19 | void setValue(String value); 20 | } 21 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/Widget.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | 18 | import java.lang.annotation.Retention; 19 | import java.lang.annotation.RetentionPolicy; 20 | 21 | @Retention(RetentionPolicy.RUNTIME) 22 | public @interface Widget { 23 | } 24 | -------------------------------------------------------------------------------- /backend/webapp/src/main/java/org/bonitasoft/web/designer/generator/parametrizedWidget/WidgetProperty.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.generator.parametrizedWidget; 16 | 17 | import java.lang.annotation.Retention; 18 | import java.lang.annotation.RetentionPolicy; 19 | 20 | @Retention(RetentionPolicy.RUNTIME) 21 | public @interface WidgetProperty { 22 | } 23 | -------------------------------------------------------------------------------- /backend/webapp/src/main/resources/application-studio.properties: -------------------------------------------------------------------------------- 1 | # Default properties values for studio profile 2 | designer.experimental=false 3 | 4 | designer.workspace.pages.dir=${designer.workspace.path}/web_page 5 | designer.workspace.fragments.dir=${designer.workspace.path}/web_fragments 6 | designer.workspace.widgets.dir=${designer.workspace.path}/web_widgets 7 | -------------------------------------------------------------------------------- /backend/webapp/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ____ _ __ __ ______ ____ _ 3 | / __ )____ ____ (_) /_____ _ / / / / _/ / __ \___ _____(_)___ _____ ___ _____ 4 | / __ / __ \/ __ \/ / __/ __ `/ / / / // /_____/ / / / _ \/ ___/ / __ `/ __ \/ _ \/ ___/ 5 | / /_/ / /_/ / / / / / /_/ /_/ / / /_/ // /_____/ /_/ / __(__ ) / /_/ / / / / __/ / 6 | /_____/\____/_/ /_/_/\__/\__,_/ \____/___/ /_____/\___/____/_/\__, /_/ /_/\___/_/ 7 | /____/ 8 | 9 | =========================================================================================== 10 | ${designer.edition} edition v.${designer.version} 11 | Running in experimental mode: ${designer.experimental} 12 | =========================================================================================== 13 | -------------------------------------------------------------------------------- /backend/webapp/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /backend/webapp/src/test/java/org/bonitasoft/web/designer/controller/FakeService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.bonitasoft.web.designer.controller; 16 | 17 | public class FakeService { 18 | 19 | public void doSomething() throws Exception { 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/config/application.properties: -------------------------------------------------------------------------------- 1 | builddirectory=@project.build.directory@ 2 | 3 | designer.experimental=false 4 | 5 | designer.workspace-uid.path=${builddirectory}/test-env/workspace-uid 6 | designer.workspace.path=${builddirectory}/test-classes/workspace 7 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/generator/resource.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/backend/webapp/src/test/resources/generator/resource.js -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss} [%thread] %-5level %logger{26} - %msg%n%rEx 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/org/bonitasoft/web/designer/controller/utils/azipFile.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/backend/webapp/src/test/resources/org/bonitasoft/web/designer/controller/utils/azipFile.zip -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/org/bonitasoft/web/designer/controller/utils/notAzipFile.txt: -------------------------------------------------------------------------------- 1 | This is not a zip -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/page-with-variables/page-with-variables.json: -------------------------------------------------------------------------------- 1 | {"id":"page-with-variables","name":"page","type":"page","lastUpdate":1514989634397,"description":"Page generated with Bonita UI designer","rows":[],"variables":{"jsVar":{"type":"expression","displayValue":"var variable = \"hello\"; return variable;","exposed":false},"constantVar":{"type":"constant","displayValue":"constantVariableValue","exposed":false},"jsonVar":{"type":"json","displayValue":"{\"var1\":1, \"var2\":2, \"var3\":\"value3\"}","exposed":false}},"assets":[],"inactiveAssets":[],"webResources":[],"favorite":false,"status":{"compatible":true,"migration":true},"hasValidationError":false} 2 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/tmpWorkspace/pages/ma-page/js/widgets-abc123.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/backend/webapp/src/test/resources/tmpWorkspace/pages/ma-page/js/widgets-abc123.min.js -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/fragments/person/person.js: -------------------------------------------------------------------------------- 1 | angular.module('bonitasoft.ui.fragments') 2 | .directive('pbFragmentPerson', function() { 3 | return { 4 | template: '

Hello world

' 5 | }; 6 | }); 7 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/fragments/person/person.json: -------------------------------------------------------------------------------- 1 | { 2 | "modelVersion" : "2.0", 3 | "id" : "person", 4 | "name" : "person", 5 | "lastUpdate" : 1599557265845, 6 | "rows" : [ 7 | [ ] 8 | ], 9 | "assets" : [ ], 10 | "inactiveAssets" : [ ], 11 | "variables" : { }, 12 | "hasValidationError" : false, 13 | "type" : "fragment" 14 | } 15 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/pages/ma-page/assets/js/timeshift.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/backend/webapp/src/test/resources/workspace/pages/ma-page/assets/js/timeshift.js -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/pages/ma-page/ma-page.json: -------------------------------------------------------------------------------- 1 | { 2 | "designerVersion": "1.0.0", 3 | "id": "ma-page", 4 | "name": "maPage", 5 | "type": "page", 6 | "lastUpdate": 1436966572684, 7 | "rows": [[]], 8 | "assets": [], 9 | "data": {} 10 | } 11 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/widgets/pbLabel/assets/css/my-css-1.0.0.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/backend/webapp/src/test/resources/workspace/widgets/pbLabel/assets/css/my-css-1.0.0.css -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/widgets/pbLabel/pbLabel.js: -------------------------------------------------------------------------------- 1 | angular.module('bonitasoft.ui.widgets') 2 | .directive('pbLabel', function() { 3 | return { 4 | template: '
\n' 5 | }; 6 | }); 7 | -------------------------------------------------------------------------------- /backend/webapp/src/test/resources/workspace/widgets/pbLabel/pbLabel.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "pbLabel", 3 | "name": "Label", 4 | "template": "
", 5 | "properties": [ 6 | { 7 | "label": "Text", 8 | "name": "text", 9 | "type": "text", 10 | "defaultValue": "Static Label" 11 | }, 12 | { 13 | "label": "Alignment", 14 | "name": "alignment", 15 | "type": "choice", 16 | "defaultValue": "left", 17 | "choiceValues": ["left", "center", "right"] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Crowdin credentials 3 | # 4 | project_id_env: CROWDIN_PROJECT_ID 5 | api_token_env: CROWDIN_PERSONAL_TOKEN 6 | "base_path" : "." 7 | "base_url" : "https://api.crowdin.com" 8 | 9 | # 10 | # File structure in Crowdin 11 | # 12 | "preserve_hierarchy": true 13 | 14 | # 15 | # Files configuration 16 | # 17 | files: [ 18 | { 19 | # 20 | # Source files filter 21 | # 22 | "source" : "infrastructure/crowdin/build/lang-template.pot", 23 | 24 | # 25 | # The dest allows you to specify a file name in Crowdin 26 | # 27 | "dest" : "/ui-designer/lang-template.pot", 28 | 29 | # 30 | # Where translations will be placed 31 | # 32 | "translation" : "backend/webapp/src/main/resources/i18n/%file_name%-%two_letters_code%.po", 33 | 34 | "languages_mapping" : { 35 | "two_letters_code" : { 36 | "fr" : "fr-FR", 37 | "es-ES" : "es-ES", 38 | "ja" : "ja-JP", 39 | "pt-BR" : "pt-BR" 40 | } 41 | }, 42 | 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | charset = utf-8 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | indent_style = space 7 | 8 | [*.md] 9 | trim_trailing_whitespace = false 10 | 11 | [*.js] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.json] 16 | indent_style = space 17 | indent_size = 2 18 | 19 | [*.html] 20 | indent_style = space 21 | indent_size = 4 22 | -------------------------------------------------------------------------------- /frontend/app/css/icons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: '<%= fontName %>'; 3 | src: url('<%= fontPath %><%= fontName %>.eot'); /* IE9 Compatibility Modes */ 4 | src: url('<%= fontPath %><%= fontName %>.woff') format('woff'), /* Modern Browsers */ 5 | url('<%= fontPath %><%= fontName %>.ttf') format('truetype'); /* Safari, Android, iOS */ 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | .ui-icon { 11 | font-family: '<%= fontName %>'; 12 | speak: none; 13 | font-style: normal; 14 | font-weight: normal; 15 | font-variant: normal; 16 | text-transform: none; 17 | text-decoration: none; 18 | line-height: 1; 19 | vertical-align: middle; 20 | 21 | /* Better Font Rendering =========== */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | <% _.each(glyphs, function(glyph) { %> 27 | .ui-<%= glyph.fileName %>:before { 28 | content: "\<%= glyph.codePoint %>"; 29 | } 30 | <% }); %> 31 | -------------------------------------------------------------------------------- /frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/frontend/app/favicon.ico -------------------------------------------------------------------------------- /frontend/app/img/container.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/app/img/customwidgets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/app/img/datamodel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | background 5 | 6 | 7 | 8 | Layer 1 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/app/img/designer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/app/img/formContainer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/app/img/layouts.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /frontend/app/img/switchWidgetFeature.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/frontend/app/img/switchWidgetFeature.jpg -------------------------------------------------------------------------------- /frontend/app/img/tabsContainer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | UI Designer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /frontend/app/js/assets/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.assets', [ 20 | 'bonitasoft.designer.common.directives', 21 | 'bonitasoft.designer.common.repositories', 22 | 'bonitasoft.designer.confirm-delete', 23 | 'gettext', 24 | 'ui.bootstrap' 25 | ]); 26 | 27 | })(); 28 | -------------------------------------------------------------------------------- /frontend/app/js/assets/asset-preview-popup.html: -------------------------------------------------------------------------------- 1 |
2 | 5 | 10 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /frontend/app/js/assets/assets-type.filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | angular.module('bonitasoft.designer.assets').filter('assetType', function(assetsService) { 18 | 19 | 'use strict'; 20 | 21 | var types = assetsService.getTypes(); 22 | 23 | return function(key) { 24 | return types.reduce(function(acc, type) { 25 | return type.key === key ? type.value : acc; 26 | }, ''); 27 | }; 28 | }); 29 | 30 | })(); 31 | -------------------------------------------------------------------------------- /frontend/app/js/assets/error-management.service.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | 3 | class AsserErrorManagement { 4 | 5 | /* @ngInject */ 6 | constructor(alerts, $q) { 7 | this.alerts = alerts; 8 | this.$q = $q; 9 | } 10 | 11 | displayError(response) { 12 | if (response.type === 'MalformedJsonException') { 13 | this.alerts.addError({ 14 | contentUrl: 'js/assets/malformed-json-error-message.html', 15 | context: response 16 | }, 12000); 17 | } else { 18 | this.alerts.addError(response.message); 19 | } 20 | } 21 | 22 | hasError(response) { 23 | return response && response.type && response.message; 24 | } 25 | 26 | manageErrorsFromResponse(response) { 27 | if (this.hasError(response)) { 28 | this.displayError(response); 29 | return this.$q.reject(response); 30 | } else { 31 | return this.$q.when(response); 32 | } 33 | } 34 | } 35 | 36 | angular 37 | .module('bonitasoft.designer.assets') 38 | .service('assetErrorManagement', AsserErrorManagement); 39 | })(); 40 | -------------------------------------------------------------------------------- /frontend/app/js/assets/malformed-json-error-message.html: -------------------------------------------------------------------------------- 1 |

2 | Malformed json file 3 |

Asset has not been saved
4 |
Error at line {{ infos.location.line }}, column {{ infos.location.column }}
5 |

6 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.common.directives', [ 20 | 'ngSanitize', 21 | 'bonitasoft.designer.common.services', 22 | 'bonitasoft.designer.templates', 23 | 'ui.ace', 24 | 'ui.router', 25 | 'gettext', 26 | 'ui.bootstrap' 27 | ]); 28 | 29 | })(); 30 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/alerts.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |

{{ alert.title || alert.type | translate }}

5 |

6 |
7 |
8 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/artifact-name-validation.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/bo-enter.directive.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('bonitasoft.designer.common.directives') 3 | .directive('boEnter', function() { 4 | return function(scope, element, attrs) { 5 | element.bind('keydown keypress', function(event) { 6 | if (event.which === 13) { 7 | scope.$apply(function() { 8 | scope.$eval(attrs.boEnter); 9 | }); 10 | 11 | event.preventDefault(); 12 | } 13 | }); 14 | }; 15 | }); 16 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/expand-modal.tpl.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/include-replace.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | 16 | angular 17 | .module('bonitasoft.designer.common.directives') 18 | .directive('includeReplace', function() { 19 | return { 20 | require: 'ngInclude', 21 | link: function(scope, element) { 22 | element.replaceWith(element.children()); 23 | } 24 | }; 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/save-indicator/save-indicator.directive.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | 3 | class SaveIndicator { 4 | 5 | constructor($timeout, $scope) { 6 | this.$timeout = $timeout; 7 | 8 | $scope.$on('saved', () => this.displaySaveIndicator()); 9 | } 10 | 11 | displaySaveIndicator() { 12 | this.isVisible = true; 13 | this.$timeout(() => { 14 | this.isVisible = false; 15 | }, 1000); 16 | } 17 | } 18 | 19 | angular 20 | .module('bonitasoft.designer.common.directives') 21 | .directive('saveIndicator', () => ({ 22 | controller: SaveIndicator, 23 | controllerAs: 'indicator', 24 | templateUrl: 'js/common/directives/save-indicator/save-indicator.html' 25 | })); 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/save-indicator/save-indicator.html: -------------------------------------------------------------------------------- 1 | 2 |  Saved 3 | 4 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/save-indicator/save-indicator.less: -------------------------------------------------------------------------------- 1 | .SaveIndicator { 2 | opacity: 0; 3 | transition: opacity 0.5s linear; 4 | 5 | &.SaveIndicator--visible { 6 | opacity: 1; 7 | transition: none; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/search/search.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | class SearchController { 5 | 6 | clearValue() { 7 | this.value = ''; 8 | } 9 | 10 | isClearButtonVisible() { 11 | return (this.value || '').trim().length > 0; 12 | } 13 | } 14 | 15 | angular.module('bonitasoft.designer.common.directives').directive('search', () => ({ 16 | scope: { value: '=', placeholder: '@' }, 17 | bindToController: true, 18 | controllerAs: 'search', 19 | controller: SearchController, 20 | templateUrl: 'js/common/directives/search/search.html' 21 | })); 22 | })(); 23 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/search/search.html: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/search/search.less: -------------------------------------------------------------------------------- 1 | .Search { 2 | position: relative; 3 | } 4 | 5 | .Search-input { 6 | padding-left: 2em; 7 | padding-right: 2em; 8 | } 9 | 10 | .Search-icon { 11 | position: absolute; 12 | left: .7em; 13 | top: .7em; 14 | color: @gray-light; 15 | } 16 | 17 | .Search-clearButton { 18 | border: none; 19 | background: none; 20 | padding: 0; 21 | position: absolute; 22 | right: .7em; 23 | top: .7em; 24 | line-height: 1; 25 | } 26 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/splitter/splitter.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /frontend/app/js/common/directives/splitter/splitter.less: -------------------------------------------------------------------------------- 1 | .resizer{ 2 | width: 0.7rem; 3 | //SVG encode 4 | background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PSczMCc+PHBhdGggZD0nTTIgMCB2MzAgTTUgMCB2MzAgTTggMCB2MzAnIGZpbGw9J25vbmUnIHN0cm9rZT0nYmxhY2snLz48L3N2Zz4=") center center no-repeat; 5 | cursor: ew-resize; 6 | } 7 | -------------------------------------------------------------------------------- /frontend/app/js/common/filters/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.common.filters', []); 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /frontend/app/js/common/repositories/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.common.repositories', ['gettext']); 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /frontend/app/js/common/repositories/repositories.service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular 20 | .module('bonitasoft.designer.common.repositories') 21 | .factory('repositories', repositoriesService); 22 | 23 | function repositoriesService($injector) { 24 | return { 25 | get: (type) => $injector.get(`${type}Repo`) 26 | }; 27 | } 28 | })(); 29 | -------------------------------------------------------------------------------- /frontend/app/js/common/services/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.common.services', [ 20 | 'gettext', 21 | 'dn.sha', 22 | 'ngStorage' 23 | ]); 24 | 25 | })(); 26 | -------------------------------------------------------------------------------- /frontend/app/js/common/services/clock.service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | angular.module('bonitasoft.designer.common.services').factory('clock', function() { 16 | 17 | 'use strict'; 18 | 19 | return { 20 | /** 21 | * Returns the current time (Date.now()). Useful as it can be mocked in tests. 22 | */ 23 | now: Date.now 24 | }; 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/app/js/common/services/key-binding.service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 'use strict'; 17 | /** 18 | * This modules wrap the Mousetrap library (available in window.Mousetrap) 19 | * into an angular service 20 | */ 21 | angular.module('bonitasoft.designer.common.services').service('keyBindingService', function($window) { 22 | // key is library name that handle keyboard shortcuts 23 | return $window.Mousetrap; 24 | }); 25 | })(); 26 | -------------------------------------------------------------------------------- /frontend/app/js/confirm-delete/_module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.confirm-delete', [ 20 | 'gettext', 21 | 'ui.bootstrap' 22 | ]); 23 | 24 | })(); 25 | -------------------------------------------------------------------------------- /frontend/app/js/confirm-delete/confirm-delete-popup.html: -------------------------------------------------------------------------------- 1 |
2 | 5 | 8 | 12 |
13 | -------------------------------------------------------------------------------- /frontend/app/js/confirm-popup/_module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.confirm-popup', [ 20 | 'gettext', 21 | 'ui.bootstrap' 22 | ]); 23 | 24 | })(); 25 | -------------------------------------------------------------------------------- /frontend/app/js/custom-widget/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function () { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.custom-widget', [ 20 | 'bonitasoft.designer.editor.header.help', 21 | 'bonitasoft.designer.common.repositories', 22 | 'bonitasoft.designer.common.services', 23 | 'bonitasoft.designer.common.directives', 24 | 'ui.bootstrap', 25 | 'gettext', 26 | 'ui.router']); 27 | 28 | })(); 29 | -------------------------------------------------------------------------------- /frontend/app/js/custom-widget/help-l10n.directive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 'use strict'; 17 | 18 | angular 19 | .module('bonitasoft.designer.i18n') 20 | .directive('uidL10nHelpTab', () => ({ 21 | restrict: 'E', 22 | replace: true, 23 | templateUrl: 'js/custom-widget/help-l10n.html' 24 | })); 25 | }()); 26 | -------------------------------------------------------------------------------- /frontend/app/js/custom-widget/help-l10n.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Widgets use the l10n mechanism that loads the translated string during page start up.

5 | 6 |

Use the uiTranslate filter in custom widgets for dynamic content to be translated

7 |

Use the ui-translate directive in custom widgets for static content to be translated

8 | 9 |

For instance, with a custom link widget :

10 |
<div>
11 |     <a title="{{ properties.title | uiTranslate }}" ui-translate>Submit</a>
12 | </div>
13 |

The link text which is static is translated using the ui-translate directive. The link text title held inside the properties.title variable is translated using the uiTranslate filter.

14 | 15 |
16 | -------------------------------------------------------------------------------- /frontend/app/js/custom-widget/save-as-popup.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | let _$uibModalInstance; 6 | 7 | class saveWidgetAsPopUpCtrl { 8 | 9 | constructor($uibModalInstance, widget) { 10 | this.widget = widget; 11 | this.newName = widget.name.replace(/\s/g, ''); 12 | _$uibModalInstance = $uibModalInstance; 13 | } 14 | 15 | ok() { 16 | let widget = angular.copy(this.widget); // copy widget to avoid side effects in case of creation error 17 | widget.name = this.newName; 18 | _$uibModalInstance.close(widget); 19 | } 20 | } 21 | 22 | angular 23 | .module('bonitasoft.designer.custom-widget') 24 | .controller('saveWidgetAsPopUpCtrl', saveWidgetAsPopUpCtrl); 25 | 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/custom-widget/save-as-popup.html: -------------------------------------------------------------------------------- 1 | 4 |
5 | 18 | 22 |
23 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.bottom-panel', [ 20 | 'bonitasoft.designer.editor.bottom-panel.data-panel', 21 | 'bonitasoft.designer.webResources', 22 | 'bonitasoft.designer.templates', 23 | 'ui.router', 24 | 'gettext' 25 | ]); 26 | 27 | })(); 28 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/bottom-panel.html: -------------------------------------------------------------------------------- 1 |
3 |
4 | 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/data-panel/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.bottom-panel.data-panel', [ 20 | 'bonitasoft.designer.common.repositories', 21 | 'bonitasoft.designer.common.directives', 22 | 'bonitasoft.designer.confirm-delete', 23 | 'bonitasoft.designer.common.filters', 24 | 'gettext', 25 | 'ui.bootstrap' 26 | ]); 27 | 28 | })(); 29 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/data-panel/data.less: -------------------------------------------------------------------------------- 1 | @data-panel-header-height: 40px; 2 | 3 | .ace_editor.ace-editor--data { 4 | height: 250px; 5 | } 6 | 7 | .btn-data--help { 8 | margin-left: 1em; 9 | } 10 | 11 | .modal-xxl { 12 | .DataPanel--hideOnFullScreen { 13 | display: none; 14 | } 15 | } 16 | 17 | .DataPopPup-advanced-options { 18 | margin-top: 15px; 19 | } 20 | 21 | .DataPanel-expandableValue button { 22 | font-size: 1em; 23 | margin-bottom: 5px; 24 | } 25 | 26 | .DataPanel-expandableValue { 27 | position: relative; 28 | } 29 | 30 | .DataPanel-valueLabel { 31 | position: absolute; 32 | bottom: 0; 33 | left: 15px; 34 | } 35 | 36 | .VariablesTable-actions { 37 | width: 5em; 38 | } 39 | 40 | .VariablesTable-type { 41 | width: 20%; 42 | } 43 | 44 | .VariablesTable-name { 45 | width: 25%; 46 | } 47 | 48 | .VariablesTable-type--exposed { 49 | font-style: italic; 50 | color: gray; 51 | } 52 | 53 | .warning-business-data { 54 | i { 55 | margin-right: 15px; 56 | } 57 | display: flex; 58 | align-items: center; 59 | } 60 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/data-panel/query-selector-edition.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/data-panel/query-selector.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/bottom-panel/web-resources-panel/_module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2023 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.webResources', [ 20 | 'bonitasoft.designer.common.directives', 21 | 'bonitasoft.designer.common.repositories', 22 | 'bonitasoft.designer.confirm-delete', 23 | 'gettext', 24 | 'ui.bootstrap' 25 | ]); 26 | 27 | })(); 28 | -------------------------------------------------------------------------------- /frontend/app/js/editor/common/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.common', [ 20 | 'gettext' 21 | ]); 22 | 23 | })(); 24 | -------------------------------------------------------------------------------- /frontend/app/js/editor/editor.config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('bonitasoft.designer.editor') 7 | .run(function(whiteboardService, editorService) { 8 | 9 | whiteboardService.registerOnWidgetAddFunction(editorService.addWidgetAssetsToPage); 10 | whiteboardService.registerOnWidgetRemoveFunction(editorService.removeAssetsFromPage); 11 | 12 | }); 13 | 14 | })(); 15 | -------------------------------------------------------------------------------- /frontend/app/js/editor/header/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.header', [ 20 | 'bonitasoft.designer.editor.header.help', 21 | 'bonitasoft.designer.common.services', 22 | 'bonitasoft.designer.common.repositories', 23 | 'gettext', 24 | 'ui.bootstrap', 25 | 'ui.router', 26 | 'ngStorage', 27 | 'angular.filter' 28 | ]); 29 | 30 | })(); 31 | -------------------------------------------------------------------------------- /frontend/app/js/editor/header/export-popup.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | class ExportPopUpController { 6 | constructor($scope, $uibModalInstance, keyBindingService, $localStorage, page) { 7 | 'ngInject'; 8 | this.$uibModalInstance = $uibModalInstance; 9 | this.$localStorage = $localStorage; 10 | this.page = page; 11 | this.doNotShowAgain = false; 12 | 13 | // Pause keyBindingService to avoid move selection in background when user press arrow key 14 | keyBindingService.pause(); 15 | // Unpause keyBindingService when popup is destroy 16 | $scope.$on('$destroy', function() { 17 | keyBindingService.unpause(); 18 | }); 19 | } 20 | 21 | ok() { 22 | if (!this.$localStorage.bonitaUIDesigner) { 23 | this.$localStorage.bonitaUIDesigner = {}; 24 | } 25 | this.$localStorage.bonitaUIDesigner.doNotShowExportMessageAgain = this.doNotShowAgain; 26 | this.$uibModalInstance.close(); 27 | } 28 | } 29 | 30 | angular 31 | .module('bonitasoft.designer.editor.header') 32 | .controller('ExportPopUpController', ExportPopUpController); 33 | })(); 34 | -------------------------------------------------------------------------------- /frontend/app/js/editor/header/help/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2018 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.header.help', [ 20 | 'ui.bootstrap', 21 | 'ngStorage' 22 | ]); 23 | 24 | })(); 25 | -------------------------------------------------------------------------------- /frontend/app/js/editor/header/metadata-popup.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | class MetadataPopUpController { 6 | constructor($scope, $uibModalInstance, keyBindingService, page, resources) { 7 | 'ngInject'; 8 | this.$uibModalInstance = $uibModalInstance; 9 | this.page = page; 10 | this.displayName = page.displayName; 11 | this.description = page.description; 12 | this.resources = resources; 13 | 14 | // Pause keyBindingService to avoid move selection in background when user press arrow key 15 | keyBindingService.pause(); 16 | // Unpause keyBindingService when popup is destroy 17 | $scope.$on('$destroy', function() { 18 | keyBindingService.unpause(); 19 | }); 20 | } 21 | 22 | save(form) { 23 | if (!form.$invalid) { 24 | this.page.displayName = this.displayName; 25 | this.page.description = this.description; 26 | this.$uibModalInstance.close(); 27 | } 28 | } 29 | } 30 | 31 | angular 32 | .module('bonitasoft.designer.editor.header') 33 | .controller('MetadataPopUpController', MetadataPopUpController); 34 | })(); 35 | -------------------------------------------------------------------------------- /frontend/app/js/editor/header/migrationReport/migration-report-popup.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | class MigrationReportPopUpController { 6 | constructor($scope, $uibModalInstance, keyBindingService, artifact, migrationReport) { 7 | this.$uibModalInstance = $uibModalInstance; 8 | this.migrationReport = migrationReport; 9 | this.artifact = artifact; 10 | 11 | // Pause keyBindingService to avoid move selection in background when user press arrow key 12 | keyBindingService.pause(); 13 | // Unpause keyBindingService when popup is destroy 14 | $scope.$on('$destroy', function() { 15 | keyBindingService.unpause(); 16 | }); 17 | } 18 | } 19 | 20 | angular 21 | .module('bonitasoft.designer.editor.header') 22 | .controller('MigrationReportPopUpController', MigrationReportPopUpController); 23 | })(); 24 | -------------------------------------------------------------------------------- /frontend/app/js/editor/palette/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.palette', [ 20 | 'bonitasoft.designer.templates', 21 | 'bonitasoft.designer.editor.common', 22 | 'gettext', 23 | 'ui.bootstrap' 24 | ]); 25 | 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/editor/palette/editor-palette-filters.js: -------------------------------------------------------------------------------- 1 | angular.module('bonitasoft.designer.editor.palette') 2 | .filter('filterByComponentName', function() { 3 | return function(widgets, search) { 4 | // Filter the widgets that should not appear in the Palette 5 | if (!widgets) { 6 | return []; 7 | } 8 | widgets = widgets.filter(widget => { 9 | return !widget.component || widget.component && widget.component.id !== 'pbTabContainer'; 10 | }); 11 | if (!search) { 12 | return widgets; 13 | } 14 | return widgets.filter(widget => { 15 | return widget.component.name.toLowerCase().indexOf(search.toLowerCase()) >= 0; 16 | }); 17 | }; 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/app/js/editor/palette/palette-model.html: -------------------------------------------------------------------------------- 1 |
2 |
7 | 8 |
9 |
{{ widget.component.name }}
10 |
11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /frontend/app/js/editor/palette/palette-widget.html: -------------------------------------------------------------------------------- 1 |
2 |
6 |
7 | 8 | 10 |
{{ widget.component.name }}
11 |
12 |
13 |
14 | 15 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.editor.properties-panel', [ 20 | 'bonitasoft.designer.templates', 21 | 'bonitasoft.designer.editor.common', 22 | 'bonitasoft.designer.common.filters', 23 | 'bonitasoft.designer.common.repositories', 24 | 'gettext', 25 | 'ui.bootstrap' 26 | ]); 27 | 28 | })(); 29 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/bond/constant.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/bond/expression.html: -------------------------------------------------------------------------------- 1 |
2 | 4 | 5 | 11 | 12 | 13 | 14 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/bond/interpolation.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
5 |
6 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/bond/variable.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/common-properties-template.html: -------------------------------------------------------------------------------- 1 |
2 | 10 | 11 |
12 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/container-properties-template.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/container-repeat-content-tip.html: -------------------------------------------------------------------------------- 1 |
2 | Tip: To use the collection data in the widgets of this container, there are contextual variables that you can bind to the widget properties: 3 |
    4 |
  • $index: the index of the current iteration of the collection (counting from zero)
  • 5 |
  • $item: the element of the current iteration
  • 6 |
  • $collection: the current collection
  • 7 |
8 |
9 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/boolean.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 10 |
11 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/choice-grouped.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/choice.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/collection.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/float.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/html.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/integer.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/field/text.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/fragment/fragment-data-binding-field.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 |
7 | 11 | 12 |
13 | 17 |
18 |
19 |
20 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/fragment/fragment-properties-template.html: -------------------------------------------------------------------------------- 1 |

Bindable fragment data

2 | 3 | 10 | 11 | 12 |
13 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/fragment/fragment-save-popup.html: -------------------------------------------------------------------------------- 1 | 4 |
5 | 19 | 23 |
24 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/bidirectional-bond-help.html: -------------------------------------------------------------------------------- 1 | 2 | Use a bidirectional field to specify a read-write binding between the 3 | property value and a variable. 4 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/constant-bond-help.html: -------------------------------------------------------------------------------- 1 | 2 | A property that requires a constant value is presented in the Properties panel as a radio 3 | button set, drop-down list, or number selector (for the Width property). Select the required value. 4 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/description-bond-help.html: -------------------------------------------------------------------------------- 1 | 2 | A property value is constant, dynamic, a bidirectional bond, or 3 | an interpolation. 4 | 5 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/dynamic-bond-help.html: -------------------------------------------------------------------------------- 1 | Use a dynamic value field to specify a constant (the default) or an expression. Click the 2 | expression 3 | icon fx to switch from constant to expression. Click the constant icon X to switch from expression 4 | to 5 | constant. An expression can include a variable to make the property value dynamic, or can simply be 6 | the 7 | name of a variable. You can apply a filter to a variable value using a pipe. The binding to the 8 | variable 9 | is a read. If you want to write to the variable, use a bidirectional bond. 10 | Examples: 11 | 12 |
    13 |
  • Define a condition for widget visibility, userAge > 18
  • 14 |
  • Define table headers as the value of a variable: myArrayVariable
  • 15 |
  • Apply a filter to the value of a variable: selectedUser | json
  • 16 |
17 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/interpolation-bond-help.html: -------------------------------------------------------------------------------- 1 | 2 | Use an interpolation field to enter text to display in the widget. The 3 | text can include variables that are interpreted using AngularJS interpolation. When the page is displayed, the 4 | variables are replaced by the interpolated values. Specify a variable as a simple expression enclosed in double 5 | braces, using the same format as for a dynamic value field. 6 | Example: I'm sorry, {{ user.name | uppercase }}. I'm afraid I can't do that. 7 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/help/property-bond-help.html: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |
6 |
Constant
7 |
8 | 9 |
Dynamic value -
10 |
11 | 12 |
13 | 14 |
Bidirectional bond -
15 |
16 | 17 |
Interpolation -
18 |
19 |
20 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/modal-container-properties-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/property-field.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/property-typeahead.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/tab-container-properties-template.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /frontend/app/js/editor/properties-panel/widgetHelpTemplate.html: -------------------------------------------------------------------------------- 1 | 5 |
6 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/component-id.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('bonitasoft.designer.editor.whiteboard') 7 | .service('componentId', componentIdService); 8 | 9 | function componentIdService() { 10 | 11 | var counters = {}; 12 | return { 13 | getNextId: getNextId 14 | }; 15 | 16 | function getNextId(type) { 17 | if (counters.hasOwnProperty(type)) { 18 | counters[type] += 1; 19 | } else { 20 | counters[type] = 0; 21 | } 22 | return type + '-' + counters[type]; 23 | } 24 | } 25 | 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/component-mover.html: -------------------------------------------------------------------------------- 1 |
2 | {{component.$$widget.name}} 3 | 4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/component-template.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/container-template.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/form-container-template.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/form-container.directive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | angular.module('bonitasoft.designer.editor.whiteboard') 16 | .directive('formContainer', function() { 17 | 18 | 'use strict'; 19 | 20 | return { 21 | restrict: 'E', 22 | scope: { 23 | id: '@', 24 | formContainer: '=', 25 | editor: '=' 26 | }, 27 | templateUrl: 'js/editor/whiteboard/form-container.html' 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/form-container.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/fragment-preview/form-container-preview.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/fragment-preview/modal-container-preview.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/fragment-preview/tabs-container-preview.html: -------------------------------------------------------------------------------- 1 | 6 |
7 | 8 |
9 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/fragment-template.html: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/fragment.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 |
7 | 8 |
9 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/modal-container-template.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/modal-container.directive.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2009, 2018 Bonitasoft S.A. 3 | * Bonitasoft is a trademark of Bonitasoft SA. 4 | * This software file is BONITASOFT CONFIDENTIAL. Not For Distribution. 5 | * For commercial licensing information, contact: 6 | * Bonitasoft, 32 rue Gustave Eiffel – 38000 Grenoble 7 | * or Bonitasoft US, 51 Federal Street, Suite 305, San Francisco, CA 94107 8 | *******************************************************************************/ 9 | angular.module('bonitasoft.designer.editor.whiteboard').directive('modalContainer', function(RecursionHelper) { 10 | 11 | 'use strict'; 12 | 13 | return { 14 | restrict: 'E', 15 | scope: { 16 | id: '@', 17 | modalContainer: '=', 18 | editor: '=' 19 | }, 20 | templateUrl: 'js/editor/whiteboard/modal-container.html', 21 | compile: function(element) { 22 | return RecursionHelper.compile(element, function() { 23 | }); 24 | } 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/modal-container.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/switchComponent/not-supported-browser-popup.html: -------------------------------------------------------------------------------- 1 | 5 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/tabs-container-template.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/editor/whiteboard/uiTranslate.filter.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('bonitasoft.designer.editor.whiteboard') 5 | 6 | // Disable widget internationalization whenever we are in the whiteboard 7 | .filter('uiTranslate', function() { 8 | return function(value) { 9 | return value; 10 | }; 11 | }); 12 | })(); 13 | -------------------------------------------------------------------------------- /frontend/app/js/home/artifact-list/alert-deletion-notpossible-popup.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | 21 | 24 |
25 | -------------------------------------------------------------------------------- /frontend/app/js/home/artifact-list/artifact-tooltip-template.html: -------------------------------------------------------------------------------- 1 |
2 | {{artifact.name }} 3 |
4 | 7 |
8 | -------------------------------------------------------------------------------- /frontend/app/js/home/artifact-list/confirm-deletion-popup.html: -------------------------------------------------------------------------------- 1 |
2 | 5 | 8 | 12 |
13 | -------------------------------------------------------------------------------- /frontend/app/js/home/artifact-list/favorite-button.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('bonitasoft.designer.home') 7 | .directive('favoriteButton', favoriteButton); 8 | 9 | function favoriteButton() { 10 | return { 11 | scope: { 12 | artifact: '=', 13 | repository: '=artifactRepository' 14 | }, 15 | controller: FavoriteButtonCtrl, 16 | controllerAs: 'vm', 17 | bindToController: true, 18 | replace: true, 19 | templateUrl: 'js/home/artifact-list/favorite-button.html' 20 | }; 21 | } 22 | 23 | function FavoriteButtonCtrl() { 24 | var vm = this; 25 | 26 | vm.toggleFavorite = function() { 27 | if (vm.artifact.favorite) { 28 | vm.repository.unmarkAsFavorite(vm.artifact.id); 29 | } else { 30 | vm.repository.markAsFavorite(vm.artifact.id); 31 | } 32 | vm.artifact.favorite = !vm.artifact.favorite; 33 | }; 34 | 35 | vm.isFavorite = function() { 36 | return vm.artifact.favorite; 37 | }; 38 | } 39 | 40 | })(); 41 | -------------------------------------------------------------------------------- /frontend/app/js/home/artifact-list/favorite-button.html: -------------------------------------------------------------------------------- 1 | 2 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /frontend/app/js/home/create/create.less: -------------------------------------------------------------------------------- 1 | .HomeCreate-popover { 2 | max-width: 400px; 3 | width: 400px; 4 | } 5 | 6 | .NewArtifact .NewArtifact-type { 7 | > label { 8 | margin-bottom: 0px; 9 | } 10 | .radio{ 11 | margin-left: 20px; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/app/js/home/create/home-create.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/home-import.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/import-error-message.html: -------------------------------------------------------------------------------- 1 |

2 | {{ cause }} 3 |

4 |

5 |

{{ consequence }}
6 |
{{ additionalInfos }}
7 |

8 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/import-report-item-list.html: -------------------------------------------------------------------------------- 1 |
    2 |
  • 3 | 4 | 5 | {{ artifactType }} 8 | 9 | 10 | {{ joinOnNames(artifacts) }} 11 |
  • 12 |
13 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/import-success-message.html: -------------------------------------------------------------------------------- 1 |
2 |

{{import.translateKeys(type)}} {{ element.name }} 3 | successfully imported. 4 |

5 |
6 | Added artifacts: 7 | 8 |
9 |
10 | Overridden artifacts: 11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/import.less: -------------------------------------------------------------------------------- 1 | .HomeImport-popover{ 2 | max-width: 500px; 3 | } 4 | 5 | .ImportReport-type { 6 | text-transform: capitalize; 7 | } 8 | 9 | .ImportReport { 10 | 11 | 12 | .ui-icon, .fa { 13 | margin-right: 4px; 14 | } 15 | ul { 16 | padding-left: 0.8em; 17 | list-style: none; 18 | } 19 | .ImportReport--smallAndUnderlined { 20 | text-decoration: underline; 21 | font-size: 0.8em; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /frontend/app/js/home/import/import.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.home.import', [ 20 | 'bonitasoft.designer.common.repositories', 21 | 'bonitasoft.designer.common.services', 22 | 'bonitasoft.designer.templates', 23 | 'gettext' 24 | ]); 25 | 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/i18n/_.module.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2009, 2015 Bonitasoft S.A. 3 | * Bonitasoft is a trademark of Bonitasoft SA. 4 | * This software file is BONITASOFT CONFIDENTIAL. Not For Distribution. 5 | * For commercial licensing information, contact: 6 | * Bonitasoft, 32 rue Gustave Eiffel – 38000 Grenoble 7 | * or Bonitasoft US, 51 Federal Street, Suite 305, San Francisco, CA 94107 8 | *******************************************************************************/ 9 | (function() { 10 | 11 | 'use strict'; 12 | 13 | angular.module('bonitasoft.designer.i18n', [ 14 | 'bonitasoft.designer.templates', 15 | 'ngCookies', 16 | 'ui.bootstrap', 17 | 'gettext' 18 | ]); 19 | 20 | })(); 21 | -------------------------------------------------------------------------------- /frontend/app/js/i18n/language-picker.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 7 | 8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /frontend/app/js/i18n/preview-localized-iframe.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('bonitasoft.designer.i18n') 7 | .directive('previewLocalizedIframe', previewIframe) 8 | .service('iframeElement', iframeElement); 9 | 10 | function previewIframe(i18n, iframeElement) { 11 | return { 12 | link 13 | }; 14 | 15 | function link(scope, element) { 16 | var iframe = iframeElement.get(element[0]); 17 | 18 | element.on('load', function() { 19 | //check https://github.com/angular/angular.js/issues/7023 20 | var catalog = iframe.angular.element(iframe.document.body).injector().get('gettextCatalog'); 21 | i18n.refresh(Object.keys(catalog.strings), catalog.getCurrentLanguage()); 22 | }); 23 | scope.$on('$destroy', () => element.off('load')); 24 | 25 | i18n.setCookiePath(iframe.location.src); 26 | } 27 | } 28 | 29 | /** 30 | * Service used for test purpose. 31 | * Allow to mock iframe 32 | */ 33 | function iframeElement() { 34 | return { 35 | get: function(iframe) { 36 | return iframe.contentWindow; 37 | } 38 | }; 39 | } 40 | 41 | })(); 42 | -------------------------------------------------------------------------------- /frontend/app/js/navbar-toggle/navbar-toggle.directive.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (C) 2009, 2015 Bonitasoft S.A. 3 | * Bonitasoft is a trademark of Bonitasoft SA. 4 | * This software file is BONITASOFT CONFIDENTIAL. Not For Distribution. 5 | * For commercial licensing information, contact: 6 | * Bonitasoft, 32 rue Gustave Eiffel – 38000 Grenoble 7 | * or Bonitasoft US, 51 Federal Street, Suite 305, San Francisco, CA 94107 8 | *******************************************************************************/ 9 | (() => { 10 | 11 | angular 12 | .module('bonitasoft.designer.i18n') 13 | .directive('navbarToggle', () => ({ 14 | scope: { 15 | onClick: '&' 16 | }, 17 | restrict: 'E', 18 | templateUrl: 'js/navbar-toggle/navbar-toggle.html' 19 | })); 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /frontend/app/js/navbar-toggle/navbar-toggle.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /frontend/app/js/navbar-toggle/navbar-toggle.less: -------------------------------------------------------------------------------- 1 | .NavbarToggle .icon-bar { 2 | background-color: @color-editor-header-text; 3 | } 4 | -------------------------------------------------------------------------------- /frontend/app/js/preview/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.preview', [ 20 | 'bonitasoft.designer.common.services', 21 | 'bonitasoft.designer.app-selector', 22 | 'bonitasoft.designer.common.repositories', 23 | 'ui.router', 24 | 'ngStorage' 25 | ]); 26 | 27 | })(); 28 | -------------------------------------------------------------------------------- /frontend/app/js/preview/app-selector/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.app-selector', [ 20 | 'bonitasoft.designer.templates', 21 | 'ngStorage', 22 | 'ui.bootstrap', 23 | 'gettext' 24 | ]); 25 | 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/app/js/preview/app-selector/app-selector.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | View in application 4 | 7 | 8 | 15 |
16 | -------------------------------------------------------------------------------- /frontend/app/js/preview/open-preview.html: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /frontend/app/js/preview/preview.less: -------------------------------------------------------------------------------- 1 | .Preview { 2 | height: 100%; 3 | 4 | &-header { 5 | background-color: @color-editor-header-bg; 6 | color: @color-editor-header-text; 7 | border-radius: 0; 8 | 9 | & .Select-control, .Select-addon { 10 | border-color: @btn-bonita-default-border; 11 | max-width: 300px; 12 | } 13 | 14 | & .Select-addon { 15 | color: @btn-bonita-default-color; 16 | background-color: @btn-bonita-default-bg; 17 | } 18 | 19 | } 20 | 21 | &-resolutionBar { 22 | .navbar-vertical-align(@input-height-base); 23 | } 24 | 25 | &-toolbar { 26 | float: right; 27 | 28 | .navbar-nav { 29 | margin: auto; 30 | } 31 | } 32 | 33 | &-artifact-name { 34 | float: left; 35 | padding: 15px 15px; 36 | font-size: 18px; 37 | line-height: 20px; 38 | word-break: break-all; 39 | word-wrap: break-word; 40 | } 41 | } 42 | 43 | .Preview-viewport { 44 | height: calc(~"100%" - @nav-bar-height + 30px); 45 | border: 2px solid #cccccc; 46 | border-radius: 5px; 47 | display: block; 48 | margin: 1em auto 0; 49 | box-sizing: content-box; 50 | } 51 | -------------------------------------------------------------------------------- /frontend/app/js/resolutions/_.module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Bonitasoft S.A. 3 | * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 2.0 of the License, or 7 | * (at your option) any later version. 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program. If not, see . 14 | */ 15 | (function() { 16 | 17 | 'use strict'; 18 | 19 | angular.module('bonitasoft.designer.resolution', ['bonitasoft.designer.common.services']); 20 | 21 | })(); 22 | -------------------------------------------------------------------------------- /frontend/app/js/resolutions/resolutions-bar.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /frontend/app/less/animations.less: -------------------------------------------------------------------------------- 1 | @keyframes fadein { 2 | from { 3 | opacity: 0; 4 | } 5 | to { 6 | opacity: 1; 7 | } 8 | } 9 | 10 | .u-fadeIn { 11 | animation: fadein 0.5s; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/app/less/drop-row.less: -------------------------------------------------------------------------------- 1 | .dropRow { 2 | position: relative; 3 | height: 5px; 4 | font-size: 12px; 5 | padding-left: 10px; 6 | border-radius: 3px; 7 | margin: 0 5px; 8 | color: transparent; 9 | } 10 | 11 | 12 | .dropRow.bo-drag-enter { 13 | .shadow-on-focus(); 14 | } 15 | 16 | .dropRow.bo-drag-enter:not(.bo-drag-dropzone-child) { 17 | height: 40px; 18 | line-height: 40px; 19 | background-color: #ddd; 20 | border: 2px dashed #999; 21 | color: #aaa; 22 | margin-left: 20px; 23 | margin-right: 15px; 24 | } 25 | 26 | .dropRow.bo-drag-dropzone-child { 27 | overflow: hidden; 28 | color: transparent; 29 | background-color: transparent; 30 | box-shadow: none; 31 | pointer-events: none 32 | } 33 | 34 | // Special case for the first and last dropRow in the editor; 35 | // we want it to cover all the upper space so once we drop a component on top, 36 | #editor > .widget-wrapper > div > .dropRow:first-child, 37 | #editor > .widget-wrapper > div > .dropRow--last{ 38 | height: 40px; 39 | } 40 | 41 | // placeholder special case when there is an empty whiteboard 42 | #editor > .widget-wrapper > div:first-child > .row-builder > .widget-placeholder:first-child { 43 | margin-top: 40px; 44 | } 45 | -------------------------------------------------------------------------------- /frontend/app/less/drop-zone.less: -------------------------------------------------------------------------------- 1 | 2 | .dropZone { 3 | width: 50%; 4 | height: 100%; 5 | position: absolute; 6 | top: 0; 7 | left: 0; 8 | z-index: 42; 9 | } 10 | 11 | .dropZone--right { 12 | left: 50%; 13 | } 14 | 15 | .dropZone.bo-dropzone-container.bo-drag-enter{ 16 | font-family: FontAwesome; 17 | background-color: rgba(132, 132, 132, 0.3); 18 | } 19 | 20 | 21 | .dropZone.bo-drag-enter::before { 22 | position: absolute; 23 | font-size:1.5em; 24 | line-height:1em; 25 | font-family: FontAwesome; 26 | text-align: center; 27 | top: 50%; 28 | left: 0; 29 | right: 0; 30 | margin-top: -.5em; 31 | color: #999 32 | } 33 | 34 | .dropZone.bo-drag-enter::before { 35 | content: "\f137"; // fa-chevron-circle-left 36 | } 37 | 38 | .dropZone--right.bo-drag-enter::before { 39 | content: "\f138"; // fa-chevron-circle-right 40 | } 41 | 42 | .dropZone.bo-drag-dropzone-child { 43 | display: none 44 | } 45 | -------------------------------------------------------------------------------- /frontend/app/less/file-upload.less: -------------------------------------------------------------------------------- 1 | .file-upload { 2 | position: relative; 3 | overflow: hidden; 4 | 5 | .form-control { 6 | z-index: 1; 7 | 8 | &[readonly] { 9 | cursor: inherit; 10 | } 11 | } 12 | 13 | } 14 | 15 | .file-upload-input { 16 | position: absolute; 17 | top: 0; 18 | right: 0; 19 | min-width: 100%; 20 | height: 100%; 21 | // allow the button part of the form input to cover all the input 22 | font-size: 1000px; 23 | text-align: right; 24 | filter: alpha(opacity=0); 25 | opacity: 0; 26 | outline: none; 27 | background: white; 28 | cursor: pointer; 29 | display: block; 30 | z-index: 2; 31 | } 32 | 33 | .file-upload-input--disabled { 34 | left: 0; 35 | right: auto; 36 | width:0; 37 | height:0; 38 | filter: alpha(opacity=0); 39 | opacity: 0; 40 | z-index: -1; 41 | } 42 | -------------------------------------------------------------------------------- /frontend/app/less/forms.less: -------------------------------------------------------------------------------- 1 | 2 | input.ng-dirty.ng-invalid, textarea.ng-dirty.ng-invalid { 3 | border: 2px solid #a94442; 4 | } 5 | 6 | input.datepicker{ 7 | border: 0; 8 | width: 1px; 9 | height: @input-height-base; 10 | position: absolute; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /frontend/app/less/fragment.less: -------------------------------------------------------------------------------- 1 | .fragment-element { 2 | background-color: #fff; 3 | min-height: 20px; 4 | img { 5 | right: 13px; 6 | } 7 | } 8 | 9 | .fragment-content { 10 | overflow-x: hidden; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/app/less/modal.less: -------------------------------------------------------------------------------- 1 | .modal-centered > div.modal-dialog { 2 | padding-top: 15%; 3 | } 4 | 5 | .modal.in .modal-dialog { 6 | transform: none; /* fix issue with ace editor tooltip */ 7 | } 8 | 9 | .modal-dialog.modal-xxl { 10 | width: 90vw; 11 | 12 | .ace_editor { 13 | height: ~"calc(100vh - 230px)"; 14 | min-height: 250px; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /frontend/app/less/panelheader.less: -------------------------------------------------------------------------------- 1 | .PanelHeader-header { 2 | padding: 0em 1em 0; 3 | line-height: 2.2; 4 | border-bottom: 1px solid @color-properties-header-border; 5 | background: @color-properties-header-bg; 6 | } 7 | 8 | .PanelHeader-header h3 { 9 | margin-top: 10px; 10 | } 11 | 12 | .PanelHeader-title { 13 | text-transform: uppercase; 14 | letter-spacing: 2px; 15 | text-overflow: ellipsis; 16 | white-space: nowrap; 17 | overflow: hidden; 18 | font-size: .9em; 19 | padding: 3px 0px; 20 | } 21 | 22 | .PanelHeader-help-btn { 23 | margin-top: 8px; 24 | font-size: 14px; 25 | float: left; 26 | margin-right:7px; 27 | } 28 | 29 | .PanelHeader-widget-action-btn { 30 | margin-top: 5px; 31 | font-size: 12px; 32 | float: right; 33 | } 34 | 35 | .PanelHeader-data-model-btn { 36 | margin-top: 8px; 37 | font-size: 12px; 38 | float: right; 39 | } 40 | -------------------------------------------------------------------------------- /frontend/app/less/popover.less: -------------------------------------------------------------------------------- 1 | /* retieved from https://github.com/mgcrea/bootstrap-additions/blob/master/src/popover/popover.less */ 2 | 3 | /* 4 | * Popovers corner placement 5 | * 6 | * Inherit exotic positionning from basic ones & fix arrow placement 7 | */ 8 | 9 | .popover { 10 | &.top-left { 11 | .popover.top; 12 | .arrow { 13 | .popover.top .arrow; 14 | left: 10%; 15 | } 16 | } 17 | &.top-right { 18 | .popover.top; 19 | .arrow { 20 | .popover.top .arrow; 21 | left: 90%; 22 | } 23 | } 24 | &.bottom-left { 25 | .popover.bottom; 26 | .arrow { 27 | .popover.bottom .arrow; 28 | left: 10%; 29 | } 30 | } 31 | &.bottom-right { 32 | .popover.bottom; 33 | .arrow { 34 | .popover.bottom .arrow; 35 | left: 90%; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /frontend/app/less/sidebar.less: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | bottom: 0; 7 | z-index: @z-index-sidebar; 8 | } 9 | 10 | .sidebar-left { 11 | right: 100 - @sidebar-palette-width; 12 | } 13 | 14 | .sidebar-action-list { 15 | padding-left: 0 16 | } 17 | 18 | .sidebar-action-list li { 19 | list-style: none 20 | } 21 | -------------------------------------------------------------------------------- /frontend/app/less/variables.less: -------------------------------------------------------------------------------- 1 | @bottom-toolbar-height: 32px; 2 | 3 | @sidebar-palette-width: 250px; 4 | @sidebar-palette-section-width: 50px; 5 | 6 | @sidebar-properties-default-width: 280px; 7 | @sidebar-data-default-height: 250px; 8 | 9 | @nav-bar-height: 60px; 10 | 11 | @z-index-sidebar: 50; /* greater than dropZone target */ 12 | 13 | @sidebar-title-height: 40px; 14 | @sidebar-bg-color: #F5F5F5; 15 | 16 | @bonita-light-grey: #AAA; 17 | 18 | @white: #ffffff; 19 | 20 | @transition-duration: 450ms; 21 | @transition-easing: cubic-bezier(0.19, 1, 0.22, 1); 22 | @sidebar-transition: @transition-duration @transition-easing; 23 | -------------------------------------------------------------------------------- /frontend/app/less/workspace.less: -------------------------------------------------------------------------------- 1 | @lightgrey: #DEDEDE; 2 | @grey: #888; 3 | 4 | @bottom-sidebar-title-height: 30px; 5 | 6 | .alert-editor-hint{ 7 | color: @grey; 8 | position: absolute; 9 | top: 8em; 10 | left: 10em; 11 | right: 1em; 12 | z-index: -1; 13 | } 14 | 15 | .alert-editor-hint .hint-title { 16 | margin: 0; 17 | font-weight: 700; 18 | } 19 | 20 | .alert-editor-hint .fa-share{ 21 | color: @lightgrey; 22 | position: absolute; 23 | top: .4em; 24 | left: -0.7em; 25 | font-size:2.6em; 26 | transform: rotate(270deg); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /frontend/assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | dist 7 | 8 | zip 9 | 10 | false 11 | 12 | 13 | / 14 | build/dist 15 | 16 | 17 | -------------------------------------------------------------------------------- /frontend/gulp/assets.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const config = require('./config.js'); 3 | 4 | let paths = config.paths; 5 | 6 | function locales() { 7 | return gulp.src(paths.locales) 8 | .pipe(gulp.dest(paths.dist + '/locales')); 9 | } 10 | 11 | function font() { 12 | return gulp.src(paths.assets.fonts) 13 | .pipe(gulp.dest(paths.dist + '/fonts')); 14 | } 15 | 16 | function ace() { 17 | return gulp.src(paths.assets.ace) 18 | .pipe(gulp.dest(paths.dist + '/js')); 19 | } 20 | 21 | function images() { 22 | return gulp.src(paths.assets.images) 23 | .pipe(gulp.dest(paths.dist + '/img')); 24 | } 25 | 26 | function licences() { 27 | return gulp.src(paths.assets.licences) 28 | .pipe(gulp.dest(paths.dist)); 29 | } 30 | 31 | function favicon() { 32 | return gulp.src(paths.assets.favicon) 33 | .pipe(gulp.dest(paths.dist)); 34 | } 35 | 36 | exports.copy = gulp.series(font, ace, images, licences, favicon, locales); 37 | -------------------------------------------------------------------------------- /frontend/gulp/bundle.js: -------------------------------------------------------------------------------- 1 | const plumber = require('gulp-plumber'); 2 | const concat = require('gulp-concat'); 3 | const babel = require('gulp-babel'); 4 | const order = require('gulp-order'); 5 | const gulp = require('gulp'); 6 | const config = require('./config.js'); 7 | 8 | 9 | /** 10 | * Concatenate e2e libs 11 | */ 12 | function bundleE2e() { 13 | return gulp.src(config.paths.e2e) 14 | .pipe(plumber()) 15 | .pipe(order([ 16 | '**/*.module.js', 17 | '**/*.js' 18 | ])) 19 | .pipe(babel()) 20 | .pipe(concat('e2e.js')) 21 | .pipe(gulp.dest(config.paths.test + '/js')); 22 | } 23 | 24 | 25 | exports.e2e = bundleE2e; 26 | -------------------------------------------------------------------------------- /frontend/gulp/dev.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const serve = require('./serve.js'); 3 | const index = require('./index.js'); 4 | const config = require('./config.js'); 5 | const build = require('./build.js'); 6 | 7 | let paths = config.paths; 8 | 9 | function watch(done) { 10 | gulp.watch(paths.js, gulp.series(build.bundleJs)); 11 | gulp.watch(paths.templates, gulp.series(build.bundleJs)); 12 | gulp.watch(['app/index.html'], gulp.series(index.dev)); 13 | gulp.watch(paths.less, gulp.series(build.bundleCss)); 14 | gulp.watch(paths.assets.icons, gulp.series(build.bundleIcons)); 15 | done(); 16 | } 17 | 18 | function setting(done) { 19 | config.devMode = true; 20 | done(); 21 | } 22 | 23 | exports.serve = gulp.series(build.clean, watch, setting, serve.dev); 24 | 25 | -------------------------------------------------------------------------------- /frontend/gulp/e2e.js: -------------------------------------------------------------------------------- 1 | const mkdirp = require('mkdirp'); 2 | const protractor = require('gulp-protractor').protractor; 3 | const gulp = require('gulp'); 4 | const config = require('./config.js'); 5 | const serve = require('./serve.js'); 6 | const build = require('./build.js'); 7 | const bundle = require('./bundle.js'); 8 | const index = require('./index.js'); 9 | let paths = config.paths; 10 | 11 | function e2eReportScafold(done) { 12 | mkdirp('build/reports/e2e-tests', done); 13 | } 14 | 15 | /** 16 | * e2e Tests 17 | */ 18 | 19 | const run = gulp.series(e2eReportScafold, build.buildAll, bundle.e2e, index.e2e, function _e2e() { 20 | let server = serve.serverE2e(paths); 21 | 22 | return gulp.src(['../test/e2e/spec/*.spec.js']) 23 | .pipe(protractor({ 24 | configFile: 'test/e2e/protractor.conf.js' 25 | })) 26 | .on('error', function (e) { 27 | throw e; 28 | }) 29 | .on('end', function () { 30 | server.close(); 31 | }); 32 | }); 33 | 34 | exports.run = run; 35 | -------------------------------------------------------------------------------- /frontend/gulp/index.js: -------------------------------------------------------------------------------- 1 | const htmlreplace = require('gulp-html-replace'); 2 | const gulp = require('gulp'); 3 | const config = require('./config.js'); 4 | 5 | let timestamp = config.timestamp; 6 | 7 | /** 8 | * Index file 9 | */ 10 | 11 | function indexDev() { 12 | return gulp.src('app/index.html') 13 | .pipe(gulp.dest(config.paths.dev)); 14 | } 15 | 16 | function indexE2e() { 17 | return gulp.src('app/index.html') 18 | .pipe(htmlreplace({ 19 | 'js': 'js/page-builder-' + timestamp + '.min.js', 20 | 'vendors': 'js/vendors-' + timestamp + '.min.js', 21 | 'css': 'css/page-builder-' + timestamp + '.min.css', 22 | 'e2e': 'js/e2e.js' 23 | })) 24 | .pipe(gulp.dest(config.paths.test)); 25 | } 26 | 27 | exports.e2e = indexE2e; 28 | exports.dev = indexDev; 29 | -------------------------------------------------------------------------------- /frontend/gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const build = require('./gulp/build.js'); 3 | const test = require('./gulp/test.js'); 4 | const e2e = require('./gulp/e2e.js'); 5 | const dev = require('./gulp/dev.js'); 6 | const serve = require('./gulp/serve.js'); 7 | 8 | exports.default = gulp.series(build.clean, test.checkCompleteness, build.buildAll); 9 | exports.test = test.run; 10 | exports.testWatch = test.watch; 11 | exports.e2e = e2e.run; 12 | exports.pot = build.pot; 13 | exports.serve = dev.serve; 14 | exports.serveDist = serve.dist; 15 | exports.serveE2e = serve.e2e; 16 | exports.checkEslint = build.checkEslint; 17 | exports.fixEsLint = build.fixEsLint; 18 | 19 | -------------------------------------------------------------------------------- /frontend/test/e2e/config/_.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | // Add e2e module to main pb module 6 | angular.module('uidesigner').requires.push('bonitasoft.designer.e2e'); 7 | 8 | angular.module('bonitasoft.designer.e2e', ['ngMockE2E']); 9 | 10 | })(); 11 | -------------------------------------------------------------------------------- /frontend/test/e2e/config/e2ehelper.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | class E2eHelper { 6 | getById(array, elementId) { 7 | return array.filter(function(elem) { 8 | return elem.id === elementId; 9 | })[0]; 10 | } 11 | 12 | lastChunk(url) { 13 | var chunk = url.match(/([^\/]*)\/*$/)[1]; 14 | // remove query parameters 15 | return chunk.split('?')[0]; 16 | } 17 | 18 | uuid() { 19 | return Math.floor((1 + Math.random()) * 0x10000).toString(16); 20 | } 21 | } 22 | 23 | angular 24 | .module('bonitasoft.designer.e2e') 25 | .service('e2ehelper', () => new E2eHelper()); 26 | })(); 27 | -------------------------------------------------------------------------------- /frontend/test/e2e/config/fixtures.assets.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('bonitasoft.designer.e2e') 7 | .value('assets', { 8 | 'myStyle.css': { 9 | content: '.somecssrule {\n color: blue\n}' 10 | } 11 | }); 12 | 13 | })(); 14 | -------------------------------------------------------------------------------- /frontend/test/e2e/pages/edit-local-asset-popup.page.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | 'use strict'; 3 | 4 | class EditLocalAssetPopUp { 5 | get fileContent() { 6 | return element(by.css('.EditAssetPopUp .ace_content')).getText(); 7 | } 8 | 9 | set fileContent(content) { 10 | element(by.css('.EditAssetPopUp .ace_text-input')).sendKeys(content); 11 | } 12 | 13 | save() { 14 | element(by.cssContainingText('.EditAssetPopUp .modal-footer button', 'Save')).click(); 15 | } 16 | 17 | dismiss() { 18 | element(by.css('.modal-footer')).element(by.css('.EditAssetPopUp-dismissBtn')).click(); 19 | } 20 | 21 | get dismissBtn() { 22 | return element(by.css('.modal-footer')).element(by.css('.EditAssetPopUp-dismissBtn')); 23 | } 24 | 25 | isOpen() { 26 | return element(by.css('.EditAssetPopUp')).isPresent(); 27 | } 28 | } 29 | 30 | module.exports = EditLocalAssetPopUp; 31 | 32 | })(); 33 | -------------------------------------------------------------------------------- /frontend/test/e2e/pages/preview.page.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var Preview = function() { 5 | }; 6 | 7 | Preview.getPage = function(pageId) { 8 | browser.get('#/en/preview/page/' + (pageId || 'empty')); 9 | return new Preview(); 10 | }; 11 | 12 | Preview.getFragment = function(fragmentId) { 13 | browser.get('#/en/preview/fragment/' + (fragmentId || 'empty')); 14 | return new Preview(); 15 | }; 16 | 17 | module.exports = Preview; 18 | 19 | Preview.prototype = Object.create({}, { 20 | 21 | iframe: { 22 | get: function() { 23 | return element(by.tagName('iframe')); 24 | } 25 | }, 26 | 27 | iframeWidth: { 28 | get: function() { 29 | return this.iframe.getAttribute('width'); 30 | } 31 | }, 32 | 33 | iframeSrc: { 34 | get: function() { 35 | return this.iframe.getAttribute('src'); 36 | } 37 | } 38 | 39 | }); 40 | 41 | })(); 42 | -------------------------------------------------------------------------------- /frontend/test/e2e/pages/utils.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | module.exports = { 5 | mouseOver, 6 | switchToAlert, 7 | clearAndFillAceEditor 8 | }; 9 | 10 | /** 11 | * Simulate mouse over on the element 12 | */ 13 | function mouseOver(element) { 14 | browser.actions().mouseMove(element, { x: 1, y: 1 }).perform(); 15 | } 16 | 17 | /** 18 | * Based on 19 | * https://github.com/angular/protractor/issues/1486 20 | * https://github.com/angular/angular.js/commit/addb1ae37d775937688ae6f09e6f0ebd79225849 21 | */ 22 | function switchToAlert() { 23 | browser.wait(protractor.ExpectedConditions.alertIsPresent(), 1000); 24 | return browser.switchTo().alert(); 25 | } 26 | 27 | function clearAndFillAceEditor(elementId, text) { 28 | browser.actions().doubleClick($('#' + elementId + ' .ace_content')).perform(); 29 | var area = $('#' + elementId + ' textarea'); 30 | area.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, protractor.Key.ALT, protractor.Key.SHIFT, 'd')); 31 | area.sendKeys(text); 32 | } 33 | })(); 34 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/confirm-on-exit.spec.js: -------------------------------------------------------------------------------- 1 | var PageEditor = require('../pages/editor.page.js'); 2 | var switchToAlert = require('../pages/utils.js').switchToAlert; 3 | 4 | describe('confirm on exit', function() { 5 | 6 | var editor; 7 | beforeEach(function() { 8 | editor = PageEditor.get('empty'); 9 | }); 10 | 11 | it('should not open a confirm dialog if there is no modification', function() { 12 | editor.back(); 13 | expect(browser.getCurrentUrl()).toMatch(/\/home/); 14 | }); 15 | 16 | it('should open a confirm dialog before going home', function() { 17 | editor.addWidget('pbParagraph'); 18 | editor.back(); 19 | 20 | var dialog = switchToAlert(); 21 | expect(dialog.accept).toBeDefined(); 22 | dialog.accept(); 23 | expect(browser.getCurrentUrl()).toMatch(/\/home/); 24 | }); 25 | 26 | it('should open a confirm dialog and stay on the same page if dismiss', function() { 27 | editor.addWidget('pbParagraph'); 28 | editor.back(); 29 | 30 | var dialog = switchToAlert(); 31 | expect(dialog.dismiss).toBeDefined(); 32 | dialog.dismiss(); 33 | expect(browser.getCurrentUrl()).toMatch(/\/empty/); 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/custom-widgets.spec.js: -------------------------------------------------------------------------------- 1 | var PageEditor = require('../pages/editor.page.js'); 2 | 3 | describe('custom widget test', function() { 4 | 5 | var editor; 6 | beforeEach(function() { 7 | editor = PageEditor.get('empty'); 8 | }); 9 | 10 | it('should allow adding a custom widget and edit it', function() { 11 | editor.addCustomWidget('customAwesomeWidget'); 12 | 13 | // then we should be able to edit it 14 | $('#widgetActionButton').click(); 15 | $('#editAction').click(); 16 | 17 | // then we should go the custom widget edition 18 | expect($('.EditorHeader-brand').getText()).toBe('WIDGET EDITOR'); 19 | }); 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/internationalisation.spec.js: -------------------------------------------------------------------------------- 1 | describe('i18n', function() { 2 | it('should translate in english by default', function() { 3 | browser.get('#/'); 4 | expect($('.HomeCreate').getText()).toBe('Create'); 5 | }); 6 | 7 | it('should translate in english if the language is not recognized', function() { 8 | browser.get('#/unknown/home'); 9 | expect($('.HomeCreate').getText()).toBe('Create'); 10 | }); 11 | 12 | it('should change when url is updated', function() { 13 | browser.get('#/fr/home'); 14 | expect($('.HomeCreate').getText()).toBe('Créer'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/resources/karma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/frontend/test/e2e/spec/resources/karma.png -------------------------------------------------------------------------------- /frontend/test/e2e/spec/resources/localization.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/resources/newVacation-localization.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /frontend/test/e2e/spec/resources/protractor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/frontend/test/e2e/spec/resources/protractor.png -------------------------------------------------------------------------------- /frontend/test/unit/assets/assets-type.filter.spec.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | describe('assetType filter', function() { 5 | var $filter; 6 | 7 | beforeEach(angular.mock.module('bonitasoft.designer.assets')); 8 | 9 | beforeEach(inject(function(_$filter_) { 10 | $filter = _$filter_; 11 | })); 12 | 13 | it('should return "JavaScript" when given js', function() { 14 | expect($filter('assetType')('js')).toEqual('JavaScript'); 15 | }); 16 | 17 | it('should return "CSS" when given css', function() { 18 | expect($filter('assetType')('css')).toEqual('CSS'); 19 | }); 20 | 21 | it('should return "Images" when given img', function() { 22 | expect($filter('assetType')('img')).toEqual('Image'); 23 | }); 24 | 25 | it('should return "" when given undefined', function() { 26 | expect($filter('assetType')()).toEqual(''); 27 | }); 28 | 29 | it('should return "" when given unknown', function() { 30 | expect($filter('assetType')('sdsdd')).toEqual(''); 31 | }); 32 | }); 33 | 34 | })(); 35 | -------------------------------------------------------------------------------- /frontend/test/unit/common/directives/compile-template.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('compile template directive', function() { 2 | var $compile, element, scope; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.common.directives')); 5 | beforeEach(inject(function(_$compile_, $rootScope) { 6 | $compile = _$compile_; 7 | 8 | scope = $rootScope.$new(); 9 | 10 | scope.template = '
inner content
'; 11 | })); 12 | 13 | it('should compile directives and insert content', function() { 14 | scope.insert = true; 15 | element = $compile('
')(scope); 16 | scope.$digest(); 17 | 18 | expect(element.find('div').length).toBe(1); 19 | }); 20 | 21 | it('should compile directives and not insert content', function() { 22 | scope.insert = false; 23 | element = $compile('
')(scope); 24 | scope.$digest(); 25 | 26 | expect(element.find('div').length).toBe(0); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /frontend/test/unit/common/directives/expand-modal.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('ExpandModal', () => { 2 | let element, scope; 3 | beforeEach(angular.mock.module('bonitasoft.designer.common.directives')); 4 | beforeEach(inject(($compile, $rootScope) => { 5 | scope = $rootScope.$new(); 6 | element = $compile('')(scope); 7 | scope.$apply(); 8 | })); 9 | 10 | it('should add a expand button', () => { 11 | expect(element.hasClass('modal-xxl')).toBeFalsy(); 12 | expect(element.find('i').hasClass('fa-expand')).toBeTruthy(); 13 | expect(element.find('i').hasClass('fa-compress')).toBeFalsy(); 14 | element.find('button').click(); 15 | scope.$apply(); 16 | 17 | expect(element.find('i').hasClass('fa-compress')).toBeTruthy(); 18 | expect(element.find('i').hasClass('fa-expand')).toBeFalsy(); 19 | expect(element.hasClass('modal-xxl')).toBeTruthy(); 20 | element.find('button').click(); 21 | scope.$apply(); 22 | 23 | expect(element.hasClass('modal-xxl')).toBeFalsy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/test/unit/common/directives/include-replace.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('directive includeReplace', function() { 2 | 3 | var compile, scope, templateCache; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.directives')); 6 | 7 | beforeEach(inject(function($injector, $rootScope) { 8 | templateCache = $injector.get('$templateCache'); 9 | compile = $injector.get('$compile'); 10 | scope = $rootScope.$new(); 11 | })); 12 | 13 | it('should replace ng-include tag with template', function() { 14 | templateCache.put('template.html', '

hello world

'); 15 | 16 | var element = compile('
')(scope); 17 | scope.$digest(); 18 | 19 | expect(element.find('ng-include').length).toBe(0); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /frontend/test/unit/common/directives/save-indicator/save-indicator.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('SaveIndicator', () => { 2 | 3 | var indicator, $scope, $timeout; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.directives')); 6 | 7 | beforeEach(inject(function ($compile, $rootScope, _$timeout_) { 8 | $scope = $rootScope.$new(); 9 | $timeout = _$timeout_; 10 | 11 | let element = $compile('')($scope); 12 | $scope.$apply(); 13 | indicator = element.find('.SaveIndicator'); 14 | })); 15 | 16 | it('should be hidden by default', function () { 17 | expect(indicator.hasClass('SaveIndicator--visible')).toBeFalsy(); 18 | }); 19 | 20 | it('should blink for one second while saved event is triggered', () => { 21 | $scope.$broadcast('saved'); 22 | $scope.$apply(); 23 | expect(indicator.hasClass('SaveIndicator--visible')).toBeTruthy(); 24 | 25 | $timeout.flush(); 26 | expect(indicator.hasClass('SaveIndicator--visible')).toBeFalsy(); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /frontend/test/unit/common/filters/mustachify.filter.spec.js: -------------------------------------------------------------------------------- 1 | describe('mustachify filter', () => { 2 | 3 | var mustachifyFilter; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.filters')); 6 | 7 | beforeEach(inject(function(_mustachifyFilter_) { 8 | mustachifyFilter = _mustachifyFilter_; 9 | })); 10 | 11 | it('should replace double brackets by curly braces', function() { 12 | var input = mustachifyFilter('hello [[ world ]]'); 13 | 14 | expect(input).toEqual('hello {{ world }}'); 15 | }); 16 | 17 | it('should replace specified characters by curly braces', function() { 18 | var input = mustachifyFilter('hello (( world $$', '((', '$$'); 19 | 20 | expect(input).toEqual('hello {{ world }}'); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/unit/common/repositories/import-repository.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('import repository service', () => { 2 | 3 | var importRepo, $httpBackend; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.repositories')); 6 | 7 | beforeEach(inject(function(_importRepo_, _$httpBackend_) { 8 | importRepo = _importRepo_; 9 | $httpBackend = _$httpBackend_; 10 | })); 11 | 12 | it('should force an import based on a uuid', () => { 13 | var uuid = 'zezaerze-zerz-zer-zer'; 14 | $httpBackend.expectPOST(`import/${uuid}/force`).respond({ 'an': 'importReport' }); 15 | importRepo.forceImport(uuid) 16 | .then(response => expect(response).toEqual({ 'an': 'importReport' })); 17 | $httpBackend.flush(); 18 | }); 19 | 20 | it('should cancel an import based on a uuid', () => { 21 | var uuid = 'zezaerze-zerz-zer-zer'; 22 | $httpBackend.expectPOST(`import/${uuid}/cancel`).respond({ 'an': 'importReport' }); 23 | importRepo.cancelImport(uuid) 24 | .then(response => expect(response).toEqual({ 'an': 'importReport' })); 25 | $httpBackend.flush(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /frontend/test/unit/common/repositories/repositories.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('repositories service', () => { 2 | 3 | var repositories, pageRepo, widgetRepo, fragmentRepo; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.repositories', 'bonitasoft.designer.editor.whiteboard')); 6 | 7 | beforeEach(inject(function(_repositories_, _pageRepo_, _widgetRepo_, _fragmentRepo_) { 8 | repositories = _repositories_; 9 | pageRepo = _pageRepo_; 10 | widgetRepo = _widgetRepo_; 11 | fragmentRepo = _fragmentRepo_; 12 | })); 13 | 14 | it('should get page repository', function() { 15 | expect(repositories.get('page')).toBe(pageRepo); 16 | }); 17 | 18 | it('should get widget repository', function() { 19 | expect(repositories.get('widget')).toBe(widgetRepo); 20 | }); 21 | 22 | it('should get fragment repository', function() { 23 | expect(repositories.get('fragment')).toBe(fragmentRepo); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/test/unit/common/services/browser-history.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('CustomWidgetEditorCtrl', function () { 2 | 3 | var $window, browserHistoryService; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.common.services')); 6 | 7 | beforeEach(inject(function ($rootScope, _$window_, _browserHistoryService_) { 8 | $window = _$window_; 9 | browserHistoryService = _browserHistoryService_; 10 | })); 11 | 12 | it('should navigate to home page', function () { 13 | let fallback = jasmine.createSpy(); 14 | browserHistoryService.back(fallback); 15 | expect(fallback).toHaveBeenCalled(); 16 | }); 17 | 18 | it('should navigate back', function () { 19 | let newState = { 20 | foo: 'bar' 21 | }; 22 | $window.history.pushState(newState, 'new state entry', 'fake-page.html'); 23 | let fallback = jasmine.createSpy(); 24 | browserHistoryService.back(fallback); 25 | expect(fallback).not.toHaveBeenCalled(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /frontend/test/unit/common/services/utils.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('utils', function() { 2 | var utils; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.common.services')); 5 | beforeEach(inject(function($injector) { 6 | utils = $injector.get('utils'); 7 | })); 8 | 9 | describe('clamp', function() { 10 | it('should return a clamp value', function() { 11 | var min = 0; 12 | var max = 5; 13 | expect(utils.clamp(min, 3, max)).toBe(3); 14 | expect(utils.clamp(min, -1, max)).toBe(min); 15 | expect(utils.clamp(min, 10, max)).toBe(max); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/bottom-panel/data-panel/exposable-data.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('exposableData', function() { 2 | var element, $scope, yesInput, noInput; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.editor.bottom-panel.data-panel')); 5 | beforeEach(angular.mock.module('bonitasoft.designer.templates')); 6 | 7 | beforeEach(inject(function($compile, $rootScope) { 8 | $scope = $rootScope.$new(); 9 | element = $compile('')($scope); 10 | $scope.$apply(); 11 | yesInput = element.find('#exposedYes'); 12 | noInput = element.find('#exposedNo'); 13 | })); 14 | 15 | it('should allow to expose a data', function() { 16 | $scope.exposed = false; 17 | $scope.$apply(); 18 | 19 | yesInput.controller('ngModel').$setViewValue(yesInput.val() === 'true'); 20 | $scope.$apply(); 21 | 22 | expect($scope.exposed).toBeTruthy(); 23 | }); 24 | 25 | it('should allow to hide a data', function() { 26 | $scope.exposed = true; 27 | $scope.$apply(); 28 | 29 | noInput.controller('ngModel').$setViewValue(noInput.val() === 'true'); 30 | $scope.$apply(); 31 | 32 | expect($scope.exposed).toBeFalsy(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/common/artifact-naming-validator.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('artifact naming validator service', function() { 2 | var artifactNamingValidatorService; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.editor.common')); 5 | beforeEach(inject(function(_artifactNamingValidatorService_) { 6 | artifactNamingValidatorService = _artifactNamingValidatorService_; 7 | })); 8 | 9 | it('should return false when new artifact name don\'t exist', function() { 10 | let artifactList = [{'type':'page','name':'myOldPage'},{'type':'page','name':'myOldPage2'}]; 11 | let isAlreadyExist = artifactNamingValidatorService.isArtifactNameAlreadyUseForType('myNewPage', 'page',artifactList); 12 | 13 | expect(isAlreadyExist).toBe(false); 14 | }); 15 | 16 | it('should return true when new artifact name already exist', function() { 17 | let artifactList = [{'type':'page','name':'mynewpage'},{'type':'page','name':'myOldPage2'}]; 18 | let isAlreadyExist = artifactNamingValidatorService.isArtifactNameAlreadyUseForType('myNewPage', 'page',artifactList); 19 | 20 | expect(isAlreadyExist).toBe(true); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/menu-bar/open-help.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('open help directive', function() { 2 | var $compile, element, scope, directiveScope, $uibModal; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.editor.header', 'mock.modal')); 5 | beforeEach(inject(function(_$compile_, $rootScope, _$uibModal_) { 6 | $compile = _$compile_; 7 | 8 | scope = $rootScope.$new(); 9 | $uibModal = _$uibModal_; 10 | 11 | spyOn($uibModal, 'open'); 12 | })); 13 | 14 | it('should open help popup on click', function() { 15 | 16 | element = $compile('')(scope); 17 | scope.$digest(); 18 | directiveScope = element.isolateScope(); 19 | 20 | expect($uibModal.open).not.toHaveBeenCalled(); 21 | 22 | element.click(); 23 | 24 | expect($uibModal.open).toHaveBeenCalled(); 25 | expect($uibModal.open.calls.mostRecent().args[0].templateUrl).toEqual('js/editor/header/help/help-popup.html'); 26 | expect($uibModal.open.calls.mostRecent().args[0].size).toEqual('lg'); 27 | expect(directiveScope.helpSection).toBe('filters'); 28 | expect(directiveScope.editorMode).toBe('page'); 29 | }); 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/palette/palette.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('paletteService', function() { 2 | var paletteService, components; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.editor.palette')); 5 | beforeEach(inject(function(_paletteService_, _components_) { 6 | paletteService = _paletteService_; 7 | components = _components_; 8 | })); 9 | 10 | it('should get palette sections', function() { 11 | spyOn(components, 'get').and.returnValue({ 12 | foo: { 13 | component: { id: 'foo' }, 14 | sectionName: 'bar', 15 | sectionOrder: 1 16 | } 17 | }); 18 | 19 | var section = paletteService.getSections()[0]; 20 | expect(section.name).toBe('bar'); 21 | expect(section.order).toBe(1); 22 | expect(section.widgets.length).toBe(1); 23 | }); 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/properties-panel/fragment/fragment-data-binding-field.controller.spec.js: -------------------------------------------------------------------------------- 1 | describe('fragment data binding field controller', function() { 2 | var $scope; 3 | 4 | beforeEach(angular.mock.module('bonitasoft.designer.editor.properties-panel')); 5 | beforeEach(inject(function($rootScope, $controller) { 6 | $scope = $rootScope.$new(); 7 | 8 | $controller('FragmentDataBindingFieldDirectiveCtrl', { 9 | $scope: $scope 10 | }); 11 | })); 12 | 13 | it('should initialize binding if undefined', function() { 14 | expect($scope.binding).toEqual(''); 15 | }); 16 | 17 | }); 18 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/whiteboard/component-id.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('componentFactory', function() { 2 | 3 | var componentId; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.editor.whiteboard')); 6 | 7 | beforeEach(inject(function(_componentId_) { 8 | componentId = _componentId_; 9 | })); 10 | 11 | it('should return an id for a given type', function() { 12 | expect(componentId.getNextId('aType')).toEqual('aType-0'); 13 | expect(componentId.getNextId('anotherType')).toEqual('anotherType-0'); 14 | }); 15 | 16 | it('should return the incremented id for a given type', function() { 17 | expect(componentId.getNextId('component')).toEqual('component-0'); 18 | expect(componentId.getNextId('component')).toEqual('component-1'); 19 | }); 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /frontend/test/unit/editor/whiteboard/component.directive.spec.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/frontend/test/unit/editor/whiteboard/component.directive.spec.js -------------------------------------------------------------------------------- /frontend/test/unit/home/file-input-change.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('directive fileInputChange', function() { 2 | 3 | var $document, scope, element; 4 | 5 | beforeEach(angular.mock.module('bonitasoft.designer.home')); 6 | 7 | beforeEach(inject(function($injector) { 8 | var rootScope = $injector.get('$rootScope'); 9 | var compile = $injector.get('$compile'); 10 | $document = $injector.get('$document'); 11 | 12 | scope = rootScope.$new(); 13 | scope.filename = ''; 14 | 15 | element = compile('')(scope); 16 | $document.find('body').append(element); 17 | scope.$digest(); 18 | })); 19 | 20 | afterEach(function() { 21 | angular.element('#myinput').remove(); 22 | }); 23 | 24 | it('should update ', function() { 25 | var event = { 26 | type: 'change', 27 | target: { 28 | files: [{ 29 | name: 'filename.jpg' 30 | }] 31 | } 32 | }; 33 | element.triggerHandler(event); 34 | expect(scope.filename).toBe('filename.jpg'); 35 | }); 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /frontend/test/unit/home/import/import-report-item-list.directive.spec.js: -------------------------------------------------------------------------------- 1 | describe('importReportItemList directive', () => { 2 | var scope; 3 | beforeEach(angular.mock.module('bonitasoft.designer.home.import')); 4 | beforeEach(inject(($rootScope, $compile) => { 5 | scope = $rootScope.$new(); 6 | var markup = ' '; 7 | var element = $compile(markup)(scope); 8 | scope.$apply(); 9 | scope = element.isolateScope(); 10 | })); 11 | it('should join artifact names',() => { 12 | expect(scope.joinOnNames()).toBeUndefined(); 13 | expect(scope.joinOnNames([])).toEqual(''); 14 | var artifacts = [{ name: 'widget1' }, { name: 'widget3' }]; 15 | expect(scope.joinOnNames(artifacts)).toEqual('widget1, widget3'); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /frontend/test/unit/preview/app-selector/app-selector.service.spec.js: -------------------------------------------------------------------------------- 1 | describe('appSelectorService', function() { 2 | 3 | 'use strict'; 4 | 5 | var appSelectorService, $localStorage; 6 | 7 | beforeEach(angular.mock.module('bonitasoft.designer.app-selector')); 8 | 9 | beforeEach(inject(function ($injector) { 10 | appSelectorService = $injector.get('appSelectorService'); 11 | $localStorage = $injector.get('$localStorage'); 12 | })); 13 | 14 | afterEach(function() { 15 | $localStorage.bonitaUIDesigner = undefined; 16 | }); 17 | 18 | it('should contain the correct default path to appName', function(){ 19 | expect(appSelectorService.getPathToLivingApp()).toBe('no-app-selected'); 20 | }); 21 | 22 | it('should update the pathToLivingApp', function () { 23 | appSelectorService.savePathToLivingApp('appPage1'); 24 | 25 | expect(appSelectorService.getPathToLivingApp()).toBe('appPage1'); 26 | expect($localStorage.bonitaUIDesigner.bosAppName).toBe('appPage1'); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /frontend/test/unit/utils/builders/ContainerElementBuilder.js: -------------------------------------------------------------------------------- 1 | class ContainerElementBuilder { 2 | 3 | constructor() { 4 | this.rows = []; 5 | } 6 | 7 | static aContainer() { 8 | return new ContainerElementBuilder(); 9 | } 10 | 11 | withRow(row) { 12 | this.rows.push(row); 13 | return this; 14 | } 15 | } 16 | 17 | export default ContainerElementBuilder.aContainer; -------------------------------------------------------------------------------- /frontend/test/unit/utils/builders/FormContainerElementBuilder.js: -------------------------------------------------------------------------------- 1 | class FormContainerElementBuilder { 2 | 3 | constructor() { 4 | this.container = { 5 | rows: [] 6 | }; 7 | } 8 | 9 | static aFormContainer() { 10 | return new FormContainerElementBuilder(); 11 | } 12 | 13 | withRow(row) { 14 | this.container.rows.push(row); 15 | return this; 16 | } 17 | } 18 | 19 | export default FormContainerElementBuilder.aFormContainer; -------------------------------------------------------------------------------- /frontend/test/unit/utils/builders/TabContainerElementBuilder.js: -------------------------------------------------------------------------------- 1 | class TabContainerElementBuilder { 2 | 3 | constructor() { 4 | this.container = { 5 | rows: [] 6 | }; 7 | this.triggerRemoved = jasmine.createSpy('triggerRemoved'); 8 | } 9 | 10 | static aTabContainer() { 11 | return new TabContainerElementBuilder(); 12 | } 13 | 14 | withRow(row) { 15 | this.container.rows.push(row); 16 | return this; 17 | } 18 | 19 | title(title) { 20 | this.title = title; 21 | return this; 22 | } 23 | } 24 | 25 | export default TabContainerElementBuilder.aTabContainer; 26 | -------------------------------------------------------------------------------- /frontend/test/unit/utils/builders/TabsContainerElementBuilder.js: -------------------------------------------------------------------------------- 1 | class TabsContainerElementBuilder { 2 | 3 | constructor() { 4 | this.tabs = []; 5 | } 6 | 7 | static aTabsContainer() { 8 | return new TabsContainerElementBuilder(); 9 | } 10 | 11 | withTab(tab) { 12 | this.tabs.push(tab); 13 | return this; 14 | } 15 | } 16 | 17 | export default TabsContainerElementBuilder.aTabsContainer; -------------------------------------------------------------------------------- /frontend/test/unit/utils/builders/WidgetElementBuilder.js: -------------------------------------------------------------------------------- 1 | class WidgetElementBuilder { 2 | 3 | constructor() { 4 | this.triggerRemoved = jasmine.createSpy('triggerRemoved'); 5 | this.triggerAdded = jasmine.createSpy('triggerAdded'); 6 | this.dimension = { xs: 12 }; 7 | } 8 | 9 | static aWidget() { 10 | return new WidgetElementBuilder(); 11 | } 12 | 13 | id(id) { 14 | this.id = id; 15 | return this; 16 | } 17 | 18 | withParentContainerRow(containerRow) { 19 | this.$$parentContainerRow = containerRow; 20 | return this; 21 | } 22 | } 23 | 24 | export default WidgetElementBuilder.aWidget; -------------------------------------------------------------------------------- /frontend/test/unit/utils/matchers.js: -------------------------------------------------------------------------------- 1 | function pass(message) { 2 | return { 3 | pass: true, 4 | message: message 5 | }; 6 | } 7 | 8 | function fail(message) { 9 | return { 10 | pass: false, 11 | message: message 12 | }; 13 | } 14 | 15 | export default { 16 | elementMatchers: { 17 | 18 | toHaveClass: function() { 19 | return { 20 | compare: function(actual, expected) { 21 | var element = angular.element(actual); 22 | if (element.hasClass(expected)) { 23 | return pass('expected to have class [' + expected + ']'); 24 | } else { 25 | return fail('expected to have class [' + expected + '] but got [' + actual[0].classList.toString() + ']'); 26 | } 27 | } 28 | }; 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /frontend/test/unit/utils/web-socket.mock.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular 6 | .module('mock.webSocket', []) 7 | .service('webSocket', webSocket); 8 | 9 | function webSocket($q) { 10 | 11 | var deferred = $q.defer(); 12 | var deferredConnect = $q.defer(); 13 | var listenUrls = []; 14 | 15 | return { 16 | subscribe: function(topic, callback) { 17 | listenUrls.push(topic); 18 | deferred.promise.then(callback); 19 | }, 20 | send: function(url, data) { 21 | if (listenUrls.indexOf(url) >= 0) { 22 | deferred.resolve(data); 23 | } 24 | }, 25 | connect: function() { 26 | return deferredConnect.promise; 27 | }, 28 | resolveConnection: function () { 29 | deferredConnect.resolve(); 30 | } 31 | }; 32 | } 33 | 34 | })(); 35 | -------------------------------------------------------------------------------- /img/WysiwygUIDEditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/img/WysiwygUIDEditor.png -------------------------------------------------------------------------------- /infrastructure/README.adoc: -------------------------------------------------------------------------------- 1 | = List Dependencies on UID 2 | 3 | Checkout branch or tag on which list dependencies 4 | 5 | git checkout tags/your-tag-name 6 | 7 | == Generate dependencies reports 8 | 9 | Run 10 | 11 | ./mvnw package -Pdependencies -DbonitaMinorVersion=7.x 12 | 13 | This command allow you to generate reports for maven dependencies and for npm dependencies on each module. 14 | 15 | == Generate dependencies reports 16 | 17 | Move dependency report in one folder, to do this run: 18 | 19 | ./infrastructure/dependencies/moveDependenciesReportsFiles.sh 20 | 21 | At this step, you get a folder name *bonita-ui-designer-dependencies* at the root of this project. 22 | 23 | == Summarize dependencies in AsciiDoc file 24 | 25 | Enter this following command line: 26 | 27 | [source,shell] 28 | ---- 29 | ./mvnw initialize -Pdependencies -DbonitaMinorVersion=7.12 30 | ---- 31 | 32 | 👏👏 Congratulations you get your dependencies report ./backend/webapp/target/bonita-ui-designer-dependencies-7.x.adoc 33 | 34 | -------------------------------------------------------------------------------- /infrastructure/next-patch-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPTDIR=$(cd $(dirname $0) && pwd) 4 | BASEDIR=$SCRIPTDIR/.. 5 | 6 | cd $BASEDIR 7 | 8 | get_current_version() { 9 | # TODO: could be replaced (safer) with curr_version=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) 10 | grep -Po -m1 '(?<=).*(?=)' pom.xml 11 | } 12 | 13 | get_next_patch_version() { 14 | curr_version=$(get_current_version) 15 | git fetch --prune origin +refs/tags/*:refs/tags/* >& /dev/null 16 | minor_version=$(echo $curr_version | grep -P '\d{1,}\.\d{1,}' -o) 17 | latest_tag=$(git tag -l ${minor_version}.* | sort --version-sort | tail -1) 18 | # increment last version number (patch) 19 | echo "${latest_tag%.*}.$((${latest_tag##*.}+1))" 20 | } 21 | 22 | echo $(get_next_patch_version) 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bonita-ui-designer", 3 | "version": "1.20.0-SNAPSHOT" 4 | } 5 | -------------------------------------------------------------------------------- /server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PORTAL_ORIGIN=http://localhost:8081 4 | export DATA_REPOSITORY_ORIGIN=http://localhost:4000 5 | export EXPERIMENTAL=false 6 | 7 | echo "Using $PORTAL_ORIGIN as portal origin." 8 | echo "Using $DATA_REPOSITORY_ORIGIN as data repository origin." 9 | 10 | yarnCrossPlatform="yarn" 11 | if [ "$OSTYPE" = "msys" ];then 12 | yarnCrossPlatform="yarn.cmd" 13 | fi 14 | 15 | (cd backend/webapp/ && \ 16 | mvn spring-boot:start \ 17 | -Dspring-boot.run.arguments="--designer.bonita.portal.url=$PORTAL_ORIGIN --designer.bonita.bdm.url=$DATA_REPOSITORY_ORIGIN --designer.experimental=$EXPERIMENTAL" \ 18 | -Dwait=500 #The number of milli-seconds to wait between each attempt to check if the spring application is ready. 19 | ) 20 | (cd frontend/ && $yarnCrossPlatform start) 21 | 22 | # use mvn spring-boot:stop to kill backend if required 23 | -------------------------------------------------------------------------------- /tests/src/test/fixtures/fragment-testImport.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/tests/src/test/fixtures/fragment-testImport.zip -------------------------------------------------------------------------------- /tests/src/test/fixtures/greeeen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/tests/src/test/fixtures/greeeen.jpg -------------------------------------------------------------------------------- /tests/src/test/fixtures/middleware/api-user.middleware.js: -------------------------------------------------------------------------------- 1 | const users = require('./users'); 2 | const url = require('url'); 3 | const queryString = require('query-string'); 4 | 5 | const match = (req) => /API\/identity\/user/.test(req.url); 6 | 7 | const parseParams = (req) => queryString.parse(url.parse(req.url).search); 8 | 9 | const middleware = (req, res, next) => { 10 | 11 | if (!match(req)) { 12 | next(); 13 | return; 14 | } 15 | 16 | const params = parseParams(req); 17 | if (params.s) { 18 | res.setHeader('Content-Type', 'application/json'); 19 | res.end(JSON.stringify(users.filter(params.s))); 20 | } else { 21 | next(); 22 | } 23 | 24 | }; 25 | 26 | module.exports = middleware; 27 | -------------------------------------------------------------------------------- /tests/src/test/fixtures/middleware/fileupload.middleware.js: -------------------------------------------------------------------------------- 1 | var multiparty = require('multiparty'); 2 | 3 | const matchUpload = (req) => /API\/formFileUpload/.test(req.url); 4 | 5 | function uploadMiddleware(req, res, next) { 6 | var form = new multiparty.Form(); 7 | var filename; 8 | 9 | if (!matchUpload(req)) { 10 | next(); 11 | return; 12 | } 13 | 14 | form.on('error', function (error) { 15 | console.log('Error parsing form', error.stack); 16 | res.writeHead(500, {'content-type': 'text/plain'}); 17 | res.end(JSON.stringify(error)); 18 | }); 19 | 20 | form.on('part', function (part) { 21 | if (part.filename) { 22 | filename = part.filename; 23 | } 24 | part.resume(); 25 | }); 26 | 27 | form.on('close', function () { 28 | res.statusCode = 200; 29 | res.setHeader('content-type', 'text/html'); 30 | res.write(JSON.stringify({ 31 | filename: filename, 32 | tempPath: '1234.file' 33 | })); 34 | res.end(); 35 | }); 36 | 37 | form.parse(req); 38 | } 39 | 40 | module.exports = uploadMiddleware; 41 | -------------------------------------------------------------------------------- /tests/src/test/fixtures/middleware/server.js: -------------------------------------------------------------------------------- 1 | // Used only for middleware manual testing. 2 | 3 | // run `node server.js` or `nodemon server.js` to have live reload 4 | // then you can access to you test middleware on http://localhost:3000 5 | // ex: http://localhost:3000/API/identity/user?s=walt 6 | 7 | const connect = require('connect'); 8 | const http = require('http'); 9 | const userApi = require('./api-user.middleware'); 10 | 11 | const app = connect(); 12 | 13 | app.use(userApi); 14 | 15 | http.createServer(app).listen(3000); 16 | 17 | -------------------------------------------------------------------------------- /tests/src/test/fixtures/page-testImport.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/tests/src/test/fixtures/page-testImport.zip -------------------------------------------------------------------------------- /tests/src/test/fixtures/widget-testImport.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/tests/src/test/fixtures/widget-testImport.zip -------------------------------------------------------------------------------- /tests/src/test/resources/fragments/c8290d5b-166b-4fc0-a775-689480f7127a/c8290d5b-166b-4fc0-a775-689480f7127a.js: -------------------------------------------------------------------------------- 1 | var module; 2 | try { 3 | module = angular.module('bonitasoft.ui.fragments'); 4 | } catch (e) { 5 | module = angular.module('bonitasoft.ui.fragments', []); 6 | angular.module('bonitasoft.ui').requires.push('bonitasoft.ui.fragments'); 7 | } 8 | module.directive('pbFragmentPerson', function() { 9 | return { 10 | template: '
\n
\n
\n \n
\n
\n
\n
' 11 | }; 12 | }); 13 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/autocomplete/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* Add margin bottom and top to each widgets */ 2 | .component { 3 | margin-bottom: 3px; 4 | margin-top: 3px; 5 | } 6 | 7 | /* Set cursor to pointer on table with selectable rows */ 8 | .table-hover tr { 9 | cursor: pointer; 10 | } 11 | 12 | /* Set a red border to invalid input fields in forms */ 13 | input[type='text'].ng-invalid.ng-dirty, input[type='email'].ng-invalid.ng-dirty, 14 | input[type='number'].ng-invalid.ng-dirty, input[type='password'].ng-invalid.ng-dirty { 15 | border-color: #C00; 16 | border-width: 1px; 17 | } 18 | 19 | /* Add a red star after required inputs */ 20 | .control-label--required:after { 21 | content: "*"; 22 | color: #C00; 23 | } 24 | .btn-invalid{ 25 | border-color: #C00; 26 | border-width: 1px; 27 | } 28 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/dateTimePicker/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* Add margin bottom and top to each widgets */ 2 | .component { 3 | margin-bottom: 3px; 4 | margin-top: 3px; 5 | } 6 | 7 | /* Set cursor to pointer on table with selectable rows */ 8 | .table-hover tr { 9 | cursor: pointer; 10 | } 11 | 12 | /* Set a red border to invalid input fields in forms */ 13 | input[type='text'].ng-invalid.ng-dirty, input[type='email'].ng-invalid.ng-dirty, 14 | input[type='number'].ng-invalid.ng-dirty, input[type='password'].ng-invalid.ng-dirty { 15 | border-color: #C00; 16 | border-width: 1px; 17 | } 18 | 19 | /* Add a red star after required inputs */ 20 | .control-label--required:after { 21 | content: "*"; 22 | color: #C00; 23 | } 24 | .btn-invalid{ 25 | border-color: #C00; 26 | border-width: 1px; 27 | } 28 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/empty/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "designerVersion": "1.5-SNAPSHOT", 3 | "id": "empty", 4 | "name": "empty", 5 | "lastUpdate": 1431949985299, 6 | "rows": [ 7 | [] 8 | ], 9 | "assets": [], 10 | "variables": {} 11 | } 12 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/fileviewer/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* Add margin bottom and top to each widgets */ 2 | .component { 3 | margin-bottom: 3px; 4 | margin-top: 3px; 5 | } 6 | 7 | /* Set cursor to pointer on table with selectable rows */ 8 | .table-hover tr { 9 | cursor: pointer; 10 | } 11 | 12 | /* Set a red border to invalid input fields in forms */ 13 | input[type='text'].ng-invalid.ng-dirty, input[type='email'].ng-invalid.ng-dirty, 14 | input[type='number'].ng-invalid.ng-dirty, input[type='password'].ng-invalid.ng-dirty { 15 | border-color: #C00; 16 | border-width: 1px; 17 | } 18 | 19 | /* Add a red star after required inputs */ 20 | .control-label--required:after { 21 | content: "*"; 22 | color: #C00; 23 | } 24 | .btn-invalid{ 25 | border-color: #C00; 26 | border-width: 1px; 27 | } 28 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/image/assets/img/bonitaLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bonitasoft/bonita-ui-designer/f90960d8be41c3f729b47549116e8a49367e83e0/tests/src/test/resources/pages/image/assets/img/bonitaLogo.png -------------------------------------------------------------------------------- /tests/src/test/resources/pages/repeatInputWithValidation/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* Add margin bottom and top to each widgets */ 2 | .component { 3 | margin-bottom: 3px; 4 | margin-top: 3px; 5 | } 6 | 7 | /* Set cursor to pointer on table with selectable rows */ 8 | .table-hover tr { 9 | cursor: pointer; 10 | } 11 | 12 | /* Set a red border to invalid input fields in forms */ 13 | input[type='text'].ng-invalid.ng-dirty, input[type='email'].ng-invalid.ng-dirty, 14 | input[type='number'].ng-invalid.ng-dirty, input[type='password'].ng-invalid.ng-dirty { 15 | border-color: #C00; 16 | border-width: 1px; 17 | } 18 | 19 | /* Add a red star after required inputs */ 20 | .control-label--required:after { 21 | content: "*"; 22 | color: #C00; 23 | } 24 | .btn-invalid{ 25 | border-color: #C00; 26 | border-width: 1px; 27 | } 28 | -------------------------------------------------------------------------------- /tests/src/test/resources/pages/tabsContainer/assets/css/style.css: -------------------------------------------------------------------------------- 1 | /* Add margin bottom and top to each widgets */ 2 | .component { 3 | margin-bottom: 3px; 4 | margin-top: 3px; 5 | } 6 | 7 | /* Set cursor to pointer on table with selectable rows */ 8 | .table-hover tr { 9 | cursor: pointer; 10 | } 11 | 12 | /* Set a red border to invalid input fields in forms */ 13 | input[type='text'].ng-invalid.ng-dirty, input[type='email'].ng-invalid.ng-dirty, 14 | input[type='number'].ng-invalid.ng-dirty, input[type='password'].ng-invalid.ng-dirty { 15 | border-color: #C00; 16 | border-width: 1px; 17 | } 18 | 19 | /* Add a red star after required inputs */ 20 | .control-label--required:after { 21 | content: "*"; 22 | color: #C00; 23 | } 24 | .btn-invalid{ 25 | border-color: #C00; 26 | border-width: 1px; 27 | } 28 | -------------------------------------------------------------------------------- /tests/src/test/resources/widgets/customButton/customButton.js: -------------------------------------------------------------------------------- 1 | angular.module('bonitasoft.ui.widgets') 2 | .directive('customButton', function() { 3 | return { 4 | controllerAs: 'ctrl', 5 | controller: function WidgetbuttonController($scope) { 6 | this.sayClicked = function() { 7 | $scope.properties.value = 'clicked'; 8 | }; 9 | }, 10 | template: '' 11 | }; 12 | }); 13 | -------------------------------------------------------------------------------- /tests/src/test/resources/widgets/customButton/customButton.json: -------------------------------------------------------------------------------- 1 | { 2 | "designerVersion": "1.5-SNAPSHOT", 3 | "id": "customButton", 4 | "name": "button", 5 | "lastUpdate": 1431954947969, 6 | "template": "", 7 | "controller": "function WidgetbuttonController($scope) {\n this.sayClicked = function() {\n $scope.properties.value = 'clicked';\n };\n}", 8 | "custom": true, 9 | "properties": [{ 10 | "label": "Value", 11 | "name": "value", 12 | "type": "text", 13 | "defaultValue": "This is the initial value", 14 | "bond": "variable" 15 | }] 16 | } 17 | -------------------------------------------------------------------------------- /tests/src/test/spec/designer/editor.spec.js: -------------------------------------------------------------------------------- 1 | describe('UI designer: editor', function () { 2 | 3 | beforeEach(function () { 4 | browser.get('/bonita/#/en/pages/empty'); 5 | }); 6 | 7 | it('should open the empty page', function(){ 8 | var elements = element.all(by.tagName('component')); 9 | expect(elements.count()).toBe(0); 10 | }); 11 | 12 | }); 13 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/chart.spec.js: -------------------------------------------------------------------------------- 1 | describe('chart', function () { 2 | 3 | it('should draw single and multiple series charts', function () { 4 | browser.get('/bonita/preview/page/no-app-selected/chart/'); 5 | 6 | expect($$('pb-chart div.chart-container canvas').count()).toBe(2); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/checkbox.spec.js: -------------------------------------------------------------------------------- 1 | describe('checkbox', function () { 2 | 3 | it('should display checkbox that return a boolean value', function () { 4 | browser.get('/bonita/preview/page/no-app-selected/checkbox/'); 5 | 6 | var checkboxes = $$('pb-checkbox'); 7 | expect(checkboxes.count()).toEqual(3); // one is hidden 8 | 9 | // first value should be false 10 | expect($('pb-text p').getText()).toEqual("false"); 11 | 12 | // last checkbox should be disabled and checked by default 13 | expect(checkboxes.get(2).$('input').isSelected()).toBeTruthy(); 14 | expect(checkboxes.get(2).$('input').isEnabled()).toBeFalsy(); 15 | 16 | // click first, value is true and second is checked 17 | checkboxes.get(0).$('input').click(); 18 | expect(checkboxes.get(1).$('input').isSelected()).toBeTruthy(); 19 | expect($('pb-text p').getText()).toEqual("true"); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/dateTimePicker.spec.js: -------------------------------------------------------------------------------- 1 | describe('date time picker', function () { 2 | 3 | it('should display dates and time not taking timezone in account', function () { 4 | browser.get('/bonita/preview/page/no-app-selected/dateTimePicker/'); 5 | 6 | $('input[name="pbDateTimepicker0date"]').click(); 7 | element(by.cssContainingText('.dropdown-menu table td button', '21')).click(); 8 | expect($('input[name="pbDateTimepicker0date"]').getAttribute('value')).toMatch(/\d\d\/21\/\d\d\d\d/); 9 | expect($('input[name="pbDateTimepicker0time"]').getAttribute('value')).toMatch("4:17:00 PM"); 10 | 11 | }); 12 | 13 | it('should show error date message on wrong date', function () { 14 | browser.get('/bonita/preview/page/no-app-selected/dateTimePicker/'); 15 | 16 | $('input[name="pbDateTimepicker0date"]').click(); 17 | $('input[name="pbDateTimepicker0date"]').sendKeys('bonita'); 18 | 19 | expect($('.text-danger').getText()).toEqual('This is not a valid date or time'); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/fileviewer.spec.js: -------------------------------------------------------------------------------- 1 | describe('fileviewer', function () { 2 | 3 | it('should try to preview document', function () { 4 | browser.get('/bonita/preview/page/no-app-selected/fileviewer/'); 5 | 6 | expect($$('pb-file-viewer a.FileViewer-fileName').count()).toBe(3); 7 | expect($$('pb-file-viewer a.FileViewer-fileName[box-viewer]').count()).toBe(2); 8 | //image file 9 | expect($$('pb-file-viewer img').count()).toBe(1); 10 | expect($('pb-file-viewer img').getAttribute('src')).toContain('/API/formsDocumentImage?document=2'); 11 | //pdf file 12 | expect($$('pb-file-viewer iframe').count()).toBe(1); 13 | expect($('pb-file-viewer iframe').getAttribute('src')).toContain('/API/formsDocumentImage?document=1'); 14 | //unknoqn file 15 | expect($$('pb-file-viewer span.FileViewer-previewNotAvailable').count()).toBe(1); 16 | expect($('pb-file-viewer span.FileViewer-previewNotAvailable').getText()).toContain('Preview is not available'); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/form-container.spec.js: -------------------------------------------------------------------------------- 1 | describe('formContainer', function() { 2 | 3 | /** 4 | * The test sets up a label, with inputs bound to its properties. 5 | * We can play with its visibility, its alignment, its text... 6 | */ 7 | beforeEach(function() { 8 | browser.get('/bonita/preview/page/no-app-selected/formContainer/'); 9 | }); 10 | 11 | it('should display the $form name', function() { 12 | var form = $('form'); 13 | var paragraph = form.element(by.css('pb-text')); 14 | expect(form.getAttribute('name')).toBe('$form'); 15 | expect(paragraph.getText()).toContain('$error'); 16 | expect(paragraph.getText()).toContain('$name'); 17 | expect(paragraph.getText()).toContain('$valid'); 18 | expect(paragraph.getText()).toContain('$invalid'); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/fragment.spec.js: -------------------------------------------------------------------------------- 1 | describe('fragment', function () { 2 | 3 | it('should be allow binding data to exposed fragment data', function () { 4 | browser.get('/bonita/preview/page/no-app-selected/pageWithFragment/'); 5 | 6 | $('pb-fragment-person input').sendKeys(' & colin'); 7 | 8 | expect($('pb-text p').getText()).toEqual('Hello vincent & colin'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/image.spec.js: -------------------------------------------------------------------------------- 1 | describe('image', function() { 2 | 3 | beforeEach(function() { 4 | browser.get('/bonita/preview/page/no-app-selected/image/'); 5 | }); 6 | 7 | it('should display a an image', function() { 8 | var images = $$('pb-image img'); 9 | 10 | expect(images.get(0).getAttribute('src')).toBe("http://localhost:8086/bonita/preview/page/no-app-selected/image/assets/img/bonitaLogo.png"); 11 | expect(images.get(0).getAttribute('alt')).toContain("Bonita Logo"); 12 | expect(images.get(1).getAttribute('src')).toBe("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSc7PIQ0-qveL_4Q2Wwl8xkaT-OnRsAewpUOHutYtZlhVBvjwJ3"); 13 | expect(images.get(1).getAttribute('alt')).toContain("a test"); 14 | 15 | }); 16 | 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/tabs-container.spec.js: -------------------------------------------------------------------------------- 1 | describe('tabsContainer', function () { 2 | 3 | beforeEach(function () { 4 | browser.get('/bonita/preview/page/no-app-selected/tabsContainer/'); 5 | }); 6 | it('should display 1 tabsContainers with 2 tabs', function () { 7 | 8 | var navTabs = element.all(by.css('.nav-tabs li')); 9 | expect(navTabs.count()).toBe(2); 10 | navTabs.first().click(); 11 | expect(element(by.css('.first-tab-content')).isDisplayed()).toBe(true); 12 | expect(element(by.css('.second-tab-content')).isPresent()).toBe(false); 13 | 14 | navTabs.last().click(); 15 | expect(element(by.css('.first-tab-content')).isPresent()).toBe(false); 16 | expect(element(by.css('.second-tab-content')).isDisplayed()).toBe(true); 17 | 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/src/test/spec/pages/textarea.spec.js: -------------------------------------------------------------------------------- 1 | describe('textarea', function() { 2 | 3 | beforeEach(function() { 4 | browser.get('/bonita/preview/page/no-app-selected/textarea/'); 5 | }); 6 | 7 | it('should display a value and update it', function() { 8 | var textareas = $$('pb-textarea textarea'); 9 | 10 | expect(textareas.get(0).getAttribute('value')).toBe("Here is the preloaded text"); 11 | expect(textareas.get(1).getAttribute('value')).toBe("Here is the preloaded text"); 12 | 13 | textareas.get(0).clear(); 14 | textareas.get(0).sendKeys('This is the new value'); 15 | 16 | expect(textareas.get(1).getAttribute('value')).toBe("This is the new value"); 17 | }); 18 | 19 | 20 | }); 21 | --------------------------------------------------------------------------------