You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by po...@apache.org on 2023/09/21 14:30:03 UTC

[incubator-kie-tools-temporary-rnd-do-not-use] 11/27: NO-ISSUE: merge main into KOGITO-8015-feature-preview (#1529)

This is an automated email from the ASF dual-hosted git repository.

porcelli pushed a commit to branch KOGITO-8015-feature-preview
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools-temporary-rnd-do-not-use.git

commit 1ffcadda8811af01ac6efadb4d95eafa9f922e17
Author: Fabrizio Antonangeli <fa...@gmail.com>
AuthorDate: Tue Mar 21 00:01:51 2023 +0100

    NO-ISSUE: merge main into KOGITO-8015-feature-preview (#1529)
    
    Signed-off-by: dependabot[bot] <su...@github.com>
    Co-authored-by: Handreyrc <47...@users.noreply.github.com>
    Co-authored-by: Roger Martinez <ro...@gmail.com>
    Co-authored-by: Tiago Bento <15...@users.noreply.github.com>
    Co-authored-by: Kumar Aditya Raj <se...@gmail.com>
    Co-authored-by: Kirill Gaevskii <kg...@redhat.com>
    Co-authored-by: William Antônio Siqueira <wi...@gmail.com>
    Co-authored-by: Jaime Enriquez <ja...@inodesoft.com>
    Co-authored-by: Luiz João Motta <lu...@gmail.com>
    Co-authored-by: Zbyněk Drápela <61...@users.noreply.github.com>
    Co-authored-by: Manaswini Das <da...@gmail.com>
    Co-authored-by: Pere Fernández <pe...@users.noreply.github.com>
    Co-authored-by: Paulo Martins <pa...@gmail.com>
    Co-authored-by: Guilherme Caponetto <63...@users.noreply.github.com>
    Co-authored-by: Thiago Lugli <th...@users.noreply.github.com>
    Co-authored-by: Daniel J dos Santos <da...@users.noreply.github.com>
    Co-authored-by: Daniel J dos Santos <da...@ibm.com>
    Co-authored-by: Lubo Terifaj <lu...@gmail.com>
    Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
    Co-authored-by: Barbora Kapustova (Siskova) <ba...@users.noreply.github.com>
    Co-authored-by: Saravana Balaji Srinivasan <40...@users.noreply.github.com>
    Co-authored-by: Bai Xiaofeng <bx...@gmail.com>
    Co-authored-by: Kbowers <92...@users.noreply.github.com>
    Co-authored-by: Kennedy Bowers <ke...@ibm.com>
    Co-authored-by: Ajay Jaganathan <36...@users.noreply.github.com>
    Co-authored-by: Jan Stastny <st...@gmail.com>
    Co-authored-by: jstastny-cz <ja...@ibm.com>
    Co-authored-by: Tiago <ti...@gmail.com>
---
 .github/workflows/release_build.yml                |     4 +-
 .../base64png-editor-vscode-extension/package.json |     2 +-
 examples/base64png-editor/src/Base64PngEditor.tsx  |     6 +-
 examples/commit-message-validation-service/go.mod  |     8 +-
 examples/commit-message-validation-service/go.sum  |    15 +-
 .../todo-list-view-vscode-extension/package.json   |     2 +-
 examples/uniforms-patternfly/src/App.tsx           |     4 +-
 examples/webapp/src/App.tsx                        |     4 +-
 examples/webapp/src/Home.tsx                       |     3 +-
 .../src/Pages/Base64Png/Base64PngGallery.tsx       |     4 +-
 .../webapp/src/Pages/Base64Png/Base64PngPage.tsx   |     2 +-
 .../webapp/src/Pages/KogitoEditors/BpmnPage.tsx    |     2 +-
 .../webapp/src/Pages/KogitoEditors/DmnPage.tsx     |     2 +-
 .../webapp/src/Pages/KogitoEditors/Sidebar.tsx     |     3 +-
 .../Angular/PingPongAngularDivViewsPage.tsx        |     2 +-
 .../Angular/PingPongAngularIFrameViewsPage.tsx     |     2 +-
 .../PingPong/Mixed/PingPongMixedViewsPage.tsx      |     2 +-
 .../PingPong/React/PingPongReactDivViewsPage.tsx   |     2 +-
 .../React/PingPongReactIFrameViewsPage.tsx         |     2 +-
 .../webapp/src/Pages/PingPong/StatsSidebar.tsx     |     4 +-
 .../StandaloneEditors/DmnStandaloneEditorPage.tsx  |     2 +-
 .../SwfStandaloneDiagramOnlyEditorPage.tsx         |     2 +-
 .../StandaloneEditors/SwfStandaloneEditorPage.tsx  |     2 +-
 .../SwfStandaloneTextOnlyEditorPage.tsx            |     2 +-
 .../webapp/src/Pages/TodoList/TodoListViewPage.tsx |     4 +-
 .../boxed-expression-component/showcase/index.tsx  |     3 +-
 .../DecisionTableExpression/HitPolicySelector.tsx  |     2 +-
 .../EditExpressionMenu/DataTypeSelector.tsx        |     3 +-
 .../EditExpressionMenu/EditExpressionMenu.tsx      |     2 +-
 .../FunctionExpression/EditParameters.tsx          |     2 +-
 .../FunctionExpression/FunctionKindSelector.tsx    |     2 +-
 .../LiteralExpression/PMMLLiteralExpression.tsx    |     2 +-
 .../LogicTypeSelector/LogicTypeSelector.tsx        |     2 +-
 .../src/components/PopoverMenu/PopoverMenu.tsx     |     2 +-
 .../src/components/Table/TableHandler.tsx          |     2 +-
 .../src/components/Table/TableHandlerMenu.tsx      |     2 +-
 .../src/FilteredTable.tsx                          |     4 +-
 .../src/UniformsComponent.tsx                      |     2 +-
 .../src/VictoryChartComponent.tsx                  |     2 +-
 .../webpack.config.js                              |     4 +
 .../external/ExternalDataSetClientProvider.java    |    23 +-
 .../services/RuntimeDataSetClientServices.java     |     2 +-
 .../dashbuilder/displayer/DisplayerSettings.java   |     2 +-
 .../dataset/json/ExternalDataSetJSONParser.java    |    23 +-
 packages/eslint/.eslintrc.js                       |    21 +
 packages/i18n-common-dictionary/src/CommonI18n.ts  |     1 +
 packages/i18n-common-dictionary/src/locales/en.ts  |     1 +
 .../ImportJavaClasses/ImportJavaClassesWizard.tsx  |     5 +-
 .../ImportJavaClassesWizardFieldListTable.tsx      |     2 +-
 .../ImportJavaClassesWizardFirstStep.tsx           |    16 +-
 .../ImportJavaClassesWizardSecondStep.tsx          |     3 +-
 packages/kie-sandbox-image/README.md               |    85 +-
 packages/kn-plugin-workflow/env/index.js           |     2 +-
 packages/kn-plugin-workflow/go.mod                 |     2 +-
 packages/kn-plugin-workflow/go.sum                 |     4 +-
 packages/online-editor/build/defaultEnvJson.ts     |    11 +
 packages/online-editor/package.json                |     2 +
 .../src/accelerators/AcceleratorsApi.ts            |    41 +
 .../src/accelerators/AcceleratorsHooks.tsx         |   413 +
 .../src/authSessions/AuthSessionSelect.tsx         |     3 +-
 packages/online-editor/src/editor/EditorPage.tsx   |     2 +-
 .../online-editor/src/editor/EditorToolbar.tsx     |  2237 --
 .../Toolbar/Accelerators/AcceleratorIcon.tsx}      |    20 +-
 .../Toolbar/Accelerators/AcceleratorIndicator.tsx  |    63 +
 .../Toolbar/Accelerators/AcceleratorModal.tsx      |   125 +
 .../Toolbar/Accelerators/AcceleratorsDropdown.tsx  |   109 +
 .../src/editor/Toolbar/EditorToolbar.tsx           |   438 +
 .../Toolbar/EditorToolbarContextProvider.tsx       |   207 +
 .../src/editor/Toolbar/FileStatus.tsx              |   121 +
 .../src/editor/{ => Toolbar}/FileSwitcher.tsx      |   802 +-
 .../GitIntegration}/CreateGistOrSnippetModal.tsx   |    46 +-
 .../GitIntegration}/CreateGitRepositoryModal.tsx   |    35 +-
 .../GitIntegration/GitIntegrationAlerts.tsx        |   396 +
 .../GitIntegrationContextProvider.tsx              |   630 +
 .../GitIntegration}/LoadOrganizationsSelect.tsx    |    50 +-
 .../GitIntegration/PushToGitAlertActionLinks.tsx   |    90 +
 .../src/editor/Toolbar/KebabDropdown.tsx           |    46 +
 .../editor/{ => Toolbar}/NewFileDropdownMenu.tsx   |   106 +-
 .../editor/Toolbar/Share/DownloadDropdownGroup.tsx |   112 +
 .../editor/Toolbar/Share/EmbedDropdownGroup.tsx    |    63 +
 .../src/editor/{ => Toolbar/Share}/EmbedModal.tsx  |     4 +-
 .../src/editor/Toolbar/Share/GitDropdownGroup.tsx  |   161 +
 .../src/editor/Toolbar/SyncDropdownMenu.tsx        |   279 +
 .../src/editor/Toolbar/VsCodeDropdownMenu.tsx      |   160 +
 .../src/editor/Toolbar/Workspace/Hooks.tsx         |   154 +
 .../editor/Toolbar/Workspace/WorkspaceToolbar.tsx  |   177 +
 packages/online-editor/src/env/EnvJson.ts          |     2 +
 .../EditorEnvelopeLocatorFactory.ts                |    70 +-
 .../online-editor/src/filesList/FileDataList.tsx   |   139 +-
 packages/online-editor/src/home/HomePage.tsx       |    24 +-
 packages/online-editor/src/i18n/OnlineI18n.ts      |    28 +
 packages/online-editor/src/i18n/locales/en.ts      |    37 +-
 .../importFromUrl/ImportFromUrlHomePageCard.tsx    |     3 +-
 .../src/pageTemplate/OnlineEditorPage.tsx          |     3 +-
 .../components/GitStatusIndicatorActions.tsx       |   479 +
 .../src/workspace/components/PromiseModal.tsx      |    30 +-
 .../workspace/components/WorkspaceCommitModal.tsx  |    12 +-
 .../components/WorkspaceStatusIndicator.tsx        |   286 +-
 ...ontextProviderWithCustomCommitMessagesModal.tsx |    17 +-
 packages/online-editor/static/resources/style.css  |    70 +-
 .../it-tests/e2e/CreateNewFile.cy.ts               |     4 +-
 packages/serverless-logic-web-tools/package.json   |     2 +
 .../src/editor/EditorPage.tsx                      |    13 +-
 .../src/editor/EditorPageErrorPage.tsx             |     2 +-
 .../src/editor/FileSwitcher.tsx                    |    16 +-
 .../src/editor/NewFileDropdownMenu.tsx             |    20 +-
 .../src/editor/api/WebToolsSwfLanguageService.ts   |    23 +-
 .../src/homepage/breadcrumb/HomepageBreadcrumb.tsx |     2 +-
 .../src/homepage/pageTemplate/OnlineEditorPage.tsx |    15 +-
 .../src/homepage/uiNav/HomePageNav.tsx             |     2 +-
 .../KieSandboxExtendedServicesSettings.tsx         |     4 +-
 .../src/settings/github/GitHubSettings.tsx         |     5 +-
 .../src/settings/kafka/ApacheKafkaSettings.tsx     |     4 +-
 .../src/settings/openshift/OpenShiftSettings.tsx   |     4 +-
 .../serviceAccount/ServiceAccountSettings.tsx      |     4 +-
 .../serviceRegistry/ServiceRegistrySettings.tsx    |     4 +-
 .../src/settings/uiNav/SettingsPageNav.tsx         |     2 +-
 .../components/WorkspaceStatusIndicator.tsx        |     2 +-
 .../static/resources/style.css                     |     4 +
 .../common/stunner/sw/autolayout/AutoLayout.java   |   149 +-
 .../stunner/sw/resources/i18n/SWConstants.java     |    60 +
 .../sw/resources/i18n/SWConstants.properties       |    22 +
 .../stunner/sw/autolayout/AutoLayoutTest.java      |    13 +-
 .../sw/client/CanvasShortcutsControlImpl.java      |     4 +-
 .../common/stunner/sw/client/ShapeFactory.java     |     9 +-
 .../sw/client/shapes/CallbackStateShape.java       |    41 +-
 .../common/stunner/sw/client/shapes/EndShape.java  |     8 +-
 .../stunner/sw/client/shapes/EndShapeView.java     |     4 +-
 .../stunner/sw/client/shapes/EventStateShape.java  |    33 +-
 .../sw/client/shapes/ForEachStateShape.java        |    38 +-
 .../stunner/sw/client/shapes/HasActions.java       |    79 +
 .../stunner/sw/client/shapes/HasDataFilter.java    |    49 +
 .../stunner/sw/client/shapes/HasTranslation.java}  |    11 +-
 .../stunner/sw/client/shapes/InjectStateShape.java |    28 +-
 .../sw/client/shapes/OperationStateShape.java      |    44 +-
 .../sw/client/shapes/ParallelStateShape.java       |    30 +-
 .../sw/client/shapes/ServerlessWorkflowShape.java  |    25 +-
 .../stunner/sw/client/shapes/SleepStateShape.java  |    17 +-
 .../stunner/sw/client/shapes/StartShape.java       |     8 +-
 .../stunner/sw/client/shapes/StartShapeView.java   |     4 +-
 .../stunner/sw/client/shapes/StateShape.java       |    41 +-
 .../stunner/sw/client/shapes/StateShapeView.java   |    21 +-
 .../stunner/sw/client/shapes/SwitchStateShape.java |    30 +-
 .../stunner/sw/client/shapes/TransitionShape.java  |     4 +-
 .../sw/client/shapes/icons/BottomDepiction.java    |    63 +
 .../stunner/sw/client/shapes/icons/CornerIcon.java |    29 +-
 .../stunner/sw/client/shapes/icons/IconPath.java   |     3 +
 .../sw/client/shapes/icons/IconPosition.java       |     1 +
 .../stunner/sw/client/shapes/HasActionsTest.java   |   182 +
 .../sw/client/shapes/HasDataFilterTest.java        |   123 +
 .../client/shapes/HasTranslationGeneralTest.java   |    66 +
 .../stunner/sw/client/shapes/StateShapeTest.java   |    20 +-
 .../sw/client/selenium/SWEditorSeleniumIT.java     |   164 +-
 .../stunner/sw/client/selenium/LoanBroker.sw.json  |   215 +
 .../serverless-workflow-jq-expressions/README.md   |     1 +
 .../env/index.js}                                  |    15 +-
 .../jest.config.js}                                |    41 +-
 .../package.json                                   |    10 +-
 .../src/api/JqExpressionReadSchemas.ts}            |    13 +-
 .../src/api}/index.ts                              |    10 +-
 .../src/api/types.ts}                              |    13 +-
 .../src/impl/JqExpressionReadSchemasImpl.ts        |    89 +
 .../src/impl}/index.ts                             |     9 +-
 .../src/utils/JqBuiltInFunctions.ts                |   575 +
 .../src/utils}/index.ts                            |    10 +-
 .../src/utils/utils.ts}                            |    23 +-
 .../tests/JqExpressionReadSchemasImpl.test.ts      |    72 +
 .../tests/mockSchema.ts                            |    20 +
 .../tests/utils.test.ts}                           |    22 +-
 .../tsconfig.json                                  |     8 +
 .../package.json                                   |     1 +
 .../empty-workflow-completions.ts}                 |    21 +-
 .../src/assets/code-completions/index.ts           |     1 +
 .../src/channel/SwfLanguageService.ts              |    95 +-
 .../channel/SwfLanguageServiceCodeCompletion.ts    |   296 +-
 .../src/channel/SwfYamlLanguageService.ts          |    16 +-
 .../src/channel/types.ts                           |    14 +
 .../tests/SwfJqExpressionTestUtils.ts              |    80 +
 .../tests/SwfJsonLanguageService.test.ts           |   378 +-
 .../tests/SwfLanguageServiceConfigs.ts             |     8 +-
 .../tests/SwfYamlLanguageService.test.ts           |   301 +-
 .../SwfJsonLanguageService.test.ts.snap            | 20886 ++++++++++++++++++-
 .../SwfYamlLanguageService.test.ts.snap            | 17330 ++++++++++++++-
 .../tests/findNodesAtLocation.test.ts              |    14 +-
 .../tests/getNodeFormat.test.ts                    |     4 +-
 .../tests/matchNodeWithLocation.test.ts            |    15 +-
 .../tests/nodeUpUntilType.test.ts                  |     4 +-
 .../tests/refValidations.test.ts                   |     3 +
 .../tests/testUtils.ts                             |     1 -
 .../package.json                                   |     1 +
 .../src/api/types.ts                               |     3 +
 .../src/channel/parsers/impl/asyncapi/asyncapi.ts  |     1 -
 .../parsers/impl/camelRoutes/CamelRoutesParser.ts  |    30 +
 .../parsers/impl/camelRoutes/camelRoutes.ts        |    94 +
 .../src/channel/parsers/impl/camelRoutes/types.ts  |    52 +
 .../parsers/impl/jsonschema/JsonSchemaParser.ts}   |    16 +-
 .../channel/parsers/impl/jsonschema/jsonschema.ts  |    71 +
 .../src/channel/parsers/impl/openapi/openapi.ts    |    20 +-
 .../src/channel/parsers/index.ts                   |     2 +
 .../src/channel/parsers/parseApiContent.ts         |    15 +-
 .../parsers/camelRoutes/camelRoutes.test.ts        |    79 +
 .../tests/channel/parsers/examples/expression.json |    20 +
 .../channel/parsers/examples/numberToWords.yaml    |    22 +
 .../channel/parsers/examples/sendMessage.yaml      |     7 +
 .../channel/parsers/jsonschema/jsonschema.test.ts  |    62 +
 .../tests/channel/parsers/parseApiContent.test.ts  |     9 +-
 .../package.json                                   |     1 +
 .../getLanguageServiceChannelApi.ts                |    22 +
 .../dev-webapp/App.tsx                             |   108 +-
 .../dev-webapp/HistoryButtons.tsx                  |    72 +-
 .../channel/DevWebAppSwfLanguageService.ts}        |    23 +-
 .../channel/SwfLanguageServiceChannelApiImpl.ts    |    39 +
 .../channel/SwfTextEditorChannelApiImpl.ts         |   156 +
 .../serverless-workflow-text-editor/package.json   |     1 +
 .../textEditor/augmentation/completion/index.ts    |     4 +-
 .../expressions/types/list/AddListRowCommand.java  |     4 +-
 .../common/dmn/client/graph/DMNSizeHandler.java    |    41 +
 .../client/widgets/toolbar/DMNGraphProcessor.java  |   194 +-
 .../widgets/toolbar/DMNSugiyamaLayoutService.java  |    16 +-
 .../types/list/AddListRowCommandTest.java          |     4 +-
 .../dmn/client/graph/DMNSizeHandlerTest.java       |    75 +
 .../widgets/toolbar/DMNGraphProcessorTest.java     |   414 +-
 .../client/editor/AbstractDMNDiagramEditor.java    |     7 +-
 .../editor/AbstractDMNDiagramEditorTest.java       |     6 +-
 .../showcase/client/editor/DMNDiagramEditor.java   |     4 +-
 .../dmn13-expected/0082-feel-coercion.dmn          |  2061 +-
 .../dmn13-expected/0085-decision-services.dmn      |  2627 +--
 .../dmn13-expected/0088-no-decision-logic.dmn      |   485 +-
 .../graph/processing/layout/GraphProcessor.java    |    77 +
 .../graph/processing/layout/LayoutExecutor.java    |     3 +-
 .../graph/processing/layout/LayoutService.java     |     7 +
 .../{LayoutExecutor.java => SizeHandler.java}      |    12 +-
 .../layout/sugiyama/step04/VertexPositioning.java  |     8 +-
 .../client/components/layout/LayoutHelper.java     |     5 +-
 .../layout/OpenDiagramLayoutExecutor.java          |    32 +-
 .../components/layout/UndoableLayoutExecutor.java  |     3 +-
 .../client/components/layout/LayoutHelperTest.java |     4 +-
 .../layout/UndoableLayoutExecutorTest.java         |     6 +-
 .../processing/layout/sugiyama/LayeredGraph.java   |     3 +-
 .../layout/sugiyama/SugiyamaLayoutService.java     |   102 +-
 .../sugiyama/step04/DefaultVertexPositioning.java  |    83 +-
 .../graph/processing/layout/IntegrationTests.java  |     9 +-
 .../layout/sugiyama/SugiyamaLayoutServiceTest.java |     6 +-
 .../step04/DefaultVertexPositioningTest.java       |   206 +-
 .../converters/tostunner/DefinitionResolver.java   |    19 +
 .../processes/BaseRootProcessConverter.java        |     2 +-
 .../marshall/service/BPMNClientMarshalling.java    |     6 +-
 .../tostunner/DefinitionResolverTest.java          |    14 +
 packages/uniforms-patternfly/src/BaseForm.tsx      |     2 +-
 packages/unitables/src/Unitables.tsx               |     2 +-
 packages/vscode-extension-backend/package.json     |     2 +-
 packages/vscode-extension-bpmn-editor/package.json |     2 +-
 .../.mocharc.json                                  |     7 +
 .../CHANGELOG.md                                   |    13 +
 .../dashbuilder-editor-extension-smoke.test.ts     |    78 +
 .../it-tests/helpers/VSCodeTestHelper.ts           |   219 +
 .../dashbuilder/DashbuilderEditorTestHelper.ts     |    50 +
 .../DashbuilderTextEditorTestHelper.ts}            |    16 +-
 .../smoke-test/empty-dashbuilder-example.dash.yaml |     0
 .../smoke-test/simple-dashbuilder-example.dash.yml |    36 +
 .../it-tests/settings.json                         |     2 +-
 .../mocha-reporter-config.json                     |    15 +
 .../package.json                                   |    19 +-
 .../tsconfig.it-tests.json                         |    11 +
 packages/vscode-extension-dmn-editor/package.json  |     2 +-
 .../vscode-extension-kie-ba-bundle/package.json    |     2 +-
 .../vscode-extension-kogito-bundle/package.json    |     2 +-
 .../it-tests/settings.json                         |     1 +
 .../package.json                                   |     6 +-
 packages/vscode-extension-pmml-editor/package.json |     2 +-
 .../package.json                                   |     2 +-
 .../CHANGELOG.md                                   |    11 +
 .../emptyworkflow_autocompletion.sw.json           |     0
 .../emptyworkflow_autocompletion.sw.json.result    |    11 +
 ...orkflow-editor-extension-autocompletion.test.ts |    24 +-
 ...low-editor-extension-diagram-navigation.test.ts |     6 +-
 .../it-tests/settings.json                         |     1 +
 .../package.json                                   |    12 +-
 .../builtInVsCodeEditorSwfContributions.ts         |     3 +-
 .../src/extension/configuration.ts                 |    24 +
 .../fs/JqExpressionsReadSchemaFromFs.ts            |    62 +
 .../languageService/VsCodeSwfLanguageService.ts    |    55 +-
 .../SwfServiceCatalogSupportActions.ts             |    15 +-
 .../fs/FsWatchingServiceCatalogRelativeStore.ts    |   113 +-
 .../it-tests/settings.json                         |     1 +
 packages/vscode-extension-yard-editor/package.json |     6 +-
 .../src/context/WorkspacesContext.tsx              |    24 +-
 .../src/context/WorkspacesContextProvider.tsx      |    78 +-
 .../src/hooks/WorkspaceFileHooks.tsx               |     3 +
 .../workspaces-git-fs/src/hooks/WorkspaceHooks.tsx |    38 +-
 .../workspaces-git-fs/src/services/GitService.tsx  |    77 +-
 .../src/services/WorkspaceDescriptorService.tsx    |     5 -
 .../src/worker/WorkspacesWorkerApiImpl.ts          |   127 +-
 .../src/worker/api/WorkspaceBroadcastEvents.ts     |     4 +-
 .../src/worker/api/WorkspacesWorkerGitApi.ts       |    25 +-
 packages/yard-editor/src/editor/YardEditor.tsx     |     8 +-
 packages/yard-editor/src/uiEditor/YardUIEditor.tsx |    19 +-
 pnpm-lock.yaml                                     |   604 +-
 repo/graph.dot                                     |     6 +-
 repo/graph.json                                    |     9 +-
 300 files changed, 53517 insertions(+), 6607 deletions(-)

diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml
index 9ff10c30c6..2007fdd061 100644
--- a/.github/workflows/release_build.yml
+++ b/.github/workflows/release_build.yml
@@ -184,7 +184,7 @@ jobs:
       KIE_SANDBOX__imageAccount: "kie-tools"
       KIE_SANDBOX__imageName: "kie-sandbox-image"
       KIE_SANDBOX__imageBuildTags: "latest ${{ inputs.tag }}"
-      ONLINE_EDITOR__buildInfo: ""
+      ONLINE_EDITOR__buildInfo: "${{ inputs.tag }}"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlLinux: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_linux_${{ inputs.tag }}.tar.gz"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlMacOs: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_macos_${{ inputs.tag }}.dmg"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlWindows: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_windows_${{ inputs.tag }}.exe"
@@ -384,7 +384,7 @@ jobs:
 
   online_editor:
     env:
-      ONLINE_EDITOR__buildInfo: ""
+      ONLINE_EDITOR__buildInfo: "${{ inputs.tag }}"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlLinux: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_linux_${{ inputs.tag }}.tar.gz"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlMacOs: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_macos_${{ inputs.tag }}.dmg"
       ONLINE_EDITOR__kieSandboxExtendedServicesDownloadUrlWindows: "https://github.com/kiegroup/kie-tools/releases/download/${{ inputs.tag }}/kie_sandbox_extended_services_windows_${{ inputs.tag }}.exe"
diff --git a/examples/base64png-editor-vscode-extension/package.json b/examples/base64png-editor-vscode-extension/package.json
index a0e10c5119..adfdd211be 100644
--- a/examples/base64png-editor-vscode-extension/package.json
+++ b/examples/base64png-editor-vscode-extension/package.json
@@ -35,7 +35,7 @@
     "@kie-tools/root-env": "workspace:*",
     "@kie-tools/tsconfig": "workspace:*",
     "@types/vscode": "^1.66.0",
-    "@vscode/vsce": "^2.15.0",
+    "@vscode/vsce": "^2.18.0",
     "rimraf": "^3.0.2",
     "typescript": "^4.4.2",
     "webpack": "^5.36.2",
diff --git a/examples/base64png-editor/src/Base64PngEditor.tsx b/examples/base64png-editor/src/Base64PngEditor.tsx
index 426567c628..cc9efd7c55 100644
--- a/examples/base64png-editor/src/Base64PngEditor.tsx
+++ b/examples/base64png-editor/src/Base64PngEditor.tsx
@@ -17,7 +17,11 @@
 import * as React from "react";
 import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
 import { EditorApi, KogitoEditorEnvelopeContextType } from "@kie-tools-core/editor/dist/api";
-import { EmptyState, EmptyStateIcon, Nav, NavItem, NavList, Page, Switch, Title } from "@patternfly/react-core";
+import { EmptyState, EmptyStateIcon } from "@patternfly/react-core/dist/js/components/EmptyState";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Page } from "@patternfly/react-core/dist/js/components/Page";
+import { Switch } from "@patternfly/react-core/dist/js/components/Switch";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
 import { DEFAULT_RECT } from "@kie-tools-core/guided-tour/dist/api";
 import CubesIcon from "@patternfly/react-icons/dist/js/icons/cubes-icon";
 import "./styles.scss";
diff --git a/examples/commit-message-validation-service/go.mod b/examples/commit-message-validation-service/go.mod
index d13caea2e9..6a934889d1 100644
--- a/examples/commit-message-validation-service/go.mod
+++ b/examples/commit-message-validation-service/go.mod
@@ -20,10 +20,10 @@ require (
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
 	github.com/ugorji/go/codec v1.2.7 // indirect
-	golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
-	golang.org/x/net v0.4.0 // indirect
-	golang.org/x/sys v0.3.0 // indirect
-	golang.org/x/text v0.5.0 // indirect
+	golang.org/x/crypto v0.1.0 // indirect
+	golang.org/x/net v0.7.0 // indirect
+	golang.org/x/sys v0.5.0 // indirect
+	golang.org/x/text v0.7.0 // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 )
diff --git a/examples/commit-message-validation-service/go.sum b/examples/commit-message-validation-service/go.sum
index 5e818b70f5..0270bb7889 100644
--- a/examples/commit-message-validation-service/go.sum
+++ b/examples/commit-message-validation-service/go.sum
@@ -67,26 +67,27 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
 github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
-golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/examples/todo-list-view-vscode-extension/package.json b/examples/todo-list-view-vscode-extension/package.json
index f22dfa6049..e2c73d5e44 100644
--- a/examples/todo-list-view-vscode-extension/package.json
+++ b/examples/todo-list-view-vscode-extension/package.json
@@ -33,7 +33,7 @@
     "@kie-tools/root-env": "workspace:*",
     "@kie-tools/tsconfig": "workspace:*",
     "@types/vscode": "^1.66.0",
-    "@vscode/vsce": "^2.15.0",
+    "@vscode/vsce": "^2.18.0",
     "rimraf": "^3.0.2",
     "typescript": "^4.4.2",
     "webpack": "^5.36.2",
diff --git a/examples/uniforms-patternfly/src/App.tsx b/examples/uniforms-patternfly/src/App.tsx
index 1edc8c61c0..fd21a4408e 100644
--- a/examples/uniforms-patternfly/src/App.tsx
+++ b/examples/uniforms-patternfly/src/App.tsx
@@ -18,7 +18,9 @@ import "@patternfly/react-core/dist/styles/base.css";
 import * as React from "react";
 import "../static/resources/styles.css";
 import { useState } from "react";
-import { Brand, Nav, NavItem, NavList, Page, PageHeader } from "@patternfly/react-core";
+import { Brand } from "@patternfly/react-core/dist/js/components/Brand";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Page, PageHeader } from "@patternfly/react-core/dist/js/components/Page";
 import { Form } from "./Form";
 
 export enum SchemaType {
diff --git a/examples/webapp/src/App.tsx b/examples/webapp/src/App.tsx
index ddf0de2c78..5c841d4085 100644
--- a/examples/webapp/src/App.tsx
+++ b/examples/webapp/src/App.tsx
@@ -17,7 +17,9 @@
 import "@patternfly/react-core/dist/styles/base.css";
 import * as React from "react";
 import { useEffect, useState } from "react";
-import { Brand, Nav, NavItem, NavList, Page, PageHeader } from "@patternfly/react-core";
+import { Brand } from "@patternfly/react-core/dist/js/components/Brand";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Page, PageHeader } from "@patternfly/react-core/dist/js/components/Page";
 import { HashRouter as Router, Link, Route, Switch } from "react-router-dom";
 import { Base64PngPage } from "./Pages/Base64Png/Base64PngPage";
 import { BpmnPage } from "./Pages/KogitoEditors/BpmnPage";
diff --git a/examples/webapp/src/Home.tsx b/examples/webapp/src/Home.tsx
index 76f394f426..7c5ba9f840 100644
--- a/examples/webapp/src/Home.tsx
+++ b/examples/webapp/src/Home.tsx
@@ -15,7 +15,8 @@
  */
 
 import * as React from "react";
-import { Page, PageSection, Text, TextContent } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
+import { Text, TextContent } from "@patternfly/react-core/dist/js/components/Text";
 
 export function Home() {
   return (
diff --git a/examples/webapp/src/Pages/Base64Png/Base64PngGallery.tsx b/examples/webapp/src/Pages/Base64Png/Base64PngGallery.tsx
index c1b42ff7ce..585cffcdd2 100644
--- a/examples/webapp/src/Pages/Base64Png/Base64PngGallery.tsx
+++ b/examples/webapp/src/Pages/Base64Png/Base64PngGallery.tsx
@@ -16,7 +16,9 @@
 
 import * as React from "react";
 import { useCallback, useEffect, useState } from "react";
-import { Nav, NavItem, Title, Card, NavList } from "@patternfly/react-core";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
+import { Card } from "@patternfly/react-core/dist/js/components/Card";
 import { EmbeddedEditorFile } from "@kie-tools-core/editor/dist/channel";
 
 const samplePaths = [
diff --git a/examples/webapp/src/Pages/Base64Png/Base64PngPage.tsx b/examples/webapp/src/Pages/Base64Png/Base64PngPage.tsx
index dc745abdf9..4548b4562b 100644
--- a/examples/webapp/src/Pages/Base64Png/Base64PngPage.tsx
+++ b/examples/webapp/src/Pages/Base64Png/Base64PngPage.tsx
@@ -18,7 +18,7 @@ import { ChannelType, EnvelopeContentType } from "@kie-tools-core/editor/dist/ap
 import * as React from "react";
 import { EditorEnvelopeLocator, EnvelopeMapping } from "@kie-tools-core/editor/dist/api";
 import { useMemo, useState } from "react";
-import { Page } from "@patternfly/react-core";
+import { Page } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedEditor } from "@kie-tools-core/editor/dist/embedded";
 import { EmbeddedEditorFile } from "@kie-tools-core/editor/dist/channel";
 import { Base64PngGallery } from "./Base64PngGallery";
diff --git a/examples/webapp/src/Pages/KogitoEditors/BpmnPage.tsx b/examples/webapp/src/Pages/KogitoEditors/BpmnPage.tsx
index a38503343d..d9750f9790 100644
--- a/examples/webapp/src/Pages/KogitoEditors/BpmnPage.tsx
+++ b/examples/webapp/src/Pages/KogitoEditors/BpmnPage.tsx
@@ -18,7 +18,7 @@ import { ChannelType, EnvelopeContentType } from "@kie-tools-core/editor/dist/ap
 import * as React from "react";
 import { EditorEnvelopeLocator, EnvelopeMapping } from "@kie-tools-core/editor/dist/api";
 import { useMemo, useState } from "react";
-import { Page } from "@patternfly/react-core";
+import { Page } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedEditor, useEditorRef } from "@kie-tools-core/editor/dist/embedded";
 import { EmbeddedEditorFile } from "@kie-tools-core/editor/dist/channel";
 import { Sidebar } from "./Sidebar";
diff --git a/examples/webapp/src/Pages/KogitoEditors/DmnPage.tsx b/examples/webapp/src/Pages/KogitoEditors/DmnPage.tsx
index ba228d153d..0629922dd7 100644
--- a/examples/webapp/src/Pages/KogitoEditors/DmnPage.tsx
+++ b/examples/webapp/src/Pages/KogitoEditors/DmnPage.tsx
@@ -18,7 +18,7 @@ import { ChannelType, EnvelopeContentType } from "@kie-tools-core/editor/dist/ap
 import * as React from "react";
 import { EditorEnvelopeLocator, EnvelopeMapping } from "@kie-tools-core/editor/dist/api";
 import { useMemo, useState } from "react";
-import { Page } from "@patternfly/react-core";
+import { Page } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedEditor, useEditorRef } from "@kie-tools-core/editor/dist/embedded";
 import { EmbeddedEditorFile } from "@kie-tools-core/editor/dist/channel";
 import { Sidebar } from "./Sidebar";
diff --git a/examples/webapp/src/Pages/KogitoEditors/Sidebar.tsx b/examples/webapp/src/Pages/KogitoEditors/Sidebar.tsx
index 601890e738..136add7b14 100644
--- a/examples/webapp/src/Pages/KogitoEditors/Sidebar.tsx
+++ b/examples/webapp/src/Pages/KogitoEditors/Sidebar.tsx
@@ -17,7 +17,8 @@
 import * as React from "react";
 import { EditorEnvelopeLocator } from "@kie-tools-core/editor/dist/api";
 import { useCallback, useRef, useState } from "react";
-import { Nav, NavItem, NavList, TextInput } from "@patternfly/react-core";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput";
 import { EmbeddedEditorRef, useDirtyState } from "@kie-tools-core/editor/dist/embedded";
 import { EmbeddedEditorFile } from "@kie-tools-core/editor/dist/channel";
 
diff --git a/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularDivViewsPage.tsx b/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularDivViewsPage.tsx
index bee3e610af..270a1a09e9 100644
--- a/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularDivViewsPage.tsx
+++ b/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularDivViewsPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useMemo, useRef } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedDivPingPong } from "@kie-tools-examples/ping-pong-view/dist/embedded";
 import { StatsSidebar } from "../StatsSidebar";
 import { pingPongEnvelopViewRenderDiv } from "@kie-tools-examples/ping-pong-view-angular/dist/wc/lib";
diff --git a/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularIFrameViewsPage.tsx b/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularIFrameViewsPage.tsx
index 46f4d709b1..79081b24f5 100644
--- a/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularIFrameViewsPage.tsx
+++ b/examples/webapp/src/Pages/PingPong/Angular/PingPongAngularIFrameViewsPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useMemo, useRef } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedIFramePingPong } from "@kie-tools-examples/ping-pong-view/dist/embedded";
 import { PingPongApi } from "@kie-tools-examples/ping-pong-view/dist/api";
 import { StatsSidebar } from "../StatsSidebar";
diff --git a/examples/webapp/src/Pages/PingPong/Mixed/PingPongMixedViewsPage.tsx b/examples/webapp/src/Pages/PingPong/Mixed/PingPongMixedViewsPage.tsx
index 4a4ce9b9e5..8e8a40937b 100644
--- a/examples/webapp/src/Pages/PingPong/Mixed/PingPongMixedViewsPage.tsx
+++ b/examples/webapp/src/Pages/PingPong/Mixed/PingPongMixedViewsPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useMemo, useRef } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedDivPingPong, EmbeddedIFramePingPong } from "@kie-tools-examples/ping-pong-view/dist/embedded";
 import { PingPongApi } from "@kie-tools-examples/ping-pong-view/dist/api";
 import { StatsSidebar } from "../StatsSidebar";
diff --git a/examples/webapp/src/Pages/PingPong/React/PingPongReactDivViewsPage.tsx b/examples/webapp/src/Pages/PingPong/React/PingPongReactDivViewsPage.tsx
index c57701d3e6..26e2de395b 100644
--- a/examples/webapp/src/Pages/PingPong/React/PingPongReactDivViewsPage.tsx
+++ b/examples/webapp/src/Pages/PingPong/React/PingPongReactDivViewsPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useMemo, useRef } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedDivPingPong } from "@kie-tools-examples/ping-pong-view/dist/embedded";
 import { PingPongApi } from "@kie-tools-examples/ping-pong-view/dist/api";
 import { pingPongEnvelopViewRenderDiv } from "@kie-tools-examples/ping-pong-view-react";
diff --git a/examples/webapp/src/Pages/PingPong/React/PingPongReactIFrameViewsPage.tsx b/examples/webapp/src/Pages/PingPong/React/PingPongReactIFrameViewsPage.tsx
index 172377dd90..e87b24be16 100644
--- a/examples/webapp/src/Pages/PingPong/React/PingPongReactIFrameViewsPage.tsx
+++ b/examples/webapp/src/Pages/PingPong/React/PingPongReactIFrameViewsPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useMemo, useRef } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import { EmbeddedIFramePingPong } from "@kie-tools-examples/ping-pong-view/dist/embedded";
 import { PingPongApi } from "@kie-tools-examples/ping-pong-view/dist/api";
 import { StatsSidebar } from "../StatsSidebar";
diff --git a/examples/webapp/src/Pages/PingPong/StatsSidebar.tsx b/examples/webapp/src/Pages/PingPong/StatsSidebar.tsx
index faf0d7c3eb..9bb3db22c7 100644
--- a/examples/webapp/src/Pages/PingPong/StatsSidebar.tsx
+++ b/examples/webapp/src/Pages/PingPong/StatsSidebar.tsx
@@ -16,7 +16,9 @@
 
 import * as React from "react";
 import { useState, useEffect } from "react";
-import { Label, Nav, NavItem, NavList, Title } from "@patternfly/react-core";
+import { Label } from "@patternfly/react-core/dist/js/components/Label";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
 
 interface Props {
   lastPing: string;
diff --git a/examples/webapp/src/Pages/StandaloneEditors/DmnStandaloneEditorPage.tsx b/examples/webapp/src/Pages/StandaloneEditors/DmnStandaloneEditorPage.tsx
index 346057e875..ee3530897b 100644
--- a/examples/webapp/src/Pages/StandaloneEditors/DmnStandaloneEditorPage.tsx
+++ b/examples/webapp/src/Pages/StandaloneEditors/DmnStandaloneEditorPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useEffect, useRef } from "react";
-import { Page } from "@patternfly/react-core";
+import { Page } from "@patternfly/react-core/dist/js/components/Page";
 import * as DmnEditor from "@kie-tools/kie-editors-standalone/dist/dmn";
 
 export function DmnStandaloneEditorPage() {
diff --git a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneDiagramOnlyEditorPage.tsx b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneDiagramOnlyEditorPage.tsx
index 2fad41e470..67412f63c0 100644
--- a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneDiagramOnlyEditorPage.tsx
+++ b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneDiagramOnlyEditorPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useEffect, useRef, useState, useCallback } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import * as SwfEditor from "@kie-tools/serverless-workflow-standalone-editor/dist/swf";
 import { ServerlessWorkflowEmptyState } from "./SwfEditorEmptyState";
 import { StandaloneEditorApi } from "@kie-tools/serverless-workflow-standalone-editor/dist/common/Editor";
diff --git a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneEditorPage.tsx b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneEditorPage.tsx
index 856491dfd2..13ea211147 100644
--- a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneEditorPage.tsx
+++ b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneEditorPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useEffect, useRef, useState, useCallback } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import * as SwfEditor from "@kie-tools/serverless-workflow-standalone-editor/dist/swf";
 import { ServerlessWorkflowEmptyState } from "./SwfEditorEmptyState";
 import {
diff --git a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneTextOnlyEditorPage.tsx b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneTextOnlyEditorPage.tsx
index 9d579c69e0..773bd86f94 100644
--- a/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneTextOnlyEditorPage.tsx
+++ b/examples/webapp/src/Pages/StandaloneEditors/SwfStandaloneTextOnlyEditorPage.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useEffect, useRef, useState, useCallback } from "react";
-import { Page, PageSection } from "@patternfly/react-core";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
 import * as SwfEditor from "@kie-tools/serverless-workflow-standalone-editor/dist/swf";
 import { ServerlessWorkflowEmptyState } from "./SwfEditorEmptyState";
 import {
diff --git a/examples/webapp/src/Pages/TodoList/TodoListViewPage.tsx b/examples/webapp/src/Pages/TodoList/TodoListViewPage.tsx
index d625f7d32b..8d23304ead 100644
--- a/examples/webapp/src/Pages/TodoList/TodoListViewPage.tsx
+++ b/examples/webapp/src/Pages/TodoList/TodoListViewPage.tsx
@@ -16,7 +16,9 @@
 
 import * as React from "react";
 import { useCallback, useMemo, useRef, useState } from "react";
-import { Nav, NavItem, NavList, Page, PageSection, Title } from "@patternfly/react-core";
+import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav";
+import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
 import { EmbeddedTodoList, EmbeddedTodoListRef } from "@kie-tools-examples/todo-list-view/dist/embedded";
 import { useStateAsSharedValue } from "@kie-tools-core/envelope-bus/dist/hooks";
 
diff --git a/packages/boxed-expression-component/showcase/index.tsx b/packages/boxed-expression-component/showcase/index.tsx
index c4dd801878..c11fcebdbb 100644
--- a/packages/boxed-expression-component/showcase/index.tsx
+++ b/packages/boxed-expression-component/showcase/index.tsx
@@ -32,7 +32,8 @@ import {
   RelationProps,
 } from "../src/api";
 import { BoxedExpressionEditor } from "../src/components";
-import { Button, Modal } from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import { Modal } from "@patternfly/react-core/dist/js/components/Modal";
 import { PenIcon } from "@patternfly/react-icons/dist/js/icons/pen-icon";
 import "../src/components/BoxedExpressionEditor/base-no-reset-wrapped.css";
 import ReactJson from "react-json-view";
diff --git a/packages/boxed-expression-component/src/components/DecisionTableExpression/HitPolicySelector.tsx b/packages/boxed-expression-component/src/components/DecisionTableExpression/HitPolicySelector.tsx
index 9eeefa5f13..960032b464 100644
--- a/packages/boxed-expression-component/src/components/DecisionTableExpression/HitPolicySelector.tsx
+++ b/packages/boxed-expression-component/src/components/DecisionTableExpression/HitPolicySelector.tsx
@@ -19,7 +19,7 @@ import { BuiltinAggregation, getEnumKeyByEnumValue, HitPolicy } from "../../api"
 import * as React from "react";
 import { useCallback, useState } from "react";
 import { PopoverMenu } from "../PopoverMenu";
-import { Select, SelectOption, SelectVariant } from "@patternfly/react-core";
+import { Select, SelectOption, SelectVariant } from "@patternfly/react-core/dist/js/components/Select";
 import * as _ from "lodash";
 import { useBoxedExpressionEditorI18n } from "../../i18n";
 import { useBoxedExpression } from "../../context";
diff --git a/packages/boxed-expression-component/src/components/EditExpressionMenu/DataTypeSelector.tsx b/packages/boxed-expression-component/src/components/EditExpressionMenu/DataTypeSelector.tsx
index 4ede8db56b..f237a194b7 100644
--- a/packages/boxed-expression-component/src/components/EditExpressionMenu/DataTypeSelector.tsx
+++ b/packages/boxed-expression-component/src/components/EditExpressionMenu/DataTypeSelector.tsx
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-import { Divider, Select, SelectGroup, SelectOption, SelectVariant } from "@patternfly/react-core";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import { Select, SelectGroup, SelectOption, SelectVariant } from "@patternfly/react-core/dist/js/components/Select";
 import * as React from "react";
 import { useCallback, useState, useRef, useEffect } from "react";
 import { useBoxedExpressionEditorI18n } from "../../i18n";
diff --git a/packages/boxed-expression-component/src/components/EditExpressionMenu/EditExpressionMenu.tsx b/packages/boxed-expression-component/src/components/EditExpressionMenu/EditExpressionMenu.tsx
index ce01ea8a7e..3f073718fc 100644
--- a/packages/boxed-expression-component/src/components/EditExpressionMenu/EditExpressionMenu.tsx
+++ b/packages/boxed-expression-component/src/components/EditExpressionMenu/EditExpressionMenu.tsx
@@ -23,7 +23,7 @@ import { DataType, ExpressionProps } from "../../api";
 import { useBoxedExpression } from "../../context";
 import { DataTypeSelector } from "./DataTypeSelector";
 import { CogIcon } from "@patternfly/react-icons/dist/js/icons/cog-icon";
-import { Button } from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { NavigationKeysUtils } from "../common";
 
 export interface EditExpressionMenuProps {
diff --git a/packages/boxed-expression-component/src/components/FunctionExpression/EditParameters.tsx b/packages/boxed-expression-component/src/components/FunctionExpression/EditParameters.tsx
index 3cad24c345..9afc481ebf 100644
--- a/packages/boxed-expression-component/src/components/FunctionExpression/EditParameters.tsx
+++ b/packages/boxed-expression-component/src/components/FunctionExpression/EditParameters.tsx
@@ -17,7 +17,7 @@
 import "./EditParameters.css";
 import * as _ from "lodash";
 import { DataTypeSelector } from "../EditExpressionMenu";
-import { Button } from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { OutlinedTrashAltIcon } from "@patternfly/react-icons/dist/js/icons/outlined-trash-alt-icon";
 import * as React from "react";
 import { ChangeEvent, useCallback } from "react";
diff --git a/packages/boxed-expression-component/src/components/FunctionExpression/FunctionKindSelector.tsx b/packages/boxed-expression-component/src/components/FunctionExpression/FunctionKindSelector.tsx
index ca42bf5123..b1febab4ba 100644
--- a/packages/boxed-expression-component/src/components/FunctionExpression/FunctionKindSelector.tsx
+++ b/packages/boxed-expression-component/src/components/FunctionExpression/FunctionKindSelector.tsx
@@ -15,7 +15,7 @@
  */
 
 import { PopoverMenu } from "../PopoverMenu";
-import { Menu, MenuItem, MenuList } from "@patternfly/react-core";
+import { Menu, MenuItem, MenuList } from "@patternfly/react-core/dist/js/components/Menu";
 import * as _ from "lodash";
 import * as React from "react";
 import { useCallback } from "react";
diff --git a/packages/boxed-expression-component/src/components/LiteralExpression/PMMLLiteralExpression.tsx b/packages/boxed-expression-component/src/components/LiteralExpression/PMMLLiteralExpression.tsx
index 35cfd1365d..972acd3517 100644
--- a/packages/boxed-expression-component/src/components/LiteralExpression/PMMLLiteralExpression.tsx
+++ b/packages/boxed-expression-component/src/components/LiteralExpression/PMMLLiteralExpression.tsx
@@ -18,7 +18,7 @@ import "./PMMLLiteralExpression.css";
 import * as React from "react";
 import { useCallback, useRef, useState } from "react";
 import { PMMLLiteralExpressionProps } from "../../api";
-import { Select, SelectOption, SelectVariant } from "@patternfly/react-core";
+import { Select, SelectOption, SelectVariant } from "@patternfly/react-core/dist/js/components/Select";
 import * as _ from "lodash";
 import { useBoxedExpression } from "../../context";
 
diff --git a/packages/boxed-expression-component/src/components/LogicTypeSelector/LogicTypeSelector.tsx b/packages/boxed-expression-component/src/components/LogicTypeSelector/LogicTypeSelector.tsx
index 3e8345c410..529b7b12c6 100644
--- a/packages/boxed-expression-component/src/components/LogicTypeSelector/LogicTypeSelector.tsx
+++ b/packages/boxed-expression-component/src/components/LogicTypeSelector/LogicTypeSelector.tsx
@@ -37,7 +37,7 @@ import { RelationExpression } from "../RelationExpression";
 import { ContextExpression } from "../ContextExpression";
 import { useBoxedExpressionEditorI18n } from "../../i18n";
 import { PopoverMenu } from "../PopoverMenu";
-import { Menu, MenuGroup, MenuItem, MenuList } from "@patternfly/react-core";
+import { Menu, MenuGroup, MenuItem, MenuList } from "@patternfly/react-core/dist/js/components/Menu";
 import * as _ from "lodash";
 import { useContextMenuHandler } from "../../hooks";
 import { useBoxedExpression } from "../../context";
diff --git a/packages/boxed-expression-component/src/components/PopoverMenu/PopoverMenu.tsx b/packages/boxed-expression-component/src/components/PopoverMenu/PopoverMenu.tsx
index 074075b9d0..4aa5a40def 100644
--- a/packages/boxed-expression-component/src/components/PopoverMenu/PopoverMenu.tsx
+++ b/packages/boxed-expression-component/src/components/PopoverMenu/PopoverMenu.tsx
@@ -16,7 +16,7 @@
 
 import * as React from "react";
 import { useCallback, useState, useImperativeHandle } from "react";
-import { Popover } from "@patternfly/react-core";
+import { Popover } from "@patternfly/react-core/dist/js/components/Popover";
 import "./PopoverMenu.css";
 import { useBoxedExpression } from "../../context";
 import { NavigationKeysUtils } from "../common";
diff --git a/packages/boxed-expression-component/src/components/Table/TableHandler.tsx b/packages/boxed-expression-component/src/components/Table/TableHandler.tsx
index 2323044cd8..bfb6033f74 100644
--- a/packages/boxed-expression-component/src/components/Table/TableHandler.tsx
+++ b/packages/boxed-expression-component/src/components/Table/TableHandler.tsx
@@ -19,7 +19,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
 import { DataType, generateUuid, TableHandlerConfiguration, TableOperation } from "../../api";
 import * as _ from "lodash";
 import { Column, ColumnInstance, DataRecord } from "react-table";
-import { Popover } from "@patternfly/react-core";
+import { Popover } from "@patternfly/react-core/dist/js/components/Popover";
 import { TableHandlerMenu } from "./TableHandlerMenu";
 import { useBoxedExpression } from "../../context";
 import { getColumnsAtLastLevel, getColumnSearchPredicate } from "./Table";
diff --git a/packages/boxed-expression-component/src/components/Table/TableHandlerMenu.tsx b/packages/boxed-expression-component/src/components/Table/TableHandlerMenu.tsx
index d723c27f9f..93066a7b13 100644
--- a/packages/boxed-expression-component/src/components/Table/TableHandlerMenu.tsx
+++ b/packages/boxed-expression-component/src/components/Table/TableHandlerMenu.tsx
@@ -16,7 +16,7 @@
 
 import "./TableHandlerMenu.css";
 import * as React from "react";
-import { Menu, MenuGroup, MenuItem, MenuList } from "@patternfly/react-core";
+import { Menu, MenuGroup, MenuItem, MenuList } from "@patternfly/react-core/dist/js/components/Menu";
 import { AllowedOperations, GroupOperations, TableOperation } from "../../api";
 import * as _ from "lodash";
 
diff --git a/packages/dashbuilder-component-table/src/FilteredTable.tsx b/packages/dashbuilder-component-table/src/FilteredTable.tsx
index 58f4387958..e23e0c3315 100644
--- a/packages/dashbuilder-component-table/src/FilteredTable.tsx
+++ b/packages/dashbuilder-component-table/src/FilteredTable.tsx
@@ -17,7 +17,9 @@ import * as React from "react";
 import { TableComposable, Thead, Tbody, Tr, Th, Td, selectable } from "@patternfly/react-table";
 
 import { useState, useCallback, useMemo } from "react";
-import { Flex, FlexItem, Pagination, SearchInput } from "@patternfly/react-core";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Pagination } from "@patternfly/react-core/dist/js/components/Pagination";
+import { SearchInput } from "@patternfly/react-core/dist/js/components/SearchInput";
 
 const DEFAULT_PAGE = 1;
 const DEFAULT_PER_PAGE = 10;
diff --git a/packages/dashbuilder-component-uniforms/src/UniformsComponent.tsx b/packages/dashbuilder-component-uniforms/src/UniformsComponent.tsx
index 1b61877f5a..2be8ec2b90 100644
--- a/packages/dashbuilder-component-uniforms/src/UniformsComponent.tsx
+++ b/packages/dashbuilder-component-uniforms/src/UniformsComponent.tsx
@@ -18,7 +18,7 @@ import * as React from "react";
 import { ComponentController, DataSet } from "@kie-tools/dashbuilder-component-api";
 import { useState, useEffect, useCallback } from "react";
 import { Uniforms } from "./Uniforms";
-import { Alert, AlertActionCloseButton } from "@patternfly/react-core";
+import { Alert, AlertActionCloseButton } from "@patternfly/react-core/dist/js/components/Alert";
 
 interface Props {
   controller: ComponentController;
diff --git a/packages/dashbuilder-component-victory-charts/src/VictoryChartComponent.tsx b/packages/dashbuilder-component-victory-charts/src/VictoryChartComponent.tsx
index 2ef494c596..0900c2b300 100644
--- a/packages/dashbuilder-component-victory-charts/src/VictoryChartComponent.tsx
+++ b/packages/dashbuilder-component-victory-charts/src/VictoryChartComponent.tsx
@@ -18,7 +18,7 @@ import * as React from "react";
 import { ComponentController, DataSet } from "@kie-tools/dashbuilder-component-api";
 import { useState, useEffect } from "react";
 import { VictoryChart, VictoryChartProps } from "./VictoryChart";
-import { Alert } from "@patternfly/react-core";
+import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
 import { ChartType, ThemeColorType, ThemeVariantType } from "./charts/BaseChart";
 
 interface Props {
diff --git a/packages/dashbuilder-component-victory-charts/webpack.config.js b/packages/dashbuilder-component-victory-charts/webpack.config.js
index ab9cacec08..5862b64d41 100644
--- a/packages/dashbuilder-component-victory-charts/webpack.config.js
+++ b/packages/dashbuilder-component-victory-charts/webpack.config.js
@@ -19,6 +19,7 @@ const patternflyBase = require("@kie-tools-core/patternfly-base");
 const { merge } = require("webpack-merge");
 const common = require("@kie-tools-core/webpack-base/webpack.common.config");
 const HtmlWebpackPlugin = require("html-webpack-plugin");
+const CopyPlugin = require("copy-webpack-plugin");
 
 module.exports = async (env) => {
   return merge(common(env), {
@@ -30,6 +31,9 @@ module.exports = async (env) => {
         template: "./static/index.html",
         minify: false,
       }),
+      new CopyPlugin({
+        patterns: [{ from: path.resolve(__dirname, "./static/index.css"), to: "." }],
+      }),
     ],
 
     module: {
diff --git a/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/external/ExternalDataSetClientProvider.java b/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/external/ExternalDataSetClientProvider.java
index de98a704cc..29f4dab87e 100644
--- a/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/external/ExternalDataSetClientProvider.java
+++ b/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/external/ExternalDataSetClientProvider.java
@@ -162,13 +162,32 @@ public class ExternalDataSetClientProvider {
                 if (response.status == HttpResponseCodes.SC_OK) {
                     return register(def, callback, responseText, mimeType);
                 } else {
-                    return notAbleToRetrieveDataSet(def, callback);
+                    var exception = buildExceptionForResponse(responseText, response);
+                   return notAbleToRetrieveDataSet(def, callback, exception);
                 }
 
             }, error -> notAbleToRetrieveDataSet(def, callback));
-        }).catch_(e -> notAbleToRetrieveDataSet(def, callback));
+        }).catch_(e -> notAbleToRetrieveDataSet(def, callback,
+                new RuntimeException("Request not started, make sure that CORS is enabled. Message: " + e)
+        ));
     }
 
+    
+
+    private Throwable buildExceptionForResponse(String responseText, Response response) {
+        var sb = new StringBuffer("The dataset URL is unreachable with status ");
+        sb.append(response.status);
+        sb.append(" - ");
+        sb.append(response.statusText);
+
+        if (responseText != null && !responseText.trim().isEmpty()) {
+            sb.append("\n");
+            sb.append("Response Text: ");
+            sb.append(responseText);
+        }
+        return new RuntimeException(sb.toString());
+   }
+
     private IThenable<Object> register(ExternalDataSetDef def,
                                        final DataSetReadyCallback callback,
                                        final String responseText,
diff --git a/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/services/RuntimeDataSetClientServices.java b/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/services/RuntimeDataSetClientServices.java
index b6c9843083..d9ba619fba 100644
--- a/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/services/RuntimeDataSetClientServices.java
+++ b/packages/dashbuilder/dashbuilder-runtime-parent/dashbuilder-runtime-client/src/main/java/org/dashbuilder/client/services/RuntimeDataSetClientServices.java
@@ -151,7 +151,7 @@ public class RuntimeDataSetClientServices implements DataSetClientServices {
 
                     @Override
                     public boolean onError(ClientRuntimeError error) {
-                        if (loader.isEditor()) {
+                        if (loader.isEditor() || loader.isClient() ) {
                             listener.onError(error);
                         } else {
                             DomGlobal.console.debug("Error retrieving dataset from client, trying from backend");
diff --git a/packages/dashbuilder/dashbuilder-shared/dashbuilder-displayer-api/src/main/java/org/dashbuilder/displayer/DisplayerSettings.java b/packages/dashbuilder/dashbuilder-shared/dashbuilder-displayer-api/src/main/java/org/dashbuilder/displayer/DisplayerSettings.java
index acfcf33299..674a150ca0 100644
--- a/packages/dashbuilder/dashbuilder-shared/dashbuilder-displayer-api/src/main/java/org/dashbuilder/displayer/DisplayerSettings.java
+++ b/packages/dashbuilder/dashbuilder-shared/dashbuilder-displayer-api/src/main/java/org/dashbuilder/displayer/DisplayerSettings.java
@@ -379,7 +379,7 @@ public class DisplayerSettings {
     }
 
     public boolean isFilterEnabled() {
-        return parseBoolean(settings.get(getSettingPath(DisplayerAttributeDef.FILTER_ENABLED)));
+        return parseBoolean(settings.get(getSettingPath(DisplayerAttributeDef.FILTER_ENABLED))) || isFilterListeningEnabled() || isFilterNotificationEnabled();
     }
 
     public void setFilterEnabled(boolean filterEnabled) {
diff --git a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/json/ExternalDataSetJSONParser.java b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/json/ExternalDataSetJSONParser.java
index 8784fa6935..c2468679ca 100644
--- a/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/json/ExternalDataSetJSONParser.java
+++ b/packages/dashbuilder/kie-soup-dataset/kie-soup-dataset-api/src/main/java/org/dashbuilder/dataset/json/ExternalDataSetJSONParser.java
@@ -46,14 +46,13 @@ public class ExternalDataSetJSONParser {
 
     private static final String COLUMN_PREFIX = "Column ";
     private static final ColumnType DEFAULT_COLUMN_TYPE = ColumnType.LABEL;
-    
-    
+
     private Function<String, Date> dateParser;
-    
+
     public ExternalDataSetJSONParser() {
         this(s -> null);
-    }         
-    
+    }
+
     public ExternalDataSetJSONParser(Function<String, Date> dateParser) {
         super();
         this.dateParser = dateParser;
@@ -107,9 +106,13 @@ public class ExternalDataSetJSONParser {
                 }
 
             } else if (trimedJson.startsWith(ARRAY_START_TOKEN)) {
-                JsonArray dataSetArray = Json.instance().parse(json);
-                fillDataSetColumns(dataSet, dataSetArray);
-                addValues(dataSet, dataSetArray);
+                try {
+                    JsonArray dataSetArray = Json.instance().parse(json);
+                    fillDataSetColumns(dataSet, dataSetArray);
+                    addValues(dataSet, dataSetArray);
+                } catch (Exception e) {
+                    throw new IllegalArgumentException("DataSet JSON is invalid. Please check that the data is in correct format.", e);
+                }
             }
         }
         return dataSet;
@@ -215,7 +218,7 @@ public class ExternalDataSetJSONParser {
         } catch (NumberFormatException e) {
             // empty
         }
-        
+
         try {
             convertToDate(value);
             return ColumnType.DATE;
@@ -225,7 +228,7 @@ public class ExternalDataSetJSONParser {
 
         return DEFAULT_COLUMN_TYPE;
     }
-    
+
     protected Date convertToDate(String value) {
         return dateParser.apply(value);
     }
diff --git a/packages/eslint/.eslintrc.js b/packages/eslint/.eslintrc.js
index 18bf908273..ec04717598 100644
--- a/packages/eslint/.eslintrc.js
+++ b/packages/eslint/.eslintrc.js
@@ -65,5 +65,26 @@ module.exports = {
         amd: true,
       },
     },
+    {
+      files: ["*.ts", "*.tsx"],
+      rules: {
+        "no-restricted-imports": [
+          "error",
+          {
+            paths: [
+              {
+                name: "@patternfly/react-core",
+                message: "Please use specific imports from @patternfly/react-core/dist/js/**)",
+              },
+              {
+                name: "@patternfly/react-icons",
+                message: "Please use specific imports from @patternfly/react-icons/dist/js/**)",
+              },
+            ],
+            patterns: ["!@patternfly/react-core/dist/*", "!@patternfly/react-icons/dist/*"],
+          },
+        ],
+      },
+    },
   ],
 };
diff --git a/packages/i18n-common-dictionary/src/CommonI18n.ts b/packages/i18n-common-dictionary/src/CommonI18n.ts
index cf239eaf62..c9ae016c2e 100644
--- a/packages/i18n-common-dictionary/src/CommonI18n.ts
+++ b/packages/i18n-common-dictionary/src/CommonI18n.ts
@@ -18,6 +18,7 @@ import { ReferenceDictionary } from "@kie-tools-core/i18n/dist/core";
 import { names } from "./names";
 
 export type CommonDictionary = {
+  apply: string;
   available: string;
   back: string;
   cancel: string;
diff --git a/packages/i18n-common-dictionary/src/locales/en.ts b/packages/i18n-common-dictionary/src/locales/en.ts
index afd397b07c..e18efe1bb9 100644
--- a/packages/i18n-common-dictionary/src/locales/en.ts
+++ b/packages/i18n-common-dictionary/src/locales/en.ts
@@ -20,6 +20,7 @@ import { names } from "../names";
 export const en: CommonI18n = {
   names,
   terms: {
+    apply: "Apply",
     available: "Available",
     back: "Back",
     cancel: "Cancel",
diff --git a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizard.tsx b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizard.tsx
index 0d18a18cd5..a4069e741e 100644
--- a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizard.tsx
+++ b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizard.tsx
@@ -25,7 +25,10 @@ import { JavaField } from "./model/JavaField";
 import { DMNSimpleType } from "./model/DMNSimpleType";
 import { getJavaClassSimpleName } from "./model/JavaClassUtils";
 import { GWTLayerService, JavaCodeCompletionService } from "./services";
-import { Button, Modal, ModalVariant, Tooltip, Wizard } from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import { Modal, ModalVariant } from "@patternfly/react-core/dist/js/components/Modal";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Wizard } from "@patternfly/react-core/dist/js/components/Wizard";
 
 export interface ImportJavaClassesWizardProps {
   /** Service class which contains all API methods to dialog with GWT layer */
diff --git a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFieldListTable.tsx b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFieldListTable.tsx
index 4a5a439cef..08ec524d41 100644
--- a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFieldListTable.tsx
+++ b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFieldListTable.tsx
@@ -18,7 +18,7 @@ import * as React from "react";
 import "./ImportJavaClassesWizardFieldListTable.css";
 import { ExpandableRowContent, TableComposable, Tbody, Td, Tr } from "@patternfly/react-table";
 import { JavaClass } from "./model/JavaClass";
-import { Button } from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { JavaField } from "./model/JavaField";
 import { DMNSimpleType, JAVA_TO_DMN_MAP } from "./model/DMNSimpleType";
 import { getJavaClassSimpleName } from "./model/JavaClassUtils";
diff --git a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFirstStep.tsx b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFirstStep.tsx
index 9a5b8294e5..10d60ff452 100644
--- a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFirstStep.tsx
+++ b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardFirstStep.tsx
@@ -16,21 +16,19 @@
 
 import * as React from "react";
 import "./ImportJavaClassesWizardFirstStep.css";
+import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
 import {
-  Bullseye,
   DataList,
   DataListCell,
   DataListCheck,
   DataListItem,
   DataListItemRow,
-  EmptyState,
-  EmptyStateBody,
-  EmptyStateIcon,
-  SearchInput,
-  Spinner,
-  Tooltip,
-  Title,
-} from "@patternfly/react-core";
+} from "@patternfly/react-core/dist/js/components/DataList";
+import { EmptyState, EmptyStateBody, EmptyStateIcon } from "@patternfly/react-core/dist/js/components/EmptyState";
+import { SearchInput } from "@patternfly/react-core/dist/js/components/SearchInput";
+import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
 import CubesIcon from "@patternfly/react-icons/dist/js/icons/cubes-icon";
 import { useImportJavaClassesWizardI18n } from "../../i18n";
 import { useCallback, useState } from "react";
diff --git a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardSecondStep.tsx b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardSecondStep.tsx
index f4539736da..c39bf6ac44 100644
--- a/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardSecondStep.tsx
+++ b/packages/import-java-classes-component/src/components/ImportJavaClasses/ImportJavaClassesWizardSecondStep.tsx
@@ -15,7 +15,8 @@
  */
 
 import * as React from "react";
-import { Bullseye, Spinner } from "@patternfly/react-core";
+import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
+import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
 import { useCallback, useEffect } from "react";
 import { ImportJavaClassesWizardFieldListTable } from "./ImportJavaClassesWizardFieldListTable";
 import { JavaField } from "./model/JavaField";
diff --git a/packages/kie-sandbox-image/README.md b/packages/kie-sandbox-image/README.md
index e281919b19..5749026936 100644
--- a/packages/kie-sandbox-image/README.md
+++ b/packages/kie-sandbox-image/README.md
@@ -54,13 +54,14 @@ This package contains the `Containerfile/Dockerfile` and scripts to build a cont
 
    [comment]: <> (//TODO: Use EnvJson.schema.json to generate this documentation somehow.. See https://github.com/kiegroup/kie-issues/issues/16)
 
-   |                            Name                            |                                                     Description                                                      |                               Default                               |
-   | :--------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------: |
-   |            `KIE_SANDBOX_EXTENDED_SERVICES_URL`             |                              The URL that points to the KIE Sandbox Extended Services.                               | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
-   |              `KIE_SANDBOX_GIT_CORS_PROXY_URL`              |                    The URL that points to the Git CORS proxy for interacting with Git providers.                     | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
-   |        `KIE_SANDBOX_REQUIRE_CUSTOM_COMMIT_MESSAGE`         |                      Require users to type a custom commit message when creating a new commit.                       | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
-   | `KIE_SANDBOX_CUSTOM_COMMIT_MESSAGE_VALIDATION_SERVICE_URL` |                                       Service URL to validate commit messages.                                       | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
-   |                `KIE_SANDBOX_AUTH_PROVIDERS`                | Authentication providers configuration. Used to enable integration with GitHub Enterprise Server instances and more. | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   |                            Name                             |                                                         Description                                                         |                               Default                               |
+   | :---------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------: |
+   |             `KIE_SANDBOX_EXTENDED_SERVICES_URL`             |                                  The URL that points to the KIE Sandbox Extended Services.                                  | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   |              `KIE_SANDBOX_GIT_CORS_PROXY_URL`               |                        The URL that points to the Git CORS proxy for interacting with Git providers.                        | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   |        `KIE_SANDBOX_REQUIRE_CUSTOM_COMMIT_MESSAGES`         |                          Require users to type a custom commit message when creating a new commit.                          | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   | `KIE_SANDBOX_CUSTOM_COMMIT_MESSAGES_VALIDATION_SERVICE_URL` |                                          Service URL to validate commit messages.                                           | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   |                `KIE_SANDBOX_AUTH_PROVIDERS`                 |    Authentication providers configuration. Used to enable integration with GitHub Enterprise Server instances and more.     | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
+   |                 `KIE_SANDBOX_ACCELERATORS`                  | Accelerators configuration. Used to add a template to a set of Decisions and Workflows, making it buildable and deployable. | See [ defaultEnvJson.ts ](../online-editor/build/defaultEnvJson.ts) |
 
    ### Examples
 
@@ -73,7 +74,15 @@ This package contains the `Containerfile/Dockerfile` and scripts to build a cont
    2. Enabling authentication with a GitHub Enterprise Server instance.
 
       ```bash
-      podman run -t -p 8080:8080 -e KIE_SANDBOX_AUTH_PROVIDERS='[{"id":"github_at_my_company","domain":"github.my-company.com","supportedGitRemoteDomains":["github.my-company.com","gist.github.my-company.com"],"type":"github","name":"GitHub @ MyCompany","enabled":true, "group":"git" }]' -i --rm quay.io/kie-tools/kie-sandbox-image:latest
+      podman run -t -p 8080:8080 -e KIE_SANDBOX_AUTH_PROVIDERS='[{
+        "id":"github_at_my_company", \
+        "domain":"github.my-company.com", \
+        "supportedGitRemoteDomains":["github.my-company.com","gist.github.my-company.com"], \
+        "type":"github", \
+        "name":"GitHub @ MyCompany", \
+        "enabled":true, \
+        "group":"git" \
+      }]' -i --rm quay.io/kie-tools/kie-sandbox-image:latest
       ```
 
    3. Requiring users to input a custom commit message on every commit.
@@ -88,6 +97,20 @@ This package contains the `Containerfile/Dockerfile` and scripts to build a cont
       podman run -t -p 8080:8080 -e KIE_SANDBOX_REQUIRE_CUSTOM_COMMIT_MESSAGE='true' KIE_SANDBOX_CUSTOM_COMMIT_MESSAGE_VALIDATION_SERVICE_URL='http://localhost:8090/validate' -i --rm quay.io/kie-tools/kie-sandbox-image:latest
       ```
 
+   5. Adding Accelerators available for your users.
+
+      ```bash
+      podman run -t -p 8080:8080 -e KIE_SANDBOX_ACCELERATORS='[{ \
+        name: "Quarkus", \
+        iconUrl: "https://github.com/kiegroup/kie-sandbox-quarkus-accelerator/raw/0.0.0/quarkus-logo.png", \
+        gitRepositoryUrl: "https://github.com/kiegroup/kie-sandbox-quarkus-accelerator", \
+        gitRepositoryGitRef: "0.0.0", \
+        dmnDestinationFolder: "src/main/resources/dmn", \
+        bpmnDestinationFolder: "src/main/resources/bpmn", \
+        otherFilesDestinationFolder: "src/main/resources/others", \
+      }]' -i --rm quay.io/kie-tools/kie-sandbox-image:latest
+      ```
+
 2. Write a custom `Containerfile/Dockerfile` from the image:
 
    ```docker
@@ -98,6 +121,7 @@ This package contains the `Containerfile/Dockerfile` and scripts to build a cont
    ENV KIE_SANDBOX_REQUIRE_CUSTOM_COMMIT_MESSAGE=<my_value>
    ENV KIE_SANDBOX_CUSTOM_COMMIT_MESSAGE_VALIDATION_SERVICE_URL=<my_value>
    ENV KIE_SANDBOX_AUTH_PROVIDERS=<my_value>
+   ENV KIE_SANDBOX_ACCELERATORS=<my_value>
    ```
 
 3. Create the application from the image in OpenShift and set the deployment environment variable right from the OpenShift UI.
@@ -168,3 +192,48 @@ Content-Type: application/json
 
 - #### HTTP Status different from 200
   If the service responds with an HTTP code other than 200, an error message is displayed alongside the HTTP Code + the response body of the request in full.
+
+### Accelerators
+
+Accelerators are Git repositories that contain a skeleton of an application and will convert a working directory with your .dmn and .bpmn files into a fully functional application that can be built and deployed.
+
+After creating yours you must define where resources should be placed inside these repositories. For example, `.dmn` files should be placed inside `src/main/resources` for a Quarkus application. As a bonus, adding an image/logo can be used to better represent your Accelerator wherever it's listed.
+
+#### The Accelerator configuration
+
+Having all of that, it's time to create the configuration required to add it to the **KIE_SANDBOX_ACCELERATORS** list env var.
+It looks like this:
+
+```js
+{
+    name: "Your Accelerator name",
+    iconUrl: "https://link.to/your/logo/image",
+    gitRepositoryUrl: "https://github.com/...",
+    gitRepositoryGitRef: "branchName",
+    dmnDestinationFolder: "path/to/place/dmn/files",
+    bpmnDestinationFolder: "path/to/place/bpmn/files",
+    otherFilesDestinationFolder: "path/to/place/other/files",
+}
+```
+
+- **name**: This is how the Accelerator will be known inside KIE Sandbox.
+- **iconUrl**: An optional parameter to add an image/logo besides you Accelerator name.
+- **gitRepositoryUrl**: This is where your Accelerator is hosted. Should be an URL that can be used with `git clone`.
+- **gitRepositoryGitRef**: Where in your repository is this Accelerator located. Could be a branch, commit, tag, anything that can be used with `git checkout`.
+- **dmnDestinationFolder**: Where your DMN and PMML files will be moved to after applying the Accelerator.
+- **bpmnDestinationFolder**: Where your BPMN files will be moved to after applying the Accelerator.
+- **otherFilesDestinationFolder**: Where other files will be moved to after applying the Accelerator.
+
+Here's an example of what it should look like:
+
+```js
+{
+    name: "Quarkus",
+    iconUrl: `https://github.com/kiegroup/kie-sandbox-quarkus-accelerator/raw/0.0.0/quarkus-logo.png`,
+    gitRepositoryUrl: "https://github.com/kiegroup/kie-sandbox-quarkus-accelerator",
+    gitRepositoryGitRef: "main,
+    dmnDestinationFolder: "src/main/resources/dmn",
+    bpmnDestinationFolder: "src/main/resources/bpmn",
+    otherFilesDestinationFolder: "src/main/resources/others",
+}
+```
diff --git a/packages/kn-plugin-workflow/env/index.js b/packages/kn-plugin-workflow/env/index.js
index c3430b2017..7089c702c3 100644
--- a/packages/kn-plugin-workflow/env/index.js
+++ b/packages/kn-plugin-workflow/env/index.js
@@ -31,7 +31,7 @@ module.exports = composeEnv([require("@kie-tools/root-env/env")], {
     },
     KN_PLUGIN_WORKFLOW__quarkusVersion: {
       name: "KN_PLUGIN_WORKFLOW__quarkusVersion",
-      default: "2.15.0.Final",
+      default: "2.16.0.Final",
       description: "Quarkus version to be used when creating the Kogito Serverless Workflow project",
     },
   }),
diff --git a/packages/kn-plugin-workflow/go.mod b/packages/kn-plugin-workflow/go.mod
index c0be1728e9..96023519b4 100644
--- a/packages/kn-plugin-workflow/go.mod
+++ b/packages/kn-plugin-workflow/go.mod
@@ -25,7 +25,7 @@ require (
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/subosito/gotenv v1.2.0 // indirect
 	golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 // indirect
-	golang.org/x/text v0.3.7 // indirect
+	golang.org/x/text v0.3.8 // indirect
 	gopkg.in/ini.v1 v1.66.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 )
diff --git a/packages/kn-plugin-workflow/go.sum b/packages/kn-plugin-workflow/go.sum
index 5fbfb1f3d7..7828ef2d5f 100644
--- a/packages/kn-plugin-workflow/go.sum
+++ b/packages/kn-plugin-workflow/go.sum
@@ -352,8 +352,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
diff --git a/packages/online-editor/build/defaultEnvJson.ts b/packages/online-editor/build/defaultEnvJson.ts
index 8d98aa97bc..124b397179 100644
--- a/packages/online-editor/build/defaultEnvJson.ts
+++ b/packages/online-editor/build/defaultEnvJson.ts
@@ -79,4 +79,15 @@ export const defaultEnvJson: EnvJson = {
       group: AuthProviderGroup.CLOUD,
     },
   ],
+  KIE_SANDBOX_ACCELERATORS: [
+    {
+      name: "Quarkus",
+      iconUrl: `https://github.com/kiegroup/kie-sandbox-quarkus-accelerator/raw/${buildEnv.root.version}/quarkus-logo.png`,
+      gitRepositoryUrl: "https://github.com/kiegroup/kie-sandbox-quarkus-accelerator",
+      gitRepositoryGitRef: buildEnv.root.version,
+      dmnDestinationFolder: "src/main/resources/dmn",
+      bpmnDestinationFolder: "src/main/resources/bpmn",
+      otherFilesDestinationFolder: "src/main/resources/others",
+    },
+  ],
 };
diff --git a/packages/online-editor/package.json b/packages/online-editor/package.json
index 59b241bcc4..0424ec2682 100644
--- a/packages/online-editor/package.json
+++ b/packages/online-editor/package.json
@@ -60,6 +60,7 @@
     "buffer": "^6.0.3",
     "history": "^4.9.0",
     "isomorphic-git": "^1.11.1",
+    "js-yaml": "^4.1.0",
     "moment": "^2.29.4",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
@@ -87,6 +88,7 @@
     "@types/history": "^4.7.3",
     "@types/jest": "^26.0.23",
     "@types/jest-when": "^2.7.4",
+    "@types/js-yaml": "^4.0.5",
     "@types/react": "^17.0.6",
     "@types/react-dom": "^17.0.5",
     "@types/react-router": "^5.1.14",
diff --git a/packages/online-editor/src/accelerators/AcceleratorsApi.ts b/packages/online-editor/src/accelerators/AcceleratorsApi.ts
new file mode 100644
index 0000000000..22a5d50b67
--- /dev/null
+++ b/packages/online-editor/src/accelerators/AcceleratorsApi.ts
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export type AcceleratorConfig = {
+  name: string;
+  gitRepositoryUrl: string;
+  gitRepositoryGitRef: string;
+  dmnDestinationFolder: string;
+  bpmnDestinationFolder: string;
+  otherFilesDestinationFolder: string;
+  iconUrl?: string;
+};
+
+export type AcceleratorAppliedConfig = AcceleratorConfig & { appliedAt?: string };
+
+export function validateAcceleratorDestinationFolderPaths(path: string) {
+  if (path.startsWith(".")) {
+    return "Accelerator destination folder misconfigured: Please only use absolute paths.";
+  } else if (path.includes("*") || path.includes("?")) {
+    return "Accelerator destination folder misconfigured: Wildcards and patterns are not allowed.";
+  }
+  return;
+}
+
+export const KIE_SANDBOX_DIRECTORY_PATH = ".kie-sandbox";
+export const ACCELERATOR_CONFIG_FILE_NAME = "accelerator";
+export const ACCELERATOR_CONFIG_FILE_EXTENSION = "yaml";
+export const ACCELERATOR_CONFIG_FILE_RELATIVE_PATH = `${KIE_SANDBOX_DIRECTORY_PATH}/${ACCELERATOR_CONFIG_FILE_NAME}.${ACCELERATOR_CONFIG_FILE_EXTENSION}`;
diff --git a/packages/online-editor/src/accelerators/AcceleratorsHooks.tsx b/packages/online-editor/src/accelerators/AcceleratorsHooks.tsx
new file mode 100644
index 0000000000..def9232810
--- /dev/null
+++ b/packages/online-editor/src/accelerators/AcceleratorsHooks.tsx
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useMemo, useState } from "react";
+import * as yaml from "js-yaml";
+import { useEnv } from "../env/hooks/EnvContext";
+import {
+  ACCELERATOR_CONFIG_FILE_NAME,
+  ACCELERATOR_CONFIG_FILE_EXTENSION,
+  KIE_SANDBOX_DIRECTORY_PATH,
+  AcceleratorConfig,
+  validateAcceleratorDestinationFolderPaths,
+  ACCELERATOR_CONFIG_FILE_RELATIVE_PATH,
+  AcceleratorAppliedConfig,
+} from "./AcceleratorsApi";
+import { WorkspaceFile, useWorkspaces } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { dirname, join } from "path";
+import { useHistory } from "react-router";
+import { useRoutes } from "../navigation/Hooks";
+import { useGlobalAlert } from "../alerts";
+import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
+import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
+import { useOnlineI18n } from "../i18n";
+import { useCancelableEffect } from "@kie-tools-core/react-hooks/dist/useCancelableEffect";
+import { useAuthSession } from "../authSessions/AuthSessionsContext";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { useWorkspaceFilePromise } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspaceFileHooks";
+import {
+  GIT_DEFAULT_BRANCH,
+  GIT_ORIGIN_REMOTE_NAME,
+} from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
+import { isDecision, isScorecard, isWorkflow } from "../envelopeLocator/EditorEnvelopeLocatorFactory";
+
+const TEMP_ACCELERATOR_REMOTE_NAME = "__kie-sandbox__accelerator-remote";
+const BACKUP_BRANCH_NAME = "__kie-sandbox__accelerator-backup-branch";
+const MOVED_FILES_BRANCH_NAME = "__kie-sandbox__accelerator-moved-files-branch";
+
+class ApplyAcceleratorError extends Error {
+  constructor(acceleratorName: string, message?: string) {
+    super(`Applying Accelerator ${acceleratorName}: ${message}`);
+  }
+}
+
+export function useAvailableAccelerators() {
+  const { env } = useEnv();
+  return useMemo<AcceleratorConfig[]>(() => env.KIE_SANDBOX_ACCELERATORS, [env.KIE_SANDBOX_ACCELERATORS]);
+}
+
+export function useAcceleratorsDispatch(workspace: ActiveWorkspace) {
+  const workspaces = useWorkspaces();
+  const history = useHistory();
+  const routes = useRoutes();
+  const { i18n } = useOnlineI18n();
+  const { gitConfig } = useAuthSession(workspace.descriptor.gitAuthSessionId);
+
+  const apllyingAcceleratorAlert = useGlobalAlert(
+    useCallback(
+      (_, staticArgs: { acceleratorName: string }) => (
+        <Alert
+          className={"kogito--alert"}
+          variant="info"
+          title={
+            <>
+              <Spinner size={"sm"} />
+              &nbsp;&nbsp; {i18n.accelerators.loadingAlert(staticArgs.acceleratorName)}
+            </>
+          }
+        />
+      ),
+      [i18n]
+    )
+  );
+
+  const applyAcceleratorSuccessAlert = useGlobalAlert(
+    useCallback(
+      (_, staticArgs: { acceleratorName: string }) => (
+        <Alert
+          className={"kogito--alert"}
+          variant="success"
+          title={i18n.accelerators.successAlert(staticArgs.acceleratorName)}
+        />
+      ),
+      [i18n]
+    ),
+    { durationInSeconds: 4 }
+  );
+
+  const applyAcceleratorFailAlert = useGlobalAlert(
+    useCallback(
+      (_, staticArgs: { acceleratorName: string }) => (
+        <Alert
+          className={"kogito--alert"}
+          variant="danger"
+          title={i18n.accelerators.failAlert(staticArgs.acceleratorName)}
+        />
+      ),
+      [i18n]
+    ),
+    { durationInSeconds: 4 }
+  );
+
+  const attemptToDeleteTemporaryBranches = useCallback(async () => {
+    const workspaceId = workspace.descriptor.workspaceId;
+    try {
+      await workspaces.deleteBranch({ workspaceId, ref: BACKUP_BRANCH_NAME });
+    } catch (e) {
+      // Do nothing
+    }
+    try {
+      await workspaces.deleteBranch({ workspaceId, ref: MOVED_FILES_BRANCH_NAME });
+    } catch (e) {
+      // Do nothing
+    }
+  }, [workspace.descriptor.workspaceId, workspaces]);
+
+  const applyAcceleratorToWorkspace = useCallback(
+    async (accelerator: AcceleratorConfig, currentFile: WorkspaceFile) => {
+      apllyingAcceleratorAlert.show({ acceleratorName: accelerator.name });
+
+      const workspaceId = workspace.descriptor.workspaceId;
+
+      let movedFiles: WorkspaceFile[] = [];
+
+      // Attempt to delete branches
+      // This is a workaround, as isomorphic-git doesn't necessarilly deletes the branch, even though it resolves
+      attemptToDeleteTemporaryBranches();
+
+      let configFile: WorkspaceFile | undefined = undefined;
+
+      try {
+        const destinationPathValidation = {
+          dmnDestinationFolder: validateAcceleratorDestinationFolderPaths(accelerator.dmnDestinationFolder),
+          bpmnDestinationFolder: validateAcceleratorDestinationFolderPaths(accelerator.bpmnDestinationFolder),
+          otherFilesDestinationFolder: validateAcceleratorDestinationFolderPaths(
+            accelerator.otherFilesDestinationFolder
+          ),
+        };
+
+        if (
+          destinationPathValidation.dmnDestinationFolder ||
+          destinationPathValidation.bpmnDestinationFolder ||
+          destinationPathValidation.otherFilesDestinationFolder
+        ) {
+          throw new ApplyAcceleratorError(accelerator.name, JSON.stringify(destinationPathValidation));
+        }
+
+        const workspaceFiles = await workspaces.getFiles({ workspaceId });
+
+        // Create new temporary branch with current files, but stay on main
+        await workspaces.branch({ workspaceId, name: BACKUP_BRANCH_NAME, checkout: false });
+
+        // Commit moved files to moved files branch (this commit will never be pushed, as this branch will be deleted)
+        await workspaces.commit({
+          workspaceId,
+          commitMessage: `KIE Sandbox: Backup files before applying ${accelerator.name} Accelerator`,
+          targetBranch: BACKUP_BRANCH_NAME,
+        });
+
+        // Create new temporary branch for moved files, but stay on main
+        await workspaces.branch({ workspaceId, name: MOVED_FILES_BRANCH_NAME, checkout: false });
+
+        // Checkout to moved files branch
+        await workspaces.checkout({
+          workspaceId,
+          ref: MOVED_FILES_BRANCH_NAME,
+          remote: GIT_ORIGIN_REMOTE_NAME,
+        });
+
+        // Move files
+        let currentFileAfterAccelerator: WorkspaceFile | undefined;
+        movedFiles = await Promise.all(
+          workspaceFiles.map(async (file) => {
+            let fileNewDestination: string;
+
+            if (isDecision(file.relativePath) || isScorecard(file.relativePath)) {
+              fileNewDestination = accelerator.dmnDestinationFolder;
+            } else if (isWorkflow(file.relativePath)) {
+              fileNewDestination = accelerator.bpmnDestinationFolder;
+            } else {
+              fileNewDestination = accelerator.otherFilesDestinationFolder;
+            }
+
+            const movedFile = await workspaces.moveFile({
+              file,
+              newDirPath: join(fileNewDestination, dirname(file.relativePath)),
+            });
+
+            await workspaces.stageFile({ workspaceId, relativePath: movedFile.relativePath });
+
+            if (file.relativePath === currentFile.relativePath) {
+              currentFileAfterAccelerator = movedFile;
+            }
+            return movedFile;
+          })
+        );
+
+        const movedFilesPaths = movedFiles.map((file) => file.relativePath);
+
+        if (!currentFileAfterAccelerator) {
+          throw new ApplyAcceleratorError(accelerator.name, "Failed to find current file after moving.");
+        }
+
+        // Commit moved files to moved files branch (this commit will never be pushed, as this branch will be deleted)
+        await workspaces.commit({
+          workspaceId,
+          commitMessage: `KIE Sandbox: Moving files to apply ${accelerator.name} Accelerator.`,
+          targetBranch: MOVED_FILES_BRANCH_NAME,
+        });
+
+        // Go back to main
+        await workspaces.checkout({ workspaceId, ref: GIT_DEFAULT_BRANCH, remote: GIT_ORIGIN_REMOTE_NAME });
+
+        // Add Accelerator remote and fetch it
+        await workspaces.addRemote({
+          workspaceId,
+          name: TEMP_ACCELERATOR_REMOTE_NAME,
+          url: accelerator.gitRepositoryUrl,
+          force: true,
+        });
+
+        const fetchResult = await workspaces.fetch({
+          workspaceId,
+          remote: TEMP_ACCELERATOR_REMOTE_NAME,
+          ref: accelerator.gitRepositoryGitRef,
+        });
+
+        if (!fetchResult.fetchHead) {
+          throw new ApplyAcceleratorError(
+            accelerator.name,
+            `Unable to find remote HEAD for ${accelerator.gitRepositoryGitRef} ref.`
+          );
+        }
+
+        // Checkout Accelerator files, wiping everything else
+        await workspaces.checkoutFilesFromLocalHead({
+          workspaceId,
+          ref: fetchResult.fetchHead,
+          filepaths: ["."],
+        });
+
+        // Delete Accelerator remote
+        await workspaces.deleteRemote({ workspaceId, name: TEMP_ACCELERATOR_REMOTE_NAME });
+
+        // Stage all Accelerator files
+        const acceleratorFiles = await workspaces.getFiles({ workspaceId });
+        await Promise.all(
+          acceleratorFiles.map(async (file) => {
+            return workspaces.stageFile({
+              workspaceId,
+              relativePath: file.relativePath,
+            });
+          })
+        );
+
+        // Bring moved user files back
+        await workspaces.checkoutFilesFromLocalHead({
+          workspaceId,
+          ref: MOVED_FILES_BRANCH_NAME,
+          filepaths: movedFilesPaths,
+        });
+
+        // Stage all moved files
+        await Promise.all(
+          movedFiles.map(async (file) => {
+            return workspaces.stageFile({
+              workspaceId,
+              relativePath: file.relativePath,
+            });
+          })
+        );
+
+        // Add Accelerator YAML config
+        const content = `# This file was automatically created by ${
+          i18n.names.businessModeler.online
+        }. Please don't modify it.\n${yaml.dump({ ...accelerator, appliedAt: new Date().toISOString() })}`;
+        configFile = await workspaces.addFile({
+          workspaceId,
+          name: ACCELERATOR_CONFIG_FILE_NAME,
+          destinationDirRelativePath: KIE_SANDBOX_DIRECTORY_PATH,
+          content,
+          extension: ACCELERATOR_CONFIG_FILE_EXTENSION,
+        });
+
+        await workspaces.stageFile({
+          workspaceId,
+          relativePath: ACCELERATOR_CONFIG_FILE_RELATIVE_PATH,
+        });
+
+        // Create commit
+        await workspaces.createSavePoint({
+          workspaceId,
+          gitConfig,
+          commitMessage: i18n.accelerators.commitMessage(accelerator.name),
+          forceHasChanges: true,
+        });
+
+        apllyingAcceleratorAlert.close();
+
+        applyAcceleratorSuccessAlert.show({ acceleratorName: accelerator.name });
+
+        attemptToDeleteTemporaryBranches();
+
+        history.replace({
+          pathname: routes.workspaceWithFilePath.path({
+            extension: currentFileAfterAccelerator.extension,
+            fileRelativePath: currentFileAfterAccelerator.relativePathWithoutExtension,
+            workspaceId,
+          }),
+        });
+      } catch (e) {
+        apllyingAcceleratorAlert.close();
+        applyAcceleratorFailAlert.show({ acceleratorName: accelerator.name });
+
+        console.error(e);
+
+        // Delete config file
+        if (configFile) {
+          await workspaces.deleteFile({ file: configFile });
+        }
+
+        // Return to main
+        await workspaces.checkout({ workspaceId, ref: GIT_DEFAULT_BRANCH, remote: GIT_ORIGIN_REMOTE_NAME });
+
+        // Revert repo
+        await workspaces.checkoutFilesFromLocalHead({
+          workspaceId,
+          ref: BACKUP_BRANCH_NAME,
+          filepaths: ["."],
+        });
+
+        attemptToDeleteTemporaryBranches();
+
+        // Delete moved files
+        await Promise.all(
+          movedFiles.map(
+            async (file) =>
+              (await workspaces.existsFile({ workspaceId, relativePath: file.relativePath })) &&
+              (await workspaces.deleteFile({ file }))
+          )
+        );
+
+        // Reload to currentFile file
+        history.replace({
+          pathname: routes.workspaceWithFilePath.path({
+            extension: currentFile.extension,
+            fileRelativePath: currentFile.relativePathWithoutExtension,
+            workspaceId,
+          }),
+        });
+      }
+    },
+    [
+      apllyingAcceleratorAlert,
+      applyAcceleratorFailAlert,
+      applyAcceleratorSuccessAlert,
+      attemptToDeleteTemporaryBranches,
+      gitConfig,
+      history,
+      i18n.accelerators,
+      i18n.names.businessModeler.online,
+      routes.workspaceWithFilePath,
+      workspace.descriptor.workspaceId,
+      workspaces,
+    ]
+  );
+
+  return { applyAcceleratorToWorkspace };
+}
+
+export function useCurrentAccelerator(workspaceId: string) {
+  const [currentAccelerator, setCurrentAccelerator] = useState<AcceleratorAppliedConfig>();
+
+  const acceleratorConfigFile = useWorkspaceFilePromise(workspaceId, ACCELERATOR_CONFIG_FILE_RELATIVE_PATH);
+
+  const getCurrentAccelerator = useCallback(async () => {
+    if (!acceleratorConfigFile?.data) {
+      return;
+    }
+
+    return yaml.load(
+      await acceleratorConfigFile.data.workspaceFile.getFileContentsAsString()
+    ) as AcceleratorAppliedConfig;
+  }, [acceleratorConfigFile.data]);
+
+  useCancelableEffect(
+    useCallback(
+      ({ canceled }) => {
+        getCurrentAccelerator().then((accelerator) => {
+          if (canceled.get()) {
+            return;
+          }
+          setCurrentAccelerator(accelerator);
+        });
+      },
+      [getCurrentAccelerator]
+    )
+  );
+
+  return currentAccelerator;
+}
diff --git a/packages/online-editor/src/authSessions/AuthSessionSelect.tsx b/packages/online-editor/src/authSessions/AuthSessionSelect.tsx
index f4ea420f71..e2e8a9f8c3 100644
--- a/packages/online-editor/src/authSessions/AuthSessionSelect.tsx
+++ b/packages/online-editor/src/authSessions/AuthSessionSelect.tsx
@@ -29,8 +29,7 @@ import { IconSize } from "@patternfly/react-icons/dist/js/createIcon";
 import { AuthProvider, AuthProviderGroup } from "../authProviders/AuthProvidersApi";
 import { useEffect, useMemo, useState } from "react";
 import { ValidatedOptions } from "@patternfly/react-core/dist/js/helpers";
-import { Button } from "@patternfly/react-core/dist/js/components/Button";
-import { ButtonVariant } from "@patternfly/react-core";
+import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
 import PlusIcon from "@patternfly/react-icons/dist/js/icons/plus-icon";
 import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
 import { AccountsDispatchActionKind, useAccountsDispatch } from "../accounts/AccountsContext";
diff --git a/packages/online-editor/src/editor/EditorPage.tsx b/packages/online-editor/src/editor/EditorPage.tsx
index 60c8a43a61..0b1889ebd7 100644
--- a/packages/online-editor/src/editor/EditorPage.tsx
+++ b/packages/online-editor/src/editor/EditorPage.tsx
@@ -18,7 +18,7 @@ import * as React from "react";
 import { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import { useHistory } from "react-router";
 import { useRoutes } from "../navigation/Hooks";
-import { EditorToolbar } from "./EditorToolbar";
+import { EditorToolbar } from "./Toolbar/EditorToolbar";
 import { useDmnTour } from "../tour";
 import { useOnlineI18n } from "../i18n";
 import { ChannelType } from "@kie-tools-core/editor/dist/api";
diff --git a/packages/online-editor/src/editor/EditorToolbar.tsx b/packages/online-editor/src/editor/EditorToolbar.tsx
deleted file mode 100644
index 148a3b2c10..0000000000
--- a/packages/online-editor/src/editor/EditorToolbar.tsx
+++ /dev/null
@@ -1,2237 +0,0 @@
-/*
- * Copyright 2019 Red Hat, Inc. and/or its affiliates.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {
-  Dropdown,
-  DropdownGroup,
-  DropdownItem,
-  DropdownPosition,
-  DropdownToggle,
-} from "@patternfly/react-core/dist/js/components/Dropdown";
-import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput";
-import { Title } from "@patternfly/react-core/dist/js/components/Title";
-import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
-import {
-  Toolbar,
-  ToolbarContent,
-  ToolbarGroup,
-  ToolbarItem,
-  ToolbarItemProps,
-} from "@patternfly/react-core/dist/js/components/Toolbar";
-import { EllipsisVIcon } from "@patternfly/react-icons/dist/js/icons/ellipsis-v-icon";
-import { SaveIcon } from "@patternfly/react-icons/dist/js/icons/save-icon";
-import { AngleLeftIcon } from "@patternfly/react-icons/dist/js/icons/angle-left-icon";
-import * as React from "react";
-import { useCallback, useEffect, useMemo, useRef, useState } from "react";
-import { useOnlineI18n } from "../i18n";
-import { KieSandboxExtendedServicesButtons } from "./KieSandboxExtendedServices/KieSandboxExtendedServicesButtons";
-import {
-  useNavigationBlockersBypass,
-  useNavigationStatus,
-  useNavigationStatusToggle,
-  useRoutes,
-} from "../navigation/Hooks";
-import { EmbeddedEditorRef, useDirtyState } from "@kie-tools-core/editor/dist/embedded";
-import { useHistory } from "react-router";
-import { EmbedModal } from "./EmbedModal";
-import { Alert, AlertActionCloseButton, AlertActionLink } from "@patternfly/react-core/dist/js/components/Alert";
-import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
-import { OutlinedClockIcon } from "@patternfly/react-icons/dist/js/icons/outlined-clock-icon";
-import { FolderIcon } from "@patternfly/react-icons/dist/js/icons/folder-icon";
-import { ImageIcon } from "@patternfly/react-icons/dist/js/icons/image-icon";
-import { DownloadIcon } from "@patternfly/react-icons/dist/js/icons/download-icon";
-import { PlusIcon } from "@patternfly/react-icons/dist/js/icons/plus-icon";
-import { ArrowCircleUpIcon } from "@patternfly/react-icons/dist/js/icons/arrow-circle-up-icon";
-import { ColumnsIcon } from "@patternfly/react-icons/dist/js/icons/columns-icon";
-import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
-import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
-import { NewFileDropdownMenu } from "./NewFileDropdownMenu";
-import { PageHeaderToolsItem, PageSection } from "@patternfly/react-core/dist/js/components/Page";
-import { FileLabel } from "../filesList/FileLabel";
-import { useWorkspacePromise } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspaceHooks";
-import { OutlinedHddIcon } from "@patternfly/react-icons/dist/js/icons/outlined-hdd-icon";
-import { DesktopIcon } from "@patternfly/react-icons/dist/js/icons/desktop-icon";
-import { FileSwitcher } from "./FileSwitcher";
-import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
-import { KieSandboxExtendedServicesDropdownGroup } from "./KieSandboxExtendedServices/KieSandboxExtendedServicesDropdownGroup";
-import { TrashIcon } from "@patternfly/react-icons/dist/js/icons/trash-icon";
-import { CaretDownIcon } from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
-import {
-  GIST_ORIGIN_REMOTE_NAME,
-  GIT_ORIGIN_REMOTE_NAME,
-} from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
-import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
-import { PromiseStateWrapper } from "@kie-tools-core/react-hooks/dist/PromiseState";
-import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
-import { WorkspaceLabel } from "../workspace/components/WorkspaceLabel";
-import { EditorPageDockDrawerRef } from "./EditorPageDockDrawer";
-import { SyncAltIcon } from "@patternfly/react-icons/dist/js/icons/sync-alt-icon";
-import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
-import { UrlType, useImportableUrl } from "../importFromUrl/ImportableUrlHooks";
-import { Location } from "history";
-import { ExternalLinkAltIcon } from "@patternfly/react-icons/dist/js/icons/external-link-alt-icon";
-import { useEditorEnvelopeLocator } from "../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
-import { useCancelableEffect } from "@kie-tools-core/react-hooks/dist/useCancelableEffect";
-import type { RestEndpointMethodTypes as OctokitRestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types";
-import { useSharedValue } from "@kie-tools-core/envelope-bus/dist/hooks";
-import { WorkspaceStatusIndicator } from "../workspace/components/WorkspaceStatusIndicator";
-import { ResponsiveDropdown } from "../ResponsiveDropdown/ResponsiveDropdown";
-import { ResponsiveDropdownToggle } from "../ResponsiveDropdown/ResponsiveDropdownToggle";
-import { useAuthSession } from "../authSessions/AuthSessionsContext";
-import { AuthSessionSelect, AuthSessionSelectFilter } from "../authSessions/AuthSessionSelect";
-import { useAuthProvider } from "../authProviders/AuthProvidersContext";
-import { useGitHubClient } from "../github/Hooks";
-import { AccountsDispatchActionKind, useAccountsDispatch } from "../accounts/AccountsContext";
-import { SelectPosition } from "@patternfly/react-core/dist/js/components/Select";
-import {
-  authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain,
-  authSessionsSelectFilterCompatibleWithGitUrlDomain,
-  gitAuthSessionSelectFilter,
-} from "../authSessions/CompatibleAuthSessions";
-import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
-import { useGlobalAlert, useGlobalAlertsDispatchContext } from "../alerts";
-import {
-  AuthProviderGroup,
-  GistEnabledAuthProviderType,
-  GitAuthProviderType,
-  isGistEnabledAuthProviderType,
-} from "../authProviders/AuthProvidersApi";
-import { CreateGitRepositoryModal, CreateRepositoryResponse } from "./CreateGitRepositoryModal";
-import { BitbucketIcon, GitIcon, GithubIcon } from "@patternfly/react-icons";
-import { useBitbucketClient } from "../bitbucket/Hooks";
-import {
-  isGistLikeWorkspaceKind,
-  WorkspaceKindGistLike,
-  WorkspaceKindGitBased,
-} from "@kie-tools-core/workspaces-git-fs/src/worker/api/WorkspaceOrigin";
-import { switchExpression } from "../switchExpression/switchExpression";
-import { CreateGistOrSnippetModal } from "./CreateGistOrSnippetModal";
-
-export interface Props {
-  editor: EmbeddedEditorRef | undefined;
-  workspaceFile: WorkspaceFile;
-  editorPageDock: EditorPageDockDrawerRef | undefined;
-}
-
-const showWhenSmall: ToolbarItemProps["visibility"] = {
-  default: "visible",
-  "2xl": "hidden",
-  xl: "hidden",
-  lg: "visible",
-  md: "visible",
-};
-
-const hideWhenSmall: ToolbarItemProps["visibility"] = {
-  default: "hidden",
-  "2xl": "visible",
-  xl: "visible",
-  lg: "hidden",
-  md: "hidden",
-};
-
-const hideWhenTiny: ToolbarItemProps["visibility"] = {
-  default: "hidden",
-  "2xl": "visible",
-  xl: "visible",
-  lg: "visible",
-  md: "hidden",
-};
-
-export function EditorToolbar(props: Props) {
-  const routes = useRoutes();
-  const editorEnvelopeLocator = useEditorEnvelopeLocator();
-  const history = useHistory();
-  const workspaces = useWorkspaces();
-  const accountsDispatch = useAccountsDispatch();
-  const [isShareDropdownOpen, setShareDropdownOpen] = useState(false);
-  const [isSyncGistOrSnippetDropdownOpen, setSyncGistOrSnippetDropdownOpen] = useState(false);
-  const [isSyncGitRepositoryDropdownOpen, setSyncGitRepositoryDropdownOpen] = useState(false);
-  const [isLargeKebabOpen, setLargeKebabOpen] = useState(false);
-  const [isSmallKebabOpen, setSmallKebabOpen] = useState(false);
-  const [isEmbedModalOpen, setEmbedModalOpen] = useState(false);
-  const { i18n } = useOnlineI18n();
-  const alertsDispatch = useGlobalAlertsDispatchContext();
-  const isEdited = useDirtyState(props.editor);
-  const downloadRef = useRef<HTMLAnchorElement>(null);
-  const downloadAllRef = useRef<HTMLAnchorElement>(null);
-  const downloadPreviewRef = useRef<HTMLAnchorElement>(null);
-  const copyContentTextArea = useRef<HTMLTextAreaElement>(null);
-  const [isNewFileDropdownMenuOpen, setNewFileDropdownMenuOpen] = useState(false);
-  const workspacePromise = useWorkspacePromise(props.workspaceFile.workspaceId);
-  const [isGistOrSnippetLoading, setGistOrSnippetLoading] = useState(false);
-  const [gitHubGist, setGitHubGist] =
-    useState<OctokitRestEndpointMethodTypes["gists"]["get"]["response"]["data"] | undefined>(undefined);
-  const [bitbucketSnippet, setBitbucketSnippet] = useState<any>(undefined);
-  const workspaceImportableUrl = useImportableUrl(workspacePromise.data?.descriptor.origin.url?.toString());
-
-  const { authSession, authInfo, gitConfig } = useAuthSession(workspacePromise.data?.descriptor.gitAuthSessionId);
-  const authProvider = useAuthProvider(authSession);
-
-  const gitHubClient = useGitHubClient(authSession);
-  const bitbucketClient = useBitbucketClient(authSession);
-
-  const canPushToGitRepository = useMemo(
-    () => authSession?.type === "git" && !!authProvider,
-    [authProvider, authSession?.type]
-  );
-  const navigationBlockersBypass = useNavigationBlockersBypass();
-
-  const [flushes] = useSharedValue(
-    workspaces.workspacesSharedWorker.workspacesWorkerBus.clientApi.shared.kieSandboxWorkspacesStorage_flushes
-  );
-
-  const authSessionSelectFilter = useMemo(() => {
-    if (!workspacePromise.data) {
-      return gitAuthSessionSelectFilter();
-    }
-
-    if (workspacePromise.data.descriptor.origin.kind === WorkspaceKind.LOCAL) {
-      return gitAuthSessionSelectFilter();
-    }
-
-    if (workspacePromise.data.descriptor.origin.kind === WorkspaceKind.GIT) {
-      return authSessionsSelectFilterCompatibleWithGitUrlDomain(
-        new URL(workspacePromise.data.descriptor.origin.url).hostname
-      );
-    }
-
-    if (workspacePromise.data.descriptor.origin.kind === WorkspaceKind.GITHUB_GIST) {
-      return authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain(
-        new URL(workspacePromise.data.descriptor.origin.url).hostname,
-        gitHubGist?.owner?.login
-      );
-    }
-
-    if (workspacePromise.data.descriptor.origin.kind === WorkspaceKind.BITBUCKET_SNIPPET) {
-      return authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain(
-        new URL(workspacePromise.data.descriptor.origin.url).hostname,
-        bitbucketSnippet?.owner?.login
-      );
-    }
-
-    return gitAuthSessionSelectFilter();
-  }, [bitbucketSnippet?.owner?.login, gitHubGist?.owner?.login, workspacePromise.data]);
-
-  const isSaved = useMemo(() => {
-    return !isEdited && flushes && !flushes.some((f) => f.includes(props.workspaceFile.workspaceId));
-  }, [isEdited, flushes, props.workspaceFile.workspaceId]);
-
-  // Prevent from closing without flushing before.
-  useEffect(() => {
-    if (isSaved) {
-      return;
-    }
-
-    window.onbeforeunload = () => "Some changes are not written to disk yet.";
-    return () => {
-      window.onbeforeunload = null;
-    };
-  }, [isSaved]);
-
-  useCancelableEffect(
-    useCallback(
-      ({ canceled }) => {
-        if (gitHubGist || workspaceImportableUrl.type !== UrlType.GIST_DOT_GITHUB_DOT_COM) {
-          return;
-        }
-
-        const { gistId } = workspaceImportableUrl;
-
-        if (!gistId) {
-          return;
-        }
-
-        gitHubClient.gists.get({ gist_id: gistId }).then(({ data: gist }) => {
-          if (canceled.get()) {
-            return;
-          }
-
-          if (gist) {
-            setGitHubGist(gist);
-          }
-        });
-      },
-      [gitHubGist, workspaceImportableUrl, gitHubClient.gists]
-    )
-  );
-
-  useCancelableEffect(
-    useCallback(
-      ({ canceled }) => {
-        if (bitbucketSnippet || workspaceImportableUrl.type !== UrlType.BITBUCKET_DOT_ORG_SNIPPET) {
-          return;
-        }
-
-        const { snippetId, org } = workspaceImportableUrl;
-
-        if (!snippetId || !org) {
-          return;
-        }
-
-        bitbucketClient.getSnippet({ workspace: org, snippetId }).then(async (response) => {
-          if (canceled.get()) {
-            return;
-          }
-          const json = await response.json();
-          setBitbucketSnippet(json);
-        });
-      },
-      [bitbucketSnippet, workspaceImportableUrl, bitbucketClient]
-    )
-  );
-
-  const successfullyCreatedGistOrSnippetAlert = useGlobalAlert(
-    useCallback(
-      ({ close }) => {
-        if (!isGistLikeWorkspaceKind(workspacePromise.data?.descriptor.origin.kind)) {
-          return <></>;
-        }
-
-        const gistOrSnippetUrl = workspacePromise.data?.descriptor.origin.url;
-        return (
-          <Alert
-            variant="success"
-            title={switchExpression(workspacePromise.data?.descriptor.origin.kind, {
-              GITHUB_GIST: i18n.editorPage.alerts.createGist,
-              BITBUCKET_SNIPPET: i18n.editorPage.alerts.createSnippet,
-            })}
-            actionClose={<AlertActionCloseButton onClose={close} />}
-            actionLinks={
-              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
-                {gistOrSnippetUrl}
-              </AlertActionLink>
-            }
-          />
-        );
-      },
-      [
-        i18n.editorPage.alerts.createGist,
-        i18n.editorPage.alerts.createSnippet,
-        workspacePromise.data?.descriptor.origin.kind,
-        workspacePromise.data?.descriptor.origin.url,
-      ]
-    ),
-    { durationInSeconds: 4 }
-  );
-
-  const loadingGistOrSnippetAlert = useGlobalAlert(
-    useCallback(
-      ({ close }) => {
-        if (!isGistLikeWorkspaceKind(workspacePromise.data?.descriptor.origin.kind)) {
-          return <></>;
-        }
-
-        const gistOrSnippetUrl = workspacePromise.data?.descriptor.origin.url;
-        return (
-          <Alert
-            variant="info"
-            title={
-              <>
-                <Spinner size={"sm"} />
-                &nbsp;&nbsp; Updating{" "}
-                {switchExpression(workspacePromise.data?.descriptor.origin.kind, {
-                  BITBUCKET_SNIPPET: "Snippet",
-                  GITHUB_GIST: "Gist",
-                })}
-                ...
-              </>
-            }
-            actionClose={<AlertActionCloseButton onClose={close} />}
-            actionLinks={
-              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
-                {gistOrSnippetUrl}
-              </AlertActionLink>
-            }
-          />
-        );
-      },
-      [workspacePromise.data?.descriptor.origin.kind, workspacePromise.data?.descriptor.origin.url]
-    )
-  );
-
-  useEffect(() => {
-    if (isGistOrSnippetLoading) {
-      loadingGistOrSnippetAlert.show();
-    } else {
-      loadingGistOrSnippetAlert.close();
-    }
-  }, [isGistOrSnippetLoading, loadingGistOrSnippetAlert]);
-
-  const successfullyUpdatedGistOrSnippetAlert = useGlobalAlert(
-    useCallback(
-      ({ close }) => {
-        if (!isGistLikeWorkspaceKind(workspacePromise.data?.descriptor.origin.kind)) {
-          return <></>;
-        }
-
-        const gistOrSnippetUrl = workspacePromise.data?.descriptor.origin.url;
-        return (
-          <Alert
-            variant="success"
-            title={switchExpression(workspacePromise.data?.descriptor.origin.kind, {
-              GITHUB_GIST: i18n.editorPage.alerts.updateGist,
-              BITBUCKET_SNIPPET: i18n.editorPage.alerts.updateSnippet,
-            })}
-            actionClose={<AlertActionCloseButton onClose={close} />}
-            actionLinks={
-              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
-                {gistOrSnippetUrl}
-              </AlertActionLink>
-            }
-          />
-        );
-      },
-      [
-        i18n.editorPage.alerts.updateGist,
-        i18n.editorPage.alerts.updateSnippet,
-        workspacePromise.data?.descriptor.origin.kind,
-        workspacePromise.data?.descriptor.origin.url,
-      ]
-    ),
-    { durationInSeconds: 4 }
-  );
-
-  const errorAlert = useGlobalAlert(
-    useCallback(
-      ({ close }) => (
-        <Alert
-          variant="danger"
-          title={i18n.editorPage.alerts.error}
-          actionClose={<AlertActionCloseButton onClose={close} />}
-        />
-      ),
-      [i18n]
-    )
-  );
-
-  const shouldIncludeDownloadSvgDropdownItem = useMemo(() => {
-    return props.workspaceFile.extension.toLowerCase() !== "pmml";
-  }, [props.workspaceFile]);
-
-  const shouldIncludeEmbedDropdownItem = useMemo(() => {
-    return props.workspaceFile.extension.toLowerCase() !== "pmml";
-  }, [props.workspaceFile]);
-
-  const onDownload = useCallback(() => {
-    props.editor?.getStateControl().setSavedCommand();
-    alertsDispatch.closeAll();
-    props.workspaceFile.getFileContents().then((content) => {
-      if (downloadRef.current) {
-        const fileBlob = new Blob([content], { type: "text/plain" });
-        downloadRef.current.href = URL.createObjectURL(fileBlob);
-        downloadRef.current.click();
-      }
-    });
-  }, [props.editor, props.workspaceFile, alertsDispatch]);
-
-  const downloadWorkspaceZip = useCallback(async () => {
-    if (!props.editor) {
-      return;
-    }
-
-    const zipBlob = await workspaces.prepareZip({ workspaceId: props.workspaceFile.workspaceId });
-    if (downloadAllRef.current) {
-      downloadAllRef.current.href = URL.createObjectURL(zipBlob);
-      downloadAllRef.current.click();
-    }
-    if (workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.LOCAL) {
-      await workspaces.createSavePoint({ workspaceId: props.workspaceFile.workspaceId, gitConfig });
-    }
-  }, [
-    props.editor,
-    props.workspaceFile.workspaceId,
-    workspaces,
-    workspacePromise.data?.descriptor.origin.kind,
-    gitConfig,
-  ]);
-
-  const downloadSvg = useCallback(() => {
-    props.editor?.getPreview().then((previewSvg) => {
-      if (downloadPreviewRef.current && previewSvg) {
-        const fileBlob = new Blob([previewSvg], { type: "image/svg+xml" });
-        downloadPreviewRef.current.href = URL.createObjectURL(fileBlob);
-        downloadPreviewRef.current.click();
-      }
-    });
-  }, [props.editor]);
-
-  const forceUpdateGistOrSnippet = useCallback(async () => {
-    try {
-      if (!authInfo || !workspacePromise.data) {
-        return;
-      }
-
-      setGistOrSnippetLoading(true);
-
-      await workspaces.push({
-        workspaceId: props.workspaceFile.workspaceId,
-        remote: GIST_ORIGIN_REMOTE_NAME,
-        ref: workspacePromise.data.descriptor.origin.branch,
-        remoteRef: `refs/heads/${workspacePromise.data.descriptor.origin.branch}`,
-        force: true,
-        authInfo,
-      });
-
-      await workspaces.pull({
-        workspaceId: props.workspaceFile.workspaceId,
-        authInfo,
-      });
-    } catch (e) {
-      errorAlert.show();
-    } finally {
-      setGistOrSnippetLoading(false);
-      setSyncGistOrSnippetDropdownOpen(false);
-    }
-
-    successfullyUpdatedGistOrSnippetAlert.show();
-  }, [
-    successfullyUpdatedGistOrSnippetAlert,
-    authInfo,
-    workspacePromise.data,
-    workspaces,
-    props.workspaceFile.workspaceId,
-    errorAlert,
-  ]);
-
-  const errorPushingGistOrSnippet = useGlobalAlert(
-    useCallback(
-      ({ close }) => {
-        return (
-          <Alert
-            variant="danger"
-            title={switchExpression(workspacePromise.data?.descriptor.origin.kind as WorkspaceKindGistLike, {
-              GITHUB_GIST: i18n.editorPage.alerts.errorPushingGist,
-              BITBUCKET_SNIPPET: i18n.editorPage.alerts.errorPushingSnippet,
-            })}
-            actionLinks={[
-              <AlertActionLink
-                key="force"
-                onClick={() => {
-                  close();
-                  forceUpdateGistOrSnippet();
-                }}
-              >
-                Push forcefully
-              </AlertActionLink>,
-              <AlertActionLink key="dismiss" onClick={close}>
-                Dismiss
-              </AlertActionLink>,
-            ]}
-            actionClose={<AlertActionCloseButton onClose={close} />}
-          >
-            <b>{i18n.editorPage.alerts.forcePushWarning}</b>
-          </Alert>
-        );
-      },
-      [
-        workspacePromise.data?.descriptor.origin.kind,
-        i18n.editorPage.alerts.errorPushingGist,
-        i18n.editorPage.alerts.errorPushingSnippet,
-        i18n.editorPage.alerts.forcePushWarning,
-        forceUpdateGistOrSnippet,
-      ]
-    )
-  );
-
-  const updateGistOrSnippet = useCallback(async () => {
-    try {
-      if (
-        !authInfo ||
-        !workspacePromise.data ||
-        !isGistEnabledAuthProviderType(authProvider?.type) ||
-        !isGistLikeWorkspaceKind(workspacePromise.data.descriptor.origin.kind)
-      ) {
-        return;
-      }
-      setGistOrSnippetLoading(true);
-
-      await workspaces.createSavePoint({
-        workspaceId: props.workspaceFile.workspaceId,
-        gitConfig,
-      });
-
-      await workspaces.push({
-        workspaceId: props.workspaceFile.workspaceId,
-        remote: GIST_ORIGIN_REMOTE_NAME,
-        ref: workspacePromise.data.descriptor.origin.branch,
-        remoteRef: `refs/heads/${workspacePromise.data.descriptor.origin.branch}`,
-        force: false,
-        authInfo,
-      });
-
-      await workspaces.pull({
-        workspaceId: props.workspaceFile.workspaceId,
-        authInfo,
-      });
-    } catch (e) {
-      errorPushingGistOrSnippet.show();
-      throw e;
-    } finally {
-      setGistOrSnippetLoading(false);
-      setSyncGistOrSnippetDropdownOpen(false);
-    }
-
-    successfullyUpdatedGistOrSnippetAlert.show();
-  }, [
-    successfullyUpdatedGistOrSnippetAlert,
-    authInfo,
-    workspacePromise.data,
-    authProvider?.type,
-    workspaces,
-    props.workspaceFile.workspaceId,
-    gitConfig,
-    errorPushingGistOrSnippet,
-  ]);
-
-  const forkGitHubGist = useCallback(async () => {
-    try {
-      if (!authSession || !authInfo || !gitHubGist?.id || !workspacePromise.data) {
-        return;
-      }
-
-      setGistOrSnippetLoading(true);
-
-      // Fork Gist
-      const gist = await gitHubClient.gists.fork({
-        gist_id: gitHubGist.id,
-      });
-
-      const remoteName = gist.data.id;
-
-      // Adds forked gist remote to current one
-      await workspaces.addRemote({
-        workspaceId: props.workspaceFile.workspaceId,
-        url: gist.data.git_push_url,
-        name: remoteName,
-        force: true,
-      });
-
-      // Commit
-      await workspaces.createSavePoint({
-        workspaceId: props.workspaceFile.workspaceId,
-        gitConfig,
-      });
-
-      // Push to forked gist remote
-      await workspaces.push({
-        workspaceId: props.workspaceFile.workspaceId,
-        remote: remoteName,
-        ref: workspacePromise.data.descriptor.origin.branch,
-        remoteRef: `refs/heads/${workspacePromise.data.descriptor.origin.branch}`,
-        force: true,
-        authInfo,
-      });
-
-      // Redirect to import workspace
-      navigationBlockersBypass.execute(() => {
-        history.push({
-          pathname: routes.import.path({}),
-          search: routes.import.queryString({
-            url: gist.data.html_url,
-            authSessionId: authSession.id,
-          }),
-        });
-      });
-    } catch (err) {
-      errorAlert.show();
-      throw err;
-    } finally {
-      setGistOrSnippetLoading(false);
-    }
-  }, [
-    authSession,
-    authInfo,
-    gitHubGist,
-    workspacePromise.data,
-    gitHubClient.gists,
-    workspaces,
-    props.workspaceFile.workspaceId,
-    gitConfig,
-    navigationBlockersBypass,
-    history,
-    routes.import,
-    errorAlert,
-  ]);
-
-  const openEmbedModal = useCallback(() => {
-    setEmbedModalOpen(true);
-  }, []);
-
-  const workspaceHasNestedDirectories = useMemo(
-    () => workspacePromise.data?.files.filter((f) => f.relativePath !== f.name).length !== 0,
-    [workspacePromise]
-  );
-
-  const isGitHubGistOwner = useMemo(() => {
-    return authInfo?.username && gitHubGist?.owner?.login === authInfo.username;
-  }, [authInfo, gitHubGist]);
-
-  const isBitbucketSnippetOwner = useMemo(() => {
-    return authInfo?.uuid && bitbucketSnippet?.creator.uuid === authInfo.uuid;
-  }, [authInfo, bitbucketSnippet]);
-
-  const isGistOrSnippetOwner = isGitHubGistOwner || isBitbucketSnippetOwner;
-
-  const canCreateGitHubRepository = useMemo(() => authProvider?.type === "github", [authProvider?.type]);
-  const canCreateBitbucketRepository = useMemo(() => authProvider?.type === "bitbucket", [authProvider?.type]);
-  const canCreateGitRepository = useMemo(
-    () => canCreateGitHubRepository || canCreateBitbucketRepository,
-    [canCreateGitHubRepository, canCreateBitbucketRepository]
-  );
-
-  const canCreateGistOrSnippet = useMemo(
-    () =>
-      authProvider &&
-      isGistEnabledAuthProviderType(authProvider?.type) &&
-      workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.LOCAL &&
-      !workspaceHasNestedDirectories,
-    [authProvider, workspacePromise.data?.descriptor.origin.kind, workspaceHasNestedDirectories]
-  );
-
-  const canUpdateGistOrSnippet = useMemo(
-    () =>
-      authProvider &&
-      isGistEnabledAuthProviderType(authProvider?.type) &&
-      !!isGistOrSnippetOwner &&
-      workspacePromise.data &&
-      isGistLikeWorkspaceKind(workspacePromise.data?.descriptor.origin.kind) &&
-      !workspaceHasNestedDirectories,
-    [authProvider, isGistOrSnippetOwner, workspacePromise.data, workspaceHasNestedDirectories]
-  );
-
-  const canForkGitHubGist = useMemo(
-    () =>
-      authProvider?.type === "github" &&
-      !isGistOrSnippetOwner &&
-      workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.GITHUB_GIST &&
-      !workspaceHasNestedDirectories,
-    [
-      authProvider?.type,
-      isGistOrSnippetOwner,
-      workspacePromise.data?.descriptor.origin.kind,
-      workspaceHasNestedDirectories,
-    ]
-  );
-
-  const changeGitAuthSessionId = useCallback(
-    (newGitAuthSessionId: React.SetStateAction<string | undefined>, lastAuthSessionId: string | undefined) => {
-      workspaces.changeGitAuthSessionId({
-        workspaceId: props.workspaceFile.workspaceId,
-        gitAuthSessionId:
-          typeof newGitAuthSessionId === "function" ? newGitAuthSessionId(lastAuthSessionId) : newGitAuthSessionId,
-      });
-    },
-    [props.workspaceFile.workspaceId, workspaces]
-  );
-
-  const [isCreateGitRepositoryModalOpen, setCreateGitRepositoryModalOpen] = useState(false);
-  const [isCreateGistOrSnippetModalOpen, setCreateGistOrSnippetModalOpen] = useState(false);
-
-  const shareDropdownItems = useMemo(
-    () => [
-      <DropdownGroup key={"download-group"} label="Download">
-        <DropdownItem
-          onClick={onDownload}
-          key={"download-file-item"}
-          description={`${props.workspaceFile.name} will be downloaded`}
-          icon={<DownloadIcon />}
-          ouiaId="download-file-dropdown-button"
-        >
-          Current file
-        </DropdownItem>
-        {shouldIncludeDownloadSvgDropdownItem && (
-          <DropdownItem
-            key={`dropdown-download-svg`}
-            data-testid="dropdown-download-svg"
-            component="button"
-            onClick={downloadSvg}
-            description={`Image of ${props.workspaceFile.name} will be downloaded in SVG format`}
-            icon={<ImageIcon />}
-          >
-            {"Current file's SVG"}
-          </DropdownItem>
-        )}
-        <DropdownItem
-          onClick={downloadWorkspaceZip}
-          key={"download-zip-item"}
-          description={`A zip file including all files will be downloaded`}
-          icon={<FolderIcon />}
-        >
-          All files
-        </DropdownItem>
-      </DropdownGroup>,
-      ...(shouldIncludeEmbedDropdownItem
-        ? [
-            <Divider key={"divider-other-group"} />,
-            <DropdownGroup key={"other-group"} label="Other">
-              <DropdownItem
-                key={`dropdown-embed`}
-                data-testid="dropdown-embed"
-                component="button"
-                onClick={openEmbedModal}
-                icon={<ColumnsIcon />}
-              >
-                {i18n.editorToolbar.embed}...
-              </DropdownItem>
-            </DropdownGroup>,
-          ]
-        : []),
-      ...(workspacePromise.data &&
-      (workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.LOCAL ||
-        isGistLikeWorkspaceKind(workspacePromise.data?.descriptor.origin.kind))
-        ? [
-            <DropdownGroup key={"git-group"} label={i18n.names.git}>
-              <Alert
-                isInline={true}
-                variant={"info"}
-                title={"Authentication source"}
-                actionLinks={
-                  <AuthSessionSelect
-                    title={`Select Git authentication for '${workspacePromise.data.descriptor.name}'...`}
-                    position={SelectPosition.right}
-                    isPlain={false}
-                    authSessionId={workspacePromise.data.descriptor.gitAuthSessionId}
-                    showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
-                    setAuthSessionId={(newAuthSessionId) => {
-                      changeGitAuthSessionId(newAuthSessionId, workspacePromise.data?.descriptor.gitAuthSessionId);
-                      setTimeout(() => {
-                        accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                        setShareDropdownOpen(true);
-                        setSmallKebabOpen(true);
-                      }, 0);
-                    }}
-                    filter={authSessionSelectFilter}
-                  />
-                }
-              >
-                {`Manage authentication sources for '${workspacePromise.data.descriptor.name}' to be able to create Repository, GitHub Gist or Bitbucket Snippet.`}
-              </Alert>
-              {canCreateGitRepository && (
-                <Tooltip
-                  data-testid={"create-git-repository-tooltip"}
-                  key={`dropdown-create-git-repository`}
-                  content={<div>{"Click to create a repository."}</div>}
-                  trigger={!canCreateGitRepository ? "mouseenter click" : ""}
-                  position="left"
-                >
-                  <DropdownItem
-                    icon={switchExpression(authProvider?.type as GitAuthProviderType, {
-                      bitbucket: <BitbucketIcon />,
-                      github: <GithubIcon />,
-                      default: <GitIcon />,
-                    })}
-                    data-testid={"create-git-repository-button"}
-                    component="button"
-                    onClick={() => setCreateGitRepositoryModalOpen(true)}
-                    isDisabled={!canCreateGitRepository}
-                  >
-                    Create{" "}
-                    {switchExpression(authProvider?.type as GitAuthProviderType, {
-                      github: "GitHub repository",
-                      bitbucket: "Bitbucket repository",
-                      default: "Git repository",
-                    })}
-                    ...
-                  </DropdownItem>
-                </Tooltip>
-              )}
-              {canCreateGistOrSnippet && (
-                <Tooltip
-                  data-testid={"create-gist-or-snippet-tooltip"}
-                  key={`dropdown-create-gist-or-snippet`}
-                  content={
-                    <div>
-                      {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
-                        github: i18n.editorToolbar.cantCreateGistTooltip,
-                        bitbucket: i18n.editorToolbar.cantCreateSnippetTooltip,
-                      })}
-                    </div>
-                  }
-                  trigger={!canCreateGistOrSnippet ? "mouseenter click" : ""}
-                  position="left"
-                >
-                  <DropdownItem
-                    icon={switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
-                      bitbucket: <BitbucketIcon />,
-                      github: <GithubIcon />,
-                    })}
-                    data-testid={"create-gist-or-snippet-button"}
-                    component="button"
-                    onClick={() => setCreateGistOrSnippetModalOpen(true)}
-                    isDisabled={!canCreateGistOrSnippet}
-                  >
-                    {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
-                      github: i18n.editorToolbar.createGist,
-                      bitbucket: i18n.editorToolbar.createSnippet,
-                    })}
-                  </DropdownItem>
-                </Tooltip>
-              )}
-            </DropdownGroup>,
-          ]
-        : []),
-    ],
-    [
-      onDownload,
-      props.workspaceFile.name,
-      shouldIncludeDownloadSvgDropdownItem,
-      downloadSvg,
-      downloadWorkspaceZip,
-      shouldIncludeEmbedDropdownItem,
-      openEmbedModal,
-      i18n.editorToolbar.embed,
-      i18n.editorToolbar.cantCreateGistTooltip,
-      i18n.editorToolbar.cantCreateSnippetTooltip,
-      i18n.editorToolbar.createGist,
-      i18n.editorToolbar.createSnippet,
-      i18n.names.git,
-      workspacePromise.data,
-      authSessionSelectFilter,
-      canCreateGitRepository,
-      authProvider?.type,
-      canCreateGistOrSnippet,
-      changeGitAuthSessionId,
-      accountsDispatch,
-    ]
-  );
-
-  useEffect(() => {
-    if (!workspacePromise.data) {
-      return;
-    }
-    if (downloadRef.current) {
-      downloadRef.current.download = `${props.workspaceFile.name}`;
-    }
-    if (downloadAllRef.current) {
-      downloadAllRef.current.download = `${workspacePromise.data.descriptor.name}.zip`;
-    }
-    if (downloadPreviewRef.current) {
-      downloadPreviewRef.current.download = `${props.workspaceFile.name}.svg`;
-    }
-  }, [props.workspaceFile, workspacePromise.data]);
-
-  const deleteWorkspaceFile = useCallback(async () => {
-    if (!workspacePromise.data) {
-      return;
-    }
-
-    if (workspacePromise.data.files.length === 1) {
-      await workspaces.deleteWorkspace({ workspaceId: props.workspaceFile.workspaceId });
-      history.push({ pathname: routes.home.path({}) });
-      return;
-    }
-
-    const nextFile = workspacePromise.data.files
-      .filter((f) => {
-        return (
-          f.relativePath !== props.workspaceFile.relativePath && editorEnvelopeLocator.hasMappingFor(f.relativePath)
-        );
-      })
-      .pop();
-
-    await workspaces.deleteFile({
-      file: props.workspaceFile,
-    });
-
-    if (!nextFile) {
-      history.push({ pathname: routes.home.path({}) });
-      return;
-    }
-
-    history.push({
-      pathname: routes.workspaceWithFilePath.path({
-        workspaceId: nextFile.workspaceId,
-        fileRelativePath: nextFile.relativePathWithoutExtension,
-        extension: nextFile.extension,
-      }),
-    });
-  }, [routes, history, workspacePromise.data, props.workspaceFile, workspaces, editorEnvelopeLocator]);
-
-  const workspaceNameRef = useRef<HTMLInputElement>(null);
-
-  const resetWorkspaceName = useCallback(() => {
-    if (workspaceNameRef.current && workspacePromise.data) {
-      workspaceNameRef.current.value = workspacePromise.data.descriptor.name;
-    }
-  }, [workspacePromise.data]);
-
-  useEffect(resetWorkspaceName, [resetWorkspaceName]);
-
-  const onRenameWorkspace = useCallback(
-    async (newName: string | undefined) => {
-      if (!newName) {
-        resetWorkspaceName();
-        return;
-      }
-
-      if (!workspacePromise.data || newName === workspacePromise.data.descriptor.name) {
-        return;
-      }
-
-      await workspaces.renameWorkspace({
-        workspaceId: workspacePromise.data.descriptor.workspaceId,
-        newName: newName.trim(),
-      });
-    },
-    [workspacePromise.data, workspaces, resetWorkspaceName]
-  );
-
-  const onWorkspaceNameKeyDown = useCallback(
-    (e: React.KeyboardEvent<HTMLInputElement>) => {
-      e.stopPropagation();
-      if (e.keyCode === 13 /* Enter */) {
-        e.currentTarget.blur();
-      } else if (e.keyCode === 27 /* ESC */) {
-        resetWorkspaceName();
-        e.currentTarget.blur();
-      }
-    },
-    [resetWorkspaceName]
-  );
-
-  const deleteFileDropdownItem = useMemo(() => {
-    return (
-      <DropdownItem key={"delete-dropdown-item"} onClick={deleteWorkspaceFile}>
-        <Flex flexWrap={{ default: "nowrap" }}>
-          <FlexItem>
-            <TrashIcon />
-            &nbsp;&nbsp;Delete <b>{`"${props.workspaceFile.nameWithoutExtension}"`}</b>
-          </FlexItem>
-          <FlexItem>
-            <b>
-              <FileLabel extension={props.workspaceFile.extension} />
-            </b>
-          </FlexItem>
-        </Flex>
-      </DropdownItem>
-    );
-  }, [deleteWorkspaceFile, props.workspaceFile]);
-
-  const pushingAlert = useGlobalAlert(
-    useCallback(() => {
-      if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-        return <></>;
-      }
-
-      return (
-        <Alert
-          variant="info"
-          title={
-            <>
-              <Spinner size={"sm"} />
-              &nbsp;&nbsp; {`Pushing to '${workspacePromise.data?.descriptor.origin.url}'...`}
-            </>
-          }
-        />
-      );
-    }, [workspacePromise])
-  );
-
-  const comittingAlert = useGlobalAlert(
-    useCallback(() => {
-      return (
-        <Alert
-          variant="info"
-          title={
-            <>
-              <Spinner size={"sm"} />
-              &nbsp;&nbsp; {`Creating commit...`}
-            </>
-          }
-        />
-      );
-    }, [])
-  );
-
-  const commitSuccessAlert = useGlobalAlert(
-    useCallback(() => {
-      return <Alert variant="success" title={`Commit created.`} />;
-    }, []),
-    { durationInSeconds: 2 }
-  );
-
-  const commitFailAlert = useGlobalAlert(
-    useCallback(({ close }, staticArgs: { reason: string }) => {
-      return (
-        <Alert
-          variant="danger"
-          title={`Failed to commit: ${staticArgs.reason}`}
-          actionClose={<AlertActionCloseButton onClose={close} />}
-        />
-      );
-    }, [])
-  );
-
-  const nothingToCommitAlert = useGlobalAlert(
-    useCallback(() => {
-      return <Alert variant="info" title={"Nothing to commit."} />;
-    }, []),
-    { durationInSeconds: 2 }
-  );
-
-  const createSavePointDropdownItem = useMemo(() => {
-    return (
-      <DropdownItem
-        key={"commit-dropdown-item"}
-        icon={<SaveIcon />}
-        onClick={async () => {
-          if (!(await workspaces.hasLocalChanges({ workspaceId: props.workspaceFile.workspaceId }))) {
-            nothingToCommitAlert.show();
-            return;
-          }
-          comittingAlert.show();
-          try {
-            await workspaces.createSavePoint({
-              workspaceId: props.workspaceFile.workspaceId,
-              gitConfig,
-            });
-            comittingAlert.close();
-            commitSuccessAlert.show();
-          } catch (e) {
-            comittingAlert.close();
-            commitFailAlert.show({ reason: e.message });
-          }
-        }}
-        description={"Create a save point"}
-      >
-        Commit
-      </DropdownItem>
-    );
-  }, [
-    workspaces,
-    props.workspaceFile.workspaceId,
-    comittingAlert,
-    nothingToCommitAlert,
-    gitConfig,
-    commitSuccessAlert,
-    commitFailAlert,
-  ]);
-
-  const pushSuccessAlert = useGlobalAlert(
-    useCallback(() => {
-      if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-        return <></>;
-      }
-
-      return <Alert variant="success" title={`Pushed to '${workspacePromise.data?.descriptor.origin.url}'`} />;
-    }, [workspacePromise]),
-    { durationInSeconds: 4 }
-  );
-
-  const pushErrorAlert = useGlobalAlert(
-    useCallback(
-      ({ close }) => {
-        if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-          return <></>;
-        }
-
-        return (
-          <Alert
-            variant="danger"
-            title={`Error Pushing to '${workspacePromise.data?.descriptor.origin.url}'`}
-            actionClose={<AlertActionCloseButton onClose={close} />}
-          />
-        );
-      },
-      [workspacePromise]
-    )
-  );
-
-  const pullingAlert = useGlobalAlert(
-    useCallback(() => {
-      if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-        return <></>;
-      }
-
-      return (
-        <Alert
-          variant="info"
-          title={
-            <>
-              <Spinner size={"sm"} />
-              &nbsp;&nbsp; {`Pulling from '${workspacePromise.data?.descriptor.origin.url}'...`}
-            </>
-          }
-        />
-      );
-    }, [workspacePromise])
-  );
-
-  const pullSuccessAlert = useGlobalAlert(
-    useCallback(() => {
-      if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-        return <></>;
-      }
-
-      return <Alert variant="success" title={`Pulled from '${workspacePromise.data?.descriptor.origin.url}'`} />;
-    }, [workspacePromise]),
-    { durationInSeconds: 4 }
-  );
-
-  const pushNewBranch = useCallback(
-    async (newBranchName: string) => {
-      if (!authInfo || !workspacePromise.data) {
-        return;
-      }
-
-      try {
-        pushingAlert.show();
-
-        await workspaces.createSavePoint({
-          workspaceId: props.workspaceFile.workspaceId,
-          gitConfig,
-        });
-
-        await workspaces.branch({ workspaceId: props.workspaceFile.workspaceId, checkout: false, name: newBranchName });
-
-        await workspaces.push({
-          workspaceId: props.workspaceFile.workspaceId,
-          remote: GIT_ORIGIN_REMOTE_NAME,
-          remoteRef: `refs/heads/${newBranchName}`,
-          ref: newBranchName,
-          force: false,
-          authInfo,
-        });
-
-        history.push({
-          pathname: routes.import.path({}),
-          search: routes.import.queryString({
-            url: `${workspacePromise.data.descriptor.origin.url}`,
-            branch: newBranchName,
-            authSessionId: workspacePromise.data.descriptor.gitAuthSessionId,
-          }),
-        });
-      } catch (e) {
-        pushErrorAlert.show();
-      } finally {
-        pushingAlert.close();
-      }
-    },
-    [
-      authInfo,
-      workspacePromise.data,
-      pushingAlert,
-      workspaces,
-      props.workspaceFile.workspaceId,
-      gitConfig,
-      history,
-      routes.import,
-      pushErrorAlert,
-    ]
-  );
-
-  const pullErrorAlert = useGlobalAlert<{ newBranchName: string; onTryAgain: () => any }>(
-    useCallback(
-      ({ close }, { newBranchName }) => {
-        if (workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.GIT) {
-          return <></>;
-        }
-
-        return (
-          <Alert
-            variant="danger"
-            title={`Error Pulling from '${workspacePromise.data?.descriptor.origin.url}'`}
-            actionClose={<AlertActionCloseButton onClose={close} />}
-            actionLinks={<></>}
-          >
-            {`This usually happens when your branch has conflicts with the upstream branch or you don't have permission to Pull.`}
-            <br />
-            <br />
-            {`You can save your work to a new branch.`}
-            <br />
-            <br />
-            <Tooltip
-              data-testid={"gist-it-tooltip"}
-              content={<div>{`You need select an authentication source to be able to Push to a new branch.`}</div>}
-              trigger={!canPushToGitRepository ? "mouseenter click" : ""}
-              position="left"
-            >
-              <Button
-                onClick={() => pushNewBranch(newBranchName)}
-                variant={ButtonVariant.link}
-                style={{ paddingLeft: 0 }}
-                isSmall={true}
-                isDisabled={!canPushToGitRepository}
-              >
-                {`Switch to '${newBranchName}'`}
-              </Button>
-            </Tooltip>
-            <br />
-            <br />
-
-            {`Or change the authentication source for '${workspacePromise.data?.descriptor.name}' and try again`}
-            <br />
-          </Alert>
-        );
-      },
-      [canPushToGitRepository, pushNewBranch, workspacePromise.data]
-    )
-  );
-
-  const pullFromGitRepository = useCallback(
-    async (args: { showAlerts: boolean }) => {
-      pullingAlert.close();
-      pullErrorAlert.close();
-      pullSuccessAlert.close();
-
-      if (args.showAlerts) {
-        pullingAlert.show();
-      }
-      await workspaces.createSavePoint({
-        workspaceId: props.workspaceFile.workspaceId,
-        gitConfig,
-      });
-
-      try {
-        await workspaces.pull({
-          workspaceId: props.workspaceFile.workspaceId,
-          authInfo,
-        });
-
-        if (args.showAlerts) {
-          pullSuccessAlert.show();
-        }
-      } catch (e) {
-        console.error(e);
-        if (args.showAlerts) {
-          const randomString = (Math.random() + 1).toString(36).substring(7);
-          const newBranchName = `${workspacePromise.data?.descriptor.origin.branch}-${randomString}`;
-          pullErrorAlert.show({ newBranchName, onTryAgain: () => pullFromGitRepository({ showAlerts: true }) });
-        }
-      } finally {
-        if (args.showAlerts) {
-          pullingAlert.close();
-        }
-      }
-    },
-    [
-      pullingAlert,
-      pullErrorAlert,
-      pullSuccessAlert,
-      workspaces,
-      props.workspaceFile.workspaceId,
-      gitConfig,
-      authInfo,
-      workspacePromise.data?.descriptor.origin.branch,
-    ]
-  );
-
-  const pushToGitRepository = useCallback(async () => {
-    pushingAlert.close();
-    pushErrorAlert.close();
-    pushSuccessAlert.close();
-
-    if (!authInfo) {
-      return;
-    }
-
-    pushingAlert.show();
-    try {
-      const workspaceId = props.workspaceFile.workspaceId;
-      await workspaces.createSavePoint({
-        workspaceId: workspaceId,
-        gitConfig,
-      });
-
-      const workspace = await workspaces.getWorkspace({ workspaceId });
-      await workspaces.push({
-        workspaceId: props.workspaceFile.workspaceId,
-        ref: workspace.origin.branch,
-        remote: GIST_ORIGIN_REMOTE_NAME,
-        remoteRef: `refs/heads/${workspace.origin.branch}`,
-        force: false,
-        authInfo,
-      });
-      await pullFromGitRepository({ showAlerts: false });
-      pushSuccessAlert.show();
-    } catch (e) {
-      console.error(e);
-      pushErrorAlert.show();
-    } finally {
-      pushingAlert.close();
-    }
-  }, [
-    pushingAlert,
-    pushErrorAlert,
-    pushSuccessAlert,
-    authInfo,
-    props.workspaceFile.workspaceId,
-    workspaces,
-    gitConfig,
-    pullFromGitRepository,
-  ]);
-
-  const navigationStatus = useNavigationStatus();
-  const navigationStatusToggle = useNavigationStatusToggle();
-  const confirmNavigationAlert = useGlobalAlert<{ lastBlockedLocation: Location }>(
-    useCallback(
-      (_, { lastBlockedLocation }) => (
-        <Alert
-          data-testid="unsaved-alert"
-          variant="warning"
-          title={
-            workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.LOCAL
-              ? i18n.editorPage.alerts.unsaved.titleLocal
-              : i18n.editorPage.alerts.unsaved.titleGit
-          }
-          actionClose={
-            <AlertActionCloseButton data-testid="unsaved-alert-close-button" onClose={navigationStatusToggle.unblock} />
-          }
-          actionLinks={
-            <>
-              <Divider inset={{ default: "insetMd" }} />
-              <br />
-              {(workspacePromise.data?.descriptor.origin.kind === WorkspaceKind.LOCAL && (
-                <AlertActionLink
-                  data-testid="unsaved-alert-save-button"
-                  onClick={() => {
-                    navigationStatusToggle.unblock();
-                    return downloadWorkspaceZip();
-                  }}
-                  style={{ fontWeight: "bold" }}
-                >
-                  {`${i18n.terms.download} '${workspacePromise.data?.descriptor.name}'`}
-                </AlertActionLink>
-              )) || (
-                <PushToGitAlertActionLinks
-                  changeGitAuthSessionId={changeGitAuthSessionId}
-                  workspaceDescriptor={workspacePromise.data?.descriptor}
-                  canPush={switchExpression(workspacePromise.data?.descriptor.origin.kind as WorkspaceKindGitBased, {
-                    BITBUCKET_SNIPPET: canUpdateGistOrSnippet,
-                    GITHUB_GIST: canUpdateGistOrSnippet,
-                    GIT: canPushToGitRepository,
-                  })}
-                  remoteRef={`${GIT_ORIGIN_REMOTE_NAME}/${workspacePromise.data?.descriptor.origin.branch}`}
-                  authSessionSelectFilter={authSessionSelectFilter}
-                  onPush={() => {
-                    navigationStatusToggle.unblock();
-                    switchExpression(workspacePromise.data?.descriptor.origin.kind as WorkspaceKindGitBased, {
-                      BITBUCKET_SNIPPET: updateGistOrSnippet,
-                      GITHUB_GIST: updateGistOrSnippet,
-                      GIT: pushToGitRepository,
-                    })();
-                  }}
-                />
-              )}
-              <br />
-              <br />
-              <AlertActionLink
-                data-testid="unsaved-alert-close-without-save-button"
-                onClick={() =>
-                  navigationBlockersBypass.execute(() => {
-                    history.push(lastBlockedLocation);
-                  })
-                }
-              >
-                {i18n.editorPage.alerts.unsaved.proceedAnyway}
-              </AlertActionLink>
-              <br />
-              <br />
-            </>
-          }
-        >
-          <br />
-          <p>{i18n.editorPage.alerts.unsaved.message}</p>
-        </Alert>
-      ),
-      [
-        workspacePromise.data?.descriptor,
-        i18n.editorPage.alerts.unsaved.titleLocal,
-        i18n.editorPage.alerts.unsaved.titleGit,
-        i18n.editorPage.alerts.unsaved.proceedAnyway,
-        i18n.editorPage.alerts.unsaved.message,
-        i18n.terms.download,
-        navigationStatusToggle,
-        changeGitAuthSessionId,
-        canUpdateGistOrSnippet,
-        canPushToGitRepository,
-        authSessionSelectFilter,
-        downloadWorkspaceZip,
-        updateGistOrSnippet,
-        pushToGitRepository,
-        navigationBlockersBypass,
-        history,
-      ]
-    )
-  );
-
-  useEffect(() => {
-    if (navigationStatus.lastBlockedLocation) {
-      confirmNavigationAlert.show({ lastBlockedLocation: navigationStatus.lastBlockedLocation });
-    } else {
-      confirmNavigationAlert.close();
-    }
-  }, [confirmNavigationAlert, navigationStatus]);
-
-  const [isVsCodeDropdownOpen, setVsCodeDropdownOpen] = useState(false);
-
-  const createRepositorySuccessAlert = useGlobalAlert<{ url: string }>(
-    useCallback(({ close }, { url }) => {
-      return (
-        <Alert
-          variant="success"
-          title={`GitHub repository created.`}
-          actionClose={<AlertActionCloseButton onClose={close} />}
-          actionLinks={<AlertActionLink onClick={() => window.open(url, "_blank")}>{url}</AlertActionLink>}
-        />
-      );
-    }, [])
-  );
-
-  const canSeeWorkspaceToolbar = useMemo(
-    () =>
-      workspacePromise.data?.descriptor.origin.kind !== WorkspaceKind.LOCAL || workspacePromise.data?.files.length > 1,
-    [workspacePromise.data?.descriptor.origin.kind, workspacePromise.data?.files.length]
-  );
-
-  return (
-    <PromiseStateWrapper
-      promise={workspacePromise}
-      resolved={(workspace) => {
-        return (
-          <>
-            <PageSection type={"nav"} variant={"light"} padding={{ default: "noPadding" }}>
-              {workspace && canSeeWorkspaceToolbar && (
-                <Flex
-                  justifyContent={{ default: "justifyContentSpaceBetween" }}
-                  flexWrap={{ default: "nowrap" }}
-                  spaceItems={{ default: "spaceItemsMd" }}
-                >
-                  <FlexItem style={{ minWidth: 0 }}>
-                    <Flex
-                      justifyContent={{ default: "justifyContentFlexStart" }}
-                      flexWrap={{ default: "nowrap" }}
-                      spaceItems={{ default: "spaceItemsSm" }}
-                      alignItems={{ default: "alignItemsCenter" }}
-                    >
-                      <FlexItem>
-                        <Button
-                          className={"kie-tools--masthead-hoverable"}
-                          variant={ButtonVariant.plain}
-                          onClick={() => history.push({ pathname: routes.home.path({}) })}
-                        >
-                          <AngleLeftIcon />
-                        </Button>
-                      </FlexItem>
-                      <FlexItem>
-                        <AuthSessionSelect
-                          title={`Select Git authentication for '${workspace.descriptor.name}'...`}
-                          isPlain={true}
-                          authSessionId={workspace.descriptor.gitAuthSessionId}
-                          showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
-                          setAuthSessionId={(newAuthSessionId) => {
-                            changeGitAuthSessionId(newAuthSessionId, workspace.descriptor.gitAuthSessionId);
-                            accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                          }}
-                          filter={authSessionSelectFilter}
-                        />
-                      </FlexItem>
-                      <FlexItem>
-                        <WorkspaceLabel descriptor={workspace.descriptor} />
-                      </FlexItem>
-                      <FlexItem
-                        style={{ minWidth: 0, padding: "0 8px 0 8px", flexShrink: 0 }}
-                        className={"kie-tools--masthead-hoverable"}
-                      >
-                        <FolderIcon style={{ marginRight: "8px", verticalAlign: "middle" }} />
-                        <div
-                          data-testid={"toolbar-title-workspace"}
-                          className={"kogito--editor__toolbar-name-container"}
-                          style={{ display: "inline-block", verticalAlign: "middle" }}
-                        >
-                          <Title
-                            aria-label={"EmbeddedEditorFile name"}
-                            headingLevel={"h3"}
-                            size={"md"}
-                            style={{
-                              fontStyle: "italic",
-                            }}
-                          >
-                            {workspace.descriptor.name}
-                          </Title>
-                          <TextInput
-                            ref={workspaceNameRef}
-                            type={"text"}
-                            aria-label={"Edit workspace name"}
-                            onKeyDown={onWorkspaceNameKeyDown}
-                            className={"kogito--editor__toolbar-subtitle"}
-                            onBlur={(e) => onRenameWorkspace(e.target.value)}
-                            style={{ fontStyle: "italic", top: "4px", height: "calc(100% - 8px)" }}
-                          />
-                        </div>
-                      </FlexItem>
-                      <FlexItem>
-                        <WorkspaceStatusIndicator workspace={workspace} />
-                      </FlexItem>
-                    </Flex>
-                  </FlexItem>
-                  {/*<Divider inset={{ default: "insetMd" }} isVertical={true} />*/}
-                  {workspace.descriptor.origin.kind === WorkspaceKind.GIT &&
-                    workspaceImportableUrl.type === UrlType.GITHUB_DOT_COM && (
-                      <FlexItem
-                        style={{
-                          minWidth: "137px",
-                        }}
-                      >
-                        <Dropdown
-                          className={"kie-tools--masthead-hoverable"}
-                          isPlain={true}
-                          onSelect={() => setVsCodeDropdownOpen(false)}
-                          isOpen={isVsCodeDropdownOpen}
-                          position={"right"}
-                          toggle={
-                            <DropdownToggle toggleIndicator={null} onToggle={setVsCodeDropdownOpen}>
-                              <Flex flexWrap={{ default: "nowrap" }}>
-                                <FlexItem
-                                  style={{
-                                    minWidth: 0 /* This is to make the flex parent not overflow horizontally */,
-                                  }}
-                                >
-                                  <Tooltip distance={5} position={"top-start"} content={workspace.descriptor.name}>
-                                    <TextContent>
-                                      <Text
-                                        component={TextVariants.small}
-                                        style={{
-                                          whiteSpace: "nowrap",
-                                          overflow: "hidden",
-                                          textOverflow: "ellipsis",
-                                        }}
-                                      >
-                                        <img
-                                          style={{
-                                            minWidth: "14px",
-                                            maxWidth: "14px",
-                                            marginTop: "-2px",
-                                            verticalAlign: "middle",
-                                          }}
-                                          alt="vscode-logo-blue"
-                                          src={routes.static.images.vscodeLogoBlue.path({})}
-                                        />
-                                        &nbsp;&nbsp;
-                                        {`Open "${workspace.descriptor.name}"`}
-                                      </Text>
-                                    </TextContent>
-                                  </Tooltip>
-                                </FlexItem>
-                                <FlexItem>
-                                  <CaretDownIcon />
-                                </FlexItem>
-                              </Flex>
-                            </DropdownToggle>
-                          }
-                          dropdownItems={[
-                            <DropdownGroup key={"open-in-vscode"}>
-                              {navigationStatus.shouldBlockNavigationTo({ pathname: "__external" }) && (
-                                <>
-                                  <Alert
-                                    isInline={true}
-                                    variant={"warning"}
-                                    title={"You have new changes to Push"}
-                                    actionLinks={
-                                      <PushToGitAlertActionLinks
-                                        changeGitAuthSessionId={changeGitAuthSessionId}
-                                        workspaceDescriptor={workspace.descriptor}
-                                        canPush={canPushToGitRepository}
-                                        authSessionSelectFilter={authSessionSelectFilter}
-                                        remoteRef={`${GIT_ORIGIN_REMOTE_NAME}/${workspace.descriptor.origin.branch}`}
-                                        onPush={pushToGitRepository}
-                                      />
-                                    }
-                                  >
-                                    {`Opening '${workspace.descriptor.name}' on vscode.dev won't show your latest changes.`}
-                                  </Alert>
-                                  <Divider />
-                                </>
-                              )}
-                              <DropdownItem
-                                style={{ minWidth: "400px" }}
-                                href={`https://vscode.dev/github${
-                                  new URL(workspace.descriptor.origin.url).pathname.endsWith(".git")
-                                    ? new URL(workspace.descriptor.origin.url).pathname.replace(".git", "")
-                                    : new URL(workspace.descriptor.origin.url).pathname
-                                }/tree/${workspace.descriptor.origin.branch}`}
-                                target={"_blank"}
-                                icon={<ExternalLinkAltIcon />}
-                                description={`The '${workspace.descriptor.origin.branch}' branch will be opened.`}
-                              >
-                                vscode.dev
-                              </DropdownItem>
-                              <Divider />
-                              <DropdownItem
-                                href={`vscode://vscode.git/clone?url=${workspace.descriptor.origin.url.toString()}`}
-                                target={"_blank"}
-                                icon={<ExternalLinkAltIcon />}
-                                description={"The default branch will be opened."}
-                              >
-                                VS Code Desktop
-                              </DropdownItem>
-                            </DropdownGroup>,
-                          ]}
-                        />
-                      </FlexItem>
-                    )}
-                </Flex>
-              )}
-            </PageSection>
-            <PageSection type={"nav"} variant={"light"} style={{ paddingTop: 0, paddingBottom: "16px" }}>
-              <Flex
-                justifyContent={{ default: "justifyContentSpaceBetween" }}
-                alignItems={{ default: "alignItemsCenter" }}
-                flexWrap={{ default: "nowrap" }}
-              >
-                <FlexItem style={{ minWidth: 0 }}>
-                  <PageHeaderToolsItem visibility={{ default: "visible" }}>
-                    <Flex flexWrap={{ default: "nowrap" }} alignItems={{ default: "alignItemsCenter" }}>
-                      <FlexItem style={{ minWidth: 0 }}>
-                        <FileSwitcher workspace={workspace} workspaceFile={props.workspaceFile} />
-                      </FlexItem>
-                      <FlexItem>
-                        {(isEdited && (
-                          <Tooltip content={"Saving in memory..."} position={"bottom"}>
-                            <TextContent
-                              style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}
-                            >
-                              <Text
-                                style={{ display: "flex" }}
-                                aria-label={"Saving in memory..."}
-                                data-testid="is-saving-in-memory-indicator"
-                                component={TextVariants.small}
-                              >
-                                <OutlinedClockIcon size={"sm"} style={{ margin: 0 }} />
-                              </Text>
-                            </TextContent>
-                          </Tooltip>
-                        )) || (
-                          <Tooltip content={"File is in memory."} position={"bottom"}>
-                            <TextContent
-                              style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}
-                            >
-                              <Text
-                                style={{ display: "flex" }}
-                                aria-label={"File is in memory."}
-                                data-testid="is-saved-in-memory-indicator"
-                                component={TextVariants.small}
-                              >
-                                <DesktopIcon size={"sm"} style={{ margin: 0 }} />
-                              </Text>
-                            </TextContent>
-                          </Tooltip>
-                        )}
-                      </FlexItem>
-                      <FlexItem>
-                        {(!isSaved && (
-                          <Tooltip content={"Writing file..."} position={"bottom"}>
-                            <TextContent
-                              style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}
-                            >
-                              <Text
-                                style={{ display: "flex" }}
-                                aria-label={"Writing file..."}
-                                data-testid="is-writing-indicator"
-                                component={TextVariants.small}
-                              >
-                                <OutlinedClockIcon size={"sm"} style={{ margin: 0 }} />
-                              </Text>
-                            </TextContent>
-                          </Tooltip>
-                        )) || (
-                          <Tooltip content={"File is written on disk."} position={"bottom"}>
-                            <TextContent
-                              style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}
-                            >
-                              <Text
-                                style={{ display: "flex" }}
-                                aria-label={"File is written on disk."}
-                                data-testid="is-written-indicator"
-                                component={TextVariants.small}
-                              >
-                                <OutlinedHddIcon size={"sm"} style={{ margin: 0 }} />
-                              </Text>
-                            </TextContent>
-                          </Tooltip>
-                        )}
-                      </FlexItem>
-                    </Flex>
-                  </PageHeaderToolsItem>
-                </FlexItem>
-                <FlexItem>
-                  <Toolbar>
-                    <ToolbarContent style={{ paddingRight: 0 }}>
-                      <ToolbarGroup>
-                        <ToolbarItem>
-                          <ResponsiveDropdown
-                            title={"Add file"}
-                            onClose={() => setNewFileDropdownMenuOpen(false)}
-                            position={"right"}
-                            isOpen={isNewFileDropdownMenuOpen}
-                            toggle={
-                              <ResponsiveDropdownToggle
-                                onToggle={() => setNewFileDropdownMenuOpen((prev) => !prev)}
-                                isPrimary={true}
-                                toggleIndicator={CaretDownIcon}
-                              >
-                                <PlusIcon />
-                                &nbsp;&nbsp;New file
-                              </ResponsiveDropdownToggle>
-                            }
-                          >
-                            <NewFileDropdownMenu
-                              workspaceDescriptor={workspace.descriptor}
-                              destinationDirPath={props.workspaceFile.relativeDirPath}
-                              onAddFile={async (file) => {
-                                setNewFileDropdownMenuOpen(false);
-                                if (!file) {
-                                  return;
-                                }
-
-                                history.push({
-                                  pathname: routes.workspaceWithFilePath.path({
-                                    workspaceId: file.workspaceId,
-                                    fileRelativePath: file.relativePathWithoutExtension,
-                                    extension: file.extension,
-                                  }),
-                                });
-                              }}
-                            />
-                          </ResponsiveDropdown>
-                        </ToolbarItem>
-                        <ToolbarItem visibility={hideWhenSmall}>
-                          {props.workspaceFile.extension === "dmn" && (
-                            <ToolbarGroup>
-                              <KieSandboxExtendedServicesButtons
-                                workspace={workspace}
-                                workspaceFile={props.workspaceFile}
-                                editorPageDock={props.editorPageDock}
-                              />
-                            </ToolbarGroup>
-                          )}
-                        </ToolbarItem>
-                        {isGistLikeWorkspaceKind(workspace.descriptor.origin.kind) && (
-                          <ToolbarItem>
-                            <Dropdown
-                              onSelect={() => setSyncGistOrSnippetDropdownOpen(false)}
-                              isOpen={isSyncGistOrSnippetDropdownOpen}
-                              position={DropdownPosition.right}
-                              toggle={
-                                <DropdownToggle
-                                  id={"sync-dropdown"}
-                                  data-testid={"sync-dropdown"}
-                                  onToggle={(isOpen) => setSyncGistOrSnippetDropdownOpen(isOpen)}
-                                >
-                                  Sync
-                                </DropdownToggle>
-                              }
-                              dropdownItems={[
-                                <DropdownGroup key={"sync-gist-or-snippet-dropdown-group"}>
-                                  <Tooltip
-                                    data-testid={"gist-or-snippet-it-tooltip"}
-                                    content={
-                                      <div>
-                                        {switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
-                                          GITHUB_GIST: i18n.editorToolbar.cantUpdateGistTooltip,
-                                          BITBUCKET_SNIPPET: i18n.editorToolbar.cantUpdateSnippetTooltip,
-                                        })}
-                                      </div>
-                                    }
-                                    trigger={!canUpdateGistOrSnippet ? "mouseenter click" : ""}
-                                    position="left"
-                                  >
-                                    <>
-                                      <DropdownItem
-                                        style={{ minWidth: "300px" }}
-                                        icon={switchExpression(
-                                          workspace.descriptor.origin.kind as WorkspaceKindGistLike,
-                                          {
-                                            BITBUCKET_SNIPPET: <BitbucketIcon />,
-                                            GITHUB_GIST: <GithubIcon />,
-                                          }
-                                        )}
-                                        onClick={updateGistOrSnippet}
-                                        isDisabled={!canUpdateGistOrSnippet}
-                                      >
-                                        Update{" "}
-                                        {switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
-                                          BITBUCKET_SNIPPET: "Bitbucket Snippet",
-                                          GITHUB_GIST: "GitHub Gist",
-                                        })}
-                                      </DropdownItem>
-                                      {canForkGitHubGist && (
-                                        <>
-                                          <Divider />
-                                          <li role="menuitem">
-                                            <Alert
-                                              isInline={true}
-                                              variant={"default"}
-                                              title={
-                                                <span style={{ whiteSpace: "nowrap" }}>
-                                                  {"Can't update Gists you don't own"}
-                                                </span>
-                                              }
-                                            >
-                                              <br />
-                                              {`You can create a fork of '${workspace.descriptor.name}' to save your updates.`}
-                                              <br />
-                                              <br />
-                                              <Button
-                                                onClick={forkGitHubGist}
-                                                variant={ButtonVariant.link}
-                                                isSmall={true}
-                                                style={{ paddingLeft: 0 }}
-                                              >
-                                                {`Fork Gist`}
-                                              </Button>
-                                              <br />
-                                              <br />
-                                              {`Or you can change the authentication source for '${workspace.descriptor.name}' to be able to Update Gist.`}
-                                              <br />
-                                              <br />
-                                              <AuthSessionSelect
-                                                title={`Select Git authentication for '${workspace.descriptor.name}'...`}
-                                                isPlain={false}
-                                                authSessionId={workspace.descriptor.gitAuthSessionId}
-                                                showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={
-                                                  AuthProviderGroup.GIT
-                                                }
-                                                setAuthSessionId={(newAuthSessionId) => {
-                                                  changeGitAuthSessionId(
-                                                    newAuthSessionId,
-                                                    workspace.descriptor.gitAuthSessionId
-                                                  );
-                                                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                                                  setTimeout(() => {
-                                                    setSyncGistOrSnippetDropdownOpen(true);
-                                                  }, 0);
-                                                }}
-                                                filter={authSessionSelectFilter}
-                                              />
-                                            </Alert>
-                                          </li>
-                                        </>
-                                      )}
-                                      {!canPushToGitRepository && (
-                                        <>
-                                          <Divider />
-                                          <Alert
-                                            isInline={true}
-                                            variant={"default"}
-                                            title={`Can't Update ${switchExpression(
-                                              authProvider?.type as GitAuthProviderType,
-                                              {
-                                                github: "GitHub repository",
-                                                bitbucket: "Bitbucket repository",
-                                                default: "Git repository",
-                                              }
-                                            )} without selecting a matching authentication source`}
-                                            actionLinks={
-                                              <AuthSessionSelect
-                                                title={`Select Git authentication for '${workspace.descriptor.name}'...`}
-                                                isPlain={false}
-                                                authSessionId={workspace.descriptor.gitAuthSessionId}
-                                                showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={
-                                                  AuthProviderGroup.GIT
-                                                }
-                                                setAuthSessionId={(newAuthSessionId) => {
-                                                  changeGitAuthSessionId(
-                                                    newAuthSessionId,
-                                                    workspace.descriptor.gitAuthSessionId
-                                                  );
-                                                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                                                  setTimeout(() => {
-                                                    setSyncGistOrSnippetDropdownOpen(true);
-                                                  }, 0);
-                                                }}
-                                                filter={authSessionSelectFilter}
-                                              />
-                                            }
-                                          >
-                                            {`Select an authentication source for '${
-                                              workspace.descriptor.name
-                                            }' to be able to Update ${switchExpression(
-                                              workspace.descriptor.origin.kind as WorkspaceKindGistLike,
-                                              {
-                                                GITHUB_GIST: "Github Gist",
-                                                BITBUCKET_SNIPPET: "Bitbucket Snippet",
-                                              }
-                                            )}.`}
-                                          </Alert>
-                                        </>
-                                      )}
-                                    </>
-                                  </Tooltip>
-                                </DropdownGroup>,
-                              ]}
-                            />
-                          </ToolbarItem>
-                        )}
-                        {workspace.descriptor.origin.kind === WorkspaceKind.GIT && (
-                          <ToolbarItem>
-                            <Dropdown
-                              onSelect={() => setSyncGitRepositoryDropdownOpen(false)}
-                              isOpen={isSyncGitRepositoryDropdownOpen}
-                              position={DropdownPosition.right}
-                              toggle={
-                                <DropdownToggle
-                                  id={"sync-dropdown"}
-                                  data-testid={"sync-dropdown"}
-                                  onToggle={(isOpen) => setSyncGitRepositoryDropdownOpen(isOpen)}
-                                >
-                                  Sync
-                                </DropdownToggle>
-                              }
-                              dropdownItems={[
-                                <DropdownGroup key={"sync-git-dropdown-group"}>
-                                  <DropdownItem
-                                    icon={<SyncAltIcon />}
-                                    onClick={() => pullFromGitRepository({ showAlerts: true })}
-                                    description={`Get new changes made upstream at '${GIT_ORIGIN_REMOTE_NAME}/${workspace.descriptor.origin.branch}'.`}
-                                  >
-                                    Pull
-                                  </DropdownItem>
-                                  <Tooltip
-                                    data-testid={"git-it-tooltip"}
-                                    content={
-                                      <div>{`You need to select an authentication source to Push to this repository.`}</div>
-                                    }
-                                    trigger={!canPushToGitRepository ? "mouseenter click" : ""}
-                                    position="left"
-                                  >
-                                    <>
-                                      <DropdownItem
-                                        icon={<ArrowCircleUpIcon />}
-                                        onClick={pushToGitRepository}
-                                        isDisabled={!canPushToGitRepository}
-                                        description={`Send your changes upstream to '${GIT_ORIGIN_REMOTE_NAME}/${workspace.descriptor.origin.branch}'.`}
-                                      >
-                                        Push
-                                      </DropdownItem>
-                                      {!canPushToGitRepository && (
-                                        <>
-                                          <Alert
-                                            isInline={true}
-                                            variant={"default"}
-                                            title={"Can't Push without selecting an authentication source"}
-                                            actionLinks={
-                                              <AuthSessionSelect
-                                                title={`Select Git authentication for '${workspace.descriptor.name}'...`}
-                                                isPlain={false}
-                                                authSessionId={workspace.descriptor.gitAuthSessionId}
-                                                showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={
-                                                  AuthProviderGroup.GIT
-                                                }
-                                                setAuthSessionId={(newAuthSessionId) => {
-                                                  changeGitAuthSessionId(
-                                                    newAuthSessionId,
-                                                    workspace.descriptor.gitAuthSessionId
-                                                  );
-                                                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                                                  setTimeout(() => {
-                                                    setSyncGitRepositoryDropdownOpen(true);
-                                                  });
-                                                }}
-                                                filter={authSessionSelectFilter}
-                                              />
-                                            }
-                                          >
-                                            {`Select an authentication source for '${workspace.descriptor.name}' to be able to Push.`}
-                                          </Alert>
-                                        </>
-                                      )}
-                                    </>
-                                  </Tooltip>
-                                </DropdownGroup>,
-                              ]}
-                            />
-                          </ToolbarItem>
-                        )}
-                        <ToolbarItem visibility={hideWhenSmall}>
-                          <Dropdown
-                            onSelect={() => setShareDropdownOpen(false)}
-                            isOpen={isShareDropdownOpen}
-                            dropdownItems={shareDropdownItems}
-                            position={DropdownPosition.right}
-                            toggle={
-                              <DropdownToggle
-                                id={"share-dropdown"}
-                                data-testid={"share-dropdown"}
-                                onToggle={(isOpen) => setShareDropdownOpen(isOpen)}
-                              >
-                                {i18n.editorToolbar.share}
-                              </DropdownToggle>
-                            }
-                          />
-                        </ToolbarItem>
-                        <ToolbarItem visibility={hideWhenSmall} style={{ marginRight: 0 }}>
-                          <KebabDropdown
-                            id={"kebab-lg"}
-                            state={[isLargeKebabOpen, setLargeKebabOpen]}
-                            items={[deleteFileDropdownItem, <Divider key={"divider-0"} />, createSavePointDropdownItem]}
-                          />
-                        </ToolbarItem>
-                        <ToolbarItem visibility={showWhenSmall} style={{ marginRight: 0 }}>
-                          <KebabDropdown
-                            id={"kebab-sm"}
-                            state={[isSmallKebabOpen, setSmallKebabOpen]}
-                            items={[
-                              deleteFileDropdownItem,
-                              <Divider key={"divider-0"} />,
-                              createSavePointDropdownItem,
-                              <Divider key={"divider-1"} />,
-                              ...shareDropdownItems,
-                              ...(props.workspaceFile.extension !== "dmn"
-                                ? []
-                                : [
-                                    <Divider key={"divider-2"} />,
-                                    <KieSandboxExtendedServicesDropdownGroup
-                                      workspace={workspace}
-                                      key="kie-sandbox-extended-services-group"
-                                    />,
-                                  ]),
-                            ]}
-                          />
-                        </ToolbarItem>
-                      </ToolbarGroup>
-                    </ToolbarContent>
-                  </Toolbar>
-                </FlexItem>
-              </Flex>
-            </PageSection>
-            <EmbedModal
-              workspace={workspace.descriptor}
-              workspaceFile={props.workspaceFile}
-              isOpen={isEmbedModalOpen}
-              onClose={() => setEmbedModalOpen(false)}
-            />
-            <CreateGitRepositoryModal
-              workspace={workspace.descriptor}
-              isOpen={isCreateGitRepositoryModalOpen}
-              onClose={() => setCreateGitRepositoryModalOpen(false)}
-              onSuccess={({ url }) => {
-                createRepositorySuccessAlert.show({ url });
-              }}
-            />
-            <CreateGistOrSnippetModal
-              workspace={workspace.descriptor}
-              isOpen={isCreateGistOrSnippetModalOpen}
-              onClose={() => setCreateGistOrSnippetModalOpen(false)}
-              onSuccess={({ url }) => {
-                successfullyCreatedGistOrSnippetAlert.show({ url });
-              }}
-              onError={() => {
-                errorAlert.show();
-              }}
-            />
-            <textarea ref={copyContentTextArea} style={{ height: 0, position: "absolute", zIndex: -1 }} />
-            <a ref={downloadRef} />
-            <a ref={downloadAllRef} />
-            <a ref={downloadPreviewRef} />
-          </>
-        );
-      }}
-    />
-  );
-}
-
-export function PushToGitAlertActionLinks(props: {
-  onPush: () => void;
-  canPush?: boolean;
-  remoteRef?: string;
-  workspaceDescriptor: WorkspaceDescriptor | undefined;
-  changeGitAuthSessionId: (a: React.SetStateAction<string | undefined>, b: string | undefined) => void;
-  authSessionSelectFilter: AuthSessionSelectFilter;
-}) {
-  const accountsDispatch = useAccountsDispatch();
-  if (props.workspaceDescriptor?.origin.kind === WorkspaceKind.GIT && !props.remoteRef) {
-    throw new Error("Should specify remoteRef for GIT workspaces");
-  }
-
-  const pushButton = useMemo(
-    () => (
-      <AlertActionLink onClick={props.onPush} style={{ fontWeight: "bold" }} isDisabled={!props.canPush}>
-        {props.workspaceDescriptor
-          ? switchExpression(props.workspaceDescriptor.origin.kind, {
-              GIT: `Push to '${props.remoteRef}'`,
-              GITHUB_GIST: "Update Gist",
-              BITBUCKET_SNIPPET: "Update Snippet",
-              default: "",
-            })
-          : ""}
-      </AlertActionLink>
-    ),
-    [props]
-  );
-
-  return (
-    <>
-      {!props.canPush && (
-        <Alert
-          isInline={true}
-          variant={"default"}
-          title={"Can't Push without selecting an authentication source"}
-          actionLinks={
-            <>
-              <AuthSessionSelect
-                title={`Select Git authentication for '${props.workspaceDescriptor?.name}'...`}
-                position={SelectPosition.right}
-                isPlain={false}
-                authSessionId={props.workspaceDescriptor?.gitAuthSessionId}
-                showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
-                setAuthSessionId={(newAuthSessionId) => {
-                  props.changeGitAuthSessionId(newAuthSessionId, props.workspaceDescriptor?.gitAuthSessionId);
-                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
-                }}
-                filter={props.authSessionSelectFilter}
-              />
-              <br />
-              <br />
-              {pushButton}
-            </>
-          }
-        >
-          {`Select an authentication source for '${props.workspaceDescriptor?.name}' to be able to Push.`}
-          <br />
-        </Alert>
-      )}
-      {props.canPush && pushButton}
-    </>
-  );
-}
-
-export function KebabDropdown(props: {
-  id: string;
-  items: React.ReactNode[];
-  state: [boolean, React.Dispatch<React.SetStateAction<boolean>>];
-}) {
-  return (
-    <Dropdown
-      className={"kie-tools--masthead-hoverable"}
-      isOpen={props.state[0]}
-      isPlain={true}
-      position={DropdownPosition.right}
-      onSelect={() => props.state[1](false)}
-      toggle={
-        <DropdownToggle
-          id={props.id}
-          toggleIndicator={null}
-          onToggle={(isOpen) => props.state[1](isOpen)}
-          ouiaId={props.id}
-        >
-          <EllipsisVIcon />
-        </DropdownToggle>
-      }
-      dropdownItems={props.items}
-    />
-  );
-}
diff --git a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/icons/IconPosition.java b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIcon.tsx
similarity index 58%
copy from packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/icons/IconPosition.java
copy to packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIcon.tsx
index c76fe691f8..568f1ecb9d 100644
--- a/packages/serverless-workflow-diagram-editor/sw-editor/sw-editor-client/src/main/java/org/kie/workbench/common/stunner/sw/client/shapes/icons/IconPosition.java
+++ b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIcon.tsx
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,12 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.kie.workbench.common.stunner.sw.client.shapes.icons;
 
-import com.ait.lienzo.client.core.types.Point2D;
+import React from "react";
+import { Icon } from "@patternfly/react-core/dist/js/components/Icon";
 
-public interface IconPosition {
+type Props = {
+  iconUrl?: string;
+};
 
-    Point2D RIGHT_TOP_CORNER = new Point2D(224, 6);
-    Point2D LEFT_FROM_RIGHT_TOP_CORNER = new Point2D(202, 6);
+export function AcceleratorIcon(props: Props) {
+  return props.iconUrl ? (
+    <Icon isInline style={{ verticalAlign: "middle" }}>
+      <img src={props.iconUrl} />
+    </Icon>
+  ) : (
+    <span>🚀</span>
+  );
 }
diff --git a/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIndicator.tsx b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIndicator.tsx
new file mode 100644
index 0000000000..ee6b795d7f
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorIndicator.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useState } from "react";
+import { useCurrentAccelerator } from "../../../accelerators/AcceleratorsHooks";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
+import { AcceleratorModal } from "./AcceleratorModal";
+import { AcceleratorIcon } from "./AcceleratorIcon";
+
+type Props = {
+  workspaceId: string;
+};
+
+export function AcceleratorIndicator(props: Props) {
+  const [isAcceleratorDetailsModalOpen, setAcceleratorDetailsModalOpen] = useState(false);
+  const currentAccelerator = useCurrentAccelerator(props.workspaceId);
+
+  if (!currentAccelerator) {
+    return <></>;
+  }
+
+  return (
+    <Tooltip
+      position={"right"}
+      content={
+        <>
+          <AcceleratorIcon iconUrl={currentAccelerator.iconUrl} />
+          &nbsp;
+          {currentAccelerator.name} Accelerator
+        </>
+      }
+    >
+      <>
+        <Button
+          variant={ButtonVariant.plain}
+          onClick={() => setAcceleratorDetailsModalOpen(true)}
+          className={"kie-tools--masthead-hoverable"}
+        >
+          <AcceleratorIcon iconUrl={currentAccelerator.iconUrl} />
+        </Button>
+        <AcceleratorModal
+          isOpen={isAcceleratorDetailsModalOpen}
+          onClose={() => setAcceleratorDetailsModalOpen(false)}
+          accelerator={currentAccelerator}
+        />
+      </>
+    </Tooltip>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorModal.tsx b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorModal.tsx
new file mode 100644
index 0000000000..b0f3982563
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorModal.tsx
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import { AcceleratorAppliedConfig } from "../../../accelerators/AcceleratorsApi";
+import { useOnlineI18n } from "../../../i18n";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
+import { Grid, GridItem } from "@patternfly/react-core/dist/js/layouts/Grid";
+import { Modal, ModalVariant } from "@patternfly/react-core/dist/js/components/Modal";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import { AcceleratorIcon } from "./AcceleratorIcon";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+
+type Props = {
+  accelerator: AcceleratorAppliedConfig;
+  isOpen: boolean;
+  onClose: () => any;
+  isApplying?: boolean;
+  onApplyAccelerator?: () => void;
+};
+
+export function AcceleratorModal(props: Props) {
+  const { i18n } = useOnlineI18n();
+
+  return (
+    <Modal
+      isOpen={props.isOpen}
+      onClose={props.onClose}
+      aria-label="Accelerator"
+      variant={ModalVariant.medium}
+      actions={
+        props.isApplying && [
+          <Button key="apply" variant="primary" onClick={props.onApplyAccelerator}>
+            {i18n.terms.apply}
+          </Button>,
+          <Button key="cancel" variant="link" onClick={props.onClose}>
+            {i18n.terms.cancel}
+          </Button>,
+        ]
+      }
+    >
+      <Title headingLevel="h1">
+        <AcceleratorIcon iconUrl={props.accelerator.iconUrl} />
+        &nbsp;
+        {props.accelerator.name} Accelerator
+      </Title>
+      <Grid style={{ margin: "1rem 0" }} hasGutter>
+        {props.isApplying && (
+          <GridItem span={12}>
+            <i>{i18n.accelerators.acceleratorDescription}</i>
+          </GridItem>
+        )}
+        <GridItem span={12}>
+          <p>
+            {i18n.accelerators.acceleratorDetails}
+            &nbsp;
+            <a href={props.accelerator.gitRepositoryUrl} target="__blank">
+              {props.accelerator.gitRepositoryUrl}
+            </a>
+          </p>
+          Git ref:{" "}
+          <small>
+            <pre style={{ display: "inline" }}>@{props.accelerator.gitRepositoryGitRef}</pre>
+          </small>
+        </GridItem>
+        <Divider />
+        <GridItem span={6}>
+          {props.isApplying ? i18n.accelerators.dmnFilesMove : i18n.accelerators.dmnFilesLocation}
+        </GridItem>
+        <GridItem span={6}>
+          <pre>{props.accelerator.dmnDestinationFolder}</pre>
+        </GridItem>
+        <GridItem span={6}>
+          {props.isApplying ? i18n.accelerators.pmmlFilesMove : i18n.accelerators.pmmlFilesLocation}
+        </GridItem>
+        <GridItem span={6}>
+          <pre>{props.accelerator.dmnDestinationFolder}</pre>
+        </GridItem>
+        <GridItem span={6}>
+          {props.isApplying ? i18n.accelerators.bpmnFilesMove : i18n.accelerators.bpmnFilesLocation}
+        </GridItem>
+        <GridItem span={6}>
+          <pre>{props.accelerator.bpmnDestinationFolder}</pre>
+        </GridItem>
+        <GridItem span={6}>
+          {props.isApplying ? i18n.accelerators.otherFilesMove : i18n.accelerators.otherFilesLocation}
+        </GridItem>
+        <GridItem span={6}>
+          <pre>{props.accelerator.otherFilesDestinationFolder}</pre>
+        </GridItem>
+        {!props.isApplying && props.accelerator.appliedAt && (
+          <>
+            <Divider />
+            <GridItem span={12}>
+              <i>
+                {i18n.accelerators.appliedAt} {new Date(props.accelerator.appliedAt).toLocaleString()}
+              </i>
+            </GridItem>
+          </>
+        )}
+        {props.isApplying && (
+          <>
+            <Divider />
+            <GridItem span={12}>
+              <i>{i18n.accelerators.applyDisclaimer}</i>
+            </GridItem>
+          </>
+        )}
+      </Grid>
+    </Modal>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorsDropdown.tsx b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorsDropdown.tsx
new file mode 100644
index 0000000000..8c535c31a1
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Accelerators/AcceleratorsDropdown.tsx
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useState } from "react";
+import { ResponsiveDropdown } from "../../../ResponsiveDropdown/ResponsiveDropdown";
+import { ResponsiveDropdownToggle } from "../../../ResponsiveDropdown/ResponsiveDropdownToggle";
+import { useEditorToolbarContext, useEditorToolbarDispatchContext } from "../EditorToolbarContextProvider";
+import CaretDownIcon from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
+import {
+  useAcceleratorsDispatch,
+  useAvailableAccelerators,
+  useCurrentAccelerator,
+} from "../../../accelerators/AcceleratorsHooks";
+import { DropdownItem } from "@patternfly/react-core/dist/js/components/Dropdown";
+import { WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { AcceleratorConfig } from "../../../accelerators/AcceleratorsApi";
+import { useOnlineI18n } from "../../../i18n";
+import { AcceleratorModal } from "./AcceleratorModal";
+import { AcceleratorIcon } from "./AcceleratorIcon";
+
+type Props = {
+  workspaceFile: WorkspaceFile;
+};
+
+export function AcceleratorsDropdown(props: Props) {
+  const { i18n } = useOnlineI18n();
+  const { isAcceleratorsDropdownOpen, workspace } = useEditorToolbarContext();
+  const { setAcceleratorsDropdownOpen } = useEditorToolbarDispatchContext();
+  const accelerators = useAvailableAccelerators();
+  const { applyAcceleratorToWorkspace } = useAcceleratorsDispatch(workspace);
+  const [isApplyModalOpen, setApplyModalOpen] = useState(false);
+  const [selectedAccelerator, setSelectedAccelerator] = useState<AcceleratorConfig | undefined>();
+
+  const currentAccelerator = useCurrentAccelerator(props.workspaceFile.workspaceId);
+
+  const onOpenApplyAccelerator = useCallback(
+    (accelerator: AcceleratorConfig) => {
+      setAcceleratorsDropdownOpen(false);
+      setSelectedAccelerator(accelerator);
+      setApplyModalOpen(true);
+    },
+    [setAcceleratorsDropdownOpen]
+  );
+
+  const onApplyAccelerator = useCallback(() => {
+    if (selectedAccelerator) {
+      applyAcceleratorToWorkspace(selectedAccelerator, props.workspaceFile);
+    }
+    setSelectedAccelerator(undefined);
+    setApplyModalOpen(false);
+  }, [applyAcceleratorToWorkspace, props.workspaceFile, selectedAccelerator]);
+
+  if (currentAccelerator) {
+    return <></>;
+  }
+
+  return (
+    <>
+      <ResponsiveDropdown
+        title="Accelerators"
+        className={"kie-tools--masthead-hoverable"}
+        isPlain={true}
+        onClose={() => setAcceleratorsDropdownOpen(false)}
+        position={"right"}
+        isOpen={isAcceleratorsDropdownOpen}
+        toggle={
+          <ResponsiveDropdownToggle
+            onToggle={() => setAcceleratorsDropdownOpen((prev) => !prev)}
+            toggleIndicator={CaretDownIcon}
+            icon={<i>🚀</i>}
+          >
+            {i18n.accelerators.applyAccelerator}
+          </ResponsiveDropdownToggle>
+        }
+        dropdownItems={accelerators.map((accelerator) => (
+          <DropdownItem
+            key={accelerator.name}
+            icon={<AcceleratorIcon iconUrl={accelerator.iconUrl} />}
+            onClick={() => onOpenApplyAccelerator(accelerator)}
+          >
+            {accelerator.name}...
+          </DropdownItem>
+        ))}
+      />
+      {selectedAccelerator && (
+        <AcceleratorModal
+          isOpen={isApplyModalOpen}
+          onClose={() => setApplyModalOpen(false)}
+          onApplyAccelerator={onApplyAccelerator}
+          accelerator={selectedAccelerator}
+          isApplying={true}
+        />
+      )}
+    </>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/EditorToolbar.tsx b/packages/online-editor/src/editor/Toolbar/EditorToolbar.tsx
new file mode 100644
index 0000000000..b173250ace
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/EditorToolbar.tsx
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2019 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useEffect, useMemo, useRef } from "react";
+import {
+  Dropdown,
+  DropdownItem,
+  DropdownPosition,
+  DropdownToggle,
+} from "@patternfly/react-core/dist/js/components/Dropdown";
+import {
+  Toolbar,
+  ToolbarContent,
+  ToolbarGroup,
+  ToolbarItem,
+  ToolbarItemProps,
+} from "@patternfly/react-core/dist/js/components/Toolbar";
+import { SaveIcon } from "@patternfly/react-icons/dist/js/icons/save-icon";
+import { useOnlineI18n } from "../../i18n";
+import { KieSandboxExtendedServicesButtons } from "../KieSandboxExtendedServices/KieSandboxExtendedServicesButtons";
+import { useRoutes } from "../../navigation/Hooks";
+import { EmbeddedEditorRef } from "@kie-tools-core/editor/dist/embedded";
+import { useHistory } from "react-router";
+import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { PlusIcon } from "@patternfly/react-icons/dist/js/icons/plus-icon";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { NewFileDropdownMenu } from "./NewFileDropdownMenu";
+import { PageHeaderToolsItem, PageSection } from "@patternfly/react-core/dist/js/components/Page";
+import { FileLabel } from "../../filesList/FileLabel";
+import {
+  useWorkspaceGitStatusPromise,
+  useWorkspacePromise,
+  WorkspaceGitStatusType,
+} from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspaceHooks";
+import { FileSwitcher } from "./FileSwitcher";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import { KieSandboxExtendedServicesDropdownGroup } from "../KieSandboxExtendedServices/KieSandboxExtendedServicesDropdownGroup";
+import { TrashIcon } from "@patternfly/react-icons/dist/js/icons/trash-icon";
+import { CaretDownIcon } from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
+import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { EditorPageDockDrawerRef } from "../EditorPageDockDrawer";
+import { useEditorEnvelopeLocator } from "../../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
+import { ResponsiveDropdown } from "../../ResponsiveDropdown/ResponsiveDropdown";
+import { ResponsiveDropdownToggle } from "../../ResponsiveDropdown/ResponsiveDropdownToggle";
+import { useAuthSession } from "../../authSessions/AuthSessionsContext";
+import { KebabDropdown } from "./KebabDropdown";
+import { VsCodeDropdownMenu } from "./VsCodeDropdownMenu";
+import { DownloadDropdownGroup } from "./Share/DownloadDropdownGroup";
+import { GitDropdownGroup } from "./Share/GitDropdownGroup";
+import { EmbedDropdownGroup } from "./Share/EmbedDropdownGroup";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { useGitIntegration } from "./GitIntegration/GitIntegrationContextProvider";
+import {
+  EditorToolbarContextProvider,
+  useEditorToolbarContext,
+  useEditorToolbarDispatchContext,
+} from "./EditorToolbarContextProvider";
+import { WorkspaceToolbar } from "./Workspace/WorkspaceToolbar";
+import { useWorkspaceNavigationBlocker } from "./Workspace/Hooks";
+import { FileStatus } from "./FileStatus";
+import { SyncDropdownMenu } from "./SyncDropdownMenu";
+import { AcceleratorsDropdown } from "./Accelerators/AcceleratorsDropdown";
+import { listDeletedFiles } from "../../workspace/components/WorkspaceStatusIndicator";
+import { PromiseState } from "@kie-tools-core/react-hooks/dist/PromiseState";
+
+export interface Props {
+  editor: EmbeddedEditorRef | undefined;
+  workspaceFile: WorkspaceFile;
+  editorPageDock: EditorPageDockDrawerRef | undefined;
+}
+
+const showWhenSmall: ToolbarItemProps["visibility"] = {
+  default: "visible",
+  "2xl": "hidden",
+  xl: "hidden",
+  lg: "visible",
+  md: "visible",
+};
+
+const hideWhenSmall: ToolbarItemProps["visibility"] = {
+  default: "hidden",
+  "2xl": "visible",
+  xl: "visible",
+  lg: "hidden",
+  md: "hidden",
+};
+
+const hideWhenTiny: ToolbarItemProps["visibility"] = {
+  default: "hidden",
+  "2xl": "visible",
+  xl: "visible",
+  lg: "visible",
+  md: "hidden",
+};
+
+export function EditorToolbarWithWorkspace(
+  props: Props & { workspace: ActiveWorkspace; workspaceGitStatusPromise: PromiseState<WorkspaceGitStatusType> }
+) {
+  const routes = useRoutes();
+  const editorEnvelopeLocator = useEditorEnvelopeLocator();
+  const history = useHistory();
+  const workspaces = useWorkspaces();
+  const { i18n } = useOnlineI18n();
+  const copyContentTextArea = useRef<HTMLTextAreaElement>(null);
+
+  const { alerts } = useGitIntegration();
+
+  const { isNewFileDropdownMenuOpen, isShareDropdownOpen, isLargeKebabOpen, isSmallKebabOpen } =
+    useEditorToolbarContext();
+
+  const { setNewFileDropdownMenuOpen, setShareDropdownOpen, setLargeKebabOpen, setSmallKebabOpen } =
+    useEditorToolbarDispatchContext();
+
+  useWorkspaceNavigationBlocker(props.workspace);
+
+  const { gitConfig } = useAuthSession(props.workspace.descriptor.gitAuthSessionId);
+
+  const shareDropdownItems = useMemo(
+    () => [
+      <DownloadDropdownGroup
+        editor={props.editor}
+        workspaceFile={props.workspaceFile}
+        workspace={props.workspace}
+        key="download-dropdown-group"
+      />,
+      <EmbedDropdownGroup workspaceFile={props.workspaceFile} workspace={props.workspace} key="embed-dropdown-group" />,
+      <GitDropdownGroup workspace={props.workspace} key="git-dropdown-group" />,
+    ],
+    [props.editor, props.workspaceFile, props.workspace]
+  );
+
+  const handleDeletedWorkspaceFile = useCallback(() => {
+    const nextFile = props.workspace.files
+      .filter((f) => {
+        return (
+          f.relativePath !== props.workspaceFile.relativePath && editorEnvelopeLocator.hasMappingFor(f.relativePath)
+        );
+      })
+      .pop();
+    if (!nextFile) {
+      history.push({ pathname: routes.home.path({}) });
+      return;
+    }
+
+    history.push({
+      pathname: routes.workspaceWithFilePath.path({
+        workspaceId: nextFile.workspaceId,
+        fileRelativePath: nextFile.relativePathWithoutExtension,
+        extension: nextFile.extension,
+      }),
+    });
+  }, [
+    editorEnvelopeLocator,
+    history,
+    props.workspace.files,
+    props.workspaceFile.relativePath,
+    routes.home,
+    routes.workspaceWithFilePath,
+  ]);
+
+  const deleteWorkspaceFile = useCallback(async () => {
+    if (props.workspace.files.length === 1) {
+      await workspaces.deleteWorkspace({ workspaceId: props.workspaceFile.workspaceId });
+      history.push({ pathname: routes.home.path({}) });
+      return;
+    }
+
+    await workspaces.deleteFile({
+      file: props.workspaceFile,
+    });
+
+    handleDeletedWorkspaceFile();
+  }, [props.workspace.files.length, props.workspaceFile, workspaces, handleDeletedWorkspaceFile, history, routes.home]);
+
+  const deleteFileDropdownItem = useMemo(() => {
+    return (
+      <DropdownItem key={"delete-dropdown-item"} onClick={deleteWorkspaceFile}>
+        <Flex flexWrap={{ default: "nowrap" }}>
+          <FlexItem>
+            <TrashIcon />
+            &nbsp;&nbsp;Delete <b>{`"${props.workspaceFile.nameWithoutExtension}"`}</b>
+          </FlexItem>
+          <FlexItem>
+            <b>
+              <FileLabel extension={props.workspaceFile.extension} />
+            </b>
+          </FlexItem>
+        </Flex>
+      </DropdownItem>
+    );
+  }, [deleteWorkspaceFile, props.workspaceFile]);
+
+  const createSavePointDropdownItem = useMemo(() => {
+    return (
+      <DropdownItem
+        key={"commit-dropdown-item"}
+        icon={<SaveIcon />}
+        onClick={async () => {
+          if (!(await workspaces.hasLocalChanges({ workspaceId: props.workspaceFile.workspaceId }))) {
+            alerts.nothingToCommitAlert.show();
+            return;
+          }
+          alerts.comittingAlert.show();
+          try {
+            await workspaces.createSavePoint({
+              workspaceId: props.workspaceFile.workspaceId,
+              gitConfig,
+            });
+            alerts.comittingAlert.close();
+            alerts.commitSuccessAlert.show();
+          } catch (e) {
+            alerts.comittingAlert.close();
+            alerts.commitFailAlert.show({ reason: e.message });
+          }
+        }}
+        description={"Create a save point"}
+      >
+        Commit
+      </DropdownItem>
+    );
+  }, [
+    workspaces,
+    props.workspaceFile.workspaceId,
+    alerts.comittingAlert,
+    alerts.nothingToCommitAlert,
+    alerts.commitSuccessAlert,
+    alerts.commitFailAlert,
+    gitConfig,
+  ]);
+
+  const canSeeWorkspaceToolbar = useMemo(
+    () =>
+      props.workspace.descriptor.origin.kind !== WorkspaceKind.LOCAL ||
+      props.workspace.files.length +
+        listDeletedFiles({
+          workspaceDescriptor: props.workspace.descriptor,
+          workspaceGitStatusPromise: props.workspaceGitStatusPromise,
+        }).length >
+        1,
+    [props.workspace.descriptor, props.workspace.files.length, props.workspaceGitStatusPromise]
+  );
+
+  return (
+    <>
+      <PageSection type={"nav"} variant={"light"} padding={{ default: "noPadding" }}>
+        {canSeeWorkspaceToolbar && (
+          <Flex
+            justifyContent={{ default: "justifyContentSpaceBetween" }}
+            flexWrap={{ default: "nowrap" }}
+            spaceItems={{ default: "spaceItemsMd" }}
+          >
+            <FlexItem style={{ minWidth: 0 }}>
+              <WorkspaceToolbar
+                workspace={props.workspace}
+                workspaceGitStatusPromise={props.workspaceGitStatusPromise}
+                currentWorkspaceFile={props.workspaceFile}
+                onDeletedWorkspaceFile={handleDeletedWorkspaceFile}
+              />
+            </FlexItem>
+            <VsCodeDropdownMenu workspace={props.workspace} />
+          </Flex>
+        )}
+      </PageSection>
+      <PageSection type={"nav"} variant={"light"} style={{ paddingTop: 0, paddingBottom: "16px" }}>
+        <Flex
+          justifyContent={{ default: "justifyContentSpaceBetween" }}
+          alignItems={{ default: "alignItemsCenter" }}
+          flexWrap={{ default: "nowrap" }}
+        >
+          <FlexItem style={{ minWidth: 0 }}>
+            <PageHeaderToolsItem visibility={{ default: "visible" }}>
+              <Flex flexWrap={{ default: "nowrap" }} alignItems={{ default: "alignItemsCenter" }}>
+                <FlexItem style={{ minWidth: 0 }}>
+                  <FileSwitcher
+                    workspace={props.workspace}
+                    gitStatusProps={
+                      canSeeWorkspaceToolbar
+                        ? {
+                            workspaceDescriptor: props.workspace.descriptor,
+                            workspaceGitStatusPromise: props.workspaceGitStatusPromise,
+                          }
+                        : undefined
+                    }
+                    workspaceFile={props.workspaceFile}
+                    onDeletedWorkspaceFile={handleDeletedWorkspaceFile}
+                  />
+                </FlexItem>
+                <FileStatus workspace={props.workspace} workspaceFile={props.workspaceFile} editor={props.editor} />
+              </Flex>
+            </PageHeaderToolsItem>
+          </FlexItem>
+          <FlexItem>
+            <Toolbar>
+              <ToolbarContent style={{ paddingRight: 0 }}>
+                <ToolbarGroup>
+                  <ToolbarItem>
+                    <AcceleratorsDropdown workspaceFile={props.workspaceFile} />
+                  </ToolbarItem>
+                  <ToolbarItem>
+                    <ResponsiveDropdown
+                      title={"Add file"}
+                      onClose={() => setNewFileDropdownMenuOpen(false)}
+                      position={"right"}
+                      isOpen={isNewFileDropdownMenuOpen}
+                      toggle={
+                        <ResponsiveDropdownToggle
+                          onToggle={() => setNewFileDropdownMenuOpen((prev) => !prev)}
+                          isPrimary={true}
+                          toggleIndicator={CaretDownIcon}
+                        >
+                          <PlusIcon />
+                          &nbsp;&nbsp;New file
+                        </ResponsiveDropdownToggle>
+                      }
+                    >
+                      <NewFileDropdownMenu
+                        workspaceDescriptor={props.workspace.descriptor}
+                        destinationDirPath={props.workspaceFile.relativeDirPath}
+                        onAddFile={async (file) => {
+                          setNewFileDropdownMenuOpen(false);
+                          if (!file) {
+                            return;
+                          }
+
+                          history.push({
+                            pathname: routes.workspaceWithFilePath.path({
+                              workspaceId: file.workspaceId,
+                              fileRelativePath: file.relativePathWithoutExtension,
+                              extension: file.extension,
+                            }),
+                          });
+                        }}
+                      />
+                    </ResponsiveDropdown>
+                  </ToolbarItem>
+                  <ToolbarItem visibility={hideWhenSmall}>
+                    {props.workspaceFile.extension === "dmn" && (
+                      <ToolbarGroup>
+                        <KieSandboxExtendedServicesButtons
+                          workspace={props.workspace}
+                          workspaceFile={props.workspaceFile}
+                          editorPageDock={props.editorPageDock}
+                        />
+                      </ToolbarGroup>
+                    )}
+                  </ToolbarItem>
+                  {props.workspace.descriptor.origin.kind !== WorkspaceKind.LOCAL && (
+                    <ToolbarItem>
+                      <SyncDropdownMenu workspace={props.workspace} />
+                    </ToolbarItem>
+                  )}
+                  <ToolbarItem visibility={hideWhenSmall}>
+                    <Dropdown
+                      onSelect={() => setShareDropdownOpen(false)}
+                      isOpen={isShareDropdownOpen}
+                      dropdownItems={shareDropdownItems}
+                      position={DropdownPosition.right}
+                      toggle={
+                        <DropdownToggle
+                          id={"share-dropdown"}
+                          data-testid={"share-dropdown"}
+                          onToggle={(isOpen) => setShareDropdownOpen(isOpen)}
+                        >
+                          {i18n.editorToolbar.share}
+                        </DropdownToggle>
+                      }
+                    />
+                  </ToolbarItem>
+                  <ToolbarItem visibility={hideWhenSmall} style={{ marginRight: 0 }}>
+                    <KebabDropdown
+                      id={"kebab-lg"}
+                      state={[isLargeKebabOpen, setLargeKebabOpen]}
+                      items={[deleteFileDropdownItem, <Divider key={"divider-0"} />, createSavePointDropdownItem]}
+                    />
+                  </ToolbarItem>
+                  <ToolbarItem visibility={showWhenSmall} style={{ marginRight: 0 }}>
+                    <KebabDropdown
+                      id={"kebab-sm"}
+                      state={[isSmallKebabOpen, setSmallKebabOpen]}
+                      items={[
+                        deleteFileDropdownItem,
+                        <Divider key={"divider-0"} />,
+                        createSavePointDropdownItem,
+                        <Divider key={"divider-1"} />,
+                        ...shareDropdownItems,
+                        ...(props.workspaceFile.extension !== "dmn"
+                          ? []
+                          : [
+                              <Divider key={"divider-2"} />,
+                              <KieSandboxExtendedServicesDropdownGroup
+                                workspace={props.workspace}
+                                key="kie-sandbox-extended-services-group"
+                              />,
+                            ]),
+                      ]}
+                    />
+                  </ToolbarItem>
+                </ToolbarGroup>
+              </ToolbarContent>
+            </Toolbar>
+          </FlexItem>
+        </Flex>
+      </PageSection>
+      <textarea ref={copyContentTextArea} style={{ height: 0, position: "absolute", zIndex: -1 }} />
+    </>
+  );
+}
+
+export function EditorToolbar(props: Props) {
+  const workspacePromise = useWorkspacePromise(props.workspaceFile.workspaceId);
+  const workspaceGitStatusPromise = useWorkspaceGitStatusPromise(workspacePromise.data?.descriptor);
+  if (!workspacePromise.data) {
+    return <></>;
+  }
+
+  return (
+    <EditorToolbarContextProvider {...props} workspace={workspacePromise.data}>
+      <EditorToolbarWithWorkspace
+        {...props}
+        workspace={workspacePromise.data}
+        workspaceGitStatusPromise={workspaceGitStatusPromise}
+      />
+    </EditorToolbarContextProvider>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/EditorToolbarContextProvider.tsx b/packages/online-editor/src/editor/Toolbar/EditorToolbarContextProvider.tsx
new file mode 100644
index 0000000000..f212e59c38
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/EditorToolbarContextProvider.tsx
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, {
+  Dispatch,
+  ReactNode,
+  RefObject,
+  SetStateAction,
+  createContext,
+  useCallback,
+  useContext,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { GitIntegrationContextProvider } from "./GitIntegration/GitIntegrationContextProvider";
+import { WorkspaceFile, useWorkspaces } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { CreateGitRepositoryModal } from "./GitIntegration/CreateGitRepositoryModal";
+import { CreateGistOrSnippetModal } from "./GitIntegration/CreateGistOrSnippetModal";
+import { EmbedModal } from "./Share/EmbedModal";
+import { EmbeddedEditorRef } from "@kie-tools-core/editor/dist/embedded";
+import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { useAuthSession } from "../../authSessions/AuthSessionsContext";
+
+export type EditorToolbarContextType = {
+  isEmbedModalOpen: boolean;
+  isCreateGitRepositoryModalOpen: boolean;
+  isCreateGistOrSnippetModalOpen: boolean;
+  isShareDropdownOpen: boolean;
+  isSyncGistOrSnippetDropdownOpen: boolean;
+  isSyncGitRepositoryDropdownOpen: boolean;
+  isLargeKebabOpen: boolean;
+  isSmallKebabOpen: boolean;
+  isNewFileDropdownMenuOpen: boolean;
+  isAcceleratorsDropdownOpen: boolean;
+  downloadRef: RefObject<HTMLAnchorElement>;
+  downloadAllRef: RefObject<HTMLAnchorElement>;
+  downloadPreviewRef: RefObject<HTMLAnchorElement>;
+  downloadWorkspaceZip: () => Promise<void>;
+  workspace: ActiveWorkspace;
+};
+
+export type EditorToolbarDispatchContextType = {
+  setEmbedModalOpen: Dispatch<SetStateAction<boolean>>;
+  setCreateGitRepositoryModalOpen: Dispatch<SetStateAction<boolean>>;
+  setCreateGistOrSnippetModalOpen: Dispatch<SetStateAction<boolean>>;
+  setShareDropdownOpen: Dispatch<SetStateAction<boolean>>;
+  setSyncGistOrSnippetDropdownOpen: Dispatch<SetStateAction<boolean>>;
+  setSyncGitRepositoryDropdownOpen: Dispatch<SetStateAction<boolean>>;
+  setLargeKebabOpen: Dispatch<SetStateAction<boolean>>;
+  setSmallKebabOpen: Dispatch<SetStateAction<boolean>>;
+  setNewFileDropdownMenuOpen: Dispatch<SetStateAction<boolean>>;
+  setAcceleratorsDropdownOpen: Dispatch<SetStateAction<boolean>>;
+};
+
+export const EditorToolbarContext = createContext<EditorToolbarContextType>({} as any);
+export const EditorToolbarDispatchContext = createContext<EditorToolbarDispatchContextType>({} as any);
+
+type Props = {
+  workspace: ActiveWorkspace;
+  workspaceFile: WorkspaceFile;
+  children: ReactNode;
+  editor: EmbeddedEditorRef | undefined;
+};
+
+export function EditorToolbarContextProvider(props: Props) {
+  const [isEmbedModalOpen, setEmbedModalOpen] = useState(false);
+  const [isCreateGitRepositoryModalOpen, setCreateGitRepositoryModalOpen] = useState(false);
+  const [isCreateGistOrSnippetModalOpen, setCreateGistOrSnippetModalOpen] = useState(false);
+  const [isShareDropdownOpen, setShareDropdownOpen] = useState(false);
+  const [isSyncGistOrSnippetDropdownOpen, setSyncGistOrSnippetDropdownOpen] = useState(false);
+  const [isSyncGitRepositoryDropdownOpen, setSyncGitRepositoryDropdownOpen] = useState(false);
+  const [isAcceleratorsDropdownOpen, setAcceleratorsDropdownOpen] = useState(false);
+  const [isLargeKebabOpen, setLargeKebabOpen] = useState(false);
+  const [isSmallKebabOpen, setSmallKebabOpen] = useState(false);
+  const [isNewFileDropdownMenuOpen, setNewFileDropdownMenuOpen] = useState(false);
+  const downloadRef = useRef<HTMLAnchorElement>(null);
+  const downloadAllRef = useRef<HTMLAnchorElement>(null);
+  const downloadPreviewRef = useRef<HTMLAnchorElement>(null);
+  const workspaces = useWorkspaces();
+  const { gitConfig } = useAuthSession(props.workspace.descriptor.gitAuthSessionId);
+
+  const downloadWorkspaceZip = useCallback(async () => {
+    if (!props.editor) {
+      return;
+    }
+
+    const zipBlob = await workspaces.prepareZip({ workspaceId: props.workspaceFile.workspaceId });
+    if (downloadAllRef.current) {
+      downloadAllRef.current.href = URL.createObjectURL(zipBlob);
+      downloadAllRef.current.click();
+    }
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.LOCAL) {
+      await workspaces.createSavePoint({ workspaceId: props.workspaceFile.workspaceId, gitConfig });
+    }
+  }, [
+    props.editor,
+    props.workspaceFile.workspaceId,
+    props.workspace.descriptor.origin.kind,
+    workspaces,
+    downloadAllRef,
+    gitConfig,
+  ]);
+
+  const value = useMemo(
+    () => ({
+      isEmbedModalOpen,
+      isCreateGitRepositoryModalOpen,
+      isCreateGistOrSnippetModalOpen,
+      isShareDropdownOpen,
+      isSyncGistOrSnippetDropdownOpen,
+      isSyncGitRepositoryDropdownOpen,
+      isAcceleratorsDropdownOpen,
+      isLargeKebabOpen,
+      isSmallKebabOpen,
+      isNewFileDropdownMenuOpen,
+      downloadRef,
+      downloadAllRef,
+      downloadPreviewRef,
+      downloadWorkspaceZip,
+      workspace: props.workspace,
+    }),
+    [
+      isCreateGistOrSnippetModalOpen,
+      isCreateGitRepositoryModalOpen,
+      isEmbedModalOpen,
+      isLargeKebabOpen,
+      isNewFileDropdownMenuOpen,
+      isShareDropdownOpen,
+      isSmallKebabOpen,
+      isSyncGistOrSnippetDropdownOpen,
+      isSyncGitRepositoryDropdownOpen,
+      isAcceleratorsDropdownOpen,
+      downloadWorkspaceZip,
+      props.workspace,
+    ]
+  );
+
+  const dispatch = useMemo(
+    () => ({
+      setEmbedModalOpen,
+      setCreateGitRepositoryModalOpen,
+      setCreateGistOrSnippetModalOpen,
+      setShareDropdownOpen,
+      setSyncGistOrSnippetDropdownOpen,
+      setSyncGitRepositoryDropdownOpen,
+      setLargeKebabOpen,
+      setSmallKebabOpen,
+      setNewFileDropdownMenuOpen,
+      setAcceleratorsDropdownOpen,
+    }),
+    []
+  );
+
+  return (
+    <EditorToolbarContext.Provider value={value}>
+      <EditorToolbarDispatchContext.Provider value={dispatch}>
+        <GitIntegrationContextProvider workspace={props.workspace}>
+          {props.children}
+          <CreateGitRepositoryModal
+            workspace={props.workspace.descriptor}
+            isOpen={isCreateGitRepositoryModalOpen}
+            onClose={() => setCreateGitRepositoryModalOpen(false)}
+          />
+          <CreateGistOrSnippetModal
+            workspace={props.workspace.descriptor}
+            isOpen={isCreateGistOrSnippetModalOpen}
+            onClose={() => setCreateGistOrSnippetModalOpen(false)}
+          />
+          <EmbedModal
+            workspace={props.workspace.descriptor}
+            workspaceFile={props.workspaceFile}
+            isOpen={isEmbedModalOpen}
+            onClose={() => setEmbedModalOpen(false)}
+          />
+          <>
+            <a ref={downloadRef} />
+            <a ref={downloadAllRef} />
+            <a ref={downloadPreviewRef} />
+          </>
+        </GitIntegrationContextProvider>
+      </EditorToolbarDispatchContext.Provider>
+    </EditorToolbarContext.Provider>
+  );
+}
+
+export function useEditorToolbarContext() {
+  return useContext(EditorToolbarContext);
+}
+
+export function useEditorToolbarDispatchContext() {
+  return useContext(EditorToolbarDispatchContext);
+}
diff --git a/packages/online-editor/src/editor/Toolbar/FileStatus.tsx b/packages/online-editor/src/editor/Toolbar/FileStatus.tsx
new file mode 100644
index 0000000000..1b33627fec
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/FileStatus.tsx
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useEffect, useMemo } from "react";
+import { EmbeddedEditorRef, useDirtyState } from "@kie-tools-core/editor/dist/embedded";
+import { WorkspaceFile, useWorkspaces } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
+import OutlinedClockIcon from "@patternfly/react-icons/dist/js/icons/outlined-clock-icon";
+import DesktopIcon from "@patternfly/react-icons/dist/js/icons/desktop-icon";
+import { useSharedValue } from "@kie-tools-core/envelope-bus/dist/hooks";
+import OutlinedHddIcon from "@patternfly/react-icons/dist/js/icons/outlined-hdd-icon";
+
+type Props = {
+  workspace: ActiveWorkspace;
+  workspaceFile: WorkspaceFile;
+  editor: EmbeddedEditorRef | undefined;
+};
+
+export function FileStatus(props: Props) {
+  const workspaces = useWorkspaces();
+  const isEdited = useDirtyState(props.editor);
+
+  const [flushes] = useSharedValue(
+    workspaces.workspacesSharedWorker.workspacesWorkerBus.clientApi.shared.kieSandboxWorkspacesStorage_flushes
+  );
+
+  const isSaved = useMemo(() => {
+    return !isEdited && flushes && !flushes.some((f) => f.includes(props.workspaceFile.workspaceId));
+  }, [isEdited, flushes, props.workspaceFile.workspaceId]);
+
+  // Prevent from closing without flushing before.
+  useEffect(() => {
+    if (isSaved) {
+      return;
+    }
+
+    window.onbeforeunload = () => "Some changes are not written to disk yet.";
+    return () => {
+      window.onbeforeunload = null;
+    };
+  }, [isSaved]);
+
+  return (
+    <>
+      <FlexItem>
+        {(isEdited && (
+          <Tooltip content={"Saving in memory..."} position={"bottom"}>
+            <TextContent style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}>
+              <Text
+                style={{ display: "flex" }}
+                aria-label={"Saving in memory..."}
+                data-testid="is-saving-in-memory-indicator"
+                component={TextVariants.small}
+              >
+                <OutlinedClockIcon size={"sm"} style={{ margin: 0 }} />
+              </Text>
+            </TextContent>
+          </Tooltip>
+        )) || (
+          <Tooltip content={"File is in memory."} position={"bottom"}>
+            <TextContent style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}>
+              <Text
+                style={{ display: "flex" }}
+                aria-label={"File is in memory."}
+                data-testid="is-saved-in-memory-indicator"
+                component={TextVariants.small}
+              >
+                <DesktopIcon size={"sm"} style={{ margin: 0 }} />
+              </Text>
+            </TextContent>
+          </Tooltip>
+        )}
+      </FlexItem>
+      <FlexItem>
+        {(!isSaved && (
+          <Tooltip content={"Writing file..."} position={"bottom"}>
+            <TextContent style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}>
+              <Text
+                style={{ display: "flex" }}
+                aria-label={"Writing file..."}
+                data-testid="is-writing-indicator"
+                component={TextVariants.small}
+              >
+                <OutlinedClockIcon size={"sm"} style={{ margin: 0 }} />
+              </Text>
+            </TextContent>
+          </Tooltip>
+        )) || (
+          <Tooltip content={"File is written on disk."} position={"bottom"}>
+            <TextContent style={{ color: "gray", ...(!props.workspaceFile ? { visibility: "hidden" } : {}) }}>
+              <Text
+                style={{ display: "flex" }}
+                aria-label={"File is written on disk."}
+                data-testid="is-written-indicator"
+                component={TextVariants.small}
+              >
+                <OutlinedHddIcon size={"sm"} style={{ margin: 0 }} />
+              </Text>
+            </TextContent>
+          </Tooltip>
+        )}
+      </FlexItem>
+    </>
+  );
+}
diff --git a/packages/online-editor/src/editor/FileSwitcher.tsx b/packages/online-editor/src/editor/Toolbar/FileSwitcher.tsx
similarity index 51%
rename from packages/online-editor/src/editor/FileSwitcher.tsx
rename to packages/online-editor/src/editor/Toolbar/FileSwitcher.tsx
index 61082f489e..eee495cb4b 100644
--- a/packages/online-editor/src/editor/FileSwitcher.tsx
+++ b/packages/online-editor/src/editor/Toolbar/FileSwitcher.tsx
@@ -16,13 +16,12 @@
 
 import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
 import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
-import { useRoutes } from "../navigation/Hooks";
 import * as React from "react";
 import { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import { join } from "path";
 import { Dropdown } from "@patternfly/react-core/dist/js/components/Dropdown";
 import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
-import { FileLabel } from "../filesList/FileLabel";
+import { FileLabel } from "../../filesList/FileLabel";
 import { Toggle } from "@patternfly/react-core/dist/js/components/Dropdown/Toggle";
 import { Title } from "@patternfly/react-core/dist/js/components/Title";
 import { Popover } from "@patternfly/react-core/dist/js/components/Popover";
@@ -46,29 +45,25 @@ import { ThLargeIcon } from "@patternfly/react-icons/dist/js/icons/th-large-icon
 import { ListIcon } from "@patternfly/react-icons/dist/js/icons/list-icon";
 import { useWorkspaceDescriptorsPromise } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspacesHooks";
 import { PromiseStateWrapper, useCombinedPromiseState } from "@kie-tools-core/react-hooks/dist/PromiseState";
-import { Split, SplitItem } from "@patternfly/react-core/dist/js/layouts/Split";
 import { Button } from "@patternfly/react-core/dist/js/components/Button";
-import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
 import { useWorkspacesFilesPromise } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspacesFiles";
 import { Skeleton } from "@patternfly/react-core/dist/js/components/Skeleton";
 import { Card, CardBody, CardHeader, CardHeaderMain } from "@patternfly/react-core/dist/js/components/Card";
 import { Gallery } from "@patternfly/react-core/dist/js/layouts/Gallery";
-import { useHistory } from "react-router";
 import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye";
 import { EmptyState, EmptyStateIcon } from "@patternfly/react-core/dist/js/components/EmptyState";
 import { CubesIcon } from "@patternfly/react-icons/dist/js/icons/cubes-icon";
-import { ArrowRightIcon } from "@patternfly/react-icons/dist/js/icons/arrow-right-icon";
-import { ArrowLeftIcon } from "@patternfly/react-icons/dist/js/icons/arrow-left-icon";
-import { useEditorEnvelopeLocator } from "../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
+import { useEditorEnvelopeLocator } from "../../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
 import { VariableSizeList } from "react-window";
 import AutoSizer from "react-virtualized-auto-sizer";
 import {
   FileDataList,
   FileLink,
   FileListItem,
+  FileListItemDisplayMode,
   getFileDataListHeight,
   SingleFileWorkspaceDataList,
-} from "../filesList/FileDataList";
+} from "../../filesList/FileDataList";
 import {
   DataList,
   DataListCell,
@@ -76,26 +71,45 @@ import {
   DataListItemCells,
   DataListItemRow,
 } from "@patternfly/react-core/dist/js/components/DataList";
-import { WorkspaceListItem } from "../workspace/components/WorkspaceListItem";
-import { usePreviewSvg } from "../previewSvgs/PreviewSvgHooks";
-import { WorkspaceLoadingMenuItem } from "../workspace/components/WorkspaceLoadingCard";
+import { WorkspaceListItem } from "../../workspace/components/WorkspaceListItem";
+import { usePreviewSvg } from "../../previewSvgs/PreviewSvgHooks";
+import { WorkspaceLoadingMenuItem } from "../../workspace/components/WorkspaceLoadingCard";
+import {
+  listDeletedFiles,
+  resolveGitLocalChangesStatus,
+  WorkspaceGitLocalChangesStatus,
+} from "../../workspace/components/WorkspaceStatusIndicator";
+import { Checkbox } from "@patternfly/react-core/dist/js/components/Checkbox";
+import { SearchInput } from "@patternfly/react-core/dist/js/components/SearchInput";
+import { switchExpression } from "../../switchExpression/switchExpression";
+import { GitStatusProps } from "../../workspace/components/GitStatusIndicatorActions";
 
 const ROOT_MENU_ID = "rootMenu";
 
-enum FilesDropdownMode {
-  LIST_MODELS,
-  LIST_MODELS_AND_OTHERS,
+enum FilesMenuMode {
+  LIST,
   CAROUSEL,
 }
 
 const MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX = 500;
 const MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN = 40;
+// properties to be used for menu height calculation
+const FILE_SWITCHER_INITIAL_HEIGHT_OFFSET_IN_PX = 204;
+const MENU_HEIGHT_MAX_LIMIT_CSS = `calc(100vh - ${FILE_SWITCHER_INITIAL_HEIGHT_OFFSET_IN_PX}px)` as const;
+const DRILLDOWN_NAVIGATION_MENU_ITEM_HEIGHT_IN_PX = 40;
+const MENU_SEARCH_HEIGHT_IN_PX = 64;
+const MENU_SHOW_CHANGED_CHECKBOX_HEIGHT_IN_PX = 36;
+const MENU_DIVIDER_HEIGHT_IN_PX = 17;
 
-export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile: WorkspaceFile }) {
+export function FileSwitcher(props: {
+  workspace: ActiveWorkspace;
+  gitStatusProps?: GitStatusProps;
+  workspaceFile: WorkspaceFile;
+  onDeletedWorkspaceFile: () => void;
+}) {
   const workspaces = useWorkspaces();
   const workspaceFileNameRef = useRef<HTMLInputElement>(null);
   const [newFileNameValid, setNewFileNameValid] = useState<boolean>(true);
-  const [filesDropdownMode, setFilesDropdownMode] = useState(FilesDropdownMode.LIST_MODELS);
 
   const resetWorkspaceFileName = useCallback(() => {
     if (workspaceFileNameRef.current) {
@@ -174,15 +188,11 @@ export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile:
   const [menuHeights, setMenuHeights] = useState<{ [key: string]: number }>({});
   const [activeMenu, setActiveMenu] = useState(ROOT_MENU_ID);
 
-  useEffect(() => {
-    setMenuHeights({});
-  }, [props.workspace, filesDropdownMode, activeMenu]);
+  const [filesMenuMode, setFilesMenuMode] = useState(FilesMenuMode.LIST);
 
   useEffect(() => {
-    setFilesDropdownMode((prev) =>
-      prev === FilesDropdownMode.LIST_MODELS_AND_OTHERS ? FilesDropdownMode.LIST_MODELS : prev
-    );
-  }, [activeMenu]);
+    setMenuHeights({});
+  }, [props.workspace, filesMenuMode, activeMenu]);
 
   useEffect(() => {
     if (isFilesDropdownOpen) {
@@ -194,21 +204,25 @@ export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile:
     setActiveMenu(`dd${props.workspace.descriptor.workspaceId}`);
   }, [isFilesDropdownOpen, props.workspace.descriptor.workspaceId]);
 
-  const drillIn = useCallback((fromMenuId, toMenuId, pathId) => {
+  const drillIn = useCallback((_event, fromMenuId, toMenuId, pathId) => {
     setMenuDrilledIn((prev) => [...prev, fromMenuId]);
     setDrilldownPath((prev) => [...prev, pathId]);
     setActiveMenu(toMenuId);
   }, []);
 
-  const drillOut = useCallback((toMenuId) => {
+  const drillOut = useCallback((_event, toMenuId) => {
     setMenuDrilledIn((prev) => prev.slice(0, prev.length - 1));
     setDrilldownPath((prev) => prev.slice(0, prev.length - 1));
     setActiveMenu(toMenuId);
   }, []);
 
   const setHeight = useCallback((menuId: string, height: number) => {
-    // do not try to simplify this ternary's condition as some heights are 0, resulting in an infinite loop.
-    setMenuHeights((prev) => (prev[menuId] === height ? prev : { ...prev, [menuId]: height }));
+    setMenuHeights((prev) => {
+      if (prev[menuId] === undefined || (menuId !== ROOT_MENU_ID && prev[menuId] !== height)) {
+        return { ...prev, [menuId]: height };
+      }
+      return prev;
+    });
   }, []);
 
   const workspacesMenuItems = useMemo(() => {
@@ -221,11 +235,11 @@ export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile:
         activeMenu={activeMenu}
         currentWorkspace={props.workspace}
         onSelectFile={() => setFilesDropdownOpen(false)}
-        filesDropdownMode={filesDropdownMode}
-        setFilesDropdownMode={setFilesDropdownMode}
+        filesMenuMode={filesMenuMode}
+        setFilesMenuMode={setFilesMenuMode}
       />
     );
-  }, [activeMenu, filesDropdownMode, props.workspace]);
+  }, [activeMenu, filesMenuMode, props.workspace]);
 
   return (
     <>
@@ -336,11 +350,6 @@ export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile:
               style={{
                 boxShadow: "none",
                 minWidth: `${MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX}px`,
-                width: `${
-                  filesDropdownMode === FilesDropdownMode.LIST_MODELS_AND_OTHERS
-                    ? MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX * 2
-                    : MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX
-                }px`,
               }}
               id={ROOT_MENU_ID}
               containsDrilldown={true}
@@ -350,37 +359,45 @@ export function FileSwitcher(props: { workspace: ActiveWorkspace; workspaceFile:
               onDrillIn={drillIn}
               onDrillOut={drillOut}
               onGetMenuHeight={setHeight}
+              className={"kie-sandbox--files-menu"}
             >
               <MenuContent
                 // MAGIC NUMBER ALERT
                 //
                 // 204px is the exact number that allows the menu to grow to
                 // the maximum size of the screen without adding scroll to the page.
-                maxMenuHeight={`calc(100vh - 204px)`}
+                maxMenuHeight={MENU_HEIGHT_MAX_LIMIT_CSS}
                 menuHeight={activeMenu === ROOT_MENU_ID ? undefined : `${menuHeights[activeMenu]}px`}
-                style={{ overflow: "hidden" }}
               >
-                <MenuList>
+                <MenuList style={{ padding: 0 }}>
                   <MenuItem
                     itemId={props.workspace.descriptor.workspaceId}
                     direction={"down"}
                     drilldownMenu={
                       <DrilldownMenu id={`dd${props.workspace.descriptor.workspaceId}`}>
                         <FilesMenuItems
-                          shouldFocusOnSearch={activeMenu === `dd${props.workspace.descriptor.workspaceId}`}
-                          filesDropdownMode={filesDropdownMode}
-                          setFilesDropdownMode={setFilesDropdownMode}
-                          workspaceDescriptor={props.workspace.descriptor}
-                          workspaceFiles={props.workspace.files}
+                          shouldFocusOnSearch={activeMenu.startsWith(`dd${props.workspace.descriptor.workspaceId}`)}
+                          filesMenuMode={filesMenuMode}
+                          setFilesMenuMode={setFilesMenuMode}
+                          workspace={props.workspace}
                           currentWorkspaceFile={props.workspaceFile}
                           onSelectFile={() => setFilesDropdownOpen(false)}
+                          currentWorkspaceGitStatusProps={props.gitStatusProps}
+                          onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
                         />
                       </DrilldownMenu>
                     }
                   >
                     Current
                   </MenuItem>
-                  {workspacesMenuItems}
+                  <MenuGroup
+                    style={{
+                      maxHeight: `calc(${MENU_HEIGHT_MAX_LIMIT_CSS} - ${DRILLDOWN_NAVIGATION_MENU_ITEM_HEIGHT_IN_PX}px)` /* height of menu minus the height of Current item*/,
+                      overflowY: "auto",
+                    }}
+                  >
+                    {workspacesMenuItems}
+                  </MenuGroup>
                 </MenuList>
               </MenuContent>
             </Menu>
@@ -395,8 +412,8 @@ export function WorkspacesMenuItems(props: {
   activeMenu: string;
   currentWorkspace: ActiveWorkspace;
   onSelectFile: () => void;
-  filesDropdownMode: FilesDropdownMode;
-  setFilesDropdownMode: React.Dispatch<React.SetStateAction<FilesDropdownMode>>;
+  filesMenuMode: FilesMenuMode;
+  setFilesMenuMode: React.Dispatch<React.SetStateAction<FilesMenuMode>>;
 }) {
   const editorEnvelopeLocator = useEditorEnvelopeLocator();
   const workspaceDescriptorsPromise = useWorkspaceDescriptorsPromise();
@@ -443,13 +460,13 @@ export function WorkspacesMenuItems(props: {
                       itemId={descriptor.workspaceId}
                       direction={"down"}
                       drilldownMenu={
-                        <DrilldownMenu id={`dd${descriptor.workspaceId}`}>
+                        <DrilldownMenu id={`dd${descriptor.workspaceId}`} style={{ position: "fixed" }}>
+                          {/* position:fixed important to render properly inside menugroup*/}
                           <FilesMenuItems
-                            shouldFocusOnSearch={props.activeMenu === `dd${descriptor.workspaceId}`}
-                            filesDropdownMode={props.filesDropdownMode}
-                            setFilesDropdownMode={props.setFilesDropdownMode}
-                            workspaceDescriptor={descriptor}
-                            workspaceFiles={workspaceFiles.get(descriptor.workspaceId) ?? []}
+                            shouldFocusOnSearch={props.activeMenu.startsWith(`dd${descriptor.workspaceId}`)}
+                            filesMenuMode={props.filesMenuMode}
+                            setFilesMenuMode={props.setFilesMenuMode}
+                            workspace={{ descriptor, files: workspaceFiles.get(descriptor.workspaceId) ?? [] }}
                             onSelectFile={props.onSelectFile}
                           />
                         </DrilldownMenu>
@@ -503,7 +520,19 @@ export function FileSvg(props: { workspaceFile: WorkspaceFile }) {
   return (
     <>
       <PromiseStateWrapper
-        pending={<Skeleton height={"180px"} style={{ margin: "10px" }} />}
+        pending={
+          imgRef.current ? (
+            <Bullseye>
+              <img
+                style={{ height: "180px", margin: "10px" }}
+                ref={imgRef}
+                alt={`SVG for ${props.workspaceFile.relativePath}`}
+              />
+            </Bullseye>
+          ) : (
+            <Skeleton height={"180px"} style={{ margin: "10px" }} />
+          )
+        }
         rejected={() => (
           <div style={{ height: "180px", margin: "10px", borderRadius: "5px", backgroundColor: "#EEE" }}>
             <Bullseye>
@@ -526,78 +555,37 @@ export function FileSvg(props: { workspaceFile: WorkspaceFile }) {
   );
 }
 
-export function SearchableFilesMenuGroup(props: {
-  shouldFocusOnSearch: boolean;
-  filesDropdownMode: FilesDropdownMode;
-  label: string;
+export function FilteredFilesMenuGroup(props: {
+  filesMenuMode: FilesMenuMode;
   allFiles: WorkspaceFile[];
+  filteredFiles: WorkspaceFile[];
   search: string;
-  setSearch: React.Dispatch<React.SetStateAction<string>>;
   children: (args: { filteredFiles: WorkspaceFile[] }) => React.ReactNode;
+  heightMaxLimitCss: string;
+  style?: React.CSSProperties;
 }) {
-  const searchInputRef = useRef<HTMLInputElement>(null);
-
-  useEffect(() => {
-    if (props.shouldFocusOnSearch) {
-      const task = setTimeout(() => {
-        searchInputRef.current?.focus();
-      }, 500);
-      return () => {
-        clearTimeout(task);
-      };
-    }
-  }, [props.shouldFocusOnSearch, props.filesDropdownMode]);
-
-  const filteredFiles = useMemo(
-    () => props.allFiles.filter((file) => file.name.toLowerCase().includes(props.search.toLowerCase())),
-    [props.allFiles, props.search]
-  );
-
   const height = useMemo(() => {
-    if (
-      props.filesDropdownMode === FilesDropdownMode.LIST_MODELS ||
-      props.filesDropdownMode === FilesDropdownMode.LIST_MODELS_AND_OTHERS
-    ) {
+    if (props.filesMenuMode === FilesMenuMode.LIST) {
       // No reason to know the exact size.
       const sizeOfFirst50Elements = props.allFiles
         .slice(0, 50)
         .map((f) => getFileDataListHeight(f))
         .reduce((a, b) => a + b, 0);
-
-      // MAGIC NUMBER ALERT
-      //
-      // 440px is the exact number that allows the menu to grow to the end of the screen without adding scroll  to the
-      // entire page, It includes the first menu item, the search bar and the "View other files" button at the bottom.
-      return `max(300px, min(calc(100vh - 440px), ${sizeOfFirst50Elements}px))`;
-    } else if (props.filesDropdownMode === FilesDropdownMode.CAROUSEL) {
-      // MAGIC NUMBER ALERT
-      //
-      // 384px is the exact number that allows the menu to grow to the end of the screen without
-      // adding a scroll to the entire page. It includes the first menu item and the search bar.
-      //
+      return `max(300px, min(${props.heightMaxLimitCss}, ${sizeOfFirst50Elements}px))`;
+    } else if (props.filesMenuMode === FilesMenuMode.CAROUSEL) {
       // 280px is the size of a File SVG card.
-      return `min(calc(100vh - 384px), calc(${props.allFiles.length} * 280px))`;
+      return `min(${props.heightMaxLimitCss}, calc(${props.allFiles.length} * 280px))`;
     } else {
       return "";
     }
-  }, [props.allFiles, props.filesDropdownMode]);
+  }, [props.allFiles, props.filesMenuMode, props.heightMaxLimitCss]);
 
   return (
-    <MenuGroup label={props.label}>
+    <MenuGroup>
       {/* Allows for arrows to work when editing the text. */}
-      <MenuInput onKeyDown={(e) => e.stopPropagation()}>
-        <TextInput
-          ref={searchInputRef}
-          value={props.search}
-          aria-label={"Other files menu items"}
-          iconVariant={"search"}
-          type={"search"}
-          onChange={(value) => props.setSearch(value)}
-        />
-      </MenuInput>
-      <div style={{ overflowY: "auto", height }}>
-        {filteredFiles.length > 0 && props.children({ filteredFiles })}
-        {filteredFiles.length <= 0 && (
+      <div style={{ ...props.style, height }}>
+        {props.filteredFiles.length > 0 && props.children({ filteredFiles: props.filteredFiles })}
+        {props.filteredFiles.length <= 0 && (
           <Bullseye>
             <EmptyState>
               <EmptyStateIcon icon={CubesIcon} />
@@ -613,72 +601,354 @@ export function SearchableFilesMenuGroup(props: {
 }
 
 export function FilesMenuItems(props: {
-  workspaceDescriptor: WorkspaceDescriptor;
-  workspaceFiles: WorkspaceFile[];
+  workspace: ActiveWorkspace;
+  currentWorkspaceGitStatusProps?: GitStatusProps;
   currentWorkspaceFile?: WorkspaceFile;
+  onDeletedWorkspaceFile?: () => void;
   onSelectFile: () => void;
-  filesDropdownMode: FilesDropdownMode;
-  setFilesDropdownMode: React.Dispatch<React.SetStateAction<FilesDropdownMode>>;
+  filesMenuMode: FilesMenuMode;
+  setFilesMenuMode: React.Dispatch<React.SetStateAction<FilesMenuMode>>;
   shouldFocusOnSearch: boolean;
 }) {
-  const history = useHistory();
-  const routes = useRoutes();
   const editorEnvelopeLocator = useEditorEnvelopeLocator();
 
-  const sortedAndFilteredFiles = useMemo(
-    () =>
-      props.workspaceFiles
-        .sort((a, b) => a.relativePath.localeCompare(b.relativePath))
-        .filter((file) => file.relativePath !== props.currentWorkspaceFile?.relativePath),
-    [props.workspaceFiles, props.currentWorkspaceFile]
+  const [topSectionHeightInPx, setTopSectionHeightInPx] = useState<number>(
+    DRILLDOWN_NAVIGATION_MENU_ITEM_HEIGHT_IN_PX +
+      MENU_SEARCH_HEIGHT_IN_PX +
+      MENU_SHOW_CHANGED_CHECKBOX_HEIGHT_IN_PX +
+      MENU_DIVIDER_HEIGHT_IN_PX
   );
+  const [bottomSectionHeightInPx, setBottomSectionHeightInPx] = useState<number>(
+    DRILLDOWN_NAVIGATION_MENU_ITEM_HEIGHT_IN_PX + MENU_DIVIDER_HEIGHT_IN_PX
+  );
+
+  const [isModelsMenuActive, setModelsMenuActive] = useState(true);
+  const [searchValue, setSearchValue] = useState("");
+  const [filteredGitSyncStatus, setFilteredGitSyncStatus] = useState<WorkspaceGitLocalChangesStatus>();
+
+  const searchInputRef = useRef<HTMLInputElement>(null);
+  const carouselScrollRef = useRef<HTMLDivElement>(null);
+  const listScrollRef = useRef<VariableSizeList>(null);
+
+  const deletedWorkspaceFiles = useMemo(() => {
+    if (!props.currentWorkspaceGitStatusProps) {
+      return [];
+    }
+    return listDeletedFiles(props.currentWorkspaceGitStatusProps);
+  }, [props.currentWorkspaceGitStatusProps]);
+
+  const allFiles = useMemo(() => {
+    return [...props.workspace.files, ...deletedWorkspaceFiles];
+  }, [deletedWorkspaceFiles, props.workspace.files]);
+
+  const sortedFiles = useMemo(() => allFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath)), [allFiles]);
 
   const models = useMemo(
-    () => sortedAndFilteredFiles.filter((file) => editorEnvelopeLocator.hasMappingFor(file.relativePath)),
-    [editorEnvelopeLocator, sortedAndFilteredFiles]
+    () => sortedFiles.filter((file) => editorEnvelopeLocator.hasMappingFor(file.relativePath)),
+    [editorEnvelopeLocator, sortedFiles]
   );
 
   const otherFiles = useMemo(
-    () => sortedAndFilteredFiles.filter((file) => !editorEnvelopeLocator.hasMappingFor(file.relativePath)),
-    [editorEnvelopeLocator, sortedAndFilteredFiles]
+    () => sortedFiles.filter((file) => !editorEnvelopeLocator.hasMappingFor(file.relativePath)),
+    [editorEnvelopeLocator, sortedFiles]
   );
 
-  const [search, setSearch] = useState("");
-  const [otherFilesSearch, setOtherFilesSearch] = useState("");
+  const filteredModels = useMemo(
+    () =>
+      models
+        .filter((file) => file.name.toLowerCase().includes(searchValue.toLowerCase()))
+        .filter(
+          (file) =>
+            !filteredGitSyncStatus ||
+            resolveGitLocalChangesStatus({
+              workspaceGitStatus: props.currentWorkspaceGitStatusProps?.workspaceGitStatusPromise.data,
+              file,
+            }) === filteredGitSyncStatus
+        ),
+    [filteredGitSyncStatus, models, props.currentWorkspaceGitStatusProps?.workspaceGitStatusPromise.data, searchValue]
+  );
+
+  const filteredOtherFiles = useMemo(
+    () => otherFiles.filter((file) => file.name.toLowerCase().includes(searchValue.toLowerCase())),
+    [otherFiles, searchValue]
+  );
+
+  const computedInitialScrollOffset = useMemo(() => {
+    if (props.filesMenuMode !== FilesMenuMode.LIST || !isModelsMenuActive || !props.currentWorkspaceFile) {
+      return;
+    }
+    const index = filteredModels.findIndex((it) => it.relativePath === props.currentWorkspaceFile?.relativePath);
+    if (index < 0) {
+      return 0;
+    }
+    return filteredModels.slice(0, index).reduce((sum, current) => sum + getFileDataListHeight(current), 0);
+  }, [filteredModels, isModelsMenuActive, props.currentWorkspaceFile, props.filesMenuMode]);
+
+  const searchInput = useCallback(
+    (searchRef?: React.RefObject<HTMLInputElement>) => {
+      return (
+        <MenuInput onKeyDown={(e) => e.stopPropagation()}>
+          <SearchInput
+            ref={searchRef}
+            value={searchValue}
+            type={"search"}
+            onChange={(_ev, value) => {
+              setSearchValue(value);
+            }}
+            placeholder={`In '${props.workspace.descriptor.name}'`}
+            style={{ fontSize: "small" }}
+            onClick={(e) => {
+              e.stopPropagation();
+            }}
+          />
+        </MenuInput>
+      );
+    },
+    [props.workspace.descriptor.name, searchValue]
+  );
+
+  const fileListMenuItemsHeightMaxLimitCss = useMemo(() => {
+    return `calc(${MENU_HEIGHT_MAX_LIMIT_CSS} - ${
+      topSectionHeightInPx + (otherFiles.length ? bottomSectionHeightInPx : 0)
+    }px)`;
+  }, [bottomSectionHeightInPx, otherFiles.length, topSectionHeightInPx]);
+
+  const isCurrentWorkspaceFile = useCallback(
+    (file: WorkspaceFile) => {
+      return (
+        props.workspace.descriptor.workspaceId === file.workspaceId &&
+        props.currentWorkspaceFile?.relativePath === file.relativePath
+      );
+    },
+    [props.currentWorkspaceFile?.relativePath, props.workspace.descriptor.workspaceId]
+  );
+
+  const getFileListItemDisplayMode = useCallback(
+    (file: WorkspaceFile) =>
+      deletedWorkspaceFiles.some((it) => it.relativePath === file.relativePath)
+        ? FileListItemDisplayMode.deleted
+        : FileListItemDisplayMode.enabled,
+    [deletedWorkspaceFiles]
+  );
+
+  useEffect(() => {
+    const task = setTimeout(() => {
+      if (props.filesMenuMode === FilesMenuMode.CAROUSEL && isModelsMenuActive) {
+        carouselScrollRef.current?.scrollIntoView({ block: "nearest", behavior: "smooth" });
+      }
+      if (props.filesMenuMode === FilesMenuMode.LIST && isModelsMenuActive) {
+        listScrollRef.current?.scrollToItem(
+          filteredModels.findIndex((it) => it.relativePath === props.currentWorkspaceFile?.relativePath)
+        );
+      }
+      if (props.shouldFocusOnSearch) {
+        searchInputRef.current?.focus({ preventScroll: true });
+      }
+    }, 500);
+    return () => {
+      clearTimeout(task);
+    };
+  }, [
+    props.filesMenuMode,
+    isModelsMenuActive,
+    filteredGitSyncStatus,
+    props.currentWorkspaceFile?.relativePath,
+    filteredModels,
+    props.shouldFocusOnSearch,
+  ]);
 
   return (
     <>
-      <Split>
-        <SplitItem isFilled={true}>
-          <MenuItem direction="up" itemId={props.workspaceDescriptor.workspaceId}>
-            All
-          </MenuItem>
-        </SplitItem>
-        <SplitItem>
-          <FilesDropdownModeIcons
-            filesDropdownMode={props.filesDropdownMode}
-            setFilesDropdownMode={props.setFilesDropdownMode}
-          />
-          &nbsp; &nbsp;
-        </SplitItem>
-      </Split>
+      <MenuItem direction={"up"} itemId={`${props.workspace.descriptor.workspaceId}-breadcrumb`}>
+        All
+      </MenuItem>
+      {searchInput(isModelsMenuActive ? searchInputRef : undefined)}
+      <Flex
+        justifyContent={{ default: "justifyContentFlexEnd" }}
+        alignItems={{ default: "alignItemsCenter" }}
+        style={{ paddingRight: "16px" }}
+      >
+        <FlexItem>
+          {props.currentWorkspaceGitStatusProps !== undefined && (
+            <Tooltip content={"Select to display only modified, added, or deleted files"} position={"bottom"}>
+              <Checkbox
+                label={"Only modified"}
+                id={"filter-git-status-modified-locally"}
+                aria-label={"Select to display only modified, added, or deleted files"}
+                isChecked={filteredGitSyncStatus === WorkspaceGitLocalChangesStatus.pending}
+                onChange={(checked) => {
+                  setFilteredGitSyncStatus(checked ? WorkspaceGitLocalChangesStatus.pending : undefined);
+                }}
+              />
+            </Tooltip>
+          )}
+        </FlexItem>
+        <FlexItem>
+          <Flex justifyContent={{ default: "justifyContentCenter" }}>
+            <FilesMenuModeIcons filesMenuMode={props.filesMenuMode} setFilesMenuMode={props.setFilesMenuMode} />
+          </Flex>
+        </FlexItem>
+      </Flex>
       <Divider component={"li"} />
 
-      <Split>
-        {(props.filesDropdownMode === FilesDropdownMode.LIST_MODELS ||
-          props.filesDropdownMode === FilesDropdownMode.LIST_MODELS_AND_OTHERS) && (
-          <SplitItem isFilled={true} style={{ minWidth: `${MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX}px` }}>
-            <>
-              <SearchableFilesMenuGroup
-                search={search}
-                setSearch={setSearch}
-                filesDropdownMode={props.filesDropdownMode}
-                shouldFocusOnSearch={props.shouldFocusOnSearch}
-                label={`Models in '${props.workspaceDescriptor.name}'`}
-                allFiles={models}
+      {props.filesMenuMode === FilesMenuMode.LIST && (
+        <FilteredFilesMenuGroup
+          search={searchValue}
+          filesMenuMode={props.filesMenuMode}
+          allFiles={models}
+          filteredFiles={filteredModels}
+          heightMaxLimitCss={fileListMenuItemsHeightMaxLimitCss}
+        >
+          {({ filteredFiles }) => {
+            return (
+              <AutoSizer>
+                {({ height, width }) => (
+                  <VariableSizeList
+                    height={height}
+                    itemCount={filteredFiles.length}
+                    itemSize={(index) => getFileDataListHeight(filteredFiles[index])}
+                    width={width}
+                    initialScrollOffset={computedInitialScrollOffset}
+                    ref={listScrollRef}
+                  >
+                    {({ index, style }) => {
+                      const fileListItemDisplayMode = getFileListItemDisplayMode(filteredFiles[index]);
+                      return (
+                        <MenuItem
+                          key={filteredFiles[index].relativePath}
+                          onClick={
+                            fileListItemDisplayMode === FileListItemDisplayMode.enabled ? props.onSelectFile : undefined
+                          }
+                          className={"kie-tools--file-switcher-no-padding-menu-item"}
+                          isFocused={isCurrentWorkspaceFile(filteredFiles[index])}
+                          isActive={isCurrentWorkspaceFile(filteredFiles[index])}
+                          style={style}
+                          component={"div"}
+                        >
+                          <FileDataList
+                            file={filteredFiles[index]}
+                            displayMode={fileListItemDisplayMode}
+                            gitStatusProps={props.currentWorkspaceGitStatusProps}
+                            isCurrentWorkspaceFile={isCurrentWorkspaceFile(filteredFiles[index])}
+                            onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+                          />
+                        </MenuItem>
+                      );
+                    }}
+                  </VariableSizeList>
+                )}
+              </AutoSizer>
+            );
+          }}
+        </FilteredFilesMenuGroup>
+      )}
+
+      {props.filesMenuMode === FilesMenuMode.CAROUSEL && (
+        <FilteredFilesMenuGroup
+          search={searchValue}
+          filesMenuMode={props.filesMenuMode}
+          allFiles={models}
+          filteredFiles={filteredModels}
+          heightMaxLimitCss={fileListMenuItemsHeightMaxLimitCss}
+          style={{ overflowY: "auto" }}
+        >
+          {({ filteredFiles }) => {
+            const isCurrentFileOutsideOfShownList =
+              props.currentWorkspaceFile &&
+              filteredFiles.findIndex((file) => file.relativePath === props.currentWorkspaceFile?.relativePath) >=
+                MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN;
+            const shouldScrollToTop =
+              props.currentWorkspaceFile &&
+              filteredFiles.findIndex((file) => file.relativePath === props.currentWorkspaceFile?.relativePath) < 0;
+            return (
+              <Gallery
+                hasGutter={true}
+                style={{
+                  paddingLeft: "8px",
+                  paddingRight: "8px",
+                  borderTop: "var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--100)",
+                }}
               >
-                {({ filteredFiles }) => (
+                {shouldScrollToTop && <div ref={carouselScrollRef} />}
+                {filteredFiles.slice(0, MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN).map((file, index) => (
+                  <FilesMenuItemCarouselCard
+                    key={index}
+                    file={file}
+                    gitStatusProps={props.currentWorkspaceGitStatusProps}
+                    isCurrentWorkspaceFile={isCurrentWorkspaceFile(file)}
+                    displayMode={getFileListItemDisplayMode(file)}
+                    onSelectFile={props.onSelectFile}
+                    onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+                    scrollRef={carouselScrollRef}
+                  />
+                ))}
+                {filteredFiles.length > MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN && (
                   <>
+                    {props.currentWorkspaceFile && isCurrentFileOutsideOfShownList && (
+                      <FilesMenuItemCarouselCard
+                        file={props.currentWorkspaceFile}
+                        gitStatusProps={props.currentWorkspaceGitStatusProps}
+                        isCurrentWorkspaceFile={isCurrentWorkspaceFile(props.currentWorkspaceFile)}
+                        displayMode={getFileListItemDisplayMode(props.currentWorkspaceFile)}
+                        onSelectFile={props.onSelectFile}
+                        onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+                        scrollRef={carouselScrollRef}
+                      />
+                    )}
+                    <Card style={{ border: 0 }}>
+                      <CardBody>
+                        <Bullseye>
+                          <div>
+                            ...and{" "}
+                            {filteredFiles.length -
+                              MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN -
+                              (isCurrentFileOutsideOfShownList ? 1 : 0)}{" "}
+                            more.
+                          </div>
+                        </Bullseye>
+                      </CardBody>
+                    </Card>
+                  </>
+                )}
+              </Gallery>
+            );
+          }}
+        </FilteredFilesMenuGroup>
+      )}
+      {otherFiles.length > 0 && (
+        <>
+          <Divider component={"li"} />
+          <MenuItem
+            itemId={`${props.workspace.descriptor.workspaceId}-other`}
+            direction={"down"}
+            onClick={(_event) => {
+              setModelsMenuActive(false);
+              setBottomSectionHeightInPx(0);
+              setTopSectionHeightInPx((prev) => prev - MENU_SHOW_CHANGED_CHECKBOX_HEIGHT_IN_PX);
+            }}
+            drilldownMenu={
+              <DrilldownMenu id={`dd${props.workspace.descriptor.workspaceId}-other`} style={{ position: "fixed" }}>
+                <MenuItem
+                  itemId={"back-up"}
+                  direction={"up"}
+                  onClick={(_event) => {
+                    setModelsMenuActive(true);
+                    setBottomSectionHeightInPx(MENU_DIVIDER_HEIGHT_IN_PX + DRILLDOWN_NAVIGATION_MENU_ITEM_HEIGHT_IN_PX);
+                    setTopSectionHeightInPx((prev) => prev + MENU_SHOW_CHANGED_CHECKBOX_HEIGHT_IN_PX);
+                  }}
+                >
+                  Back
+                </MenuItem>
+                {searchInput(isModelsMenuActive ? undefined : searchInputRef)}
+                <Divider component={"li"} />
+                <FilteredFilesMenuGroup
+                  search={searchValue}
+                  filesMenuMode={FilesMenuMode.LIST} // always LIST for otherFiles, even for mode CAROUSEL
+                  allFiles={otherFiles}
+                  filteredFiles={filteredOtherFiles}
+                  heightMaxLimitCss={fileListMenuItemsHeightMaxLimitCss}
+                >
+                  {({ filteredFiles }) => (
                     <AutoSizer>
                       {({ height, width }) => (
                         <VariableSizeList
@@ -690,190 +960,112 @@ export function FilesMenuItems(props: {
                           {({ index, style }) => (
                             <MenuItem
                               key={filteredFiles[index].relativePath}
-                              onClick={props.onSelectFile}
                               style={style}
+                              component={"div"}
                               className={"kie-tools--file-switcher-no-padding-menu-item"}
                             >
-                              <FileDataList file={filteredFiles[index]} isEditable={true} />
+                              <FileDataList
+                                file={filteredFiles[index]}
+                                displayMode={FileListItemDisplayMode.readonly}
+                                gitStatusProps={props.currentWorkspaceGitStatusProps}
+                                onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+                              />
                             </MenuItem>
                           )}
                         </VariableSizeList>
                       )}
                     </AutoSizer>
-                  </>
-                )}
-              </SearchableFilesMenuGroup>
-              {otherFiles.length > 0 && (
-                <>
-                  <Divider component={"li"} />
-                  <MenuGroup>
-                    <MenuList>
-                      <MenuItem
-                        onClick={(e) => {
-                          e.stopPropagation();
-                          props.setFilesDropdownMode((prev) =>
-                            prev === FilesDropdownMode.LIST_MODELS
-                              ? FilesDropdownMode.LIST_MODELS_AND_OTHERS
-                              : FilesDropdownMode.LIST_MODELS
-                          );
-                        }}
-                      >
-                        {props.filesDropdownMode === FilesDropdownMode.LIST_MODELS
-                          ? "View other files"
-                          : "Hide other files"}
-                        &nbsp;&nbsp;
-                        {props.filesDropdownMode === FilesDropdownMode.LIST_MODELS ? (
-                          <ArrowRightIcon />
-                        ) : (
-                          <ArrowLeftIcon />
-                        )}
-                      </MenuItem>
-                    </MenuList>
-                  </MenuGroup>
-                </>
-              )}
-            </>
-          </SplitItem>
-        )}
-
-        {props.filesDropdownMode === FilesDropdownMode.LIST_MODELS_AND_OTHERS && (
-          <SplitItem isFilled={true} style={{ minWidth: `${MIN_FILE_SWITCHER_PANEL_WIDTH_IN_PX}px` }}>
-            <SearchableFilesMenuGroup
-              search={otherFilesSearch}
-              setSearch={setOtherFilesSearch}
-              filesDropdownMode={props.filesDropdownMode}
-              shouldFocusOnSearch={props.shouldFocusOnSearch}
-              label={`Other files in '${props.workspaceDescriptor.name}'`}
-              allFiles={otherFiles}
-            >
-              {({ filteredFiles }) => (
-                <>
-                  <AutoSizer>
-                    {({ height, width }) => (
-                      <VariableSizeList
-                        height={height}
-                        itemCount={filteredFiles.length}
-                        itemSize={(index) => getFileDataListHeight(filteredFiles[index])}
-                        width={width}
-                      >
-                        {({ index, style }) => (
-                          <MenuItem
-                            component={"span"}
-                            onClick={() => {}}
-                            style={style}
-                            className={"kie-tools--file-switcher-no-padding-menu-item"}
-                          >
-                            <FileDataList file={filteredFiles[index]} isEditable={false} />
-                          </MenuItem>
-                        )}
-                      </VariableSizeList>
-                    )}
-                  </AutoSizer>
-                </>
-              )}
-            </SearchableFilesMenuGroup>
-          </SplitItem>
-        )}
-
-        {props.filesDropdownMode === FilesDropdownMode.CAROUSEL && (
-          <SplitItem isFilled={true}>
-            <SearchableFilesMenuGroup
-              search={search}
-              setSearch={setSearch}
-              filesDropdownMode={props.filesDropdownMode}
-              shouldFocusOnSearch={props.shouldFocusOnSearch}
-              label={`Models in '${props.workspaceDescriptor.name}'`}
-              allFiles={models}
-            >
-              {({ filteredFiles }) => (
-                <Gallery
-                  hasGutter={true}
-                  style={{
-                    padding: "8px",
-                    borderTop: "var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--100)",
-                  }}
-                >
-                  {filteredFiles.slice(0, MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN).map((file) => (
-                    <Card
-                      key={file.relativePath}
-                      isSelectable={true}
-                      isRounded={true}
-                      isCompact={true}
-                      isHoverable={true}
-                      isFullHeight={true}
-                      onClick={() => {
-                        history.push({
-                          pathname: routes.workspaceWithFilePath.path({
-                            workspaceId: file.workspaceId,
-                            fileRelativePath: file.relativePathWithoutExtension,
-                            extension: file.extension,
-                          }),
-                        });
-
-                        props.onSelectFile();
-                      }}
-                    >
-                      <FileLink file={file}>
-                        {/* The default display:flex makes the text overflow */}
-                        <CardHeader style={{ display: "block" }}>
-                          <CardHeaderMain>
-                            <FileListItem file={file} isEditable={true} />
-                          </CardHeaderMain>
-                        </CardHeader>
-                      </FileLink>
-                      <Divider inset={{ default: "insetMd" }} />
-                      <CardBody style={{ padding: 0 }}>
-                        <FileSvg workspaceFile={file} />
-                      </CardBody>
-                    </Card>
-                  ))}
-                  {filteredFiles.length > MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN && (
-                    <Card style={{ border: 0 }}>
-                      <CardBody>
-                        <Bullseye>
-                          <div>...and {filteredFiles.length - MAX_NUMBER_OF_CAROUSEL_ITEMS_SHOWN} more.</div>
-                        </Bullseye>
-                      </CardBody>
-                    </Card>
                   )}
-                </Gallery>
-              )}
-            </SearchableFilesMenuGroup>
-          </SplitItem>
-        )}
-      </Split>
+                </FilteredFilesMenuGroup>
+              </DrilldownMenu>
+            }
+          >
+            Other files
+          </MenuItem>
+        </>
+      )}
     </>
   );
 }
 
-export function FilesDropdownModeIcons(props: {
-  filesDropdownMode: FilesDropdownMode;
-  setFilesDropdownMode: React.Dispatch<React.SetStateAction<FilesDropdownMode>>;
+const FilesMenuItemCarouselCard = (props: {
+  file: WorkspaceFile;
+  gitStatusProps?: GitStatusProps;
+  isCurrentWorkspaceFile?: boolean;
+  onDeletedWorkspaceFile?: () => void;
+  displayMode: FileListItemDisplayMode;
+  onSelectFile: () => void;
+  scrollRef: React.RefObject<HTMLDivElement>;
+}) => {
+  const cardInternals = [
+    <CardHeader style={{ display: "block" }} key={0}>
+      <CardHeaderMain>
+        <FileListItem
+          file={props.file}
+          displayMode={props.displayMode}
+          gitStatusProps={props.gitStatusProps}
+          isCurrentWorkspaceFile={props.isCurrentWorkspaceFile}
+          onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+        />
+      </CardHeaderMain>
+    </CardHeader>,
+    <Divider inset={{ default: "insetMd" }} key={1} />,
+    <CardBody style={{ padding: 0 }} key={2}>
+      <FileSvg workspaceFile={props.file} />
+    </CardBody>,
+  ];
+  return (
+    <Card
+      key={props.file.relativePath}
+      isSelectable={props.displayMode === FileListItemDisplayMode.enabled}
+      isRounded={true}
+      isCompact={true}
+      isFullHeight={true}
+      onClick={props.displayMode === FileListItemDisplayMode.enabled ? props.onSelectFile : undefined}
+      className={switchExpression(props.displayMode, {
+        enabled: "kie-tools--file-list-item-enabled",
+        deleted: "kie-tools--file-list-item-deleted",
+        readonly: "kie-tools--file-list-item-readonly",
+      })}
+    >
+      <div id={`scrollRef-${props.file.relativePath}`} ref={props.isCurrentWorkspaceFile ? props.scrollRef : undefined}>
+        {props.displayMode === FileListItemDisplayMode.enabled ? (
+          <FileLink file={props.file}>{cardInternals}</FileLink>
+        ) : (
+          cardInternals
+        )}
+      </div>
+    </Card>
+  );
+};
+
+export function FilesMenuModeIcons(props: {
+  filesMenuMode: FilesMenuMode;
+  setFilesMenuMode: React.Dispatch<React.SetStateAction<FilesMenuMode>>;
 }) {
   return (
     <>
-      {props.filesDropdownMode === FilesDropdownMode.CAROUSEL && (
+      {props.filesMenuMode === FilesMenuMode.CAROUSEL && (
         <Button
           className={"kie-tools--masthead-hoverable"}
           variant="plain"
           aria-label="Switch to list view"
           onClick={(e) => {
             e.stopPropagation();
-            props.setFilesDropdownMode(FilesDropdownMode.LIST_MODELS);
+            props.setFilesMenuMode(FilesMenuMode.LIST);
           }}
         >
           <ListIcon />
         </Button>
       )}
-      {(props.filesDropdownMode === FilesDropdownMode.LIST_MODELS ||
-        props.filesDropdownMode === FilesDropdownMode.LIST_MODELS_AND_OTHERS) && (
+      {props.filesMenuMode === FilesMenuMode.LIST && (
         <Button
           className={"kie-tools--masthead-hoverable"}
           variant="plain"
           aria-label="Switch to carousel view"
           onClick={(e) => {
             e.stopPropagation();
-            props.setFilesDropdownMode(FilesDropdownMode.CAROUSEL);
+            props.setFilesMenuMode(FilesMenuMode.CAROUSEL);
           }}
         >
           <ThLargeIcon />
diff --git a/packages/online-editor/src/editor/CreateGistOrSnippetModal.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
similarity index 89%
rename from packages/online-editor/src/editor/CreateGistOrSnippetModal.tsx
rename to packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
index 28100c07f4..04033b0907 100644
--- a/packages/online-editor/src/editor/CreateGistOrSnippetModal.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGistOrSnippetModal.tsx
@@ -27,22 +27,23 @@ import { LockIcon } from "@patternfly/react-icons/dist/js/icons/lock-icon";
 import { ExclamationCircleIcon } from "@patternfly/react-icons/dist/js/icons/exclamation-circle-icon";
 import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { GIST_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
-import { useSettingsDispatch } from "../settings/SettingsContext";
 import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
-import { useAuthSession } from "../authSessions/AuthSessionsContext";
-import { useBitbucketClient } from "../bitbucket/Hooks";
-import { GithubIcon, BitbucketIcon } from "@patternfly/react-icons";
-import { useGitHubClient } from "../github/Hooks";
+import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
+import { useBitbucketClient } from "../../../bitbucket/Hooks";
+import { BitbucketIcon } from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
+import { GithubIcon } from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { useGitHubClient } from "../../../github/Hooks";
 import {
   AuthProviderType,
   GistEnabledAuthProviderType,
   isGistEnabledAuthProviderType,
   isSupportedGitAuthProviderType,
-} from "../authProviders/AuthProvidersApi";
-import { useAuthProvider } from "../authProviders/AuthProvidersContext";
-import { switchExpression } from "../switchExpression/switchExpression";
-import { useOnlineI18n } from "../i18n";
+} from "../../../authProviders/AuthProvidersApi";
+import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { useOnlineI18n } from "../../../i18n";
 import { LoadOrganizationsSelect, SelectOptionObjectType } from "./LoadOrganizationsSelect";
+import { useGitIntegration } from "./GitIntegrationContextProvider";
 
 export interface CreateGistOrSnippetResponse {
   cloneUrl: string;
@@ -52,11 +53,10 @@ export const CreateGistOrSnippetModal = (props: {
   workspace: WorkspaceDescriptor;
   isOpen: boolean;
   onClose: () => void;
-  onSuccess: (args: { url: string }) => void;
-  onError: () => void;
+  onSuccess?: (args: { url: string }) => void;
+  onError?: () => void;
 }) => {
   const workspaces = useWorkspaces();
-  const settingsDispatch = useSettingsDispatch();
   const { authSession, gitConfig, authInfo } = useAuthSession(props.workspace.gitAuthSessionId);
   const authProvider = useAuthProvider(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
@@ -68,6 +68,10 @@ export const CreateGistOrSnippetModal = (props: {
   const [selectedOrganization, setSelectedOrganization] = useState<SelectOptionObjectType>();
   const [isGistOrSnippetLoading, setGistOrSnippetLoading] = useState(false);
 
+  const {
+    alerts: { successfullyUpdatedGistOrSnippetAlert, errorAlert },
+  } = useGitIntegration();
+
   const createGitHubGist: () => Promise<CreateGistOrSnippetResponse> = useCallback(async () => {
     const gist = await gitHubClient.gists.create({
       description: props.workspace.name ?? "",
@@ -193,16 +197,28 @@ If you are, it means that creating this Snippet failed and it can safely be dele
       });
 
       props.onClose();
-      props.onSuccess({ url: gistOrSnippet.cloneUrl });
+      successfullyUpdatedGistOrSnippetAlert.show({ url: gistOrSnippet.cloneUrl });
+      props.onSuccess?.({ url: gistOrSnippet.cloneUrl });
       return;
     } catch (err) {
       setError(err);
-      props.onError();
+      errorAlert.show();
+      props.onError?.();
       throw err;
     } finally {
       setGistOrSnippetLoading(false);
     }
-  }, [authInfo, authProvider?.type, createGitHubGist, createBitbucketSnippet, workspaces, props, gitConfig]);
+  }, [
+    authInfo,
+    authProvider?.type,
+    createGitHubGist,
+    createBitbucketSnippet,
+    workspaces,
+    props,
+    gitConfig,
+    successfullyUpdatedGistOrSnippetAlert,
+    errorAlert,
+  ]);
 
   if (!authProvider?.type || !isSupportedGitAuthProviderType(authProvider?.type)) {
     return <></>;
diff --git a/packages/online-editor/src/editor/CreateGitRepositoryModal.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
similarity index 91%
rename from packages/online-editor/src/editor/CreateGitRepositoryModal.tsx
rename to packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
index 6481dd7649..9f4e69a1f5 100644
--- a/packages/online-editor/src/editor/CreateGitRepositoryModal.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/CreateGitRepositoryModal.tsx
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Red Hat, Inc. and/or its affiliates.
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,17 +30,18 @@ import { Button } from "@patternfly/react-core/dist/js/components/Button";
 import { ValidatedOptions } from "@patternfly/react-core/dist/js/helpers/constants";
 import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
 import { GIT_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
-import { useSettingsDispatch } from "../settings/SettingsContext";
 import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
-import { useAuthSession } from "../authSessions/AuthSessionsContext";
-import { useBitbucketClient } from "../bitbucket/Hooks";
-import { GithubIcon, BitbucketIcon } from "@patternfly/react-icons";
-import { useGitHubClient } from "../github/Hooks";
-import { isSupportedGitAuthProviderType } from "../authProviders/AuthProvidersApi";
-import { useAuthProvider } from "../authProviders/AuthProvidersContext";
-import { switchExpression } from "../switchExpression/switchExpression";
-import { useOnlineI18n } from "../i18n";
+import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
+import { useBitbucketClient } from "../../../bitbucket/Hooks";
+import { BitbucketIcon } from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
+import { GithubIcon } from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { useGitHubClient } from "../../../github/Hooks";
+import { isSupportedGitAuthProviderType } from "../../../authProviders/AuthProvidersApi";
+import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { useOnlineI18n } from "../../../i18n";
 import { LoadOrganizationsSelect, SelectOptionObjectType } from "./LoadOrganizationsSelect";
+import { useGitIntegration } from "./GitIntegrationContextProvider";
 
 export interface CreateRepositoryResponse {
   cloneUrl: string;
@@ -57,10 +58,9 @@ export function CreateGitRepositoryModal(props: {
   workspace: WorkspaceDescriptor;
   isOpen: boolean;
   onClose: () => void;
-  onSuccess: (args: { url: string }) => void;
+  onSuccess?: (args: { url: string }) => void;
 }) {
   const workspaces = useWorkspaces();
-  const settingsDispatch = useSettingsDispatch();
   const { authSession, gitConfig, authInfo } = useAuthSession(props.workspace.gitAuthSessionId);
   const authProvider = useAuthProvider(authSession);
   const bitbucketClient = useBitbucketClient(authSession);
@@ -73,6 +73,10 @@ export function CreateGitRepositoryModal(props: {
   const { i18n } = useOnlineI18n();
   const [selectedOrganization, setSelectedOrganization] = useState<SelectOptionObjectType>();
 
+  const {
+    alerts: { createRepositorySuccessAlert, errorAlert },
+  } = useGitIntegration();
+
   useEffect(() => {
     setName(getSuggestedRepositoryName(props.workspace.name));
   }, [props.workspace.name]);
@@ -196,8 +200,10 @@ export function CreateGitRepositoryModal(props: {
       });
 
       props.onClose();
-      props.onSuccess({ url: websiteUrl });
+      createRepositorySuccessAlert.show({ url: websiteUrl });
+      props.onSuccess?.({ url: websiteUrl });
     } catch (err) {
+      errorAlert.show();
       setError(err);
       throw err;
     } finally {
@@ -212,6 +218,8 @@ export function CreateGitRepositoryModal(props: {
     pushEmptyCommitIntoBitbucket,
     workspaces,
     props,
+    createRepositorySuccessAlert,
+    errorAlert,
   ]);
 
   const isNameValid = useMemo(() => {
@@ -229,6 +237,7 @@ export function CreateGitRepositoryModal(props: {
   if (!authProvider?.type || !isSupportedGitAuthProviderType(authProvider?.type)) {
     return <></>;
   }
+
   return (
     <Modal
       variant={ModalVariant.medium}
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx
new file mode 100644
index 0000000000..e9867eea81
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationAlerts.tsx
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback } from "react";
+import { useGlobalAlert } from "../../../alerts";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import {
+  WorkspaceKind,
+  WorkspaceKindGistLike,
+  isGistLikeWorkspaceKind,
+} from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { Alert, AlertActionCloseButton, AlertActionLink } from "@patternfly/react-core/dist/js/components/Alert";
+import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { useOnlineI18n } from "../../../i18n";
+
+export function useGitIntegrationAlerts(workspace: ActiveWorkspace) {
+  const { i18n } = useOnlineI18n();
+
+  const createRepositorySuccessAlert = useGlobalAlert<{ url: string }>(
+    useCallback(({ close }, { url }) => {
+      return (
+        <Alert
+          variant="success"
+          title={`GitHub repository created.`}
+          actionClose={<AlertActionCloseButton onClose={close} />}
+          actionLinks={<AlertActionLink onClick={() => window.open(url, "_blank")}>{url}</AlertActionLink>}
+        />
+      );
+    }, [])
+  );
+
+  const pushingAlert = useGlobalAlert(
+    useCallback(() => {
+      if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+        return <></>;
+      }
+
+      return (
+        <Alert
+          variant="info"
+          title={
+            <>
+              <Spinner size={"sm"} />
+              &nbsp;&nbsp; {`Pushing to '${workspace.descriptor.origin.url}'...`}
+            </>
+          }
+        />
+      );
+    }, [workspace.descriptor])
+  );
+
+  const comittingAlert = useGlobalAlert(
+    useCallback(() => {
+      return (
+        <Alert
+          variant="info"
+          title={
+            <>
+              <Spinner size={"sm"} />
+              &nbsp;&nbsp; {`Creating commit...`}
+            </>
+          }
+        />
+      );
+    }, [])
+  );
+
+  const commitSuccessAlert = useGlobalAlert(
+    useCallback(() => {
+      return <Alert variant="success" title={`Commit created.`} />;
+    }, []),
+    { durationInSeconds: 2 }
+  );
+
+  const commitFailAlert = useGlobalAlert(
+    useCallback(({ close }, staticArgs: { reason: string }) => {
+      return (
+        <Alert
+          variant="danger"
+          title={`Failed to commit: ${staticArgs.reason}`}
+          actionClose={<AlertActionCloseButton onClose={close} />}
+        />
+      );
+    }, [])
+  );
+
+  const pushSuccessAlert = useGlobalAlert(
+    useCallback(() => {
+      if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+        return <></>;
+      }
+
+      return <Alert variant="success" title={`Pushed to '${workspace.descriptor.origin.url}'`} />;
+    }, [workspace.descriptor]),
+    { durationInSeconds: 4 }
+  );
+
+  const pushErrorAlert = useGlobalAlert(
+    useCallback(
+      ({ close }) => {
+        if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+          return <></>;
+        }
+
+        return (
+          <Alert
+            variant="danger"
+            title={`Error Pushing to '${workspace.descriptor.origin.url}'`}
+            actionClose={<AlertActionCloseButton onClose={close} />}
+          />
+        );
+      },
+      [workspace.descriptor]
+    )
+  );
+
+  const pullingAlert = useGlobalAlert(
+    useCallback(() => {
+      if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+        return <></>;
+      }
+
+      return (
+        <Alert
+          variant="info"
+          title={
+            <>
+              <Spinner size={"sm"} />
+              &nbsp;&nbsp; {`Pulling from '${workspace.descriptor.origin.url}'...`}
+            </>
+          }
+        />
+      );
+    }, [workspace.descriptor])
+  );
+
+  const pullSuccessAlert = useGlobalAlert(
+    useCallback(() => {
+      if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+        return <></>;
+      }
+
+      return <Alert variant="success" title={`Pulled from '${workspace.descriptor.origin.url}'`} />;
+    }, [workspace.descriptor]),
+    { durationInSeconds: 4 }
+  );
+
+  const pullErrorAlert = useGlobalAlert<{
+    newBranchName: string;
+    canPushToGitRepository: boolean;
+    pushNewBranch: (branchName: string) => Promise<void>;
+  }>(
+    useCallback(
+      ({ close }, { newBranchName, canPushToGitRepository, pushNewBranch }) => {
+        if (workspace.descriptor.origin.kind !== WorkspaceKind.GIT) {
+          return <></>;
+        }
+
+        return (
+          <Alert
+            variant="danger"
+            title={`Error Pulling from '${workspace.descriptor.origin.url}'`}
+            actionClose={<AlertActionCloseButton onClose={close} />}
+            actionLinks={<></>}
+          >
+            {`This usually happens when your branch has conflicts with the upstream branch or you don't have permission to Pull.`}
+            <br />
+            <br />
+            {`You can save your work to a new branch.`}
+            <br />
+            <br />
+            <Tooltip
+              data-testid={"gist-it-tooltip"}
+              content={<div>{`You need select an authentication source to be able to Push to a new branch.`}</div>}
+              trigger={!canPushToGitRepository ? "mouseenter click" : ""}
+              position="left"
+            >
+              <Button
+                onClick={() => pushNewBranch(newBranchName)}
+                variant={ButtonVariant.link}
+                style={{ paddingLeft: 0 }}
+                isSmall={true}
+                isDisabled={!canPushToGitRepository}
+              >
+                {`Switch to '${newBranchName}'`}
+              </Button>
+            </Tooltip>
+            <br />
+            <br />
+
+            {`Or change the authentication source for '${workspace.descriptor.name}' and try again`}
+            <br />
+          </Alert>
+        );
+      },
+      [workspace.descriptor]
+    )
+  );
+
+  const nothingToCommitAlert = useGlobalAlert(
+    useCallback(() => {
+      return <Alert variant="info" title={"Nothing to commit."} />;
+    }, []),
+    { durationInSeconds: 2 }
+  );
+
+  const successfullyCreatedGistOrSnippetAlert = useGlobalAlert(
+    useCallback(
+      ({ close }) => {
+        if (!isGistLikeWorkspaceKind(workspace.descriptor.origin.kind)) {
+          return <></>;
+        }
+
+        const gistOrSnippetUrl = workspace.descriptor.origin.url;
+        return (
+          <Alert
+            variant="success"
+            title={switchExpression(workspace.descriptor.origin.kind, {
+              GITHUB_GIST: i18n.editorPage.alerts.createGist,
+              BITBUCKET_SNIPPET: i18n.editorPage.alerts.createSnippet,
+            })}
+            actionClose={<AlertActionCloseButton onClose={close} />}
+            actionLinks={
+              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
+                {gistOrSnippetUrl}
+              </AlertActionLink>
+            }
+          />
+        );
+      },
+      [
+        i18n.editorPage.alerts.createGist,
+        i18n.editorPage.alerts.createSnippet,
+        workspace.descriptor.origin.kind,
+        workspace.descriptor.origin.url,
+      ]
+    ),
+    { durationInSeconds: 4 }
+  );
+
+  const loadingGistOrSnippetAlert = useGlobalAlert(
+    useCallback(
+      ({ close }) => {
+        if (!isGistLikeWorkspaceKind(workspace.descriptor.origin.kind)) {
+          return <></>;
+        }
+
+        const gistOrSnippetUrl = workspace.descriptor.origin.url;
+        return (
+          <Alert
+            variant="info"
+            title={
+              <>
+                <Spinner size={"sm"} />
+                &nbsp;&nbsp; Updating{" "}
+                {switchExpression(workspace.descriptor.origin.kind, {
+                  BITBUCKET_SNIPPET: "Snippet",
+                  GITHUB_GIST: "Gist",
+                })}
+                ...
+              </>
+            }
+            actionClose={<AlertActionCloseButton onClose={close} />}
+            actionLinks={
+              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
+                {gistOrSnippetUrl}
+              </AlertActionLink>
+            }
+          />
+        );
+      },
+      [workspace.descriptor.origin.kind, workspace.descriptor.origin.url]
+    )
+  );
+
+  const successfullyUpdatedGistOrSnippetAlert = useGlobalAlert(
+    useCallback(
+      ({ close }) => {
+        if (!isGistLikeWorkspaceKind(workspace.descriptor.origin.kind)) {
+          return <></>;
+        }
+
+        const gistOrSnippetUrl = workspace.descriptor.origin.url;
+        return (
+          <Alert
+            variant="success"
+            title={switchExpression(workspace.descriptor.origin.kind, {
+              GITHUB_GIST: i18n.editorPage.alerts.updateGist,
+              BITBUCKET_SNIPPET: i18n.editorPage.alerts.updateSnippet,
+            })}
+            actionClose={<AlertActionCloseButton onClose={close} />}
+            actionLinks={
+              <AlertActionLink onClick={() => window.open(gistOrSnippetUrl, "_blank")}>
+                {gistOrSnippetUrl}
+              </AlertActionLink>
+            }
+          />
+        );
+      },
+      [
+        i18n.editorPage.alerts.updateGist,
+        i18n.editorPage.alerts.updateSnippet,
+        workspace.descriptor.origin.kind,
+        workspace.descriptor.origin.url,
+      ]
+    ),
+    { durationInSeconds: 4 }
+  );
+
+  const errorPushingGistOrSnippet = useGlobalAlert<{ forceUpdateGistOrSnippet: () => Promise<void> }>(
+    useCallback(
+      ({ close }, { forceUpdateGistOrSnippet }) => {
+        return (
+          <Alert
+            variant="danger"
+            title={switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
+              GITHUB_GIST: i18n.editorPage.alerts.errorPushingGist,
+              BITBUCKET_SNIPPET: i18n.editorPage.alerts.errorPushingSnippet,
+            })}
+            actionLinks={[
+              <AlertActionLink
+                key="force"
+                onClick={() => {
+                  close();
+                  forceUpdateGistOrSnippet();
+                }}
+              >
+                Push forcefully
+              </AlertActionLink>,
+              <AlertActionLink key="dismiss" onClick={close}>
+                Dismiss
+              </AlertActionLink>,
+            ]}
+            actionClose={<AlertActionCloseButton onClose={close} />}
+          >
+            <b>{i18n.editorPage.alerts.forcePushWarning}</b>
+          </Alert>
+        );
+      },
+      [
+        workspace.descriptor.origin.kind,
+        i18n.editorPage.alerts.errorPushingGist,
+        i18n.editorPage.alerts.errorPushingSnippet,
+        i18n.editorPage.alerts.forcePushWarning,
+      ]
+    )
+  );
+
+  const errorAlert = useGlobalAlert(
+    useCallback(
+      ({ close }) => (
+        <Alert
+          variant="danger"
+          title={i18n.editorPage.alerts.error}
+          actionClose={<AlertActionCloseButton onClose={close} />}
+        />
+      ),
+      [i18n]
+    )
+  );
+
+  return {
+    createRepositorySuccessAlert,
+    comittingAlert,
+    commitSuccessAlert,
+    commitFailAlert,
+    pushingAlert,
+    pushSuccessAlert,
+    pushErrorAlert,
+    pullingAlert,
+    pullSuccessAlert,
+    pullErrorAlert,
+    nothingToCommitAlert,
+    successfullyCreatedGistOrSnippetAlert,
+    loadingGistOrSnippetAlert,
+    successfullyUpdatedGistOrSnippetAlert,
+    errorPushingGistOrSnippet,
+    errorAlert,
+  };
+}
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx
new file mode 100644
index 0000000000..be98c9ca2c
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/GitIntegrationContextProvider.tsx
@@ -0,0 +1,630 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, {
+  ReactNode,
+  SetStateAction,
+  createContext,
+  useCallback,
+  useContext,
+  useEffect,
+  useMemo,
+  useState,
+} from "react";
+import { useWorkspaces } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { AuthSessionSelectFilter } from "../../../authSessions/AuthSessionSelect";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
+import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
+import { useGitHubClient } from "../../../github/Hooks";
+import { useBitbucketClient } from "../../../bitbucket/Hooks";
+import {
+  WorkspaceKind,
+  isGistLikeWorkspaceKind,
+} from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import {
+  authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain,
+  authSessionsSelectFilterCompatibleWithGitUrlDomain,
+  gitAuthSessionSelectFilter,
+} from "../../../authSessions/CompatibleAuthSessions";
+import type { RestEndpointMethodTypes as OctokitRestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types";
+import { useCancelableEffect } from "@kie-tools-core/react-hooks/dist/useCancelableEffect";
+import { ImportableUrl, UrlType, useImportableUrl } from "../../../importFromUrl/ImportableUrlHooks";
+import {
+  GIST_ORIGIN_REMOTE_NAME,
+  GIT_ORIGIN_REMOTE_NAME,
+} from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
+import { useNavigationBlockersBypass, useRoutes } from "../../../navigation/Hooks";
+import { useHistory } from "react-router";
+import { useGitIntegrationAlerts } from "./GitIntegrationAlerts";
+import { isGistEnabledAuthProviderType } from "../../../authProviders/AuthProvidersApi";
+import { useEditorToolbarDispatchContext } from "../EditorToolbarContextProvider";
+
+export type GitIntegrationContextType = {
+  workspaceImportableUrl: ImportableUrl;
+  git: {
+    canPushToGitRepository: boolean;
+    canCreateGitRepository: boolean;
+    pushNewBranch: (newBranchName: string) => Promise<void>;
+    pushToGitRepository: () => Promise<void>;
+    pullFromGitRepository: (args: { showAlerts: boolean }) => Promise<void>;
+  };
+  gistOrSnippet: {
+    canCreateGistOrSnippet: boolean;
+    canUpdateGistOrSnippet: boolean;
+    canForkGitHubGist: boolean;
+    forceUpdateGistOrSnippet: () => Promise<void>;
+    updateGistOrSnippet: () => Promise<void>;
+    forkGitHubGist: () => Promise<void>;
+  };
+  auth: {
+    changeGitAuthSessionId: (
+      newGitAuthSessionId: SetStateAction<string | undefined>,
+      lastAuthSessionId: string | undefined
+    ) => void;
+    authSessionSelectFilter: AuthSessionSelectFilter;
+  };
+  alerts: ReturnType<typeof useGitIntegrationAlerts>;
+};
+
+export const GitIntegrationContext = createContext<GitIntegrationContextType>({} as any);
+
+export type GitIntegrationContextProviderProps = {
+  children: ReactNode;
+  workspace: ActiveWorkspace;
+};
+
+export function GitIntegrationContextProvider(props: GitIntegrationContextProviderProps) {
+  const workspaces = useWorkspaces();
+  const routes = useRoutes();
+  const history = useHistory();
+  const { authSession, authInfo, gitConfig } = useAuthSession(props.workspace.descriptor.gitAuthSessionId);
+  const authProvider = useAuthProvider(authSession);
+  const workspaceImportableUrl = useImportableUrl(props.workspace.descriptor.origin.url?.toString());
+  const alerts = useGitIntegrationAlerts(props.workspace);
+  const navigationBlockersBypass = useNavigationBlockersBypass();
+  const { setSyncGistOrSnippetDropdownOpen } = useEditorToolbarDispatchContext();
+
+  const gitHubClient = useGitHubClient(authSession);
+  const bitbucketClient = useBitbucketClient(authSession);
+
+  const [isGistOrSnippetLoading, setGistOrSnippetLoading] = useState(false);
+  const [gitHubGist, setGitHubGist] =
+    useState<OctokitRestEndpointMethodTypes["gists"]["get"]["response"]["data"] | undefined>(undefined);
+  const [bitbucketSnippet, setBitbucketSnippet] = useState<any>(undefined);
+
+  useCancelableEffect(
+    useCallback(
+      ({ canceled }) => {
+        if (gitHubGist || workspaceImportableUrl.type !== UrlType.GIST_DOT_GITHUB_DOT_COM) {
+          return;
+        }
+
+        const { gistId } = workspaceImportableUrl;
+
+        if (!gistId) {
+          return;
+        }
+
+        gitHubClient.gists.get({ gist_id: gistId }).then(({ data: gist }) => {
+          if (canceled.get()) {
+            return;
+          }
+
+          if (gist) {
+            setGitHubGist(gist);
+          }
+        });
+      },
+      [gitHubGist, workspaceImportableUrl, gitHubClient.gists]
+    )
+  );
+
+  useCancelableEffect(
+    useCallback(
+      ({ canceled }) => {
+        if (bitbucketSnippet || workspaceImportableUrl.type !== UrlType.BITBUCKET_DOT_ORG_SNIPPET) {
+          return;
+        }
+
+        const { snippetId, org } = workspaceImportableUrl;
+
+        if (!snippetId || !org) {
+          return;
+        }
+
+        bitbucketClient.getSnippet({ workspace: org, snippetId }).then(async (response) => {
+          if (canceled.get()) {
+            return;
+          }
+          const json = await response.json();
+          setBitbucketSnippet(json);
+        });
+      },
+      [bitbucketSnippet, workspaceImportableUrl, bitbucketClient]
+    )
+  );
+
+  const authSessionSelectFilter = useMemo(() => {
+    if (!props.workspace) {
+      return gitAuthSessionSelectFilter();
+    }
+
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.LOCAL) {
+      return gitAuthSessionSelectFilter();
+    }
+
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.GIT) {
+      return authSessionsSelectFilterCompatibleWithGitUrlDomain(
+        new URL(props.workspace.descriptor.origin.url).hostname
+      );
+    }
+
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.GITHUB_GIST) {
+      return authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain(
+        new URL(props.workspace.descriptor.origin.url).hostname,
+        gitHubGist?.owner?.login
+      );
+    }
+
+    if (props.workspace.descriptor.origin.kind === WorkspaceKind.BITBUCKET_SNIPPET) {
+      return authSessionsSelectFilterCompatibleWithGistOrSnippetUrlDomain(
+        new URL(props.workspace.descriptor.origin.url).hostname,
+        bitbucketSnippet?.owner?.login
+      );
+    }
+
+    return gitAuthSessionSelectFilter();
+  }, [bitbucketSnippet?.owner?.login, gitHubGist?.owner?.login, props.workspace]);
+
+  const changeGitAuthSessionId = useCallback(
+    (newGitAuthSessionId: React.SetStateAction<string | undefined>, lastAuthSessionId: string | undefined) => {
+      workspaces.changeGitAuthSessionId({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        gitAuthSessionId:
+          typeof newGitAuthSessionId === "function" ? newGitAuthSessionId(lastAuthSessionId) : newGitAuthSessionId,
+      });
+    },
+    [props.workspace.descriptor.workspaceId, workspaces]
+  );
+
+  const workspaceHasNestedDirectories = useMemo(
+    () => props.workspace.files.filter((f) => f.relativePath !== f.name).length !== 0,
+    [props.workspace]
+  );
+
+  const canCreateGitHubRepository = useMemo(() => authProvider?.type === "github", [authProvider?.type]);
+
+  const canCreateBitbucketRepository = useMemo(() => authProvider?.type === "bitbucket", [authProvider?.type]);
+
+  const canCreateGitRepository = useMemo(
+    () => canCreateGitHubRepository || canCreateBitbucketRepository,
+    [canCreateGitHubRepository, canCreateBitbucketRepository]
+  );
+
+  const canPushToGitRepository = useMemo(
+    () => authSession?.type === "git" && !!authProvider,
+    [authProvider, authSession?.type]
+  );
+
+  const isGitHubGistOwner = useMemo(() => {
+    return authInfo?.username && gitHubGist?.owner?.login === authInfo.username;
+  }, [authInfo, gitHubGist]);
+
+  const isBitbucketSnippetOwner = useMemo(() => {
+    return authInfo?.uuid && bitbucketSnippet?.creator.uuid === authInfo.uuid;
+  }, [authInfo, bitbucketSnippet]);
+
+  const isGistOrSnippetOwner = isGitHubGistOwner || isBitbucketSnippetOwner;
+
+  const canCreateGistOrSnippet = useMemo(
+    () =>
+      Boolean(
+        authProvider &&
+          isGistEnabledAuthProviderType(authProvider?.type) &&
+          props.workspace.descriptor.origin.kind === WorkspaceKind.LOCAL &&
+          !workspaceHasNestedDirectories
+      ),
+    [authProvider, props.workspace.descriptor.origin.kind, workspaceHasNestedDirectories]
+  );
+
+  const canUpdateGistOrSnippet = useMemo(
+    () =>
+      Boolean(
+        authProvider &&
+          isGistEnabledAuthProviderType(authProvider?.type) &&
+          !!isGistOrSnippetOwner &&
+          props.workspace &&
+          isGistLikeWorkspaceKind(props.workspace.descriptor.origin.kind) &&
+          !workspaceHasNestedDirectories
+      ),
+    [authProvider, isGistOrSnippetOwner, props.workspace, workspaceHasNestedDirectories]
+  );
+
+  const canForkGitHubGist = useMemo(
+    () =>
+      authProvider?.type === "github" &&
+      !isGistOrSnippetOwner &&
+      props.workspace.descriptor.origin.kind === WorkspaceKind.GITHUB_GIST &&
+      !workspaceHasNestedDirectories,
+    [authProvider?.type, isGistOrSnippetOwner, props.workspace.descriptor.origin.kind, workspaceHasNestedDirectories]
+  );
+
+  const pushNewBranch = useCallback(
+    async (newBranchName: string) => {
+      if (!authInfo || !props.workspace) {
+        return;
+      }
+
+      try {
+        alerts.pushingAlert.show();
+
+        await workspaces.createSavePoint({
+          workspaceId: props.workspace.descriptor.workspaceId,
+          gitConfig,
+        });
+
+        await workspaces.branch({
+          workspaceId: props.workspace.descriptor.workspaceId,
+          checkout: false,
+          name: newBranchName,
+        });
+
+        await workspaces.push({
+          workspaceId: props.workspace.descriptor.workspaceId,
+          remote: GIT_ORIGIN_REMOTE_NAME,
+          remoteRef: `refs/heads/${newBranchName}`,
+          ref: newBranchName,
+          force: false,
+          authInfo,
+        });
+
+        history.push({
+          pathname: routes.import.path({}),
+          search: routes.import.queryString({
+            url: `${props.workspace.descriptor.origin.url}`,
+            branch: newBranchName,
+            authSessionId: props.workspace.descriptor.gitAuthSessionId,
+          }),
+        });
+      } catch (e) {
+        alerts.pushErrorAlert.show();
+      } finally {
+        alerts.pushingAlert.close();
+      }
+    },
+    [
+      authInfo,
+      props.workspace,
+      alerts.pushingAlert,
+      alerts.pushErrorAlert,
+      workspaces,
+      gitConfig,
+      history,
+      routes.import,
+    ]
+  );
+
+  const pullFromGitRepository = useCallback(
+    async (args: { showAlerts: boolean }) => {
+      alerts.pullingAlert.close();
+      alerts.pullErrorAlert.close();
+      alerts.pullSuccessAlert.close();
+
+      if (args.showAlerts) {
+        alerts.pullingAlert.show();
+      }
+      await workspaces.createSavePoint({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        gitConfig,
+      });
+
+      try {
+        await workspaces.pull({
+          workspaceId: props.workspace.descriptor.workspaceId,
+          authInfo,
+        });
+
+        if (args.showAlerts) {
+          alerts.pullSuccessAlert.show();
+        }
+      } catch (e) {
+        console.error(e);
+        if (args.showAlerts) {
+          const randomString = (Math.random() + 1).toString(36).substring(7);
+          const newBranchName = `${props.workspace.descriptor.origin.branch}-${randomString}`;
+          alerts.pullErrorAlert.show({ newBranchName, canPushToGitRepository, pushNewBranch });
+        }
+      } finally {
+        if (args.showAlerts) {
+          alerts.pullingAlert.close();
+        }
+      }
+    },
+    [
+      alerts.pullingAlert,
+      alerts.pullErrorAlert,
+      alerts.pullSuccessAlert,
+      workspaces,
+      props.workspace.descriptor.workspaceId,
+      props.workspace.descriptor.origin.branch,
+      gitConfig,
+      authInfo,
+      canPushToGitRepository,
+      pushNewBranch,
+    ]
+  );
+
+  const pushToGitRepository = useCallback(async () => {
+    alerts.pushingAlert.close();
+    alerts.pushErrorAlert.close();
+    alerts.pushSuccessAlert.close();
+
+    if (!authInfo) {
+      return;
+    }
+
+    alerts.pushingAlert.show();
+    try {
+      const workspaceId = props.workspace.descriptor.workspaceId;
+      await workspaces.createSavePoint({
+        workspaceId: workspaceId,
+        gitConfig,
+      });
+
+      const workspace = await workspaces.getWorkspace({ workspaceId });
+      await workspaces.push({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        ref: workspace.origin.branch,
+        remote: GIST_ORIGIN_REMOTE_NAME,
+        remoteRef: `refs/heads/${workspace.origin.branch}`,
+        force: false,
+        authInfo,
+      });
+      await pullFromGitRepository({ showAlerts: false });
+      alerts.pushSuccessAlert.show();
+    } catch (e) {
+      console.error(e);
+      alerts.pushErrorAlert.show();
+    } finally {
+      alerts.pushingAlert.close();
+    }
+  }, [
+    alerts.pushingAlert,
+    alerts.pushErrorAlert,
+    alerts.pushSuccessAlert,
+    authInfo,
+    props.workspace.descriptor.workspaceId,
+    workspaces,
+    gitConfig,
+    pullFromGitRepository,
+  ]);
+
+  const forceUpdateGistOrSnippet = useCallback(async () => {
+    try {
+      if (!authInfo || !props.workspace) {
+        return;
+      }
+
+      setGistOrSnippetLoading(true);
+
+      await workspaces.push({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        remote: GIST_ORIGIN_REMOTE_NAME,
+        ref: props.workspace.descriptor.origin.branch,
+        remoteRef: `refs/heads/${props.workspace.descriptor.origin.branch}`,
+        force: true,
+        authInfo,
+      });
+
+      await workspaces.pull({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        authInfo,
+      });
+    } catch (e) {
+      alerts.errorAlert.show();
+    } finally {
+      setGistOrSnippetLoading(false);
+      setSyncGistOrSnippetDropdownOpen(false);
+    }
+
+    alerts.successfullyUpdatedGistOrSnippetAlert.show();
+  }, [
+    alerts.errorAlert,
+    alerts.successfullyUpdatedGistOrSnippetAlert,
+    authInfo,
+    props.workspace,
+    setSyncGistOrSnippetDropdownOpen,
+    workspaces,
+  ]);
+
+  const updateGistOrSnippet = useCallback(async () => {
+    try {
+      if (
+        !authInfo ||
+        !props.workspace ||
+        !isGistEnabledAuthProviderType(authProvider?.type) ||
+        !isGistLikeWorkspaceKind(props.workspace.descriptor.origin.kind)
+      ) {
+        return;
+      }
+      setGistOrSnippetLoading(true);
+
+      await workspaces.createSavePoint({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        gitConfig,
+      });
+
+      await workspaces.push({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        remote: GIST_ORIGIN_REMOTE_NAME,
+        ref: props.workspace.descriptor.origin.branch,
+        remoteRef: `refs/heads/${props.workspace.descriptor.origin.branch}`,
+        force: false,
+        authInfo,
+      });
+
+      await workspaces.pull({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        authInfo,
+      });
+    } catch (e) {
+      alerts.errorPushingGistOrSnippet.show({ forceUpdateGistOrSnippet });
+      throw e;
+    } finally {
+      setGistOrSnippetLoading(false);
+      setSyncGistOrSnippetDropdownOpen(false);
+    }
+
+    alerts.successfullyUpdatedGistOrSnippetAlert.show();
+  }, [
+    alerts.successfullyUpdatedGistOrSnippetAlert,
+    alerts.errorPushingGistOrSnippet,
+    authInfo,
+    props.workspace,
+    authProvider?.type,
+    workspaces,
+    gitConfig,
+    forceUpdateGistOrSnippet,
+    setSyncGistOrSnippetDropdownOpen,
+  ]);
+
+  const forkGitHubGist = useCallback(async () => {
+    try {
+      if (!authSession || !authInfo || !gitHubGist?.id || !props.workspace) {
+        return;
+      }
+
+      setGistOrSnippetLoading(true);
+
+      // Fork Gist
+      const gist = await gitHubClient.gists.fork({
+        gist_id: gitHubGist.id,
+      });
+
+      const remoteName = gist.data.id;
+
+      // Adds forked gist remote to current one
+      await workspaces.addRemote({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        url: gist.data.git_push_url,
+        name: remoteName,
+        force: true,
+      });
+
+      // Commit
+      await workspaces.createSavePoint({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        gitConfig,
+      });
+
+      // Push to forked gist remote
+      await workspaces.push({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        remote: remoteName,
+        ref: props.workspace.descriptor.origin.branch,
+        remoteRef: `refs/heads/${props.workspace.descriptor.origin.branch}`,
+        force: true,
+        authInfo,
+      });
+
+      // Redirect to import workspace
+      navigationBlockersBypass.execute(() => {
+        history.push({
+          pathname: routes.import.path({}),
+          search: routes.import.queryString({
+            url: gist.data.html_url,
+            authSessionId: authSession.id,
+          }),
+        });
+      });
+    } catch (err) {
+      alerts.errorAlert.show();
+      throw err;
+    } finally {
+      setGistOrSnippetLoading(false);
+    }
+  }, [
+    authSession,
+    authInfo,
+    gitHubGist,
+    props.workspace,
+    gitHubClient.gists,
+    workspaces,
+    gitConfig,
+    navigationBlockersBypass,
+    history,
+    routes.import,
+    alerts.errorAlert,
+  ]);
+
+  useEffect(() => {
+    if (isGistOrSnippetLoading) {
+      alerts.loadingGistOrSnippetAlert.show();
+    } else {
+      alerts.loadingGistOrSnippetAlert.close();
+    }
+  }, [alerts.loadingGistOrSnippetAlert, isGistOrSnippetLoading]);
+
+  const value = useMemo(
+    () => ({
+      workspaceImportableUrl,
+      git: {
+        canPushToGitRepository,
+        canCreateGitRepository,
+        pushNewBranch,
+        pushToGitRepository,
+        pullFromGitRepository,
+      },
+      gistOrSnippet: {
+        canCreateGistOrSnippet,
+        canUpdateGistOrSnippet,
+        canForkGitHubGist,
+        forceUpdateGistOrSnippet,
+        updateGistOrSnippet,
+        forkGitHubGist,
+      },
+      auth: {
+        authSessionSelectFilter,
+        changeGitAuthSessionId,
+      },
+      alerts,
+    }),
+    [
+      workspaceImportableUrl,
+      canPushToGitRepository,
+      canCreateGitRepository,
+      pushNewBranch,
+      pushToGitRepository,
+      pullFromGitRepository,
+      canCreateGistOrSnippet,
+      canUpdateGistOrSnippet,
+      canForkGitHubGist,
+      forceUpdateGistOrSnippet,
+      updateGistOrSnippet,
+      forkGitHubGist,
+      authSessionSelectFilter,
+      changeGitAuthSessionId,
+      alerts,
+    ]
+  );
+
+  return <GitIntegrationContext.Provider value={value}>{props.children}</GitIntegrationContext.Provider>;
+}
+
+export function useGitIntegration() {
+  return useContext(GitIntegrationContext);
+}
diff --git a/packages/online-editor/src/editor/LoadOrganizationsSelect.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
similarity index 82%
rename from packages/online-editor/src/editor/LoadOrganizationsSelect.tsx
rename to packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
index 43ec3f76d4..15aa56d71a 100644
--- a/packages/online-editor/src/editor/LoadOrganizationsSelect.tsx
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/LoadOrganizationsSelect.tsx
@@ -14,28 +14,25 @@
  * limitations under the License.
  */
 
-import * as React from "react";
-import { useMemo } from "react";
+import React, { useMemo } from "react";
 import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
-import {
-  Button,
-  Divider,
-  Flex,
-  FlexItem,
-  Select,
-  SelectGroup,
-  SelectOption,
-  SelectVariant,
-} from "@patternfly/react-core";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Select, SelectGroup, SelectOption, SelectVariant } from "@patternfly/react-core/dist/js/components/Select";
 import { useCallback, useEffect, useState } from "react";
-import { AuthProviderType, isSupportedGitAuthProviderType } from "../authProviders/AuthProvidersApi";
-import { useAuthProvider } from "../authProviders/AuthProvidersContext";
-import { useAuthSession } from "../authSessions/AuthSessionsContext";
-import { useBitbucketClient } from "../bitbucket/Hooks";
-import { useGitHubClient } from "../github/Hooks";
-import { switchExpression } from "../switchExpression/switchExpression";
-import { BitbucketIcon, GithubIcon, SyncAltIcon, UserAltIcon, UserIcon, UsersIcon } from "@patternfly/react-icons";
-import { useOnlineI18n } from "../i18n";
+import { AuthProviderType, isSupportedGitAuthProviderType } from "../../../authProviders/AuthProvidersApi";
+import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
+import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
+import { useBitbucketClient } from "../../../bitbucket/Hooks";
+import { useGitHubClient } from "../../../github/Hooks";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { BitbucketIcon } from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
+import { GithubIcon } from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { SyncAltIcon } from "@patternfly/react-icons/dist/js/icons/sync-alt-icon";
+import { UserIcon } from "@patternfly/react-icons/dist/js/icons/user-icon";
+import { UsersIcon } from "@patternfly/react-icons/dist/js/icons/users-icon";
+import { useOnlineI18n } from "../../../i18n";
 
 export interface LoadOrganizationsReponse {
   organizations: {
@@ -105,12 +102,13 @@ export const LoadOrganizationsSelect = (props: Props) => {
     return { organizations: values.map((it) => ({ name: it.workspace.slug })) };
   }, [bitbucketClient]);
 
+  const { onSelect } = props;
   const setSelectedOption = useCallback(
     (option?: SelectOptionObjectType) => {
-      props.onSelect(option);
+      onSelect(option);
       setInternalSelectedOption(option);
     },
-    [props]
+    [onSelect]
   );
 
   const selectDefaultOption = useCallback(
@@ -125,7 +123,7 @@ export const LoadOrganizationsSelect = (props: Props) => {
         })
       );
     },
-    [authInfo?.username, authProvider?.type]
+    [authInfo, authProvider?.type, setSelectedOption]
   );
 
   const loadOrganizations = useCallback(() => {
@@ -152,9 +150,9 @@ export const LoadOrganizationsSelect = (props: Props) => {
     if (authProvider && isSupportedGitAuthProviderType(authProvider?.type)) {
       loadOrganizations();
     }
-  }, [loadOrganizations, authProvider?.type, authProvider]);
+  }, [loadOrganizations, setSelectedOption, authProvider]);
 
-  const selectOptions = useCallback(() => {
+  const selectOptions = useMemo(() => {
     const options: JSX.Element[] = [];
     if (!authProvider || !isSupportedGitAuthProviderType(authProvider.type)) {
       return options;
@@ -215,7 +213,7 @@ export const LoadOrganizationsSelect = (props: Props) => {
             selections={internalSelectedOption}
             isDisabled={props.readonly}
           >
-            {selectOptions()}
+            {selectOptions}
           </Select>
         )}
       </FlexItem>
diff --git a/packages/online-editor/src/editor/Toolbar/GitIntegration/PushToGitAlertActionLinks.tsx b/packages/online-editor/src/editor/Toolbar/GitIntegration/PushToGitAlertActionLinks.tsx
new file mode 100644
index 0000000000..6ab16f1801
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/GitIntegration/PushToGitAlertActionLinks.tsx
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useMemo } from "react";
+import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
+import { AuthSessionSelect, AuthSessionSelectFilter } from "../../../authSessions/AuthSessionSelect";
+import { AccountsDispatchActionKind, useAccountsDispatch } from "../../../accounts/AccountsContext";
+import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { Alert, AlertActionLink } from "@patternfly/react-core/dist/js/components/Alert";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { SelectPosition } from "@patternfly/react-core/dist/js/components/Select";
+import { AuthProviderGroup } from "../../../authProviders/AuthProvidersApi";
+
+export function PushToGitAlertActionLinks(props: {
+  onPush: () => void;
+  canPush?: boolean;
+  remoteRef?: string;
+  workspaceDescriptor: WorkspaceDescriptor | undefined;
+  changeGitAuthSessionId: (a: React.SetStateAction<string | undefined>, b: string | undefined) => void;
+  authSessionSelectFilter: AuthSessionSelectFilter;
+}) {
+  const accountsDispatch = useAccountsDispatch();
+  if (props.workspaceDescriptor?.origin.kind === WorkspaceKind.GIT && !props.remoteRef) {
+    throw new Error("Should specify remoteRef for GIT workspaces");
+  }
+
+  const pushButton = useMemo(
+    () => (
+      <AlertActionLink onClick={props.onPush} style={{ fontWeight: "bold" }} isDisabled={!props.canPush}>
+        {props.workspaceDescriptor
+          ? switchExpression(props.workspaceDescriptor.origin.kind, {
+              GIT: `Push to '${props.remoteRef}'`,
+              GITHUB_GIST: "Update Gist",
+              BITBUCKET_SNIPPET: "Update Snippet",
+              default: "",
+            })
+          : ""}
+      </AlertActionLink>
+    ),
+    [props]
+  );
+
+  return (
+    <>
+      {!props.canPush && (
+        <Alert
+          isInline={true}
+          variant={"default"}
+          title={"Can't Push without selecting an authentication source"}
+          actionLinks={
+            <>
+              <AuthSessionSelect
+                title={`Select Git authentication for '${props.workspaceDescriptor?.name}'...`}
+                position={SelectPosition.right}
+                isPlain={false}
+                authSessionId={props.workspaceDescriptor?.gitAuthSessionId}
+                showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+                setAuthSessionId={(newAuthSessionId) => {
+                  props.changeGitAuthSessionId(newAuthSessionId, props.workspaceDescriptor?.gitAuthSessionId);
+                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+                }}
+                filter={props.authSessionSelectFilter}
+              />
+              <br />
+              <br />
+              {pushButton}
+            </>
+          }
+        >
+          {`Select an authentication source for '${props.workspaceDescriptor?.name}' to be able to Push.`}
+          <br />
+        </Alert>
+      )}
+      {props.canPush && pushButton}
+    </>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/KebabDropdown.tsx b/packages/online-editor/src/editor/Toolbar/KebabDropdown.tsx
new file mode 100644
index 0000000000..0743a3b0a4
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/KebabDropdown.tsx
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import { Dropdown, DropdownPosition, DropdownToggle } from "@patternfly/react-core/dist/js/components/Dropdown";
+import EllipsisVIcon from "@patternfly/react-icons/dist/js/icons/ellipsis-v-icon";
+
+export function KebabDropdown(props: {
+  id: string;
+  items: React.ReactNode[];
+  state: [boolean, React.Dispatch<React.SetStateAction<boolean>>];
+}) {
+  return (
+    <Dropdown
+      className={"kie-tools--masthead-hoverable"}
+      isOpen={props.state[0]}
+      isPlain={true}
+      position={DropdownPosition.right}
+      onSelect={() => props.state[1](false)}
+      toggle={
+        <DropdownToggle
+          id={props.id}
+          toggleIndicator={null}
+          onToggle={(isOpen) => props.state[1](isOpen)}
+          ouiaId={props.id}
+        >
+          <EllipsisVIcon />
+        </DropdownToggle>
+      }
+      dropdownItems={props.items}
+    />
+  );
+}
diff --git a/packages/online-editor/src/editor/NewFileDropdownMenu.tsx b/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
similarity index 81%
rename from packages/online-editor/src/editor/NewFileDropdownMenu.tsx
rename to packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
index 17e88deb70..14094d632c 100644
--- a/packages/online-editor/src/editor/NewFileDropdownMenu.tsx
+++ b/packages/online-editor/src/editor/Toolbar/NewFileDropdownMenu.tsx
@@ -17,7 +17,7 @@
 import * as React from "react";
 import { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
-import { FileLabel } from "../filesList/FileLabel";
+import { FileLabel } from "../../filesList/FileLabel";
 import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
 import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
 import {
@@ -32,22 +32,25 @@ import {
 import {
   SupportedFileExtensions,
   useEditorEnvelopeLocator,
-} from "../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
+} from "../../envelopeLocator/hooks/EditorEnvelopeLocatorContext";
 import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
 import { Alert, AlertActionCloseButton } from "@patternfly/react-core/dist/js/components/Alert";
 import { basename, extname } from "path";
-import { ImportSingleFileFromUrlForm } from "../importFromUrl/ImportSingleFileFromUrlForm";
-import { ImportableUrl, UrlType, useImportableUrl } from "../importFromUrl/ImportableUrlHooks";
-import { useRoutes } from "../navigation/Hooks";
-import { fetchSingleFileContent } from "../importFromUrl/fetchSingleFileContent";
-import { useAuthSession, useAuthSessions } from "../authSessions/AuthSessionsContext";
-import { useGitHubClient } from "../github/Hooks";
-import { useAuthProviders } from "../authProviders/AuthProvidersContext";
-import { getCompatibleAuthSessionWithUrlDomain } from "../authSessions/CompatibleAuthSessions";
+import { ImportSingleFileFromUrlForm } from "../../importFromUrl/ImportSingleFileFromUrlForm";
+import { ImportableUrl, UrlType, useImportableUrl } from "../../importFromUrl/ImportableUrlHooks";
+import { useRoutes } from "../../navigation/Hooks";
+import { fetchSingleFileContent } from "../../importFromUrl/fetchSingleFileContent";
+import { useAuthSession, useAuthSessions } from "../../authSessions/AuthSessionsContext";
+import { useGitHubClient } from "../../github/Hooks";
+import { useAuthProviders } from "../../authProviders/AuthProvidersContext";
+import { getCompatibleAuthSessionWithUrlDomain } from "../../authSessions/CompatibleAuthSessions";
 import { decoder } from "@kie-tools-core/workspaces-git-fs/dist/encoderdecoder/EncoderDecoder";
 import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
-import { useGlobalAlert } from "../alerts";
-import { useBitbucketClient } from "../bitbucket/Hooks";
+import { useGlobalAlert } from "../../alerts";
+import { useBitbucketClient } from "../../bitbucket/Hooks";
+import { isEditable } from "../../envelopeLocator/EditorEnvelopeLocatorFactory";
+
+const ROOT_MENU_ID = "addFileRootMenu";
 
 export function NewFileDropdownMenu(props: {
   destinationDirPath: string;
@@ -59,28 +62,33 @@ export function NewFileDropdownMenu(props: {
   const [menuDrilledIn, setMenuDrilledIn] = useState<string[]>([]);
   const [drilldownPath, setDrilldownPath] = useState<string[]>([]);
   const [menuHeights, setMenuHeights] = useState<{ [key: string]: number }>({});
-  const [activeMenu, setActiveMenu] = useState("addFileRootMenu");
+  const [activeMenu, setActiveMenu] = useState(ROOT_MENU_ID);
 
-  const drillIn = useCallback((fromMenuId, toMenuId, pathId) => {
+  const drillIn = useCallback((_event, fromMenuId, toMenuId, pathId) => {
     setMenuDrilledIn((prev) => [...prev, fromMenuId]);
     setDrilldownPath((prev) => [...prev, pathId]);
     setActiveMenu(toMenuId);
   }, []);
 
-  const drillOut = useCallback((toMenuId) => {
+  const drillOut = useCallback((_event, toMenuId) => {
     setMenuDrilledIn((prev) => prev.slice(0, prev.length - 1));
     setDrilldownPath((prev) => prev.slice(0, prev.length - 1));
     setActiveMenu(toMenuId);
   }, []);
 
   const setHeight = useCallback((menuId: string, height: number) => {
-    // do not try to simplify this ternary's condition as some heights are 0, resulting in an infinite loop.
-    setMenuHeights((prev) => (prev[menuId] !== undefined ? prev : { ...prev, [menuId]: height }));
+    setMenuHeights((prev) => {
+      if (prev[menuId] === undefined || (menuId !== ROOT_MENU_ID && prev[menuId] !== height)) {
+        return { ...prev, [menuId]: height };
+      }
+      return prev;
+    });
   }, []);
 
   const workspaces = useWorkspaces();
   const routes = useRoutes();
   const editorEnvelopeLocator = useEditorEnvelopeLocator();
+  const { gitConfig } = useAuthSession(props.workspaceDescriptor.gitAuthSessionId);
 
   const addEmptyFile = useCallback(
     async (extension: SupportedFileExtensions) => {
@@ -147,12 +155,30 @@ export function NewFileDropdownMenu(props: {
         })
       );
 
+      // Since non-editable files are not checked for changes, manually stage and commit these files
+      await Promise.all(
+        uploadedFiles.map(async (file) => {
+          if (!isEditable(file.relativePath)) {
+            return workspaces.stageFile({
+              workspaceId: props.workspaceDescriptor.workspaceId,
+              relativePath: file.relativePath,
+            });
+          }
+        })
+      );
+      await workspaces.createSavePoint({
+        workspaceId: props.workspaceDescriptor.workspaceId,
+        gitConfig,
+        commitMessage: `KIE Sandbox: Added files${uploadedFiles.map((file) => `\n- ${file.relativePath}`)}`,
+        forceHasChanges: true,
+      });
+
       const fileToGoTo = uploadedFiles.filter((file) => editorEnvelopeLocator.hasMappingFor(file.relativePath)).pop();
 
       await props.onAddFile(fileToGoTo);
       successfullyUploadedAlert.show({ qtt: uploadedFiles.length });
     },
-    [editorEnvelopeLocator, workspaces, props, successfullyUploadedAlert]
+    [editorEnvelopeLocator, workspaces, props, successfullyUploadedAlert, gitConfig]
   );
 
   const [url, setUrl] = useState("");
@@ -247,7 +273,7 @@ export function NewFileDropdownMenu(props: {
     <Menu
       tabIndex={1}
       style={{ boxShadow: "none", minWidth: "400px" }}
-      id="addFileRootMenu"
+      id={ROOT_MENU_ID}
       containsDrilldown={true}
       onDrillIn={drillIn}
       onDrillOut={drillOut}
@@ -257,7 +283,7 @@ export function NewFileDropdownMenu(props: {
       drilledInMenus={menuDrilledIn}
     >
       <MenuContent menuHeight={`${menuHeights[activeMenu]}px`}>
-        <MenuList>
+        <MenuList style={{ padding: 0 }}>
           <MenuItem
             itemId={"newBpmnItemId"}
             onClick={() => addEmptyFile("bpmn")}
@@ -267,28 +293,24 @@ export function NewFileDropdownMenu(props: {
               <FileLabel style={{ marginBottom: "4px" }} extension={"bpmn"} />
             </b>
           </MenuItem>
-          <MenuGroup label={" "}>
-            <MenuItem
-              itemId={"newDmnItemId"}
-              onClick={() => addEmptyFile("dmn")}
-              description="DMN files are used to generate decision models"
-            >
-              <b>
-                <FileLabel style={{ marginBottom: "4px" }} extension={"dmn"} />
-              </b>
-            </MenuItem>
-          </MenuGroup>
-          <MenuGroup label={" "}>
-            <MenuItem
-              itemId={"newPmmlItemId"}
-              onClick={() => addEmptyFile("pmml")}
-              description="PMML files are used to generate scorecards"
-            >
-              <b>
-                <FileLabel style={{ marginBottom: "4px" }} extension={"pmml"} />
-              </b>
-            </MenuItem>
-          </MenuGroup>
+          <MenuItem
+            itemId={"newDmnItemId"}
+            onClick={() => addEmptyFile("dmn")}
+            description="DMN files are used to generate decision models"
+          >
+            <b>
+              <FileLabel style={{ marginBottom: "4px" }} extension={"dmn"} />
+            </b>
+          </MenuItem>
+          <MenuItem
+            itemId={"newPmmlItemId"}
+            onClick={() => addEmptyFile("pmml")}
+            description="PMML files are used to generate scorecards"
+          >
+            <b>
+              <FileLabel style={{ marginBottom: "4px" }} extension={"pmml"} />
+            </b>
+          </MenuItem>
           <Divider />
           <MenuItem
             description={"Try sample models"}
diff --git a/packages/online-editor/src/editor/Toolbar/Share/DownloadDropdownGroup.tsx b/packages/online-editor/src/editor/Toolbar/Share/DownloadDropdownGroup.tsx
new file mode 100644
index 0000000000..ed0d17e583
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Share/DownloadDropdownGroup.tsx
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useEffect, useMemo } from "react";
+import { DropdownGroup, DropdownItem } from "@patternfly/react-core/dist/js/components/Dropdown";
+import DownloadIcon from "@patternfly/react-icons/dist/js/icons/download-icon";
+import FolderIcon from "@patternfly/react-icons/dist/js/icons/folder-icon";
+import ImageIcon from "@patternfly/react-icons/dist/js/icons/image-icon";
+import { WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { useGlobalAlertsDispatchContext } from "../../../alerts";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { EmbeddedEditorRef } from "@kie-tools-core/editor/dist/embedded";
+import { useEditorToolbarContext } from "../EditorToolbarContextProvider";
+
+type Props = {
+  workspaceFile: WorkspaceFile;
+  workspace: ActiveWorkspace;
+  editor: EmbeddedEditorRef | undefined;
+};
+
+export const DownloadDropdownGroup = (props: Props) => {
+  const alertsDispatch = useGlobalAlertsDispatchContext();
+  const { downloadRef, downloadAllRef, downloadPreviewRef, downloadWorkspaceZip } = useEditorToolbarContext();
+
+  useEffect(() => {
+    if (!props.workspaceFile) {
+      return;
+    }
+    if (downloadRef.current) {
+      downloadRef.current.download = `${props.workspaceFile.name}`;
+    }
+    if (downloadAllRef.current) {
+      downloadAllRef.current.download = `${props.workspace.descriptor.name}.zip`;
+    }
+    if (downloadPreviewRef.current) {
+      downloadPreviewRef.current.download = `${props.workspaceFile.name}.svg`;
+    }
+  }, [props.workspaceFile, props.workspace.descriptor, downloadRef, downloadAllRef, downloadPreviewRef]);
+
+  const shouldIncludeDownloadSvgDropdownItem = useMemo(() => {
+    return props.workspaceFile.extension.toLowerCase() !== "pmml";
+  }, [props.workspaceFile]);
+
+  const onDownload = useCallback(() => {
+    props.editor?.getStateControl().setSavedCommand();
+    alertsDispatch.closeAll();
+    props.workspaceFile.getFileContents().then((content) => {
+      if (downloadRef.current) {
+        const fileBlob = new Blob([content], { type: "text/plain" });
+        downloadRef.current.href = URL.createObjectURL(fileBlob);
+        downloadRef.current.click();
+      }
+    });
+  }, [props.editor, props.workspaceFile, alertsDispatch, downloadRef]);
+
+  const downloadSvg = useCallback(() => {
+    props.editor?.getPreview().then((previewSvg) => {
+      if (downloadPreviewRef.current && previewSvg) {
+        const fileBlob = new Blob([previewSvg], { type: "image/svg+xml" });
+        downloadPreviewRef.current.href = URL.createObjectURL(fileBlob);
+        downloadPreviewRef.current.click();
+      }
+    });
+  }, [downloadPreviewRef, props.editor]);
+
+  return (
+    <DropdownGroup key={"download-group"} label="Download">
+      <DropdownItem
+        onClick={onDownload}
+        key={"download-file-item"}
+        description={`${props.workspaceFile.name} will be downloaded`}
+        icon={<DownloadIcon />}
+        ouiaId="download-file-dropdown-button"
+      >
+        Current file
+      </DropdownItem>
+      {shouldIncludeDownloadSvgDropdownItem && (
+        <DropdownItem
+          key={`dropdown-download-svg`}
+          data-testid="dropdown-download-svg"
+          component="button"
+          onClick={downloadSvg}
+          description={`Image of ${props.workspaceFile.name} will be downloaded in SVG format`}
+          icon={<ImageIcon />}
+        >
+          {"Current file's SVG"}
+        </DropdownItem>
+      )}
+      <DropdownItem
+        onClick={downloadWorkspaceZip}
+        key={"download-zip-item"}
+        description={`A zip file including all files will be downloaded`}
+        icon={<FolderIcon />}
+      >
+        All files
+      </DropdownItem>
+    </DropdownGroup>
+  );
+};
diff --git a/packages/online-editor/src/editor/Toolbar/Share/EmbedDropdownGroup.tsx b/packages/online-editor/src/editor/Toolbar/Share/EmbedDropdownGroup.tsx
new file mode 100644
index 0000000000..7c6520d23e
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Share/EmbedDropdownGroup.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useMemo } from "react";
+import { DropdownGroup, DropdownItem } from "@patternfly/react-core/dist/js/components/Dropdown";
+import { WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import ColumnsIcon from "@patternfly/react-icons/dist/js/icons/columns-icon";
+import { useOnlineI18n } from "../../../i18n";
+import { useEditorToolbarDispatchContext } from "../EditorToolbarContextProvider";
+
+type Props = {
+  workspaceFile: WorkspaceFile;
+  workspace: ActiveWorkspace;
+};
+
+export const EmbedDropdownGroup = (props: Props) => {
+  const { i18n } = useOnlineI18n();
+  const { setEmbedModalOpen } = useEditorToolbarDispatchContext();
+
+  const shouldIncludeEmbedDropdownItem = useMemo(() => {
+    return props.workspaceFile.extension.toLowerCase() !== "pmml";
+  }, [props.workspaceFile]);
+
+  const openEmbedModal = useCallback(() => {
+    setEmbedModalOpen(true);
+  }, [setEmbedModalOpen]);
+
+  if (!shouldIncludeEmbedDropdownItem) {
+    return null;
+  }
+
+  return (
+    <>
+      <Divider key={"divider-other-group"} />
+      <DropdownGroup key={"other-group"} label="Other">
+        <DropdownItem
+          key={`dropdown-embed`}
+          data-testid="dropdown-embed"
+          component="button"
+          onClick={openEmbedModal}
+          icon={<ColumnsIcon />}
+        >
+          {i18n.editorToolbar.embed}...
+        </DropdownItem>
+      </DropdownGroup>
+    </>
+  );
+};
diff --git a/packages/online-editor/src/editor/EmbedModal.tsx b/packages/online-editor/src/editor/Toolbar/Share/EmbedModal.tsx
similarity index 98%
rename from packages/online-editor/src/editor/EmbedModal.tsx
rename to packages/online-editor/src/editor/Toolbar/Share/EmbedModal.tsx
index 569edcb5af..1573209906 100644
--- a/packages/online-editor/src/editor/EmbedModal.tsx
+++ b/packages/online-editor/src/editor/Toolbar/Share/EmbedModal.tsx
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 Red Hat, Inc. and/or its affiliates.
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import { Modal, ModalVariant } from "@patternfly/react-core/dist/js/components/M
 import { Radio } from "@patternfly/react-core/dist/js/components/Radio";
 import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
 import { ClipboardCopy, ClipboardCopyVariant } from "@patternfly/react-core/dist/js/components/ClipboardCopy";
-import { useOnlineI18n } from "../i18n";
+import { useOnlineI18n } from "../../../i18n";
 import { WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
 import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
 import { GistOrigin, WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
diff --git a/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx b/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx
new file mode 100644
index 0000000000..771eba4d54
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Share/GitDropdownGroup.tsx
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import {
+  WorkspaceKind,
+  isGistLikeWorkspaceKind,
+} from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { useOnlineI18n } from "../../../i18n";
+import {
+  AuthProviderGroup,
+  GistEnabledAuthProviderType,
+  GitAuthProviderType,
+} from "../../../authProviders/AuthProvidersApi";
+import { SelectPosition } from "@patternfly/react-core/dist/js/components/Select";
+import { DropdownGroup, DropdownItem } from "@patternfly/react-core/dist/js/components/Dropdown";
+import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
+import { AuthSessionSelect } from "../../../authSessions/AuthSessionSelect";
+import { AccountsDispatchActionKind, useAccountsDispatch } from "../../../accounts/AccountsContext";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import BitbucketIcon from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
+import GithubIcon from "@patternfly/react-icons/dist/js/icons/github-icon";
+import GitIcon from "@patternfly/react-icons/dist/js/icons/git-icon";
+import { useAuthSession } from "../../../authSessions/AuthSessionsContext";
+import { useAuthProvider } from "../../../authProviders/AuthProvidersContext";
+import { useGitIntegration } from "../GitIntegration/GitIntegrationContextProvider";
+import { useEditorToolbarDispatchContext } from "../EditorToolbarContextProvider";
+
+type Props = {
+  workspace: ActiveWorkspace;
+};
+
+export const GitDropdownGroup = (props: Props) => {
+  const { i18n } = useOnlineI18n();
+  const { authSession } = useAuthSession(props.workspace.descriptor.gitAuthSessionId);
+  const authProvider = useAuthProvider(authSession);
+  const accountsDispatch = useAccountsDispatch();
+
+  const {
+    auth: { authSessionSelectFilter, changeGitAuthSessionId },
+    git: { canCreateGitRepository },
+    gistOrSnippet: { canCreateGistOrSnippet },
+  } = useGitIntegration();
+  const { setCreateGitRepositoryModalOpen, setCreateGistOrSnippetModalOpen, setShareDropdownOpen, setSmallKebabOpen } =
+    useEditorToolbarDispatchContext();
+
+  if (
+    props.workspace.descriptor.origin.kind !== WorkspaceKind.LOCAL &&
+    !isGistLikeWorkspaceKind(props.workspace.descriptor.origin.kind)
+  ) {
+    return null;
+  }
+
+  return (
+    <>
+      <DropdownGroup key={"git-group"} label={i18n.names.git}>
+        <Alert
+          isInline={true}
+          variant={"info"}
+          title={"Authentication source"}
+          actionLinks={
+            <AuthSessionSelect
+              title={`Select Git authentication for '${props.workspace.descriptor.name}'...`}
+              position={SelectPosition.right}
+              isPlain={false}
+              authSessionId={props.workspace.descriptor.gitAuthSessionId}
+              showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+              setAuthSessionId={(newAuthSessionId) => {
+                changeGitAuthSessionId(newAuthSessionId, props.workspace.descriptor.gitAuthSessionId);
+                setTimeout(() => {
+                  accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+                  setShareDropdownOpen(true);
+                  setSmallKebabOpen(true);
+                }, 0);
+              }}
+              filter={authSessionSelectFilter}
+            />
+          }
+        >
+          {`Manage authentication sources for '${props.workspace.descriptor.name}' to be able to create Repository, GitHub Gist or Bitbucket Snippet.`}
+        </Alert>
+        {canCreateGitRepository && (
+          <Tooltip
+            data-testid={"create-git-repository-tooltip"}
+            key={`dropdown-create-git-repository`}
+            content={<div>{"Click to create a repository."}</div>}
+            trigger={!canCreateGitRepository ? "mouseenter click" : ""}
+            position="left"
+          >
+            <DropdownItem
+              icon={switchExpression(authProvider?.type as GitAuthProviderType, {
+                bitbucket: <BitbucketIcon />,
+                github: <GithubIcon />,
+                default: <GitIcon />,
+              })}
+              data-testid={"create-git-repository-button"}
+              component="button"
+              onClick={() => setCreateGitRepositoryModalOpen(true)}
+              isDisabled={!canCreateGitRepository}
+            >
+              Create{" "}
+              {switchExpression(authProvider?.type as GitAuthProviderType, {
+                github: "GitHub repository",
+                bitbucket: "Bitbucket repository",
+                default: "Git repository",
+              })}
+              ...
+            </DropdownItem>
+          </Tooltip>
+        )}
+        {canCreateGistOrSnippet && (
+          <Tooltip
+            data-testid={"create-gist-or-snippet-tooltip"}
+            key={`dropdown-create-gist-or-snippet`}
+            content={
+              <div>
+                {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
+                  github: i18n.editorToolbar.cantCreateGistTooltip,
+                  bitbucket: i18n.editorToolbar.cantCreateSnippetTooltip,
+                })}
+              </div>
+            }
+            trigger={!canCreateGistOrSnippet ? "mouseenter click" : ""}
+            position="left"
+          >
+            <DropdownItem
+              icon={switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
+                bitbucket: <BitbucketIcon />,
+                github: <GithubIcon />,
+              })}
+              data-testid={"create-gist-or-snippet-button"}
+              component="button"
+              onClick={() => setCreateGistOrSnippetModalOpen(true)}
+              isDisabled={!canCreateGistOrSnippet}
+            >
+              {switchExpression(authProvider?.type as GistEnabledAuthProviderType, {
+                github: i18n.editorToolbar.createGist,
+                bitbucket: i18n.editorToolbar.createSnippet,
+              })}
+            </DropdownItem>
+          </Tooltip>
+        )}
+      </DropdownGroup>
+    </>
+  );
+};
diff --git a/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx b/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx
new file mode 100644
index 0000000000..ca0452e58f
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/SyncDropdownMenu.tsx
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import {
+  WorkspaceKind,
+  WorkspaceKindGistLike,
+  isGistLikeWorkspaceKind,
+} from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import {
+  Dropdown,
+  DropdownGroup,
+  DropdownItem,
+  DropdownPosition,
+  DropdownToggle,
+} from "@patternfly/react-core/dist/js/components/Dropdown";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { switchExpression } from "../../switchExpression/switchExpression";
+import { useOnlineI18n } from "../../i18n";
+import BitbucketIcon from "@patternfly/react-icons/dist/js/icons/bitbucket-icon";
+import GithubIcon from "@patternfly/react-icons/dist/js/icons/github-icon";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
+import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
+import { AuthSessionSelect } from "../../authSessions/AuthSessionSelect";
+import { AuthProviderGroup, GitAuthProviderType } from "../../authProviders/AuthProvidersApi";
+import { AccountsDispatchActionKind, useAccountsDispatch } from "../../accounts/AccountsContext";
+import SyncAltIcon from "@patternfly/react-icons/dist/js/icons/sync-alt-icon";
+import { GIT_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
+import ArrowCircleUpIcon from "@patternfly/react-icons/dist/js/icons/arrow-circle-up-icon";
+import { useEditorToolbarContext, useEditorToolbarDispatchContext } from "./EditorToolbarContextProvider";
+import { useGitIntegration } from "./GitIntegration/GitIntegrationContextProvider";
+import { useAuthProvider } from "../../authProviders/AuthProvidersContext";
+import { useAuthSession } from "../../authSessions/AuthSessionsContext";
+
+type Props = {
+  workspace: ActiveWorkspace;
+};
+
+export function SyncDropdownMenu(props: Props) {
+  const { i18n } = useOnlineI18n();
+  const accountsDispatch = useAccountsDispatch();
+  const { authSession } = useAuthSession(props.workspace.descriptor.gitAuthSessionId);
+  const authProvider = useAuthProvider(authSession);
+  const { isSyncGistOrSnippetDropdownOpen, isSyncGitRepositoryDropdownOpen } = useEditorToolbarContext();
+
+  const { setSyncGistOrSnippetDropdownOpen, setSyncGitRepositoryDropdownOpen } = useEditorToolbarDispatchContext();
+
+  const {
+    auth: { changeGitAuthSessionId, authSessionSelectFilter },
+    git: { canPushToGitRepository, pushToGitRepository, pullFromGitRepository },
+    gistOrSnippet: { canUpdateGistOrSnippet, updateGistOrSnippet, canForkGitHubGist, forkGitHubGist },
+  } = useGitIntegration();
+
+  return (
+    <>
+      {isGistLikeWorkspaceKind(props.workspace.descriptor.origin.kind) && (
+        <Dropdown
+          onSelect={() => setSyncGistOrSnippetDropdownOpen(false)}
+          isOpen={isSyncGistOrSnippetDropdownOpen}
+          position={DropdownPosition.right}
+          toggle={
+            <DropdownToggle
+              id={"sync-dropdown"}
+              data-testid={"sync-dropdown"}
+              onToggle={(isOpen) => setSyncGistOrSnippetDropdownOpen(isOpen)}
+            >
+              Sync
+            </DropdownToggle>
+          }
+          dropdownItems={[
+            <DropdownGroup key={"sync-gist-or-snippet-dropdown-group"}>
+              <Tooltip
+                data-testid={"gist-or-snippet-it-tooltip"}
+                content={
+                  <div>
+                    {switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
+                      GITHUB_GIST: i18n.editorToolbar.cantUpdateGistTooltip,
+                      BITBUCKET_SNIPPET: i18n.editorToolbar.cantUpdateSnippetTooltip,
+                    })}
+                  </div>
+                }
+                trigger={!canUpdateGistOrSnippet ? "mouseenter click" : ""}
+                position="left"
+              >
+                <>
+                  <DropdownItem
+                    style={{ minWidth: "300px" }}
+                    icon={switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
+                      BITBUCKET_SNIPPET: <BitbucketIcon />,
+                      GITHUB_GIST: <GithubIcon />,
+                    })}
+                    onClick={updateGistOrSnippet}
+                    isDisabled={!canUpdateGistOrSnippet}
+                  >
+                    Update{" "}
+                    {switchExpression(props.workspace.descriptor.origin.kind as WorkspaceKindGistLike, {
+                      BITBUCKET_SNIPPET: "Bitbucket Snippet",
+                      GITHUB_GIST: "GitHub Gist",
+                    })}
+                  </DropdownItem>
+                  {canForkGitHubGist && (
+                    <>
+                      <Divider />
+                      <li role="menuitem">
+                        <Alert
+                          isInline={true}
+                          variant={"default"}
+                          title={<span style={{ whiteSpace: "nowrap" }}>{"Can't update Gists you don't own"}</span>}
+                        >
+                          <br />
+                          {`You can create a fork of '${props.workspace.descriptor.name}' to save your updates.`}
+                          <br />
+                          <br />
+                          <Button
+                            onClick={forkGitHubGist}
+                            variant={ButtonVariant.link}
+                            isSmall={true}
+                            style={{ paddingLeft: 0 }}
+                          >
+                            {`Fork Gist`}
+                          </Button>
+                          <br />
+                          <br />
+                          {`Or you can change the authentication source for '${props.workspace.descriptor.name}' to be able to Update Gist.`}
+                          <br />
+                          <br />
+                          <AuthSessionSelect
+                            title={`Select Git authentication for '${props.workspace.descriptor.name}'...`}
+                            isPlain={false}
+                            authSessionId={props.workspace.descriptor.gitAuthSessionId}
+                            showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+                            setAuthSessionId={(newAuthSessionId) => {
+                              changeGitAuthSessionId(newAuthSessionId, props.workspace.descriptor.gitAuthSessionId);
+                              accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+                              setTimeout(() => {
+                                setSyncGistOrSnippetDropdownOpen(true);
+                              }, 0);
+                            }}
+                            filter={authSessionSelectFilter}
+                          />
+                        </Alert>
+                      </li>
+                    </>
+                  )}
+                  {!canPushToGitRepository && (
+                    <>
+                      <Divider />
+                      <Alert
+                        isInline={true}
+                        variant={"default"}
+                        title={`Can't Update ${switchExpression(authProvider?.type as GitAuthProviderType, {
+                          github: "GitHub repository",
+                          bitbucket: "Bitbucket repository",
+                          default: "Git repository",
+                        })} without selecting a matching authentication source`}
+                        actionLinks={
+                          <AuthSessionSelect
+                            title={`Select Git authentication for '${props.workspace.descriptor.name}'...`}
+                            isPlain={false}
+                            authSessionId={props.workspace.descriptor.gitAuthSessionId}
+                            showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+                            setAuthSessionId={(newAuthSessionId) => {
+                              changeGitAuthSessionId(newAuthSessionId, props.workspace.descriptor.gitAuthSessionId);
+                              accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+                              setTimeout(() => {
+                                setSyncGistOrSnippetDropdownOpen(true);
+                              }, 0);
+                            }}
+                            filter={authSessionSelectFilter}
+                          />
+                        }
+                      >
+                        {`Select an authentication source for '${
+                          props.workspace.descriptor.name
+                        }' to be able to Update ${switchExpression(
+                          props.workspace.descriptor.origin.kind as WorkspaceKindGistLike,
+                          {
+                            GITHUB_GIST: "Github Gist",
+                            BITBUCKET_SNIPPET: "Bitbucket Snippet",
+                          }
+                        )}.`}
+                      </Alert>
+                    </>
+                  )}
+                </>
+              </Tooltip>
+            </DropdownGroup>,
+          ]}
+        />
+      )}
+      {props.workspace.descriptor.origin.kind === WorkspaceKind.GIT && (
+        <Dropdown
+          onSelect={() => setSyncGitRepositoryDropdownOpen(false)}
+          isOpen={isSyncGitRepositoryDropdownOpen}
+          position={DropdownPosition.right}
+          toggle={
+            <DropdownToggle
+              id={"sync-dropdown"}
+              data-testid={"sync-dropdown"}
+              onToggle={(isOpen) => setSyncGitRepositoryDropdownOpen(isOpen)}
+            >
+              Sync
+            </DropdownToggle>
+          }
+          dropdownItems={[
+            <DropdownGroup key={"sync-git-dropdown-group"}>
+              <DropdownItem
+                icon={<SyncAltIcon />}
+                onClick={() => pullFromGitRepository({ showAlerts: true })}
+                description={`Get new changes made upstream at '${GIT_ORIGIN_REMOTE_NAME}/${props.workspace.descriptor.origin.branch}'.`}
+              >
+                Pull
+              </DropdownItem>
+              <Tooltip
+                data-testid={"git-it-tooltip"}
+                content={<div>{`You need to select an authentication source to Push to this repository.`}</div>}
+                trigger={!canPushToGitRepository ? "mouseenter click" : ""}
+                position="left"
+              >
+                <>
+                  <DropdownItem
+                    icon={<ArrowCircleUpIcon />}
+                    onClick={pushToGitRepository}
+                    isDisabled={!canPushToGitRepository}
+                    description={`Send your changes upstream to '${GIT_ORIGIN_REMOTE_NAME}/${props.workspace.descriptor.origin.branch}'.`}
+                  >
+                    Push
+                  </DropdownItem>
+                  {!canPushToGitRepository && (
+                    <>
+                      <Alert
+                        isInline={true}
+                        variant={"default"}
+                        title={"Can't Push without selecting an authentication source"}
+                        actionLinks={
+                          <AuthSessionSelect
+                            title={`Select Git authentication for '${props.workspace.descriptor.name}'...`}
+                            isPlain={false}
+                            authSessionId={props.workspace.descriptor.gitAuthSessionId}
+                            showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+                            setAuthSessionId={(newAuthSessionId) => {
+                              changeGitAuthSessionId(newAuthSessionId, props.workspace.descriptor.gitAuthSessionId);
+                              accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+                              setTimeout(() => {
+                                setSyncGitRepositoryDropdownOpen(true);
+                              });
+                            }}
+                            filter={authSessionSelectFilter}
+                          />
+                        }
+                      >
+                        {`Select an authentication source for '${props.workspace.descriptor.name}' to be able to Push.`}
+                      </Alert>
+                    </>
+                  )}
+                </>
+              </Tooltip>
+            </DropdownGroup>,
+          ]}
+        />
+      )}
+    </>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/VsCodeDropdownMenu.tsx b/packages/online-editor/src/editor/Toolbar/VsCodeDropdownMenu.tsx
new file mode 100644
index 0000000000..4566beba98
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/VsCodeDropdownMenu.tsx
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useState } from "react";
+import {
+  Dropdown,
+  DropdownGroup,
+  DropdownItem,
+  DropdownToggle,
+} from "@patternfly/react-core/dist/js/components/Dropdown";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
+import CaretDownIcon from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
+import { Alert } from "@patternfly/react-core/dist/js/components/Alert";
+import { PushToGitAlertActionLinks } from "./GitIntegration/PushToGitAlertActionLinks";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import ExternalLinkAltIcon from "@patternfly/react-icons/dist/js/icons/external-link-alt-icon";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { useNavigationStatus, useRoutes } from "../../navigation/Hooks";
+import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { UrlType } from "../../importFromUrl/ImportableUrlHooks";
+import { GIT_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
+import { useGitIntegration } from "./GitIntegration/GitIntegrationContextProvider";
+
+export function VsCodeDropdownMenu(props: { workspace: ActiveWorkspace }) {
+  const routes = useRoutes();
+  const navigationStatus = useNavigationStatus();
+  const [isVsCodeDropdownOpen, setVsCodeDropdownOpen] = useState(false);
+
+  const {
+    workspaceImportableUrl,
+    auth: { changeGitAuthSessionId, authSessionSelectFilter },
+    git: { canPushToGitRepository, pushToGitRepository },
+  } = useGitIntegration();
+
+  if (
+    props.workspace.descriptor.origin.kind !== WorkspaceKind.GIT ||
+    workspaceImportableUrl.type !== UrlType.GITHUB_DOT_COM
+  ) {
+    return null;
+  }
+
+  return (
+    <FlexItem
+      style={{
+        minWidth: "137px",
+      }}
+    >
+      <Dropdown
+        className={"kie-tools--masthead-hoverable"}
+        isPlain={true}
+        onSelect={() => setVsCodeDropdownOpen(false)}
+        isOpen={isVsCodeDropdownOpen}
+        position={"right"}
+        toggle={
+          <DropdownToggle toggleIndicator={null} onToggle={setVsCodeDropdownOpen}>
+            <Flex flexWrap={{ default: "nowrap" }}>
+              <FlexItem
+                style={{
+                  minWidth: 0 /* This is to make the flex parent not overflow horizontally */,
+                }}
+              >
+                <Tooltip distance={5} position={"top-start"} content={props.workspace.descriptor.name}>
+                  <TextContent>
+                    <Text
+                      component={TextVariants.small}
+                      style={{
+                        whiteSpace: "nowrap",
+                        overflow: "hidden",
+                        textOverflow: "ellipsis",
+                      }}
+                    >
+                      <img
+                        style={{
+                          minWidth: "14px",
+                          maxWidth: "14px",
+                          marginTop: "-2px",
+                          verticalAlign: "middle",
+                        }}
+                        alt="vscode-logo-blue"
+                        src={routes.static.images.vscodeLogoBlue.path({})}
+                      />
+                      &nbsp;&nbsp;
+                      {`Open "${props.workspace.descriptor.name}"`}
+                    </Text>
+                  </TextContent>
+                </Tooltip>
+              </FlexItem>
+              <FlexItem>
+                <CaretDownIcon />
+              </FlexItem>
+            </Flex>
+          </DropdownToggle>
+        }
+        dropdownItems={[
+          <DropdownGroup key={"open-in-vscode"}>
+            {navigationStatus.shouldBlockNavigationTo({ pathname: "__external" }) && (
+              <>
+                <Alert
+                  isInline={true}
+                  variant={"warning"}
+                  title={"You have new changes to Push"}
+                  actionLinks={
+                    <PushToGitAlertActionLinks
+                      changeGitAuthSessionId={changeGitAuthSessionId}
+                      workspaceDescriptor={props.workspace.descriptor}
+                      canPush={canPushToGitRepository}
+                      authSessionSelectFilter={authSessionSelectFilter}
+                      remoteRef={`${GIT_ORIGIN_REMOTE_NAME}/${props.workspace.descriptor.origin.branch}`}
+                      onPush={pushToGitRepository}
+                    />
+                  }
+                >
+                  {`Opening '${props.workspace.descriptor.name}' on vscode.dev won't show your latest changes.`}
+                </Alert>
+                <Divider />
+              </>
+            )}
+            <DropdownItem
+              style={{ minWidth: "400px" }}
+              href={`https://vscode.dev/github${
+                new URL(props.workspace.descriptor.origin.url).pathname.endsWith(".git")
+                  ? new URL(props.workspace.descriptor.origin.url).pathname.replace(".git", "")
+                  : new URL(props.workspace.descriptor.origin.url).pathname
+              }/tree/${props.workspace.descriptor.origin.branch}`}
+              target={"_blank"}
+              icon={<ExternalLinkAltIcon />}
+              description={`The '${props.workspace.descriptor.origin.branch}' branch will be opened.`}
+            >
+              vscode.dev
+            </DropdownItem>
+            <Divider />
+            <DropdownItem
+              href={`vscode://vscode.git/clone?url=${props.workspace.descriptor.origin.url.toString()}`}
+              target={"_blank"}
+              icon={<ExternalLinkAltIcon />}
+              description={"The default branch will be opened."}
+            >
+              VS Code Desktop
+            </DropdownItem>
+          </DropdownGroup>,
+        ]}
+      />
+    </FlexItem>
+  );
+}
diff --git a/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx b/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx
new file mode 100644
index 0000000000..581774a8c4
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Workspace/Hooks.tsx
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useEffect } from "react";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { useNavigationBlockersBypass, useNavigationStatus, useNavigationStatusToggle } from "../../../navigation/Hooks";
+import { useGlobalAlert } from "../../../alerts";
+import { Alert, AlertActionCloseButton, AlertActionLink } from "@patternfly/react-core/dist/js/components/Alert";
+import {
+  WorkspaceKind,
+  WorkspaceKindGitBased,
+} from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
+import { useOnlineI18n } from "../../../i18n";
+import { Divider } from "@patternfly/react-core/dist/js/components/Divider";
+import { PushToGitAlertActionLinks } from "../GitIntegration/PushToGitAlertActionLinks";
+import { useGitIntegration } from "../GitIntegration/GitIntegrationContextProvider";
+import { switchExpression } from "../../../switchExpression/switchExpression";
+import { GIT_ORIGIN_REMOTE_NAME } from "@kie-tools-core/workspaces-git-fs/dist/constants/GitConstants";
+import { useHistory } from "react-router";
+import { useEditorToolbarContext } from "../EditorToolbarContextProvider";
+
+export function useWorkspaceNavigationBlocker(workspace: ActiveWorkspace) {
+  const { i18n } = useOnlineI18n();
+  const history = useHistory();
+
+  const {
+    auth: { changeGitAuthSessionId, authSessionSelectFilter },
+    git: { canPushToGitRepository, pushToGitRepository },
+    gistOrSnippet: { canUpdateGistOrSnippet, updateGistOrSnippet },
+  } = useGitIntegration();
+
+  const { downloadWorkspaceZip } = useEditorToolbarContext();
+
+  const navigationStatus = useNavigationStatus();
+  const navigationStatusToggle = useNavigationStatusToggle();
+  const navigationBlockersBypass = useNavigationBlockersBypass();
+
+  const confirmNavigationAlert = useGlobalAlert<{
+    lastBlockedLocation: Location;
+  }>(
+    useCallback(
+      (_, { lastBlockedLocation }) => (
+        <Alert
+          data-testid="unsaved-alert"
+          variant="warning"
+          title={
+            workspace.descriptor.origin.kind === WorkspaceKind.LOCAL
+              ? i18n.editorPage.alerts.unsaved.titleLocal
+              : i18n.editorPage.alerts.unsaved.titleGit
+          }
+          actionClose={
+            <AlertActionCloseButton data-testid="unsaved-alert-close-button" onClose={navigationStatusToggle.unblock} />
+          }
+          actionLinks={
+            <>
+              <Divider inset={{ default: "insetMd" }} />
+              <br />
+              {(workspace.descriptor.origin.kind === WorkspaceKind.LOCAL && (
+                <AlertActionLink
+                  data-testid="unsaved-alert-save-button"
+                  onClick={() => {
+                    navigationStatusToggle.unblock();
+                    return downloadWorkspaceZip();
+                  }}
+                  style={{ fontWeight: "bold" }}
+                >
+                  {`${i18n.terms.download} '${workspace.descriptor.name}'`}
+                </AlertActionLink>
+              )) || (
+                <PushToGitAlertActionLinks
+                  changeGitAuthSessionId={changeGitAuthSessionId}
+                  workspaceDescriptor={workspace.descriptor}
+                  canPush={switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGitBased, {
+                    BITBUCKET_SNIPPET: canUpdateGistOrSnippet,
+                    GITHUB_GIST: canUpdateGistOrSnippet,
+                    GIT: canPushToGitRepository,
+                  })}
+                  remoteRef={`${GIT_ORIGIN_REMOTE_NAME}/${workspace.descriptor.origin.branch}`}
+                  authSessionSelectFilter={authSessionSelectFilter}
+                  onPush={() => {
+                    navigationStatusToggle.unblock();
+                    switchExpression(workspace.descriptor.origin.kind as WorkspaceKindGitBased, {
+                      BITBUCKET_SNIPPET: updateGistOrSnippet,
+                      GITHUB_GIST: updateGistOrSnippet,
+                      GIT: pushToGitRepository,
+                    })();
+                  }}
+                />
+              )}
+              <br />
+              <br />
+              <AlertActionLink
+                data-testid="unsaved-alert-close-without-save-button"
+                onClick={() =>
+                  navigationBlockersBypass.execute(() => {
+                    history.push(lastBlockedLocation);
+                  })
+                }
+              >
+                {i18n.editorPage.alerts.unsaved.proceedAnyway}
+              </AlertActionLink>
+              <br />
+              <br />
+            </>
+          }
+        >
+          <br />
+          <p>{i18n.editorPage.alerts.unsaved.message}</p>
+        </Alert>
+      ),
+      [
+        workspace.descriptor,
+        i18n.editorPage.alerts.unsaved.titleLocal,
+        i18n.editorPage.alerts.unsaved.titleGit,
+        i18n.editorPage.alerts.unsaved.proceedAnyway,
+        i18n.editorPage.alerts.unsaved.message,
+        i18n.terms.download,
+        navigationStatusToggle,
+        changeGitAuthSessionId,
+        canUpdateGistOrSnippet,
+        canPushToGitRepository,
+        authSessionSelectFilter,
+        downloadWorkspaceZip,
+        updateGistOrSnippet,
+        pushToGitRepository,
+        navigationBlockersBypass,
+        history,
+      ]
+    )
+  );
+
+  useEffect(() => {
+    if (navigationStatus.lastBlockedLocation) {
+      confirmNavigationAlert.show({ lastBlockedLocation: navigationStatus.lastBlockedLocation });
+    } else {
+      confirmNavigationAlert.close();
+    }
+  }, [confirmNavigationAlert, navigationStatus]);
+
+  return;
+}
diff --git a/packages/online-editor/src/editor/Toolbar/Workspace/WorkspaceToolbar.tsx b/packages/online-editor/src/editor/Toolbar/Workspace/WorkspaceToolbar.tsx
new file mode 100644
index 0000000000..01dec5770b
--- /dev/null
+++ b/packages/online-editor/src/editor/Toolbar/Workspace/WorkspaceToolbar.tsx
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, { useCallback, useEffect, useRef } from "react";
+import { ActiveWorkspace } from "@kie-tools-core/workspaces-git-fs/dist/model/ActiveWorkspace";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
+import { useHistory } from "react-router";
+import { useRoutes } from "../../../navigation/Hooks";
+import AngleLeftIcon from "@patternfly/react-icons/dist/js/icons/angle-left-icon";
+import { AuthSessionSelect } from "../../../authSessions/AuthSessionSelect";
+import { AuthProviderGroup } from "../../../authProviders/AuthProvidersApi";
+import { useGitIntegration } from "../GitIntegration/GitIntegrationContextProvider";
+import { AccountsDispatchActionKind, useAccountsDispatch } from "../../../accounts/AccountsContext";
+import { WorkspaceLabel } from "../../../workspace/components/WorkspaceLabel";
+import FolderIcon from "@patternfly/react-icons/dist/js/icons/folder-icon";
+import { Title } from "@patternfly/react-core/dist/js/components/Title";
+import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput";
+import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { WorkspaceStatusIndicator } from "../../../workspace/components/WorkspaceStatusIndicator";
+import { AcceleratorIndicator } from "../Accelerators/AcceleratorIndicator";
+import { PromiseState } from "@kie-tools-core/react-hooks/dist/PromiseState";
+import { WorkspaceGitStatusType } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspaceHooks";
+
+type Props = {
+  workspace: ActiveWorkspace;
+  currentWorkspaceFile: WorkspaceFile;
+  workspaceGitStatusPromise: PromiseState<WorkspaceGitStatusType>;
+  onDeletedWorkspaceFile: () => void;
+};
+
+export function WorkspaceToolbar(props: Props) {
+  const history = useHistory();
+  const routes = useRoutes();
+  const workspaces = useWorkspaces();
+
+  const {
+    auth: { changeGitAuthSessionId, authSessionSelectFilter },
+  } = useGitIntegration();
+
+  const accountsDispatch = useAccountsDispatch();
+
+  const workspaceNameRef = useRef<HTMLInputElement>(null);
+
+  const resetWorkspaceName = useCallback(() => {
+    if (workspaceNameRef.current) {
+      workspaceNameRef.current.value = props.workspace.descriptor.name;
+    }
+  }, [props.workspace]);
+
+  useEffect(resetWorkspaceName, [resetWorkspaceName]);
+
+  const onRenameWorkspace = useCallback(
+    async (newName: string | undefined) => {
+      if (!newName) {
+        resetWorkspaceName();
+        return;
+      }
+
+      if (newName === props.workspace.descriptor.name) {
+        return;
+      }
+
+      await workspaces.renameWorkspace({
+        workspaceId: props.workspace.descriptor.workspaceId,
+        newName: newName.trim(),
+      });
+    },
+    [props.workspace.descriptor, workspaces, resetWorkspaceName]
+  );
+
+  const onWorkspaceNameKeyDown = useCallback(
+    (e: React.KeyboardEvent<HTMLInputElement>) => {
+      e.stopPropagation();
+      if (e.keyCode === 13 /* Enter */) {
+        e.currentTarget.blur();
+      } else if (e.keyCode === 27 /* ESC */) {
+        resetWorkspaceName();
+        e.currentTarget.blur();
+      }
+    },
+    [resetWorkspaceName]
+  );
+
+  return (
+    <Flex
+      justifyContent={{ default: "justifyContentFlexStart" }}
+      flexWrap={{ default: "nowrap" }}
+      spaceItems={{ default: "spaceItemsSm" }}
+      alignItems={{ default: "alignItemsCenter" }}
+    >
+      <FlexItem>
+        <Button
+          className={"kie-tools--masthead-hoverable"}
+          variant={ButtonVariant.plain}
+          onClick={() => history.push({ pathname: routes.home.path({}) })}
+        >
+          <AngleLeftIcon />
+        </Button>
+      </FlexItem>
+      <FlexItem>
+        <AuthSessionSelect
+          title={`Select Git authentication for '${props.workspace.descriptor.name}'...`}
+          isPlain={true}
+          authSessionId={props.workspace.descriptor.gitAuthSessionId}
+          showOnlyThisAuthProviderGroupWhenConnectingToNewAccount={AuthProviderGroup.GIT}
+          setAuthSessionId={(newAuthSessionId) => {
+            changeGitAuthSessionId(newAuthSessionId, props.workspace.descriptor.gitAuthSessionId);
+            accountsDispatch({ kind: AccountsDispatchActionKind.CLOSE });
+          }}
+          filter={authSessionSelectFilter}
+        />
+      </FlexItem>
+      <FlexItem>
+        <WorkspaceLabel descriptor={props.workspace.descriptor} />
+      </FlexItem>
+      <FlexItem>
+        <AcceleratorIndicator workspaceId={props.workspace.descriptor.workspaceId} />
+      </FlexItem>
+      <FlexItem
+        style={{ minWidth: 0, padding: "0 8px 0 8px", flexShrink: 0 }}
+        className={"kie-tools--masthead-hoverable"}
+      >
+        <FolderIcon style={{ marginRight: "8px", verticalAlign: "middle" }} />
+        <div
+          data-testid={"toolbar-title-workspace"}
+          className={"kogito--editor__toolbar-name-container"}
+          style={{ display: "inline-block", verticalAlign: "middle" }}
+        >
+          <Title
+            aria-label={"EmbeddedEditorFile name"}
+            headingLevel={"h3"}
+            size={"md"}
+            style={{
+              fontStyle: "italic",
+            }}
+          >
+            {props.workspace.descriptor.name}
+          </Title>
+          <TextInput
+            ref={workspaceNameRef}
+            type={"text"}
+            aria-label={"Edit workspace name"}
+            onKeyDown={onWorkspaceNameKeyDown}
+            className={"kogito--editor__toolbar-subtitle"}
+            onBlur={(e) => onRenameWorkspace(e.target.value)}
+            style={{ fontStyle: "italic", top: "4px", height: "calc(100% - 8px)" }}
+          />
+        </div>
+      </FlexItem>
+      <FlexItem>
+        <WorkspaceStatusIndicator
+          gitStatusProps={{
+            workspaceDescriptor: props.workspace.descriptor,
+            workspaceGitStatusPromise: props.workspaceGitStatusPromise,
+          }}
+          currentWorkspaceFile={props.currentWorkspaceFile}
+          onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+          workspaceFiles={props.workspace.files}
+        />
+      </FlexItem>
+    </Flex>
+  );
+}
diff --git a/packages/online-editor/src/env/EnvJson.ts b/packages/online-editor/src/env/EnvJson.ts
index 2b92854ec7..4df37326a9 100644
--- a/packages/online-editor/src/env/EnvJson.ts
+++ b/packages/online-editor/src/env/EnvJson.ts
@@ -15,6 +15,7 @@
  */
 
 import { AuthProvider } from "../authProviders/AuthProvidersApi";
+import { AcceleratorConfig } from "../accelerators/AcceleratorsApi";
 
 export interface EnvJson {
   KIE_SANDBOX_EXTENDED_SERVICES_URL: string;
@@ -22,4 +23,5 @@ export interface EnvJson {
   KIE_SANDBOX_REQUIRE_CUSTOM_COMMIT_MESSAGE: boolean;
   KIE_SANDBOX_CUSTOM_COMMIT_MESSAGE_VALIDATION_SERVICE_URL: string;
   KIE_SANDBOX_AUTH_PROVIDERS: AuthProvider[];
+  KIE_SANDBOX_ACCELERATORS: AcceleratorConfig[];
 }
diff --git a/packages/online-editor/src/envelopeLocator/EditorEnvelopeLocatorFactory.ts b/packages/online-editor/src/envelopeLocator/EditorEnvelopeLocatorFactory.ts
index 91c8332fca..d278130ad8 100644
--- a/packages/online-editor/src/envelopeLocator/EditorEnvelopeLocatorFactory.ts
+++ b/packages/online-editor/src/envelopeLocator/EditorEnvelopeLocatorFactory.ts
@@ -20,24 +20,82 @@ import {
   EnvelopeMapping,
 } from "@kie-tools-core/editor/dist/api/EditorEnvelopeLocator";
 
+const REGEX = {
+  supported: /(\.bpmn|\.bpmn2|\.dmn|\.pmml|\.scesim)$/i,
+  dmn: /^.*\.dmn$/i,
+  bpmn: /^.*\.(bpmn|bpmn2)$/i,
+  scesim: /^.*\.scesim$/i,
+  pmml: /^.*\.pmml$/i,
+};
+
+export const GLOB_PATTERN = {
+  all: "**/*",
+  dmn: "**/*.dmn",
+  bpmn: "**/*.bpmn?(2)",
+  scesim: "**/*.scesim",
+  pmml: "**/*.pmml",
+};
+
+export enum FileTypes {
+  DMN = "dmn",
+  BPMN = "bpmn",
+  BPMN2 = "bpmn2",
+  SCESIM = "scesim",
+  PMML = "pmml",
+}
+
+export const supportedFileExtensionArray = [
+  FileTypes.DMN,
+  FileTypes.BPMN,
+  FileTypes.BPMN2,
+  FileTypes.SCESIM,
+  FileTypes.PMML,
+];
+
+export type SupportedFileExtensions = typeof supportedFileExtensionArray[number];
+
+export function isDecision(path: string): boolean {
+  return REGEX.dmn.test(path);
+}
+
+export function isWorkflow(path: string): boolean {
+  return REGEX.bpmn.test(path);
+}
+
+export function isTestScenario(path: string): boolean {
+  return REGEX.scesim.test(path);
+}
+
+export function isScorecard(path: string): boolean {
+  return REGEX.pmml.test(path);
+}
+
+export function isModel(path: string): boolean {
+  return isDecision(path) || isWorkflow(path) || isScorecard(path);
+}
+
+export function isEditable(path: string): boolean {
+  return isModel(path) || isTestScenario(path);
+}
+
 export class EditorEnvelopeLocatorFactory {
   public create(args: { targetOrigin: string }) {
     return new EditorEnvelopeLocator(args.targetOrigin, [
       new EnvelopeMapping({
-        type: "bpmn",
-        filePathGlob: "**/*.bpmn?(2)",
+        type: FileTypes.BPMN,
+        filePathGlob: GLOB_PATTERN.bpmn,
         resourcesPathPrefix: "gwt-editors/bpmn",
         envelopeContent: { type: EnvelopeContentType.PATH, path: "bpmn-envelope.html" },
       }),
       new EnvelopeMapping({
-        type: "dmn",
-        filePathGlob: "**/*.dmn",
+        type: FileTypes.DMN,
+        filePathGlob: GLOB_PATTERN.dmn,
         resourcesPathPrefix: "gwt-editors/dmn",
         envelopeContent: { type: EnvelopeContentType.PATH, path: "dmn-envelope.html" },
       }),
       new EnvelopeMapping({
-        type: "pmml",
-        filePathGlob: "**/*.pmml",
+        type: FileTypes.PMML,
+        filePathGlob: GLOB_PATTERN.pmml,
         resourcesPathPrefix: "",
         envelopeContent: { type: EnvelopeContentType.PATH, path: "pmml-envelope.html" },
       }),
diff --git a/packages/online-editor/src/filesList/FileDataList.tsx b/packages/online-editor/src/filesList/FileDataList.tsx
index e1b4152f94..e5fd724a91 100644
--- a/packages/online-editor/src/filesList/FileDataList.tsx
+++ b/packages/online-editor/src/filesList/FileDataList.tsx
@@ -32,6 +32,10 @@ import { useRoutes } from "../navigation/Hooks";
 import { TaskIcon } from "@patternfly/react-icons/dist/js/icons/task-icon";
 import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
 import { WorkspaceDescriptorDates } from "../workspace/components/WorkspaceDescriptorDates";
+import { EyeIcon } from "@patternfly/react-icons/dist/js/icons/eye-icon";
+import { GitStatusIndicator } from "../workspace/components/WorkspaceStatusIndicator";
+import { GitStatusIndicatorActions, GitStatusProps } from "../workspace/components/GitStatusIndicatorActions";
+import { switchExpression } from "../switchExpression/switchExpression";
 
 const FILE_DATA_LIST_HEIGHTS = {
   atRoot: 55 + 24,
@@ -42,31 +46,73 @@ export function getFileDataListHeight(file: WorkspaceFile) {
   return file.relativePath.indexOf("/") >= 0 ? FILE_DATA_LIST_HEIGHTS.atSubDir : FILE_DATA_LIST_HEIGHTS.atRoot;
 }
 
-export function FileListItem(props: { file: WorkspaceFile; isEditable: boolean }) {
+export enum FileListItemDisplayMode {
+  enabled = "enabled",
+  readonly = "readonly",
+  deleted = "deleted",
+}
+
+export function FileListItem(props: {
+  file: WorkspaceFile;
+  displayMode: FileListItemDisplayMode;
+  isCurrentWorkspaceFile?: boolean;
+  onDeletedWorkspaceFile?: () => void;
+  gitStatusProps?: GitStatusProps;
+}) {
+  const [keepGitStatusActionsDisplayed, setKeepGitStatusActionsDisplayed] = React.useState(false);
   const fileDirPath = props.file.relativeDirPath.split("/").join(" > ");
-  const fileName = props.isEditable ? props.file.nameWithoutExtension : props.file.name;
+  const fileName = [FileListItemDisplayMode.enabled, FileListItemDisplayMode.deleted].includes(props.displayMode)
+    ? props.file.nameWithoutExtension
+    : props.file.name;
   return (
     <>
-      <Flex flexWrap={{ default: "nowrap" }}>
+      <Flex
+        flexWrap={{ default: "nowrap" }}
+        onClick={(e) => {
+          if (props.displayMode !== FileListItemDisplayMode.enabled) {
+            // this prevents the FileSwitcher from closing on click.
+            e.stopPropagation();
+            e.preventDefault();
+          }
+        }}
+      >
+        {props.isCurrentWorkspaceFile && (
+          <FlexItem align={{ default: "alignLeft" }}>
+            <EyeIcon title="Currently selected file." />
+          </FlexItem>
+        )}
         <FlexItem style={{ minWidth: 0 /* This is to make the flex parent not overflow horizontally */ }}>
-          <Tooltip distance={5} position={"top-start"} content={fileName}>
+          <Tooltip
+            distance={5}
+            position={"top-start"}
+            content={fileName + (props.displayMode === FileListItemDisplayMode.deleted ? " (Deleted)" : "")}
+          >
             <TextContent>
-              <Text
-                component={TextVariants.p}
-                style={{
-                  whiteSpace: "nowrap",
-                  overflow: "hidden",
-                  textOverflow: "ellipsis",
-                }}
-              >
-                {fileName}
-              </Text>
+              <Text component={TextVariants.p}>{fileName}</Text>
             </TextContent>
           </Tooltip>
         </FlexItem>
         <FlexItem>
           <FileLabel extension={props.file.extension} />
         </FlexItem>
+        {props.gitStatusProps && (
+          <FlexItem align={{ default: "alignRight" }}>
+            <GitStatusIndicator
+              gitStatusProps={props.gitStatusProps}
+              workspaceFile={props.file}
+              isHoverable={!keepGitStatusActionsDisplayed}
+            >
+              <GitStatusIndicatorActions
+                gitStatusProps={props.gitStatusProps}
+                workspaceFile={props.file}
+                currentWorkspaceFile={props.isCurrentWorkspaceFile ? props.file : undefined}
+                onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+                isOpen={keepGitStatusActionsDisplayed}
+                setOpen={setKeepGitStatusActionsDisplayed}
+              />
+            </GitStatusIndicator>
+          </FlexItem>
+        )}
       </Flex>
       <TextContent>
         <Text
@@ -86,13 +132,25 @@ export function FileListItem(props: { file: WorkspaceFile; isEditable: boolean }
   );
 }
 
-export function FileDataListItem(props: { file: WorkspaceFile; isEditable: boolean }) {
+export function FileDataListItem(props: {
+  file: WorkspaceFile;
+  displayMode: FileListItemDisplayMode;
+  isCurrentWorkspaceFile?: boolean;
+  onDeletedWorkspaceFile?: () => void;
+  gitStatusProps?: GitStatusProps;
+}) {
   return (
-    <DataListItemRow>
+    <DataListItemRow disabled={props.displayMode !== FileListItemDisplayMode.enabled}>
       <DataListItemCells
         dataListCells={[
-          <DataListCell key="link" isFilled={false}>
-            <FileListItem file={props.file} isEditable={props.isEditable} />
+          <DataListCell key="link" isFilled={true} autoFocus={props.isCurrentWorkspaceFile}>
+            <FileListItem
+              gitStatusProps={props.gitStatusProps}
+              file={props.file}
+              displayMode={props.displayMode}
+              isCurrentWorkspaceFile={props.isCurrentWorkspaceFile}
+              onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+            />
           </DataListCell>,
         ]}
       />
@@ -100,16 +158,37 @@ export function FileDataListItem(props: { file: WorkspaceFile; isEditable: boole
   );
 }
 
-export function FileDataList(props: { file: WorkspaceFile; isEditable: boolean; style?: React.CSSProperties }) {
+export function FileDataList(props: {
+  file: WorkspaceFile;
+  displayMode: FileListItemDisplayMode;
+  style?: React.CSSProperties;
+  isCurrentWorkspaceFile?: boolean;
+  onDeletedWorkspaceFile?: () => void;
+  gitStatusProps?: GitStatusProps;
+}) {
+  const fileDataListItem = (
+    <FileDataListItem
+      gitStatusProps={props.gitStatusProps}
+      key={props.file.relativePath}
+      file={props.file}
+      displayMode={props.displayMode}
+      isCurrentWorkspaceFile={props.isCurrentWorkspaceFile}
+      onDeletedWorkspaceFile={props.onDeletedWorkspaceFile}
+    />
+  );
   return (
-    <DataList aria-label="file-data-list" style={props.style}>
+    <DataList
+      aria-label="file-data-list"
+      style={props.style}
+      className={switchExpression(props.displayMode, {
+        enabled: "kie-tools--file-list-item-enabled",
+        deleted: "kie-tools--file-list-item-deleted",
+        readonly: "kie-tools--file-list-item-readonly",
+      })}
+    >
       <DataListItem style={{ border: 0 }}>
-        {(!props.isEditable && (
-          <FileDataListItem key={props.file.relativePath} file={props.file} isEditable={props.isEditable} />
-        )) || (
-          <FileLink file={props.file}>
-            <FileDataListItem file={props.file} isEditable={props.isEditable} />
-          </FileLink>
+        {(props.displayMode !== FileListItemDisplayMode.enabled && fileDataListItem) || (
+          <FileLink file={props.file}>{fileDataListItem}</FileLink>
         )}
       </DataListItem>
     </DataList>
@@ -133,9 +212,13 @@ export function FileLink(props: React.PropsWithChildren<{ file: WorkspaceFile; s
   );
 }
 
-export function SingleFileWorkspaceDataList(props: { workspaceDescriptor: WorkspaceDescriptor; file: WorkspaceFile }) {
+export function SingleFileWorkspaceDataList(props: {
+  workspaceDescriptor: WorkspaceDescriptor;
+  file: WorkspaceFile;
+  style?: React.CSSProperties;
+}) {
   return (
-    <DataList aria-label="file-data-list">
+    <DataList aria-label="file-data-list" style={props.style}>
       <DataListItem style={{ border: 0 }}>
         <FileLink file={props.file}>
           <DataListItemRow>
diff --git a/packages/online-editor/src/home/HomePage.tsx b/packages/online-editor/src/home/HomePage.tsx
index c10e8f328e..3e6a07446d 100644
--- a/packages/online-editor/src/home/HomePage.tsx
+++ b/packages/online-editor/src/home/HomePage.tsx
@@ -69,19 +69,26 @@ import { UploadCard } from "./UploadCard";
 import { ImportFromUrlCard } from "../importFromUrl/ImportFromUrlHomePageCard";
 import { WorkspaceKind } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceOrigin";
 import { PlusIcon } from "@patternfly/react-icons/dist/js/icons/plus-icon";
-import { NewFileDropdownMenu } from "../editor/NewFileDropdownMenu";
+import { NewFileDropdownMenu } from "../editor/Toolbar/NewFileDropdownMenu";
 import { Spinner } from "@patternfly/react-core/dist/js/components/Spinner";
 import { useRoutes } from "../navigation/Hooks";
 import { ErrorBoundary } from "../reactExt/ErrorBoundary";
 import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
 import { VariableSizeList } from "react-window";
 import AutoSizer from "react-virtualized-auto-sizer";
-import { FileDataList, FileLink, getFileDataListHeight, SingleFileWorkspaceListItem } from "../filesList/FileDataList";
+import {
+  FileDataList,
+  FileLink,
+  FileListItemDisplayMode,
+  getFileDataListHeight,
+  SingleFileWorkspaceListItem,
+} from "../filesList/FileDataList";
 import { WorkspaceListItem } from "../workspace/components/WorkspaceListItem";
 import { WorkspaceLoadingCard } from "../workspace/components/WorkspaceLoadingCard";
 import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
 import { ResponsiveDropdown } from "../ResponsiveDropdown/ResponsiveDropdown";
 import { ResponsiveDropdownToggle } from "../ResponsiveDropdown/ResponsiveDropdownToggle";
+import { listDeletedFiles } from "../workspace/components/WorkspaceStatusIndicator";
 
 export function HomePage() {
   const routes = useRoutes();
@@ -117,10 +124,6 @@ export function HomePage() {
     document.title = "KIE Sandbox :: Home";
   }, []);
 
-  const buildInfo = useMemo(() => {
-    return process.env["WEBPACK_REPLACE__buildInfo"];
-  }, []);
-
   return (
     <OnlineEditorPage>
       <PageSection
@@ -243,11 +246,6 @@ export function HomePage() {
           }}
         />
       </PageSection>
-      {buildInfo && (
-        <div className={"kie-tools--build-info"}>
-          <Label>{buildInfo}</Label>
-        </div>
-      )}
     </OnlineEditorPage>
   );
 }
@@ -569,7 +567,9 @@ export function WorkspacesListDrawerPanelContent(props: { workspaceId: string |
                   {({ index, style }) => (
                     <FileDataList
                       file={arrayWithModelsThenOtherFiles[index]}
-                      isEditable={index < models.length}
+                      displayMode={
+                        index < models.length ? FileListItemDisplayMode.enabled : FileListItemDisplayMode.readonly
+                      }
                       style={style}
                     />
                   )}
diff --git a/packages/online-editor/src/i18n/OnlineI18n.ts b/packages/online-editor/src/i18n/OnlineI18n.ts
index 8a4bbc2ef3..a6eec372c0 100644
--- a/packages/online-editor/src/i18n/OnlineI18n.ts
+++ b/packages/online-editor/src/i18n/OnlineI18n.ts
@@ -18,6 +18,7 @@ import { ReferenceDictionary, Wrapped } from "@kie-tools-core/i18n/dist/core";
 import { CommonI18n } from "@kie-tools/i18n-common-dictionary";
 import { DmnUnitablesI18n } from "@kie-tools/unitables-dmn/dist/i18n";
 import { GistEnabledAuthProviderType, SupportedGitAuthProviders } from "../authProviders/AuthProvidersApi";
+import { SupportedActions } from "../workspace/components/GitStatusIndicatorActions";
 
 interface OnlineDictionary extends ReferenceDictionary {
   editorPage: {
@@ -64,6 +65,25 @@ interface OnlineDictionary extends ReferenceDictionary {
     share: string;
     embed: string;
   };
+  accelerators: {
+    commitMessage: (acceleratorName: string) => string;
+    loadingAlert: (acceleratorName: string) => string;
+    successAlert: (acceleratorName: string) => string;
+    failAlert: (acceleratorName: string) => string;
+    acceleratorDescription: string;
+    acceleratorDetails: string;
+    dmnFilesMove: string;
+    dmnFilesLocation: string;
+    pmmlFilesMove: string;
+    pmmlFilesLocation: string;
+    bpmnFilesMove: string;
+    bpmnFilesLocation: string;
+    otherFilesMove: string;
+    otherFilesLocation: string;
+    applyAccelerator: string;
+    appliedAt: string;
+    applyDisclaimer: string;
+  };
   devDeployments: {
     common: {
       deployYourModel: string;
@@ -516,6 +536,14 @@ interface OnlineDictionary extends ReferenceDictionary {
       organizations: string;
     };
   };
+  gitStatusIndicatorActions: {
+    [key in SupportedActions]: {
+      title: string;
+      warning: string;
+      description: string;
+      confirmButtonText: string;
+    };
+  };
 }
 
 export interface OnlineI18n extends OnlineDictionary, CommonI18n {}
diff --git a/packages/online-editor/src/i18n/locales/en.ts b/packages/online-editor/src/i18n/locales/en.ts
index 3df8360971..a20ad37aa4 100644
--- a/packages/online-editor/src/i18n/locales/en.ts
+++ b/packages/online-editor/src/i18n/locales/en.ts
@@ -18,7 +18,6 @@ import { OnlineI18n } from "..";
 import { en as en_common } from "@kie-tools/i18n-common-dictionary";
 import { en as en_unitables } from "@kie-tools/unitables/dist/i18n/locales/en";
 import { wrapped } from "@kie-tools-core/i18n/dist/core";
-import { names } from "@kie-tools/i18n-common-dictionary/dist/names";
 
 export const en: OnlineI18n = {
   ...en_common,
@@ -66,6 +65,28 @@ export const en: OnlineI18n = {
     share: "Share",
     embed: "Embed",
   },
+  accelerators: {
+    commitMessage: (acceleratorName: string) =>
+      `${en_common.names.businessModeler.online}: Applying ${acceleratorName} Accelerator`,
+    loadingAlert: (acceleratorName: string) => `Applying ${acceleratorName} Accelerator...`,
+    successAlert: (acceleratorName: string) => `Successfully applied ${acceleratorName} Accelerator`,
+    failAlert: (acceleratorName: string) => `Failed to apply ${acceleratorName} Accelerator`,
+    acceleratorDescription:
+      "An Accelerator is a template. Applying it will move your current files according to the Accelerator specifications and create a new commit for it.",
+    acceleratorDetails: "This Accelerator is hosted at",
+    dmnFilesMove: "Decisions (.dmn) will be moved to:",
+    dmnFilesLocation: "Decisions (.dmn) were moved to:",
+    pmmlFilesMove: "Score cards (.pmml) will moved to:",
+    pmmlFilesLocation: "Score cards (.pmml) were moved to:",
+    bpmnFilesMove: "Workflows (.bpmn, .bpmn2) will be moved to:",
+    bpmnFilesLocation: "Workflows (.bpmn, .bpmn2) were moved to:",
+    otherFilesMove: "Other files will be moved to:",
+    otherFilesLocation: "Other files were moved to:",
+    applyAccelerator: "Apply Accelerator",
+    appliedAt: "This Accelerator was applied at:",
+    applyDisclaimer:
+      "This action is permanent. Any changes made after applying an Accelerator may result in your files being in different directories.",
+  },
   devDeployments: {
     common: {
       deployYourModel: "Deploy",
@@ -626,4 +647,18 @@ export const en: OnlineI18n = {
       organizations: "GitHub organizations",
     },
   },
+  gitStatusIndicatorActions: {
+    revert: {
+      title: "Revert",
+      warning: "This action is permanent",
+      description: "Are you sure you want to revert local changes to:",
+      confirmButtonText: "Yes, revert permanently",
+    },
+    revertAll: {
+      title: "Revert all changes",
+      warning: "This action is permanent",
+      description: "Are you sure? The following files will be reverted to the last commit:",
+      confirmButtonText: "Yes, revert permanently",
+    },
+  },
 };
diff --git a/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx b/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
index 28d42795c1..18fa3e4016 100644
--- a/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
+++ b/packages/online-editor/src/importFromUrl/ImportFromUrlHomePageCard.tsx
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-import { FlexItem } from "@patternfly/react-core";
 import { Button, ButtonVariant } from "@patternfly/react-core/dist/js/components/Button";
 import { Card, CardBody, CardFooter, CardTitle } from "@patternfly/react-core/dist/js/components/Card";
 import { Form, FormGroup } from "@patternfly/react-core/dist/js/components/Form";
 import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
 import { TextInput } from "@patternfly/react-core/dist/js/components/TextInput";
 import { ValidatedOptions } from "@patternfly/react-core/dist/js/helpers/constants";
-import { Flex } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
 import { CodeIcon } from "@patternfly/react-icons/dist/js/icons/code-icon";
 import { ExclamationCircleIcon } from "@patternfly/react-icons/dist/js/icons/exclamation-circle-icon";
 import * as React from "react";
diff --git a/packages/online-editor/src/pageTemplate/OnlineEditorPage.tsx b/packages/online-editor/src/pageTemplate/OnlineEditorPage.tsx
index 3c6f5d2753..1a98f1afa4 100644
--- a/packages/online-editor/src/pageTemplate/OnlineEditorPage.tsx
+++ b/packages/online-editor/src/pageTemplate/OnlineEditorPage.tsx
@@ -27,7 +27,8 @@ import { DevDeploymentsDropdown } from "../devDeployments/DevDeploymentsDropdown
 import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
 import { AccountsIcon } from "../accounts/AccountsIcon";
 import { AboutButton } from "../aboutModal/AboutButton";
-import { MastheadContent, Toolbar, ToolbarContent } from "@patternfly/react-core";
+import { MastheadContent } from "@patternfly/react-core/dist/js/components/Masthead";
+import { Toolbar, ToolbarContent } from "@patternfly/react-core/dist/js/components/Toolbar";
 import { ToolbarGroup, ToolbarItem } from "@patternfly/react-core/dist/js/components/Toolbar";
 
 export function OnlineEditorPage(props: { children?: React.ReactNode }) {
diff --git a/packages/online-editor/src/workspace/components/GitStatusIndicatorActions.tsx b/packages/online-editor/src/workspace/components/GitStatusIndicatorActions.tsx
new file mode 100644
index 0000000000..818ea1ee7d
--- /dev/null
+++ b/packages/online-editor/src/workspace/components/GitStatusIndicatorActions.tsx
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2023 Red Hat, Inc. and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { PromiseState } from "@kie-tools-core/react-hooks/dist/PromiseState";
+import { useWorkspaces, WorkspaceFile } from "@kie-tools-core/workspaces-git-fs/dist/context/WorkspacesContext";
+import { WorkspaceGitStatusType } from "@kie-tools-core/workspaces-git-fs/dist/hooks/WorkspaceHooks";
+import {
+  FileModificationStatus,
+  UnstagedModifiedFilesStatusEntryType,
+} from "@kie-tools-core/workspaces-git-fs/dist/services/GitService";
+import { WorkspaceDescriptor } from "@kie-tools-core/workspaces-git-fs/dist/worker/api/WorkspaceDescriptor";
+
+import {
+  Alert,
+  AlertActionCloseButton,
+  AlertActionLink,
+  AlertVariant,
+} from "@patternfly/react-core/dist/js/components/Alert";
+import {
+  Dropdown,
+  DropdownItem,
+  DropdownPosition,
+  KebabToggle,
+} from "@patternfly/react-core/dist/js/components/Dropdown";
+import { Button } from "@patternfly/react-core/dist/js/components/Button";
+import { Flex, FlexItem } from "@patternfly/react-core/dist/js/layouts/Flex";
+import { Popover, PopoverPosition } from "@patternfly/react-core/dist/js/components/Popover";
+import { List, ListItem } from "@patternfly/react-core/dist/js/components/List";
+import { UndoAltIcon } from "@patternfly/react-icons/dist/js/icons/undo-alt-icon";
+import * as React from "react";
+import { useOnlineI18n } from "../../i18n";
+import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text";
+import { Tooltip } from "@patternfly/react-core/dist/js/components/Tooltip";
+import { listDeletedFiles } from "./WorkspaceStatusIndicator";
+import { FileLabel } from "../../filesList/FileLabel";
+import CaretDownIcon from "@patternfly/react-icons/dist/js/icons/caret-down-icon";
+import { switchExpression } from "../../switchExpression/switchExpression";
+
+export type GitStatusProps = {
+  workspaceDescriptor: WorkspaceDescriptor;
+  workspaceGitStatusPromise: PromiseState<WorkspaceGitStatusType>;
+};
+
+export enum SupportedActions {
+  revert = "revert",
+  revertAll = "revertAll",
+}
+
+type GitStatusIndicatorActionType = {
+  id: SupportedActions;
+  titleText: string;
+  warningText: string;
+  titleIcon: JSX.Element;
+  description: JSX.Element;
+  alertVariant: AlertVariant;
+  confirmButtonText: string;
+  onConfirm: () => void;
+};
+interface GitStatusIndicatorActionsPropsBase {
+  gitStatusProps: GitStatusProps;
+  isOpen: boolean;
+  setOpen: (isOpen: boolean) => void;
+  currentWorkspaceFile?: WorkspaceFile;
+  onDeletedWorkspaceFile?: () => void;
+}
+
+interface GitStatusIndicatorActionsSingleFileProps extends GitStatusIndicatorActionsPropsBase {
+  workspaceFile: WorkspaceFile;
+}
+interface GitStatusIndicatorActionsMultipleFilesProps extends GitStatusIndicatorActionsPropsBase {
+  workspaceFiles: WorkspaceFile[];
+}
+const isSingleFile = (
+  maybeSingleFile: GitStatusIndicatorActionsSingleFileProps | GitStatusIndicatorActionsMultipleFilesProps
+): maybeSingleFile is GitStatusIndicatorActionsSingleFileProps => {
+  return "workspaceFile" in maybeSingleFile;
+};
+
+export const GitStatusIndicatorActions = (
+  props: GitStatusIndicatorActionsSingleFileProps | GitStatusIndicatorActionsMultipleFilesProps
+) => {
+  const { i18n } = useOnlineI18n();
+  const workspaces = useWorkspaces();
+
+  const renderFile = React.useCallback(
+    (file: WorkspaceFile) => (
+      <Flex direction={{ default: "row" }} flexWrap={{ default: "nowrap" }} spacer={{ default: "spacerMd" }}>
+        <FlexItem style={{ minWidth: 0 /* This is to make the flex parent not overflow horizontally */ }}>
+          <Tooltip distance={5} position={"top-start"} content={file.nameWithoutExtension}>
+            <TextContent>
+              <Text component={TextVariants.p}>{file.nameWithoutExtension}</Text>
+            </TextContent>
+          </Tooltip>
+        </FlexItem>
+        <FlexItem>
+          <FileLabel extension={file.extension} />
+        </FlexItem>
+        <FlexItem>
+          {switchExpression(
+            props.gitStatusProps.workspaceGitStatusPromise.data?.unstagedModifiedFilesStatus.find(
+              (entry) => entry.path === file.relativePath
+            )?.status,
+            {
+              added: (
+                <Tooltip content={"Added"} position={"right"}>
+                  <small>
+                    <i>A</i>
+                  </small>
+                </Tooltip>
+              ),
+              deleted: (
+                <Tooltip content={"Deleted"} position={"right"}>
+                  <small>
+                    <i>D</i>
+                  </small>
+                </Tooltip>
+              ),
+              modified: (
+                <Tooltip content={"Modified"} position={"right"}>
+                  <small>
+                    <i>M</i>
+                  </small>
+                </Tooltip>
+              ),
+              default: <></>,
+            }
+          )}
+        </FlexItem>
+      </Flex>
+    ),
+    [props.gitStatusProps.workspaceGitStatusPromise.data?.unstagedModifiedFilesStatus]
+  );
+
+  const workspaceFilesRendered = React.useMemo(() => {
+    return isSingleFile(props) ? (
+      <b>{renderFile(props.workspaceFile)}</b>
+    ) : (
+      <b>
+        <List>
+          {[...props.workspaceFiles, ...listDeletedFiles(props.gitStatusProps)]
+            .filter((file) =>
+              props.gitStatusProps.workspaceGitStatusPromise.data?.unstagedModifiedFilesStatus.some(
+                (entry) => entry.path === file.relativePath
+              )
+            )
+            .map((file, index) => (
+              <ListItem key={index}>{renderFile(file)}</ListItem>
+            ))}
+        </List>
+      </b>
+    );
+  }, [props, renderFile]);
+
+  const filterAcceptedStageStatuses = React.useCallback(
+    (acceptedValues: FileModificationStatus[]) => {
+      return (stageStatusEntry: UnstagedModifiedFilesStatusEntryType) => {
+        return (
+          acceptedValues.includes(stageStatusEntry.status) &&
+          (isSingleFile(props)
+            ? [props.workspaceFile.relativePath]
+            : props.gitStatusProps.workspaceGitStatusPromise!.data!.unstagedModifiedFilesStatus.map(({ path }) => path)
+          ).includes(stageStatusEntry.path)
+        );
+      };
+    },
+    [props]
+  );
+
+  const actionRevert = React.useCallback((): GitStatusIndicatorActionType | undefined => {
+    const doRevert = async (filepaths: string[]) => {
+      await workspaces.checkoutFilesFromLocalHead({
+        workspaceId: props.gitStatusProps.workspaceDescriptor.workspaceId,
+        ref: props.gitStatusProps.workspaceDescriptor.origin.branch,
+        filepaths,
+      });
+      if (
+        props.currentWorkspaceFile &&
+        !(await workspaces.existsFile({
+          workspaceId: props.gitStatusProps.workspaceDescriptor.workspaceId,
+          relativePath: props.currentWorkspaceFile.relativePath,
+        }))
+      ) {
+        props.onDeletedWorkspaceFile?.();
+      }
+    };
+    const maybeWorkspaceGitStatus = props.gitStatusProps.workspaceGitStatusPromise?.data;
+
+    if (!maybeWorkspaceGitStatus) {
+      return;
+    }
+    const id = isSingleFile(props) ? SupportedActions.revert : SupportedActions.revertAll;
+
+    const filepaths = maybeWorkspaceGitStatus.unstagedModifiedFilesStatus
+      .filter(
+        filterAcceptedStageStatuses([
+          FileModificationStatus.deleted,
+          FileModificationStatus.modified,
+          FileModificationStatus.added,
+        ])
+      )
+      .map(({ path }) => path);
+
+    if (!filepaths.length) {
+      return;
+    }
+    return {
+      onConfirm: async () => await doRevert(filepaths),
+      id,
+      titleText: i18n.gitStatusIndicatorActions[id].title,
+      titleIcon: <UndoAltIcon />,
+      alertVariant: AlertVariant.warning,
+      warningText: i18n.gitStatusIndicatorActions[id].warning,
+      description: (
+        <>
+          <span>{i18n.gitStatusIndicatorActions[id].description}</span>
+          <br />
+          <br />
+          {workspaceFilesRendered}
+          <br />
+        </>
+      ),
+      confirmButtonText: i18n.gitStatusIndicatorActions[id].confirmButtonText,
+    };
+  }, [i18n.gitStatusIndicatorActions, props, filterAcceptedStageStatuses, workspaceFilesRendered, workspaces]);
+
+  const actions: GitStatusIndicatorActionType[] = React.useMemo(() => {
+    const maybeActions = [
+      // list all actions here, which (based on internal state) could be undefined
+      actionRevert(),
+    ];
+
+    const result: GitStatusIndicatorActionType[] = [];
+
+    maybeActions.forEach((action) => {
+      if (action !== undefined) {
+        result.push(action);
+      }
+    });
+
+    return result;
+  }, [actionRevert]);
+
+  return isSingleFile(props) ? (
+    <MultipleActionsButtonsWithPopover actions={actions} isOpen={props.isOpen} setOpen={props.setOpen} />
+  ) : (
+    <MultipleActionsPopoverWithDropdown
+      title={
+        <TextContent>
+          <Text component="h3">Local Changes</Text>
+        </TextContent>
+      }
+      description={
+        <Flex direction={{ default: "column" }}>
+          <FlexItem>
+            <TextContent>
+              <Text component="p">
+                {`There are local changes to the following files in`}
+                <i>{`'${props.gitStatusProps.workspaceDescriptor.name}'`}</i>
+              </Text>
+            </TextContent>
+          </FlexItem>
+          {workspaceFilesRendered}
+        </Flex>
+      }
+      actions={actions}
+      isOpen={props.isOpen}
+      setOpen={props.setOpen}
+    />
+  );
+};
+
+const MultipleActionsButtonsWithPopover = (props: {
+  actions: GitStatusIndicatorActionType[];
+  isOpen: boolean;
+  setOpen: (value: boolean) => void;
+}) => {
+  const [openedPopoverId, setOpenedPopoverId] = React.useState<string>();
+  return (
+    <Flex spaceItems={{ default: "spaceItemsXs" }}>
+      {props.actions.map((action) => (
+        <SingleActionPopover
+          key={action.id}
+          action={action}
+          isOpen={props.isOpen && openedPopoverId === action.id}
+          setOpen={(isOpen: boolean) => {
+            setOpenedPopoverId(isOpen ? action.id : undefined);
+            props.setOpen(isOpen);
+          }}
+        />
+      ))}
+    </Flex>
+  );
+};
+
+const MultipleActionsPopoverWithDropdown = (props: {
+  actions: GitStatusIndicatorActionType[];
+  title: React.ReactNode;
+  description: JSX.Element;
+  isOpen: boolean;
+  setOpen: (isOpen: boolean) => void;
+}) => {
+  const [selectedActionId, setSelectedActionId] = React.useState<string>();
+  const [isDropdownOpen, setDropdownOpen] = React.useState<boolean>(false);
+
+  const selectedAction = React.useMemo(() => {
+    return props.actions.find((action) => action.id === selectedActionId);
+  }, [props.actions, selectedActionId]);
+
+  return (
+    <Popover
+      id={"popover-with-actions-dropdown"}
+      className={selectedActionId !== undefined ? " kie-tools--git-status-indicator__popover-no-padding" : ""} // noPadding prop not working nice for the ActionsAlert
+      position={PopoverPosition.bottom}
+      showClose={false}
+      isVisible={props.isOpen}
+      shouldOpen={() => props.setOpen(true)}
+      shouldClose={() => {
... 57738 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org