From d00f771a57f6b4bbbfe5aac899466dcabbb29270 Mon Sep 17 00:00:00 2001 From: Andreas Pfau Date: Thu, 28 Nov 2024 16:01:59 +0100 Subject: [PATCH] chore(core): remove obsolete code and update (#664) * chore(dashboard): remove obsolete code and clean up * chore(volta): update package-lock.json * chore(volta): delete obsolete workflows --- .github/workflows/block-deprecated_assets.yml | 61 - apps_deprecated/exampleapp/LICENSE | 201 - apps_deprecated/exampleapp/README.md | 88 - .../exampleapp/__mocks__/client.js | 9 - .../exampleapp/__mocks__/fileMock.js | 6 - .../exampleapp/__mocks__/styleMock.js | 6 - apps_deprecated/exampleapp/babel.config.js | 13 - apps_deprecated/exampleapp/db.json | 290 - apps_deprecated/exampleapp/esbuild.config.js | 211 - apps_deprecated/exampleapp/jest.config.js | 21 - apps_deprecated/exampleapp/package.json | 91 - apps_deprecated/exampleapp/public/favicon.ico | Bin 15086 -> 0 bytes apps_deprecated/exampleapp/public/index.html | 47 - apps_deprecated/exampleapp/setupTests.js | 10 - apps_deprecated/exampleapp/src/App.jsx | 93 - apps_deprecated/exampleapp/src/App.test.js | 17 - .../exampleapp/src/components/AppContent.js | 112 - .../exampleapp/src/components/AsyncWorker.jsx | 16 - .../exampleapp/src/components/ModalManager.js | 21 - .../exampleapp/src/components/PanelManager.js | 55 - .../exampleapp/src/components/Playground.js | 46 - .../src/components/StoreProvider.jsx | 42 - .../exampleapp/src/components/TestModal.js | 31 - .../exampleapp/src/components/WelcomeView.js | 25 - .../exampleapp/src/components/auth/Avatar.js | 34 - .../src/components/auth/HeaderUser.js | 39 - .../exampleapp/src/components/peaks/Peaks.js | 41 - .../src/components/peaks/PeaksEdit.js | 119 - .../src/components/peaks/PeaksList.js | 88 - .../src/components/peaks/PeaksListItem.js | 79 - .../src/components/peaks/PeaksNew.js | 101 - .../src/components/shared/HintLoading.js | 18 - .../src/components/shared/HintNotFound.jsx | 22 - .../src/hooks/useEndlessScrollList.js | 99 - .../exampleapp/src/hooks/useQueryClientFn.js | 150 - .../exampleapp/src/hooks/useUrlState.js | 69 - .../exampleapp/src/img/app_bg_example.svg | 17 - apps_deprecated/exampleapp/src/index.js | 19 - .../src/lib/store/createAuthSlice.js | 39 - .../src/lib/store/createGlobalsSlice.js | 74 - .../exampleapp/src/lib/store/index.js | 17 - apps_deprecated/exampleapp/src/styles.scss | 12 - apps_deprecated/exampleapp/tailwind.config.js | 30 - apps_deprecated/greenhouse-management/LICENSE | 201 - .../greenhouse-management/README.md | 7 - .../greenhouse-management/__mocks__/client.js | 9 - .../__mocks__/fileMock.js | 6 - .../__mocks__/styleMock.js | 6 - .../greenhouse-management/babel.config.js | 13 - .../greenhouse-management/esbuild.config.js | 205 - .../greenhouse-management/jest.config.js | 21 - .../greenhouse-management/package.json | 124 - .../public/favicon-16x16.png | Bin 953 -> 0 bytes .../public/favicon-32x32.png | Bin 1482 -> 0 bytes .../greenhouse-management/public/favicon.ico | Bin 22936 -> 0 bytes .../greenhouse-management/public/index.html | 68 - .../secretProps.template.json | 10 - .../greenhouse-management/setupTests.js | 10 - .../greenhouse-management/src/App.js | 77 - .../greenhouse-management/src/App.test.js | 18 - .../greenhouse-management/src/AppContent.js | 44 - .../greenhouse-management/src/assets/.gitkeep | 0 .../src/assets/juno-danger.svg | 8 - .../greenhouse-management/src/assets/map.svg | 4421 ------ .../src/assets/rocket.gif | Bin 4484489 -> 0 bytes .../src/components/AsyncWorker.jsx | 16 - .../src/components/Auth.jsx | 26 - .../src/components/OrgInfo.jsx | 105 - .../src/components/Plugin.jsx | 102 - .../src/components/PluginContainer.jsx | 26 - .../src/components/SideNav.js | 29 - .../src/components/StoreProvider.js | 33 - .../src/components/UrlState.jsx | 20 - .../src/components/shared/HintLoading.js | 31 - .../greenhouse-management/src/hooks/.gitkeep | 0 .../src/hooks/useCommunication.js | 41 - .../src/hooks/useUrlState.js | 55 - .../greenhouse-management/src/index.js | 17 - .../greenhouse-management/src/lib/helpers.js | 15 - .../greenhouse-management/src/lib/store.js | 101 - .../greenhouse-management/src/styles.scss | 20 - .../greenhouse-management/tailwind.config.js | 30 - apps_deprecated/greenhouse/.gitignore | 1 - apps_deprecated/greenhouse/LICENSE | 201 - apps_deprecated/greenhouse/README.md | 7 - .../greenhouse/__mocks__/client.js | 9 - .../greenhouse/__mocks__/fileMock.js | 6 - .../greenhouse/__mocks__/styleMock.js | 6 - apps_deprecated/greenhouse/babel.config.js | 13 - apps_deprecated/greenhouse/esbuild.config.js | 205 - apps_deprecated/greenhouse/jest.config.js | 21 - apps_deprecated/greenhouse/package.json | 127 - .../public/android-chrome-192x192.png | Bin 3392 -> 0 bytes .../public/android-chrome-512x512.png | Bin 10031 -> 0 bytes .../greenhouse/public/apple-touch-icon.png | Bin 2821 -> 0 bytes apps_deprecated/greenhouse/public/favicon.ico | Bin 15406 -> 0 bytes apps_deprecated/greenhouse/public/favicon.svg | 15 - apps_deprecated/greenhouse/public/index.html | 47 - .../greenhouse/secretProps.template.json | 7 - apps_deprecated/greenhouse/setupTests.js | 10 - apps_deprecated/greenhouse/src/Shell.js | 62 - apps_deprecated/greenhouse/src/Shell.test.js | 28 - apps_deprecated/greenhouse/src/actions.js | 52 - .../greenhouse/src/assets/ccloud_shape.svg | 8 - .../greenhouse/src/assets/greenhouse_logo.svg | 13 - .../src/assets/juno_default_app.svg | 15 - .../greenhouse/src/assets/juno_doop.svg | 15 - .../greenhouse/src/assets/juno_heureka.svg | 15 - .../greenhouse/src/assets/juno_supernova.svg | 16 - .../greenhouse/src/components/AsyncWorker.jsx | 43 - .../greenhouse/src/components/Auth.jsx | 176 - .../greenhouse/src/components/Avatar.jsx | 34 - .../src/components/NotificationsContainer.jsx | 27 - .../greenhouse/src/components/Plugin.jsx | 102 - .../src/components/PluginContainer.jsx | 70 - .../src/components/StoreProvider.jsx | 45 - .../src/components/layout/ShellLayout.js | 35 - .../src/components/layout/ShellLayout.test.js | 30 - .../src/components/nav/PluginNav.js | 156 - .../src/components/shared/HintLoading.js | 18 - .../greenhouse/src/hooks/useApi.js | 90 - .../greenhouse/src/hooks/useCommunication.js | 80 - .../greenhouse/src/hooks/useUrlState.js | 76 - apps_deprecated/greenhouse/src/index.js | 31 - apps_deprecated/greenhouse/src/lib/helpers.js | 15 - apps_deprecated/greenhouse/src/lib/plugin.js | 242 - .../greenhouse/src/lib/plugin.test.js | 173 - .../src/lib/store/createAuthDataSlice.js | 66 - .../src/lib/store/createGlobalsSlice.js | 52 - .../greenhouse/src/lib/store/index.js | 23 - apps_deprecated/greenhouse/src/styles.scss | 11 - apps_deprecated/greenhouse/tailwind.config.js | 30 - apps_deprecated/heureka/LICENSE | 201 - apps_deprecated/heureka/README.md | 13 - apps_deprecated/heureka/__mocks__/client.js | 9 - apps_deprecated/heureka/__mocks__/fileMock.js | 6 - .../heureka/__mocks__/styleMock.js | 6 - apps_deprecated/heureka/babel.config.js | 13 - apps_deprecated/heureka/esbuild.config.js | 205 - apps_deprecated/heureka/jest.config.js | 21 - apps_deprecated/heureka/package.json | 91 - apps_deprecated/heureka/public/favicon.ico | Bin 15086 -> 0 bytes apps_deprecated/heureka/public/index.html | 47 - apps_deprecated/heureka/setupTests.js | 10 - apps_deprecated/heureka/src/App.js | 55 - apps_deprecated/heureka/src/App.test.js | 21 - apps_deprecated/heureka/src/actions.js | 157 - .../heureka/src/components/AsyncWorker.jsx | 16 - .../heureka/src/components/StoreProvider.jsx | 26 - .../src/components/backup/AppContainer.js | 51 - .../src/components/backup/AppRouter.js | 146 - .../heureka/src/components/backup/Avatar.js | 34 - .../src/components/backup/Breadcrumb.js | 12 - .../src/components/backup/ChangesLogDetail.js | 143 - .../src/components/backup/ChangesLogList.js | 55 - .../components/backup/ChangesLogListItem.js | 50 - .../src/components/backup/ComponentDetail.js | 170 - .../src/components/backup/Components.js | 95 - .../src/components/backup/ComponentsList.js | 103 - .../components/backup/ComponentsListItem.js | 81 - .../src/components/backup/CustomBadge.js | 21 - .../src/components/backup/CustomPageHeader.js | 22 - .../src/components/backup/EvidenceNew.js | 17 - .../src/components/backup/EvidencesList.js | 47 - .../components/backup/EvidencesListItem.js | 33 - .../src/components/backup/FilterToolbar.js | 29 - .../components/backup/FilterToolbarCore.js | 109 - .../components/backup/FilterToolbarStore.js | 75 - .../src/components/backup/HeaderUser.js | 29 - .../heureka/src/components/backup/Home.js | 129 - .../src/components/backup/PackagesList.js | 32 - .../src/components/backup/PackagesListItem.js | 19 - .../src/components/backup/Pagination.js | 69 - .../src/components/backup/PatchLogDetail.js | 110 - .../src/components/backup/PatchLogNew.js | 72 - .../src/components/backup/PatchLogsList.js | 49 - .../components/backup/PatchLogsListItem.js | 44 - .../src/components/backup/ServiceDetail.js | 202 - .../heureka/src/components/backup/Services.js | 93 - .../src/components/backup/ServicesList.js | 55 - .../src/components/backup/ServicesListItem.js | 72 - .../src/components/backup/SupportGroups.js | 23 - .../components/backup/SupportGroupsList.js | 42 - .../src/components/backup/UserDetail.js | 116 - .../heureka/src/components/backup/Users.js | 86 - .../src/components/backup/UsersList.js | 50 - .../src/components/backup/UsersListItem.js | 40 - .../src/components/backup/Vulnerabilities.js | 88 - .../components/backup/VulnerabilitiesList.js | 64 - .../backup/VulnerabilitiesListItem.js | 54 - .../backup/VulnerabilitiesOverview.js | 47 - .../backup/VulnerabilitiyDetails.js | 224 - .../components/backup/VulnerabilityBadge.js | 58 - .../src/components/backup/WelcomeView.js | 31 - .../src/components/filters/FilterPills.jsx | 32 - .../src/components/filters/FilterSelect.jsx | 127 - .../src/components/filters/Filters.jsx | 47 - .../src/components/services/ServicesList.jsx | 52 - .../services/ServicesListController.jsx | 57 - .../components/services/ServicesListItem.js | 40 - .../src/components/services/ServicesTab.jsx | 19 - .../src/components/shared/HintLoading.jsx | 18 - .../src/components/shared/HintNotFound.jsx | 22 - .../src/components/shared/Pagination.jsx | 69 - .../src/components/shared/PaginationV2.jsx | 79 - .../src/components/tabs/TabContext.jsx | 59 - .../heureka/src/components/tabs/TabPanel.jsx | 22 - .../vulnerabilities/VulnerabilitiesList.jsx | 53 - .../VulnerabilitiesListController.jsx | 85 - .../VulnerabilitiesListItem.jsx | 40 - .../vulnerabilities/VulnerabilitiesTab.jsx | 19 - apps_deprecated/heureka/src/helpers.js | 201 - apps_deprecated/heureka/src/helpers.test.js | 102 - .../heureka/src/hooks/useCommunication.js | 51 - .../heureka/src/hooks/useQueryClientFn.js | 56 - .../heureka/src/hooks/useUrlState.js | 46 - .../heureka/src/img/app_bg_example.svg | 12 - apps_deprecated/heureka/src/index.js | 17 - .../heureka/src/lib/queries/serviceFilters.js | 32 - .../heureka/src/lib/queries/services.js | 92 - .../src/lib/queries/vulnerabilityMatches.js | 87 - apps_deprecated/heureka/src/lib/store.js | 58 - apps_deprecated/heureka/src/queries.js | 205 - apps_deprecated/heureka/src/styles.js | 27 - apps_deprecated/heureka/src/styles.scss | 12 - apps_deprecated/heureka/tailwind.config.js | 28 - apps_deprecated/supernova/LICENSE | 201 - apps_deprecated/supernova/README.md | 138 - apps_deprecated/supernova/__mocks__/client.js | 9 - .../supernova/__mocks__/fileMock.js | 6 - .../supernova/__mocks__/styleMock.js | 6 - apps_deprecated/supernova/babel.config.js | 13 - apps_deprecated/supernova/esbuild.config.js | 210 - apps_deprecated/supernova/jest.config.js | 21 - apps_deprecated/supernova/package.json | 112 - apps_deprecated/supernova/public/favicon.ico | Bin 15086 -> 0 bytes apps_deprecated/supernova/public/index.html | 54 - .../supernova/public/index_test.html | 60 - apps_deprecated/supernova/setupTests.js | 10 - apps_deprecated/supernova/src/App.jsx | 108 - apps_deprecated/supernova/src/App.test.js | 27 - apps_deprecated/supernova/src/AppContent.jsx | 125 - .../supernova/src/api/apiService.js | 122 - apps_deprecated/supernova/src/api/client.js | 54 - .../supernova/src/components/AsyncWorker.jsx | 18 - .../supernova/src/components/Avatar.jsx | 34 - .../src/components/CustomAppShell.jsx | 40 - .../supernova/src/components/HeaderUser.jsx | 29 - .../supernova/src/components/WelcomeView.jsx | 38 - .../supernova/src/components/alerts/Alert.jsx | 103 - .../src/components/alerts/AlertDetail.jsx | 151 - .../src/components/alerts/AlertSilences.jsx | 78 - .../src/components/alerts/AlertStatus.jsx | 65 - .../src/components/alerts/AlertsList.jsx | 120 - .../alerts/shared/AlertDescription.jsx | 28 - .../components/alerts/shared/AlertIcon.jsx | 43 - .../components/alerts/shared/AlertLabels.jsx | 63 - .../components/alerts/shared/AlertLinks.jsx | 118 - .../components/alerts/shared/AlertRegion.jsx | 24 - .../alerts/shared/AlertSilencesList.jsx | 85 - .../alerts/shared/AlertTimestamp.jsx | 38 - .../src/components/filters/FilterPills.jsx | 32 - .../src/components/filters/FilterSelect.jsx | 144 - .../src/components/filters/Filters.jsx | 28 - .../components/filters/PredefinedFilters.jsx | 49 - .../src/components/regions/Region.jsx | 72 - .../src/components/regions/RegionSeverity.jsx | 63 - .../src/components/regions/RegionsList.jsx | 46 - .../components/silences/SilenceMatchers.jsx | 57 - .../src/components/silences/SilenceNew.jsx | 278 - .../silences/SilenceNewAdvanced.jsx | 83 - .../components/silences/SilenceScheduled.jsx | 364 - .../silences/SilenceScheduledWrapper.jsx | 44 - .../src/components/silences/silenceHelpers.js | 80 - .../silences/silenceHelpers.test.js | 51 - .../silences/silenceScheduledHelpers.js | 95 - .../src/components/status/StatusBar.jsx | 39 - apps_deprecated/supernova/src/helpers.js | 39 - .../supernova/src/hooks/useAlertmanagerAPI.js | 201 - .../supernova/src/hooks/useAppStore.js | 147 - .../supernova/src/hooks/useCommunication.js | 70 - .../supernova/src/hooks/useUrlState.js | 134 - apps_deprecated/supernova/src/index.js | 17 - .../supernova/src/lib/createAlertsSlice.js | 218 - .../src/lib/createAlertsSlice.test.js | 440 - .../supernova/src/lib/createAuthDataSlice.js | 71 - .../supernova/src/lib/createFiltersSlice.js | 255 - .../src/lib/createFiltersSlice.test.js | 192 - .../supernova/src/lib/createGlobalsSlice.js | 47 - .../supernova/src/lib/createSilencesSlice.js | 334 - .../src/lib/createSilencesSlice.test.js | 778 - .../src/lib/createUserActivitySlice.js | 26 - .../supernova/src/lib/fakeObjects.js | 110 - apps_deprecated/supernova/src/lib/utils.js | 155 - apps_deprecated/supernova/src/styles.scss | 34 - .../supernova/src/workers/alerts.js | 90 - .../supernova/src/workers/silences.js | 55 - apps_deprecated/supernova/tailwind.config.js | 30 - apps_deprecated/template/.gitignore | 3 - apps_deprecated/template/LICENSE | 201 - apps_deprecated/template/README.md | 46 - apps_deprecated/template/__mocks__/client.js | 9 - .../template/__mocks__/fileMock.js | 6 - .../template/__mocks__/styleMock.js | 6 - apps_deprecated/template/babel.config.js | 13 - apps_deprecated/template/esbuild.config.js | 205 - apps_deprecated/template/jest.config.js | 21 - apps_deprecated/template/package.json | 94 - .../template/public/favicon-16x16.png | Bin 691 -> 0 bytes .../template/public/favicon-32x32.png | Bin 1048 -> 0 bytes apps_deprecated/template/public/favicon.ico | Bin 15086 -> 0 bytes apps_deprecated/template/public/index.html | 51 - .../template/secretProps.template.json | 5 - apps_deprecated/template/setupTests.js | 10 - apps_deprecated/template/src/App.js | 73 - apps_deprecated/template/src/App.test.js | 18 - apps_deprecated/template/src/AppContent.js | 19 - apps_deprecated/template/src/assets/.gitkeep | 0 .../template/src/components/StoreProvider.js | 24 - apps_deprecated/template/src/hooks/.gitkeep | 0 apps_deprecated/template/src/index.js | 17 - .../src/lib/store/createGlobalsSlice.js | 19 - .../src/lib/store/createGlobalsSlice.test.js | 34 - .../template/src/lib/store/index.js | 15 - apps_deprecated/template/src/styles.scss | 9 - apps_deprecated/template/tailwind.config.js | 30 - ci/pipeline.yaml.erb | 13 - docs/build_and_host_app.md | 4 +- libs_deprecated/communicator/.gitignore | 1 - libs_deprecated/communicator/LICENSE | 201 - libs_deprecated/communicator/README.md | 176 - libs_deprecated/communicator/dev/build.js | 183 - libs_deprecated/communicator/dev/build.js.map | 7 - libs_deprecated/communicator/dev/index.html | 113 - libs_deprecated/communicator/dev/index.js | 170 - .../communicator/esbuild.config.js | 51 - libs_deprecated/communicator/package.json | 46 - libs_deprecated/communicator/src/index.js | 290 - .../communicator/src/index.test.js | 216 - libs_deprecated/juno-ui-components/.gitignore | 3 - libs_deprecated/juno-ui-components/.npmignore | 9 - .../juno-ui-components/.storybook/.babelrc | 8 - .../.storybook/juno-addon/Decorator.jsx | 52 - .../.storybook/juno-addon/DocsContainer.jsx | 32 - .../.storybook/juno-addon/README.md | 41 - .../.storybook/juno-addon/ThemeToggle.jsx | 46 - .../.storybook/juno-addon/constants.js | 17 - .../.storybook/juno-addon/manager.js | 22 - .../.storybook/juno-addon/preview.js | 29 - .../.storybook/juno-addon/themes.js | 117 - .../juno-ui-components/.storybook/main.js | 93 - .../juno-ui-components/.storybook/preview.js | 111 - libs_deprecated/juno-ui-components/LICENSE | 201 - libs_deprecated/juno-ui-components/README.md | 61 - .../juno-ui-components/babel.config.json | 9 - .../juno-ui-components/lib/variables.scss | 635 - .../juno-ui-components/package.json | 119 - .../juno-ui-components/postcss.config.js | 8 - .../juno-ui-components/rollup.config.js | 153 - .../juno-ui-components/setupTests.js | 48 - .../components/AppBody/AppBody.component.js | 37 - .../src/components/AppBody/AppBody.stories.js | 35 - .../src/components/AppBody/AppBody.test.js | 59 - .../src/components/AppBody/index.js | 6 - .../components/AppIntro/AppIntro.component.js | 34 - .../components/AppIntro/AppIntro.stories.js | 40 - .../src/components/AppIntro/AppIntro.test.js | 41 - .../src/components/AppIntro/index.js | 6 - .../components/AppShell/AppShell.component.js | 121 - .../components/AppShell/AppShell.stories.js | 202 - .../src/components/AppShell/AppShell.test.js | 143 - .../src/components/AppShell/index.js | 6 - .../AppShellProvider.component.js | 61 - .../AppShellProvider.stories.js | 128 - .../AppShellProvider/AppShellProvider.test.js | 20 - .../src/components/AppShellProvider/index.js | 6 - .../src/components/Badge/Badge.component.js | 135 - .../src/components/Badge/Badge.stories.js | 103 - .../src/components/Badge/Badge.test.js | 82 - .../src/components/Badge/index.js | 6 - .../src/components/Box/Box.component.js | 52 - .../src/components/Box/Box.stories.js | 41 - .../src/components/Box/Box.test.js | 46 - .../src/components/Box/index.js | 6 - .../Breadcrumb/Breadcrumb.component.js | 51 - .../Breadcrumb/Breadcrumb.stories.js | 40 - .../components/Breadcrumb/Breadcrumb.test.js | 32 - .../src/components/Breadcrumb/index.js | 6 - .../BreadcrumbItem.component.js | 113 - .../BreadcrumbItem/BreadcrumbItem.stories.js | 110 - .../BreadcrumbItem/BreadcrumbItem.test.js | 88 - .../src/components/BreadcrumbItem/index.js | 6 - .../src/components/Button/Button.component.js | 241 - .../src/components/Button/Button.stories.js | 453 - .../src/components/Button/Button.test.js | 140 - .../src/components/Button/button.scss | 73 - .../src/components/Button/index.js | 6 - .../ButtonRow/ButtonRow.component.js | 40 - .../components/ButtonRow/ButtonRow.stories.js | 39 - .../components/ButtonRow/ButtonRow.test.js | 38 - .../src/components/ButtonRow/index.js | 6 - .../components/Checkbox/Checkbox.component.js | 380 - .../components/Checkbox/Checkbox.stories.js | 97 - .../src/components/Checkbox/Checkbox.test.js | 174 - .../src/components/Checkbox/index.js | 6 - .../CheckboxGroup/CheckboxGroup.component.js | 271 - .../CheckboxGroup/CheckboxGroup.stories.js | 213 - .../CheckboxGroup/CheckboxGroup.test.js | 202 - .../src/components/CheckboxGroup/index.js | 6 - .../CheckboxRow/CheckboxRow.component.js | 103 - .../CheckboxRow/CheckboxRow.stories.js | 106 - .../CheckboxRow/CheckboxRow.test.js | 117 - .../src/components/CheckboxRow/index.js | 6 - .../src/components/Code/Code.component.js | 35 - .../src/components/Code/Code.stories.js | 46 - .../src/components/Code/Code.test.js | 50 - .../src/components/Code/index.js | 6 - .../CodeBlock/CodeBlock.component.js | 224 - .../components/CodeBlock/CodeBlock.stories.js | 210 - .../components/CodeBlock/CodeBlock.test.js | 185 - .../src/components/CodeBlock/index.js | 6 - .../components/ComboBox/ComboBox.component.js | 534 - .../components/ComboBox/ComboBox.stories.js | 886 -- .../src/components/ComboBox/ComboBox.test.js | 401 - .../src/components/ComboBox/index.js | 6 - .../ComboBoxOption.component.js | 123 - .../ComboBoxOption/ComboBoxOption.stories.js | 47 - .../ComboBoxOption/ComboBoxOption.test.js | 98 - .../src/components/ComboBoxOption/index.js | 6 - .../Container/Container.component.js | 51 - .../components/Container/Container.stories.js | 60 - .../components/Container/Container.test.js | 64 - .../src/components/Container/index.js | 6 - .../ContentArea/ContentArea.component.js | 44 - .../ContentArea/ContentArea.stories.js | 33 - .../ContentArea/ContentArea.test.js | 74 - .../src/components/ContentArea/index.js | 6 - .../ContentAreaToolbar.component.js | 46 - .../ContentAreaToolbar.stories.js | 40 - .../ContentAreaToolbar.test.js | 50 - .../components/ContentAreaToolbar/index.js | 6 - .../ContentAreaWrapper.component.js | 40 - .../ContentAreaWrapper.stories.js | 44 - .../ContentAreaWrapper.test.js | 62 - .../components/ContentAreaWrapper/index.js | 6 - .../ContentContainer.component.js | 40 - .../ContentContainer.stories.js | 35 - .../ContentContainer/ContentContainer.test.js | 51 - .../src/components/ContentContainer/index.js | 6 - .../ContentHeading.component.js | 44 - .../ContentHeading/ContentHeading.stories.js | 33 - .../ContentHeading/ContentHeading.test.js | 58 - .../src/components/ContentHeading/index.js | 6 - .../ContextMenu/ContextMenu.component.js | 94 - .../ContextMenu/ContextMenu.stories.js | 98 - .../ContextMenu/ContextMenu.test.js | 28 - .../src/components/ContextMenu/index.js | 6 - .../components/DataGrid/DataGrid.component.js | 105 - .../components/DataGrid/DataGrid.stories.js | 242 - .../src/components/DataGrid/DataGrid.test.js | 23 - .../src/components/DataGrid/index.js | 6 - .../DataGridCell/DataGridCell.component.js | 77 - .../DataGridCell/DataGridCell.stories.js | 85 - .../DataGridCell/DataGridCell.test.js | 24 - .../src/components/DataGridCell/index.js | 6 - .../DataGridCheckboxCell.component.js | 41 - .../DataGridCheckboxCell.stories.js | 65 - .../DataGridCheckboxCell.test.js | 39 - .../components/DataGridCheckboxCell/index.js | 6 - .../DataGridFoot/DataGridFoot.component.js | 31 - .../DataGridFoot/DataGridFoot.stories.js | 53 - .../DataGridFoot/DataGridFoot.test.js | 27 - .../src/components/DataGridFoot/index.js | 6 - .../DataGridHeadCell.component.js | 74 - .../DataGridHeadCell.stories.js | 85 - .../DataGridHeadCell/DataGridHeadCell.test.js | 23 - .../src/components/DataGridHeadCell/index.js | 6 - .../DataGridRow/DataGridRow.component.js | 65 - .../DataGridRow/DataGridRow.stories.js | 59 - .../DataGridRow/DataGridRow.test.js | 24 - .../src/components/DataGridRow/index.js | 6 - .../DataGridToolbar.component.js | 56 - .../DataGridToolbar.stories.js | 68 - .../DataGridToolbar/DataGridToolbar.test.js | 35 - .../src/components/DataGridToolbar/index.js | 6 - .../components/DataList/DataList.component.js | 46 - .../components/DataList/DataList.stories.js | 160 - .../src/components/DataList/DataList.test.js | 23 - .../src/components/DataList/index.js | 6 - .../DataListCell/DataListCell.component.js | 151 - .../DataListCell/DataListCell.stories.js | 42 - .../DataListCell/DataListCell.test.js | 23 - .../src/components/DataListCell/index.js | 6 - .../DataListCheckboxCell.component.js | 51 - .../DataListCheckboxCell.stories.js | 56 - .../DataListCheckboxCell.test.js | 30 - .../components/DataListCheckboxCell/index.js | 6 - .../DataListRow/DataListRow.component.js | 62 - .../DataListRow/DataListRow.stories.js | 160 - .../DataListRow/DataListRow.test.js | 23 - .../src/components/DataListRow/index.js | 6 - .../DateTimePicker.component.js | 711 - .../DateTimePicker/DateTimePicker.stories.js | 500 - .../DateTimePicker/DateTimePicker.test.js | 684 - .../DateTimePicker/datetimepicker.scss | 831 -- .../src/components/DateTimePicker/index.js | 6 - .../FilterInput/FilterInput.component.js | 232 - .../FilterInput/FilterInput.stories.js | 50 - .../FilterInput/FilterInput.test.js | 281 - .../src/components/FilterInput/index.js | 6 - .../FilterPill/FilterPill.component.js | 100 - .../FilterPill/FilterPill.stories.js | 22 - .../components/FilterPill/FilterPill.test.js | 133 - .../src/components/FilterPill/index.js | 6 - .../components/Filters/Filters.component.js | 167 - .../src/components/Filters/Filters.stories.js | 121 - .../src/components/Filters/Filters.test.js | 204 - .../src/components/Filters/index.js | 6 - .../src/components/Form/Form.component.js | 50 - .../src/components/Form/Form.stories.js | 132 - .../src/components/Form/Form.test.js | 41 - .../src/components/Form/index.js | 6 - .../components/FormHint/FormHint.component.js | 66 - .../components/FormHint/FormHint.stories.js | 69 - .../src/components/FormHint/FormHint.test.js | 70 - .../src/components/FormHint/index.js | 6 - .../components/FormRow/FormRow.component.js | 40 - .../src/components/FormRow/FormRow.stories.js | 28 - .../src/components/FormRow/FormRow.test.js | 34 - .../src/components/FormRow/index.js | 6 - .../FormSection/FormSection.component.js | 53 - .../FormSection/FormSection.stories.js | 57 - .../FormSection/FormSection.test.js | 41 - .../src/components/FormSection/index.js | 6 - .../src/components/Grid/Grid.component.js | 49 - .../src/components/Grid/Grid.stories.js | 159 - .../src/components/Grid/Grid.test.js | 30 - .../src/components/Grid/index.js | 6 - .../GridColumn/GridColumn.component.js | 152 - .../GridColumn/GridColumn.stories.js | 50 - .../components/GridColumn/GridColumn.test.js | 38 - .../src/components/GridColumn/index.js | 6 - .../components/GridRow/GridRow.component.js | 40 - .../src/components/GridRow/GridRow.stories.js | 46 - .../src/components/GridRow/GridRow.test.js | 22 - .../src/components/GridRow/index.js | 6 - .../src/components/Icon/Icon.component.js | 826 -- .../src/components/Icon/Icon.stories.js | 403 - .../src/components/Icon/Icon.test.js | 381 - .../src/components/Icon/icons/home_sharp.svg | 6 - .../src/components/Icon/icons/juno-danger.svg | 8 - .../Icon/icons/juno_severity_critical.svg | 10 - .../Icon/icons/juno_severity_high.svg | 11 - .../Icon/icons/juno_severity_low.svg | 11 - .../Icon/icons/juno_severity_medium.svg | 11 - .../src/components/Icon/icons/place.svg | 6 - .../src/components/Icon/index.js | 6 - .../InputGroup/InputGroup.component.js | 56 - .../InputGroup/InputGroup.stories.js | 141 - .../components/InputGroup/InputGroup.test.js | 105 - .../src/components/InputGroup/index.js | 6 - .../components/InputGroup/input-group.scss | 32 - .../components/IntroBox/IntroBox.component.js | 114 - .../components/IntroBox/IntroBox.stories.js | 48 - .../src/components/IntroBox/IntroBox.test.js | 99 - .../src/components/IntroBox/index.js | 6 - .../JsonViewer/JsonViewer.component.js | 543 - .../JsonViewer/JsonViewer.stories.js | 110 - .../components/JsonViewer/JsonViewer.test.js | 29 - .../src/components/JsonViewer/index.js | 6 - .../src/components/JsonViewer/themes.js | 42 - .../src/components/Label/Label.component.js | 113 - .../src/components/Label/Label.stories.js | 33 - .../src/components/Label/Label.test.js | 57 - .../src/components/Label/index.js | 6 - .../LoadingIndicator.component.js | 44 - .../LoadingIndicator.stories.js | 37 - .../LoadingIndicator/LoadingIndicator.test.js | 44 - .../src/components/LoadingIndicator/index.js | 6 - .../LoadingIndicator/loading-indicator.svg | 37 - .../MainContainer/MainContainer.component.js | 44 - .../MainContainer/MainContainer.stories.js | 35 - .../MainContainer/MainContainer.test.js | 46 - .../src/components/MainContainer/index.js | 6 - .../MainContainerInner.component.js | 69 - .../MainContainerInner.test.js | 64 - .../components/MainContainerInner/index.js | 6 - .../components/MainTabs/MainTabs.component.js | 53 - .../components/MainTabs/MainTabs.stories.js | 99 - .../src/components/MainTabs/MainTabs.test.js | 188 - .../src/components/MainTabs/index.js | 6 - .../src/components/Menu/Menu.component.js | 83 - .../src/components/Menu/Menu.stories.js | 118 - .../src/components/Menu/Menu.test.js | 55 - .../src/components/Menu/index.js | 6 - .../components/MenuItem/MenuItem.component.js | 133 - .../components/MenuItem/MenuItem.stories.js | 114 - .../src/components/MenuItem/MenuItem.test.js | 86 - .../src/components/MenuItem/index.js | 6 - .../MenuSection/MenuSection.component.js | 48 - .../MenuSection/MenuSection.stories.js | 44 - .../MenuSection/MenuSection.test.js | 18 - .../src/components/MenuSection/index.js | 6 - .../components/Message/Message.component.js | 237 - .../src/components/Message/Message.stories.js | 65 - .../src/components/Message/Message.test.js | 184 - .../src/components/Message/index.js | 6 - .../src/components/Modal/Modal.component.js | 276 - .../src/components/Modal/Modal.stories.js | 228 - .../src/components/Modal/Modal.test.js | 251 - .../src/components/Modal/index.js | 6 - .../ModalFooter/ModalFooter.component.js | 99 - .../ModalFooter/ModalFooter.stories.js | 59 - .../ModalFooter/ModalFooter.test.js | 80 - .../src/components/ModalFooter/index.js | 6 - .../NativeSelect/NativeSelect.component.js | 251 - .../NativeSelect/NativeSelect.stories.js | 115 - .../NativeSelect/NativeSelect.test.js | 123 - .../src/components/NativeSelect/index.js | 6 - .../NativeSelectOption.component.js | 45 - .../NativeSelectOption.stories.js | 28 - .../NativeSelectOption/SelectOption.test.js | 47 - .../components/NativeSelectOption/index.js | 6 - .../NativeSelectOptionGroup.component.js | 44 - .../NativeSelectOptionGroup.stories.js | 62 - .../NativeSelectOptionGroup.test.js | 51 - .../NativeSelectOptionGroup/index.js | 6 - .../Navigation/Navigation.component.js | 134 - .../Navigation/Navigation.stories.js | 155 - .../components/Navigation/Navigation.test.js | 1524 -- .../src/components/Navigation/index.js | 6 - .../NavigationItem.component.js | 216 - .../NavigationItem/NavigationItem.stories.js | 75 - .../NavigationItem/NavigationItem.test.js | 150 - .../src/components/NavigationItem/index.js | 6 - .../PageFooter/PageFooter.component.js | 57 - .../PageFooter/PageFooter.stories.js | 35 - .../components/PageFooter/PageFooter.test.js | 47 - .../src/components/PageFooter/index.js | 6 - .../PageHeader/PageHeader.component.js | 87 - .../PageHeader/PageHeader.stories.js | 49 - .../components/PageHeader/PageHeader.test.js | 55 - .../src/components/PageHeader/index.js | 6 - .../Pagination/Pagination.component.js | 168 - .../Pagination/Pagination.stories.js | 78 - .../components/Pagination/Pagination.test.js | 106 - .../src/components/Pagination/index.js | 6 - .../src/components/Panel/Panel.component.js | 163 - .../src/components/Panel/Panel.stories.js | 57 - .../src/components/Panel/Panel.test.js | 81 - .../src/components/Panel/index.js | 6 - .../PanelBody/PanelBody.component.js | 46 - .../components/PanelBody/PanelBody.stories.js | 66 - .../components/PanelBody/PanelBody.test.js | 62 - .../src/components/PanelBody/index.js | 6 - .../PanelFooter/PanelFooter.component.js | 42 - .../PanelFooter/PanelFooter.stories.js | 53 - .../PanelFooter/PanelFooter.test.js | 49 - .../src/components/PanelFooter/index.js | 6 - .../src/components/Pill/Pill.component.js | 126 - .../src/components/Pill/Pill.stories.js | 47 - .../src/components/Pill/Pill.test.js | 154 - .../src/components/Pill/index.js | 6 - .../PortalProvider.component.js | 88 - .../PortalProvider/PortalProvider.stories.js | 67 - .../PortalProvider/PortalProvider.test.js | 40 - .../src/components/PortalProvider/index.js | 6 - .../src/components/Radio/Radio.component.js | 355 - .../src/components/Radio/Radio.stories.js | 108 - .../src/components/Radio/Radio.test.js | 182 - .../src/components/Radio/index.js | 6 - .../RadioGroup/RadioGroup.component.js | 267 - .../RadioGroup/RadioGroup.stories.js | 226 - .../components/RadioGroup/RadioGroup.test.js | 186 - .../src/components/RadioGroup/index.js | 6 - .../components/RadioRow/RadioRow.component.js | 97 - .../components/RadioRow/RadioRow.stories.js | 112 - .../src/components/RadioRow/RadioRow.test.js | 111 - .../src/components/RadioRow/index.js | 6 - .../SearchInput/SearchInput.component.js | 212 - .../SearchInput/SearchInput.stories.js | 35 - .../SearchInput/SearchInput.test.js | 143 - .../src/components/SearchInput/index.js | 6 - .../components/SearchInput/searchinput.scss | 6 - .../src/components/Select/Select.component.js | 479 - .../src/components/Select/Select.stories.js | 529 - .../src/components/Select/Select.test.js | 421 - .../src/components/Select/index.js | 6 - .../src/components/Select/select.scss | 84 - .../SelectDivider/SelectDivider.component.js | 31 - .../SelectDivider/SelectDivider.stories.js | 32 - .../SelectDivider/SelectDivider.test.js | 30 - .../src/components/SelectDivider/index.js | 6 - .../SelectOption/SelectOption.component.js | 127 - .../SelectOption/SelectOption.stories.js | 62 - .../SelectOption/SelectOption.test.js | 98 - .../src/components/SelectOption/index.js | 6 - .../SelectRow/SelectRow.component.js | 132 - .../components/SelectRow/SelectRow.stories.js | 335 - .../components/SelectRow/SelectRow.test.js | 214 - .../src/components/SelectRow/index.js | 6 - .../ShadowRoot/ShadowRoot.component.js | 83 - .../ShadowRoot/ShadowRoot.stories.js | 31 - .../src/components/ShadowRoot/index.js | 6 - .../SideNavigation.component.js | 65 - .../SideNavigation/SideNavigation.stories.js | 100 - .../SideNavigation/SideNavigation.test.js | 264 - .../src/components/SideNavigation/index.js | 6 - .../SideNavigationItem.component.js | 103 - .../SideNavigationItem.stories.js | 68 - .../SideNavigationItem.test.js | 152 - .../components/SideNavigationItem/index.js | 6 - .../components/Spinner/Spinner.component.js | 118 - .../src/components/Spinner/Spinner.stories.js | 59 - .../src/components/Spinner/Spinner.test.js | 109 - .../src/components/Spinner/index.js | 6 - .../src/components/Stack/Stack.component.js | 183 - .../src/components/Stack/Stack.stories.js | 282 - .../src/components/Stack/Stack.test.js | 106 - .../src/components/Stack/index.js | 6 - .../src/components/StyleProvider/Fonts.js | 53 - .../components/StyleProvider/GlobalStyles.js | 38 - .../StyleProvider/StyleProvider.component.js | 142 - .../StyleProvider/StyleProvider.stories.js | 61 - .../StyleProvider/StyleProvider.test.js | 24 - .../src/components/StyleProvider/index.js | 6 - .../src/components/Switch/Switch.component.js | 297 - .../src/components/Switch/Switch.stories.js | 135 - .../src/components/Switch/Switch.test.js | 181 - .../src/components/Switch/index.js | 6 - .../SwitchRow/SwitchRow.component.js | 103 - .../components/SwitchRow/SwitchRow.stories.js | 234 - .../components/SwitchRow/SwitchRow.test.js | 133 - .../src/components/SwitchRow/index.js | 6 - .../src/components/Tab/Tab.component.js | 76 - .../src/components/Tab/Tab.stories.js | 37 - .../src/components/Tab/Tab.test.js | 49 - .../src/components/Tab/index.js | 6 - .../components/TabList/TabList.component.js | 73 - .../src/components/TabList/TabList.stories.js | 54 - .../src/components/TabList/TabList.test.js | 42 - .../src/components/TabList/index.js | 6 - .../TabNavigation/TabNavigation.component.js | 78 - .../TabNavigation/TabNavigation.stories.js | 128 - .../TabNavigation/TabNavigation.test.js | 278 - .../src/components/TabNavigation/index.js | 6 - .../TabNavigationItem.component.js | 111 - .../TabNavigationItem.stories.js | 65 - .../TabNavigationItem.test.js | 152 - .../src/components/TabNavigationItem/index.js | 6 - .../components/TabPanel/TabPanel.component.js | 45 - .../components/TabPanel/TabPanel.stories.js | 23 - .../src/components/TabPanel/TabPanel.test.js | 30 - .../src/components/TabPanel/index.js | 6 - .../src/components/Tabs/Tabs.component.js | 84 - .../src/components/Tabs/Tabs.stories.js | 130 - .../src/components/Tabs/Tabs.test.js | 211 - .../src/components/Tabs/index.js | 6 - .../TextInput/TextInput.component.js | 331 - .../components/TextInput/TextInput.stories.js | 128 - .../components/TextInput/TextInput.test.js | 187 - .../src/components/TextInput/index.js | 6 - .../src/components/TextInput/textinput.scss | 6 - .../TextInputRow/TextInputRow.component.js | 124 - .../TextInputRow/TextInputRow.stories.js | 179 - .../TextInputRow/TextInputRow.test.js | 206 - .../src/components/TextInputRow/index.js | 6 - .../components/Textarea/Textarea.component.js | 326 - .../components/Textarea/Textarea.stories.js | 98 - .../src/components/Textarea/Textarea.test.js | 158 - .../src/components/Textarea/index.js | 6 - .../TextareaRow/TextareaRow.component.js | 102 - .../TextareaRow/TextareaRow.stories.js | 124 - .../TextareaRow/TextareaRow.test.js | 136 - .../src/components/TextareaRow/index.js | 6 - .../src/components/Toast/Toast.component.js | 121 - .../src/components/Toast/Toast.stories.js | 64 - .../src/components/Toast/Toast.test.js | 99 - .../src/components/Toast/index.js | 6 - .../components/Tooltip/Tooltip.component.js | 97 - .../src/components/Tooltip/Tooltip.stories.js | 232 - .../src/components/Tooltip/Tooltip.test.js | 144 - .../src/components/Tooltip/index.js | 7 - .../src/components/Tooltip/useTooltip.js | 124 - .../TooltipContent.component.js | 92 - .../TooltipContent/TooltipContent.stories.js | 34 - .../TooltipContent/TooltipContent.test.js | 43 - .../src/components/TooltipContent/index.js | 6 - .../TooltipTrigger.component.js | 69 - .../TooltipTrigger/TooltipTrigger.stories.js | 59 - .../TooltipTrigger/TooltipTrigger.test.js | 43 - .../src/components/TooltipTrigger/index.js | 7 - .../TopNavigation/TopNavigation.component.js | 68 - .../TopNavigation/TopNavigation.stories.js | 102 - .../TopNavigation/TopNavigation.test.js | 201 - .../src/components/TopNavigation/index.js | 7 - .../TopNavigationItem.component.js | 107 - .../TopNavigationItem.stories.js | 66 - .../TopNavigationItem.test.js | 129 - .../src/components/TopNavigationItem/index.js | 7 - .../withDeprecationWarning/index.js | 6 - .../withDeprecationWarning.component.js | 23 - .../withDeprecationWarning.test.js | 35 - .../src/docs/ColorPalette/ColorCard.jsx | 40 - .../src/docs/ColorPalette/ColorPalette.jsx | 53 - .../docs/ColorPalette/JunoColorPalette.jsx | 29 - .../src/docs/ColorPalette/TailwindColors.js | 121 - .../src/docs/ColorPalette/TextColorCard.jsx | 42 - .../generateTailwindThemeClassesJson.js | 109 - .../JunoComponentWrapper.jsx | 48 - .../juno-ui-components/src/docs/colors.mdx | 35 - .../src/docs/img/Schwan.jpg | Bin 59573 -> 0 bytes .../src/docs/navigation.mdx | 115 - .../src/docsHidden/examplePage.mdx | 44 - .../src/dummyComponents/DummyComponent.js | 26 - .../src/dummyComponents/DummyComponentList.js | 19 - .../juno-ui-components/src/global.scss | 48 - .../src/hooks/useTimeout.js | 31 - .../src/img/app_bg_example.svg | 18 - .../src/img/ccloud_shape.svg | 8 - .../src/img/icon_arrow_down.svg | 18 - .../juno-ui-components/src/img/sap_logo.svg | 20 - .../juno-ui-components/src/index.js | 118 - .../juno-ui-components/src/utils.js | 68 - .../juno-ui-components/tailwind.config.js | 340 - .../test/__mocks__/styleMock.js | 6 - .../juno-ui-components/test/__mocks__/svg.js | 32 - .../test/__mocks__/svgLib.js | 13 - libs_deprecated/messages-provider/LICENSE | 201 - libs_deprecated/messages-provider/README.md | 223 - .../messages-provider/babel.config.json | 8 - .../messages-provider/package.json | 61 - .../messages-provider/rollup.config.js | 49 - .../messages-provider/setupTests.js | 48 - .../messages-provider/src/Messages.js | 53 - .../messages-provider/src/Messages.test.js | 35 - .../messages-provider/src/index.js | 14 - .../messages-provider/src/useMessageStore.js | 152 - .../src/useMessageStore.test.js | 216 - libs_deprecated/oauth/LICENSE | 201 - libs_deprecated/oauth/README.md | 202 - .../oauth/__tests__/__utils__/globalsMock.js | 34 - .../oauth/__tests__/__utils__/idTokenMock.js | 21 - .../__tests__/__utils__/oidcConfigMock.js | 42 - .../oauth/__tests__/codeFlow.test.js | 243 - .../oauth/__tests__/implicitFlow.test.js | 123 - .../oauth/__tests__/mockedSession.test.js | 144 - .../oauth/__tests__/oidcConfig.test.js | 81 - .../oauth/__tests__/oidcSession.test.js | 106 - .../oauth/__tests__/tokenHelpers.test.js | 240 - libs_deprecated/oauth/esbuild.config.js | 28 - libs_deprecated/oauth/package.json | 49 - libs_deprecated/oauth/src/codeFlow.js | 130 - libs_deprecated/oauth/src/implicitFlow.js | 53 - libs_deprecated/oauth/src/index.js | 8 - libs_deprecated/oauth/src/mockedSession.js | 91 - libs_deprecated/oauth/src/oidcConfig.js | 38 - libs_deprecated/oauth/src/oidcSession.js | 331 - libs_deprecated/oauth/src/oidcState.js | 67 - libs_deprecated/oauth/src/tokenHelpers.js | 114 - libs_deprecated/oauth/src/utils.js | 49 - libs_deprecated/policy-engine/LICENSE | 201 - libs_deprecated/policy-engine/README.md | 121 - libs_deprecated/policy-engine/package.json | 44 - .../policy-engine/rollup.config.js | 57 - .../policy-engine/src/debugTrace.js | 32 - .../policy-engine/src/debugTrace.test.js | 36 - libs_deprecated/policy-engine/src/engine.js | 106 - .../policy-engine/src/engine.test.js | 293 - .../policy-engine/src/evaluator.js | 170 - .../policy-engine/src/evaluator.test.js | 400 - libs_deprecated/policy-engine/src/index.js | 9 - libs_deprecated/policy-engine/src/lexer.js | 37 - .../policy-engine/src/lexer.test.js | 116 - libs_deprecated/policy-engine/src/parser.js | 286 - .../policy-engine/src/parser.test.js | 545 - libs_deprecated/template-lib/LICENSE | 201 - libs_deprecated/template-lib/README.md | 101 - .../template-lib/__tests__/index.js | 30 - .../template-lib/esbuild.config.js | 28 - libs_deprecated/template-lib/package.json | 48 - libs_deprecated/template-lib/src/index.js | 55 - libs_deprecated/url-state-provider/LICENSE | 201 - libs_deprecated/url-state-provider/README.md | 182 - .../url-state-provider/babel.config.js | 13 - .../url-state-provider/jest.config.js | 11 - .../url-state-provider/package.json | 48 - .../url-state-provider/rollup.config.js | 55 - .../url-state-provider/src/index.js | 314 - .../url-state-provider/src/index.test.js | 294 - libs_deprecated/url-state-router/LICENSE | 201 - libs_deprecated/url-state-router/README.md | 204 - .../url-state-router/babel.config.js | 10 - libs_deprecated/url-state-router/package.json | 64 - .../url-state-router/rollup.config.js | 72 - libs_deprecated/url-state-router/src/Link.js | 37 - .../url-state-router/src/Link.test.js | 45 - .../url-state-router/src/Redirect.js | 29 - .../url-state-router/src/Redirect.test.js | 26 - libs_deprecated/url-state-router/src/Route.js | 44 - .../url-state-router/src/Route.test.js | 81 - .../url-state-router/src/Router.js | 50 - .../url-state-router/src/Router.test.js | 16 - .../url-state-router/src/RouterContext.js | 25 - .../src/RouterContext.test.js | 44 - .../url-state-router/src/Switch.js | 50 - .../url-state-router/src/Switch.test.js | 71 - libs_deprecated/url-state-router/src/index.js | 13 - .../url-state-router/src/routeMatcher.js | 50 - .../url-state-router/src/routeMatcher.test.js | 113 - .../src/useURLStateProvider.js | 110 - .../src/useURLStateProvider.test.js | 72 - libs_deprecated/utils/LICENSE | 201 - libs_deprecated/utils/README.md | 475 - .../__mocks__/intersectionObserverMock.js | 12 - libs_deprecated/utils/babel.config.json | 8 - libs_deprecated/utils/esbuild.config.js | 32 - libs_deprecated/utils/package.json | 58 - .../utils/src/hooks/useAppLoader.js | 83 - .../utils/src/hooks/useEndlessScrollList.js | 100 - .../src/hooks/useEndlessScrollList.test.js | 84 - libs_deprecated/utils/src/index.js | 10 - libs_deprecated/utils/src/lib/fetchProxy.js | 346 - .../utils/src/lib/fetchProxy.test.js | 262 - package-lock.json | 1948 +-- packages/assets-overview/LICENSE | 201 - packages/assets-overview/README.md | 9 - packages/assets-overview/__mocks__/client.js | 9 - .../assets-overview/__mocks__/fileMock.js | 6 - .../__mocks__/react-markdown.js | 10 - .../assets-overview/__mocks__/remark-gfm.js | 10 - .../assets-overview/__mocks__/styleMock.js | 6 - packages/assets-overview/babel.config.js | 13 - packages/assets-overview/esbuild.config.js | 206 - packages/assets-overview/jest.config.js | 21 - packages/assets-overview/package-lock.json | 11968 ---------------- packages/assets-overview/package.json | 92 - packages/assets-overview/public/favicon.ico | Bin 15086 -> 0 bytes packages/assets-overview/public/index.html | 68 - packages/assets-overview/setupTests.js | 10 - packages/assets-overview/src/App.js | 91 - packages/assets-overview/src/App.test.js | 36 - packages/assets-overview/src/actions.js | 65 - .../src/components/AppContent.jsx | 153 - .../src/components/AppRouter.jsx | 27 - .../src/components/AssetDetails.js | 284 - .../src/components/AssetsList.js | 52 - .../src/components/AssetsListItem.js | 86 - .../src/components/BuildLog.jsx | 104 - .../src/components/CustomPageHeader.js | 22 - .../src/components/Documentation.js | 157 - .../src/components/HintLoading.js | 18 - .../src/components/HintNotFound.js | 22 - .../src/components/Markdown.js | 53 - .../src/components/TabContainer.js | 19 - .../src/components/TestContent.js | 63 - .../src/components/details/DetailSection.jsx | 19 - .../details/PreviewAppPropsForm.jsx | 100 - .../src/components/details/TabAdvanced.jsx | 17 - .../src/components/details/TabGetStarted.jsx | 132 - .../src/components/details/TabPreview.jsx | 116 - .../components/details/TabWithMarkdown.jsx | 31 - packages/assets-overview/src/helpers.js | 91 - .../src/hooks/useAssetTestUrl.js | 35 - .../src/img/app_bg_example.svg | 18 - packages/assets-overview/src/index.js | 17 - packages/assets-overview/src/store.js | 22 - packages/assets-overview/src/styles.js | 23 - packages/assets-overview/src/styles.scss | 12 - packages/assets-overview/src/test-data.json | 651 - packages/assets-overview/src/widget.js | 8 - packages/assets-overview/tailwind.config.js | 30 - packages/auth/LICENSE | 201 - packages/auth/README.md | 81 - packages/auth/__mocks__/fileMock.js | 6 - packages/auth/__mocks__/styleMock.js | 6 - packages/auth/babel.config.js | 13 - packages/auth/esbuild.config.js | 206 - packages/auth/jest.config.js | 19 - packages/auth/package-lock.json | 10538 -------------- packages/auth/package.json | 96 - packages/auth/public/favicon.ico | Bin 15086 -> 0 bytes packages/auth/public/index.html | 52 - packages/auth/public/index_test.html | 60 - packages/auth/secretProps.template.json | 4 - packages/auth/setupTests.js | 10 - packages/auth/src/App.js | 75 - packages/auth/src/App.test.js | 58 - packages/auth/src/index.js | 23 - packages/auth/src/mockedToken.js | 16 - packages/auth/src/styles.scss | 12 - packages/auth/src/useCommunication.js | 43 - packages/auth/tailwind.config.js | 30 - packages/dashboard/.gitignore | 3 - packages/dashboard/LICENSE | 201 - packages/dashboard/README.md | 6 - packages/dashboard/__mocks__/client.js | 9 - packages/dashboard/__mocks__/fileMock.js | 6 - packages/dashboard/__mocks__/styleMock.js | 6 - packages/dashboard/babel.config.js | 13 - packages/dashboard/esbuild.config.js | 206 - packages/dashboard/jest.config.js | 19 - packages/dashboard/package-lock.json | 10211 ------------- packages/dashboard/package.json | 76 - packages/dashboard/postcss.config.js | 8 - packages/dashboard/public/favicon.ico | Bin 15086 -> 0 bytes packages/dashboard/public/index.html | 47 - packages/dashboard/setupTests.js | 10 - packages/dashboard/src/App.css | 45 - packages/dashboard/src/App.js | 66 - packages/dashboard/src/App.test.js | 31 - .../dashboard/src/assets/images/AWS_logo.svg | 6 - .../src/assets/images/CCloud_Logo_light.svg | 6 - .../assets/images/Microsoft_Azure_logo.svg | 6 - .../src/assets/images/Reference_Icon.svg | 20 - .../src/assets/images/Region_Icon_sm.svg | 31 - .../src/assets/images/Service_Icon.svg | 29 - .../src/assets/images/background_center.png | Bin 172063 -> 0 bytes .../src/assets/images/background_footer.jpg | Bin 36628 -> 0 bytes .../src/assets/images/background_footer.svg | 6 - .../src/assets/images/background_header.png | Bin 396686 -> 0 bytes .../dashboard/src/assets/images/cloud.png | Bin 29535 -> 0 bytes .../src/assets/images/docu_shape.svg | 8 - .../src/assets/images/flag_australia.svg | 15 - .../src/assets/images/flag_brazil.svg | 145 - .../src/assets/images/flag_canada.svg | 12 - .../src/assets/images/flag_ccloud.svg | 22 - .../src/assets/images/flag_china.svg | 11 - .../src/assets/images/flag_germany.svg | 12 - .../src/assets/images/flag_japan.svg | 11 - .../src/assets/images/flag_netherlands.svg | 12 - .../src/assets/images/flag_russia.svg | 12 - .../src/assets/images/flag_saudiarabia.svg | 22 - .../assets/images/flag_unitedarabempire.svg | 19 - .../dashboard/src/assets/images/flag_usa.svg | 24 - .../src/assets/images/icon_documentation.svg | 6 - .../src/assets/images/icon_slack.svg | 6 - .../src/assets/images/icon_support.svg | 6 - packages/dashboard/src/assets/images/map.svg | 4421 ------ .../dashboard/src/assets/images/sap_logo.svg | 6 - .../components/landingpage/DomainSelect.js | 105 - .../components/landingpage/LoginOverlay.js | 138 - .../components/landingpage/RegionSelect.js | 85 - .../landingpage/WorldMapQASelect.js | 50 - .../src/components/layout/PageFooter.js | 143 - .../src/components/layout/PageHead.js | 45 - packages/dashboard/src/index.js | 17 - .../src/lib/hooks/useDynamicScript.js | 83 - .../src/lib/hooks/useMicroFrontend.js | 71 - packages/dashboard/src/lib/pages-loader.js | 13 - packages/dashboard/src/lib/utils.js | 47 - packages/dashboard/src/logo.svg | 12 - packages/dashboard/src/pages/home.js | 122 - packages/dashboard/src/store.js | 224 - packages/dashboard/src/styles.scss | 62 - packages/dashboard/tailwind.config.js | 40 - packages/playground/.gitignore | 3 - packages/playground/LICENSE | 201 - packages/playground/README.md | 3 - packages/playground/__mocks__/client.js | 9 - packages/playground/__mocks__/fileMock.js | 6 - packages/playground/__mocks__/styleMock.js | 6 - packages/playground/babel.config.js | 13 - packages/playground/esbuild.config.js | 216 - packages/playground/jest.config.js | 21 - packages/playground/package-lock.json | 11408 --------------- packages/playground/package.json | 86 - packages/playground/public/favicon-16x16.png | Bin 691 -> 0 bytes packages/playground/public/favicon-32x32.png | Bin 1048 -> 0 bytes packages/playground/public/favicon.ico | Bin 15086 -> 0 bytes packages/playground/public/index.html | 49 - packages/playground/secretProps.template.json | 3 - packages/playground/setupTests.js | 10 - packages/playground/src/App.js | 39 - packages/playground/src/App.test.js | 29 - packages/playground/src/AppContent.js | 91 - packages/playground/src/assets/.gitkeep | 0 packages/playground/src/components/Error.jsx | 25 - .../playground/src/components/HintLoading.js | 31 - .../playground/src/components/Preview.jsx | 61 - .../src/components/PreviewShell.jsx | 21 - .../src/components/StoreProvider.js | 24 - packages/playground/src/hooks/.gitkeep | 0 packages/playground/src/index.js | 17 - packages/playground/src/lib/executeCode.js | 46 - packages/playground/src/lib/store.js | 27 - packages/playground/src/styles.scss | 9 - packages/playground/tailwind.config.js | 30 - packages/user-activity/LICENSE | 201 - packages/user-activity/README.md | 37 - packages/user-activity/__mocks__/client.js | 9 - packages/user-activity/__mocks__/fileMock.js | 6 - packages/user-activity/__mocks__/styleMock.js | 6 - packages/user-activity/babel.config.js | 13 - packages/user-activity/esbuild.config.js | 206 - packages/user-activity/jest.config.js | 19 - packages/user-activity/package-lock.json | 10156 ------------- packages/user-activity/package.json | 71 - packages/user-activity/public/favicon.ico | Bin 15086 -> 0 bytes packages/user-activity/public/index.html | 47 - .../user-activity/secretProps.template.json | 4 - packages/user-activity/setupTests.js | 10 - packages/user-activity/src/App.js | 26 - packages/user-activity/src/App.test.js | 26 - .../src/hooks/useCommunication.js | 29 - .../user-activity/src/hooks/useIdleTimer.js | 96 - packages/user-activity/src/index.js | 17 - packages/user-activity/src/store.js | 18 - packages/user-activity/src/styles.scss | 20 - packages/user-activity/tailwind.config.js | 30 - packages/volta/jest.config.js | 2 +- packages/volta/package-lock.json | 151 +- packages/volta/package.json | 21 +- packages/volta/src/App.js | 11 +- packages/volta/src/App.test.js | 2 +- packages/volta/src/AppContent.js | 5 +- packages/volta/src/actions.js | 2 +- .../volta/src/components/AddNewSSOButton.js | 2 +- packages/volta/src/components/Avatar.js | 2 +- packages/volta/src/components/CAsList.js | 2 +- packages/volta/src/components/CAsListItem.js | 2 +- .../volta/src/components/CertificateList.js | 6 +- .../src/components/CertificateListItem.js | 9 +- .../volta/src/components/CustomAppShell.js | 4 +- .../volta/src/components/CustomIntroBox.js | 2 +- .../volta/src/components/CustomPanelBody.js | 4 +- packages/volta/src/components/HeaderUser.js | 2 +- packages/volta/src/components/HintLoading.js | 2 +- packages/volta/src/components/HintNotFound.js | 2 +- .../src/components/InlineConfirmRemove.js | 7 +- .../volta/src/components/NewCertificate.js | 4 +- .../src/components/NewCertificateForm.js | 4 +- .../NewCertificateFormPanelFooter.js | 2 +- .../src/components/NewCertificateResults.js | 7 +- packages/volta/src/components/WelcomeView.js | 2 +- packages/volta/src/hooks/useUrlState.js | 2 +- packages/volta/tailwind.config.js | 4 +- packages/whois/jest.config.js | 2 +- packages/whois/package-lock.json | 325 +- packages/whois/package.json | 12 +- packages/whois/src/App.js | 8 +- packages/whois/src/ResultItem.js | 2 +- packages/whois/src/Results.js | 2 +- packages/whois/src/Search.js | 2 +- packages/whois/src/bootstrap.js | 2 +- packages/whois/src/styles.scss | 13 - packages/whois/tailwind.config.js | 4 +- packages/widget-loader/LICENSE | 201 - packages/widget-loader/README.md | 228 - packages/widget-loader/esbuild.config.js | 82 - packages/widget-loader/package-lock.json | 7395 ---------- packages/widget-loader/package.json | 84 - packages/widget-loader/public/index.html | 167 - packages/widget-loader/src/index.js | 186 - packages/widget-loader/src/index.test.js | 32 - 1155 files changed, 714 insertions(+), 159058 deletions(-) delete mode 100644 .github/workflows/block-deprecated_assets.yml delete mode 100644 apps_deprecated/exampleapp/LICENSE delete mode 100644 apps_deprecated/exampleapp/README.md delete mode 100644 apps_deprecated/exampleapp/__mocks__/client.js delete mode 100644 apps_deprecated/exampleapp/__mocks__/fileMock.js delete mode 100644 apps_deprecated/exampleapp/__mocks__/styleMock.js delete mode 100644 apps_deprecated/exampleapp/babel.config.js delete mode 100644 apps_deprecated/exampleapp/db.json delete mode 100644 apps_deprecated/exampleapp/esbuild.config.js delete mode 100644 apps_deprecated/exampleapp/jest.config.js delete mode 100644 apps_deprecated/exampleapp/package.json delete mode 100644 apps_deprecated/exampleapp/public/favicon.ico delete mode 100644 apps_deprecated/exampleapp/public/index.html delete mode 100644 apps_deprecated/exampleapp/setupTests.js delete mode 100644 apps_deprecated/exampleapp/src/App.jsx delete mode 100644 apps_deprecated/exampleapp/src/App.test.js delete mode 100644 apps_deprecated/exampleapp/src/components/AppContent.js delete mode 100644 apps_deprecated/exampleapp/src/components/AsyncWorker.jsx delete mode 100644 apps_deprecated/exampleapp/src/components/ModalManager.js delete mode 100644 apps_deprecated/exampleapp/src/components/PanelManager.js delete mode 100644 apps_deprecated/exampleapp/src/components/Playground.js delete mode 100644 apps_deprecated/exampleapp/src/components/StoreProvider.jsx delete mode 100644 apps_deprecated/exampleapp/src/components/TestModal.js delete mode 100644 apps_deprecated/exampleapp/src/components/WelcomeView.js delete mode 100644 apps_deprecated/exampleapp/src/components/auth/Avatar.js delete mode 100644 apps_deprecated/exampleapp/src/components/auth/HeaderUser.js delete mode 100644 apps_deprecated/exampleapp/src/components/peaks/Peaks.js delete mode 100644 apps_deprecated/exampleapp/src/components/peaks/PeaksEdit.js delete mode 100644 apps_deprecated/exampleapp/src/components/peaks/PeaksList.js delete mode 100644 apps_deprecated/exampleapp/src/components/peaks/PeaksListItem.js delete mode 100644 apps_deprecated/exampleapp/src/components/peaks/PeaksNew.js delete mode 100644 apps_deprecated/exampleapp/src/components/shared/HintLoading.js delete mode 100644 apps_deprecated/exampleapp/src/components/shared/HintNotFound.jsx delete mode 100644 apps_deprecated/exampleapp/src/hooks/useEndlessScrollList.js delete mode 100644 apps_deprecated/exampleapp/src/hooks/useQueryClientFn.js delete mode 100644 apps_deprecated/exampleapp/src/hooks/useUrlState.js delete mode 100644 apps_deprecated/exampleapp/src/img/app_bg_example.svg delete mode 100644 apps_deprecated/exampleapp/src/index.js delete mode 100644 apps_deprecated/exampleapp/src/lib/store/createAuthSlice.js delete mode 100644 apps_deprecated/exampleapp/src/lib/store/createGlobalsSlice.js delete mode 100644 apps_deprecated/exampleapp/src/lib/store/index.js delete mode 100644 apps_deprecated/exampleapp/src/styles.scss delete mode 100644 apps_deprecated/exampleapp/tailwind.config.js delete mode 100644 apps_deprecated/greenhouse-management/LICENSE delete mode 100644 apps_deprecated/greenhouse-management/README.md delete mode 100644 apps_deprecated/greenhouse-management/__mocks__/client.js delete mode 100644 apps_deprecated/greenhouse-management/__mocks__/fileMock.js delete mode 100644 apps_deprecated/greenhouse-management/__mocks__/styleMock.js delete mode 100644 apps_deprecated/greenhouse-management/babel.config.js delete mode 100644 apps_deprecated/greenhouse-management/esbuild.config.js delete mode 100644 apps_deprecated/greenhouse-management/jest.config.js delete mode 100644 apps_deprecated/greenhouse-management/package.json delete mode 100644 apps_deprecated/greenhouse-management/public/favicon-16x16.png delete mode 100644 apps_deprecated/greenhouse-management/public/favicon-32x32.png delete mode 100644 apps_deprecated/greenhouse-management/public/favicon.ico delete mode 100644 apps_deprecated/greenhouse-management/public/index.html delete mode 100644 apps_deprecated/greenhouse-management/secretProps.template.json delete mode 100644 apps_deprecated/greenhouse-management/setupTests.js delete mode 100644 apps_deprecated/greenhouse-management/src/App.js delete mode 100644 apps_deprecated/greenhouse-management/src/App.test.js delete mode 100644 apps_deprecated/greenhouse-management/src/AppContent.js delete mode 100644 apps_deprecated/greenhouse-management/src/assets/.gitkeep delete mode 100644 apps_deprecated/greenhouse-management/src/assets/juno-danger.svg delete mode 100644 apps_deprecated/greenhouse-management/src/assets/map.svg delete mode 100644 apps_deprecated/greenhouse-management/src/assets/rocket.gif delete mode 100644 apps_deprecated/greenhouse-management/src/components/AsyncWorker.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/Auth.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/OrgInfo.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/Plugin.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/PluginContainer.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/SideNav.js delete mode 100644 apps_deprecated/greenhouse-management/src/components/StoreProvider.js delete mode 100644 apps_deprecated/greenhouse-management/src/components/UrlState.jsx delete mode 100644 apps_deprecated/greenhouse-management/src/components/shared/HintLoading.js delete mode 100644 apps_deprecated/greenhouse-management/src/hooks/.gitkeep delete mode 100644 apps_deprecated/greenhouse-management/src/hooks/useCommunication.js delete mode 100644 apps_deprecated/greenhouse-management/src/hooks/useUrlState.js delete mode 100644 apps_deprecated/greenhouse-management/src/index.js delete mode 100644 apps_deprecated/greenhouse-management/src/lib/helpers.js delete mode 100644 apps_deprecated/greenhouse-management/src/lib/store.js delete mode 100644 apps_deprecated/greenhouse-management/src/styles.scss delete mode 100644 apps_deprecated/greenhouse-management/tailwind.config.js delete mode 100644 apps_deprecated/greenhouse/.gitignore delete mode 100644 apps_deprecated/greenhouse/LICENSE delete mode 100644 apps_deprecated/greenhouse/README.md delete mode 100644 apps_deprecated/greenhouse/__mocks__/client.js delete mode 100644 apps_deprecated/greenhouse/__mocks__/fileMock.js delete mode 100644 apps_deprecated/greenhouse/__mocks__/styleMock.js delete mode 100644 apps_deprecated/greenhouse/babel.config.js delete mode 100644 apps_deprecated/greenhouse/esbuild.config.js delete mode 100644 apps_deprecated/greenhouse/jest.config.js delete mode 100644 apps_deprecated/greenhouse/package.json delete mode 100644 apps_deprecated/greenhouse/public/android-chrome-192x192.png delete mode 100644 apps_deprecated/greenhouse/public/android-chrome-512x512.png delete mode 100644 apps_deprecated/greenhouse/public/apple-touch-icon.png delete mode 100644 apps_deprecated/greenhouse/public/favicon.ico delete mode 100644 apps_deprecated/greenhouse/public/favicon.svg delete mode 100644 apps_deprecated/greenhouse/public/index.html delete mode 100644 apps_deprecated/greenhouse/secretProps.template.json delete mode 100644 apps_deprecated/greenhouse/setupTests.js delete mode 100644 apps_deprecated/greenhouse/src/Shell.js delete mode 100644 apps_deprecated/greenhouse/src/Shell.test.js delete mode 100644 apps_deprecated/greenhouse/src/actions.js delete mode 100644 apps_deprecated/greenhouse/src/assets/ccloud_shape.svg delete mode 100644 apps_deprecated/greenhouse/src/assets/greenhouse_logo.svg delete mode 100644 apps_deprecated/greenhouse/src/assets/juno_default_app.svg delete mode 100644 apps_deprecated/greenhouse/src/assets/juno_doop.svg delete mode 100644 apps_deprecated/greenhouse/src/assets/juno_heureka.svg delete mode 100644 apps_deprecated/greenhouse/src/assets/juno_supernova.svg delete mode 100644 apps_deprecated/greenhouse/src/components/AsyncWorker.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/Auth.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/Avatar.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/NotificationsContainer.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/Plugin.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/PluginContainer.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/StoreProvider.jsx delete mode 100644 apps_deprecated/greenhouse/src/components/layout/ShellLayout.js delete mode 100644 apps_deprecated/greenhouse/src/components/layout/ShellLayout.test.js delete mode 100644 apps_deprecated/greenhouse/src/components/nav/PluginNav.js delete mode 100644 apps_deprecated/greenhouse/src/components/shared/HintLoading.js delete mode 100644 apps_deprecated/greenhouse/src/hooks/useApi.js delete mode 100644 apps_deprecated/greenhouse/src/hooks/useCommunication.js delete mode 100644 apps_deprecated/greenhouse/src/hooks/useUrlState.js delete mode 100644 apps_deprecated/greenhouse/src/index.js delete mode 100644 apps_deprecated/greenhouse/src/lib/helpers.js delete mode 100644 apps_deprecated/greenhouse/src/lib/plugin.js delete mode 100644 apps_deprecated/greenhouse/src/lib/plugin.test.js delete mode 100644 apps_deprecated/greenhouse/src/lib/store/createAuthDataSlice.js delete mode 100644 apps_deprecated/greenhouse/src/lib/store/createGlobalsSlice.js delete mode 100644 apps_deprecated/greenhouse/src/lib/store/index.js delete mode 100644 apps_deprecated/greenhouse/src/styles.scss delete mode 100644 apps_deprecated/greenhouse/tailwind.config.js delete mode 100644 apps_deprecated/heureka/LICENSE delete mode 100644 apps_deprecated/heureka/README.md delete mode 100644 apps_deprecated/heureka/__mocks__/client.js delete mode 100644 apps_deprecated/heureka/__mocks__/fileMock.js delete mode 100644 apps_deprecated/heureka/__mocks__/styleMock.js delete mode 100644 apps_deprecated/heureka/babel.config.js delete mode 100644 apps_deprecated/heureka/esbuild.config.js delete mode 100644 apps_deprecated/heureka/jest.config.js delete mode 100644 apps_deprecated/heureka/package.json delete mode 100644 apps_deprecated/heureka/public/favicon.ico delete mode 100644 apps_deprecated/heureka/public/index.html delete mode 100644 apps_deprecated/heureka/setupTests.js delete mode 100644 apps_deprecated/heureka/src/App.js delete mode 100644 apps_deprecated/heureka/src/App.test.js delete mode 100644 apps_deprecated/heureka/src/actions.js delete mode 100644 apps_deprecated/heureka/src/components/AsyncWorker.jsx delete mode 100644 apps_deprecated/heureka/src/components/StoreProvider.jsx delete mode 100644 apps_deprecated/heureka/src/components/backup/AppContainer.js delete mode 100644 apps_deprecated/heureka/src/components/backup/AppRouter.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Avatar.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Breadcrumb.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ChangesLogDetail.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ChangesLogList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ChangesLogListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ComponentDetail.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Components.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ComponentsList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ComponentsListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/CustomBadge.js delete mode 100644 apps_deprecated/heureka/src/components/backup/CustomPageHeader.js delete mode 100644 apps_deprecated/heureka/src/components/backup/EvidenceNew.js delete mode 100644 apps_deprecated/heureka/src/components/backup/EvidencesList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/EvidencesListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/FilterToolbar.js delete mode 100644 apps_deprecated/heureka/src/components/backup/FilterToolbarCore.js delete mode 100644 apps_deprecated/heureka/src/components/backup/FilterToolbarStore.js delete mode 100644 apps_deprecated/heureka/src/components/backup/HeaderUser.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Home.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PackagesList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PackagesListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Pagination.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PatchLogDetail.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PatchLogNew.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PatchLogsList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/PatchLogsListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ServiceDetail.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Services.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ServicesList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/ServicesListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/SupportGroups.js delete mode 100644 apps_deprecated/heureka/src/components/backup/SupportGroupsList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/UserDetail.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Users.js delete mode 100644 apps_deprecated/heureka/src/components/backup/UsersList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/UsersListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/Vulnerabilities.js delete mode 100644 apps_deprecated/heureka/src/components/backup/VulnerabilitiesList.js delete mode 100644 apps_deprecated/heureka/src/components/backup/VulnerabilitiesListItem.js delete mode 100644 apps_deprecated/heureka/src/components/backup/VulnerabilitiesOverview.js delete mode 100644 apps_deprecated/heureka/src/components/backup/VulnerabilitiyDetails.js delete mode 100644 apps_deprecated/heureka/src/components/backup/VulnerabilityBadge.js delete mode 100644 apps_deprecated/heureka/src/components/backup/WelcomeView.js delete mode 100644 apps_deprecated/heureka/src/components/filters/FilterPills.jsx delete mode 100644 apps_deprecated/heureka/src/components/filters/FilterSelect.jsx delete mode 100644 apps_deprecated/heureka/src/components/filters/Filters.jsx delete mode 100644 apps_deprecated/heureka/src/components/services/ServicesList.jsx delete mode 100644 apps_deprecated/heureka/src/components/services/ServicesListController.jsx delete mode 100644 apps_deprecated/heureka/src/components/services/ServicesListItem.js delete mode 100644 apps_deprecated/heureka/src/components/services/ServicesTab.jsx delete mode 100644 apps_deprecated/heureka/src/components/shared/HintLoading.jsx delete mode 100644 apps_deprecated/heureka/src/components/shared/HintNotFound.jsx delete mode 100644 apps_deprecated/heureka/src/components/shared/Pagination.jsx delete mode 100644 apps_deprecated/heureka/src/components/shared/PaginationV2.jsx delete mode 100644 apps_deprecated/heureka/src/components/tabs/TabContext.jsx delete mode 100644 apps_deprecated/heureka/src/components/tabs/TabPanel.jsx delete mode 100644 apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesList.jsx delete mode 100644 apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListController.jsx delete mode 100644 apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListItem.jsx delete mode 100644 apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesTab.jsx delete mode 100644 apps_deprecated/heureka/src/helpers.js delete mode 100644 apps_deprecated/heureka/src/helpers.test.js delete mode 100644 apps_deprecated/heureka/src/hooks/useCommunication.js delete mode 100644 apps_deprecated/heureka/src/hooks/useQueryClientFn.js delete mode 100644 apps_deprecated/heureka/src/hooks/useUrlState.js delete mode 100644 apps_deprecated/heureka/src/img/app_bg_example.svg delete mode 100644 apps_deprecated/heureka/src/index.js delete mode 100644 apps_deprecated/heureka/src/lib/queries/serviceFilters.js delete mode 100644 apps_deprecated/heureka/src/lib/queries/services.js delete mode 100644 apps_deprecated/heureka/src/lib/queries/vulnerabilityMatches.js delete mode 100644 apps_deprecated/heureka/src/lib/store.js delete mode 100644 apps_deprecated/heureka/src/queries.js delete mode 100644 apps_deprecated/heureka/src/styles.js delete mode 100644 apps_deprecated/heureka/src/styles.scss delete mode 100644 apps_deprecated/heureka/tailwind.config.js delete mode 100644 apps_deprecated/supernova/LICENSE delete mode 100644 apps_deprecated/supernova/README.md delete mode 100644 apps_deprecated/supernova/__mocks__/client.js delete mode 100644 apps_deprecated/supernova/__mocks__/fileMock.js delete mode 100644 apps_deprecated/supernova/__mocks__/styleMock.js delete mode 100644 apps_deprecated/supernova/babel.config.js delete mode 100644 apps_deprecated/supernova/esbuild.config.js delete mode 100644 apps_deprecated/supernova/jest.config.js delete mode 100644 apps_deprecated/supernova/package.json delete mode 100644 apps_deprecated/supernova/public/favicon.ico delete mode 100644 apps_deprecated/supernova/public/index.html delete mode 100644 apps_deprecated/supernova/public/index_test.html delete mode 100644 apps_deprecated/supernova/setupTests.js delete mode 100644 apps_deprecated/supernova/src/App.jsx delete mode 100644 apps_deprecated/supernova/src/App.test.js delete mode 100644 apps_deprecated/supernova/src/AppContent.jsx delete mode 100644 apps_deprecated/supernova/src/api/apiService.js delete mode 100644 apps_deprecated/supernova/src/api/client.js delete mode 100644 apps_deprecated/supernova/src/components/AsyncWorker.jsx delete mode 100644 apps_deprecated/supernova/src/components/Avatar.jsx delete mode 100644 apps_deprecated/supernova/src/components/CustomAppShell.jsx delete mode 100644 apps_deprecated/supernova/src/components/HeaderUser.jsx delete mode 100644 apps_deprecated/supernova/src/components/WelcomeView.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/Alert.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/AlertDetail.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/AlertSilences.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/AlertStatus.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/AlertsList.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertDescription.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertIcon.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertLabels.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertLinks.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertRegion.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertSilencesList.jsx delete mode 100644 apps_deprecated/supernova/src/components/alerts/shared/AlertTimestamp.jsx delete mode 100644 apps_deprecated/supernova/src/components/filters/FilterPills.jsx delete mode 100644 apps_deprecated/supernova/src/components/filters/FilterSelect.jsx delete mode 100644 apps_deprecated/supernova/src/components/filters/Filters.jsx delete mode 100644 apps_deprecated/supernova/src/components/filters/PredefinedFilters.jsx delete mode 100644 apps_deprecated/supernova/src/components/regions/Region.jsx delete mode 100644 apps_deprecated/supernova/src/components/regions/RegionSeverity.jsx delete mode 100644 apps_deprecated/supernova/src/components/regions/RegionsList.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/SilenceMatchers.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/SilenceNew.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/SilenceNewAdvanced.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/SilenceScheduled.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/SilenceScheduledWrapper.jsx delete mode 100644 apps_deprecated/supernova/src/components/silences/silenceHelpers.js delete mode 100644 apps_deprecated/supernova/src/components/silences/silenceHelpers.test.js delete mode 100644 apps_deprecated/supernova/src/components/silences/silenceScheduledHelpers.js delete mode 100644 apps_deprecated/supernova/src/components/status/StatusBar.jsx delete mode 100644 apps_deprecated/supernova/src/helpers.js delete mode 100644 apps_deprecated/supernova/src/hooks/useAlertmanagerAPI.js delete mode 100644 apps_deprecated/supernova/src/hooks/useAppStore.js delete mode 100644 apps_deprecated/supernova/src/hooks/useCommunication.js delete mode 100644 apps_deprecated/supernova/src/hooks/useUrlState.js delete mode 100644 apps_deprecated/supernova/src/index.js delete mode 100644 apps_deprecated/supernova/src/lib/createAlertsSlice.js delete mode 100644 apps_deprecated/supernova/src/lib/createAlertsSlice.test.js delete mode 100644 apps_deprecated/supernova/src/lib/createAuthDataSlice.js delete mode 100644 apps_deprecated/supernova/src/lib/createFiltersSlice.js delete mode 100644 apps_deprecated/supernova/src/lib/createFiltersSlice.test.js delete mode 100644 apps_deprecated/supernova/src/lib/createGlobalsSlice.js delete mode 100644 apps_deprecated/supernova/src/lib/createSilencesSlice.js delete mode 100644 apps_deprecated/supernova/src/lib/createSilencesSlice.test.js delete mode 100644 apps_deprecated/supernova/src/lib/createUserActivitySlice.js delete mode 100644 apps_deprecated/supernova/src/lib/fakeObjects.js delete mode 100644 apps_deprecated/supernova/src/lib/utils.js delete mode 100644 apps_deprecated/supernova/src/styles.scss delete mode 100644 apps_deprecated/supernova/src/workers/alerts.js delete mode 100644 apps_deprecated/supernova/src/workers/silences.js delete mode 100644 apps_deprecated/supernova/tailwind.config.js delete mode 100644 apps_deprecated/template/.gitignore delete mode 100644 apps_deprecated/template/LICENSE delete mode 100644 apps_deprecated/template/README.md delete mode 100644 apps_deprecated/template/__mocks__/client.js delete mode 100644 apps_deprecated/template/__mocks__/fileMock.js delete mode 100644 apps_deprecated/template/__mocks__/styleMock.js delete mode 100644 apps_deprecated/template/babel.config.js delete mode 100644 apps_deprecated/template/esbuild.config.js delete mode 100644 apps_deprecated/template/jest.config.js delete mode 100644 apps_deprecated/template/package.json delete mode 100644 apps_deprecated/template/public/favicon-16x16.png delete mode 100644 apps_deprecated/template/public/favicon-32x32.png delete mode 100644 apps_deprecated/template/public/favicon.ico delete mode 100644 apps_deprecated/template/public/index.html delete mode 100644 apps_deprecated/template/secretProps.template.json delete mode 100644 apps_deprecated/template/setupTests.js delete mode 100644 apps_deprecated/template/src/App.js delete mode 100644 apps_deprecated/template/src/App.test.js delete mode 100644 apps_deprecated/template/src/AppContent.js delete mode 100644 apps_deprecated/template/src/assets/.gitkeep delete mode 100644 apps_deprecated/template/src/components/StoreProvider.js delete mode 100644 apps_deprecated/template/src/hooks/.gitkeep delete mode 100644 apps_deprecated/template/src/index.js delete mode 100644 apps_deprecated/template/src/lib/store/createGlobalsSlice.js delete mode 100644 apps_deprecated/template/src/lib/store/createGlobalsSlice.test.js delete mode 100644 apps_deprecated/template/src/lib/store/index.js delete mode 100644 apps_deprecated/template/src/styles.scss delete mode 100644 apps_deprecated/template/tailwind.config.js delete mode 100644 libs_deprecated/communicator/.gitignore delete mode 100644 libs_deprecated/communicator/LICENSE delete mode 100644 libs_deprecated/communicator/README.md delete mode 100644 libs_deprecated/communicator/dev/build.js delete mode 100644 libs_deprecated/communicator/dev/build.js.map delete mode 100644 libs_deprecated/communicator/dev/index.html delete mode 100644 libs_deprecated/communicator/dev/index.js delete mode 100644 libs_deprecated/communicator/esbuild.config.js delete mode 100644 libs_deprecated/communicator/package.json delete mode 100644 libs_deprecated/communicator/src/index.js delete mode 100644 libs_deprecated/communicator/src/index.test.js delete mode 100644 libs_deprecated/juno-ui-components/.gitignore delete mode 100644 libs_deprecated/juno-ui-components/.npmignore delete mode 100644 libs_deprecated/juno-ui-components/.storybook/.babelrc delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/Decorator.jsx delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/DocsContainer.jsx delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/README.md delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/ThemeToggle.jsx delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/constants.js delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/manager.js delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/preview.js delete mode 100644 libs_deprecated/juno-ui-components/.storybook/juno-addon/themes.js delete mode 100644 libs_deprecated/juno-ui-components/.storybook/main.js delete mode 100644 libs_deprecated/juno-ui-components/.storybook/preview.js delete mode 100644 libs_deprecated/juno-ui-components/LICENSE delete mode 100644 libs_deprecated/juno-ui-components/README.md delete mode 100644 libs_deprecated/juno-ui-components/babel.config.json delete mode 100644 libs_deprecated/juno-ui-components/lib/variables.scss delete mode 100644 libs_deprecated/juno-ui-components/package.json delete mode 100644 libs_deprecated/juno-ui-components/postcss.config.js delete mode 100644 libs_deprecated/juno-ui-components/rollup.config.js delete mode 100644 libs_deprecated/juno-ui-components/setupTests.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppBody/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppIntro/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/AppShellProvider/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Badge/Badge.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Badge/Badge.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Badge/Badge.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Badge/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Box/Box.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Box/Box.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Box/Box.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Box/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Breadcrumb/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Button/Button.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Button/Button.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Button/Button.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Button/button.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/Button/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ButtonRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Checkbox/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxGroup/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CheckboxRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Code/Code.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Code/Code.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Code/Code.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Code/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/CodeBlock/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBox/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ComboBoxOption/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Container/Container.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Container/Container.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Container/Container.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Container/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentArea/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentContainer/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContentHeading/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ContextMenu/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGrid/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridFoot/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataGridToolbar/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataList/DataList.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataList/DataList.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataList/DataList.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataList/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DataListRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/DateTimePicker/datetimepicker.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/DateTimePicker/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterInput/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FilterPill/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Filters/Filters.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Filters/Filters.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Filters/Filters.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Filters/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Form/Form.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Form/Form.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Form/Form.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Form/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormHint/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/FormSection/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Grid/Grid.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Grid/Grid.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Grid/Grid.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Grid/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridColumn/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/GridRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/Icon.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/Icon.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/Icon.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/home_sharp.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/juno-danger.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_critical.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_high.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_low.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_medium.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/icons/place.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/Icon/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/InputGroup/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/InputGroup/input-group.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/IntroBox/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/JsonViewer/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/JsonViewer/themes.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Label/Label.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Label/Label.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Label/Label.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Label/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/LoadingIndicator/LoadingIndicator.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/LoadingIndicator/LoadingIndicator.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/LoadingIndicator/LoadingIndicator.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/LoadingIndicator/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/LoadingIndicator/loading-indicator.svg delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainer/MainContainer.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainer/MainContainer.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainer/MainContainer.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainer/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainerInner/MainContainerInner.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainerInner/MainContainerInner.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainContainerInner/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainTabs/MainTabs.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainTabs/MainTabs.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainTabs/MainTabs.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MainTabs/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Menu/Menu.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Menu/Menu.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Menu/Menu.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Menu/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuItem/MenuItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuItem/MenuItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuItem/MenuItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuSection/MenuSection.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuSection/MenuSection.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuSection/MenuSection.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/MenuSection/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Message/Message.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Message/Message.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Message/Message.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Message/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Modal/Modal.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Modal/Modal.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Modal/Modal.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Modal/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ModalFooter/ModalFooter.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ModalFooter/ModalFooter.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ModalFooter/ModalFooter.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ModalFooter/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelect/NativeSelect.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelect/NativeSelect.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelect/NativeSelect.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelect/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOption/NativeSelectOption.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOption/NativeSelectOption.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOption/SelectOption.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOption/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOptionGroup/NativeSelectOptionGroup.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NativeSelectOptionGroup/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Navigation/Navigation.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Navigation/Navigation.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Navigation/Navigation.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Navigation/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NavigationItem/NavigationItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NavigationItem/NavigationItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NavigationItem/NavigationItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/NavigationItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageFooter/PageFooter.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageFooter/PageFooter.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageFooter/PageFooter.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageFooter/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageHeader/PageHeader.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageHeader/PageHeader.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageHeader/PageHeader.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PageHeader/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pagination/Pagination.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pagination/Pagination.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pagination/Pagination.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pagination/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Panel/Panel.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Panel/Panel.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Panel/Panel.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Panel/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelBody/PanelBody.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelBody/PanelBody.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelBody/PanelBody.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelBody/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelFooter/PanelFooter.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelFooter/PanelFooter.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelFooter/PanelFooter.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PanelFooter/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pill/Pill.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pill/Pill.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pill/Pill.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Pill/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PortalProvider/PortalProvider.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PortalProvider/PortalProvider.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PortalProvider/PortalProvider.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/PortalProvider/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Radio/Radio.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Radio/Radio.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Radio/Radio.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Radio/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioGroup/RadioGroup.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioGroup/RadioGroup.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioGroup/RadioGroup.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioGroup/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioRow/RadioRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioRow/RadioRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioRow/RadioRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/RadioRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SearchInput/SearchInput.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SearchInput/SearchInput.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SearchInput/SearchInput.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SearchInput/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SearchInput/searchinput.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/Select/Select.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Select/Select.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Select/Select.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Select/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Select/select.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectDivider/SelectDivider.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectDivider/SelectDivider.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectDivider/SelectDivider.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectDivider/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectOption/SelectOption.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectOption/SelectOption.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectOption/SelectOption.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectOption/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectRow/SelectRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectRow/SelectRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectRow/SelectRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SelectRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ShadowRoot/ShadowRoot.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ShadowRoot/ShadowRoot.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/ShadowRoot/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigation/SideNavigation.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigation/SideNavigation.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigation/SideNavigation.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigation/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigationItem/SideNavigationItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigationItem/SideNavigationItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigationItem/SideNavigationItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SideNavigationItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Spinner/Spinner.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Spinner/Spinner.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Spinner/Spinner.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Spinner/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Stack/Stack.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Stack/Stack.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Stack/Stack.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Stack/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/Fonts.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/GlobalStyles.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/StyleProvider.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/StyleProvider.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/StyleProvider.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/StyleProvider/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Switch/Switch.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Switch/Switch.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Switch/Switch.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Switch/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SwitchRow/SwitchRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SwitchRow/SwitchRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SwitchRow/SwitchRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/SwitchRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tab/Tab.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tab/Tab.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tab/Tab.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tab/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabList/TabList.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabList/TabList.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabList/TabList.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabList/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigation/TabNavigation.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigation/TabNavigation.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigation/TabNavigation.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigation/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigationItem/TabNavigationItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigationItem/TabNavigationItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigationItem/TabNavigationItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabNavigationItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabPanel/TabPanel.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabPanel/TabPanel.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabPanel/TabPanel.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TabPanel/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tabs/Tabs.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tabs/Tabs.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tabs/Tabs.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tabs/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInput/TextInput.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInput/TextInput.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInput/TextInput.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInput/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInput/textinput.scss delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInputRow/TextInputRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInputRow/TextInputRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInputRow/TextInputRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextInputRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Textarea/Textarea.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Textarea/Textarea.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Textarea/Textarea.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Textarea/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextareaRow/TextareaRow.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextareaRow/TextareaRow.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextareaRow/TextareaRow.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TextareaRow/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Toast/Toast.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Toast/Toast.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Toast/Toast.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Toast/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tooltip/Tooltip.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tooltip/Tooltip.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tooltip/Tooltip.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tooltip/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/Tooltip/useTooltip.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipContent/TooltipContent.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipContent/TooltipContent.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipContent/TooltipContent.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipContent/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipTrigger/TooltipTrigger.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipTrigger/TooltipTrigger.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipTrigger/TooltipTrigger.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TooltipTrigger/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigation/TopNavigation.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigation/TopNavigation.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigation/TopNavigation.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigation/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.stories.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigationItem/TopNavigationItem.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/TopNavigationItem/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/withDeprecationWarning/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/withDeprecationWarning/withDeprecationWarning.component.js delete mode 100644 libs_deprecated/juno-ui-components/src/components/withDeprecationWarning/withDeprecationWarning.test.js delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/ColorCard.jsx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/ColorPalette.jsx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/JunoColorPalette.jsx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/TailwindColors.js delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/TextColorCard.jsx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/ColorPalette/generateTailwindThemeClassesJson.js delete mode 100644 libs_deprecated/juno-ui-components/src/docs/JunoComponentWrapper/JunoComponentWrapper.jsx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/colors.mdx delete mode 100644 libs_deprecated/juno-ui-components/src/docs/img/Schwan.jpg delete mode 100644 libs_deprecated/juno-ui-components/src/docs/navigation.mdx delete mode 100644 libs_deprecated/juno-ui-components/src/docsHidden/examplePage.mdx delete mode 100644 libs_deprecated/juno-ui-components/src/dummyComponents/DummyComponent.js delete mode 100644 libs_deprecated/juno-ui-components/src/dummyComponents/DummyComponentList.js delete mode 100644 libs_deprecated/juno-ui-components/src/global.scss delete mode 100644 libs_deprecated/juno-ui-components/src/hooks/useTimeout.js delete mode 100644 libs_deprecated/juno-ui-components/src/img/app_bg_example.svg delete mode 100644 libs_deprecated/juno-ui-components/src/img/ccloud_shape.svg delete mode 100644 libs_deprecated/juno-ui-components/src/img/icon_arrow_down.svg delete mode 100644 libs_deprecated/juno-ui-components/src/img/sap_logo.svg delete mode 100644 libs_deprecated/juno-ui-components/src/index.js delete mode 100644 libs_deprecated/juno-ui-components/src/utils.js delete mode 100644 libs_deprecated/juno-ui-components/tailwind.config.js delete mode 100644 libs_deprecated/juno-ui-components/test/__mocks__/styleMock.js delete mode 100644 libs_deprecated/juno-ui-components/test/__mocks__/svg.js delete mode 100644 libs_deprecated/juno-ui-components/test/__mocks__/svgLib.js delete mode 100644 libs_deprecated/messages-provider/LICENSE delete mode 100644 libs_deprecated/messages-provider/README.md delete mode 100644 libs_deprecated/messages-provider/babel.config.json delete mode 100644 libs_deprecated/messages-provider/package.json delete mode 100644 libs_deprecated/messages-provider/rollup.config.js delete mode 100644 libs_deprecated/messages-provider/setupTests.js delete mode 100644 libs_deprecated/messages-provider/src/Messages.js delete mode 100644 libs_deprecated/messages-provider/src/Messages.test.js delete mode 100644 libs_deprecated/messages-provider/src/index.js delete mode 100644 libs_deprecated/messages-provider/src/useMessageStore.js delete mode 100644 libs_deprecated/messages-provider/src/useMessageStore.test.js delete mode 100644 libs_deprecated/oauth/LICENSE delete mode 100644 libs_deprecated/oauth/README.md delete mode 100644 libs_deprecated/oauth/__tests__/__utils__/globalsMock.js delete mode 100644 libs_deprecated/oauth/__tests__/__utils__/idTokenMock.js delete mode 100644 libs_deprecated/oauth/__tests__/__utils__/oidcConfigMock.js delete mode 100644 libs_deprecated/oauth/__tests__/codeFlow.test.js delete mode 100644 libs_deprecated/oauth/__tests__/implicitFlow.test.js delete mode 100644 libs_deprecated/oauth/__tests__/mockedSession.test.js delete mode 100644 libs_deprecated/oauth/__tests__/oidcConfig.test.js delete mode 100644 libs_deprecated/oauth/__tests__/oidcSession.test.js delete mode 100644 libs_deprecated/oauth/__tests__/tokenHelpers.test.js delete mode 100644 libs_deprecated/oauth/esbuild.config.js delete mode 100644 libs_deprecated/oauth/package.json delete mode 100644 libs_deprecated/oauth/src/codeFlow.js delete mode 100644 libs_deprecated/oauth/src/implicitFlow.js delete mode 100644 libs_deprecated/oauth/src/index.js delete mode 100644 libs_deprecated/oauth/src/mockedSession.js delete mode 100644 libs_deprecated/oauth/src/oidcConfig.js delete mode 100644 libs_deprecated/oauth/src/oidcSession.js delete mode 100644 libs_deprecated/oauth/src/oidcState.js delete mode 100644 libs_deprecated/oauth/src/tokenHelpers.js delete mode 100644 libs_deprecated/oauth/src/utils.js delete mode 100644 libs_deprecated/policy-engine/LICENSE delete mode 100644 libs_deprecated/policy-engine/README.md delete mode 100644 libs_deprecated/policy-engine/package.json delete mode 100644 libs_deprecated/policy-engine/rollup.config.js delete mode 100644 libs_deprecated/policy-engine/src/debugTrace.js delete mode 100644 libs_deprecated/policy-engine/src/debugTrace.test.js delete mode 100644 libs_deprecated/policy-engine/src/engine.js delete mode 100644 libs_deprecated/policy-engine/src/engine.test.js delete mode 100644 libs_deprecated/policy-engine/src/evaluator.js delete mode 100644 libs_deprecated/policy-engine/src/evaluator.test.js delete mode 100644 libs_deprecated/policy-engine/src/index.js delete mode 100644 libs_deprecated/policy-engine/src/lexer.js delete mode 100644 libs_deprecated/policy-engine/src/lexer.test.js delete mode 100644 libs_deprecated/policy-engine/src/parser.js delete mode 100644 libs_deprecated/policy-engine/src/parser.test.js delete mode 100644 libs_deprecated/template-lib/LICENSE delete mode 100644 libs_deprecated/template-lib/README.md delete mode 100644 libs_deprecated/template-lib/__tests__/index.js delete mode 100644 libs_deprecated/template-lib/esbuild.config.js delete mode 100644 libs_deprecated/template-lib/package.json delete mode 100644 libs_deprecated/template-lib/src/index.js delete mode 100644 libs_deprecated/url-state-provider/LICENSE delete mode 100644 libs_deprecated/url-state-provider/README.md delete mode 100644 libs_deprecated/url-state-provider/babel.config.js delete mode 100644 libs_deprecated/url-state-provider/jest.config.js delete mode 100644 libs_deprecated/url-state-provider/package.json delete mode 100644 libs_deprecated/url-state-provider/rollup.config.js delete mode 100644 libs_deprecated/url-state-provider/src/index.js delete mode 100644 libs_deprecated/url-state-provider/src/index.test.js delete mode 100644 libs_deprecated/url-state-router/LICENSE delete mode 100644 libs_deprecated/url-state-router/README.md delete mode 100644 libs_deprecated/url-state-router/babel.config.js delete mode 100644 libs_deprecated/url-state-router/package.json delete mode 100644 libs_deprecated/url-state-router/rollup.config.js delete mode 100644 libs_deprecated/url-state-router/src/Link.js delete mode 100644 libs_deprecated/url-state-router/src/Link.test.js delete mode 100644 libs_deprecated/url-state-router/src/Redirect.js delete mode 100644 libs_deprecated/url-state-router/src/Redirect.test.js delete mode 100644 libs_deprecated/url-state-router/src/Route.js delete mode 100644 libs_deprecated/url-state-router/src/Route.test.js delete mode 100644 libs_deprecated/url-state-router/src/Router.js delete mode 100644 libs_deprecated/url-state-router/src/Router.test.js delete mode 100644 libs_deprecated/url-state-router/src/RouterContext.js delete mode 100644 libs_deprecated/url-state-router/src/RouterContext.test.js delete mode 100644 libs_deprecated/url-state-router/src/Switch.js delete mode 100644 libs_deprecated/url-state-router/src/Switch.test.js delete mode 100644 libs_deprecated/url-state-router/src/index.js delete mode 100644 libs_deprecated/url-state-router/src/routeMatcher.js delete mode 100644 libs_deprecated/url-state-router/src/routeMatcher.test.js delete mode 100644 libs_deprecated/url-state-router/src/useURLStateProvider.js delete mode 100644 libs_deprecated/url-state-router/src/useURLStateProvider.test.js delete mode 100644 libs_deprecated/utils/LICENSE delete mode 100644 libs_deprecated/utils/README.md delete mode 100644 libs_deprecated/utils/__mocks__/intersectionObserverMock.js delete mode 100644 libs_deprecated/utils/babel.config.json delete mode 100644 libs_deprecated/utils/esbuild.config.js delete mode 100644 libs_deprecated/utils/package.json delete mode 100644 libs_deprecated/utils/src/hooks/useAppLoader.js delete mode 100644 libs_deprecated/utils/src/hooks/useEndlessScrollList.js delete mode 100644 libs_deprecated/utils/src/hooks/useEndlessScrollList.test.js delete mode 100644 libs_deprecated/utils/src/index.js delete mode 100644 libs_deprecated/utils/src/lib/fetchProxy.js delete mode 100644 libs_deprecated/utils/src/lib/fetchProxy.test.js delete mode 100644 packages/assets-overview/LICENSE delete mode 100644 packages/assets-overview/README.md delete mode 100644 packages/assets-overview/__mocks__/client.js delete mode 100644 packages/assets-overview/__mocks__/fileMock.js delete mode 100644 packages/assets-overview/__mocks__/react-markdown.js delete mode 100644 packages/assets-overview/__mocks__/remark-gfm.js delete mode 100644 packages/assets-overview/__mocks__/styleMock.js delete mode 100644 packages/assets-overview/babel.config.js delete mode 100644 packages/assets-overview/esbuild.config.js delete mode 100644 packages/assets-overview/jest.config.js delete mode 100644 packages/assets-overview/package-lock.json delete mode 100644 packages/assets-overview/package.json delete mode 100644 packages/assets-overview/public/favicon.ico delete mode 100644 packages/assets-overview/public/index.html delete mode 100644 packages/assets-overview/setupTests.js delete mode 100644 packages/assets-overview/src/App.js delete mode 100644 packages/assets-overview/src/App.test.js delete mode 100644 packages/assets-overview/src/actions.js delete mode 100644 packages/assets-overview/src/components/AppContent.jsx delete mode 100644 packages/assets-overview/src/components/AppRouter.jsx delete mode 100644 packages/assets-overview/src/components/AssetDetails.js delete mode 100644 packages/assets-overview/src/components/AssetsList.js delete mode 100644 packages/assets-overview/src/components/AssetsListItem.js delete mode 100644 packages/assets-overview/src/components/BuildLog.jsx delete mode 100644 packages/assets-overview/src/components/CustomPageHeader.js delete mode 100644 packages/assets-overview/src/components/Documentation.js delete mode 100644 packages/assets-overview/src/components/HintLoading.js delete mode 100644 packages/assets-overview/src/components/HintNotFound.js delete mode 100644 packages/assets-overview/src/components/Markdown.js delete mode 100644 packages/assets-overview/src/components/TabContainer.js delete mode 100644 packages/assets-overview/src/components/TestContent.js delete mode 100644 packages/assets-overview/src/components/details/DetailSection.jsx delete mode 100644 packages/assets-overview/src/components/details/PreviewAppPropsForm.jsx delete mode 100644 packages/assets-overview/src/components/details/TabAdvanced.jsx delete mode 100644 packages/assets-overview/src/components/details/TabGetStarted.jsx delete mode 100644 packages/assets-overview/src/components/details/TabPreview.jsx delete mode 100644 packages/assets-overview/src/components/details/TabWithMarkdown.jsx delete mode 100644 packages/assets-overview/src/helpers.js delete mode 100644 packages/assets-overview/src/hooks/useAssetTestUrl.js delete mode 100644 packages/assets-overview/src/img/app_bg_example.svg delete mode 100644 packages/assets-overview/src/index.js delete mode 100644 packages/assets-overview/src/store.js delete mode 100644 packages/assets-overview/src/styles.js delete mode 100644 packages/assets-overview/src/styles.scss delete mode 100644 packages/assets-overview/src/test-data.json delete mode 100644 packages/assets-overview/src/widget.js delete mode 100644 packages/assets-overview/tailwind.config.js delete mode 100644 packages/auth/LICENSE delete mode 100644 packages/auth/README.md delete mode 100644 packages/auth/__mocks__/fileMock.js delete mode 100644 packages/auth/__mocks__/styleMock.js delete mode 100644 packages/auth/babel.config.js delete mode 100644 packages/auth/esbuild.config.js delete mode 100644 packages/auth/jest.config.js delete mode 100644 packages/auth/package-lock.json delete mode 100644 packages/auth/package.json delete mode 100644 packages/auth/public/favicon.ico delete mode 100644 packages/auth/public/index.html delete mode 100644 packages/auth/public/index_test.html delete mode 100644 packages/auth/secretProps.template.json delete mode 100644 packages/auth/setupTests.js delete mode 100644 packages/auth/src/App.js delete mode 100644 packages/auth/src/App.test.js delete mode 100644 packages/auth/src/index.js delete mode 100644 packages/auth/src/mockedToken.js delete mode 100644 packages/auth/src/styles.scss delete mode 100644 packages/auth/src/useCommunication.js delete mode 100644 packages/auth/tailwind.config.js delete mode 100644 packages/dashboard/.gitignore delete mode 100644 packages/dashboard/LICENSE delete mode 100644 packages/dashboard/README.md delete mode 100644 packages/dashboard/__mocks__/client.js delete mode 100644 packages/dashboard/__mocks__/fileMock.js delete mode 100644 packages/dashboard/__mocks__/styleMock.js delete mode 100644 packages/dashboard/babel.config.js delete mode 100644 packages/dashboard/esbuild.config.js delete mode 100644 packages/dashboard/jest.config.js delete mode 100644 packages/dashboard/package-lock.json delete mode 100644 packages/dashboard/package.json delete mode 100644 packages/dashboard/postcss.config.js delete mode 100644 packages/dashboard/public/favicon.ico delete mode 100644 packages/dashboard/public/index.html delete mode 100644 packages/dashboard/setupTests.js delete mode 100644 packages/dashboard/src/App.css delete mode 100644 packages/dashboard/src/App.js delete mode 100644 packages/dashboard/src/App.test.js delete mode 100644 packages/dashboard/src/assets/images/AWS_logo.svg delete mode 100644 packages/dashboard/src/assets/images/CCloud_Logo_light.svg delete mode 100644 packages/dashboard/src/assets/images/Microsoft_Azure_logo.svg delete mode 100644 packages/dashboard/src/assets/images/Reference_Icon.svg delete mode 100644 packages/dashboard/src/assets/images/Region_Icon_sm.svg delete mode 100644 packages/dashboard/src/assets/images/Service_Icon.svg delete mode 100644 packages/dashboard/src/assets/images/background_center.png delete mode 100644 packages/dashboard/src/assets/images/background_footer.jpg delete mode 100644 packages/dashboard/src/assets/images/background_footer.svg delete mode 100644 packages/dashboard/src/assets/images/background_header.png delete mode 100644 packages/dashboard/src/assets/images/cloud.png delete mode 100644 packages/dashboard/src/assets/images/docu_shape.svg delete mode 100644 packages/dashboard/src/assets/images/flag_australia.svg delete mode 100644 packages/dashboard/src/assets/images/flag_brazil.svg delete mode 100644 packages/dashboard/src/assets/images/flag_canada.svg delete mode 100644 packages/dashboard/src/assets/images/flag_ccloud.svg delete mode 100644 packages/dashboard/src/assets/images/flag_china.svg delete mode 100644 packages/dashboard/src/assets/images/flag_germany.svg delete mode 100644 packages/dashboard/src/assets/images/flag_japan.svg delete mode 100644 packages/dashboard/src/assets/images/flag_netherlands.svg delete mode 100644 packages/dashboard/src/assets/images/flag_russia.svg delete mode 100644 packages/dashboard/src/assets/images/flag_saudiarabia.svg delete mode 100644 packages/dashboard/src/assets/images/flag_unitedarabempire.svg delete mode 100644 packages/dashboard/src/assets/images/flag_usa.svg delete mode 100644 packages/dashboard/src/assets/images/icon_documentation.svg delete mode 100644 packages/dashboard/src/assets/images/icon_slack.svg delete mode 100644 packages/dashboard/src/assets/images/icon_support.svg delete mode 100644 packages/dashboard/src/assets/images/map.svg delete mode 100644 packages/dashboard/src/assets/images/sap_logo.svg delete mode 100644 packages/dashboard/src/components/landingpage/DomainSelect.js delete mode 100644 packages/dashboard/src/components/landingpage/LoginOverlay.js delete mode 100644 packages/dashboard/src/components/landingpage/RegionSelect.js delete mode 100644 packages/dashboard/src/components/landingpage/WorldMapQASelect.js delete mode 100644 packages/dashboard/src/components/layout/PageFooter.js delete mode 100644 packages/dashboard/src/components/layout/PageHead.js delete mode 100644 packages/dashboard/src/index.js delete mode 100644 packages/dashboard/src/lib/hooks/useDynamicScript.js delete mode 100644 packages/dashboard/src/lib/hooks/useMicroFrontend.js delete mode 100644 packages/dashboard/src/lib/pages-loader.js delete mode 100644 packages/dashboard/src/lib/utils.js delete mode 100644 packages/dashboard/src/logo.svg delete mode 100644 packages/dashboard/src/pages/home.js delete mode 100644 packages/dashboard/src/store.js delete mode 100644 packages/dashboard/src/styles.scss delete mode 100644 packages/dashboard/tailwind.config.js delete mode 100644 packages/playground/.gitignore delete mode 100644 packages/playground/LICENSE delete mode 100644 packages/playground/README.md delete mode 100644 packages/playground/__mocks__/client.js delete mode 100644 packages/playground/__mocks__/fileMock.js delete mode 100644 packages/playground/__mocks__/styleMock.js delete mode 100644 packages/playground/babel.config.js delete mode 100644 packages/playground/esbuild.config.js delete mode 100644 packages/playground/jest.config.js delete mode 100644 packages/playground/package-lock.json delete mode 100644 packages/playground/package.json delete mode 100644 packages/playground/public/favicon-16x16.png delete mode 100644 packages/playground/public/favicon-32x32.png delete mode 100644 packages/playground/public/favicon.ico delete mode 100644 packages/playground/public/index.html delete mode 100644 packages/playground/secretProps.template.json delete mode 100644 packages/playground/setupTests.js delete mode 100644 packages/playground/src/App.js delete mode 100644 packages/playground/src/App.test.js delete mode 100644 packages/playground/src/AppContent.js delete mode 100644 packages/playground/src/assets/.gitkeep delete mode 100644 packages/playground/src/components/Error.jsx delete mode 100644 packages/playground/src/components/HintLoading.js delete mode 100644 packages/playground/src/components/Preview.jsx delete mode 100644 packages/playground/src/components/PreviewShell.jsx delete mode 100644 packages/playground/src/components/StoreProvider.js delete mode 100644 packages/playground/src/hooks/.gitkeep delete mode 100644 packages/playground/src/index.js delete mode 100644 packages/playground/src/lib/executeCode.js delete mode 100644 packages/playground/src/lib/store.js delete mode 100644 packages/playground/src/styles.scss delete mode 100644 packages/playground/tailwind.config.js delete mode 100644 packages/user-activity/LICENSE delete mode 100644 packages/user-activity/README.md delete mode 100644 packages/user-activity/__mocks__/client.js delete mode 100644 packages/user-activity/__mocks__/fileMock.js delete mode 100644 packages/user-activity/__mocks__/styleMock.js delete mode 100644 packages/user-activity/babel.config.js delete mode 100644 packages/user-activity/esbuild.config.js delete mode 100644 packages/user-activity/jest.config.js delete mode 100644 packages/user-activity/package-lock.json delete mode 100644 packages/user-activity/package.json delete mode 100644 packages/user-activity/public/favicon.ico delete mode 100644 packages/user-activity/public/index.html delete mode 100644 packages/user-activity/secretProps.template.json delete mode 100644 packages/user-activity/setupTests.js delete mode 100644 packages/user-activity/src/App.js delete mode 100644 packages/user-activity/src/App.test.js delete mode 100644 packages/user-activity/src/hooks/useCommunication.js delete mode 100644 packages/user-activity/src/hooks/useIdleTimer.js delete mode 100644 packages/user-activity/src/index.js delete mode 100644 packages/user-activity/src/store.js delete mode 100644 packages/user-activity/src/styles.scss delete mode 100644 packages/user-activity/tailwind.config.js delete mode 100644 packages/widget-loader/LICENSE delete mode 100644 packages/widget-loader/README.md delete mode 100644 packages/widget-loader/esbuild.config.js delete mode 100644 packages/widget-loader/package-lock.json delete mode 100644 packages/widget-loader/package.json delete mode 100644 packages/widget-loader/public/index.html delete mode 100644 packages/widget-loader/src/index.js delete mode 100644 packages/widget-loader/src/index.test.js diff --git a/.github/workflows/block-deprecated_assets.yml b/.github/workflows/block-deprecated_assets.yml deleted file mode 100644 index 902bbd5ae..000000000 --- a/.github/workflows/block-deprecated_assets.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Block PRs on deprecated apps and libs - -on: - pull_request: - types: [opened, synchronize, reopened, edited] - -# Default to bash -defaults: - run: - shell: bash - -jobs: - changes: - runs-on: [ubuntu-latest] - outputs: - apps: ${{ steps.filters.outputs.apps }} - libs: ${{ steps.filters.outputs.libs }} - app-changes: ${{ steps.app-filters.outputs.changes }} - lib-changes: ${{ steps.lib-filters.outputs.changes }} - steps: - - name: Checkout Pull Request - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} - - - uses: dorny/paths-filter@v3 - id: filters - with: - list-files: shell - filters: | - apps: apps_deprecated/** - libs: libs_deprecated/** - - - name: Show outputs - run: | - echo "====================" - echo apps: ${{ steps.filters.outputs.apps}} - echo apps_files: ${{ steps.filters.outputs.apps_files}} - echo app changes: ${{ steps.app-filters.outputs.changes}} - echo libs: ${{ steps.filters.outputs.libs}} - echo libs_files: ${{ steps.filters.outputs.libs_files}} - echo lib changes: ${{ steps.lib-filters.outputs.changes}} - echo "====================" - evaluate-changes: - needs: changes - runs-on: [ubuntu-latest] - steps: - - name: Show inputs - run: | - echo apps: ${{ needs.changes.outputs.apps }} - echo libs: ${{ needs.changes.outputs.libs }} - echo app changes: ${{ needs.changes.outputs.app-changes }} - echo lib changes: ${{ needs.changes.outputs.lib-changes }} - - - name: Check if changes belong to deprecated apps or libs - if: ${{ needs.changes.outputs.apps == 'true' || needs.changes.outputs.libs == 'true' }} - run: | - echo "::error not allowed to make changes to deprecated apps or libs" - exit 1 diff --git a/apps_deprecated/exampleapp/LICENSE b/apps_deprecated/exampleapp/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/apps_deprecated/exampleapp/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/apps_deprecated/exampleapp/README.md b/apps_deprecated/exampleapp/README.md deleted file mode 100644 index 5113e4cbb..000000000 --- a/apps_deprecated/exampleapp/README.md +++ /dev/null @@ -1,88 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/juno](https://github.com/cloudoperators/juno) for the latest updates and active development. - -# Example App - -The example app serves as a demonstration application where we thoroughly test and implement interactions between multiple components following our best practices. Additionally, it functions as a prime illustration of how Juno components can be effectively utilized. - -# Usage - -## Standalone - -To integrate the Microfrontend as a standalone module, follow these steps: - -1. Include the following script tag in your HTML file: - -```js - -``` - -2. Place a div element with the id "root" where you want the Microfrontend to be rendered: - -```html -
-``` - -## Embedded - -1. To embed the React Microfrontend into your application, start by installing it: - -```bash -npm add @sapcc/juno-app-exampleapp" -``` - -2. Next, import and integrate it into your code: - -```js -import Exampleapp from "@sapcc/juno-app-exampleapp" - -const App = () => { - /*...*/ - return ( -
- -
- ) -} -``` - -Or using React's lazy loading to keep the bundle size small - -```js -import { lazy } from "react" - -const Exampleapp = lazy(() => import("@sapcc/juno-app-exampleapp")) - -const App = () => { - /*...*/ - return ( -
- -
- ) -} -``` - -# Best practices - -- [React Zustand] implementation with React context -- [React Zustand] store sliced and structured in lib folder. -- [React Zustand] [Avoid Rerenders] Zustand export single States instead of the whole Store. -- [React Query] [Avoid Rerenders] Use of hook `useQueryClilentFn` isolated in AsyncWorker component. -- [React Query] use of hook `useQueryClilentFn` to encapsulate all queries and react to changes. -- [Avoid Rerenders] use of hook `useUrlState` instead isolated in AsyncWorker component. -- [Coworking Experience] use of hook `useUrlState` without boiler plate. -- [Enhance Rendering Experience] Use of hook `useEndlessScrollList`. -- [Coworking Experience] Components splitted in contexts. -- Use of fetchLocal to simulate a local db. - -``` - -``` diff --git a/apps_deprecated/exampleapp/__mocks__/client.js b/apps_deprecated/exampleapp/__mocks__/client.js deleted file mode 100644 index 84531d3c2..000000000 --- a/apps_deprecated/exampleapp/__mocks__/client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { JSDOM } from "jsdom" -const dom = new JSDOM() -global.document = dom.window.document -global.window = dom.window diff --git a/apps_deprecated/exampleapp/__mocks__/fileMock.js b/apps_deprecated/exampleapp/__mocks__/fileMock.js deleted file mode 100644 index 27ce65aca..000000000 --- a/apps_deprecated/exampleapp/__mocks__/fileMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = "test-file-stub" diff --git a/apps_deprecated/exampleapp/__mocks__/styleMock.js b/apps_deprecated/exampleapp/__mocks__/styleMock.js deleted file mode 100644 index d74516001..000000000 --- a/apps_deprecated/exampleapp/__mocks__/styleMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = {} diff --git a/apps_deprecated/exampleapp/babel.config.js b/apps_deprecated/exampleapp/babel.config.js deleted file mode 100644 index 0719e2fec..000000000 --- a/apps_deprecated/exampleapp/babel.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - env: { - test: { - presets: ["@babel/preset-env", "@babel/preset-react"], - plugins: [["babel-plugin-transform-import-meta", { module: "ES6" }]], - }, - }, -} diff --git a/apps_deprecated/exampleapp/db.json b/apps_deprecated/exampleapp/db.json deleted file mode 100644 index 589b05254..000000000 --- a/apps_deprecated/exampleapp/db.json +++ /dev/null @@ -1,290 +0,0 @@ -{ - "peaks-test": [], - "peaks": [ - { - "id": 2, - "name": "Ama Dablam", - "height": "6814m", - "region": "Khumbu", - "mainrange": "Himalayas", - "countries": "Nepal", - "url": "https://en.wikipedia.org/wiki/Ama_Dablam" - }, - { - "id": 3, - "name": "Lhotse", - "height": "8516m", - "region": "Khumbu", - "mainrange": "Himalayas", - "countries": "China, Nepal", - "url": "https://en.wikipedia.org/wiki/Lhotse" - }, - { - "id": 4, - "name": "Nuptse", - "height": "7861m", - "region": "Khumbu", - "mainrange": "Himalayas", - "countries": "Nepal", - "url": "https://en.wikipedia.org/wiki/Nuptse" - }, - { - "id": 5, - "name": "Weisshorn", - "height": "4506m", - "region": "Valais", - "mainrange": "Swiss Alps", - "countries": "Switzerland", - "url": "https://en.wikipedia.org/wiki/Weisshorn" - }, - { - "id": 6, - "name": "Zinalrothorn", - "height": "4221m", - "region": "Valais", - "mainrange": "Swiss Alps", - "countries": "Switzerland", - "url": "https://en.wikipedia.org/wiki/Zinalrothorn" - }, - { - "id": 7, - "name": "Mont Blanc", - "height": "4,808 m", - "mainrange": "Mont Blanc Massif", - "region": "Auvergne-Rhône-Alpes", - "countries": "France" - }, - { - "id": 8, - "name": "Matterhorn", - "height": "4,478 m", - "mainrange": "Pennine Alps", - "region": "Valais", - "countries": "Switzerland" - }, - { - "id": 9, - "name": "Eiger", - "height": "3,967 m", - "mainrange": "Bernese Alps", - "region": "Bern", - "countries": "Switzerland" - }, - { - "id": 10, - "name": "Grossglockner", - "height": "3,798 m", - "mainrange": "Hohe Tauern", - "region": "Carinthia/Tyrol", - "countries": "Austria" - }, - { - "id": 11, - "name": "Mulhacén", - "height": "3,479 m", - "mainrange": "Sierra Nevada", - "region": "Andalusia", - "countries": "Spain" - }, - { - "id": 12, - "name": "Piz Bernina", - "height": "4,049 m", - "mainrange": "Bernina Range", - "region": "Graubünden", - "countries": "Switzerland" - }, - { - "id": 13, - "name": "Tatra High Peak (Gerlachovský štít)", - "height": "2,655 m", - "mainrange": "Tatra Mountains", - "region": "Prešov", - "countries": "Slovakia" - }, - { - "id": 14, - "name": "Ben Nevis", - "height": "1,345 m", - "mainrange": "Grampian Mountains", - "region": "Highland", - "countries": "United Kingdom" - }, - { - "id": 15, - "name": "Dufourspitze", - "height": "4,634 m", - "mainrange": "Pennine Alps", - "region": "Valais", - "countries": "Switzerland" - }, - { - "id": 16, - "name": "Triglav", - "height": "2,863 m", - "mainrange": "Julian Alps", - "region": "Gorenjska", - "countries": "Slovenia" - }, - { - "id": 17, - "name": "Aneto", - "height": "3,404 m", - "mainrange": "Pyrenees", - "region": "Aragon", - "countries": "Spain" - }, - { - "id": 18, - "name": "Galdhøpiggen", - "height": "2,469 m", - "mainrange": "Jotunheimen", - "region": "Innlandet", - "countries": "Norway" - }, - { - "id": 19, - "name": "Sněžka", - "height": "1,603 m", - "mainrange": "Giant Mountains", - "region": "Hradec Králové", - "countries": "Czech Republic" - }, - { - "id": 20, - "name": "Scafell Pike", - "height": "978 m", - "mainrange": "Lake District", - "region": "Cumbria", - "countries": "United Kingdom" - }, - { - "id": 21, - "name": "Vihren", - "height": "2,914 m", - "mainrange": "Pirin Mountains", - "region": "Blagoevgrad", - "countries": "Bulgaria" - }, - { - "id": 22, - "name": "Santorini Volcano (Mount Profitis Ilias)", - "height": "550 m", - "mainrange": "Aegean Islands", - "region": "South Aegean", - "countries": "Greece" - }, - { - "id": 23, - "name": "Vatnajökull (Hvannadalshnjúkur)", - "height": "2,110 m", - "mainrange": "Vatnajökull Glacier", - "region": "Eastern region", - "countries": "Iceland" - }, - { - "id": 24, - "name": "Grintovec", - "height": "2,558 m", - "mainrange": "Kamnik-Savinja Alps", - "region": "Upper Carniola", - "countries": "Slovenia" - }, - { - "id": 25, - "name": "Puy de Sancy", - "height": "1,885 m", - "mainrange": "Massif Central", - "region": "Auvergne", - "countries": "France" - }, - { - "id": 26, - "name": "Snøhetta", - "height": "2,286 m", - "mainrange": "Dovre Mountains", - "region": "Trøndelag", - "countries": "Norway" - }, - { - "id": 27, - "name": "Grossvenediger", - "height": "3,666 m", - "mainrange": "Venediger Group", - "region": "Tyrol", - "countries": "Austria" - }, - { - "id": 28, - "name": "Rila Monastery Peak", - "height": "2,729 m", - "mainrange": "Rila Mountains", - "region": "Kyustendil", - "countries": "Bulgaria" - }, - { - "id": 29, - "name": "Ben Macdui", - "height": "1,309 m", - "mainrange": "Cairngorms", - "region": "Highland", - "countries": "United Kingdom" - }, - { - "id": 30, - "name": "Maja Jezercë", - "height": "2,694 m", - "mainrange": "Accursed Mountains", - "region": "Shkodër", - "countries": "Albania" - }, - { - "id": 31, - "name": "Kebnekaise (South Peak)", - "height": "2,106 m", - "mainrange": "Scandinavian Mountains", - "region": "Norrbotten", - "countries": "Sweden" - }, - { - "id": 32, - "name": "Piz Palü", - "height": "3,901 m", - "mainrange": "Bernina Range", - "region": "Graubünden", - "countries": "Switzerland" - }, - { - "id": 33, - "name": "Carrantuohill", - "height": "1,038 m", - "mainrange": "Macgillycuddy's Reeks", - "region": "County Kerry", - "countries": "Ireland" - }, - { - "id": 34, - "name": "Großvenediger", - "height": "3,657 m", - "mainrange": "Venediger Group", - "region": "Tyrol", - "countries": "Austria" - }, - { - "id": 35, - "name": "Gerlachovský štít", - "height": "2,655 m", - "mainrange": "Tatra Mountains", - "region": "Prešov", - "countries": "Slovakia" - }, - { - "id": 36, - "name": "Mullach an Rathain (Liathach)", - "height": "1,055 m", - "mainrange": "Torridon Hills", - "region": "Highland", - "countries": "United Kingdom" - } - ] -} diff --git a/apps_deprecated/exampleapp/esbuild.config.js b/apps_deprecated/exampleapp/esbuild.config.js deleted file mode 100644 index 6bad6e827..000000000 --- a/apps_deprecated/exampleapp/esbuild.config.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const esbuild = require("esbuild") -const fs = require("node:fs/promises") -const pkg = require("./package.json") -const postcss = require("postcss") -const sass = require("sass") -const { transform } = require("@svgr/core") -const url = require("postcss-url") -// this function generates app props based on package.json and propSecrets.json -const appProps = require("../../helpers/appProps") - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) - -const isProduction = process.env.NODE_ENV === "production" -// If the jspm server fails and we cannot use external packages -// in our import map then IGNORE_EXTERNALS (global env variable) -// should be set to true -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" -// in dev environment we prefix output file with public -let outfile = `${isProduction ? "" : "public/"}${pkg.main || pkg.module}` - -// get output from outputfile -// let [outdir, file] = outfile.split("/", 2) -let outdir = outfile.slice(0, outfile.lastIndexOf("/")) - -console.log(`=====================outdir: ${outdir}`) -console.log(`=====================file: ${outfile}`) -// process.exit() -const args = process.argv.slice(2) -const watch = args.indexOf("--watch") >= 0 -const serve = args.indexOf("--serve") >= 0 - -// helpers for console log -const green = "\x1b[32m%s\x1b[0m" -const yellow = "\x1b[33m%s\x1b[0m" -const clear = "\033c" - -const build = async () => { - // delete build folder and re-create it as an empty folder - await fs.rm(outdir, { recursive: true, force: true }) - await fs.mkdir(outdir, { recursive: true }) - - // build app - let ctx = await esbuild.context({ - bundle: true, - minify: isProduction, - // target: ["es2020"], - target: ["es2020"], //["chrome64", "firefox67", "safari11.1", "edge79"], - format: "esm", - platform: "browser", - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - loader: { ".js": "jsx" }, - sourcemap: !isProduction, - // here we exclude package from bundle which are defined in peerDependencies - // our importmap generator uses also the peerDependencies to create the importmap - // it means all packages defined in peerDependencies are in browser available via the importmap - external: - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [], - entryPoints: [pkg.source], - outdir, - // this step is important for performance reason. - // the main file (index.js) contains minimal code needed to - // load the app via dynamic import (splitting: true) - splitting: true, - // we suport only esm! - format: "esm", - plugins: [ - // minimal plugin to log the recompiling process. - { - name: "start/end", - setup(build) { - build.onStart(() => { - console.log(yellow, "Compiling...") - }) - build.onEnd(() => console.log(green, "Done!")) - }, - }, - - // this custom plugin rewrites SVG imports to - // dataurls, paths or react components based on the - // search param and size - { - name: "svg-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(svg)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - let loader = "text" - if (args.suffix === "?url") { - // as URL - const maxSize = 10240 // 10Kb - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - } else { - // as react component - // use react component loader (jsx) - loader = "jsx" - contents = await transform(contents, { - plugins: ["@svgr/plugin-jsx"], - }) - } - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin rewrites image imports to - // dataurls or urls based on the size - { - name: "image-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(png|jpg|jpeg|gif)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - const maxSize = 10240 // 10Kb - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin parses the style files - { - name: "parse-styles", - setup(build) { - build.onLoad( - // consider only .scss and .css files - { filter: /.\.(css|scss)$/, namespace: "file" }, - async (args) => { - let content - // handle scss, convert to css - if (args.path.endsWith(".scss")) { - const result = sass.renderSync({ file: args.path }) - content = result.css - } else { - // read file content - content = await fs.readFile(args.path) - } - - // postcss plugins - const plugins = [ - require("tailwindcss"), - require("autoprefixer"), - // rewrite urls inside css - url({ - url: "inline", - // maxSize: 10, // use dataurls if files are smaller than 10k - // fallback: "copy", // if files are bigger use copy method - // assetsPath: "./build/assets", - // useHash: true, - // optimizeSvgEncode: true, - }), - ] - - const { css } = await postcss(plugins).process(content, { - from: args.path, - to: outdir, - }) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - return { contents: css, loader: "text" } - } - ) - }, - }, - ], - }) - - // watch and serve - if (watch || serve) { - if (watch) await ctx.watch() - if (serve) { - // generate app props based on package.json and secretProps.json - await fs.writeFile( - `./${outdir}/appProps.js`, - `export default ${JSON.stringify(appProps())}` - ) - - let { host, port } = await ctx.serve({ - host: "0.0.0.0", - port: parseInt(process.env.APP_PORT || process.env.PORT || 3000), - servedir: "public", - }) - console.log("serve on", `${host}:${port}`) - } - } else { - await ctx.rebuild() - await ctx.dispose() - } -} - -build() diff --git a/apps_deprecated/exampleapp/jest.config.js b/apps_deprecated/exampleapp/jest.config.js deleted file mode 100644 index 33ea7ddfe..000000000 --- a/apps_deprecated/exampleapp/jest.config.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - transform: { "\\.[jt]sx?$": "babel-jest" }, - testEnvironment: "jsdom", - setupFilesAfterEnv: ["/setupTests.js"], - transformIgnorePatterns: [ - "node_modules/(?!(juno-ui-components|oauth|messages-provider|utils)/)", - ], - moduleNameMapper: { - // Jest currently doesn't support resources with query parameters. - // Therefore we add the optional query parameter matcher at the end - // https://github.com/facebook/jest/issues/4181 - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)(\\?.+)?$": - require.resolve("./__mocks__/fileMock"), - "\\.(css|less|scss)$": require.resolve("./__mocks__/styleMock"), - }, -} diff --git a/apps_deprecated/exampleapp/package.json b/apps_deprecated/exampleapp/package.json deleted file mode 100644 index d53261183..000000000 --- a/apps_deprecated/exampleapp/package.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "exampleapp", - "version": "1.0.4", - "author": "UI-Team", - "contributors": [ - "Arturo Reuschenbach Pucernau" - ], - "repository": "https://github.com/sapcc/juno/tree/main/apps/exampleapp", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/juno for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "module": "build/index.js", - "source": "src/index.js", - "private": true, - "devDependencies": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0", - "@tanstack/react-query": "4.28.0", - "@testing-library/dom": "^8.19.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "assert": "^2.0.0", - "autoprefixer": "^10.4.2", - "babel-jest": "^29.3.1", - "babel-plugin-transform-import-meta": "^2.2.0", - "body-parser": "^1.20.1", - "esbuild": "^0.17.19", - "jest": "^29.3.1", - "jest-environment-jsdom": "^29.3.1", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.14.1/package.tgz", - "luxon": "^2.3.0", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "oauth": "https://assets.juno.global.cloud.sap/libs/oauth@1.2.1/package.tgz", - "postcss": "^8.4.21", - "postcss-url": "^10.1.3", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-test-renderer": "18.2.0", - "sass": "^1.60.0", - "shadow-dom-testing-library": "^1.7.1", - "tailwindcss": "^3.3.1", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "util": "^0.12.4", - "utils": "https://assets.juno.global.cloud.sap/libs/utils@1.1.6/package.tgz", - "zustand": "4.5.2" - }, - "scripts": { - "test": "jest", - "start": "NODE_ENV=development node esbuild.config.js --serve --watch", - "build": "NODE_ENV=production node esbuild.config.js", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prestart": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "peerDependencies": { - "@tanstack/react-query": "4.28.0", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.14.1/package.tgz", - "luxon": "^2.3.0", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "oauth": "https://assets.juno.global.cloud.sap/libs/oauth@1.2.1/package.tgz", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "utils": "https://assets.juno.global.cloud.sap/libs/utils@1.1.6/package.tgz", - "zustand": "4.5.2" - }, - "importmapExtras": { - "zustand/middleware": "4.3.7" - }, - "appProps": { - "theme": { - "value": "theme-dark", - "description": "Override the default theme. Possible values are theme-light or theme-dark (default)" - }, - "endpoint": { - "value": "", - "description": "Endpoint URL of the API" - }, - "embedded": { - "value": "false", - "description": "Set to true if app is to be embedded in another existing app or page, like e.g. Elektra. If set to true the app won't render a page header/footer and instead render only the content" - } - }, - "appPreview": true -} diff --git a/apps_deprecated/exampleapp/public/favicon.ico b/apps_deprecated/exampleapp/public/favicon.ico deleted file mode 100644 index 9ebc4bb2e04736789f9fcfe03121b296c693079a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHOc~DkW6h8=vpa^PaX3JM9iaLr~+M@BPg-&UinG_1xqN9VFP8qhyVv3gI5)y)q zTINC;R?|K;#Z=Q?rdcjEfL2psi+^QPO{eqwE|2&4e8Bs@_ib;6J9D_-d+*+Je)rsS zw{s6fQ4~#SX(YLes`?X+A|jWo@j02OR^BB`j_>ngh)SfuKq(_tXtogEds07@wedGr zzRwh@rmJplpzU=``%W`${FrIleN26aGbMIs`5p@TOXSoGJtveUB&};Tx#jC|A*LG_ zG41`GX~z#t*Uo0@5FHArF33-gz4hJZSf5CcVNu%YJgjw z6?WGUracWzyMAW6WN4_dS(OK@>5XlGO&t+Zbqiipx}UPZDz9*rJ0_ShR%bO~A9#hr zzU3%WY^QMH@_-h3_=2)hvD5l*q zW--@al459QQcid2PTLeyU!zA+Owd_+jT$7c2behY2~(YeQ@t)2cUB8>)U~ zns~SK+R*Jhri!oieptGbsdqnTwWE7)rblb^HsCDt$m>kg?`KNCjcN20rt#TKBPT^} zyW--RW-McR=10997#Bv$d?0f1YwK3hxlGs3V=8<}=BE?Q@#n0JeEeEFw7g>{rX|}| zI~Hwm9)9CIyY~I?;m0`Cbn0t9{5qxoy?=y$zl#0k!~2zdUvX>Yu})}f_0%Q)>p|mZ z%!iI+TK^GKZiyOq*JLu?FrNwM!pA?=#~*ZOtmo_RIqMZK__z|f+T*3k#yP6^RUM;o zt~36I{`-xzC$pDJKeNr`XO&KQ*tkB7~p4`p09jR^AB`CxdkYr24s`lfsIc~$F=9p9_|!Ttl|aO-z^J5griCrm@ep4~=`Z>V#e z<8E21<_@h5-Z{n!e68>mM22tPTz@!6r%e!_{OxKjLOys5Q+yZm@}bssyS(;(Xt#lI z+JNqZc3wXK`^k{6)q&GfonU|7!T75Md$xn|BTfK!kl#A64aXa?OGe{`)ctkfY%`d1 z60o|3jA^z!{38@hxq;vf?72c_3H=bswgj7Tn*lex!+5}$#=Z7Qp>VDb+WZbIh!X&| zX6au%r4yY-o}_|pD2}KG&(TCh$fNWekL{^t4HV&%L0>g^7CqJ@7rknF*7S}zEtim6 zs3}fMV!2vLUFBN=^-ViYWe5JFbswsDp&otA&$+(O2WN!;L80YBi9*ISNFM4u@c~bt zRQ|Z&p4||iklF}9tW#vibYw!DMdd?A3*TF?)qQ9(HtB{EG68+u>oS zZpNLe4@ON6j}9>YH+{jht(K`zN_a3JCKGX`xHlMcYj}Kyh_ig+pz4c?Z=|n@Vn3I^V6D872ktS}eZaJI7ZdKqu)b<{ZLl+A+17p|J^_6&BExze@Poe? z_ldv&|2AYJZUc9$R`m})SR={~sIl2+fHe$=p+L;Cub5lX1Lh^n4QNkm^CbFfavoFF zDWHQw}8`_-?><8mC^-78D9Hji$h~+Q+T*(gBdX9d>n8Y5{+y9SsbYX?e z;THSIyM4Ys!;g>n=wahke5Efo<*Tgr@`1HwrBAj043BQH|2%AY4h%d-?7xe`D8E2t z`$(L?&dzPXV`tOQ^|DVgBD(2^8P8oEB7`k^di)d(uQRy?VcE5Voa4@j_)Z zvyiF(W!`11JcCCA6}@bwtXY``PpkmW*mi6TXEem1`pX0R$Q7?i47d1n{N;hThmyC{ zSrKcnzkINlnO|nDzF90PVnJ5F&4hSXGYp6qS@{OjWA8G}DmE`O)U9G{jQT)K2mZ$o z`zJHL-tQ0(1iL`oBjQ^SdoXUMwYo-L@cY>5TO%*?-xv$N<5G1{x6DTUO;R_Zk;f?? P_&~0wZjp_d33dMme?Bb{ diff --git a/apps_deprecated/exampleapp/public/index.html b/apps_deprecated/exampleapp/public/index.html deleted file mode 100644 index 48895cb91..000000000 --- a/apps_deprecated/exampleapp/public/index.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - EXAMPLEAPP Dev - - - - - -
- - diff --git a/apps_deprecated/exampleapp/setupTests.js b/apps_deprecated/exampleapp/setupTests.js deleted file mode 100644 index db44c9038..000000000 --- a/apps_deprecated/exampleapp/setupTests.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom" diff --git a/apps_deprecated/exampleapp/src/App.jsx b/apps_deprecated/exampleapp/src/App.jsx deleted file mode 100644 index 7b3aa83a2..000000000 --- a/apps_deprecated/exampleapp/src/App.jsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect } from "react" -import styles from "./styles.scss" -import { - AppShellProvider, - AppShell, - PageHeader, - Container, -} from "juno-ui-components" -import { oidcSession, mockedSession } from "oauth" -import { QueryClient, QueryClientProvider } from "@tanstack/react-query" -import AppContent from "./components/AppContent" -import HeaderUser from "./components/auth/HeaderUser" -import AsyncWorker from "./components/AsyncWorker" -import StoreProvider, { - useGlobalsActions, - useAuthActions, -} from "./components/StoreProvider" -import { MessagesProvider } from "messages-provider" - -// mock API -import { fetchProxyInitDB } from "utils" -import db from "../db.json" - -const App = (props = {}) => { - const { setEndpoint } = useGlobalsActions() - const { setData } = useAuthActions() - - // Create query client which it can be used from overall in the app - const queryClient = new QueryClient() - - // on app initial load save Endpoint and URL_STATE_KEY so it can be - // used from overall in the application - useEffect(() => { - // set default endpoint so the useQueryClientFn can be used - setEndpoint(props.endpoint || window.location.origin) - }, []) - - // fetch the mocked auth object and save it globally - const oidc = React.useMemo(() => { - // force fetch mocked session - return mockedSession({ - initialLogin: true, - onUpdate: (data) => { - setData(data) - }, - }) - }, []) - - // setup the mock db.json - useEffect(() => { - fetchProxyInitDB(db) - }, []) - - console.log("[exampleapp] embedded mode:", props.embedded) - - return ( - - - - - - } - embedded={props.embedded === "true" || props.embedded === true} - > - - - - - - ) -} - -const StyledApp = (props) => { - return ( - - {/* load styles inside the shadow dom */} - - - - - - - - ) -} -export default StyledApp diff --git a/apps_deprecated/exampleapp/src/App.test.js b/apps_deprecated/exampleapp/src/App.test.js deleted file mode 100644 index 3b33c0e99..000000000 --- a/apps_deprecated/exampleapp/src/App.test.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { render } from "@testing-library/react" -// support shadow dom queries -// https://reactjsexample.com/an-extension-of-dom-testing-library-to-provide-hooks-into-the-shadow-dom/ -import { screen } from "shadow-dom-testing-library" -import App from "./App" - -test("renders app", () => { - render() - const loginTitle = screen.queryAllByShadowText(/Converged Cloud/i) - expect(loginTitle.length > 0).toBe(true) -}) diff --git a/apps_deprecated/exampleapp/src/components/AppContent.js b/apps_deprecated/exampleapp/src/components/AppContent.js deleted file mode 100644 index 575b80436..000000000 --- a/apps_deprecated/exampleapp/src/components/AppContent.js +++ /dev/null @@ -1,112 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect, useState } from "react" -import { - Breadcrumb, - BreadcrumbItem, - Container, - Button, - MainTabs, - Tab, - TabList, - TabPanel, - Select, - SelectOption, -} from "juno-ui-components" -import { - useGlobalsActions, - useGlobalsTabIndex, - useAuthLoggedIn, - useAuthError, -} from "./StoreProvider" -import { useActions, Messages } from "messages-provider" -import ModalManager from "./ModalManager" -import PanelManager from "./PanelManager" -import Peaks from "./peaks/Peaks" -import WelcomeView from "./WelcomeView" - -const AppContent = (props) => { - const { setTabIndex, setCurrentModal } = useGlobalsActions() - const loggedIn = useAuthLoggedIn() - const authError = useAuthError() - const tabIndex = useGlobalsTabIndex() - const { addMessage } = useActions() - - // set an error message when oidc fails - useEffect(() => { - if (authError) { - addMessage({ - variant: "error", - text: parseError(authError), - }) - } - }, [authError]) - - const onTabSelected = (index) => { - setTabIndex(index) - } - - return ( - <> - {loggedIn && !authError ? ( - <> - - - - - - - - Peaks - Tab Two - - - - - {/* Set the background graphic using tailwind background image syntax as below. The image must exist at the specified location in your app */} - {/* - This is the fancy introbox variant for apps that have some app specific flavor branding with a special background graphic. - */} - {/* Messages always at the top of the content area or if there is a hero introbox directly underneath that */} - - - - - - - -

Test a panel pressing the Button

- - - ) : ( - "Looks like the auth app is missing!" - )} - - )} - - )} - - ) -} - -export default Auth diff --git a/apps_deprecated/greenhouse/src/components/Avatar.jsx b/apps_deprecated/greenhouse/src/components/Avatar.jsx deleted file mode 100644 index 6e41eb812..000000000 --- a/apps_deprecated/greenhouse/src/components/Avatar.jsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack } from "juno-ui-components" - -const avatarCss = ` -h-8 -w-8 -bg-theme-background-lvl-2 -rounded-full -bg-cover -` - -const Avatar = ({ userName, url }) => { - return ( - - {url && ( -
- )} - {userName && {userName}} - - ) -} - -export default Avatar diff --git a/apps_deprecated/greenhouse/src/components/NotificationsContainer.jsx b/apps_deprecated/greenhouse/src/components/NotificationsContainer.jsx deleted file mode 100644 index 61afdffc8..000000000 --- a/apps_deprecated/greenhouse/src/components/NotificationsContainer.jsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Messages } from "messages-provider" -import { useDemoMode } from "./StoreProvider" - -const NotificationsContainer = () => { - const demoMode = useDemoMode() - - return ( - <> - {demoMode && ( -
- Welcome to the Greenhouse demo system! We're glad you're here! Just a - quick heads up: you won't find any live data here. Enjoy exploring! -
- )} - {/* do not use a container here to align the messages to the ones coming from each plugin */} - - - ) -} - -export default NotificationsContainer diff --git a/apps_deprecated/greenhouse/src/components/Plugin.jsx b/apps_deprecated/greenhouse/src/components/Plugin.jsx deleted file mode 100644 index 45ac97e77..000000000 --- a/apps_deprecated/greenhouse/src/components/Plugin.jsx +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect, useState, useMemo, useRef } from "react" -import { useAppLoader } from "utils" -import { usePlugin, useGlobalsAssetsHost } from "../components/StoreProvider" -import { Messages, useActions } from "messages-provider" -import { parseError } from "../lib/helpers" -import { Stack, Button } from "juno-ui-components" - -const Plugin = ({ id }) => { - const assetsHost = useGlobalsAssetsHost() - const { mount } = useAppLoader(assetsHost) - const holder = useRef() - const config = usePlugin().config() - const activeApps = usePlugin().active() - const { addMessage } = useActions() - - const [displayReload, setDisplayReload] = useState(false) - const [reload, setReload] = useState(0) - const [isMounted, setIsMounted] = useState(false) - - // element to mount the app - const el = document.createElement("div") - el.classList.add("inline") - const app = useRef(el) - - // mount the app each time the component is reloaded losing the state - useEffect(() => { - if (!mount || !assetsHost || !config) return - // mount the app - mount(app.current, { - ...config[id], - props: { ...config[id]?.props, embedded: true }, - }) - .then((loaded) => { - if (!loaded) return - setIsMounted(true) - }) - .catch((error) => { - setDisplayReload(true) - addMessage({ - variant: "error", - text: `${config?.name}: ` + parseError(error), - }) - }) - }, [mount, reload, config, assetsHost]) - - const displayPluging = useMemo( - () => activeApps.indexOf(id) >= 0, - [activeApps, config] - ) - - useEffect(() => { - if (!config[id] || !isMounted) return - - if (displayPluging) { - // add to holder - holder.current.appendChild(app.current) - } else { - // remove from holder - if (holder.current.contains(app.current)) - holder.current.removeChild(app.current) - } - }, [isMounted, displayPluging]) - - return ( -
- {displayPluging && ( - <> - - {displayReload && ( - -

- Uh-oh! Our plugin {config?.label} encountered a hiccup.{" "} -

-

- No worries, just give it a little nudge by clicking the{" "} - Reload button below. -

-
- ) -} - -export default Plugin diff --git a/apps_deprecated/greenhouse/src/components/PluginContainer.jsx b/apps_deprecated/greenhouse/src/components/PluginContainer.jsx deleted file mode 100644 index 70fe7e8d4..000000000 --- a/apps_deprecated/greenhouse/src/components/PluginContainer.jsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import Plugin from "./Plugin" -import { usePlugin, useGlobalsEnvironment } from "../components/StoreProvider" -import useApi from "../hooks/useApi" -import { useLayoutEffect } from "react" -import HintLoading from "./shared/HintLoading" -import { parseError } from "../lib/helpers" -import { useActions, MessagesProvider } from "messages-provider" - -const PluginContainer = () => { - const { getPluginConfigs } = useApi() - const environment = useGlobalsEnvironment() - const config = usePlugin().config() - const isFetching = usePlugin().isFetching() - const { addMessage } = useActions() - - // prevent to load a plugin before the config is fetched to avoid rerendering do tue the default plugin greenhouse-mng - const [displayPlugin, setDisplayPlugin] = React.useState(false) - - const requestConfig = usePlugin().requestConfig - const receiveConfig = usePlugin().receiveConfig - const receiveError = usePlugin().receiveError - - const availableAppIds = React.useMemo(() => Object.keys(config), [config]) - - useLayoutEffect(() => { - if (!getPluginConfigs) return - requestConfig() - - // fetch configs from kubernetes - getPluginConfigs() - .then((kubernetesConfig) => { - receiveConfig(kubernetesConfig) - }) - .catch((error) => { - // error fetching configs - receiveError(error.message) - addMessage({ - variant: "error", - text: parseError(error), - }) - }) - .finally(() => { - setDisplayPlugin(true) - }) - }, [getPluginConfigs, environment]) - - return ( - <> - {displayPlugin && - availableAppIds.length > 0 && - availableAppIds.map((id, i) => ( - - - - ))} - {!isFetching && - !displayPlugin && - availableAppIds.length <= 0 && - "No plugins available."} - - ) -} - -export default PluginContainer diff --git a/apps_deprecated/greenhouse/src/components/StoreProvider.jsx b/apps_deprecated/greenhouse/src/components/StoreProvider.jsx deleted file mode 100644 index 15d54f269..000000000 --- a/apps_deprecated/greenhouse/src/components/StoreProvider.jsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { createContext, useContext } from "react" -import { useStore as create } from "zustand" -import createStore from "../lib/store" - -const StoreContext = createContext() -const StoreProvider = ({ options, children }) => ( - - {children} - -) - -// build a hook from the store -const useStore = (selector) => create(useContext(StoreContext).store, selector) - -// AUTH -export const useAuthData = () => useStore((s) => s.auth.data) -export const useAuthIsProcessing = () => useStore((s) => s.auth.isProcessing) -export const useAuthLoggedIn = () => useStore((s) => s.auth.loggedIn) -export const useAuthError = () => useStore((s) => s.auth.error) -export const useAuthLastAction = () => useStore((s) => s.auth.lastAction) -export const useAuthAppLoaded = () => useStore((s) => s.auth.appLoaded) -export const useAuthAppIsLoading = () => useStore((s) => s.auth.appIsLoading) -export const useAuthActions = () => useStore((s) => s.auth.actions) - -// APPS -export const usePlugin = () => useContext(StoreContext).plugin - -// GLOBAL -export const useGlobalsApiEndpoint = () => - useStore((s) => s.globals.apiEndpoint) -export const useGlobalsAssetsHost = () => useStore((s) => s.globals.assetsHost) -export const useGlobalsIsUrlStateSetup = () => - useStore((state) => state.globals.isUrlStateSetup) -export const useGlobalsActions = () => useStore((s) => s.globals.actions) -export const useGlobalsEnvironment = () => - useStore((s) => s.globals.environment) -export const useDemoMode = () => useStore((s) => s.globals.demoMode) -export const useDemoUserToken = () => useStore((s) => s.globals.demoUserToken) - -export default StoreProvider diff --git a/apps_deprecated/greenhouse/src/components/layout/ShellLayout.js b/apps_deprecated/greenhouse/src/components/layout/ShellLayout.js deleted file mode 100644 index b4a7bb88b..000000000 --- a/apps_deprecated/greenhouse/src/components/layout/ShellLayout.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PluginNav from "../nav/PluginNav" -import NotificationsContainer from "../NotificationsContainer" - -const shellStyles = ` - grid - grid-cols-[max-content_auto] - grid-rows-[minmax(100vh,100%)] -` - -const mainStyles = ` - py-4 - pl-4 - bg-theme-global-bg - h-full -` - -const ShellLayout = ({ children }) => { - return ( -
- -
- -
{children}
-
-
- ) -} - -export default ShellLayout diff --git a/apps_deprecated/greenhouse/src/components/layout/ShellLayout.test.js b/apps_deprecated/greenhouse/src/components/layout/ShellLayout.test.js deleted file mode 100644 index b5d252a44..000000000 --- a/apps_deprecated/greenhouse/src/components/layout/ShellLayout.test.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { render, act, renderHook } from "@testing-library/react" -// support shadow dom queries -// https://reactjsexample.com/an-extension-of-dom-testing-library-to-provide-hooks-into-the-shadow-dom/ -import { screen } from "shadow-dom-testing-library" -import ShellLayout from "./ShellLayout" -import StoreProvider from "../StoreProvider" -import { MessagesProvider } from "messages-provider" - -jest.mock("communicator") - -test("renders app", async () => { - await act(() => - render( - - - - - - ) - ) - - let logoTitle = await screen.queryAllByShadowTitle(/Greenhouse/i) - expect(logoTitle.length > 0).toBe(true) -}) diff --git a/apps_deprecated/greenhouse/src/components/nav/PluginNav.js b/apps_deprecated/greenhouse/src/components/nav/PluginNav.js deleted file mode 100644 index f76ff38f8..000000000 --- a/apps_deprecated/greenhouse/src/components/nav/PluginNav.js +++ /dev/null @@ -1,156 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import CCloudShape from "../../assets/ccloud_shape.svg" -import GreenhouseLogo from "../../assets/greenhouse_logo.svg" -import SupernovaIcon from "../../assets/juno_supernova.svg" -import DoopIcon from "../../assets/juno_doop.svg" -import HeurekaIcon from "../../assets/juno_heureka.svg" -import { Icon, Stack, Button } from "juno-ui-components" -import { - useAuthData, - useAuthLoggedIn, - useAuthActions, - usePlugin, -} from "../../components/StoreProvider" -import Avatar from "../Avatar" - -const AppIcon = ({ name }) => { - switch (name) { - case "supernova": - return - case "doop": - return - case "heureka": - return - default: - return - } -} - -const navStyles = ` -bg-juno-grey-blue-11 -py-4 -` - -const navItem = (active) => { - return ` - px-2 - py-3 - w-full - hover:text-theme-high - - ${ - active && - ` - bg-theme-global-bg - border-text-theme-light - border-l-4 - text-white - hover:text-white - ` - } -` -} - -const logoStyles = ` -pb-1 -` - -const logoText = ` -py-2 -font-bold -text-sm -leading-4 -` - -const appIconStyles = ` - -` - -const appNameStyles = ` -text-xs -break-all -` - -const PluginNav = () => { - const authData = useAuthData() - const loggedIn = useAuthLoggedIn() - const { login, logout } = useAuthActions() - const setActiveApps = usePlugin().setActive - const activeApps = usePlugin().active() - const appConfig = usePlugin().appConfig() - const mngConfig = usePlugin().mngConfig() - - return ( - - - - {appConfig.map((appConf, i) => ( - = 0 - )}`} - role="button" - tabIndex="0" - onClick={() => setActiveApps([appConf.id])} - > - - {appConf.displayName} - - ))} - - - {mngConfig.map((appConf, i) => ( - = 0 - )}`} - role="button" - tabIndex="0" - onClick={() => setActiveApps([appConf.id])} - > - - {appConf.displayName} - - ))} - - - {loggedIn ? ( - <> - - - - ) : ( - - )} - - - - ) -} - -export default PluginNav diff --git a/apps_deprecated/greenhouse/src/components/shared/HintLoading.js b/apps_deprecated/greenhouse/src/components/shared/HintLoading.js deleted file mode 100644 index 65a2f8eec..000000000 --- a/apps_deprecated/greenhouse/src/components/shared/HintLoading.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack, Spinner } from "juno-ui-components" - -const HintLoading = ({ text }) => { - return ( - - - {text ? {text} : Loading...} - - ) -} - -export default HintLoading diff --git a/apps_deprecated/greenhouse/src/hooks/useApi.js b/apps_deprecated/greenhouse/src/hooks/useApi.js deleted file mode 100644 index 35226e05e..000000000 --- a/apps_deprecated/greenhouse/src/hooks/useApi.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useCallback, useMemo } from "react" -import { createClient } from "sapcc-k8sclient" -import { - useAuthData, - useGlobalsApiEndpoint, - useGlobalsAssetsHost, -} from "../components/StoreProvider" -import { createPluginConfig } from "../lib/plugin" - -// get plugin configs from k8s api -const useApi = () => { - const authData = useAuthData() - // const token = useStoreByKey("auth.data?.JWT") - // const groups = useStoreByKey("auth.data?.raw?.groups") - const apiEndpoint = useGlobalsApiEndpoint() - const assetsHost = useGlobalsAssetsHost() - - const namespace = useMemo(() => { - if (!authData?.raw?.groups) return null - const orgString = authData?.raw?.groups.find( - (g) => g.indexOf("organization:") === 0 - ) - if (!orgString) return null - return orgString.split(":")[1] - }, [authData?.raw?.groups]) - - const client = useMemo(() => { - if (!apiEndpoint || !authData?.JWT) return null - return createClient({ apiEndpoint, token: authData?.JWT }) - }, [apiEndpoint, authData?.JWT]) - - const getPluginConfigs = useCallback(() => { - if (!client || !assetsHost || !namespace) return Promise.resolve({}) - - const manifestUrl = new URL("/manifest.json", assetsHost) - return Promise.all([ - // manifest - fetch(manifestUrl).then((r) => r.json()), - // plugin configs - client.get( - `/apis/greenhouse.sap/v1alpha1/namespaces/${namespace}/plugins`, - { - limit: 500, - } - ), - ]).then(([manifest, configs]) => { - // console.log("::::::::::::::::::::::::manifest", manifest) - // console.log("::::::::::::::::::::::::configs", configs.items) - - // create config map - const config = {} - configs.items.forEach((conf) => { - const id = conf.metadata?.name - const name = conf.status?.uiApplication?.name - const displayName = conf.spec?.displayName - const weight = conf.status?.weight - const version = conf.status?.uiApplication?.version - const url = conf.status?.uiApplication?.url - - // only add plugin if the url is from another host or the name with the given version is in the manifest! - if ((url && url.indexOf(assetsHost) < 0) || manifest[name]?.[version]) { - const newConf = createPluginConfig({ - id, - name, - displayName, - weight, - version, - url, - props: conf.spec?.optionValues?.reduce((map, item) => { - map[item.name] = item.value - return map - }, {}), - }) - if (newConf) config[id] = newConf - } - }) - - return config - }) - }, [client, assetsHost, namespace]) - - return { client, getPluginConfigs } -} - -export default useApi diff --git a/apps_deprecated/greenhouse/src/hooks/useCommunication.js b/apps_deprecated/greenhouse/src/hooks/useCommunication.js deleted file mode 100644 index 2826e4131..000000000 --- a/apps_deprecated/greenhouse/src/hooks/useCommunication.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect, useCallback } from "react" -import { broadcast, get, watch } from "communicator" -import { - useAuthAppLoaded, - useAuthIsProcessing, - useAuthError, - useAuthLoggedIn, - useAuthLastAction, - useAuthActions, - useDemoMode, - useDemoUserToken, -} from "../components/StoreProvider" - -const useCommunication = () => { - const authAppLoaded = useAuthAppLoaded() - const authIsProcessing = useAuthIsProcessing() - const authLastAction = useAuthLastAction() - const { setData: authSetData, setAppLoaded: authSetAppLoaded } = - useAuthActions() - const demoMode = useDemoMode() - const demoUserToken = useDemoUserToken() - - const setAuthData = useCallback( - (data) => { - // If we're in demo mode, we need to make sure the JWT is set to the demo user's JWT - if (data?.auth && demoMode && demoUserToken) { - data.auth.JWT = demoUserToken - } - if (data?.auth?.error) - console.warn("Greenhouse: Auth error: ", data?.auth?.error) - authSetData(data) - }, - [authSetData, demoMode, demoUserToken] - ) - - useEffect(() => { - if (!authAppLoaded || authIsProcessing) return - if (authLastAction?.name === "signOn") { - broadcast("AUTH_LOGIN", "greenhouse", { - debug: true, - consumerID: "greenhouse", - }) - } else if (authLastAction?.name === "signOut") { - broadcast("AUTH_LOGOUT", "greenhouse", { - debug: true, - consumerID: "greenhouse", - }) - } - }, [authAppLoaded, authIsProcessing, authLastAction]) - - useEffect(() => { - if (!authSetData || !authSetAppLoaded) return - get("AUTH_APP_LOADED", authSetAppLoaded, { - consumerID: "greenhouse", - debug: true, - }) - const unwatchLoaded = watch("AUTH_APP_LOADED", authSetAppLoaded, { - debug: true, - consumerID: "greenhouse", - }) - - get("AUTH_GET_DATA", setAuthData, { consumerID: "greenhouse", debug: true }) - const unwatchUpdate = watch("AUTH_UPDATE_DATA", setAuthData, { - debug: true, - consumerID: "greenhouse", - }) - - return () => { - if (unwatchLoaded) unwatchLoaded() - if (unwatchUpdate) unwatchUpdate() - } - }, [setAuthData, authSetAppLoaded]) -} - -export default useCommunication diff --git a/apps_deprecated/greenhouse/src/hooks/useUrlState.js b/apps_deprecated/greenhouse/src/hooks/useUrlState.js deleted file mode 100644 index 24f34a29d..000000000 --- a/apps_deprecated/greenhouse/src/hooks/useUrlState.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect, useLayoutEffect } from "react" -import { registerConsumer } from "url-state-provider" -import { - useAuthLoggedIn, - useGlobalsIsUrlStateSetup, - useGlobalsActions, - usePlugin, -} from "../components/StoreProvider" - -// url state manager -const GREENHOUSE_STATE_KEY = "greenhouse" -const ACTIVE_APPS_KEY = "a" -const urlStateManager = registerConsumer(GREENHOUSE_STATE_KEY) - -const useUrlState = () => { - // const { setActive: setActiveApps } = usePlugin.actions() - const setActiveApps = usePlugin().setActive - const activeApps = usePlugin().active() - const appsConfig = usePlugin().config() - const loggedIn = useAuthLoggedIn() - const isUrlStateSetup = useGlobalsIsUrlStateSetup() - const { setIsUrlStateSetup } = useGlobalsActions() - - // Initial state from URL (on login) - useLayoutEffect(() => { - if (!loggedIn || !appsConfig || isUrlStateSetup) return - - let active = urlStateManager.currentState()?.[ACTIVE_APPS_KEY] - if (active) setActiveApps(active.split(",")) - setIsUrlStateSetup(true) - }, [loggedIn, appsConfig, setActiveApps]) - - // sync URL state - useEffect(() => { - if (!loggedIn || !isUrlStateSetup) return - - const newActiveApps = activeApps?.join(",") - // if the current state is the same as the new state, don't push - // this prevents the history from being filled with the same state - // and therefore prevents the forward button from being disabled - // This small optimization allows the user to go back and forth! - if (urlStateManager.currentState()?.[ACTIVE_APPS_KEY] === newActiveApps) - return - - urlStateManager.push({ [ACTIVE_APPS_KEY]: activeApps.join(",") }) - }, [loggedIn, activeApps]) - - useEffect(() => { - const unregisterStateListener = urlStateManager.onChange((state) => { - const newActiveApps = state?.[ACTIVE_APPS_KEY]?.split(",") - setActiveApps(newActiveApps || []) - }) - - // disable this for now, it's annoying! - // This code sets the title of the page if URL changes. - // It was introduced to see different titles in the browser history. - // const unregisterGlobalChangeListener = urlStateManager.onGlobalChange( - // (state) => { - // const url = new URL(window.location) - // document.title = `Greenhouse - ${url.searchParams.get("__s")}` - // } - // ) - - return () => { - unregisterStateListener() - //unregisterGlobalChangeListener() - } - }, []) -} - -export default useUrlState diff --git a/apps_deprecated/greenhouse/src/index.js b/apps_deprecated/greenhouse/src/index.js deleted file mode 100644 index b16f8a89d..000000000 --- a/apps_deprecated/greenhouse/src/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createRoot } from "react-dom/client" -import React from "react" -import { version } from "../package.json" - -const logAppName = (version) => { - const appName = `%c - ____ ____ _____ _____ _ _ _ _ ___ _ _ ____ _____ - / ___| _ \\| ____| ____| \\ | | | | |/ _ \\| | | / ___|| ____| -| | _| |_) | _| | _| | \\| | |_| | | | | | | \\___ \\| _| -| |_| | _ <| |___| |___| |\\ | _ | |_| | |_| |___) | |___ - \\____|_| \\_\\_____|_____|_| \\_|_| |_|\\___/ \\___/|____/|_____| v${version} -` - console.log(appName, "color:green") -} - -logAppName(version) - -// export mount and unmount functions -export const mount = (container, options = {}) => { - import("./Shell").then((App) => { - mount.root = createRoot(container) - mount.root.render(React.createElement(App.default, options?.props)) - }) -} - -export const unmount = () => mount.root && mount.root.unmount() diff --git a/apps_deprecated/greenhouse/src/lib/helpers.js b/apps_deprecated/greenhouse/src/lib/helpers.js deleted file mode 100644 index 531d03702..000000000 --- a/apps_deprecated/greenhouse/src/lib/helpers.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const parseError = (error) => { - let errMsg = JSON.stringify(error) - if (error?.message) { - errMsg = error?.message - try { - errMsg = JSON.parse(error?.message).msg - } catch (error) {} - } - return errMsg -} diff --git a/apps_deprecated/greenhouse/src/lib/plugin.js b/apps_deprecated/greenhouse/src/lib/plugin.js deleted file mode 100644 index 4d3fc40a6..000000000 --- a/apps_deprecated/greenhouse/src/lib/plugin.js +++ /dev/null @@ -1,242 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useStore, createStore } from "zustand" -import { devtools } from "zustand/middleware" -import produce from "immer" -import { managementVersion } from "../../package.json" - -export const NAV_TYPES = { - APP: "app", - MNG: "management", -} - -const pluginConfig = { - id: "", - name: "", - displayName: "", - version: "latest", - url: null, - weight: 0, - navType: NAV_TYPES.APP, - navigable: true, - props: { - id: "", - }, -} - -export const createPluginConfig = (config) => { - // check required attrs - if (!config?.id || !config?.name) { - console.warn( - `[greenhouse]::createPluginConfig: id and name are required. Skipping config: ${config}` - ) - return null - } - - // clone default pluginConfig - const newConfig = { ...pluginConfig } - // update just known attrs - Object.keys(newConfig).forEach((key) => { - // check agains type to update falsy booleans - if (typeof config?.[key] !== "undefined") newConfig[key] = config?.[key] - }) - // check displayName - if (!newConfig?.displayName) newConfig.displayName = newConfig.name - // update id to the props attr - newConfig.props = { ...newConfig.props, id: newConfig.id } - - return newConfig -} - -const filterAndSortConfigByType = (config, navtype) => { - if (typeof config !== "object" || config === null) return [] - return Object.values(config) - .filter((a) => a.navigable) - .filter((a) => a.navType === navtype) - .sort((a, b) => { - // sort by weight, then by name - // if weight is not defined, app is sorted to the end - const w1 = a.weight === undefined ? Infinity : a.weight - const w2 = b.weight === undefined ? Infinity : b.weight - let weightSort = w1 - w2 - weightSort = weightSort > 0 ? 1 : weightSort < 0 ? -1 : 0 - return weightSort || a.displayName.localeCompare(b.displayName) - }) -} - -// if no active app already set will set the app (no mng apps) with the lowest weight -const findActiveAppId = (appConfig) => { - if (!appConfig || appConfig.length === 0) return null - - // if there is no active app, then from appsConfig, get the app id of the app with the lowest weight and set it as active - const minWeightApp = appConfig.reduce((previous, current) => { - return current.weight < previous.weight ? current : previous - }) - - return [minWeightApp.id] -} - -const Plugin = ({ environment, apiEndpoint, currentHost }) => { - const store = createStore( - devtools((set, get) => ({ - active: [], - config: { - [`greenhouse-management`]: createPluginConfig({ - id: "greenhouse-management", - name: "greenhouse-management", - displayName: "Organization", - version: environment =='qa' || environment == 'development' ? 'latest' : managementVersion, // pull latest version in dev and qa - navType: NAV_TYPES.MNG, - props: { - assetsUrl: currentHost, - apiEndpoint: apiEndpoint, - environment: environment, - }, - }), - }, - appConfig: [], // kube app configs - mngConfig: [], // management app configs - isFetching: false, - error: null, - updatedAt: null, - })) - ) - const { getState, setState } = store - - const setIsFetching = (newState) => { - setState( - produce((state) => { - state.isFetching = newState - }), - false, - "plugin/setIsFetching" - ) - } - - const setError = (error) => - setState( - produce((state) => { - state.error = error - }), - false, - "plugin/setError" - ) - - const setActive = (active) => - setState( - produce((state) => { - if (!Array.isArray(active)) active = [active] - // if the current state is the same as the new state, don't update - if (JSON.stringify(state.active) === JSON.stringify(active)) return - state.active = active - }), - false, - "plugin/setActive" - ) - - // const addActive = (appName) => - // setState( - // produce((state) => { - // const index = getState().active.findIndex((i) => i === appName) - // if (index >= 0) return - // const newActive = getState().active.slice() - // newActive.push(appName) - // state.active = newActive - // }), - // false, - // "plugin/addActive" - // ) - - // const removeActive = (appName) => - // setState( - // produce((state) => { - // const index = getState().active.findIndex((i) => i === appName) - // if (index < 0) return - // let newActive = getState().active.slice() - // newActive.splice(index, 1) - // state.active = newActive - // }), - // false, - // "plugin/removeActive" - // ) - - const addConfig = (config) => - setState( - produce((state) => { - state.config = { ...getState().config, ...config } - }), - false, - "plugin/addConfig" - ) - - const splitApps = () => { - const allConfig = getState().config - const appConfig = filterAndSortConfigByType(allConfig, NAV_TYPES.APP) - setAppConfig(appConfig) - const mngConfig = filterAndSortConfigByType(allConfig, NAV_TYPES.MNG) - setMngConfig(mngConfig) - } - - const setAppConfig = (appConfig) => - setState( - produce((state) => { - state.appConfig = appConfig - }), - false, - "plugin/setAppConfig" - ) - - const setMngConfig = (mngConfig) => - setState( - produce((state) => { - state.mngConfig = mngConfig - }), - false, - "plugin/setMngConfig" - ) - - return { - active: () => useStore(store, (s) => s.active), - config: () => useStore(store, (s) => s.config), - appConfig: () => useStore(store, (s) => s.appConfig), - mngConfig: () => useStore(store, (s) => s.mngConfig), - isFetching: () => useStore(store, (s) => s.isFetching), - error: () => useStore(store, (s) => s.error), - updatedAt: () => useStore(store, (s) => s.updatedAt), - setActive: setActive, - requestConfig: () => { - setIsFetching(true) - setError(null) - }, - receiveError: (error) => { - setIsFetching(false) - setError(error) - // on api error split then the preconfigured - splitApps() - }, - receiveConfig: (kubeConfig) => { - // add config and other states - addConfig(kubeConfig) - setIsFetching(false) - setError(null) - - // split apps in mng and apps - splitApps() - - // if no config found in the active apps set a new one but from the apps and not mng - if ( - Object.keys(getState().config).filter((key) => - getState().active.includes(key) - ).length === 0 - ) { - const newActiveApp = findActiveAppId(getState().appConfig) - setActive(newActiveApp) - } - }, - } -} - -export default Plugin diff --git a/apps_deprecated/greenhouse/src/lib/plugin.test.js b/apps_deprecated/greenhouse/src/lib/plugin.test.js deleted file mode 100644 index 7a26ddd01..000000000 --- a/apps_deprecated/greenhouse/src/lib/plugin.test.js +++ /dev/null @@ -1,173 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { createPluginConfig, NAV_TYPES } from "./plugin" -import StoreProvider, { usePlugin } from "../components/StoreProvider" -import { renderHook, act } from "@testing-library/react" - -describe("Plugin", () => { - describe("createPluginConfig", () => { - it("requires at least an id and name", () => { - const spy = jest.spyOn(console, "warn").mockImplementation(() => {}) - - createPluginConfig() - createPluginConfig({ id: "test" }) - createPluginConfig({ name: "test" }) - - expect(spy).toHaveBeenCalledTimes(3) - expect(spy).toHaveBeenCalledWith( - expect.stringContaining( - "[greenhouse]::createPluginConfig: id and name are required." - ) - ) - spy.mockRestore() - }) - - it("maps name to displayName if missing", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ displayName: "name_test" }) - ) - }) - - it("sets weight to default 0 if missing", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ weight: 0 }) - ) - }) - - it("sets version to latest if missing", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ version: "latest" }) - ) - }) - - it("sets navigable to true if missing", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ navigable: true }) - ) - }) - - it("sets navigation type to app", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ navType: NAV_TYPES.APP }) - ) - }) - - it("adds id to the props", () => { - expect(createPluginConfig({ id: "id_test", name: "name_test" })).toEqual( - expect.objectContaining({ - props: expect.objectContaining({ id: "id_test" }), - }) - ) - }) - - it("does not save not known keys", () => { - expect( - createPluginConfig({ - id: "id_test", - name: "name_test", - miau: "bup", - }) - ).not.toEqual( - expect.objectContaining({ - miau: "bup", - }) - ) - }) - - it("creates a plugin", () => { - const config = { - id: "id_test", - name: "name_test", - displayName: "displayName_Test", - version: "1.2.3", - url: "http://miau.bup", - weight: 9, - navigable: false, - navType: NAV_TYPES.MNG, - props: { - test1: "test1", - test2: "test2", - }, - } - expect(createPluginConfig(config)).toEqual({ - ...config, - props: { ...config.props, id: config.id }, - }) - }) - }) - - describe("savePlugin", () => { - describe("set active plugin", () => { - it("keeps active plugin if existing in the config", () => { - const wrapper = ({ children }) => ( - {children} - ) - - const store = renderHook( - () => ({ - setActive: usePlugin().setActive, - receiveConfig: usePlugin().receiveConfig, - active: usePlugin().active(), - }), - { wrapper } - ) - - const configs = { - plugin1: createPluginConfig({ - id: "plugin1", - name: "plugin1", - weight: 9, - }), - plugin2: createPluginConfig({ - id: "plugin2", - name: "plugin2", - weight: 0, - }), - } - - act(() => store.result.current.setActive(["plugin1"])) - act(() => store.result.current.receiveConfig(configs)) - expect(store.result.current.active).toEqual(["plugin1"]) - }) - it("sets a new active plugin (from apps and not from mng) with the lowest weight", () => { - const wrapper = ({ children }) => ( - {children} - ) - - const store = renderHook( - () => ({ - receiveConfig: usePlugin().receiveConfig, - active: usePlugin().active(), - }), - { wrapper } - ) - - const configs = { - plugin0: createPluginConfig({ - id: "plugin0", - name: "plugin0", - weight: 0, - navType: NAV_TYPES.MNG, - }), - plugin1: createPluginConfig({ - id: "plugin1", - name: "plugin1", - weight: 9, - }), - plugin2: createPluginConfig({ - id: "plugin2", - name: "plugin2", - weight: 1, - }), - } - - act(() => store.result.current.receiveConfig(configs)) - expect(store.result.current.active).toEqual(["plugin2"]) - }) - }) - }) -}) diff --git a/apps_deprecated/greenhouse/src/lib/store/createAuthDataSlice.js b/apps_deprecated/greenhouse/src/lib/store/createAuthDataSlice.js deleted file mode 100644 index 671517788..000000000 --- a/apps_deprecated/greenhouse/src/lib/store/createAuthDataSlice.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const ACTIONS = { - SIGN_ON: "signOn", - SIGN_OUT: "signOut", -} - -const createAuthDataSlice = (set, get) => ({ - auth: { - data: null, - isProcessing: false, - loggedIn: false, - error: null, - lastAction: {}, - appLoaded: false, - appIsLoading: false, - - actions: { - setAppLoaded: (appLoaded) => { - set( - (state) => ({ auth: { ...state.auth, appLoaded } }), - false, - "auth/setAppLoaded" - ) - }, - setData: (data = {}) => { - set( - (state) => ({ - auth: { - ...state.auth, - isProcessing: data ? data.isProcessing : false, - loggedIn: data ? data.loggedIn : false, - error: data ? data.error : null, - data: data ? data.auth : null, - }, - }), - false, - "auth/setData" - ) - if (!data) get().auth.actions.setAction(ACTIONS.SIGN_OUT) - }, - setAction: (name) => - set( - (state) => ({ - auth: { - ...state.auth, - lastAction: { name: name, updatedAt: Date.now() }, - }, - }), - false, - "auth/setAction" - ), - login: () => { - // logout - get().auth.actions.setAction(ACTIONS.SIGN_OUT) - get().auth.actions.setAction(ACTIONS.SIGN_ON) - }, - logout: () => get().auth.actions.setAction(ACTIONS.SIGN_OUT), - }, - }, -}) - -export default createAuthDataSlice diff --git a/apps_deprecated/greenhouse/src/lib/store/createGlobalsSlice.js b/apps_deprecated/greenhouse/src/lib/store/createGlobalsSlice.js deleted file mode 100644 index 66e33fdbc..000000000 --- a/apps_deprecated/greenhouse/src/lib/store/createGlobalsSlice.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const createGlobalsSlice = (set, get) => ({ - globals: { - apiEndpoint: "", - assetsHost: "", - environment: "", - isUrlStateSetup: false, - demoMode: false, - demoUserToken: null, - - actions: { - setDemoMode: (demoMode) => - set((state) => ({ globals: { ...state.globals, demoMode } })), - setDemoUserToken: (demoUserToken) => - set((state) => ({ globals: { ...state.globals, demoUserToken } })), - - setApiEndpoint: (value) => - set( - (state) => ({ globals: { ...state.globals, apiEndpoint: value } }), - false, - "globals/setApiEndpoint" - ), - - setEnvironment: (value) => - set( - (state) => ({ globals: { ...state.globals, environment: value } }), - false, - "globals/setEnvironment" - ), - setAssetsHost: (value) => - set( - (state) => ({ globals: { ...state.globals, assetsHost: value } }), - false, - "globals/setAssetsHost" - ), - setIsUrlStateSetup: (setup) => - set( - (state) => ({ - globals: { ...state.globals, isUrlStateSetup: setup }, - }), - false, - "globals/setIsUrlStateSetup" - ), - }, - }, -}) - -export default createGlobalsSlice diff --git a/apps_deprecated/greenhouse/src/lib/store/index.js b/apps_deprecated/greenhouse/src/lib/store/index.js deleted file mode 100644 index 75e693236..000000000 --- a/apps_deprecated/greenhouse/src/lib/store/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createStore } from "zustand" -import { devtools } from "zustand/middleware" -import createAuthDataSlice from "./createAuthDataSlice" -import createGlobalsSlice from "./createGlobalsSlice" -import Plugin from "../plugin" - -export default (options) => { - const store = createStore( - devtools((set, get) => ({ - ...createAuthDataSlice(set, get), - ...createGlobalsSlice(set, get), - })) - ) - - const plugin = Plugin(options) - - return { store, plugin } -} diff --git a/apps_deprecated/greenhouse/src/styles.scss b/apps_deprecated/greenhouse/src/styles.scss deleted file mode 100644 index f3b5dd36d..000000000 --- a/apps_deprecated/greenhouse/src/styles.scss +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -/* Do not remove these tailwind directives. Without them styles won't work as expected */ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* If necessary, app styles can be added below */ - - diff --git a/apps_deprecated/greenhouse/tailwind.config.js b/apps_deprecated/greenhouse/tailwind.config.js deleted file mode 100644 index 81b1f8fef..000000000 --- a/apps_deprecated/greenhouse/tailwind.config.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// opacity helper to make custom colors work with opacity -function withOpacity(variableName) { - return ({ opacityVariable, opacityValue }) => { - if (opacityValue !== undefined) { - return `rgba(var(${variableName}), ${opacityValue})` - } - if (opacityVariable !== undefined) { - return `rgba(var(${variableName}), var(${opacityVariable}, 1))` - } - return `rgb(var(${variableName}))` - } -} - -module.exports = { - presets: [ - require("juno-ui-components/build/lib/tailwind.config"), // important, do not change - ], - prefix: "", // important, do not change - content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], - corePlugins: { - preflight: false, // important, do not change - }, - theme: {}, - plugins: [], -} diff --git a/apps_deprecated/heureka/LICENSE b/apps_deprecated/heureka/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/apps_deprecated/heureka/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/apps_deprecated/heureka/README.md b/apps_deprecated/heureka/README.md deleted file mode 100644 index c26779fde..000000000 --- a/apps_deprecated/heureka/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/greenhouse-extensions](https://github.com/cloudoperators/greenhouse-extensions) for the latest updates and active development. - -# Heureka - -This mircro frontent uses the Heureka POC API which aims to: - -- Track the overall state of our technology landscape -- Establish a unified & complete Patch Management Process: - - Maintain & track vulnerabilities and affected components - - Document the remediation, classification, and impact of vulnerabilities - - Document the changes corresponding with patching of vulnerabilities, as well as updating components diff --git a/apps_deprecated/heureka/__mocks__/client.js b/apps_deprecated/heureka/__mocks__/client.js deleted file mode 100644 index 84531d3c2..000000000 --- a/apps_deprecated/heureka/__mocks__/client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { JSDOM } from "jsdom" -const dom = new JSDOM() -global.document = dom.window.document -global.window = dom.window diff --git a/apps_deprecated/heureka/__mocks__/fileMock.js b/apps_deprecated/heureka/__mocks__/fileMock.js deleted file mode 100644 index 27ce65aca..000000000 --- a/apps_deprecated/heureka/__mocks__/fileMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = "test-file-stub" diff --git a/apps_deprecated/heureka/__mocks__/styleMock.js b/apps_deprecated/heureka/__mocks__/styleMock.js deleted file mode 100644 index d74516001..000000000 --- a/apps_deprecated/heureka/__mocks__/styleMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = {} diff --git a/apps_deprecated/heureka/babel.config.js b/apps_deprecated/heureka/babel.config.js deleted file mode 100644 index 0719e2fec..000000000 --- a/apps_deprecated/heureka/babel.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - env: { - test: { - presets: ["@babel/preset-env", "@babel/preset-react"], - plugins: [["babel-plugin-transform-import-meta", { module: "ES6" }]], - }, - }, -} diff --git a/apps_deprecated/heureka/esbuild.config.js b/apps_deprecated/heureka/esbuild.config.js deleted file mode 100644 index e09482676..000000000 --- a/apps_deprecated/heureka/esbuild.config.js +++ /dev/null @@ -1,205 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const esbuild = require("esbuild") -const fs = require("node:fs/promises") -const pkg = require("./package.json") -const postcss = require("postcss") -const sass = require("sass") -const { transform } = require("@svgr/core") -const url = require("postcss-url") -// this function generates app props based on package.json and propSecrets.json -const appProps = require("../../helpers/appProps") - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) - -const isProduction = process.env.NODE_ENV === "production" -// If the jspm server fails and we cannot use external packages -// in our import map then IGNORE_EXTERNALS (global env variable) -// should be set to true -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" -// in dev environment we prefix output file with public -let outfile = `${isProduction ? "" : "public/"}${pkg.main || pkg.module}` -// get output from outputfile -let outdir = outfile.slice(0, outfile.lastIndexOf("/")) -const args = process.argv.slice(2) -const watch = args.indexOf("--watch") >= 0 -const serve = args.indexOf("--serve") >= 0 - -// helpers for console log -const green = "\x1b[32m%s\x1b[0m" -const yellow = "\x1b[33m%s\x1b[0m" -const clear = "\033c" - -const build = async () => { - // delete build folder and re-create it as an empty folder - await fs.rm(outdir, { recursive: true, force: true }) - await fs.mkdir(outdir, { recursive: true }) - - // build app - let ctx = await esbuild.context({ - bundle: true, - minify: isProduction, - // target: ["es2020"], - target: ["es2020"], //["chrome64", "firefox67", "safari11.1", "edge79"], - format: "esm", - platform: "browser", - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - loader: { ".js": "jsx" }, - sourcemap: !isProduction, - // here we exclude package from bundle which are defined in peerDependencies - // our importmap generator uses also the peerDependencies to create the importmap - // it means all packages defined in peerDependencies are in browser available via the importmap - external: - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [], - entryPoints: [pkg.source], - outdir, - // this step is important for performance reason. - // the main file (index.js) contains minimal code needed to - // load the app via dynamic import (splitting: true) - splitting: true, - // we suport only esm! - format: "esm", - plugins: [ - // minimal plugin to log the recompiling process. - { - name: "start/end", - setup(build) { - build.onStart(() => { - console.log(yellow, "Compiling...") - }) - build.onEnd(() => console.log(green, "Done!")) - }, - }, - - // this custom plugin rewrites SVG imports to - // dataurls, paths or react components based on the - // search param and size - { - name: "svg-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(svg)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - let loader = "text" - if (args.suffix === "?url") { - // as URL - const maxSize = 10240 // 10Kb - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - } else { - // as react component - // use react component loader (jsx) - loader = "jsx" - contents = await transform(contents, { - plugins: ["@svgr/plugin-jsx"], - }) - } - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin rewrites image imports to - // dataurls or urls based on the size - { - name: "image-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(png|jpg|jpeg|gif)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - const maxSize = 10240 // 10Kb - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin parses the style files - { - name: "parse-styles", - setup(build) { - build.onLoad( - // consider only .scss and .css files - { filter: /.\.(css|scss)$/, namespace: "file" }, - async (args) => { - let content - // handle scss, convert to css - if (args.path.endsWith(".scss")) { - const result = sass.renderSync({ file: args.path }) - content = result.css - } else { - // read file content - content = await fs.readFile(args.path) - } - - // postcss plugins - const plugins = [ - require("tailwindcss"), - require("autoprefixer"), - // rewrite urls inside css - url({ - url: "inline", - // maxSize: 10, // use dataurls if files are smaller than 10k - // fallback: "copy", // if files are bigger use copy method - // assetsPath: "./build/assets", - // useHash: true, - // optimizeSvgEncode: true, - }), - ] - - const { css } = await postcss(plugins).process(content, { - from: args.path, - to: outdir, - }) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - return { contents: css, loader: "text" } - } - ) - }, - }, - ], - }) - - // watch and serve - if (watch || serve) { - if (watch) await ctx.watch() - if (serve) { - // generate app props based on package.json and secretProps.json - await fs.writeFile( - `./${outdir}/appProps.js`, - `export default ${JSON.stringify(appProps())}` - ) - - let { host, port } = await ctx.serve({ - host: "0.0.0.0", - port: parseInt(process.env.APP_PORT || process.env.PORT || 3000), - servedir: "public", - }) - console.log("serve on", `${host}:${port}`) - } - } else { - await ctx.rebuild() - await ctx.dispose() - } -} - -build() diff --git a/apps_deprecated/heureka/jest.config.js b/apps_deprecated/heureka/jest.config.js deleted file mode 100644 index 58feee149..000000000 --- a/apps_deprecated/heureka/jest.config.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - transform: { "\\.[jt]sx?$": "babel-jest" }, - testEnvironment: "jsdom", - setupFilesAfterEnv: ["/setupTests.js"], - transformIgnorePatterns: [ - "node_modules/(?!(juno-ui-components|url-state-router|communicator|oauth)/)", - ], - moduleNameMapper: { - // Jest currently doesn't support resources with query parameters. - // Therefore we add the optional query parameter matcher at the end - // https://github.com/facebook/jest/issues/4181 - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)(\\?.+)?$": - require.resolve("./__mocks__/fileMock"), - "\\.(css|less|scss)$": require.resolve("./__mocks__/styleMock"), - }, -} diff --git a/apps_deprecated/heureka/package.json b/apps_deprecated/heureka/package.json deleted file mode 100644 index 898b9f086..000000000 --- a/apps_deprecated/heureka/package.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "name": "heureka", - "version": "2.0.4", - "author": "UI-Team", - "contributors": [ - "Arturo Reuschenbach Pucernau" - ], - "repository": "https://github.com/sapcc/juno/tree/main/apps/heureka", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/greenhouse-extensions for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "module": "build/index.js", - "source": "src/index.js", - "private": true, - "devDependencies": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0", - "@tanstack/react-query": "4.28.0", - "@testing-library/dom": "^8.19.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "assert": "^2.0.0", - "autoprefixer": "^10.4.2", - "babel-jest": "^29.3.1", - "babel-plugin-transform-import-meta": "^2.2.0", - "communicator": "https://assets.juno.global.cloud.sap/libs/communicator@2.2.6/package.tgz", - "esbuild": "^0.19.4", - "graphql-request": "^6.0.0", - "immer": "^9.0.21", - "jest": "^29.3.1", - "jest-environment-jsdom": "^29.3.1", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.13.8/package.tgz", - "luxon": "^2.3.0", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "postcss": "^8.4.21", - "postcss-url": "^10.1.3", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-test-renderer": "18.2.0", - "sass": "^1.60.0", - "shadow-dom-testing-library": "^1.7.1", - "tailwindcss": "^3.3.1", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "util": "^0.12.4", - "zustand": "4.5.2" - }, - "scripts": { - "test": "jest", - "start": "NODE_ENV=development node esbuild.config.js --serve --watch", - "build": "NODE_ENV=production node esbuild.config.js", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prestart": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "peerDependencies": { - "@tanstack/react-query": "4.28.0", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.13.8/package.tgz", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "zustand": "4.5.2" - }, - "importmapExtras": { - "zustand/middleware": "4.5.2" - }, - "appProps": { - "theme": { - "value": "theme-dark", - "type": "optional", - "description": "Override the default theme. Possible values are theme-light or theme-dark (default)" - }, - "apiEndpoint": { - "value": "", - "type": "required", - "description": "Endpoint URL of the API" - }, - "embedded": { - "value": "false", - "type": "optional", - "description": "Set to true if app is to be embedded in another existing app or page, like e.g. Elektra. If set to true the app won't render a page header/footer and instead render only the content. The default value is false." - } - }, - "appPreview": true -} diff --git a/apps_deprecated/heureka/public/favicon.ico b/apps_deprecated/heureka/public/favicon.ico deleted file mode 100644 index 9ebc4bb2e04736789f9fcfe03121b296c693079a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHOc~DkW6h8=vpa^PaX3JM9iaLr~+M@BPg-&UinG_1xqN9VFP8qhyVv3gI5)y)q zTINC;R?|K;#Z=Q?rdcjEfL2psi+^QPO{eqwE|2&4e8Bs@_ib;6J9D_-d+*+Je)rsS zw{s6fQ4~#SX(YLes`?X+A|jWo@j02OR^BB`j_>ngh)SfuKq(_tXtogEds07@wedGr zzRwh@rmJplpzU=``%W`${FrIleN26aGbMIs`5p@TOXSoGJtveUB&};Tx#jC|A*LG_ zG41`GX~z#t*Uo0@5FHArF33-gz4hJZSf5CcVNu%YJgjw z6?WGUracWzyMAW6WN4_dS(OK@>5XlGO&t+Zbqiipx}UPZDz9*rJ0_ShR%bO~A9#hr zzU3%WY^QMH@_-h3_=2)hvD5l*q zW--@al459QQcid2PTLeyU!zA+Owd_+jT$7c2behY2~(YeQ@t)2cUB8>)U~ zns~SK+R*Jhri!oieptGbsdqnTwWE7)rblb^HsCDt$m>kg?`KNCjcN20rt#TKBPT^} zyW--RW-McR=10997#Bv$d?0f1YwK3hxlGs3V=8<}=BE?Q@#n0JeEeEFw7g>{rX|}| zI~Hwm9)9CIyY~I?;m0`Cbn0t9{5qxoy?=y$zl#0k!~2zdUvX>Yu})}f_0%Q)>p|mZ z%!iI+TK^GKZiyOq*JLu?FrNwM!pA?=#~*ZOtmo_RIqMZK__z|f+T*3k#yP6^RUM;o zt~36I{`-xzC$pDJKeNr`XO&KQ*tkB7~p4`p09jR^AB`CxdkYr24s`lfsIc~$F=9p9_|!Ttl|aO-z^J5griCrm@ep4~=`Z>V#e z<8E21<_@h5-Z{n!e68>mM22tPTz@!6r%e!_{OxKjLOys5Q+yZm@}bssyS(;(Xt#lI z+JNqZc3wXK`^k{6)q&GfonU|7!T75Md$xn|BTfK!kl#A64aXa?OGe{`)ctkfY%`d1 z60o|3jA^z!{38@hxq;vf?72c_3H=bswgj7Tn*lex!+5}$#=Z7Qp>VDb+WZbIh!X&| zX6au%r4yY-o}_|pD2}KG&(TCh$fNWekL{^t4HV&%L0>g^7CqJ@7rknF*7S}zEtim6 zs3}fMV!2vLUFBN=^-ViYWe5JFbswsDp&otA&$+(O2WN!;L80YBi9*ISNFM4u@c~bt zRQ|Z&p4||iklF}9tW#vibYw!DMdd?A3*TF?)qQ9(HtB{EG68+u>oS zZpNLe4@ON6j}9>YH+{jht(K`zN_a3JCKGX`xHlMcYj}Kyh_ig+pz4c?Z=|n@Vn3I^V6D872ktS}eZaJI7ZdKqu)b<{ZLl+A+17p|J^_6&BExze@Poe? z_ldv&|2AYJZUc9$R`m})SR={~sIl2+fHe$=p+L;Cub5lX1Lh^n4QNkm^CbFfavoFF zDWHQw}8`_-?><8mC^-78D9Hji$h~+Q+T*(gBdX9d>n8Y5{+y9SsbYX?e z;THSIyM4Ys!;g>n=wahke5Efo<*Tgr@`1HwrBAj043BQH|2%AY4h%d-?7xe`D8E2t z`$(L?&dzPXV`tOQ^|DVgBD(2^8P8oEB7`k^di)d(uQRy?VcE5Voa4@j_)Z zvyiF(W!`11JcCCA6}@bwtXY``PpkmW*mi6TXEem1`pX0R$Q7?i47d1n{N;hThmyC{ zSrKcnzkINlnO|nDzF90PVnJ5F&4hSXGYp6qS@{OjWA8G}DmE`O)U9G{jQT)K2mZ$o z`zJHL-tQ0(1iL`oBjQ^SdoXUMwYo-L@cY>5TO%*?-xv$N<5G1{x6DTUO;R_Zk;f?? P_&~0wZjp_d33dMme?Bb{ diff --git a/apps_deprecated/heureka/public/index.html b/apps_deprecated/heureka/public/index.html deleted file mode 100644 index 3717575f0..000000000 --- a/apps_deprecated/heureka/public/index.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - Heureka Dev - - - - - -
- - diff --git a/apps_deprecated/heureka/setupTests.js b/apps_deprecated/heureka/setupTests.js deleted file mode 100644 index db44c9038..000000000 --- a/apps_deprecated/heureka/setupTests.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom" diff --git a/apps_deprecated/heureka/src/App.js b/apps_deprecated/heureka/src/App.js deleted file mode 100644 index 72feb1488..000000000 --- a/apps_deprecated/heureka/src/App.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect } from "react" -import styles from "./styles.scss" -import { AppShell, AppShellProvider } from "juno-ui-components" -import { QueryClient, QueryClientProvider } from "@tanstack/react-query" -import { MessagesProvider } from "messages-provider" -import AsyncWorker from "./components/AsyncWorker" -import StoreProvider, { useActions } from "./components/StoreProvider" -import TabContext from "./components/tabs/TabContext" - -const App = (props) => { - // Create a client - const queryClient = new QueryClient({ - defaultOptions: { - // global default options that apply to all queries - queries: { - // staleTime: Infinity, // if you wish to keep data from the keys until reload - keepPreviousData: true, // nice when paginating - refetchOnWindowFocus: false, // default: true - }, - }, - }) - - return ( - - - - - - - ) -} - -const StyledApp = (props) => { - return ( - - {/* load styles inside the shadow dom */} - - - - - - - - ) -} - -export default StyledApp diff --git a/apps_deprecated/heureka/src/App.test.js b/apps_deprecated/heureka/src/App.test.js deleted file mode 100644 index df4eb46ea..000000000 --- a/apps_deprecated/heureka/src/App.test.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { render } from "@testing-library/react" -// support shadow dom queries -// https://reactjsexample.com/an-extension-of-dom-testing-library-to-provide-hooks-into-the-shadow-dom/ -import { screen } from "shadow-dom-testing-library" -import App from "./App" - -jest.mock("communicator") - -describe("logged in", () => { - test("renders app", async () => { - render() - const loginTitle = await screen.queryAllByShadowText(/Converged Cloud/i) - expect(loginTitle.length > 0).toBe(true) - }) -}) diff --git a/apps_deprecated/heureka/src/actions.js b/apps_deprecated/heureka/src/actions.js deleted file mode 100644 index 06410e52a..000000000 --- a/apps_deprecated/heureka/src/actions.js +++ /dev/null @@ -1,157 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -class HTTPError extends Error { - constructor(code, message) { - super(message || code) - this.name = "HTTPError" - this.statusCode = code - } -} - -export const encodeUrlParamsFromObject = (options) => { - if (!options) return "" - let encodedOptions = Object.keys(options) - .map((k) => { - if (typeof options[k] === "object") { - const childOption = options[k] - return Object.keys(childOption).map( - (childKey) => - `${encodeURIComponent(childKey)}=${encodeURIComponent( - childOption[childKey] - )}` - ) - } - return `${encodeURIComponent(k)}=${encodeURIComponent(options[k])}` - }) - .join("&") - return `&${encodedOptions}` -} - -const checkStatus = (response) => { - if (response.status < 400) { - return response - } else { - return response.text().then((message) => { - var error = new HTTPError(response.status, message || response.statusText) - error.statusCode = response.status - return Promise.reject(error) - }) - } -} - -// -// SERVICES -// - -export const services = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/services", options) -} - -export const service = ({ queryKey }) => { - const [_key, bearerToken, endpoint, serviceId] = queryKey - return fetchFromAPI(bearerToken, endpoint, `/services/${serviceId}`) -} - -export const serviceFilters = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/services/filters", options) -} - -// -// COMPONENTS -// - -export const components = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/components", options) -} - -export const component = ({ queryKey }) => { - const [_key, bearerToken, endpoint, componentId] = queryKey - return fetchFromAPI(bearerToken, endpoint, `/components/${componentId}`) -} - -export const componentFilters = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/components/filters", options) -} - -// -// VULNERABILITIES -// - -export const vulnerabilities = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/vulnerabilities", options) -} - -export const vulnerability = ({ queryKey }) => { - const [_key, bearerToken, endpoint, vulnerabilityId] = queryKey - return fetchFromAPI( - bearerToken, - endpoint, - `/vulnerabilities/${vulnerabilityId}` - ) -} - -export const vulnerabilityFilters = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI( - bearerToken, - endpoint, - "/vulnerabilities/filters", - options - ) -} - -// -// USERS -// - -export const users = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/users", options) -} - -export const user = ({ queryKey }) => { - const [_key, bearerToken, endpoint, userId] = queryKey - return fetchFromAPI(bearerToken, endpoint, `/users/${userId}`) -} - -export const userFilters = ({ queryKey }) => { - const [_key, bearerToken, endpoint, options] = queryKey - return fetchFromAPI(bearerToken, endpoint, "/users/filters", options) -} - -// -// COMMONS -// - -const fetchFromAPI = (bearerToken, endpoint, path, options) => { - const query = encodeUrlParamsFromObject(options) - return fetch(`${endpoint}${path}?${query}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${bearerToken}`, - }, - }) - .then(checkStatus) - .then((response) => { - let isJSON = response.headers - .get("content-type") - .includes("application/json") - if (!isJSON) { - var error = new HTTPError( - 400, - "The response is not a valid JSON response" - ) - return Promise.reject(error) - } - return response.json() - }) -} diff --git a/apps_deprecated/heureka/src/components/AsyncWorker.jsx b/apps_deprecated/heureka/src/components/AsyncWorker.jsx deleted file mode 100644 index d9728e5e9..000000000 --- a/apps_deprecated/heureka/src/components/AsyncWorker.jsx +++ /dev/null @@ -1,16 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import useUrlState from "../hooks/useUrlState" -import useQueryClientFn from "../hooks/useQueryClientFn" - -const AsyncWorker = () => { - useUrlState() - useQueryClientFn() - return null -} - -export default AsyncWorker diff --git a/apps_deprecated/heureka/src/components/StoreProvider.jsx b/apps_deprecated/heureka/src/components/StoreProvider.jsx deleted file mode 100644 index d601f3d69..000000000 --- a/apps_deprecated/heureka/src/components/StoreProvider.jsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { createContext, useContext } from "react" -import { useStore as create } from "zustand" -import createStore from "../lib/store" - -const StoreContext = createContext() -const StoreProvider = ({ options, children }) => ( - - {children} - -) - -const useStore = (selector) => create(useContext(StoreContext), selector) - -export const useEndpoint = () => useStore((s) => s.endpoint) -export const useQueryClientFnReady = () => useStore((s) => s.queryClientFnReady) -export const useActiveTab = () => useStore((s) => s.activeTab) -export const useQueryOptions = (tab) => - useStore((s) => s.tabs[tab].queryOptions) -export const useActions = () => useStore((s) => s.actions) - -export default StoreProvider diff --git a/apps_deprecated/heureka/src/components/backup/AppContainer.js b/apps_deprecated/heureka/src/components/backup/AppContainer.js deleted file mode 100644 index 776ed1371..000000000 --- a/apps_deprecated/heureka/src/components/backup/AppContainer.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - MainTabs, - TabList, - Tab, - TabPanel, - Icon, - Container, -} from "juno-ui-components" -import { useRouter } from "url-state-router" -import Breadcrumb from "./Breadcrumb" -import { Messages } from "messages-provider" - -const AppContainer = ({ tabsConfig, component, children }) => { - const { navigateTo, currentPath } = useRouter() - - const tabIndex = useMemo(() => { - if (!currentPath) return 0 - return tabsConfig.findIndex((tab) => currentPath.startsWith(tab.path)) - }, [currentPath]) - - return ( - <> - - - {tabsConfig.map((tab, index) => ( - navigateTo(tab.path)}> - - {tab.label} - - ))} - - {tabsConfig.map((tab, index) => ( - - ))} - - - - {component || children} - - - - ) -} - -export default AppContainer diff --git a/apps_deprecated/heureka/src/components/backup/AppRouter.js b/apps_deprecated/heureka/src/components/backup/AppRouter.js deleted file mode 100644 index 716a4a65f..000000000 --- a/apps_deprecated/heureka/src/components/backup/AppRouter.js +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect } from "react" -import { Router, Route, Redirect, Switch } from "url-state-router" -import { useActions, Messages } from "messages-provider" - -import AppContainer from "./AppContainer" -import Services from "./Services" -import ServiceDetail from "./ServiceDetail" -import ChangesLogDetail from "./ChangesLogDetail" -import PatchLogNew from "./PatchLogNew" -import PatchLogDetail from "./PatchLogDetail" -import Components from "./Components" -import ComponentDetail from "./ComponentDetail" -import Vulnerabilities from "./Vulnerabilities" -import VulnerabilitiyDetails from "./VulnerabilitiyDetails" -import Users from "./Users" -import UserDetail from "./UserDetail" -import SupportGroups from "./SupportGroups" -import Home from "./Home" -import useStore from "../hooks/useStore" -import WelcomeView from "./WelcomeView" - -export const HOME_PATH = "/home" -export const SUPPORT_GROUP_PATH = "/support_group" -export const SERVICES_PATH = "/services" -export const COMPONENTS_PATH = "/components" -export const VULNERABILITIES_PATH = "/vulnerabilities" -export const USERS_PATH = "/users" -export const TABS_CONFIG = [ - { path: HOME_PATH, label: "Home", icon: "autoAwesomeMosaic" }, - { path: SERVICES_PATH, label: "Services", icon: "dns" }, - { path: COMPONENTS_PATH, label: "Components", icon: "widgets" }, - { - path: VULNERABILITIES_PATH, - label: "Vulnerabilities", - icon: "autoAwesomeMotion", - }, - { path: SUPPORT_GROUP_PATH, label: "Support group", icon: "manageAccounts" }, - { - path: USERS_PATH, - label: "Users", - icon: "accountCircle", - }, -] - -const AppRouter = (props) => { - const urlStateKey = useStore((state) => state.urlStateKey) - const auth = useStore((state) => state.auth) - const loggedIn = useStore((state) => state.loggedIn) - const login = useStore((state) => state.login) - const { addMessage } = useActions() - const embedded = useStore((state) => state.embedded) - - useEffect(() => { - if (auth?.error) { - addMessage({ - variant: "error", - text: parseError(auth?.error), - }) - } - }, [auth?.error]) - - return ( - <> - {/* wait util the user is logged in to avoid that url-state-router processes the wrong URL do tue Redirects in the login process*/} - {loggedIn && !auth?.error ? ( - <> - {/* wait util the urlStateKey is stored and retrieved to avoid to initialized the Router with nil stateID*/} - {urlStateKey && ( - - - - - - - - - - - - - - - - - - - - - - - - )} - - ) : embedded ? ( - "Authentication required!" - ) : ( - <> - - - - )} - - ) -} - -export default AppRouter diff --git a/apps_deprecated/heureka/src/components/backup/Avatar.js b/apps_deprecated/heureka/src/components/backup/Avatar.js deleted file mode 100644 index 6e41eb812..000000000 --- a/apps_deprecated/heureka/src/components/backup/Avatar.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack } from "juno-ui-components" - -const avatarCss = ` -h-8 -w-8 -bg-theme-background-lvl-2 -rounded-full -bg-cover -` - -const Avatar = ({ userName, url }) => { - return ( - - {url && ( -
- )} - {userName && {userName}} - - ) -} - -export default Avatar diff --git a/apps_deprecated/heureka/src/components/backup/Breadcrumb.js b/apps_deprecated/heureka/src/components/backup/Breadcrumb.js deleted file mode 100644 index 0a12d4708..000000000 --- a/apps_deprecated/heureka/src/components/backup/Breadcrumb.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -const Breadcrumb = ({}) => { - return "Breadcrumb" -} - -export default Breadcrumb diff --git a/apps_deprecated/heureka/src/components/backup/ChangesLogDetail.js b/apps_deprecated/heureka/src/components/backup/ChangesLogDetail.js deleted file mode 100644 index 19844211a..000000000 --- a/apps_deprecated/heureka/src/components/backup/ChangesLogDetail.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - Button, - Panel, - PanelBody, - PanelFooter, - DataGrid, - DataGridRow, - DataGridCell, - Stack, - TextareaRow, -} from "juno-ui-components" -import { - DetailSection, - DetailSectionBox, - DetailContentHeading, - DetailSectionHeader, -} from "../styles" -import { changeLogExample1, changeLogExample2 } from "../helpers" -import { useRouter } from "url-state-router" -import { DateTime } from "luxon" -import ComponentsList from "./ComponentsList" -import { SERVICES_PATH } from "./AppRouter" - -const ChangesLogDetail = ({}) => { - const { options, routeParams, navigateTo } = useRouter() - const changeLogId = routeParams?.changeLogId - const serviceId = routeParams?.serviceId - - const change = useMemo(() => { - if (changeLogId === "4323") { - return changeLogExample1 - } - if (changeLogId === "1234") { - return changeLogExample2 - } - return {} - }, [changeLogId]) - - const createdAt = useMemo(() => { - if (change?.CreatedAt) { - return DateTime.fromSQL(change.CreatedAt).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [change?.CreatedAt]) - - const onPanelClose = () => { - navigateTo(`${SERVICES_PATH}/${serviceId}`) - } - - return ( - - -
-
- - - - ID: - - {change.ID} - - - - Date: - - {createdAt} - - -
-
- {change.Type === "manually" && ( - <> -
-

Components

-
- -
-
- -
- -
- - )} - {change.Type === "automatic" && ( - <> -
-

State before

-
- -
-
-
-

State after

-
- -
-
- - )} -
-
- ) -} - -export default ChangesLogDetail diff --git a/apps_deprecated/heureka/src/components/backup/ChangesLogList.js b/apps_deprecated/heureka/src/components/backup/ChangesLogList.js deleted file mode 100644 index e72dd39c4..000000000 --- a/apps_deprecated/heureka/src/components/backup/ChangesLogList.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import ChangesLogListItem from "./ChangesLogListItem" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "./HintNotFound" - -const ChangesLogList = ({ changes, selectable }) => { - changes = useMemo(() => { - if (!changes) return [] - return changes - }, [changes]) - - const columnsLength = useMemo(() => { - const configurableCols = 4 - return selectable ? configurableCols + 1 : configurableCols - }, [selectable]) - - return ( - <> - - - {selectable && } - ID - Type - Date - Changed components - - {changes.length > 0 ? ( - <> - {changes.map((item, i) => ( - - ))} - - ) : ( - - - - - - )} - - - ) -} - -export default ChangesLogList diff --git a/apps_deprecated/heureka/src/components/backup/ChangesLogListItem.js b/apps_deprecated/heureka/src/components/backup/ChangesLogListItem.js deleted file mode 100644 index 8c304fbf4..000000000 --- a/apps_deprecated/heureka/src/components/backup/ChangesLogListItem.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell, CheckboxRow } from "juno-ui-components" -import { DateTime } from "luxon" -import { Link } from "url-state-router" -import { useRouter } from "url-state-router" -import { SERVICES_PATH } from "./AppRouter" - -const ChangesLogListItem = ({ item, selectable }) => { - const { options, routeParams } = useRouter() - const serviceId = routeParams?.serviceId - - const createdAt = useMemo(() => { - if (item.CreatedAt) { - return DateTime.fromSQL(item.CreatedAt).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [item.CreatedAt]) - - return ( - - {selectable && ( - - - - )} - - - {item.ID} - - - {item.Type} - {createdAt} - - {item.Components.map((component) => component.Name).join(", ")} - - - ) -} - -export default ChangesLogListItem diff --git a/apps_deprecated/heureka/src/components/backup/ComponentDetail.js b/apps_deprecated/heureka/src/components/backup/ComponentDetail.js deleted file mode 100644 index ec843e4d9..000000000 --- a/apps_deprecated/heureka/src/components/backup/ComponentDetail.js +++ /dev/null @@ -1,170 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useMemo } from "react" -import { - Icon, - DataGrid, - DataGridRow, - DataGridCell, - Container, -} from "juno-ui-components" -import { useRouter } from "url-state-router" -import { getComponent } from "../queries" -import { useActions } from "messages-provider" -import useStore from "../hooks/useStore" -import { - usersListToString, - componentDetailsByType, - parseError, -} from "../helpers" -import VulnerabilitiesList from "./VulnerabilitiesList" -import PackagesList from "./PackagesList" -import { - DetailSection, - DetailContentHeading, - DetailSectionHeader, -} from "../styles" -import HintLoading from "./HintLoading" -import HintNotFound from "./HintNotFound" -import ServicesList from "./ServicesList" - -const DetailSectionTop = ` -bg-theme-code-block -rounded-t -mb-0.5 -` - -const DetailSectionBottom = ` -bg-theme-code-block -rounded-b -pb-0.5 -` - -const ComponentDetail = () => { - const { options, routeParams } = useRouter() - - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const componentId = routeParams?.componentId - const { isLoading, isError, isFetching, data, error } = getComponent( - auth?.id_token, - endpoint, - componentId - ) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (error) { - addMessage({ - variant: "error", - text: parseError(error), - }) - } - }, [error]) - - const owners = useMemo(() => { - if (!data?.Owners) return [] - return usersListToString(data.Owners) - }, [data?.Owners]) - - const operators = useMemo(() => { - if (!data?.Operators) return [] - return usersListToString(data.Operators) - }, [data?.Operators]) - - return ( - - {isLoading && !data ? ( - - ) : ( - <> - {data ? ( - <> -

- {data.Name} -

- -
-
- - - - ID: - - {data.ID} - - - - Owners: - - {owners} - - - - Operators: - - {operators} - - - - Type: - - {data.Type} - - -
-
- - {componentDetailsByType(data).map((item, index) => ( - - - {`${item.label}: `} - - {item.value} - - ))} - -
-
- -
-

Belongs to

-
- -
-
- -
-

Vulnerabilities

-
- -
-
- -
-

Packages

-
- -
-
- - ) : ( - - )} - - )} -
- ) -} - -export default ComponentDetail diff --git a/apps_deprecated/heureka/src/components/backup/Components.js b/apps_deprecated/heureka/src/components/backup/Components.js deleted file mode 100644 index cf8e9ecb1..000000000 --- a/apps_deprecated/heureka/src/components/backup/Components.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect, useCallback, useState } from "react" -import { getComponents, getComponentFilters } from "../queries" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { parseError } from "../helpers" -import { Container } from "juno-ui-components" -import Pagination from "./Pagination" -import ComponentsList from "./ComponentsList" -import FilterToolbar from "./FilterToolbar" -import HintLoading from "./HintLoading" - -const ITEMS_PER_PAGE = 10 - -const Components = () => { - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const [paginationOptions, setPaginationOptions] = useState({ - limit: ITEMS_PER_PAGE, - offset: 0, - }) - const [searchOptions, setSearchOptions] = useState({}) - const components = getComponents(auth?.id_token, endpoint, { - ...paginationOptions, - ...searchOptions, - }) - - const filters = getComponentFilters(auth?.id_token, endpoint) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (components.error) { - addMessage({ - variant: "error", - text: parseError(components.error), - }) - } - }, [components.error]) - - useEffect(() => { - if (filters.error) { - addMessage({ - variant: "error", - text: parseError(filters.error), - }) - } - }, [filters.error]) - - const onPaginationChanged = (offset) => { - setPaginationOptions({ ...paginationOptions, offset: offset }) - } - - const onSearchTerm = (options) => { - setSearchOptions(options) - } - - return ( - - {components.isLoading && !components.data ? ( - - ) : ( - <> - - - - - )} - - ) -} - -export default Components diff --git a/apps_deprecated/heureka/src/components/backup/ComponentsList.js b/apps_deprecated/heureka/src/components/backup/ComponentsList.js deleted file mode 100644 index a6bd54ccb..000000000 --- a/apps_deprecated/heureka/src/components/backup/ComponentsList.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import ComponentsListItem from "./ComponentsListItem" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "./HintNotFound" -import { classifyVulnerabilities } from "../helpers" - -const ComponentsList = ({ - components, - columns, - sorted, - unlink, - selectable, -}) => { - components = useMemo(() => { - if (!components) return [] - // inforce input as array - if (!Array.isArray(components)) components = [components] - // sort components by threat level - if (sorted) { - return components - .sort((a, b) => { - const vulA = classifyVulnerabilities(a) - const vulB = classifyVulnerabilities(b) - return ( - vulA.critical - vulB.critical || - vulA.high - vulB.high || - vulA.medium - vulB.medium || - vulA.low - vulB.low - ) - }) - .reverse() - } - return components - }, [components]) - - columns = useMemo(() => { - if (!columns) { - return { - name: {}, - type: {}, - version: {}, - vulnerabilities: {}, - belongsTo: {}, - owners: {}, - operators: {}, - } - } - return columns - }, [columns]) - - const columnsLength = useMemo(() => { - const configurableCols = columns ? Object.keys(columns).length : 7 - return selectable ? configurableCols + 1 : configurableCols - }, [columns, selectable]) - - return ( - - - {selectable && } - {columns?.name && Name} - {columns?.type && Type} - {columns?.version && Version} - {columns?.vulnerabilities && ( - Vulnerabilities - )} - {columns?.belongsTo && Belongs to} - {columns?.owners && Owners} - {columns?.operators && Operators} - - {components.length > 0 ? ( - <> - {components.map((item, i) => ( - - ))} - - ) : ( - - - - - - )} - - ) -} - -export default ComponentsList diff --git a/apps_deprecated/heureka/src/components/backup/ComponentsListItem.js b/apps_deprecated/heureka/src/components/backup/ComponentsListItem.js deleted file mode 100644 index ef4c7bdec..000000000 --- a/apps_deprecated/heureka/src/components/backup/ComponentsListItem.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell, CheckboxRow } from "juno-ui-components" -import { Link } from "url-state-router" -import VulnerabilitiesOverview from "./VulnerabilitiesOverview" -import { - classifyVulnerabilities, - usersListToString, - componentVersionByType, -} from "../helpers" -import { COMPONENTS_PATH } from "./AppRouter" -import CustomBadge from "./CustomBadge" - -const ComponentsListItem = ({ item, columns, unlink, selectable }) => { - const services = useMemo(() => { - if (!item.Services) return [] - return item.Services - }, [item.Services]) - - const vulnerabilities = useMemo(() => { - return classifyVulnerabilities(item) - }, [item]) - - const owners = useMemo(() => { - return usersListToString(item.Owners) - }, [item.Owners]) - - const operators = useMemo(() => { - return usersListToString(item.Operators) - }, [item.Operators]) - - return ( - - {selectable && ( - - - - )} - {columns?.name && ( - - {unlink ? ( - <>{item.Name} - ) : ( - - {item.Name} - - )} - - )} - {columns?.type && {item.Type}} - {columns?.version && ( - {componentVersionByType(item)} - )} - {columns?.vulnerabilities && ( - - - - )} - {columns?.belongsTo && ( - - - - )} - {columns?.owners && {owners}} - {columns?.operators && {operators}} - - ) -} - -export default ComponentsListItem diff --git a/apps_deprecated/heureka/src/components/backup/CustomBadge.js b/apps_deprecated/heureka/src/components/backup/CustomBadge.js deleted file mode 100644 index 1f6ff2620..000000000 --- a/apps_deprecated/heureka/src/components/backup/CustomBadge.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Badge, Icon } from "juno-ui-components" - -const CustomBadge = ({ badgeVariant, icon, label, className }) => { - return ( - - - {label} - - ) -} - -export default CustomBadge diff --git a/apps_deprecated/heureka/src/components/backup/CustomPageHeader.js b/apps_deprecated/heureka/src/components/backup/CustomPageHeader.js deleted file mode 100644 index 5ca68b106..000000000 --- a/apps_deprecated/heureka/src/components/backup/CustomPageHeader.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect } from "react" -import useStore from "../hooks/useStore" -import { PageHeader } from "juno-ui-components" -import HeaderUser from "./HeaderUser" - -const CustomPageHeader = () => { - const auth = useStore((state) => state.auth) - const logout = useStore((state) => state.logout) - const loggedIn = useStore((state) => state.loggedIn) - return ( - - {loggedIn && } - - ) -} - -export default CustomPageHeader diff --git a/apps_deprecated/heureka/src/components/backup/EvidenceNew.js b/apps_deprecated/heureka/src/components/backup/EvidenceNew.js deleted file mode 100644 index 070920ca0..000000000 --- a/apps_deprecated/heureka/src/components/backup/EvidenceNew.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { Button, Panel, PanelBody, PanelFooter } from "juno-ui-components" - -const EvidenceNew = ({}) => { - return ( - - Panel Body - - ) -} - -export default EvidenceNew diff --git a/apps_deprecated/heureka/src/components/backup/EvidencesList.js b/apps_deprecated/heureka/src/components/backup/EvidencesList.js deleted file mode 100644 index 393e41bdd..000000000 --- a/apps_deprecated/heureka/src/components/backup/EvidencesList.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import EvidencesListItem from "./EvidencesListItem" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "./HintNotFound" - -const EvidencesList = ({ evidences }) => { - evidences = useMemo(() => { - if (!evidences) return [] - return evidences - }, [evidences]) - - return ( - <> - - - ID - Date - - {evidences.length > 0 ? ( - <> - {evidences.map((item, i) => ( - - ))} - - ) : ( - - - - - - )} - - - ) -} - -export default EvidencesList diff --git a/apps_deprecated/heureka/src/components/backup/EvidencesListItem.js b/apps_deprecated/heureka/src/components/backup/EvidencesListItem.js deleted file mode 100644 index 1fcaa6a4b..000000000 --- a/apps_deprecated/heureka/src/components/backup/EvidencesListItem.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell, Button } from "juno-ui-components" -import { DateTime } from "luxon" -import { Link } from "url-state-router" -import { useRouter } from "url-state-router" -import { SERVICES_PATH } from "./AppRouter" - -const EvidencesListItem = ({ item }) => { - const { options, routeParams } = useRouter() - const evidenceId = routeParams?.evidenceId - - const createdAt = useMemo(() => { - if (item.CreatedAt) { - return DateTime.fromSQL(item.CreatedAt).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [item.CreatedAt]) - - return ( - - {item.ID} - {createdAt} - - ) -} - -export default EvidencesListItem diff --git a/apps_deprecated/heureka/src/components/backup/FilterToolbar.js b/apps_deprecated/heureka/src/components/backup/FilterToolbar.js deleted file mode 100644 index a550f23d3..000000000 --- a/apps_deprecated/heureka/src/components/backup/FilterToolbar.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { FilterToolbarStateProvider } from "./FilterToolbarStore" -import FilterToolbarCore from "./FilterToolbarCore" - -const FilterToolbar = ({ - filterTypes, - onSearchTerm, - isLoading, - filterLabels, - placeholders, -}) => { - return ( - - - - ) -} - -export default FilterToolbar diff --git a/apps_deprecated/heureka/src/components/backup/FilterToolbarCore.js b/apps_deprecated/heureka/src/components/backup/FilterToolbarCore.js deleted file mode 100644 index c1cdd4027..000000000 --- a/apps_deprecated/heureka/src/components/backup/FilterToolbarCore.js +++ /dev/null @@ -1,109 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo, useState, useEffect, useCallback } from "react" -import { Filters, FilterPill } from "juno-ui-components" -import { useStore } from "./FilterToolbarStore" - -const toURLOptions = (items) => { - let options = [] - items.forEach((item) => { - options.push({ [item.key]: item.value }) - }) - return options -} - -// onSearchTerm (callback): returns key:value selected filters, ex: {name: "Elektra"} -// isLoading (boolean): sets the tool in loading state -// filterLabels (object): labels matching the filter key to be displayed in the dropdown. Ex: {name: "service name"} -// placeholders (object): placeholders matching the selected key -const FilterToolbarCore = ({ - onSearchTerm, - isLoading, - filterLabels, - placeholders, -}) => { - const selectedFilters = useStore(useCallback((state) => state.filters)) - const filterTypes = useStore(useCallback((state) => state.filterTypes)) - const addFilter = useStore((state) => state.addFilter) - const removeFilter = useStore((state) => state.removeFilter) - - const [placeholder, setPlaceholder] = useState("") - const [filterKey, setFilterKey] = useState("") - const [error, setError] = useState(null) - - const filterOptions = useMemo(() => { - if (typeof filterTypes !== "object") return [] - let result = [] - Object.keys(filterTypes).forEach((key) => { - // check if there is a label for the key - const label = - filterLabels && typeof filterLabels === "object" && filterLabels[key] - result.push({ label: label || key, key: key }) - }) - return result - }, [filterTypes, filterLabels]) - - useEffect(() => { - onSearchTerm(toURLOptions(selectedFilters)) - }, [selectedFilters]) - - const onSelectChange = (event) => { - const selectedValue = event.target.value - let label = `Please enter ${selectedValue}` - if (placeholders && placeholders[selectedValue]) { - label = placeholders[selectedValue] - } - // save the selected key - setFilterKey(selectedValue) - // set the new placeholder - setPlaceholder(label) - } - - const onPillClosed = (uid) => { - removeFilter(uid) - } - - const onFilter = (value) => { - setError(null) - if (filterKey === "") { - return setError("Please select a filter type") - } - if (value === "") { - return setError("Filter value can't be blank") - } - addFilter(filterKey, value) - } - - return ( - - {selectedFilters.map((item, index) => ( - - ))} - {error && ( -
- {error} -
- )} -
- ) -} - -export default FilterToolbarCore diff --git a/apps_deprecated/heureka/src/components/backup/FilterToolbarStore.js b/apps_deprecated/heureka/src/components/backup/FilterToolbarStore.js deleted file mode 100644 index 5b762bbeb..000000000 --- a/apps_deprecated/heureka/src/components/backup/FilterToolbarStore.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import uniqueId from "lodash.uniqueid" -import { createStore, useStore as useZustandStore } from "zustand" -import React, { createContext, useContext, useRef } from "react" - -const StoreContext = createContext() - -export const SEARCH_STRING_TYPE = "string" -export const SEARCH_BOOL_TYPE = "bool" -export const SEARCH_ARRAY_TYPE = "[string]" - -// custom store for the selected filters -const initialStore = (filterTypes) => { - return createStore((set) => ({ - filterTypes: filterTypes || {}, - filters: [], // this is the initial state - addFilter: (key, value) => addFilter(set, key, value), - removeFilter: (key, value) => removeFilter(set, key, value), - })) -} - -const addFilter = (set, key, value) => - set((state) => { - // prevent to add duplicates - const index = state.filters.findIndex( - (item) => item.key === key && item.value === value - ) - if (index >= 0) return state - - // if key type is string or boolean do not add more than 1 filter, overwrite existing - if ( - state.filterTypes[key] === SEARCH_STRING_TYPE || - state.filterTypes[key] === SEARCH_BOOL_TYPE - ) { - const newFilters = state.filters.slice() - const foundItem = newFilters.find((element) => element.key === key) - if (foundItem) { - foundItem.value = value - return { ...state, filters: newFilters } - } - } - // add entry - let newFilters = state.filters - .slice() - .concat({ uid: uniqueId("filter-"), key: key, value: value }) - // sort entries - newFilters.sort((a, b) => a.key.localeCompare(b.key)) - return { ...state, filters: newFilters } - }) - -const removeFilter = (set, uid) => - set((state) => { - let newItems = state.filters.slice() - const index = newItems.findIndex((item) => item.uid === uid) - // if NOT found return - if (index < 0) return state - - newItems.splice(index, 1) - return { ...state, filters: newItems } - }) - -export const FilterToolbarStateProvider = ({ filterTypes, children }) => { - const store = useRef(initialStore(filterTypes)).current - return {children} -} - -const useStore = (selector) => { - const store = useContext(StoreContext) - return useZustandStore(store, selector) -} -export { useStore } diff --git a/apps_deprecated/heureka/src/components/backup/HeaderUser.js b/apps_deprecated/heureka/src/components/backup/HeaderUser.js deleted file mode 100644 index 8cdff6776..000000000 --- a/apps_deprecated/heureka/src/components/backup/HeaderUser.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack, Button } from "juno-ui-components" -import Avatar from "./Avatar" - -const HeaderUser = ({ auth, logout }) => { - return ( - -
- -
- -
- -
- -

Evidences

-
- - - ) -} - -export default PatchLogDetail diff --git a/apps_deprecated/heureka/src/components/backup/PatchLogNew.js b/apps_deprecated/heureka/src/components/backup/PatchLogNew.js deleted file mode 100644 index 84929f36f..000000000 --- a/apps_deprecated/heureka/src/components/backup/PatchLogNew.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useMemo } from "react" -import { - Button, - Panel, - PanelBody, - PanelFooter, - Form, - TextInputRow, -} from "juno-ui-components" -import { useRouter } from "url-state-router" -import { getService } from "../queries" -import useStore from "../hooks/useStore" -import ChangesLogList from "./ChangesLogList" -import { SERVICES_PATH } from "./AppRouter" -import { changeLogExample1, changeLogExample2 } from "../helpers" - -const PatchLogNew = ({}) => { - const { options, routeParams, navigateTo } = useRouter() - const serviceId = routeParams?.serviceId - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - - const changes = useMemo(() => { - return [changeLogExample1, changeLogExample2] - }, []) - - const onPanelClose = () => { - navigateTo(`${SERVICES_PATH}/${serviceId}`) - } - - const formPanelFooter = useMemo( - () => ( - - - - - ), - [] - ) - - return ( - - -
e.preventDefault()}> -

Components

- - - - - - -
-
- ) -} - -export default PatchLogNew diff --git a/apps_deprecated/heureka/src/components/backup/PatchLogsList.js b/apps_deprecated/heureka/src/components/backup/PatchLogsList.js deleted file mode 100644 index e1680c5f4..000000000 --- a/apps_deprecated/heureka/src/components/backup/PatchLogsList.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import PatchLogsListItem from "./PatchLogsListItem" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "./HintNotFound" - -const PatchLogsList = ({ patches }) => { - patches = useMemo(() => { - if (!patches) return [] - return patches - }, [patches]) - - return ( - <> - - - ID - Date - Changes - Evidences - - {patches.length > 0 ? ( - <> - {patches.map((item, i) => ( - - ))} - - ) : ( - - - - - - )} - - - ) -} - -export default PatchLogsList diff --git a/apps_deprecated/heureka/src/components/backup/PatchLogsListItem.js b/apps_deprecated/heureka/src/components/backup/PatchLogsListItem.js deleted file mode 100644 index 4293a6cb3..000000000 --- a/apps_deprecated/heureka/src/components/backup/PatchLogsListItem.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell, Button } from "juno-ui-components" -import { DateTime } from "luxon" -import CustomBadge from "./CustomBadge" -import { Link } from "url-state-router" -import { useRouter } from "url-state-router" -import { SERVICES_PATH } from "./AppRouter" - -const PatchLogsListItem = ({ item }) => { - const { options, routeParams } = useRouter() - const serviceId = routeParams?.serviceId - - const createdAt = useMemo(() => { - if (item.CreatedAt) { - return DateTime.fromSQL(item.CreatedAt).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [item.CreatedAt]) - - return ( - - - - {item.ID} - - - {createdAt} - - - - - - - - ) -} - -export default PatchLogsListItem diff --git a/apps_deprecated/heureka/src/components/backup/ServiceDetail.js b/apps_deprecated/heureka/src/components/backup/ServiceDetail.js deleted file mode 100644 index ff8b4f567..000000000 --- a/apps_deprecated/heureka/src/components/backup/ServiceDetail.js +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useMemo } from "react" -import { getService } from "../queries" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { useRouter } from "url-state-router" -import { - parseError, - patchExampl1, - patchExampl2, - changeLogExample1, - changeLogExample2, -} from "../helpers" -import { - Icon, - DataGrid, - DataGridRow, - DataGridCell, - Container, - Stack, - Button, -} from "juno-ui-components" -import { - DetailSection, - DetailSectionBox, - DetailContentHeading, - DetailSectionHeader, -} from "../styles" -import HintLoading from "./HintLoading" -import HintNotFound from "./HintNotFound" -import PatchLogsList from "./PatchLogsList" -import ComponentsList from "./ComponentsList" -import { SERVICES_PATH } from "./AppRouter" -import ChangesLogList from "./ChangesLogList" - -const listOfUsers = (users) => { - users = users || [] - return users.map((user, index) => ( - - {index ? ", " : ""} - {`${user.Name} `} - - ({user.SapID}) - - - )) -} -const ServiceDetail = () => { - const { options, routeParams, navigateTo } = useRouter() - - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const serviceId = routeParams?.serviceId - const { isLoading, isError, isFetching, data, error } = getService( - auth?.id_token, - endpoint, - serviceId - ) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (error) { - addMessage({ - variant: "error", - text: parseError(error), - }) - } - }, [error]) - - const owners = useMemo(() => { - if (!data?.Owners) return [] - return listOfUsers(data.Owners) - }, [data?.Owners]) - - const operators = useMemo(() => { - if (!data?.Operators) return [] - return listOfUsers(data.Operators) - }, [data?.Operators]) - - const components = useMemo(() => { - if (!data?.Components) return [] - return data.Components - }, [data]) - - const patches = useMemo(() => { - if (data?.Name && data?.Name === "Elektra") { - return [patchExampl2, patchExampl1] - } - return [] - }, [data]) - - const changes = useMemo(() => { - if (data?.Name && data?.Name === "Elektra") { - return [changeLogExample1, changeLogExample2] - } - return [] - }, [data]) - - return ( - - {isLoading && !data ? ( - - ) : ( - <> - {data ? ( - <> -

- {data.Name} -

- -
-
- - - - ID: - - {data.ID} - - - - Owners: - - {owners} - - - - Operators: - - {operators} - - -
-
- -
-

- Vulnerabilities in this service -

-
- -
-
- -
- -

Patches log

-
- -
- -

Changes log

-
- - ) : ( - - )} - - )} -
- ) -} - -export default ServiceDetail diff --git a/apps_deprecated/heureka/src/components/backup/Services.js b/apps_deprecated/heureka/src/components/backup/Services.js deleted file mode 100644 index f1863d3b4..000000000 --- a/apps_deprecated/heureka/src/components/backup/Services.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useState, useMemo } from "react" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { Container } from "juno-ui-components" -import { getServices, getServiceFilters } from "../queries" -import { parseError } from "../helpers" -import Pagination from "./Pagination" -import ServicesList from "./ServicesList" -import FilterToolbar from "./FilterToolbar" -import HintLoading from "./HintLoading" - -const ITEMS_PER_PAGE = 10 - -const Services = ({}) => { - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const addMessage = useActions() - const [paginationOptions, setPaginationOptions] = useState({ - limit: ITEMS_PER_PAGE, - offset: 0, - }) - const [searchOptions, setSearchOptions] = useState({}) - const services = getServices(auth?.id_token, endpoint, { - ...paginationOptions, - ...searchOptions, - }) - const filters = getServiceFilters(auth?.id_token, endpoint) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (services.error) { - addMessage({ - variant: "error", - text: parseError(services.error), - }) - } - }, [services.error]) - - useEffect(() => { - if (filters.error) { - addMessage({ - variant: "error", - text: parseError(filters.error), - }) - } - }, [filters.error]) - - const onPaginationChanged = (offset) => { - setPaginationOptions({ ...paginationOptions, offset: offset }) - } - - const onSearchTerm = (options) => { - setSearchOptions(options) - } - - return useMemo(() => { - return ( - - {services.isLoading && !services.data ? ( - - ) : ( - <> - - - - - )} - - ) - }, [services, filters]) -} - -export default Services diff --git a/apps_deprecated/heureka/src/components/backup/ServicesList.js b/apps_deprecated/heureka/src/components/backup/ServicesList.js deleted file mode 100644 index 397c780dd..000000000 --- a/apps_deprecated/heureka/src/components/backup/ServicesList.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - Stack, - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import ServicesListItem from "./ServicesListItem" -import HintNotFound from "./HintNotFound" - -const ServicesList = ({ services, minimized }) => { - services = useMemo(() => { - if (!services) return [] - return services - }, [services]) - - return ( - <> - - - Name - {!minimized && ( - <> - Support group - Operators - Vulnerabilities - Components - - )} - - {services.length > 0 ? ( - <> - {services.map((item, i) => ( - - ))} - - ) : ( - - - - - - )} - - - ) -} - -export default ServicesList diff --git a/apps_deprecated/heureka/src/components/backup/ServicesListItem.js b/apps_deprecated/heureka/src/components/backup/ServicesListItem.js deleted file mode 100644 index ce73e5215..000000000 --- a/apps_deprecated/heureka/src/components/backup/ServicesListItem.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell } from "juno-ui-components" -import { Link } from "url-state-router" -import { classifyVulnerabilities } from "../helpers" -import VulnerabilitiesOverview from "./VulnerabilitiesOverview" -import { SERVICES_PATH } from "./AppRouter" -import CustomBadge from "./CustomBadge" - -const cellClasses = ` -justify-start -` - -const listOfUsers = (users) => { - users = users || [] - return users.map((user, index) => ( - - {index ? ", " : ""} - {`${user.Name} `} - - ({user.SapID}) - - - )) -} - -const ServicesListItem = ({ item, minimized }) => { - const owners = useMemo(() => { - return listOfUsers(item.Owners) - }, [item.Owners]) - - const operators = useMemo(() => { - return listOfUsers(item.Operators) - }, [item.Operators]) - - const components = useMemo(() => { - if (!item?.Components) return [] - return item.Components - }, [item.Components]) - - const vulnerabilities = useMemo(() => { - return classifyVulnerabilities(components) - }, [components]) - - return ( - - - {item.Name} - - {!minimized && ( - <> - {owners} - {operators} - - - - -
- -
-
- - )} -
- ) -} - -export default ServicesListItem diff --git a/apps_deprecated/heureka/src/components/backup/SupportGroups.js b/apps_deprecated/heureka/src/components/backup/SupportGroups.js deleted file mode 100644 index 393a170f9..000000000 --- a/apps_deprecated/heureka/src/components/backup/SupportGroups.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback } from "react" -import { Container } from "juno-ui-components" -import useStore from "../hooks/useStore" -import ServerGroupsList from "./SupportGroupsList" - -const ITEMS_PER_PAGE = 10 - -const SupportGroups = () => { - const endpoint = useStore(useCallback((state) => state.endpoint)) - - return ( - - - - ) -} - -export default SupportGroups diff --git a/apps_deprecated/heureka/src/components/backup/SupportGroupsList.js b/apps_deprecated/heureka/src/components/backup/SupportGroupsList.js deleted file mode 100644 index 437ad9404..000000000 --- a/apps_deprecated/heureka/src/components/backup/SupportGroupsList.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "./HintNotFound" - -const ServerGroupsList = ({ supportGroups }) => { - supportGroups = useMemo(() => { - if (!supportGroups) return [] - return supportGroups - }, [supportGroups]) - - return ( - - - Name - Members - - {supportGroups.length > 0 ? ( - <> - No yet implemented - - ) : ( - - - - - - )} - - ) -} - -export default ServerGroupsList diff --git a/apps_deprecated/heureka/src/components/backup/UserDetail.js b/apps_deprecated/heureka/src/components/backup/UserDetail.js deleted file mode 100644 index 10c15893e..000000000 --- a/apps_deprecated/heureka/src/components/backup/UserDetail.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useMemo } from "react" -import { - Icon, - DataGrid, - DataGridRow, - DataGridCell, - Stack, - Spinner, - Container, -} from "juno-ui-components" -import { useRouter } from "url-state-router" -import { getUser } from "../queries" -import { useActions } from "messages-provider" -import useStore from "../hooks/useStore" -import { - DetailSection, - DetailSectionBox, - DetailContentHeading, - DetailSectionHeader, -} from "../styles" -import HintLoading from "./HintLoading" -import ServicesList from "./ServicesList" -import { parseError } from "../helpers" -import HintNotFound from "./HintNotFound" - -const UserDetail = ({}) => { - const { routeParams } = useRouter() - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const userId = routeParams?.userId - const { isLoading, isError, isFetching, data, error } = getUser( - auth?.id_token, - endpoint, - userId - ) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (error) { - addMessage({ - variant: "error", - text: parseError(error), - }) - } - }, [error]) - - return ( - - {isLoading && !data ? ( - - ) : ( - <> - {data ? ( - <> -

- {data.Name} -

- -
-
- - - - ID: - - {data.ID} - - - - Email: - - {data.Email} - - - - SAP ID: - - {data.SapID} - - - - Support team: - - Services team - - -
-
-
-

Owned services

-
- -
-
- -
-

Evidences

-
-
- - ) : ( - - )} - - )} -
- ) -} - -export default UserDetail diff --git a/apps_deprecated/heureka/src/components/backup/Users.js b/apps_deprecated/heureka/src/components/backup/Users.js deleted file mode 100644 index 5b33aa64d..000000000 --- a/apps_deprecated/heureka/src/components/backup/Users.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useState } from "react" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { Container } from "juno-ui-components" -import { getUsers, getUserFilters } from "../queries" -import UsersList from "./UsersList" -import HintLoading from "./HintLoading" -import FilterToolbar from "./FilterToolbar" -import { parseError } from "../helpers" -import Pagination from "./Pagination" - -const ITEMS_PER_PAGE = 10 - -const Users = ({}) => { - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const [paginationOptions, setPaginationOptions] = useState({ - limit: ITEMS_PER_PAGE, - offset: 0, - }) - const [searchOptions, setSearchOptions] = useState({}) - const users = getUsers(auth?.id_token, endpoint, { - ...paginationOptions, - ...searchOptions, - }) - - const filters = getUserFilters(auth?.id_token, endpoint) - - useEffect(() => { - if (users.error) { - addMessage({ - variant: "error", - text: parseError(users.error), - }) - } - }, [users.error]) - - useEffect(() => { - if (filters.error) { - addMessage({ - variant: "error", - text: parseError(filters.error), - }) - } - }, [filters.error]) - - const onPaginationChanged = (offset) => { - setPaginationOptions({ ...paginationOptions, offset: offset }) - } - - const onSearchTerm = (options) => { - setSearchOptions(options) - } - - return ( - - {users.isLoading && !users.data ? ( - - ) : ( - <> - - - - - )} - - ) -} - -export default Users diff --git a/apps_deprecated/heureka/src/components/backup/UsersList.js b/apps_deprecated/heureka/src/components/backup/UsersList.js deleted file mode 100644 index e5bf4fdfe..000000000 --- a/apps_deprecated/heureka/src/components/backup/UsersList.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - Stack, - DataGrid, - DataGridRow, - DataGridCell, - DataGridHeadCell, -} from "juno-ui-components" -import UserListItem from "./UsersListItem" -import HintNotFound from "./HintNotFound" - -const UsersList = ({ users }) => { - users = useMemo(() => { - if (!users) return [] - return users - }, [users]) - - return ( - <> - - - Name - SAP ID - Support group - Owned services - - {users.length > 0 ? ( - <> - {users.map((user, index) => ( - - ))} - - ) : ( - - - - - - )} - - - ) -} - -export default UsersList diff --git a/apps_deprecated/heureka/src/components/backup/UsersListItem.js b/apps_deprecated/heureka/src/components/backup/UsersListItem.js deleted file mode 100644 index b038b3581..000000000 --- a/apps_deprecated/heureka/src/components/backup/UsersListItem.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell } from "juno-ui-components" -import { USERS_PATH } from "./AppRouter" -import { Link } from "url-state-router" -import Avatar from "./Avatar" -import CustomBadge from "./CustomBadge" - -const UserListItem = ({ item }) => { - const ownServices = useMemo(() => { - if (!item.OwnServices) return [] - return item.OwnServices - }, [item.OwnServices]) - - const evidences = useMemo(() => { - if (!item.Evidences) return [] - return item.Evidences - }, [item.Evidences]) - - return ( - - - - - - - {item.SapID} - Services team - - - - - ) -} - -export default UserListItem diff --git a/apps_deprecated/heureka/src/components/backup/Vulnerabilities.js b/apps_deprecated/heureka/src/components/backup/Vulnerabilities.js deleted file mode 100644 index 6fe1554ab..000000000 --- a/apps_deprecated/heureka/src/components/backup/Vulnerabilities.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useState } from "react" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { Stack, Spinner, Container } from "juno-ui-components" -import { getVulnerabilities, getVulnerabilityFilters } from "../queries" -import { parseError } from "../helpers" -import Pagination from "./Pagination" -import VulnerabilitiesList from "./VulnerabilitiesList" -import FilterToolbar from "./FilterToolbar" -import HintLoading from "./HintLoading" - -const ITEMS_PER_PAGE = 10 - -const Vulnerabilities = ({}) => { - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const [paginationOptions, setPaginationOptions] = useState({ - limit: ITEMS_PER_PAGE, - offset: 0, - }) - const [searchOptions, setSearchOptions] = useState({}) - const vulnerabilities = getVulnerabilities(auth?.id_token, endpoint, { - ...paginationOptions, - ...searchOptions, - }) - const filters = getVulnerabilityFilters(auth?.id_token, endpoint) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (vulnerabilities.error) { - addMessage({ - variant: "error", - text: parseError(vulnerabilities.error), - }) - } - }, [vulnerabilities.error]) - - useEffect(() => { - if (filters.error) { - addMessage({ - variant: "error", - text: parseError(filters.error), - }) - } - }, [filters.error]) - - const onPaginationChanged = (offset) => { - setPaginationOptions({ ...paginationOptions, offset: offset }) - } - - const onSearchTerm = (options) => { - setSearchOptions(options) - } - - return ( - - {vulnerabilities.isLoading && !vulnerabilities.data ? ( - - ) : ( - <> - - - - - )} - - ) -} - -export default Vulnerabilities diff --git a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesList.js b/apps_deprecated/heureka/src/components/backup/VulnerabilitiesList.js deleted file mode 100644 index d6bae33cf..000000000 --- a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesList.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, - Stack, -} from "juno-ui-components" -import VulnerabilitiesListItem from "./VulnerabilitiesListItem" -import { threadLevelToWeight } from "../helpers" -import HintNotFound from "./HintNotFound" - -const VulnerabilitiesList = ({ vulnerabilities, sortBy, minimized }) => { - vulnerabilities = useMemo(() => { - if (!vulnerabilities) return [] - if (!Array.isArray(vulnerabilities)) vulnerabilities = [vulnerabilities] - if (sortBy === "ThreatLevelOverall") { - return vulnerabilities - .sort( - (a, b) => - threadLevelToWeight(a[sortBy]) - threadLevelToWeight(b[sortBy]) - ) - .reverse() - } - return vulnerabilities - }, [vulnerabilities]) - - return ( - - - SCN/CVE - Threat level - {!minimized && Component} - Last modified - State - - {vulnerabilities.length > 0 ? ( - <> - {" "} - {vulnerabilities.map((item, index) => ( - - ))} - - ) : ( - - - - - - )} - - ) -} - -export default VulnerabilitiesList diff --git a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesListItem.js b/apps_deprecated/heureka/src/components/backup/VulnerabilitiesListItem.js deleted file mode 100644 index 7e2403d0b..000000000 --- a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesListItem.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DataGridRow, DataGridCell } from "juno-ui-components" -import { DateTime } from "luxon" -import VulnerabilityBadge from "./VulnerabilityBadge" -import { Link } from "url-state-router" -import { VULNERABILITIES_PATH } from "./AppRouter" - -const IdClasses = ` -text-sm -pt-1 -whitespace-nowrap -text-theme-disabled -` -const VulnerabilityCss = ` -flex -` - -const VulnerabilitiesListItem = ({ item, minimized }) => { - const lastModifiedtString = useMemo(() => { - if (!item?.Scn?.ScnLastModified) return "No date available" - return DateTime.fromSQL(item.Scn.ScnLastModified).toLocaleString( - DateTime.DATETIME_SHORT - ) - }, [item?.Scn?.ScnLastModified]) - - return ( - - - - {item?.Scn?.Name} -
{item?.Scn?.CveID}
- -
- -
- -
-
- {!minimized && {item?.Component?.Name}} - {lastModifiedtString} - {item?.State} -
- ) -} - -export default VulnerabilitiesListItem diff --git a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesOverview.js b/apps_deprecated/heureka/src/components/backup/VulnerabilitiesOverview.js deleted file mode 100644 index 99519c8cd..000000000 --- a/apps_deprecated/heureka/src/components/backup/VulnerabilitiesOverview.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Icon, Badge } from "juno-ui-components" -import VulnerabilityBadge from "./VulnerabilityBadge" -import { - THREAD_LEVEL_LOW, - THREAD_LEVEL_MEDIUM, - THREAD_LEVEL_HIGH, - THREAD_LEVEL_CRITICAL, -} from "../helpers" - -const VulnerabilitiesOverview = ({ vulnerabilities }) => { - return ( -
- {vulnerabilities.low > 0 && ( - - )} - {vulnerabilities.medium > 0 && ( - - )} - {vulnerabilities.high > 0 && ( - - )} - {vulnerabilities.critical > 0 && ( - - )} -
- ) -} - -export default VulnerabilitiesOverview diff --git a/apps_deprecated/heureka/src/components/backup/VulnerabilitiyDetails.js b/apps_deprecated/heureka/src/components/backup/VulnerabilitiyDetails.js deleted file mode 100644 index c74a989bf..000000000 --- a/apps_deprecated/heureka/src/components/backup/VulnerabilitiyDetails.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useCallback, useEffect, useMemo } from "react" -import { - Icon, - DataGrid, - DataGridRow, - DataGridCell, - Container, -} from "juno-ui-components" -import { getVulnerability } from "../queries" -import useStore from "../hooks/useStore" -import { useActions } from "messages-provider" -import { useRouter } from "url-state-router" -import { parseError } from "../helpers" -import { - DetailSection, - DetailSectionBox, - DetailContentHeading, - DetailSectionHeader, -} from "../styles" -import HintLoading from "./HintLoading" -import HintNotFound from "./HintNotFound" -import { DateTime } from "luxon" - -const VulnerabilitiyDetails = () => { - const { options, routeParams } = useRouter() - - const endpoint = useStore(useCallback((state) => state.endpoint)) - const auth = useStore(useCallback((state) => state.auth)) - const { addMessage } = useActions() - const vulnerabilityId = routeParams?.vulnerabilityId - const { isLoading, isError, isFetching, data, error } = getVulnerability( - auth?.id_token, - endpoint, - vulnerabilityId - ) - - // dispatch error with useEffect because error variable will first set once all retries did not succeed - useEffect(() => { - if (error) { - addMessage({ - variant: "error", - text: parseError(error), - }) - } - }, [error]) - - const scnLastModified = useMemo(() => { - if (data?.Scn?.ScnLastModified) { - return DateTime.fromSQL(data?.Scn?.ScnLastModified).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [data?.Scn?.ScnLastModified]) - - const cveLastModified = useMemo(() => { - if (data?.Scn?.CveLastModified) { - return DateTime.fromSQL(data?.Scn?.CveLastModified).toLocaleString( - DateTime.DATETIME_SHORT - ) - } - }, [data?.Scn?.CveLastModified]) - - return ( - - {isLoading && !data ? ( - - ) : ( - <> - {data ? ( - <> -

- {" "} - {data?.Scn?.Name} -

-
-
- - - - ID: - - {data?.ID} - - - - CCScore: - - {data?.CCScore} - - - - CCScoreReason: - - {data?.CCScoreReason} - - - - State: - - {data?.State} - - -
-
- -
- -
-

- Common Vulnerabilities and Exposures (CVE) information -

-
-
- - - - Name: - - {data?.Scn?.CveID} - - - - Last modified: - - {cveLastModified} - - - - URL: - - - {data?.Scn?.CveURL && ( - - {data?.Scn?.CveURL} - - )} - - - - - CVSS score: - - {data?.Scn?.CvssBase} - - -
-
-
- - ) : ( - - )} - - )} - - ) -} - -export default VulnerabilitiyDetails diff --git a/apps_deprecated/heureka/src/components/backup/VulnerabilityBadge.js b/apps_deprecated/heureka/src/components/backup/VulnerabilityBadge.js deleted file mode 100644 index 1de5f4b99..000000000 --- a/apps_deprecated/heureka/src/components/backup/VulnerabilityBadge.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { - THREAD_LEVEL_LOW, - THREAD_LEVEL_MEDIUM, - THREAD_LEVEL_HIGH, - THREAD_LEVEL_CRITICAL, -} from "../helpers" -import CustomBadge from "./CustomBadge" - -const badgeCss = ` - mr-2 -` - -const VulnerabilityBadge = ({ level, label }) => { - const icon = useMemo(() => { - const threadLevel = level || "" - switch (threadLevel.toLowerCase()) { - case THREAD_LEVEL_LOW: - return "severityLow" - case THREAD_LEVEL_MEDIUM: - return "severityMedium" - case THREAD_LEVEL_HIGH: - return "severityHigh" - case THREAD_LEVEL_CRITICAL: - return "severityCritical" - } - }, [level]) - - const badgeVariant = useMemo(() => { - const threadLevel = level || "" - switch (threadLevel.toLowerCase()) { - case THREAD_LEVEL_LOW: - return "default" - case THREAD_LEVEL_MEDIUM: - return "warning" - case THREAD_LEVEL_HIGH: - return "danger" - case THREAD_LEVEL_CRITICAL: - return "critical" - } - }, [level]) - - return ( - - ) -} - -export default VulnerabilityBadge diff --git a/apps_deprecated/heureka/src/components/backup/WelcomeView.js b/apps_deprecated/heureka/src/components/backup/WelcomeView.js deleted file mode 100644 index 40cbc73b0..000000000 --- a/apps_deprecated/heureka/src/components/backup/WelcomeView.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack, Button } from "juno-ui-components" - -const WelcomeView = ({ loginCallback }) => { - return ( - -

- Welcome to the Converged Cloud Patch Management System -

-

Login to maintain & track vulnerabilities

-
- - ) -} - -export default PaginationV2 diff --git a/apps_deprecated/heureka/src/components/tabs/TabContext.jsx b/apps_deprecated/heureka/src/components/tabs/TabContext.jsx deleted file mode 100644 index 034ba6abf..000000000 --- a/apps_deprecated/heureka/src/components/tabs/TabContext.jsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { Container, TabNavigation, TabNavigationItem } from "juno-ui-components" -import TabPanel from "./TabPanel" -import { useActions, useActiveTab } from "../StoreProvider" - -import ServicesTab from "../services/ServicesTab" -import VulnerabilitiesTab from "../vulnerabilities/VulnerabilitiesTab" - -const TAB_CONFIG = [ - { - label: "Services", - value: "services", - icon: "dns", - component: ServicesTab, - }, - { - label: "Vulnerabilities", - value: "vulnerabilities", - icon: "autoAwesomeMotion", - component: VulnerabilitiesTab, - }, -] - -const TabContext = () => { - const { setActiveTab } = useActions() - const activeTab = useActiveTab() - - return ( - <> - setActiveTab(value)} - > - {TAB_CONFIG.map((tab) => ( - - ))} - - - {TAB_CONFIG.map((tab) => ( - - - - ))} - - - ) -} - -export default TabContext diff --git a/apps_deprecated/heureka/src/components/tabs/TabPanel.jsx b/apps_deprecated/heureka/src/components/tabs/TabPanel.jsx deleted file mode 100644 index 0c6655821..000000000 --- a/apps_deprecated/heureka/src/components/tabs/TabPanel.jsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo, useRef, useEffect } from "react" -import { useActiveTab } from "../StoreProvider" - -const TabPanel = ({ value, children }) => { - const activeTab = useActiveTab() - - // ATENTION!! compare with == since tabindex is int and value is string - const displayChildren = useMemo(() => activeTab == value, [activeTab, value]) - - return ( -
- {children} -
- ) -} - -export default TabPanel diff --git a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesList.jsx b/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesList.jsx deleted file mode 100644 index 08f9503d0..000000000 --- a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesList.jsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { - DataGrid, - DataGridRow, - DataGridHeadCell, - DataGridCell, -} from "juno-ui-components" -import HintNotFound from "../shared/HintNotFound" -import HintLoading from "../shared/HintLoading" -import VulnerabilitiesListItem from "./VulnerabilitiesListItem" - -const VulnerabilitiesList = ({ vulnerabilities, isLoading }) => { - return ( - - - SCN/CVE - Threat level - Component - Last modified - State - - {isLoading && !vulnerabilities ? ( - - ) : ( - <> - {vulnerabilities?.length > 0 ? ( - <> - {vulnerabilities.map((item, index) => ( - - ))} - - ) : ( - - - - - - )} - - )} - - ) -} - -export default VulnerabilitiesList diff --git a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListController.jsx b/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListController.jsx deleted file mode 100644 index 67e676cdf..000000000 --- a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListController.jsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { useQuery } from "@tanstack/react-query" -import { - useQueryClientFnReady, - useQueryOptions, - useActions, -} from "../StoreProvider" -import VulnerabilitiesList from "./VulnerabilitiesList" -import PaginationV2 from "../shared/PaginationV2" - -// targetRemediationDate -// discoveryDate -// severity -// remediationDate (detailview) - -const VulnerabilitiesListController = () => { - const queryClientFnReady = useQueryClientFnReady() - const queryOptions = useQueryOptions("vulnerabilities") - const { setQueryOptions } = useActions() - - const { isLoading, isFetching, isError, data, error } = useQuery({ - queryKey: [`vulnerabilities`, queryOptions], - enabled: !!queryClientFnReady, - }) - - const vulnerabilities = useMemo(() => { - if (!data) return null - return data?.VulnerabilityMatches?.edges - }, [data]) - - const pageInfo = useMemo(() => { - if (!data) return null - return data?.VulnerabilityMatches?.pageInfo - }, [data]) - - const { currentPage, totalPages } = useMemo(() => { - if (!data?.VulnerabilityMatches?.pageInfo?.pages) return {} - const pages = data?.VulnerabilityMatches?.pageInfo?.pages - let currentPage = null - const currentPageIndex = pages?.findIndex((page) => page?.isCurrent) - if (currentPageIndex > -1) { - currentPage = pages[currentPageIndex]?.pageNumber - } - const totalPages = pages?.length - return { currentPage, totalPages } - }, [data?.VulnerabilityMatches?.pageInfo]) - - const onPaginationChanged = (newPage) => { - if (!data?.VulnerabilityMatches?.pageInfo?.pages) return - const pages = data?.VulnerabilityMatches?.pageInfo?.pages - const currentPageIndex = pages?.findIndex( - (page) => page?.pageNumber === newPage - ) - if (currentPageIndex > -1) { - const after = pages[currentPageIndex]?.after - setQueryOptions("vulnerabilities", { - ...queryOptions, - after: `${after}`, - }) - } - } - - return ( - <> - - - - ) -} - -export default VulnerabilitiesListController diff --git a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListItem.jsx b/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListItem.jsx deleted file mode 100644 index 42e29eda9..000000000 --- a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesListItem.jsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { DataGridRow, DataGridCell } from "juno-ui-components" - -const IdClasses = ` -text-sm -pt-1 -whitespace-nowrap -text-theme-disabled -` -const VulnerabilityCss = ` -flex -` - -const VulnerabilitiesListItem = ({ item }) => { - return ( - - - {item?.node?.id} - - -
- {/* */} -
-
- {item?.Component?.Name} - - {item?.State} -
- ) -} - -export default VulnerabilitiesListItem diff --git a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesTab.jsx b/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesTab.jsx deleted file mode 100644 index f48d1cab5..000000000 --- a/apps_deprecated/heureka/src/components/vulnerabilities/VulnerabilitiesTab.jsx +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import VulnerabilitiesListController from "./VulnerabilitiesListController" -import Filters from "../filters/Filters" - -const VulnerabilitiesTab = () => { - return ( - <> - - - - ) -} - -export default VulnerabilitiesTab diff --git a/apps_deprecated/heureka/src/helpers.js b/apps_deprecated/heureka/src/helpers.js deleted file mode 100644 index 37a89b7d6..000000000 --- a/apps_deprecated/heureka/src/helpers.js +++ /dev/null @@ -1,201 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { DateTime } from "luxon" - -export const parseError = (error) => { - if (!error || (typeof error === "object" && Object.keys(error).length === 0)) - return "An error occurred. There is no further information" - let errMsg = JSON.stringify(error) - if (error?.message) { - errMsg = error?.message - try { - const msgJson = JSON.parse(error?.message) - if (msgJson.error) errMsg = msgJson.error - if (msgJson.msg) errMsg = msgJson.msg - } catch (error) {} - } - return errMsg -} - -export const usersListToString = (users) => { - if (!users) users = [] - if (!Array.isArray(users)) users = [users] - - return users.map((user) => `${user.Name} (${user.SapID})`).join(", ") -} - -export const THREAD_LEVEL_LOW = "low" -export const THREAD_LEVEL_MEDIUM = "medium" -export const THREAD_LEVEL_HIGH = "high" -export const THREAD_LEVEL_CRITICAL = "critical" - -export const threadLevelToWeight = (level) => { - switch (level?.toLowerCase()) { - case THREAD_LEVEL_LOW: - return 3 - case THREAD_LEVEL_MEDIUM: - return 5 - case THREAD_LEVEL_HIGH: - return 8 - case THREAD_LEVEL_CRITICAL: - return 10 - } -} - -export const classifyVulnerabilitiesV2 = (vulnerabilites = []) => { - if (!vulnerabilites) vulnerabilites = [] - if (!Array.isArray(vulnerabilites)) vulnerabilites = [vulnerabilites] - let severities = { low: 0, medium: 0, high: 0, critical: 0 } - vulnerabilites.forEach((vulnerability) => { - // use of ThreatLevelOverall to get the index - switch (vulnerability?.ThreatLevelOverall?.toLowerCase()) { - case THREAD_LEVEL_LOW: - return (severities.low += 1) - case THREAD_LEVEL_MEDIUM: - return (severities.medium += 1) - case THREAD_LEVEL_HIGH: - return (severities.high += 1) - case THREAD_LEVEL_CRITICAL: - return (severities.critical += 1) - } - }) - return severities -} - -export const classifyVulnerabilities = (components = []) => { - if (!components) components = [] - if (!Array.isArray(components)) components = [components] - - let severities = { low: 0, medium: 0, high: 0, critical: 0 } - components.forEach((component) => { - // collect vulnerabilities from one component - if (component?.Vulnerabilities) { - const vulnerabilites = component?.Vulnerabilities - vulnerabilites.forEach((vulnerability) => { - // use of ThreatLevelOverall to get the index - switch (vulnerability?.ThreatLevelOverall?.toLowerCase()) { - case THREAD_LEVEL_LOW: - return (severities.low += 1) - case THREAD_LEVEL_MEDIUM: - return (severities.medium += 1) - case THREAD_LEVEL_HIGH: - return (severities.high += 1) - case THREAD_LEVEL_CRITICAL: - return (severities.critical += 1) - } - }) - } - }) - return severities -} - -export const COMPONENT_TYPE_KEPPEL = "KeppelImage" - -export const componentTypes = () => { - return [COMPONENT_TYPE_KEPPEL] -} - -export const componentDetailsByType = (component) => { - let detailKeys = [] - switch (component.Type) { - case COMPONENT_TYPE_KEPPEL: - detailKeys = [ - { - label: "Version", - value: componentVersionByType(component), - }, - { - label: "Maintainer", - value: component?.Details?.Maintainer, - }, - { - label: "Region", - value: component?.Details?.Region, - }, - { - label: "Source Repository", - value: component?.Details?.SourceRepository, - }, - ] - default: - } - return detailKeys -} - -export const componentVersionByType = (component) => { - let version = "" - switch (component.Type) { - case COMPONENT_TYPE_KEPPEL: - if (component?.Details?.PushedAt) { - version = DateTime.fromSeconds( - component?.Details?.PushedAt - ).toLocaleString(DateTime.DATETIME_SHORT) - } - default: - } - return version -} - -export const changeLogExample1 = { - ID: "4323", - Type: "automatic", - Components: [{ Name: "ubuntu" }, { Name: "alpine" }], - BeforeState: [ - { - ID: "333", - Name: "ubuntu", - Type: "KeppelImage", - Details: { PushedAt: 1543974164 }, - Vulnerabilities: [ - { - ID: 666, - ThreatLevelOverall: "Critical", - }, - ], - }, - ], - AfterState: [ - { - ID: "334", - Name: "alpine", - Type: "KeppelImage", - Details: { PushedAt: 1608021867 }, - Vulnerabilities: [], - }, - ], - CreatedAt: "2022-05-04 19:15:00.000", -} - -export const changeLogExample2 = { - ID: "1234", - Type: "manually", - Components: [ - { - Name: "absent-metrics-operator", - Type: "KeppelImage", - Details: { PushedAt: 1608021867 }, - }, - ], - BeforeState: [], - AfterState: [], - CreatedAt: "2022-04-29 14:15:00.000", -} - -export const patchExampl1 = { - ID: "123", - Type: "automatic", - Changes: [changeLogExample1], - CreatedAt: "2022-07-06 18:15:00.000", - Evidences: [], -} - -export const patchExampl2 = { - ID: "456", - Type: "automatic", - Changes: [changeLogExample2], - CreatedAt: "2022-05-04 19:15:00.000", - Evidences: [], -} diff --git a/apps_deprecated/heureka/src/helpers.test.js b/apps_deprecated/heureka/src/helpers.test.js deleted file mode 100644 index 691a20feb..000000000 --- a/apps_deprecated/heureka/src/helpers.test.js +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { parseError, classifyVulnerabilities } from "./helpers" - -describe("Helpers", () => { - describe("parseError", () => { - test("return error as string if no object with message", () => { - expect(parseError({ error: "This is an error text" })).toEqual( - '{"error":"This is an error text"}' - ) - }) - test("return error message if object with message attr exists", () => { - expect(parseError({ message: "This is an error text" })).toEqual( - "This is an error text" - ) - }) - test("return error message if object message has attr msg", () => { - expect( - parseError({ message: '{ "msg": "This is an error text" }' }) - ).toEqual("This is an error text") - }) - test("return error message if object message has attr error", () => { - expect( - parseError({ message: '{ "error": "This is an error text" }' }) - ).toEqual("This is an error text") - }) - test("return standard error message if no object message available", () => { - expect(parseError({})).toEqual( - "An error occurred. There is no further information" - ) - }) - test("return standard error message if no object message available", () => { - expect(parseError()).toEqual( - "An error occurred. There is no further information" - ) - }) - test("return error text if just a string is available", () => { - expect(parseError("This is a mega error")).toEqual( - '"This is a mega error"' - ) - }) - }) - - describe("classifyVulnerabilities", () => { - test("return empty results if no components provided", () => { - expect(classifyVulnerabilities(classifyVulnerabilities)).toEqual({ - low: 0, - medium: 0, - high: 0, - critical: 0, - }) - }) - test("return empty results if null provided", () => { - expect(classifyVulnerabilities(null)).toEqual({ - low: 0, - medium: 0, - high: 0, - critical: 0, - }) - }) - test("map to array if object instead of array provided", () => { - expect( - classifyVulnerabilities({ - Vulnerabilities: [{ ThreatLevelOverall: "Medium" }], - }) - ).toEqual({ - low: 0, - medium: 1, - high: 0, - critical: 0, - }) - }) - test("classify all possibilities with and without capital letter", () => { - const component1 = { - Vulnerabilities: [ - { ThreatLevelOverall: "High" }, - { ThreatLevelOverall: "Low" }, - ], - } - const component2 = { - Vulnerabilities: [ - { ThreatLevelOverall: "Critical" }, - { ThreatLevelOverall: "Medium" }, - ], - } - const component3 = { - Vulnerabilities: [{ ThreatLevelOverall: "medium" }], - } - expect( - classifyVulnerabilities([component1, component2, component3]) - ).toEqual({ - low: 1, - medium: 2, - high: 1, - critical: 1, - }) - }) - }) -}) diff --git a/apps_deprecated/heureka/src/hooks/useCommunication.js b/apps_deprecated/heureka/src/hooks/useCommunication.js deleted file mode 100644 index a22ef054e..000000000 --- a/apps_deprecated/heureka/src/hooks/useCommunication.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useReducer, useEffect, useCallback } from "react" -import { broadcast, get, watch } from "communicator" -import useStore from "./useStore" - -const useCommunication = () => { - console.log("[heureka] useCommunication setup") - - const setAuth = useStore((state) => state.setAuth) - const setLoggedIn = useStore((state) => state.setLoggedIn) - const setLoggedOut = useStore((state) => state.setLoggedOut) - const setLogin = useStore((state) => state.setLogin) - - useEffect(() => { - // get manually the current auth object in case the this app mist the first auth update message - // this is the case this app is loaded after the Auth app. - get( - "AUTH_GET_DATA", - (data) => { - setAuth(data.auth) - setLoggedIn(data.loggedIn) - }, - { debug: true } - ) - // watch for auth updates messages - // with the watcher we get the auth object when this app is loaded before the Auth app - const unwatch = watch( - "AUTH_UPDATE_DATA", - (data) => { - setAuth(data.auth) - setLoggedIn(data.loggedIn) - }, - { debug: true } - ) - return unwatch - }, [setAuth, setLoggedIn]) - - setLogin(() => { - broadcast("AUTH_LOGIN", "heureka", { debug: true }) - }) - - setLoggedOut(() => { - broadcast("AUTH_LOGOUT", "heureka") - }) -} - -export default useCommunication diff --git a/apps_deprecated/heureka/src/hooks/useQueryClientFn.js b/apps_deprecated/heureka/src/hooks/useQueryClientFn.js deleted file mode 100644 index 756353278..000000000 --- a/apps_deprecated/heureka/src/hooks/useQueryClientFn.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect, useMemo } from "react" -import { useQueryClient } from "@tanstack/react-query" -import { useEndpoint, useActions } from "../components/StoreProvider" -import { request } from "graphql-request" -import sevicesQuery from "../lib/queries/services" -import vulnerabilityMatchesQuery from "../lib/queries/vulnerabilityMatches" -import ServiceFilterQuery from "../lib/queries/serviceFilters" - -// hook to register query defaults that depends on the queryClient and options -const useQueryClientFn = () => { - const queryClient = useQueryClient() - const endpoint = useEndpoint() - const { setQueryClientFnReady } = useActions() - - /* - As stated in getQueryDefaults, the order of registration of query defaults does matter. Since the first matching defaults are returned by getQueryDefaults, the registration should be made in the following order: from the least generic key to the most generic one. This way, in case of specific key, the first matching one would be the expected one. - */ - useEffect(() => { - if (!queryClient || !endpoint) return - console.log("useQueryClientFn::: setting defaults") - - queryClient.setQueryDefaults(["services"], { - queryFn: async ({ queryKey }) => { - const [_key, options] = queryKey - console.log("useQueryClientFn::: queryKey: ", queryKey, options) - return await request(endpoint, sevicesQuery(), options) - }, - }) - - queryClient.setQueryDefaults(["vulnerabilities"], { - queryFn: async ({ queryKey }) => { - const [_key, options] = queryKey - console.log("useQueryClientFn::: queryKey: ", queryKey) - return await request(endpoint, vulnerabilityMatchesQuery(), options) - }, - }) - - queryClient.setQueryDefaults(["serviceFilters"], { - queryFn: async ({ queryKey }) => { - console.log("useQueryClientFn::: queryKey: ", queryKey) - return await request(endpoint, ServiceFilterQuery()) - }, - staleTime: Infinity, // this do not change often keep it until reload - }) - - // set queryClientFnReady to true once - setQueryClientFnReady(true) - }, [queryClient, endpoint]) -} - -export default useQueryClientFn diff --git a/apps_deprecated/heureka/src/hooks/useUrlState.js b/apps_deprecated/heureka/src/hooks/useUrlState.js deleted file mode 100644 index af5835d23..000000000 --- a/apps_deprecated/heureka/src/hooks/useUrlState.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useState, useEffect } from "react" -import { registerConsumer } from "url-state-provider" -import { useActions, useActiveTab } from "../components/StoreProvider" - -const DEFAULT_KEY = "heureka" -const ACTIVE_TAB = "t" - -const useUrlState = (key) => { - const [isURLRead, setIsURLRead] = useState(false) - // it is possible to have two apps instances on the same page - // int his case the key should be different per app - const urlStateManager = registerConsumer(key || DEFAULT_KEY) - - const { setActiveTab } = useActions() - const activeTab = useActiveTab() - - // Set initial state from URL (on login) - useEffect(() => { - if (isURLRead) return - console.log( - `HEUREKA: (${key || DEFAULT_KEY}) setting up state from url:`, - urlStateManager.currentState() - ) - - // READ the url state and set the state - const newTabIndex = urlStateManager.currentState()?.[ACTIVE_TAB] - // SAVE the state - if (newTabIndex) setActiveTab(newTabIndex) - setIsURLRead(true) - }, [isURLRead]) - - // SYNC states to URL state - useEffect(() => { - if (!isURLRead) return - urlStateManager.push({ - [ACTIVE_TAB]: activeTab, - }) - }, [isURLRead, activeTab]) -} - -export default useUrlState diff --git a/apps_deprecated/heureka/src/img/app_bg_example.svg b/apps_deprecated/heureka/src/img/app_bg_example.svg deleted file mode 100644 index b28325349..000000000 --- a/apps_deprecated/heureka/src/img/app_bg_example.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/apps_deprecated/heureka/src/index.js b/apps_deprecated/heureka/src/index.js deleted file mode 100644 index f6f988315..000000000 --- a/apps_deprecated/heureka/src/index.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createRoot } from "react-dom/client" -import React from "react" - -// export mount and unmount functions -export const mount = (container, options = {}) => { - import("./App").then((App) => { - mount.root = createRoot(container) - mount.root.render(React.createElement(App.default, options?.props)) - }) -} - -export const unmount = () => mount.root && mount.root.unmount() diff --git a/apps_deprecated/heureka/src/lib/queries/serviceFilters.js b/apps_deprecated/heureka/src/lib/queries/serviceFilters.js deleted file mode 100644 index 5ba6c2080..000000000 --- a/apps_deprecated/heureka/src/lib/queries/serviceFilters.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { gql } from "graphql-request" - -// gql -// It is there for convenience so that you can get the tooling support -// like prettier formatting and IDE syntax highlighting. -// You can use gql from graphql-tag if you need it for some reason too. -export default () => gql` - { - __type(name: "ServiceFilter") { - name - inputFields { - name - type { - name - kind - ofType { - name - kind - enumValues { - name - } - } - } - } - } - } -` diff --git a/apps_deprecated/heureka/src/lib/queries/services.js b/apps_deprecated/heureka/src/lib/queries/services.js deleted file mode 100644 index ab294fb75..000000000 --- a/apps_deprecated/heureka/src/lib/queries/services.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { gql } from "graphql-request" - -// gql -// It is there for convenience so that you can get the tooling support -// like prettier formatting and IDE syntax highlighting. -// You can use gql from graphql-tag if you need it for some reason too. -export default () => gql` - query ($filter: ServiceFilter, $first: Int, $after: String) { - Services(filter: $filter, first: $first, after: $after) { - __typename - totalCount - edges { - node { - id - name - owners { - totalCount - edges { - node { - id - sapID - name - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - supportGroups { - totalCount - edges { - node { - id - name - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - activities { - totalCount - edges { - node { - id - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - advisoryRepositories { - totalCount - edges { - node { - id - name - url - created_at - updated_at - } - cursor - priority - created_at - updated_at - } - pageInfo { - hasNextPage - nextPageAfter - } - } - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - } -` diff --git a/apps_deprecated/heureka/src/lib/queries/vulnerabilityMatches.js b/apps_deprecated/heureka/src/lib/queries/vulnerabilityMatches.js deleted file mode 100644 index 0c3b3d806..000000000 --- a/apps_deprecated/heureka/src/lib/queries/vulnerabilityMatches.js +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { gql } from "graphql-request" - -// gql -// It is there for convenience so that you can get the tooling support -// like prettier formatting and IDE syntax highlighting. -// You can use gql from graphql-tag if you need it for some reason too. -export default () => gql` - query ($filter: VulnerabilityMatchFilter, $first: Int, $after: String) { - VulnerabilityMatches(filter: $filter, first: $first, after: $after) { - __typename - totalCount - edges { - node { - id - status - remediationDate - discoveryDate - targetRemediationDate - severity { - value - score - } - evidences { - totalCount - edges { - node { - id - description - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - vulnerabilityDisclosureId - vulnerabilityDisclosure { - id - lastModified - } - componentInstanceId - componentInstance { - id - ccrn - count - } - vulnerabilityMatchChanges { - totalCount - edges { - node { - id - action - vulnerabilityMatchId - activityId - } - cursor - } - pageInfo { - hasNextPage - nextPageAfter - } - } - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - isValidPage - pageNumber - nextPageAfter - pages { - after - isCurrent - pageNumber - pageCount - } - } - } - } -` diff --git a/apps_deprecated/heureka/src/lib/store.js b/apps_deprecated/heureka/src/lib/store.js deleted file mode 100644 index b35ad2071..000000000 --- a/apps_deprecated/heureka/src/lib/store.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createStore } from "zustand" -import { devtools } from "zustand/middleware" -import produce from "immer" - -export default (options) => - createStore( - devtools((set, get) => ({ - isUrlStateSetup: false, - queryClientFnReady: false, - endpoint: options?.apiEndpoint, - - activeTab: "services", - tabs: { - services: { - queryOptions: { - first: 20, - }, - }, - vulnerabilities: { - queryOptions: { - first: 20, - }, - }, - }, - - actions: { - setQueryClientFnReady: (readiness) => - set( - (state) => { - state.queryClientFnReady = readiness - }, - false, - "setQueryClientFnReady" - ), - setActiveTab: (index) => - set( - (state) => { - state.activeTab = index - }, - false, - "setActiveTab" - ), - setQueryOptions: (tab, options) => - set( - produce((state) => { - state.tabs[tab].queryOptions = options - }), - false, - "setQueryOptions" - ), - }, - })) - ) diff --git a/apps_deprecated/heureka/src/queries.js b/apps_deprecated/heureka/src/queries.js deleted file mode 100644 index 210c7fcf0..000000000 --- a/apps_deprecated/heureka/src/queries.js +++ /dev/null @@ -1,205 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useQuery } from "@tanstack/react-query" -import { - services, - serviceFilters, - service, - components, - componentFilters, - component, - vulnerabilities, - vulnerability, - vulnerabilityFilters, - users, - user, - userFilters, -} from "./actions" - -// get all services -export const getServices = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["services", bearerToken, endpoint, options], - queryFn: services, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - }) -} - -export const getServiceFilters = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["serviceFilters", bearerToken, endpoint, options], - queryFn: serviceFilters, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - // If a user leaves your application and returns to stale data, React Query automatically requests fresh data for you in the background. - // You can disable this globally or per-query using the refetchOnWindowFocus option - refetchOnWindowFocus: false, - }) -} - -export const getService = ( - bearerToken, - endpoint, - serviceId, - placeholderData -) => { - return useQuery({ - queryKey: ["service", bearerToken, endpoint, serviceId], - queryFn: service, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // Placeholder data allows a query to behave as if it already has data, similar to the initialData option, - // but the data is not persisted to the cache. This comes in handy for situations where you have enough partial (or fake) - // data to render the query successfully while the actual data is fetched in the background. - placeholderData: placeholderData, - }) -} - -// get all components -export const getComponents = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["components", bearerToken, endpoint, options], - queryFn: components, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - }) -} - -export const getComponentFilters = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["componentFilters", bearerToken, endpoint, options], - queryFn: componentFilters, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - // If a user leaves your application and returns to stale data, React Query automatically requests fresh data for you in the background. - // You can disable this globally or per-query using the refetchOnWindowFocus option - refetchOnWindowFocus: false, - }) -} - -export const getComponent = ( - bearerToken, - endpoint, - componentId, - placeholderData -) => { - return useQuery({ - queryKey: ["component", bearerToken, endpoint, componentId], - queryFn: component, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // Placeholder data allows a query to behave as if it already has data, similar to the initialData option, - // but the data is not persisted to the cache. This comes in handy for situations where you have enough partial (or fake) - // data to render the query successfully while the actual data is fetched in the background. - placeholderData: placeholderData, - }) -} - -export const getVulnerabilities = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["vulnerabilities", bearerToken, endpoint, options], - queryFn: vulnerabilities, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - }) -} - -export const getVulnerability = ( - bearerToken, - endpoint, - vulnerabilityId, - placeholderData -) => { - return useQuery({ - queryKey: ["user", bearerToken, endpoint, vulnerabilityId], - queryFn: vulnerability, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // Placeholder data allows a query to behave as if it already has data, similar to the initialData option, - // but the data is not persisted to the cache. This comes in handy for situations where you have enough partial (or fake) - // data to render the query successfully while the actual data is fetched in the background. - placeholderData: placeholderData, - }) -} - -export const getVulnerabilityFilters = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["vulnerabilityFilters", bearerToken, endpoint, options], - queryFn: vulnerabilityFilters, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - // If a user leaves your application and returns to stale data, React Query automatically requests fresh data for you in the background. - // You can disable this globally or per-query using the refetchOnWindowFocus option - refetchOnWindowFocus: false, - }) -} - -export const getUsers = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["users", bearerToken, endpoint, options], - queryFn: users, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - }) -} - -export const getUser = (bearerToken, endpoint, userId, placeholderData) => { - return useQuery({ - queryKey: ["user", bearerToken, endpoint, userId], - queryFn: user, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // Placeholder data allows a query to behave as if it already has data, similar to the initialData option, - // but the data is not persisted to the cache. This comes in handy for situations where you have enough partial (or fake) - // data to render the query successfully while the actual data is fetched in the background. - placeholderData: placeholderData, - }) -} - -export const getUserFilters = (bearerToken, endpoint, options) => { - return useQuery({ - queryKey: ["userFilters", endpoint, options], - queryFn: userFilters, - // The query will not execute until the bearerToken exists - enabled: !!bearerToken, - // The data from the last successful fetch available while new data is being requested, even though the query key has changed. - // When the new data arrives, the previous data is seamlessly swapped to show the new data. - // isPreviousData is made available to know what data the query is currently providing you - keepPreviousData: true, - // If a user leaves your application and returns to stale data, React Query automatically requests fresh data for you in the background. - // You can disable this globally or per-query using the refetchOnWindowFocus option - refetchOnWindowFocus: false, - }) -} diff --git a/apps_deprecated/heureka/src/styles.js b/apps_deprecated/heureka/src/styles.js deleted file mode 100644 index d18e47105..000000000 --- a/apps_deprecated/heureka/src/styles.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const DetailContentHeading = ` -jn-font-bold -jn-text-lg -jn-text-theme-high -jn-pb-2 - ` - -export const DetailSection = ` -mt-6 -` - -export const DetailSectionHeader = ` -font-bold -mt-4 -text-lg -` - -export const DetailSectionBox = ` -bg-theme-background-lvl-1 -rounded -pb-0.5 -` diff --git a/apps_deprecated/heureka/src/styles.scss b/apps_deprecated/heureka/src/styles.scss deleted file mode 100644 index 8c927175f..000000000 --- a/apps_deprecated/heureka/src/styles.scss +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -/* Do not remove these tailwind directives. Without them styles won't work as expected */ -@tailwind base; -@tailwind components; -@tailwind utilities; - - -/* If necessary, app styles can be added below */ - - diff --git a/apps_deprecated/heureka/tailwind.config.js b/apps_deprecated/heureka/tailwind.config.js deleted file mode 100644 index 4ee65e3b0..000000000 --- a/apps_deprecated/heureka/tailwind.config.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// opacity helper to make custom colors work with opacity -function withOpacity(variableName) { - return ({ opacityVariable, opacityValue }) => { - if (opacityValue !== undefined) { - return `rgba(var(${variableName}), ${opacityValue})` - } - if (opacityVariable !== undefined) { - return `rgba(var(${variableName}), var(${opacityVariable}, 1))` - } - return `rgb(var(${variableName}))` - } -} - -module.exports = { - presets: [require("juno-ui-components/build/lib/tailwind.config")], - prefix: "", // important, do not change - content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], - corePlugins: { - preflight: false, - }, - theme: {}, - plugins: [], -} diff --git a/apps_deprecated/supernova/LICENSE b/apps_deprecated/supernova/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/apps_deprecated/supernova/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/apps_deprecated/supernova/README.md b/apps_deprecated/supernova/README.md deleted file mode 100644 index 15506fdcb..000000000 --- a/apps_deprecated/supernova/README.md +++ /dev/null @@ -1,138 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/greenhouse-extensions](https://github.com/cloudoperators/greenhouse-extensions) for the latest updates and active development. - -Supernova is an alternative UI for Prometheus Alertmanager with some quality of life improvements: - -- Micro frontend design based on [Juno UI components](https://ui.juno.global.cloud.sap) -- Predefined filter categories -- Easy filtering -- Autodiscover of the support group and added automatically as filter -- Aggregation and counting of alerts by region and severity -- Automatic URL linking for URLs in descriptions -- Parsing of alert labels for included external links -- Display of active and expired silences for a given alert -- Warning of an existing silence displaying the exact expiration time when creating new silences - -## Concepts - -### Alerts - -Alerting rules offer the capability to define alert conditions using expressions in the Prometheus expression language. These rules enable you to specify conditions that trigger alerts, and subsequently send notifications regarding the firing alerts to an external service. Whenever the alert expression results in one or more vector elements at a given point in time, the alert counts as active for these elements `label sets`. - -#### Labels - -The labels clause allows specifying a set of additional labels to be attached to the alert. Following is a live example of a set of labels from an alert of the `support group:containers` with `severity:info` in the `region:eu-de-2`. - -```js -{ - ... - "labels": { - "alertname": "PodOOMKilled", - "cluster": "eu-de-2", - "cluster_type": "metal", - "context": "memory", - "label_ccloud_support_group": "containers", - "meta": "Pod kube-system/kube-system-metal-owner-label-injector-28150200-2vgk5 OOMKilled", - "namespace": "kube-system", - "no_alert_on_absence": "true", - "playbook": "docs/support/playbook/kubernetes/k8s_pod_oomkilled", - "pod_name": "kube-system-metal-owner-label-injector-28150200-2vgk5", - "prometheus": "kube-monitoring/kubernetes", - "region": "eu-de-2", - "service": "resources", - "severity": "info", - "support_group": "containers", - "tier": "k8s", - "status": "active" - } - ... -} -``` - -### Silences - -Silences are a straightforward way to simply mute alerts for a given time. A silence is configured based on matchers. Incoming alerts are checked whether they match all the equality matchers of an active silence. If they do, no notifications will be sent out for that alert. - -#### Matchers - -A matcher is a string with a syntax inspired by PromQL and OpenMetrics. Matchers are ANDed together, meaning that all matchers must evaluate to "true" when tested against the labels on a given alert. - -When utilizing Supernova to add a silence, the matchers will be preselected based on the alert you selected. Moreover, through the advanced section, you have the option to include additional labels that are excluded by default. These exclusions are dependent on the configured excluded labels, which will be explained in detail in the section below. - -Given an alert with following labels: - -```js -{ - ... - fingerprint: "alert123", - labels: { - severity: "critical", - support_group: "containers", - service: "automation", - } - ... -} -``` - -In order to prevent the alert from continuing to trigger, we require a silence that includes the following matchers: - -```js -{ - ... - id: "silence123", - matchers: [ - { name: "severity", value: "critical" }, - { name: "support_group", value: "containers" }, - { name: "service", value: "automation" }, - ], - ... -} -``` - -## Configuration - -### Filter labels - -Filter labels are a set of labels that are utilized to define the criteria by which alerts will be filtered, if those labels exist within the fetched alerts. These filter labels enable you to selectively narrow down the alerts based on specific label values, resulting in a more targeted and refined alert filtering process. - -To set the filter labels: - -1. Utilize the app prop `filterLabels`, which is used during the setup of the script tag. For further information, please consult the [Get Started]() section. - -### Silence excluded alert labels - -Excluded labels are a collection of labels that are automatically excluded by default when configuring silence matchers. These labels, such as `pod`, `pod_name` or `instance`, often undergo frequent value changes, causing new alerts to be triggered that are not covered by the existing silence. - -Consider the following example: an alert is triggered when a pod runs out of memory and gets killed `Out Of Memory killed`. When this pod is recreated, it receives a different name. If the pod runs again out of memory because of the same issue, a new alarm will be triggered, but it won't be covered if we had used the `pod_name` as a matcher in the silence configuration. - -PodOOMKilled alarm labels example: - -```js -{ - "alertname": "PodOOMKilled", - "cluster": "eu-de-1", - "cluster_type": "metal", - "context": "memory", - "label_ccloud_service": "keppel", - "label_ccloud_support_group": "containers", - "meta": "Pod keppel/keppel-janitor-6dc777bcbf-5xrns OOMKilled", - "namespace": "keppel", - "no_alert_on_absence": "true", - "playbook": "docs/support/playbook/kubernetes/k8s_pod_oomkilled", - "pod_name": "keppel-janitor-6dc777bcbf-5xrns", - "prometheus": "kube-monitoring/kubernetes", - "region": "eu-de-1", - "service": "resources", - "severity": "info", - "support_group": "containers", - "tier": "k8s", - "status": "active" -} -``` - -If the end user wishes to include any excluded labels as matchers, they can easily do so by expanding the advanced section during the silence creation process. This allows for greater flexibility and customization when configuring the silence matchers. - -To set the excluded alert labels: - -1. Utilize the app prop `silenceExcludedLabels`, which is used during the setup of the script tag. For further information, please consult the [Get Started]() section. diff --git a/apps_deprecated/supernova/__mocks__/client.js b/apps_deprecated/supernova/__mocks__/client.js deleted file mode 100644 index 84531d3c2..000000000 --- a/apps_deprecated/supernova/__mocks__/client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { JSDOM } from "jsdom" -const dom = new JSDOM() -global.document = dom.window.document -global.window = dom.window diff --git a/apps_deprecated/supernova/__mocks__/fileMock.js b/apps_deprecated/supernova/__mocks__/fileMock.js deleted file mode 100644 index 27ce65aca..000000000 --- a/apps_deprecated/supernova/__mocks__/fileMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = "test-file-stub" diff --git a/apps_deprecated/supernova/__mocks__/styleMock.js b/apps_deprecated/supernova/__mocks__/styleMock.js deleted file mode 100644 index d74516001..000000000 --- a/apps_deprecated/supernova/__mocks__/styleMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = {} diff --git a/apps_deprecated/supernova/babel.config.js b/apps_deprecated/supernova/babel.config.js deleted file mode 100644 index abc1af7d1..000000000 --- a/apps_deprecated/supernova/babel.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - presets: ["@babel/preset-env", "@babel/preset-react"], - env: { - test: { - plugins: [["babel-plugin-transform-import-meta", { module: "ES6" }]], - }, - }, -} diff --git a/apps_deprecated/supernova/esbuild.config.js b/apps_deprecated/supernova/esbuild.config.js deleted file mode 100644 index 8d73d5c41..000000000 --- a/apps_deprecated/supernova/esbuild.config.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const esbuild = require("esbuild") -const fs = require("node:fs/promises") -const pkg = require("./package.json") -const postcss = require("postcss") -const sass = require("sass") -const { transform } = require("@svgr/core") -const url = require("postcss-url") -// this function generates app props based on package.json and propSecrets.json -const appProps = require("../../helpers/appProps") - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) - -const isProduction = process.env.NODE_ENV === "production" -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" -// in dev environment we prefix output file with public -let outfile = `${isProduction ? "" : "public/"}${pkg.main || pkg.module}` -// get output from outputfile -let outdir = outfile.slice(0, outfile.lastIndexOf("/")) -const args = process.argv.slice(2) -const watch = args.indexOf("--watch") >= 0 -const serve = args.indexOf("--serve") >= 0 - -const green = "\x1b[32m%s\x1b[0m" -const yellow = "\x1b[33m%s\x1b[0m" -const clear = "\033c" - -// shared config -const config = { - bundle: true, - minify: isProduction, - // target: ["es2020"], - target: ["es2020"], //["chrome64", "firefox67", "safari11.1", "edge79"], - format: "esm", - platform: "browser", - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - loader: { ".js": "jsx" }, - sourcemap: isProduction ? false : "both", - external: - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [], -} - -const build = async () => { - // delete build folder - await fs.rm(outdir, { recursive: true, force: true }) - await fs.mkdir(outdir, { recursive: true }) - - // build web workers - try { - const workerFiles = await fs.readdir("src/workers") - for (let f of workerFiles) { - await esbuild.build({ - ...config, - entryPoints: [`src/workers/${f}`], - outfile: `${outdir}/workers/${f}`, - }) - } - } catch (e) { - console.log("WARNING: BUILD WEB WORKERS", e.message) - } - - // build app - let ctx = await esbuild.context({ - ...config, - entryPoints: [pkg.source], - outdir, - splitting: true, - format: "esm", - plugins: [ - { - name: "start/end", - setup(build) { - build.onStart(() => { - console.log(yellow, "Compiling...") - }) - build.onEnd((result) => console.log(green, "Done!")) - }, - }, - // this custom plugin rewrites SVG imports to - // dataurls, paths or react components based on the - // search param and size - { - name: "svg-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(svg)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - let loader = "text" - if (args.suffix === "?url") { - // as URL - const maxSize = 10240 // 10Kb - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - } else { - // as react component - // use react component loader (jsx) - loader = "jsx" - contents = await transform(contents, { - plugins: ["@svgr/plugin-jsx"], - }) - } - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin rewrites image imports to - // dataurls or urls based on the size - { - name: "image-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(png|jpg|jpeg|gif)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - const maxSize = 10240 // 10Kb - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin parses the style files - { - name: "parse-styles", - setup(build) { - build.onLoad( - // consider only .scss and .css files - { filter: /.\.(css|scss)$/, namespace: "file" }, - async (args) => { - let content - // handle scss, convert to css - if (args.path.endsWith(".scss")) { - const result = sass.renderSync({ file: args.path }) - content = result.css - } else { - // read file content - content = await fs.readFile(args.path) - } - - // postcss plugins - const plugins = [ - require("tailwindcss"), - require("autoprefixer"), - // rewrite urls inside css - url({ - url: "inline", - // maxSize: 10, // use dataurls if files are smaller than 10k - // fallback: "copy", // if files are bigger use copy method - // assetsPath: "./build/assets", - // useHash: true, - // optimizeSvgEncode: true, - }), - ] - - const { css } = await postcss(plugins).process(content, { - from: args.path, - to: outdir, - }) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - return { contents: css, loader: "text" } - } - ) - }, - }, - ], - }) - - if (watch || serve) { - if (watch) await ctx.watch() - if (serve) { - // generate app props based on package.json and secretProps.json - await fs.writeFile( - `./${outdir}/appProps.js`, - `export default ${JSON.stringify(appProps())}` - ) - - let { host, port } = await ctx.serve({ - host: "0.0.0.0", - port: parseInt(process.env.APP_PORT || process.env.PORT || 3000), - servedir: "public", - }) - console.log("serve on", `${host}:${port}`) - } - } else { - await ctx.rebuild() - await ctx.dispose() - } -} - -build() diff --git a/apps_deprecated/supernova/jest.config.js b/apps_deprecated/supernova/jest.config.js deleted file mode 100644 index 0cb80394c..000000000 --- a/apps_deprecated/supernova/jest.config.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - transform: { "\\.[jt]sx?$": "babel-jest" }, - testEnvironment: "jsdom", - setupFilesAfterEnv: ["/setupTests.js"], - transformIgnorePatterns: [ - "node_modules/(?!(juno-ui-components|communicator)/)", - ], - moduleNameMapper: { - // Jest currently doesn't support resources with query parameters. - // Therefore we add the optional query parameter matcher at the end - // https://github.com/facebook/jest/issues/4181 - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)(\\?.+)?$": - require.resolve("./__mocks__/fileMock"), - "\\.(css|less|scss)$": require.resolve("./__mocks__/styleMock"), - }, -} diff --git a/apps_deprecated/supernova/package.json b/apps_deprecated/supernova/package.json deleted file mode 100644 index 78777e47f..000000000 --- a/apps_deprecated/supernova/package.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "name": "supernova", - "version": "0.9.11", - "author": "UI-Team", - "contributors": [ - "Esther Schmitz", - "Arturo Reuschenbach Puncernau" - ], - "repository": "https://github.com/sapcc/juno/tree/main/apps/supernova", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/greenhouse-extensions for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "source": "src/index.js", - "module": "build/index.js", - "private": true, - "devDependencies": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0", - "@tanstack/react-query": "4.28.0", - "@testing-library/dom": "^8.19.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "assert": "^2.0.0", - "autoprefixer": "^10.4.2", - "babel-jest": "^29.3.1", - "babel-plugin-transform-import-meta": "^2.2.0", - "communicator": "https://assets.juno.global.cloud.sap/libs/communicator@2.2.6/package.tgz", - "esbuild": "^0.19.4", - "esbuild-sass-plugin": "^2.6.0", - "immer": "^9.0.21", - "interweave": "^13.0.0", - "jest": "^29.3.1", - "jest-environment-jsdom": "^29.3.1", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.13.8/package.tgz", - "luxon": "^2.3.0", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "postcss": "^8.4.21", - "postcss-url": "^10.1.3", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-test-renderer": "18.2.0", - "sass": "^1.60.0", - "shadow-dom-testing-library": "^1.7.1", - "tailwindcss": "^3.3.1", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "util": "^0.12.4", - "zustand": "4.5.2" - }, - "peerDependencies": { - "@tanstack/react-query": "4.28.0", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.13.8/package.tgz", - "luxon": "^2.3.0", - "messages-provider": "https://assets.juno.global.cloud.sap/libs/messages-provider@0.1.12/package.tgz", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "zustand": "4.5.2" - }, - "importmapExtras": { - "zustand/middleware": "4.5.2" - }, - "scripts": { - "start": "NODE_ENV=development node esbuild.config.js --port=$APP_PORT --serve --watch", - "test": "jest", - "build": "NODE_ENV=production node esbuild.config.js", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prestart": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "appProps": { - "theme": { - "value": "theme-dark", - "type": "optional", - "description": "Override the default theme. Possible values are theme-light or theme-dark (default)" - }, - "embedded": { - "value": "false", - "type": "optional", - "description": "Set to true if app is to be embedded in another existing app or page, like e.g. Elektra. If set to true the app won't render a page header/footer and instead render only the content. The default value is false." - }, - "endpoint": { - "value": "", - "type": "required", - "description": "Alertmanager API Endpoint URL" - }, - "filterLabels": { - "value": null, - "type": "optional", - "description": "FilterLabels are the labels shown in the filter dropdown, enabling users to filter alerts based on specific criteria. The 'Status' label serves as a default filter, automatically computed from the alert status attribute and will be not overwritten. The labels must be an array of strings. Example: [\"app\", \"cluster\", \"cluster_type\"]" - }, - "silenceExcludedLabels": { - "value": null, - "type": "optional", - "description": "SilenceExcludedLabels are labels that are initially excluded by default when creating a silence. However, they can be added if necessary when utilizing the advanced options in the silence form. The labels must be an array of strings. Example: [\"pod\", \"pod_name\", \"instance\"]" - }, - "silenceTemplates": { - "value": null, - "type": "optional", - "description": "SilenceTemplates are pre-defined silence templates that can be used to scheduled Maintenance Windows. The format consists of a list of objects including description, editable_labels (array of strings specifying the labels that users can modify), fixed_labels (map containing fixed labels and their corresponding values), status, and title." - } - }, - "appDependencies": { - "auth": "latest" - }, - "appPreview": true -} diff --git a/apps_deprecated/supernova/public/favicon.ico b/apps_deprecated/supernova/public/favicon.ico deleted file mode 100644 index 9ebc4bb2e04736789f9fcfe03121b296c693079a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHOc~DkW6h8=vpa^PaX3JM9iaLr~+M@BPg-&UinG_1xqN9VFP8qhyVv3gI5)y)q zTINC;R?|K;#Z=Q?rdcjEfL2psi+^QPO{eqwE|2&4e8Bs@_ib;6J9D_-d+*+Je)rsS zw{s6fQ4~#SX(YLes`?X+A|jWo@j02OR^BB`j_>ngh)SfuKq(_tXtogEds07@wedGr zzRwh@rmJplpzU=``%W`${FrIleN26aGbMIs`5p@TOXSoGJtveUB&};Tx#jC|A*LG_ zG41`GX~z#t*Uo0@5FHArF33-gz4hJZSf5CcVNu%YJgjw z6?WGUracWzyMAW6WN4_dS(OK@>5XlGO&t+Zbqiipx}UPZDz9*rJ0_ShR%bO~A9#hr zzU3%WY^QMH@_-h3_=2)hvD5l*q zW--@al459QQcid2PTLeyU!zA+Owd_+jT$7c2behY2~(YeQ@t)2cUB8>)U~ zns~SK+R*Jhri!oieptGbsdqnTwWE7)rblb^HsCDt$m>kg?`KNCjcN20rt#TKBPT^} zyW--RW-McR=10997#Bv$d?0f1YwK3hxlGs3V=8<}=BE?Q@#n0JeEeEFw7g>{rX|}| zI~Hwm9)9CIyY~I?;m0`Cbn0t9{5qxoy?=y$zl#0k!~2zdUvX>Yu})}f_0%Q)>p|mZ z%!iI+TK^GKZiyOq*JLu?FrNwM!pA?=#~*ZOtmo_RIqMZK__z|f+T*3k#yP6^RUM;o zt~36I{`-xzC$pDJKeNr`XO&KQ*tkB7~p4`p09jR^AB`CxdkYr24s`lfsIc~$F=9p9_|!Ttl|aO-z^J5griCrm@ep4~=`Z>V#e z<8E21<_@h5-Z{n!e68>mM22tPTz@!6r%e!_{OxKjLOys5Q+yZm@}bssyS(;(Xt#lI z+JNqZc3wXK`^k{6)q&GfonU|7!T75Md$xn|BTfK!kl#A64aXa?OGe{`)ctkfY%`d1 z60o|3jA^z!{38@hxq;vf?72c_3H=bswgj7Tn*lex!+5}$#=Z7Qp>VDb+WZbIh!X&| zX6au%r4yY-o}_|pD2}KG&(TCh$fNWekL{^t4HV&%L0>g^7CqJ@7rknF*7S}zEtim6 zs3}fMV!2vLUFBN=^-ViYWe5JFbswsDp&otA&$+(O2WN!;L80YBi9*ISNFM4u@c~bt zRQ|Z&p4||iklF}9tW#vibYw!DMdd?A3*TF?)qQ9(HtB{EG68+u>oS zZpNLe4@ON6j}9>YH+{jht(K`zN_a3JCKGX`xHlMcYj}Kyh_ig+pz4c?Z=|n@Vn3I^V6D872ktS}eZaJI7ZdKqu)b<{ZLl+A+17p|J^_6&BExze@Poe? z_ldv&|2AYJZUc9$R`m})SR={~sIl2+fHe$=p+L;Cub5lX1Lh^n4QNkm^CbFfavoFF zDWHQw}8`_-?><8mC^-78D9Hji$h~+Q+T*(gBdX9d>n8Y5{+y9SsbYX?e z;THSIyM4Ys!;g>n=wahke5Efo<*Tgr@`1HwrBAj043BQH|2%AY4h%d-?7xe`D8E2t z`$(L?&dzPXV`tOQ^|DVgBD(2^8P8oEB7`k^di)d(uQRy?VcE5Voa4@j_)Z zvyiF(W!`11JcCCA6}@bwtXY``PpkmW*mi6TXEem1`pX0R$Q7?i47d1n{N;hThmyC{ zSrKcnzkINlnO|nDzF90PVnJ5F&4hSXGYp6qS@{OjWA8G}DmE`O)U9G{jQT)K2mZ$o z`zJHL-tQ0(1iL`oBjQ^SdoXUMwYo-L@cY>5TO%*?-xv$N<5G1{x6DTUO;R_Zk;f?? P_&~0wZjp_d33dMme?Bb{ diff --git a/apps_deprecated/supernova/public/index.html b/apps_deprecated/supernova/public/index.html deleted file mode 100644 index 13beb9f20..000000000 --- a/apps_deprecated/supernova/public/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - Supernova Dev - - - - - - -
- - diff --git a/apps_deprecated/supernova/public/index_test.html b/apps_deprecated/supernova/public/index_test.html deleted file mode 100644 index aa41d46a8..000000000 --- a/apps_deprecated/supernova/public/index_test.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - Supernova Dev - - - - - - - -
- - diff --git a/apps_deprecated/supernova/setupTests.js b/apps_deprecated/supernova/setupTests.js deleted file mode 100644 index db44c9038..000000000 --- a/apps_deprecated/supernova/setupTests.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom" diff --git a/apps_deprecated/supernova/src/App.jsx b/apps_deprecated/supernova/src/App.jsx deleted file mode 100644 index 1663c5e2d..000000000 --- a/apps_deprecated/supernova/src/App.jsx +++ /dev/null @@ -1,108 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useLayoutEffect } from "react" - -import { AppShellProvider } from "juno-ui-components" -import AppContent from "./AppContent" -import styles from "./styles.scss" -import { - useGlobalsActions, - useFilterActions, - useSilencesActions, - useAlertsActions, - StoreProvider, -} from "./hooks/useAppStore" -import AsyncWorker from "./components/AsyncWorker" -import { MessagesProvider } from "messages-provider" -import CustomAppShell from "./components/CustomAppShell" - -function App(props = {}) { - const { setLabels, setPredefinedFilters, setActivePredefinedFilter } = - useFilterActions() - const { setEmbedded, setApiEndpoint } = useGlobalsActions() - const { setExcludedLabels } = useSilencesActions() - - useLayoutEffect(() => { - // filterLabels are the labels shown in the filter dropdown, enabling users to filter alerts based on specific criteria. Default is status. - if (props.filterLabels) setLabels(props.filterLabels) - - // silenceExcludedLabels are labels that are initially excluded by default when creating a silence. However, they can be added if necessary when utilizing the advanced options in the silence form. - if (props.silenceExcludedLabels) - setExcludedLabels(props.silenceExcludedLabels) - - // predefined filters config - const predefinedFilters = [ - { - name: "prod", - displayName: "Prod", - matchers: { - // regex that matches anything except regions that start with qa-de- - region: "^(?!qa-de-).*", - }, - }, - { - name: "prod-qa", - displayName: "Prod + QA", - matchers: { - // regex that matches anything except regions that start with qa-de- and end with a number that is not 1 - // regex is used in RegExp constructor, so we need to escape the backslashes for flags - region: "^(?!qa-de-(?!1$)\\d+).*", - }, - }, - { - name: "labs", - displayName: "Labs", - matchers: { - // regex that matches all regions that start with qa-de- and end with a number that is not 1 - // regex is used in RegExp constructor, so we need to escape the backslashes for flags - region: "^qa-de-(?!1$)\\d+", - }, - }, - { - name: "all", - displayName: "All", - matchers: { - region: ".*", - }, - }, - ] - setPredefinedFilters(predefinedFilters) - - // initially active predefined filter - const initialPredefinedFilter = "prod" - setActivePredefinedFilter(initialPredefinedFilter) - - // save the apiEndpoint. It is also used outside the alertManager hook - setApiEndpoint(props.endpoint) - }, []) - - useLayoutEffect(() => { - if (props.embedded === "true" || props.embedded === true) setEmbedded(true) - }, []) - - return ( - - - - - - - ) -} - -const StyledApp = (props) => { - return ( - - {/* load appstyles inside the shadow dom */} - - - - - - ) -} - -export default StyledApp diff --git a/apps_deprecated/supernova/src/App.test.js b/apps_deprecated/supernova/src/App.test.js deleted file mode 100644 index cb360db19..000000000 --- a/apps_deprecated/supernova/src/App.test.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { render, act } from "@testing-library/react" - -// support shadow dom queries -// https://reactjsexample.com/an-extension-of-dom-testing-library-to-provide-hooks-into-the-shadow-dom/ -import { screen } from "shadow-dom-testing-library" - -jest.mock("./hooks/useCommunication", () => { - return jest.fn(() => ({})) -}) -jest.mock("./hooks/useAlertmanagerAPI", () => { - return jest.fn(() => ({})) -}) - -import App from "./App" - -test("renders app", async () => { - render() - - let loginTitle = await screen.queryAllByShadowText(/Supernova/i) - expect(loginTitle.length > 0).toBe(true) -}) diff --git a/apps_deprecated/supernova/src/AppContent.jsx b/apps_deprecated/supernova/src/AppContent.jsx deleted file mode 100644 index 0e365d145..000000000 --- a/apps_deprecated/supernova/src/AppContent.jsx +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect } from "react" -import { useActions, Messages } from "messages-provider" -import { Container, Spinner, Stack } from "juno-ui-components" -import { - useAlertsError, - useAlertsIsLoading, - useAlertsIsUpdating, - useAlertsUpdatedAt, - useAlertsTotalCounts, - useAuthLoggedIn, - useAuthError, - useSilencesError, -} from "./hooks/useAppStore" -import AlertsList from "./components/alerts/AlertsList" -import RegionsList from "./components/regions/RegionsList" -import StatusBar from "./components/status/StatusBar" -import Filters from "./components/filters/Filters" -import WelcomeView from "./components/WelcomeView" -import { parseError } from "./helpers" -import AlertDetail from "./components/alerts/AlertDetail" -import PredefinedFilters from "./components/filters/PredefinedFilters" - -const AppContent = () => { - const { addMessage } = useActions() - const loggedIn = useAuthLoggedIn() - const authError = useAuthError() - - // alerts - const alertsError = useAlertsError() - const isAlertsLoading = useAlertsIsLoading() - const totalCounts = useAlertsTotalCounts() - const isAlertsUpdating = useAlertsIsUpdating() - const updatedAt = useAlertsUpdatedAt() - - // silences - const silencesError = useSilencesError() - - useEffect(() => { - if (!authError) return - addMessage({ - variant: "error", - text: parseError(authError), - }) - }, [authError]) - - useEffect(() => { - // since the API call is done in a web worker and not logging aware, we need to show the error just in case the user is logged in - if (!alertsError || !loggedIn) return - - // if user uses firefox warn to activate `allow_client_cert`. Should be enough to do it just here since the API call is done in a web worker and nothing else will be loaded until the alerts are loaded - const isFirefox = navigator.userAgent.toLowerCase().includes("firefox") - if (isFirefox) { - addMessage({ - variant: "warning", - text: ( -

- Firefox detected. Please ensure that you have activated{" "} - allow_client_cert to enable the retrieval of alerts and - silences from the API. -

    -
  • 1. Go to about:config (via address bar)
  • -
  • - 2. Change network.cors_preflight.allow_client_cert to{" "} - true -
  • -
  • 3. Reload Greenhouse
  • -
-

- ), - }) - } - - addMessage({ - variant: "error", - text: parseError(alertsError), - }) - }, [alertsError, loggedIn]) - - useEffect(() => { - // since the API call is done in a web worker and not logging aware, we need to show the error just in case the user is logged in - if (!silencesError || !loggedIn) return - addMessage({ - variant: "error", - text: parseError(silencesError), - }) - }, [silencesError, loggedIn]) - - return ( - - - {loggedIn && !authError ? ( - <> - - - {isAlertsLoading ? ( - - Loading - - - ) : ( - <> - - - - - - )} - - ) : ( - - )} - - ) -} - -export default AppContent diff --git a/apps_deprecated/supernova/src/api/apiService.js b/apps_deprecated/supernova/src/api/apiService.js deleted file mode 100644 index b81b93bc5..000000000 --- a/apps_deprecated/supernova/src/api/apiService.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * This module implements a service to retrieve information from an API - * @module apiService - */ - -// default value for watch interval -const DEFAULT_INTERVAL = 300000 - -/** - * This function implements the actual service. - * @param {object} initialConfig - */ -function ApiService(initialConfig) { - // default config - let config = { - serviceName: null, - initialFetch: true, // Set this to false to disable this service from automatically running. - fetchFn: null, // The promise function that the service will use to request data - watch: true, // if true runs the fetchFn periodically with an interval defined in watchInterval - watchInterval: DEFAULT_INTERVAL, // 5 min - onFetchStart: null, - onFetchEnd: null, - onFetchError: null, - debug: false, - } - - let initialFetchPerformed = false - - // get the allowed config keys from default config - const allowedOptions = Object.keys(config) - // variable to hold the watch timer created by setInterval - let watchTimer - - // This function performs the request to get the target data - const update = () => { - if (config.fetchFn) { - // call onFetchStart if defined - // This is useful to inform the listener that a new fetch is starting - if (config.onFetchStart) config.onFetchStart() - if (config?.debug) - console.info(`ApiService::${config.serviceName || ""}: start fetch`) - initialFetchPerformed = true - return config - .fetchFn() - .then(() => { - if (config.onFetchEnd) config.onFetchEnd() - }) - .catch((error) => { - if (error?.httperror) { - error.message = "API: " + error.message - } - if (error.message == "Failed to fetch") { - error.message = - "Could not reach endpoint. Possible causes could include network issues, incorrect URL, or server outages." - } - - console.warn(`ApiService::${config.serviceName || ""}:`, error) - if (config.onFetchError) config.onFetchError(error) - }) - } else { - if (config?.debug) - console.warn( - `ApiService::${config.serviceName || ""}: missing fetch function` - ) - return - } - } - - // update watcher if config has changed - const updateWatcher = (oldConfig) => { - // do nothing if watch and watchInterval are the same - if ( - initialFetchPerformed && - oldConfig.watch === config.watch && - oldConfig.watchInterval === config.watchInterval - ) - return - - // delete last watcher - clearInterval(watchTimer) - - // create a new watcher which calls the update method - if (config.watch) { - watchTimer = setInterval(update, config.watchInterval || DEFAULT_INTERVAL) - } - } - - // this function is public and used to update the config - this.configure = (newOptions) => { - const oldConfig = { ...config } - // update apiService config - config = { ...config, ...newOptions } - - // check for allowed keys - Object.keys(config).forEach( - (key) => allowedOptions.indexOf(key) < 0 && delete config[key] - ) - - if (config?.debug) - console.log( - `ApiService::${config.serviceName || ""}: new config: `, - config - ) - - // update watcher will check the config relevant attribute changed to update the watcher - updateWatcher(oldConfig) - if (config.initialFetch && !initialFetchPerformed) update() - } - - // make it possible to update explicitly, not by a watcher! - this.fetch = update - - // set the config initially - this.configure(initialConfig) -} - -export default ApiService diff --git a/apps_deprecated/supernova/src/api/client.js b/apps_deprecated/supernova/src/api/client.js deleted file mode 100644 index bfbcc8f49..000000000 --- a/apps_deprecated/supernova/src/api/client.js +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -class HTTPError extends Error { - constructor(code, message) { - super(message || code) - this.name = "HTTPError" - this.statusCode = code - } -} - -// Check response status -const checkStatus = (response) => { - if (response.status < 400) { - return response - } else { - return response.text().then((message) => { - var error = new HTTPError(response.status, message || response.statusText) - error.statusCode = response.status - error.httperror = true - return Promise.reject(error) - }) - } -} - -const DEFAULT_HEADERS = { - "Content-Type": "application/json", - Accept: "application/json", -} - -const request = (url, options = {}) => { - const requestOptions = { headers: DEFAULT_HEADERS, ...options } - - return fetch(url, requestOptions) - .then(checkStatus) - .then((response) => response.json()) -} - -export const head = (url, options = {}) => - request(url, { method: "HEAD", ...options }) -export const get = (url, options = {}) => - request(url, { method: "GET", ...options }) -export const post = (url, options = {}) => - request(url, { method: "POST", ...options }) -export const put = (url, options = {}) => - request(url, { method: "PUT", ...options }) -export const patch = (url, options = {}) => - request(url, { method: "PATCH", ...options }) -export const del = (url, options = {}) => - request(url, { method: "DELETE", ...options }) -export const copy = (url, options = {}) => - request(url, { method: "COPY", ...options }) diff --git a/apps_deprecated/supernova/src/components/AsyncWorker.jsx b/apps_deprecated/supernova/src/components/AsyncWorker.jsx deleted file mode 100644 index 98cc4cc8e..000000000 --- a/apps_deprecated/supernova/src/components/AsyncWorker.jsx +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import useCommunication from "../hooks/useCommunication" -import useAlertmanagerAPI from "../hooks/useAlertmanagerAPI" -import useUrlState from "../hooks/useUrlState" - -const AsyncWorker = ({ endpoint }) => { - useCommunication() - useAlertmanagerAPI(endpoint) - useUrlState() - return null -} - -export default AsyncWorker diff --git a/apps_deprecated/supernova/src/components/Avatar.jsx b/apps_deprecated/supernova/src/components/Avatar.jsx deleted file mode 100644 index 6e41eb812..000000000 --- a/apps_deprecated/supernova/src/components/Avatar.jsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack } from "juno-ui-components" - -const avatarCss = ` -h-8 -w-8 -bg-theme-background-lvl-2 -rounded-full -bg-cover -` - -const Avatar = ({ userName, url }) => { - return ( - - {url && ( -
- )} - {userName && {userName}} - - ) -} - -export default Avatar diff --git a/apps_deprecated/supernova/src/components/CustomAppShell.jsx b/apps_deprecated/supernova/src/components/CustomAppShell.jsx deleted file mode 100644 index b35fceb8b..000000000 --- a/apps_deprecated/supernova/src/components/CustomAppShell.jsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { AppShell, PageHeader } from "juno-ui-components" -import { - useAuthData, - useAuthLoggedIn, - useGlobalsEmbedded, - useAuthActions, -} from "../hooks/useAppStore" -import HeaderUser from "./HeaderUser" - -const CustomAppShell = ({ children }) => { - const embedded = useGlobalsEmbedded() - const authData = useAuthData() - const loggedIn = useAuthLoggedIn() - const { logout } = useAuthActions() - - const pageHeader = useMemo(() => { - return ( - - {loggedIn && } - - ) - }, [loggedIn, authData, logout]) - - return ( - - {children} - - ) -} - -export default CustomAppShell diff --git a/apps_deprecated/supernova/src/components/HeaderUser.jsx b/apps_deprecated/supernova/src/components/HeaderUser.jsx deleted file mode 100644 index 8cdff6776..000000000 --- a/apps_deprecated/supernova/src/components/HeaderUser.jsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack, Button } from "juno-ui-components" -import Avatar from "./Avatar" - -const HeaderUser = ({ auth, logout }) => { - return ( - -
- -
- - - - - ))} - - - )} - - ) -} - -export default AlertSilences diff --git a/apps_deprecated/supernova/src/components/alerts/AlertStatus.jsx b/apps_deprecated/supernova/src/components/alerts/AlertStatus.jsx deleted file mode 100644 index dd7bb3d0e..000000000 --- a/apps_deprecated/supernova/src/components/alerts/AlertStatus.jsx +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { Stack } from "juno-ui-components" -import { - useSilencesItemsHash, - useSilencesLocalItems, - useSilencesActions, -} from "../../hooks/useAppStore" - -const AlertStatus = ({ alert }) => { - const allSilences = useSilencesItemsHash() - const localSilences = useSilencesLocalItems() - const { getMappingSilences, getMappedState } = useSilencesActions() - - const silences = useMemo(() => { - if (!alert) return [] - return getMappingSilences(alert) - }, [alert, allSilences, localSilences]) - - const state = useMemo(() => { - if (!alert) return {} - return getMappedState(alert) - }, [alert, allSilences, localSilences]) - - return ( -
- {state && ( - <> - {state?.isProcessing ? ( - - {state.type} - processing - - ) : ( - {state.type} - )} - - )} - {alert?.status?.inhibitedBy?.length > 0 && ( -
- - Inhibited by: - {alert?.status?.inhibitedBy} - -
- )} - {silences && silences.length > 0 && ( -
- - Silenced by: - {silences.map((data) => ( - {data?.createdBy || data.id} - ))} - -
- )} -
- ) -} - -export default AlertStatus diff --git a/apps_deprecated/supernova/src/components/alerts/AlertsList.jsx b/apps_deprecated/supernova/src/components/alerts/AlertsList.jsx deleted file mode 100644 index 0fc750155..000000000 --- a/apps_deprecated/supernova/src/components/alerts/AlertsList.jsx +++ /dev/null @@ -1,120 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo, useState, useRef, useCallback } from "react" -import { - DataGrid, - DataGridHeadCell, - DataGridRow, - DataGridCell, - Icon, - Stack, -} from "juno-ui-components" -import Alert from "./Alert" -import { - useAlertsItemsFiltered, - useAlertsIsLoading, -} from "../../hooks/useAppStore" - -const AlertsList = () => { - const [visibleAmount, setVisibleAmount] = useState(20) - const [isAddingItems, setIsAddingItems] = useState(false) - const timeoutRef = React.useRef(null) - - const itemsFiltered = useAlertsItemsFiltered() - const alertsIsLoading = useAlertsIsLoading() - - const alertsSorted = useMemo(() => { - if (itemsFiltered) { - return itemsFiltered.slice(0, visibleAmount) - } - }, [itemsFiltered, visibleAmount]) - - React.useEffect(() => { - return () => clearTimeout(timeoutRef.current) // clear when component is unmounted - }, []) - - // endless scroll observer - const observer = useRef() - const lastListElementRef = useCallback( - (node) => { - // no fetch if loading original data - if (alertsIsLoading || isAddingItems) return - if (observer.current) observer.current.disconnect() - observer.current = new IntersectionObserver((entries) => { - console.log("IntersectionObserver: callback") - if (entries[0].isIntersecting && visibleAmount <= alertsSorted.length) { - // setVisibleAmount((prev) => prev + 10) - clearTimeout(timeoutRef.current) - setIsAddingItems(true) - timeoutRef.current = setTimeout(() => { - setIsAddingItems(false) - setVisibleAmount((prev) => prev + 10) - }, 500) - } - }) - if (node) observer.current.observe(node) - }, - [alertsIsLoading, isAddingItems] - ) - - return ( - - {!alertsIsLoading && ( - - - - - Region - Service - Description - Firing Since - Status - - - )} - {alertsSorted?.length > 0 ? ( - alertsSorted?.map((alert, index) => { - if (alertsSorted.length === index + 1) { - // DataRow in alerts muss implement forwardRef - return ( - - ) - } - return - }) - ) : ( - - - - -
- We couldn't find anything. It's possible that the matching - alerts are not active at the moment, or the chosen filters could - be overly limiting. -
-
-
-
- )} - {isAddingItems && ( - - Loading ... - - )} -
- ) -} - -export default AlertsList diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertDescription.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertDescription.jsx deleted file mode 100644 index e9ffbd49f..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertDescription.jsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Markup } from "interweave" - -import { descriptionParsed } from "../../../lib/utils" - - -const AlertDescription = ({description, subdued}) => { - - return ( - $1" - ) - )} - tagName="div" - className={subdued ? "text-theme-light" : ""} - /> - ) -} - -export default AlertDescription \ No newline at end of file diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertIcon.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertIcon.jsx deleted file mode 100644 index e85826895..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertIcon.jsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { forwardRef } from "react" - -import { Icon } from "juno-ui-components" - - -const AlertIcon = ({severity}, ref) => { - - const iconColor = () => { - - switch (severity) { - case "critical": - return "text-theme-danger" - case "warning": - return "text-theme-warning" - case "info": - return "text-theme-info" - } - - } - - return ( - <> - {severity === "critical" ? ( - - ) : severity?.match(/^(warning|info)$/) ? ( - - ) : ( - - )} - - ) -} - -export default forwardRef(AlertIcon) \ No newline at end of file diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertLabels.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertLabels.jsx deleted file mode 100644 index cf172256d..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertLabels.jsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { Pill, Stack } from "juno-ui-components" - -import { - useActiveFilters, - useFilterLabels, - useFilterActions, -} from "../../../hooks/useAppStore" - -/** - * For each of the given alert's labels which is included in the configured filterLabels render a Pill showing filterLabel and filterValue - */ -const AlertLabels = ({ alert, showAll}) => { - const filterLabels = showAll ? Object.keys(alert?.labels) : useFilterLabels() - const activeFilters = useActiveFilters() - const { addActiveFilter, removeActiveFilter } = useFilterActions() - - const handleLabelClick = (e, filterLabel, filterValue) => { - // if filter isn't already active, add it - if (!activeFilters?.[filterLabel]?.includes(filterValue)) { - e.stopPropagation() - addActiveFilter(filterLabel, filterValue) - } else { - // otherwise remove it - handleRemoveFilter(e, filterLabel, filterValue) - } - } - - const handleRemoveFilter = (e, filterLabel, filterValue) => { - e.stopPropagation() - removeActiveFilter(filterLabel, filterValue) - } - - return ( - - {filterLabels.map((filterLabel) => { - let value = alert?.labels?.[filterLabel] - let isActive = activeFilters?.[filterLabel]?.includes(value) - - return ( - value && ( - handleLabelClick(e, filterLabel, value)} - closeable={isActive} - onClose={(e, _) => handleRemoveFilter(e, filterLabel, value)} - /> - ) - ) - })} - - ) -} - -export default AlertLabels diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertLinks.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertLinks.jsx deleted file mode 100644 index 0ba9a37e7..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertLinks.jsx +++ /dev/null @@ -1,118 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { Stack } from "juno-ui-components" - -const AlertLinks = ({ alert, className }) => { - - return ( - - {alert?.generatorURL && ( - e.stopPropagation()} - > - Prometheus - - )} - {alert?.labels?.playbook && ( - e.stopPropagation()} - > - Playbook - - )} - {alert?.labels?.kibana && ( - e.stopPropagation()} - > - Logs - - )} - {alert?.labels?.dashboard && ( - e.stopPropagation()} - > - Grafana - - )} - {alert?.labels?.spc && ( - e.stopPropagation()} - > - SPC Ticket - - )} - {alert?.labels?.sentry && ( - e.stopPropagation()} - > - Sentry - - )} - {alert?.labels?.cloudops && ( - e.stopPropagation()} - > - CloudOps - - )} - {alert?.labels?.report && ( - e.stopPropagation()} - > - Report - - )} - {alert?.annotations?.mail_subject && ( - e.stopPropagation()} - > - Email Owner - - )} - - ) -} - -export default AlertLinks diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertRegion.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertRegion.jsx deleted file mode 100644 index 04e4e2d14..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertRegion.jsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - - -const AlertRegion = ({ region, cluster }) => { - - return ( - <> - {region} - {region !== cluster && ( - <> -
- {cluster} - - )} - - ) -} - -export default AlertRegion \ No newline at end of file diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertSilencesList.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertSilencesList.jsx deleted file mode 100644 index 1f3601cf8..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertSilencesList.jsx +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useMemo } from "react" -import { DateTime } from "luxon" - -import { - Badge, - DataGrid, - DataGridCell, - DataGridHeadCell, - DataGridRow, -} from "juno-ui-components" - -import { useSilencesActions } from "../../../hooks/useAppStore" - -const badgeVariant = (state) => { - switch (state) { - case "active": - return "info" - case "processing": - return "warning" - default: - return "default" - } -} - -const AlertSilencesList = ({ alert }) => { - const dateFormat = { ...DateTime.DATETIME_SHORT } - const timeFormat = { ...DateTime.TIME_24_WITH_SHORT_OFFSET } - - const formatDateTime = (timestamp) => { - const time = DateTime.fromISO(timestamp) - return time.toLocaleString(dateFormat) - } - - const { getMappingSilences, getExpiredSilences } = useSilencesActions() - - const activeSilences = getMappingSilences(alert) - const expiredSilences = getExpiredSilences(alert) - console.log("expiredSilences", expiredSilences) - const silenceList = activeSilences.concat(expiredSilences) - - return ( - <> - {silenceList.length > 0 && ( - <> -

Silences

- - - Status - Silence start - Silence end - Created by - Comment - - {silenceList.map((silence) => ( - - -
- - {silence.status?.state} - -
-
- {formatDateTime(silence.startsAt)} - {formatDateTime(silence.endsAt)} - {silence.createdBy} - - {silence.comment} - -
- ))} -
- - )} - - ) -} - -export default AlertSilencesList diff --git a/apps_deprecated/supernova/src/components/alerts/shared/AlertTimestamp.jsx b/apps_deprecated/supernova/src/components/alerts/shared/AlertTimestamp.jsx deleted file mode 100644 index dbb80c4f4..000000000 --- a/apps_deprecated/supernova/src/components/alerts/shared/AlertTimestamp.jsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { DateTime } from "luxon" - -import { Icon, Stack, Tooltip, TooltipContent, TooltipTrigger } from "juno-ui-components" - - -const AlertTimestamp = ({startTimestamp}) => { - const dateFormat = { ...DateTime.DATE_MED } - const timeFormat = { ...DateTime.TIME_24_WITH_SHORT_OFFSET } - const startTime = DateTime.fromISO(startTimestamp) - const daysFiring = DateTime.now().diff(startTime, "days") - - return ( - -
{startTime.toLocaleString(dateFormat)}
-
{startTime.toLocaleString(timeFormat)}
- {daysFiring.days > 7 && ( - - - - - - {`Alert has been firing for ${Math.round( - daysFiring.days - )} days`} - - - )} -
- ) - -} -export default AlertTimestamp \ No newline at end of file diff --git a/apps_deprecated/supernova/src/components/filters/FilterPills.jsx b/apps_deprecated/supernova/src/components/filters/FilterPills.jsx deleted file mode 100644 index 160fdbdd2..000000000 --- a/apps_deprecated/supernova/src/components/filters/FilterPills.jsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { Pill, Stack } from "juno-ui-components" -import { useActiveFilters, useFilterActions } from "../../hooks/useAppStore" - -const FilterPills = () => { - const activeFilters = useActiveFilters() - const { removeActiveFilter } = useFilterActions() - - return ( - - {Object.entries(activeFilters).map(([key, values]) => { - return values.map((value) => ( - removeActiveFilter(key, value)} - key={`${key}:${value}`} - /> - )) - })} - - ) -} - -export default FilterPills diff --git a/apps_deprecated/supernova/src/components/filters/FilterSelect.jsx b/apps_deprecated/supernova/src/components/filters/FilterSelect.jsx deleted file mode 100644 index 4feb52a90..000000000 --- a/apps_deprecated/supernova/src/components/filters/FilterSelect.jsx +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState } from "react" - -import { - Button, - InputGroup, - SelectOption, - Select, - Stack, - SearchInput, -} from "juno-ui-components" -import { - useFilterLabels, - useFilterLabelValues, - useFilterActions, - useActiveFilters, - useSearchTerm, -} from "../../hooks/useAppStore" -import { humanizeString } from "../../lib/utils" - -const FilterSelect = () => { - const [filterLabel, setFilterLabel] = useState("") - const [filterValue, setFilterValue] = useState("") - const [resetKey, setResetKey] = useState(Date.now()) - - const { - addActiveFilter, - loadFilterLabelValues, - clearActiveFilters, - setSearchTerm, - } = useFilterActions() - const filterLabels = useFilterLabels() - const filterLabelValues = useFilterLabelValues() - const activeFilters = useActiveFilters() - const searchTerm = useSearchTerm() - - const handleFilterAdd = (value) => { - if (filterLabel && (filterValue || value)) { - // add active filter to store - addActiveFilter(filterLabel, filterValue || value) - - // reset filterValue - setFilterValue("") - } else { - // TODO: show error -> please select filter/value - } - } - - const handleFilterLabelChange = (value) => { - setFilterLabel(value) - // lazy loading of all possible values for this label (only load them if we haven't already) - if (!filterLabelValues[value]?.values) { - loadFilterLabelValues(value) - } - } - - const handleFilterValueChange = (value) => { - setFilterValue(value) - handleFilterAdd(value) - } - - const handleSearchChange = (value) => { - // debounce setSearchTerm to avoid unnecessary re-renders - const debouncedSearchTerm = setTimeout(() => { - setSearchTerm(value.target.value) - }, 500) - - // clear timeout if we have a new value - return () => clearTimeout(debouncedSearchTerm) - } - - // const handleKeyDown = (event) => { - // if (event.key === "Enter") { - // handleFilterValueChange() - // } - // } - - return ( - - - - - - {displayNewSilence && ( - setDisplayNewSilence(false)} - onConfirm={success ? null : onSubmitForm} - > - {error && } - - {success && ( - - A silence object with id {success?.silenceID} was created - successfully. Please note that it may take up to 5 minutes for the - alert to show up as silenced. - - )} - - {expirationDate && !success && ( - - There is already a silence for this alert that expires at{" "} - - {DateTime.fromISO(expirationDate).toLocaleString( - DateTime.DATETIME_SHORT - )} - - - )} - - {alert?.labels?.alertname} - - - - - - {!success && ( - <> - - -
- - - - - - - - - {formState?.editable_labels && - Object.keys(formState?.editable_labels).length > 0 && ( - - -

- Editable Labels are labels that are editable. You can - use regular expressions. -

-
- - -
- {Object.keys(formState.editable_labels).map( - (editable_label, index) => ( - - ) - )} -
-
-
- )} - - {Object.keys(formState?.fixed_labels).length > 0 && ( - - -

Fixed Labels are labels that are not editable.

-
- - - - {Object.keys(formState.fixed_labels).map( - (label, index) => ( - - ) - )} - - -
- )} -
- )} - - )} -
- ) -} - -export default SilenceScheduled diff --git a/apps_deprecated/supernova/src/components/silences/SilenceScheduledWrapper.jsx b/apps_deprecated/supernova/src/components/silences/SilenceScheduledWrapper.jsx deleted file mode 100644 index eacd31880..000000000 --- a/apps_deprecated/supernova/src/components/silences/SilenceScheduledWrapper.jsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import SilenceScheduled from "./SilenceScheduled" - -import { MessagesProvider } from "messages-provider" -import { Button, Icon } from "juno-ui-components" -import { useSilenceTemplates } from "../../hooks/useAppStore.js" - -const SilenceScheduledWrapper = () => { - const templates = useSilenceTemplates() - const [displayNewScheduledSilence, setDisplayNewScheduledSilence] = - useState(false) - - // function which sets displayNewScheduledSilence to false - const callbackOnClose = () => { - setDisplayNewScheduledSilence(false) - } - - return ( - <> - {templates && templates?.length > 0 && ( - - - {displayNewScheduledSilence && ( - - )} - - )} - - ) -} - -export default SilenceScheduledWrapper diff --git a/apps_deprecated/supernova/src/components/silences/silenceHelpers.js b/apps_deprecated/supernova/src/components/silences/silenceHelpers.js deleted file mode 100644 index 525ca9fe1..000000000 --- a/apps_deprecated/supernova/src/components/silences/silenceHelpers.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const DEFAULT_DURATION_OPTIONS = [ - { label: "2 hours", value: "2" }, - { label: "12 hours", value: "12" }, - { label: "1 day", value: "24" }, - { label: "3 days", value: "72" }, - { label: "7 days", value: "168" }, -] - -// get the "latest" expiration date from the given silences -export const latestExpirationDate = (silences) => { - if (silences?.length > 0) { - const sortedSilences = silences.sort((a, b) => { - return new Date(b.endsAt) - new Date(a.endsAt) - }) - return sortedSilences[0].endsAt - } -} - -// returns options for duration select dropdown. Options with which exceeds the expiration date are marked as "covered" -// return also the first option which is not covered by the expiration date -export const getSelectOptions = (expirationDate) => { - if (!expirationDate) return { items: DEFAULT_DURATION_OPTIONS } - const now = new Date() - const expiration = new Date(expirationDate) - const diff = expiration - now - const diffInHours = diff / (1000 * 60 * 60) - const options = DEFAULT_DURATION_OPTIONS.map((o) => { - if (o.value <= diffInHours) { - return { - ...o, - label: o.label + " (covered with the existing silence)", - covered: true, - } - } - return o - }) - // find the first option which is not covered by the expiration date - const firstNotCovered = options.find((o) => !o?.covered) - - return { items: options, firstNotCovered } -} - -// Setup the matchers for the silence removing the excluded labels -// These excluded labels are those that not included by default when generating a silence configuration. -// The enrichedLabels are those that are added by the worker just for UI purposes when the alert is received. -export const setupMatchers = ( - alertLabels, - excludedLabels = [], - enrichedLabels = [] -) => { - if (!alertLabels || !excludedLabels) return - let items = [] - - Object.keys(alertLabels).forEach((label) => { - const value = alertLabels?.[label] - if (value) { - const matcher = { - name: label, - value: value, - isRegex: false, // for now hardcode isRegex to false since we take the exact value - excluded: false, - configurable: false, - } - if (enrichedLabels.includes(label)) { - // do not add enriched labels, skip - } else if (excludedLabels.includes(label)) { - // mark excluded label - items.push({ ...matcher, excluded: true, configurable: true }) - } else { - items.push(matcher) - } - } - }) - return items -} diff --git a/apps_deprecated/supernova/src/components/silences/silenceHelpers.test.js b/apps_deprecated/supernova/src/components/silences/silenceHelpers.test.js deleted file mode 100644 index 98ce288c7..000000000 --- a/apps_deprecated/supernova/src/components/silences/silenceHelpers.test.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { setupMatchers } from "./silenceHelpers" - -describe("helpers", () => { - describe("setupMatchers", () => { - test("mark excluded labels and ignore enriched labels", () => { - const alertLables = { - region: "na-us-1", - service: "compute", - severity: "critical", - pod: "node014-bb164.cc.na-us-1.cloud.sap", - status: "active", - } - const matchers = setupMatchers(alertLables, ["pod"], ["status"]) - expect(matchers).toEqual([ - { - name: "region", - value: "na-us-1", - isRegex: false, - excluded: false, - configurable: false, - }, - { - name: "service", - value: "compute", - isRegex: false, - excluded: false, - configurable: false, - }, - { - name: "severity", - value: "critical", - isRegex: false, - excluded: false, - configurable: false, - }, - { - name: "pod", - value: "node014-bb164.cc.na-us-1.cloud.sap", - isRegex: false, - excluded: true, - configurable: true, - }, - ]) - }) - }) -}) diff --git a/apps_deprecated/supernova/src/components/silences/silenceScheduledHelpers.js b/apps_deprecated/supernova/src/components/silences/silenceScheduledHelpers.js deleted file mode 100644 index a8cd12a63..000000000 --- a/apps_deprecated/supernova/src/components/silences/silenceScheduledHelpers.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const DEFAULT_FORM_VALUES = { - fixed_labels: {}, - editable_labels: {}, - comment: { - value: "", - error: null, - }, - createdBy: "", - date: { - start: null, - end: null, - error: null, - }, -} - -////// Form Validation - -export const validateForm = (state) => { - let formState = state - let errorexist = false - - // validate if comment is at least 3 characters long - if (formState.comment.value.length < 3) { - errorexist = true - formState = { - ...formState, - comment: { - ...formState.comment, // Only create the comment object if it exists - error: "Please enter at least 3 characters", - }, - } - } - - // checks if start date is before end date - if (new Date(formState.date.start) >= new Date(formState.date.end)) { - errorexist = true - formState = { - ...formState, - date: { - ...formState.date, // Only create the comment object if it exists - error: "The start date need to be before the end date", - }, - } - } - - // All editable labels are valid regular expressions - Object.keys(formState.editable_labels).map((editable_label) => { - if (!validateLabelValue(formState.editable_labels[editable_label].value)) { - errorexist = true - formState = { - ...formState, - editable_labels: { - ...formState.editable_labels, - [editable_label]: { - ...formState.editable_labels[editable_label], - error: `Value for ${editable_label} is not a valid regular expression`, - }, - }, - } - } - - if (!formState.editable_labels[editable_label]?.value) { - errorexist = true - formState = { - ...formState, - editable_labels: { - ...formState.editable_labels, - [editable_label]: { - ...formState.editable_labels[editable_label], - error: `Value for ${editable_label} is empty`, - }, - }, - } - } - }) - - if (!errorexist) { - return null - } - - return formState -} - -const validateLabelValue = (value) => { - try { - return !!new RegExp(value) - } catch (e) { - return false - } -} diff --git a/apps_deprecated/supernova/src/components/status/StatusBar.jsx b/apps_deprecated/supernova/src/components/status/StatusBar.jsx deleted file mode 100644 index 425273aa5..000000000 --- a/apps_deprecated/supernova/src/components/status/StatusBar.jsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { DateTime } from "luxon" - -import { Spinner, Stack } from "juno-ui-components" - -const statusBarStyles = ` - bg-theme-background-lvl-1 - py-1.5 - px-4 - my-px - text-theme-light -` - -const StatusBar = ({totalCounts, isUpdating, updatedAt}) => { - - return ( - -
- {`${totalCounts.total} alerts`} - {`(${totalCounts.critical || 0} critical, ${totalCounts.warning || 0} warning, ${totalCounts.info || 0} info)`} -
- - {isUpdating && - - } - {updatedAt && - `updated ${DateTime.fromMillis(updatedAt).toLocaleString({...DateTime.TIME_24_WITH_SHORT_OFFSET})}` - } - -
- ) -} - -export default StatusBar \ No newline at end of file diff --git a/apps_deprecated/supernova/src/helpers.js b/apps_deprecated/supernova/src/helpers.js deleted file mode 100644 index 9d8953d9b..000000000 --- a/apps_deprecated/supernova/src/helpers.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const parseError = (error) => { - let errMsg = error - - // check if error is JSON containing message or just string - if (typeof error === "string") { - errMsg = parseMessage(error) - } - - // check if the error is a object containing message - if (typeof error === "object") { - console.log("Error parsing error message::object") - if (error?.message) { - errMsg = parseMessage(error?.message) - } - } - return errMsg -} - -const parseMessage = (message) => { - let newMsg = message - try { - newMsg = JSON.parse(message) - if (newMsg?.message) { - newMsg = (newMsg?.code ? `${newMsg.code}, ` : "") + newMsg?.message - } - } catch (error) {} - - if (newMsg === "Failed to fetch") { - newMsg = - "Sorry, there was an issue fetching the data. Possible causes could include network issues, incorrect URL, or server outages. " - } - - return newMsg -} diff --git a/apps_deprecated/supernova/src/hooks/useAlertmanagerAPI.js b/apps_deprecated/supernova/src/hooks/useAlertmanagerAPI.js deleted file mode 100644 index e4b478cc6..000000000 --- a/apps_deprecated/supernova/src/hooks/useAlertmanagerAPI.js +++ /dev/null @@ -1,201 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect } from "react" -import { - useAlertsActions, - useUserIsActive, - useSilencesActions, - useSilencesLocalItems, -} from "./useAppStore" - -const createWorker = (path) => { - return fetch(new URL(path, import.meta.url)) - .then((r) => r.blob()) - .then((blob) => { - var blobUrl = window.URL.createObjectURL(blob) - let worker - - const createWorker = () => { - if (!worker) worker = new Worker(blobUrl, { type: "module" }) - return worker - } - - const stopWorker = () => { - if (!worker) return - worker.terminate() - worker = null - } - - return { createWorker, stopWorker } - }) -} - -// create workers -const alertsWorker = createWorker("workers/alerts.js") -const silencesWorker = createWorker("workers/silences.js") - -const useAlertmanagerAPI = (apiEndpoint) => { - const { - setAlertsData, - setIsLoading: setAlertsIsLoading, - setIsUpdating: setAlertsIsUpdating, - setError: setAlertsError, - } = useAlertsActions() - const isUserActive = useUserIsActive() - const { - setSilences, - setIsUpdating: setSilencesIsUpdating, - setIsLoading: setSilencesIsLoading, - setError: setSilencesError, - } = useSilencesActions() - - //Setup web workers - useEffect(() => { - let cleanupAlertsWorker - let cleanupSilencesWorker - - alertsWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - console.log("Worker::Setting up ALERTS worker", worker) - - // receive messages from worker - worker.onmessage = (e) => { - const action = e.data.action - switch (action) { - case "ALERTS_UPDATE": - console.log("Worker::ALERT_UPDATE::", e.data) - setAlertsData({ items: e.data.alerts, counts: e.data.counts }) - break - case "ALERTS_FETCH_START": - console.log("Worker::ALERTS_FETCH_START::") - setAlertsIsUpdating(true) - break - case "ALERTS_FETCH_END": - console.log("Worker::ALERTS_FETCH_END::") - setAlertsIsUpdating(false) - break - case "ALERTS_FETCH_ERROR": - console.log("Worker::ALERTS_FETCH_ERROR::", e.data.error) - setAlertsIsUpdating(false) - // error comes as object string and have to be parsed - setAlertsError(e.data.error) - break - } - } - - cleanupAlertsWorker = () => { - console.log("Worker::Terminating Alerts Worker") - return stopWorker() - } - }) - - silencesWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - console.log("Worker::Setting up SILENCES worker") - - // receive messages from worker - worker.onmessage = (e) => { - const action = e.data.action - switch (action) { - case "SILENCES_UPDATE": - console.log("Worker::SILENCES_UPDATE::", e.data) - setSilences({ - items: e.data?.silences, - itemsHash: e.data?.silencesHash, - itemsByState: e.data?.silencesBySate, - }) - break - case "SILENCES_FETCH_START": - console.log("Worker::SILENCES_FETCH_START::") - setSilencesIsUpdating(true) - break - case "SILENCES_FETCH_END": - console.log("Worker::SILENCES_FETCH_END::") - setSilencesIsUpdating(false) - break - case "SILENCES_FETCH_ERROR": - console.log("Worker::SILENCES_FETCH_ERROR::", e.data.error) - setSilencesIsUpdating(false) - // error comes as object string and have to be parsed - setSilencesError(e.data.error) - break - } - } - - cleanupSilencesWorker = () => { - console.log("Worker::Terminating Silences Worker") - return stopWorker() - } - }) - - return () => { - cleanupAlertsWorker && cleanupAlertsWorker() - cleanupSilencesWorker && cleanupSilencesWorker() - } - }, []) - - // Reconfigure the workers each time we get a new endpoint - useEffect(() => { - if (!apiEndpoint) return - - // set alerts state to loading - setAlertsIsLoading(true) - alertsWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - // initial config - worker.postMessage({ - action: "ALERTS_CONFIGURE", - fetchVars: { - apiEndpoint, - options: {}, - }, - debug: true, - }) - }) - - setSilencesIsLoading(true) - silencesWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - // initial config - worker.postMessage({ - action: "SILENCES_CONFIGURE", - apiEndpoint: apiEndpoint, - }) - }) - }, [apiEndpoint]) - - // enable/disable watching in the workers - useEffect(() => { - if (isUserActive === undefined) return - alertsWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - worker.postMessage({ - action: "ALERTS_CONFIGURE", - watch: isUserActive, - }) - }) - silencesWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - worker.postMessage({ - action: "SILENCES_CONFIGURE", - watch: isUserActive, - }) - }) - }, [isUserActive]) - - // as soon as we have locally some silences we refetch the them - useEffect(() => { - if (!useSilencesLocalItems || useSilencesLocalItems?.length <= 0) return - silencesWorker.then(({ createWorker, stopWorker }) => { - const worker = createWorker() - worker.postMessage({ - action: "SILENCES_FETCH", - }) - }) - }, [useSilencesLocalItems]) -} - -export default useAlertmanagerAPI diff --git a/apps_deprecated/supernova/src/hooks/useAppStore.js b/apps_deprecated/supernova/src/hooks/useAppStore.js deleted file mode 100644 index a84448c9e..000000000 --- a/apps_deprecated/supernova/src/hooks/useAppStore.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { createContext, useContext } from "react" -import { createStore, useStore } from "zustand" -import { devtools } from "zustand/middleware" - -import createSilencesSlice from "../lib/createSilencesSlice" -import createAlertsSlice from "../lib/createAlertsSlice" -import createFiltersSlice from "../lib/createFiltersSlice" -import createAuthDataSlice from "../lib/createAuthDataSlice" -import createGlobalsSlice from "../lib/createGlobalsSlice" -import createUserActivitySlice from "../lib/createUserActivitySlice" - -const createAppStore = devtools((set, get) => ({ - ...createGlobalsSlice(set, get), - ...createAuthDataSlice(set, get), - ...createUserActivitySlice(set, get), - ...createAlertsSlice(set, get), - ...createFiltersSlice(set, get), - ...createSilencesSlice(set, get), -})) - -const StoreContext = createContext() - -export const StoreProvider = ({ options, children }) => { - return ( - ({ - ...createGlobalsSlice(set, get), - ...createAuthDataSlice(set, get), - ...createUserActivitySlice(set, get), - ...createAlertsSlice(set, get), - ...createFiltersSlice(set, get), - ...createSilencesSlice(set, get, options), - })) - )} - > - {children} - - ) -} - -const useAppStore = (selector) => useStore(useContext(StoreContext), selector) - -// atomic exports only instead of exporting whole store -// See reasoning here: https://tkdodo.eu/blog/working-with-zustand - -// Globals exports -export const useGlobalsEmbedded = () => - useAppStore((state) => state.globals.embedded) -export const useShowDetailsFor = () => - useAppStore((state) => state.globals.showDetailsFor) -export const useGlobalsApiEndpoint = () => - useAppStore((state) => state.globals.apiEndpoint) -export const useGlobalsActions = () => - useAppStore((state) => state.globals.actions) - -// AUTH -export const useAuthData = () => useAppStore((state) => state.auth.data) -export const useAuthIsProcessing = () => - useAppStore((state) => state.auth.isProcessing) -export const useAuthLoggedIn = () => useAppStore((state) => state.auth.loggedIn) -export const useAuthError = () => useAppStore((state) => state.auth.error) -export const useAuthLastAction = () => - useAppStore((state) => state.auth.lastAction) -export const useAuthAppLoaded = () => - useAppStore((state) => state.auth.appLoaded) -export const useAuthAppIsLoading = () => - useAppStore((state) => state.auth.appIsLoading) -export const useAuthActions = () => useAppStore((state) => state.auth.actions) - -// UserActivity exports -export const useUserIsActive = () => - useAppStore((state) => state.userActivity.isActive) - -export const useUserActivityActions = () => - useAppStore((state) => state.userActivity.actions) - -// Alert exports -export const useAlertsItems = () => useAppStore((state) => state.alerts.items) -export const useAlertsItemsFiltered = () => - useAppStore((state) => state.alerts.itemsFiltered) -export const useAlertsTotalCounts = () => - useAppStore((state) => state.alerts.totalCounts) -export const useAlertsSeverityCountsPerRegion = () => - useAppStore((state) => state.alerts.severityCountsPerRegion) -export const useAlertsRegions = () => - useAppStore((state) => state.alerts.regions) -export const useAlertsRegionsFiltered = () => - useAppStore((state) => state.alerts.regionsFiltered) -export const useAlertsIsLoading = () => - useAppStore((state) => state.alerts.isLoading) -export const useAlertsIsUpdating = () => - useAppStore((state) => state.alerts.isUpdating) -export const useAlertsUpdatedAt = () => - useAppStore((state) => state.alerts.updatedAt) -export const useAlertsError = () => useAppStore((state) => state.alerts.error) -export const useAlertEnrichedLabels = () => - useAppStore((state) => state.alerts.enrichedLabels) - -export const useAlertsActions = () => - useAppStore((state) => state.alerts.actions) - -// Filter exports -export const useFilterLabels = () => - useAppStore((state) => state.filters.labels) -export const useActiveFilters = () => - useAppStore((state) => state.filters.activeFilters) -export const useSearchTerm = () => - useAppStore((state) => state.filters.searchTerm) -export const useFilterLabelValues = () => - useAppStore((state) => state.filters.filterLabelValues) -export const usePredefinedFilters = () => - useAppStore((state) => state.filters.predefinedFilters) -export const useActivePredefinedFilter = () => - useAppStore((state) => state.filters.activePredefinedFilter) - -export const useFilterActions = () => - useAppStore((state) => state.filters.actions) - -// Silences exports -export const useSilencesItems = () => - useAppStore((state) => state.silences.items) -export const useSilencesItemsHash = () => - useAppStore((state) => state.silences.itemsHash) -export const useSilencesExcludedLabels = () => - useAppStore((state) => state.silences.excludedLabels) -export const useSilencesIsLoading = () => - useAppStore((state) => state.silences.isLoading) -export const useSilencesIsUpdating = () => - useAppStore((state) => state.silences.isUpdating) -export const useSilencesUpdatedAt = () => - useAppStore((state) => state.silences.updatedAt) -export const useSilencesError = () => - useAppStore((state) => state.silences.error) -export const useSilencesLocalItems = () => - useAppStore((state) => state.silences.localItems) - -export const useSilenceTemplates = () => - useAppStore((state) => state.silences.templates) - -export const useSilencesActions = () => - useAppStore((state) => state.silences.actions) diff --git a/apps_deprecated/supernova/src/hooks/useCommunication.js b/apps_deprecated/supernova/src/hooks/useCommunication.js deleted file mode 100644 index be3964e20..000000000 --- a/apps_deprecated/supernova/src/hooks/useCommunication.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useEffect } from "react" -import { broadcast, get, watch } from "communicator" -import { - useUserActivityActions, - useAuthAppLoaded, - useAuthIsProcessing, - useAuthError, - useAuthLoggedIn, - useAuthLastAction, - useAuthActions, -} from "./useAppStore" -import { AUTH_ACTIONS } from "../lib/createAuthDataSlice" - -const useCommunication = () => { - console.log("[supernova] useCommunication setup") - const { setIsActive } = useUserActivityActions() - const authAppLoaded = useAuthAppLoaded() - const authIsProcessing = useAuthIsProcessing() - const authError = useAuthError() - const authLoggedIn = useAuthLoggedIn() - const authLastAction = useAuthLastAction() - const { setData: authSetData, setAppLoaded: authSetAppLoaded } = - useAuthActions() - - useEffect(() => { - // watch for user activity updates messages - // with the watcher we get the user activity object when this app is loaded before the Auth app - const unwatch = watch( - "USER_ACTIVITY_UPDATE_DATA", - (data) => { - console.log("got message USER_ACTIVITY_UPDATE_DATA: ", data) - setIsActive(data?.isActive) - }, - { debug: true } - ) - return unwatch - }, [setIsActive]) - - // allow supernova to login/logout the user. Visible when app is not in embedded mode - useEffect(() => { - if (!authAppLoaded || authIsProcessing || authError) return - if (authLastAction?.name === AUTH_ACTIONS.SIGN_ON && !authLoggedIn) { - broadcast("AUTH_LOGIN", "supernova", { debug: false }) - } else if (authLastAction?.name === AUTH_ACTIONS.SIGN_OUT && authLoggedIn) { - broadcast("AUTH_LOGOUT", "supernova") - } - }, [authAppLoaded, authIsProcessing, authError, authLoggedIn, authLastAction]) - - useEffect(() => { - if (!authSetData || !authSetAppLoaded) return - - get("AUTH_APP_LOADED", authSetAppLoaded) - const unwatchLoaded = watch("AUTH_APP_LOADED", authSetAppLoaded) - - get("AUTH_GET_DATA", authSetData) - const unwatchUpdate = watch("AUTH_UPDATE_DATA", authSetData) - - return () => { - if (unwatchLoaded) unwatchLoaded() - if (unwatchUpdate) unwatchUpdate() - } - }, [authSetData, authSetAppLoaded]) -} - -export default useCommunication diff --git a/apps_deprecated/supernova/src/hooks/useUrlState.js b/apps_deprecated/supernova/src/hooks/useUrlState.js deleted file mode 100644 index 7e20b6d1d..000000000 --- a/apps_deprecated/supernova/src/hooks/useUrlState.js +++ /dev/null @@ -1,134 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { useLayoutEffect, useEffect, useState } from "react" -import { registerConsumer } from "url-state-provider" -import { - useAuthLoggedIn, - useAuthData, - useFilterLabels, - useFilterActions, - useActiveFilters, - useActivePredefinedFilter, - useSearchTerm, - useShowDetailsFor, - useGlobalsActions, -} from "./useAppStore" - -const urlStateManager = registerConsumer("supernova") -const ACTIVE_FILTERS = "f" -const ACTIVE_PREDEFINED_FILTER = "p" -const DETAILS_FOR = "d" -const SEARCH_TERM = "s" - -const useUrlState = () => { - const [isURLRead, setIsURLRead] = useState(false) - const loggedIn = useAuthLoggedIn() - const authData = useAuthData() - const { setActiveFilters, setActivePredefinedFilter, setSearchTerm } = - useFilterActions() - const filterLabels = useFilterLabels() - const activeFilters = useActiveFilters() - const searchTerm = useSearchTerm() - const activePredefinedFilter = useActivePredefinedFilter() - const { setShowDetailsFor } = useGlobalsActions() - const detailsFor = useShowDetailsFor() - - // Set initial state from URL (on login) - // useLayoutEffect so this is done before rendering anything - useLayoutEffect(() => { - // do not read the url state until the user is logged in and do it just once - if (!loggedIn || isURLRead) return - - console.log( - "SUPERNOVA:: setting up state from url with state::", - urlStateManager.currentState() - ) - - // get active filters from url state - const activeFiltersFromURL = - urlStateManager.currentState()?.[ACTIVE_FILTERS] - - // check if there are active filters in the url state - if (activeFiltersFromURL && Object.keys(activeFiltersFromURL).length > 0) { - setActiveFilters(activeFiltersFromURL) - } else { - // otherwise set the support group filter - // we just add this default filter when no other filters are set via URL - const label = "support_group" - if ( - authData?.parsed?.supportGroups?.length > 0 && - filterLabels?.length > 0 && - filterLabels.includes(label) - ) { - // this will also trigger a filterItems() call from the store self - setActiveFilters({ [label]: authData.parsed.supportGroups }) - } - } - - const searchTermFromURL = urlStateManager.currentState()?.[SEARCH_TERM] - if (searchTermFromURL) { - // decode the search term from the url. It is base64 encoded to avoid issues with special characters - setSearchTerm(atob(searchTermFromURL)) - } - - // get active predefined filters from url state - const activePredefinedFilterFromURL = - urlStateManager.currentState()?.[ACTIVE_PREDEFINED_FILTER] - if (activePredefinedFilterFromURL) { - setActivePredefinedFilter(activePredefinedFilterFromURL) - } - - // get detail view target from url state - const detailsForFromURL = urlStateManager.currentState()?.[DETAILS_FOR] - if (detailsForFromURL) { - setShowDetailsFor(detailsForFromURL) - } - setIsURLRead(true) - }, [loggedIn, isURLRead, authData, filterLabels]) - - // sync URL with the desired states - useEffect(() => { - // do not synchronize the states until the url state is read and user logged in - if (!loggedIn || !isURLRead) return - - // encode searchTerm before pushing it to the URL to avoid missinterpretation of special characters - const encodedSearchTerm = btoa(searchTerm) - - const newState = { - ...urlStateManager.currentState(), - [ACTIVE_FILTERS]: activeFilters, - [SEARCH_TERM]: encodedSearchTerm, - [ACTIVE_PREDEFINED_FILTER]: activePredefinedFilter, - [DETAILS_FOR]: detailsFor, - } - - // do not push the state if it is the same as the current one - // otherwise it will reset the browser history and the forward button will not work - if ( - JSON.stringify(newState) === - JSON.stringify(urlStateManager.currentState()) - ) - return - - urlStateManager.push(newState) - }, [loggedIn, activeFilters, searchTerm, activePredefinedFilter, detailsFor]) - - // Support for back button - useEffect(() => { - const unregisterStateListener = urlStateManager.onChange((state) => { - setActiveFilters(state?.[ACTIVE_FILTERS]) - setSearchTerm(state?.[SEARCH_TERM]) - setActivePredefinedFilter(state?.[ACTIVE_PREDEFINED_FILTER]) - setShowDetailsFor(state?.[DETAILS_FOR]) - }) - - return () => { - unregisterStateListener() - } - }, []) -} - -export default useUrlState diff --git a/apps_deprecated/supernova/src/index.js b/apps_deprecated/supernova/src/index.js deleted file mode 100644 index f6f988315..000000000 --- a/apps_deprecated/supernova/src/index.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createRoot } from "react-dom/client" -import React from "react" - -// export mount and unmount functions -export const mount = (container, options = {}) => { - import("./App").then((App) => { - mount.root = createRoot(container) - mount.root.render(React.createElement(App.default, options?.props)) - }) -} - -export const unmount = () => mount.root && mount.root.unmount() diff --git a/apps_deprecated/supernova/src/lib/createAlertsSlice.js b/apps_deprecated/supernova/src/lib/createAlertsSlice.js deleted file mode 100644 index ae3add14b..000000000 --- a/apps_deprecated/supernova/src/lib/createAlertsSlice.js +++ /dev/null @@ -1,218 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import produce from "immer" -import { countAlerts } from "./utils" - -const initialAlertsState = { - items: [], - itemsFiltered: [], - totalCounts: {}, // { total: number, critical: number, ...}, - severityCountsPerRegion: {}, // {"eu-de-1": { total: number, critical: {total: number, suppressed: number}, warning: {...}, ...} - regions: [], // save all available regions from initial list here - regionsFiltered: [], // regions list filtered by active predefined filters - enrichedLabels: ["status"], // labels that are enriched by the alert worker - isLoading: false, - isUpdating: false, - updatedAt: null, - error: null, -} - -const createAlertsSlice = (set, get) => ({ - alerts: { - ...initialAlertsState, - actions: { - setAlertsData: ({ items, counts }) => { - set( - produce((state) => { - state.alerts.items = items - state.alerts.totalCounts = counts?.global - state.alerts.severityCountsPerRegion = counts?.regions - state.alerts.regions = Object.keys(counts?.regions).sort() - state.alerts.isLoading = false - state.alerts.isUpdating = false - state.alerts.updatedAt = Date.now() - state.alerts.error = null - - // on the initial fetch copy all items to the filtered items list once since - // most views operate on the filtered items list - if (state.alerts.itemsFiltered.length === 0) { - state.alerts.itemsFiltered = items - } - - // same with the filtered regions list - if (state.alerts.regionsFiltered.length === 0) { - state.alerts.regionsFiltered = state.alerts.regions - } - - // TODO: - // reload previously loaded filter label values (they might have changed since last load) - // state.filters.filterLabelValues = {} // -> do NOT just reset them, reload instead - }), - false, - "alerts.setAlertsData" - ) - // if there are already active filters or active predefined filters, filter the new list - if ( - Object.keys(get().filters.activeFilters)?.length > 0 || - get().filters.activePredefinedFilter - ) { - get().alerts.actions.filterItems() - } - }, - - filterItems: () => { - const activePredefinedFilter = get().filters.predefinedFilters.find( - (filter) => filter.name === get().filters.activePredefinedFilter - ) - - const filteredRegions = new Set() - - set( - produce((state) => { - state.alerts.itemsFiltered = state.alerts.items.filter((item) => { - let visible = true - - // test if the item has a label "visibility" with value "hidden" - // if it does, immediately return false, no further processing needed, these items are always filtered out - if (item.labels.visibility === "hidden") { - return false - } - - // if the item is still visible test if item labels match the regex matchers of the active predefined filter - // for each key and value pair in the filter matchers check if the key's value regex matches the item's label value for this key - // if it doesn't match, set visible to false and break out of the loop - activePredefinedFilter && - Object.entries(activePredefinedFilter.matchers).forEach( - ([key, value]) => { - if (!new RegExp(value, "i").test(item.labels[key])) { - visible = false - return - } else { - // if the item is visible, add the item's region to the filtered regions set - // this way the filtered Regions set will contain all regions that have at least one visible item - filteredRegions.add(item.labels.region) - } - } - ) - - // if the item is still visible after the predefined filters, check if it gets filtered out by the active filters - // active filters is an object where the keys correspond to labels and the value is an array of all selected values to be filtered by - // iterate over all active filter keys and then check if one of the selected values matches the item's value for this key - if (visible) { - Object.keys(state.filters.activeFilters).forEach((key) => { - // if the item's label value for the current label isn't included in the selected filters set visible to false, i.e. filter out item - // this automatically leads to different values for the same label to be OR concatenated, while different labels are AND concatenated - // so an item must have at least one of the selected values for each filtered label - if ( - state.filters.activeFilters[key].indexOf(item.labels[key]) < - 0 - ) { - // we can break out of the loop here since we already know the item is not visible - visible = false - return - } - }) - } - - // if the item is still visible check if it gets filtered out by a search term - // the search term is matched against the stringified item object via regex - // if the item object does not contain the search term, it is not visible - if ( - visible && - state.filters.searchTerm && - state.filters.searchTerm.length > 0 - ) { - const itemString = JSON.stringify(item) - const re = new RegExp(state.filters.searchTerm, "i") - if (!itemString.match(re)) { - visible = false - } - } - - return visible - }) - }), - false, - "alerts.filterItems" - ) - get().alerts.actions.updateFilteredCounts() - if (filteredRegions.size > 0) { - get().alerts.actions.setRegionsFiltered( - Array.from(filteredRegions).sort() - ) - } else { - // if nothing was filtered out, set the filtered regions to all available regions - get().alerts.actions.setRegionsFiltered(get().alerts.regions) - } - }, - - setFilteredItems: (items) => { - set( - produce((state) => { - state.alerts.itemsFiltered = items - }), - false, - "alerts.setFilteredItems" - ) - get().alerts.actions.updateFilteredCounts() - }, - - setRegionsFiltered: (regions) => { - set( - produce((state) => { - state.alerts.regionsFiltered = regions - }), - false, - "alerts.setRegionsFiltered" - ) - }, - - updateFilteredCounts: () => { - const counts = countAlerts(get().alerts.itemsFiltered) - set( - produce((state) => { - state.alerts.totalCounts = counts.global - state.alerts.severityCountsPerRegion = counts.regions - }), - false, - "alerts.updateFilteredCounts" - ) - }, - - setIsLoading: (value) => { - set( - (state) => ({ alerts: { ...state.alerts, isLoading: value } }), - false, - "alerts.setIsLoading" - ) - }, - - setIsUpdating: (value) => { - set( - (state) => ({ alerts: { ...state.alerts, isUpdating: value } }), - false, - "alerts.setIsUpdating" - ) - }, - - setError: (error) => { - set( - (state) => ({ alerts: { ...state.alerts, error, isLoading: false } }), - false, - "alerts.setError" - ) - }, - - getAlertByFingerprint: (fingerprint) => { - return get().alerts.items.find( - (alert) => alert.fingerprint === fingerprint - ) - }, - }, - }, -}) - -export default createAlertsSlice diff --git a/apps_deprecated/supernova/src/lib/createAlertsSlice.test.js b/apps_deprecated/supernova/src/lib/createAlertsSlice.test.js deleted file mode 100644 index a3197bb99..000000000 --- a/apps_deprecated/supernova/src/lib/createAlertsSlice.test.js +++ /dev/null @@ -1,440 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { renderHook, act } from "@testing-library/react" -import { - useAlertsActions, - useAlertEnrichedLabels, - StoreProvider, - useAlertsItemsFiltered, -} from "../hooks/useAppStore" - -describe("createAlertsSlice", () => { - describe("setEnrichedLabels", () => { - it("return status as default", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useAlertsActions(), - enrichedLabels: useAlertEnrichedLabels(), - }), - { wrapper } - ) - expect(store.result.current.enrichedLabels).toEqual(["status"]) - }) - }) - - describe("setFilteredItems", () => { - it("return empty array as default", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useAlertsActions(), - itemsFiltered: useAlertsItemsFiltered(), - }), - { wrapper } - ) - expect(store.result.current.itemsFiltered).toEqual([]) - }) - - it("accepts and transforms to array of strings coma separated strings containing the labels to use", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useAlertsActions(), - itemsFiltered: useAlertsItemsFiltered(), - }), - { wrapper } - ) - - let mock - - act(() => { - store.result.current.actions.setFilteredItems(mock) - }) - - expect(store.result.current.enrichedLabels).toEqual(mock) - }) - }) -}) - -/** - * { - "action": "ALERTS_UPDATE", - "alerts": [ - { - "annotations": { - "description": "storage paths for `node003-bb322.cc.eu-de-1.cloud.sap` is less than other hosts in the `productionbb322`. (vc-d-4.cc.eu-de-1.cloud.sap)", - "summary": "storage paths for `node003-bb322.cc.eu-de-1.cloud.sap` is less than other hosts in the `productionbb322`. (vc-d-4.cc.eu-de-1.cloud.sap)" - }, - "endsAt": "2023-11-01T08:29:10.787Z", - "fingerprint": "662491f9dd5bc5eb", - "receivers": [ - { - "name": "elastic" - }, - { - "name": "awx" - }, - { - "name": "octobus" - }, - { - "name": "slack_vmware_info" - } - ], - "startsAt": "2023-10-23T09:29:40.787Z", - "status": { - "inhibitedBy": [], - "silencedBy": [ - "ed08c9ff-898a-49c9-9621-35f38191462e" - ], - "state": "suppressed" - }, - "updatedAt": "2023-11-01T08:25:11.606Z", - "generatorURL": "https://prometheus-vmware-vc-d-4.eu-de-1.cloud.sap/graph?g0.expr=vrops_hostsystem_storage_number_of_path+%3C+on+%28vccluster%29+group_left+%28%29+%28max+by+%28vccluster%29+%28vrops_hostsystem_storage_number_of_path%29%29&g0.tab=1", - "labels": { - "alertname": "HostStoragePathCheck", - "cluster": "s-eu-de-1", - "cluster_type": "scaleout", - "collector": "vrops-vc-d-4-host", - "context": "node003-bb322.cc.eu-de-1.cloud.sap storage paths", - "datacenter": "eu-de-1d", - "hostsystem": "node003-bb322.cc.eu-de-1.cloud.sap", - "internal_name": "host-120240", - "job": "vrops-exporter", - "meta": "storage paths for `node003-bb322.cc.eu-de-1.cloud.sap` is less than other hosts in the `productionbb322`. (vc-d-4.cc.eu-de-1.cloud.sap)", - "no_alert_on_absence": "true", - "prometheus": "vmware-monitoring/vmware-vc-d-4", - "region": "eu-de-1", - "service": "compute", - "severity": "info", - "support_group": "compute", - "tier": "vmware", - "vccluster": "productionbb322", - "vcenter": "vc-d-4.cc.eu-de-1.cloud.sap", - "status": "suppressed" - } - }, - { - "annotations": { - "description": "The certificate for kubevirt-operator-webhook,kubevirt-operator-webhook.kubevirt,kubevirt-operator-webhook.kubevirt.svc,kubevirt-operator-webhook.kubevirt.svc.cluster.local expires in 417ms. See secret kubevirt/kubevirt-operator-certs, key tls.crt.", - "summary": "Certificate expires" - }, - "endsAt": "2023-11-01T08:29:52.979Z", - "fingerprint": "dcff442a4c5301b6", - "receivers": [ - { - "name": "elastic" - } - ], - "startsAt": "2023-10-04T09:49:52.979Z", - "status": { - "inhibitedBy": [ - "82b6187e7c363b9a" - ], - "silencedBy": [], - "state": "suppressed" - }, - "updatedAt": "2023-11-01T08:25:52.998Z", - "generatorURL": "https://prometheus-kubernetes.qa-de-6.cloud.sap/graph?g0.expr=%28secrets_exporter_certificate_not_after+-+time%28%29%29+%2F+60+%2F+60+%2F+24+%3C%3D+30&g0.tab=1", - "labels": { - "alertname": "CertificateExpiresIn30Days", - "app": "k8s-secrets-certificate-exporter", - "ccloud_support_group": "observability", - "cluster": "qa-de-6", - "cluster_type": "metal", - "context": "availability", - "host": "kubevirt-operator-webhook,kubevirt-operator-webhook.kubevirt,kubevirt-operator-webhook.kubevirt.svc,kubevirt-operator-webhook.kubevirt.svc.cluster.local", - "instance": "100.90.11.32:9091", - "job": "pods", - "key": "tls.crt", - "kubernetes_namespace": "kube-monitoring", - "kubernetes_pod_name": "k8s-secrets-certificate-exporter-664b7d4d68-p28hp", - "metrics_path": "/metrics", - "pod_template_hash": "664b7d4d68", - "prometheus": "kube-monitoring/collector-kubernetes", - "region": "qa-de-6", - "secret": "kubevirt/kubevirt-operator-certs", - "service": "certificates", - "severity": "info", - "support_group": "containers", - "tier": "k8s", - "status": "suppressed" - } - } - ], - "counts": { - "global": { - "total": 3469, - "critical": 84, - "warning": 281, - "info": 3088, - "none": 16 - }, - "regions": { - "eu-de-2": { - "total": 640, - "critical": { - "total": 7, - "suppressed": 3 - }, - "warning": { - "total": 51, - "suppressed": 6 - }, - "info": { - "total": 578, - "suppressed": 5 - }, - "none": { - "total": 4 - } - }, - "qa-de-1": { - "total": 393, - "critical": { - "total": 46 - }, - "warning": { - "total": 28, - "suppressed": 12 - }, - "info": { - "total": 319, - "suppressed": 38 - } - }, - "ap-au-1": { - "total": 169, - "critical": { - "total": 11, - "suppressed": 2 - }, - "warning": { - "total": 34, - "suppressed": 8 - }, - "info": { - "total": 124, - "suppressed": 3 - } - }, - "qa-de-3": { - "total": 65, - "critical": { - "total": 1 - }, - "warning": { - "total": 6 - }, - "info": { - "total": 58 - } - }, - "ap-cn-1": { - "total": 173, - "critical": { - "total": 9, - "suppressed": 9 - }, - "warning": { - "total": 35, - "suppressed": 6 - }, - "info": { - "total": 126, - "suppressed": 1 - }, - "none": { - "total": 3 - } - }, - "eu-de-1": { - "total": 415, - "critical": { - "total": 3, - "suppressed": 3 - }, - "warning": { - "total": 29, - "suppressed": 1 - }, - "info": { - "total": 383, - "suppressed": 45 - } - }, - "na-us-1": { - "total": 273, - "critical": { - "total": 3, - "suppressed": 3 - }, - "warning": { - "total": 18 - }, - "info": { - "total": 252, - "suppressed": 16 - } - }, - "eu-nl-1": { - "total": 185, - "critical": { - "total": 1, - "suppressed": 1 - }, - "warning": { - "total": 6 - }, - "info": { - "total": 178, - "suppressed": 2 - } - }, - "na-us-2": { - "total": 148, - "critical": { - "total": 1, - "suppressed": 1 - }, - "warning": { - "total": 4 - }, - "info": { - "total": 143, - "suppressed": 1 - } - }, - "ap-sa-1": { - "total": 114, - "critical": { - "total": 2, - "suppressed": 2 - }, - "warning": { - "total": 2, - "suppressed": 2 - }, - "info": { - "total": 110, - "suppressed": 1 - } - }, - "qa-de-2": { - "total": 48, - "warning": { - "total": 4 - }, - "info": { - "total": 44 - } - }, - "qa-de-6": { - "total": 58, - "warning": { - "total": 12 - }, - "info": { - "total": 46, - "suppressed": 10 - } - }, - "ap-sa-2": { - "total": 115, - "warning": { - "total": 22 - }, - "info": { - "total": 93, - "suppressed": 1 - } - }, - "ap-ae-1": { - "total": 124, - "warning": { - "total": 10, - "suppressed": 6 - }, - "info": { - "total": 111, - "suppressed": 1 - }, - "none": { - "total": 3 - } - }, - "na-us-3": { - "total": 144, - "warning": { - "total": 1 - }, - "info": { - "total": 143, - "suppressed": 1 - } - }, - "ap-jp-1": { - "total": 133, - "warning": { - "total": 11, - "suppressed": 6 - }, - "info": { - "total": 119, - "suppressed": 1 - }, - "none": { - "total": 3 - } - }, - "la-br-1": { - "total": 85, - "warning": { - "total": 1 - }, - "info": { - "total": 84, - "suppressed": 1 - } - }, - "na-ca-1": { - "total": 94, - "warning": { - "total": 1, - "suppressed": 1 - }, - "info": { - "total": 93, - "suppressed": 1 - } - }, - "ap-jp-2": { - "total": 93, - "warning": { - "total": 6, - "suppressed": 6 - }, - "info": { - "total": 84, - "suppressed": 1 - }, - "none": { - "total": 3 - } - } - } - } -} - * - */ diff --git a/apps_deprecated/supernova/src/lib/createAuthDataSlice.js b/apps_deprecated/supernova/src/lib/createAuthDataSlice.js deleted file mode 100644 index e4b347e38..000000000 --- a/apps_deprecated/supernova/src/lib/createAuthDataSlice.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const AUTH_ACTIONS = { - SIGN_ON: "signOn", - SIGN_OUT: "signOut", -} - -const createAuthDataSlice = (set, get) => ({ - auth: { - data: null, - isProcessing: false, - loggedIn: false, - error: null, - lastAction: {}, - appLoaded: false, - appIsLoading: false, - - actions: { - setAppLoaded: (appLoaded) => { - set( - (state) => ({ auth: { ...state.auth, appLoaded } }), - false, - "auth/setAppLoaded" - ) - }, - setData: (data) => { - if (!data) return - // check if data has changed before updating the state - if ( - data?.isProcessing === get().auth.isProcessing && - data?.loggedIn === get().auth.loggedIn && - data?.error === get().auth.error && - data?.auth === get().auth.data - ) - return - - set( - (state) => ({ - auth: { - ...state.auth, - isProcessing: data?.isProcessing, - loggedIn: data?.loggedIn, - error: data?.error, - data: data?.auth, - }, - }), - false, - "auth/setData" - ) - }, - setAction: (name) => - set( - (state) => ({ - auth: { - ...state.auth, - lastAction: { name: name, updatedAt: Date.now() }, - }, - }), - false, - "auth/setAction" - ), - login: () => get().auth.actions.setAction(AUTH_ACTIONS.SIGN_ON), - logout: () => get().auth.actions.setAction(AUTH_ACTIONS.SIGN_OUT), - }, - }, -}) - -export default createAuthDataSlice diff --git a/apps_deprecated/supernova/src/lib/createFiltersSlice.js b/apps_deprecated/supernova/src/lib/createFiltersSlice.js deleted file mode 100644 index 1b4822fab..000000000 --- a/apps_deprecated/supernova/src/lib/createFiltersSlice.js +++ /dev/null @@ -1,255 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import produce from "immer" - -const initialFiltersState = { - labels: ["status"], // labels to be used for filtering: [ "label1", "label2", "label3"]. Default is status which is enriched by the worker - activeFilters: {}, // for each active filter key list the selected values: {key1: [value1], key2: [value2_1, value2_2], ...} - filterLabelValues: {}, // contains all possible values for filter labels: {label1: ["val1", "val2", "val3", ...], label2: [...]}, lazy loaded when a label is selected for filtering - predefinedFilters: [], // predefined complex filters that filter using regex: [{name: "filter1", displayName: "Filter 1", matchers: {"label1": "regex1", "label2": "regex2", ...}}, ...] - activePredefinedFilter: null, // the currently active predefined filter - searchTerm: "", // the search term used for full-text filtering -} - -const createFiltersSlice = (set, get) => ({ - filters: { - ...initialFiltersState, - actions: { - setLabels: (labels) => - set( - (state) => { - if (!labels) return state - - // check if labels is an array - if (!Array.isArray(labels)) { - console.warn( - "[supernova]::setLabels: labels object is not an array" - ) - return state - } - - // check if all elements in the array are strings delete the ones that are not - if (!labels.every((element) => typeof element === "string")) { - console.warn( - "[supernova]::setLabels: Some elements of the array are not strings." - ) - labels = labels.filter((element) => typeof element === "string") - } - - // merge given labels with the initial, make it unique and sort it alphabetically - const uniqueLabels = Array.from( - new Set(initialFiltersState.labels.concat(labels)) - ).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())) - - return { - filters: { - ...state.filters, - labels: uniqueLabels, - }, - } - }, - false, - "filters.setLabels" - ), - - setActiveFilters: (activeFilters) => { - set( - (state) => { - return { - filters: { - ...state.filters, - activeFilters, - }, - } - }, - false, - "filters.setActiveFilters" - ) - get().alerts.actions.filterItems() - }, - - clearActiveFilters: () => { - set( - produce((state) => { - state.filters.activeFilters = {} - }), - false, - "filters.clearActiveFilters" - ) - get().alerts.actions.filterItems() - }, - - addActiveFilter: (filterLabel, filterValue) => { - set( - produce((state) => { - // use Set to prevent duplicate values - state.filters.activeFilters[filterLabel] = [ - ...new Set([ - ...(state.filters.activeFilters[filterLabel] || []), - filterValue, - ]), - ] - }), - false, - "filters.addActiveFilter" - ) - // after adding a new filter key and value: filter items - get().alerts.actions.filterItems() - }, - - // add multiple values for a filter label - addActiveFilters: (filterLabel, filterValues) => { - set( - produce((state) => { - // use Set to prevent duplicate values - state.filters.activeFilters[filterLabel] = [ - ...new Set([ - ...(state.filters.activeFilters[filterLabel] || []), - ...filterValues, - ]), - ] - }), - false, - "filters.addActiveFilters" - ) - // after adding a new filter key and value: filter items - get().alerts.actions.filterItems() - }, - - removeActiveFilter: (filterLabel, filterValue) => { - set( - produce((state) => { - state.filters.activeFilters[filterLabel] = - state.filters.activeFilters[filterLabel].filter( - (value) => value !== filterValue - ) - // if this was the last selected value delete the whole label key - if (state.filters.activeFilters[filterLabel].length === 0) { - delete state.filters.activeFilters[filterLabel] - } - }), - false, - "filters.removeActiveFilter" - ) - // after removing a filter: filter items - get().alerts.actions.filterItems() - }, - - setPredefinedFilters: (predefinedFilters) => { - set( - produce((state) => { - state.filters.predefinedFilters = predefinedFilters - }), - false, - "filters.setPredefinedFilters" - ) - }, - - setActivePredefinedFilter: (filterName) => { - set( - produce((state) => { - state.filters.activePredefinedFilter = filterName - }), - false, - "filters.setActivePredefinedFilter" - ) - // after activating predefined filter: filter items - get().alerts.actions.filterItems() - }, - - clearActivePredefinedFilter: () => { - set( - produce((state) => { - state.filters.activePredefinedFilter = null - }), - false, - "filters.clearActivePredefinedFilter" - ) - // after clearing predefined filter: filter items - get().alerts.actions.filterItems() - }, - - togglePredefinedFilter: (filterName) => { - set( - produce((state) => { - // if active predefined filter is already set and equal to the one that was clicked, clear it - if (state.filters.activePredefinedFilter === filterName) { - state.filters.activePredefinedFilter = null - } else { - state.filters.activePredefinedFilter = filterName - } // otherwise set the clicked filter as active - }), - false, - "filters.togglePredefinedFilter" - ) - // after activating predefined filter: filter items - get().alerts.actions.filterItems() - }, - - // retieve all possible values for the given filter label from the list of items and add them to the list - loadFilterLabelValues: (filterLabel) => { - set( - produce((state) => { - state.filters.filterLabelValues[filterLabel] = { isLoading: true } - }), - false, - "filters.loadFilterLabelValues.isLoading" - ) - set( - produce((state) => { - // use Set to ensure unique values - const values = [ - ...new Set( - state.alerts.items.map((item) => item.labels[filterLabel]) - ), - ] - // remove any "blank" values from the list, then sort - state.filters.filterLabelValues[filterLabel].values = values - .filter((value) => (value ? true : false)) - .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())) - - state.filters.filterLabelValues[filterLabel].isLoading = false - }), - false, - "filters.loadFilterLabelValues" - ) - }, - - // for each filter label where we already loaded the values, reload them - reloadFilterLabelValues: () => { - Object.keys(get().filters.filterLabelValues).map((label) => { - get().filters.actions.loadFilterLabelValues(label) - }) - }, - - setSearchTerm: (searchTerm) => { - set( - produce((state) => { - state.filters.searchTerm = searchTerm - }), - false, - "filters.setSearchTerm" - ) - // after setting the search term: filter items - get().alerts.actions.filterItems() - }, - - // TODO: - // update previously loaded filter label values (e.g. after new items were fetched, the possible values might have changed) - // updateFilterLabelValues: () => { - // set( - // produce((state) => { - // Object.keys(state.filters.filterLabelValues).map((label) => - - // ) - // }) - // ) - // } - }, - }, -}) - -export default createFiltersSlice diff --git a/apps_deprecated/supernova/src/lib/createFiltersSlice.test.js b/apps_deprecated/supernova/src/lib/createFiltersSlice.test.js deleted file mode 100644 index dede36679..000000000 --- a/apps_deprecated/supernova/src/lib/createFiltersSlice.test.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { renderHook, act } from "@testing-library/react" -import { - useFilterLabels, - useFilterActions, - useSearchTerm, - StoreProvider, -} from "../hooks/useAppStore" - -const originalConsoleError = global.console.warn - -describe("createFiltersSlice", () => { - describe("setLabels", () => { - it("return default status label", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - filterLabels: useFilterLabels(), - }), - { wrapper } - ) - expect(store.result.current.filterLabels).toEqual(["status"]) - }) - - it("Adds array with strings to select", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - filterLabels: useFilterLabels(), - }), - { wrapper } - ) - - act(() => { - store.result.current.actions.setLabels([ - "app", - "cluster", - "cluster_type", - "context", - "job", - "region", - "service", - "severity", - "support_group", - "tier", - "type", - ]) - }) - - expect(store.result.current.filterLabels).toEqual( - expect.arrayContaining([ - "app", - "status", - "cluster", - "cluster_type", - "context", - "job", - "region", - "service", - "severity", - "support_group", - "tier", - "type", - ]) - ) - }) - - it("Adds empty array to select", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - filterLabels: useFilterLabels(), - }), - { wrapper } - ) - - act(() => { - store.result.current.actions.setLabels([]) - }) - - expect(store.result.current.filterLabels).toEqual( - expect.arrayContaining(["status"]) - ) - }) - - it("warns the user if labels are not an array", () => { - const spy = jest.spyOn(console, "warn").mockImplementation(() => {}) - - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - filterLabels: useFilterLabels(), - }), - { wrapper } - ) - - act(() => - store.result.current.actions.setLabels( - "app,cluster,cluster_type,context,job,region,service,severity,status,support_group,tier,type" - ) - ) - - expect(spy).toHaveBeenCalledTimes(1) - expect(spy).toHaveBeenCalledWith( - "[supernova]::setLabels: labels object is not an array" - ) - spy.mockRestore() - }) - - it("warns the user if labels array also includes non-strings and adds the valid labels", () => { - const spy = jest.spyOn(console, "warn").mockImplementation(() => {}) - - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - filterLabels: useFilterLabels(), - }), - { wrapper } - ) - - act(() => store.result.current.actions.setLabels(["app", 1, 9])) - - // Is the warning called? - expect(spy).toHaveBeenCalledTimes(1) - expect(spy).toHaveBeenCalledWith( - "[supernova]::setLabels: Some elements of the array are not strings." - ) - spy.mockRestore() - - // Are valid labels still set? - expect(store.result.current.filterLabels).toEqual( - expect.arrayContaining(["app", "status"]) - ) - }) - }) - - describe("setSearchTerm", () => { - it("empty search term", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - searchTerm: useSearchTerm(), - }), - { wrapper } - ) - - expect(store.result.current.searchTerm).toEqual("") - }) - - it("Set a search term", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - actions: useFilterActions(), - searchTerm: useSearchTerm(), - }), - { wrapper } - ) - - act(() => { - store.result.current.actions.setSearchTerm("k8s") - }) - - expect(store.result.current.searchTerm).toEqual("k8s") - }) - }) -}) diff --git a/apps_deprecated/supernova/src/lib/createGlobalsSlice.js b/apps_deprecated/supernova/src/lib/createGlobalsSlice.js deleted file mode 100644 index f6a5cf667..000000000 --- a/apps_deprecated/supernova/src/lib/createGlobalsSlice.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import produce from "immer" - -const createGlobalsSlice = (set, get) => ({ - globals: { - embedded: false, - showDetailsFor: null, - apiEndpoint: null, - - actions: { - setEmbedded: (embedded) => - set( - (state) => ({ globals: { ...state.globals, embedded: embedded } }), - false, - "globals/setEmbedded" - ), - setShowDetailsFor: (alertID) => - set( - (state) => ({ - // if the alertID is the same as the current one, we want to close the details panel again, - // otherwise set the new alertID to replace the details in the panel - globals: { - ...state.globals, - showDetailsFor: - get().globals.showDetailsFor === alertID ? null : alertID, - }, - }), - false, - "globals/setShowDetailsFor" - ), - setApiEndpoint: (endpoint) => - set( - (state) => ({ - globals: { ...state.globals, apiEndpoint: endpoint }, - }), - false, - "globals/setShowDetailsFor" - ), - }, - }, -}) - -export default createGlobalsSlice diff --git a/apps_deprecated/supernova/src/lib/createSilencesSlice.js b/apps_deprecated/supernova/src/lib/createSilencesSlice.js deleted file mode 100644 index e4ebe603f..000000000 --- a/apps_deprecated/supernova/src/lib/createSilencesSlice.js +++ /dev/null @@ -1,334 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import produce from "immer" - -const initialSilencesState = { - items: [], - itemsHash: {}, - itemsByState: {}, - excludedLabels: [], - isLoading: false, - isUpdating: false, - updatedAt: null, - error: null, - localItems: {}, - - // silence templates for maintanance - templates: [], -} - -const validateTemplates = (templates) => { - // check if the templates are an array - if (!Array.isArray(templates)) { - console.warn( - "[supernova]::validateTemplates: templates object is not an array" - ) - return [ - { - id: "1", - title: "Invalid template object", - invalid: "Templates object is not an array", - }, - ] - } - - // check if every element in the array is an object - if (!templates.every((element) => typeof element === "object")) { - console.warn( - "[supernova]::validateTemplates: templates object is not an array of objects" - ) - return [ - { - id: "1", - title: "Invalid template object", - invalid: "Templates object is not an array of objects", - }, - ] - } - - // check if every object - return templates - ?.map((template, index) => { - // check if status is active - if (template?.status === "active") { - // check if title and discription is a string, fixed_labels is an object and editable_labels is an array of strings - if ( - typeof template?.title !== "string" || - typeof template?.description !== "string" || - typeof template?.fixed_labels !== "object" || - !Array.isArray(template?.editable_labels) || - !template?.editable_labels.every( - (element) => typeof element === "string" - ) - ) { - let brokenElement = "Following elements are not well formed: " - - ;(brokenElement += - typeof template?.title !== "string" ? "title " : ""), - (brokenElement += - typeof template?.description !== "string" ? "description " : ""), - (brokenElement += - typeof template?.fixed_labels !== "object" - ? "fixed_labels " - : ""), - (brokenElement += !Array.isArray(template?.editable_labels) - ? "editable_labels " - : "") - return { - id: "elem" + index, - title: - typeof template?.title === "string" - ? template?.title - : "Invalid template", - invalid: brokenElement, - } - } - // if all ok, return the template - return { - id: "elem" + index, - title: template?.title, - description: template?.description, - fixed_labels: template?.fixed_labels || {}, - editable_labels: template?.editable_labels || [], - invalid: false, - } - } - // if status is not active, return null to filter it out - return null - }) - .filter((template) => template !== null) -} - -const createSilencesSlice = (set, get, options) => ({ - silences: { - ...initialSilencesState, - - // silence templates for maintanance - templates: options?.silenceTemplates - ? validateTemplates(options?.silenceTemplates) - : [], - actions: { - setSilences: ({ items, itemsHash, itemsByState }) => { - if (!items) return - - set( - produce((state) => { - state.silences.items = items - state.silences.itemsHash = itemsHash - state.silences.itemsByState = itemsByState - state.silences.isLoading = false - state.silences.isUpdating = false - state.silences.updatedAt = Date.now() - state.silences.error = null - }), - false, - "silences.setSilencesData" - ) - - // check if any local item can be removed - get().silences.actions.updateLocalItems() - }, - /* - Save temporary created silences to be able to display which alert is silenced - and who silenced it until the next alert fetch contains the silencedBy reference - */ - addLocalItem: ({ silence, id, alertFingerprint }) => { - // enforce silences with id and alertFingerprint - if (!silence || !id || !alertFingerprint) return - return set( - produce((state) => { - state.silences.localItems = { - ...get().silences.localItems, - [id]: { - ...silence, - id, - alertFingerprint, - type: "local", - }, - } - }), - false, - "silences.addLocalItem" - ) - }, - /* - Remove local silences which are already referenced by an alert - */ - updateLocalItems: () => { - const allSilences = get().silences.itemsHash - let newLocalSilences = { ...get().silences.localItems } - Object.keys(newLocalSilences).forEach((key) => { - const alert = get().alerts.actions.getAlertByFingerprint( - newLocalSilences[key]?.alertFingerprint - ) - - // check if the alert has already the silence reference and if the extern silence already exists - const silencedBy = alert?.status?.silencedBy - if ( - silencedBy?.length > 0 && - silencedBy?.includes(newLocalSilences[key]?.id) && - allSilences[key] - ) { - // mark to remove silence - newLocalSilences[key] = { ...newLocalSilences[key], remove: true } - } - }) - - // remove silences marked to remove - const reducedLocalSilences = Object.keys(newLocalSilences) - .filter((key) => !newLocalSilences[key]?.remove) - .reduce((obj, key) => { - obj[key] = newLocalSilences[key] - return obj - }, {}) - - return set( - produce((state) => { - state.silences.localItems = reducedLocalSilences - }), - false, - "silences.updateLocalItems" - ) - }, - /* - Given an alert fingerprint, this function returns all silences referenced by silencingBy. It also - check if there are local silences with the same alert fingerprint and return them as well. - */ - getMappingSilences: (alert) => { - if (!alert) return - const externalSilences = get().silences.itemsHash - let silencedBy = alert?.status?.silencedBy || [] - - // ensure silencedBy is an array - if (!Array.isArray(silencedBy)) silencedBy = [silencedBy] - let mappingSilences = [] - silencedBy.forEach((id) => { - if (externalSilences[id]) { - mappingSilences.push(externalSilences[id]) - } - }) - - // add local silences - let localSilences = get().silences.localItems - Object.keys(localSilences).forEach((silenceID) => { - // if there is already a silence with the same id, skip it and exists as external silence - if (silencedBy.includes(silenceID) && externalSilences[silenceID]) - return - // if the local silence has the same alert fingerprint, add it to the mapping silences - if ( - localSilences[silenceID]?.alertFingerprint === alert?.fingerprint - ) { - mappingSilences.push(localSilences[silenceID]) - } - }) - return mappingSilences - }, - /* - Return the state of an alert. If the alert is silenced by a local silence, the state is suppressed (processing) - */ - getMappedState: (alert) => { - if (!alert) return - // get all silences (local and external) - const silences = get().silences.actions.getMappingSilences(alert) - // if there is a silence with type local, return suppressed (processing) - if (silences?.find((silence) => silence?.type === "local")) { - return { type: "suppressed", isProcessing: true } - } - return { type: alert?.status?.state, isProcessing: false } - }, - setExcludedLabels: (labels) => { - return set( - (state) => { - // check if labels is an array and if every element in the array is a string - if ( - !Array.isArray(labels) || - !labels.some((element) => typeof element === "string") - ) { - console.warn( - "[supernova]::setExcludedLabels: labels object is not an array of strings" - ) - return state - } - - return { - silences: { - ...state.silences, - excludedLabels: labels, - }, - } - }, - false, - "silences.setExcludedLabels" - ) - }, - /* - Find all silences in itemsByState with key expired that matches all labels (key&value) from the alert but omit the labels that are excluded (excludedLabels) - */ - getExpiredSilences: (alert) => { - if (!alert) return - const alertLabels = alert?.labels || {} - const silences = get().silences.itemsByState?.expired || [] - const excludedLabels = get().silences.excludedLabels || [] - const enrichedLabels = get().alerts.enrichedLabels || [] - // combine the arrays containing the labels that shouldn't be used for matching into one for easier checking - const labelsExcludedForMatching = [...excludedLabels, ...enrichedLabels] - - // find all expired silences that matches all labels from the alert excluding the excluded excludedLabels - return silences.filter((silence) => { - const silenceMatchers = silence?.matchers || [] - // check if all labels from the alert are included in the silence - return Object.keys(alertLabels).every((label) => { - // check if the label is excluded - if (labelsExcludedForMatching.includes(label)) return true - // check if the label is included in the silence - return silenceMatchers.some( - (silenceLabel) => - silenceLabel?.name === label && - silenceLabel?.value === alertLabels?.[label] - ) - }) - }) - }, - /* - Returns the silence (including the local ones) with the latest expiration time for an alert. Useful to display when the alert will be active again. - */ - getLatestMappingSilence: (alert) => { - if (!alert) return - const silences = get().silences.actions.getMappingSilences(alert) - if (!silences?.length) return - // return the latest expired silence - return silences.reduce((prev, current) => - prev.endsAt > current.endsAt ? prev : current - ) - }, - setIsLoading: (value) => - set( - (state) => ({ silences: { ...state.silences, isLoading: value } }), - false, - "silences.setIsLoading" - ), - setIsUpdating: (value) => - set( - (state) => ({ - silences: { ...state.silences, isUpdating: value }, - }), - false, - "silences.setIsUpdating" - ), - setError: (error) => { - set( - (state) => ({ - silences: { ...state.silences, error, isLoading: false }, - }), - false, - "silences.setError" - ) - }, - }, - }, -}) - -export default createSilencesSlice diff --git a/apps_deprecated/supernova/src/lib/createSilencesSlice.test.js b/apps_deprecated/supernova/src/lib/createSilencesSlice.test.js deleted file mode 100644 index cea24fca9..000000000 --- a/apps_deprecated/supernova/src/lib/createSilencesSlice.test.js +++ /dev/null @@ -1,778 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { renderHook, act } from "@testing-library/react" -import { - useSilencesActions, - useSilencesLocalItems, - useAlertsActions, - useAlertsItems, - useSilencesExcludedLabels, - StoreProvider, -} from "../hooks/useAppStore" -import { - createFakeAlertStatustWith, - createFakeAlertWith, - createFakeSilenceWith, -} from "./fakeObjects" -import { countAlerts } from "../lib/utils" - -describe("addLocalItem", () => { - it("should append the object with key silence id and value the silence itself", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - actions: useSilencesActions(), - localSilences: useSilencesLocalItems(), - }), - { wrapper } - ) - - const silence = createFakeSilenceWith() - act(() => - store.result.current.actions.addLocalItem({ - silence, - id: "test", - alertFingerprint: "123", - }) - ) - - expect(Object.keys(store.result.current.localSilences).length).toEqual(1) - expect(store.result.current.localSilences["test"]["id"]).toEqual("test") - expect( - store.result.current.localSilences["test"]["alertFingerprint"] - ).toEqual("123") - }) - it("should avoid to add any silences without id or alertFingerprint", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - actions: useSilencesActions(), - localSilences: useSilencesLocalItems(), - }), - { wrapper } - ) - - const silence = createFakeSilenceWith() - act(() => store.result.current.actions.addLocalItem({ silence, id: "" })) - act(() => store.result.current.actions.addLocalItem({ silence, id: null })) - act(() => - store.result.current.actions.addLocalItem({ - silence, - id: "test", - alertFingerprint: "", - }) - ) - act(() => - store.result.current.actions.addLocalItem({ - silence, - id: "test", - alertFingerprint: null, - }) - ) - expect(Object.keys(store.result.current.localSilences).length).toEqual(0) - }) -}) - -describe("getMappingSilences", () => { - it("return all external silences referenced by silencedBy and all local silences with the same fingerprint which are not yet included", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create extern silences adding an id to the object - const silence = createFakeSilenceWith({ id: "external" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence], - itemsHash: { external: silence }, - itemsByState: { active: [silence] }, - }) - ) - // create local silence adding per attribute the id and the alert fingerprint - const silence2 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence2, - id: "local", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappingSilences(alert)) - ) - expect(mappingResult.length).toEqual(2) - expect(mappingResult.map((item) => item.id)).toContainEqual("external") - expect(mappingResult.map((item) => item.id)).toContainEqual("local") - expect(mappingResult.find((item) => item.id === "local").type).toEqual( - "local" - ) - }) - - it("return silences also when alert silencedBy is just a string", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert - const status = createFakeAlertStatustWith({ silencedBy: "external" }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create local silence - const silence = createFakeSilenceWith({ id: "external" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence], - itemsHash: { external: silence }, - itemsByState: { active: [silence] }, - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappingSilences(alert)) - ) - expect(mappingResult.length).toEqual(1) - expect(mappingResult.map((item) => item.id)).toContainEqual("external") - }) - - it("ignores 'local silences' which are already included in silencedBy and exist as external silence", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external", "externalAndLocal"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create external silences adding an id to the object - const silence = createFakeSilenceWith({ id: "external" }) - const silence2 = createFakeSilenceWith({ id: "externalAndLocal" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence, silence2], - itemsHash: { external: silence, externalAndLocal: silence2 }, - itemsByState: { active: [silence, silence2] }, - }) - ) - // create local silence which already exists as external silence - const silence3 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence3, - id: "externalAndLocal", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappingSilences(alert)) - ) - expect(mappingResult.length).toEqual(2) - // checking type to be undefined means that the silence is not local - expect(mappingResult[0].type).toEqual(undefined) - expect(mappingResult[1].type).toEqual(undefined) - }) - - it("returns local silences when the id exists in silencedBy but it does not exist as external silence", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external", "local"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create external silences adding an id to the object - const silence = createFakeSilenceWith({ id: "external" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence], - itemsHash: { external: silence }, - itemsByState: { active: [silence] }, - }) - ) - // create local silence which already exists as external silence - const silence2 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence2, - id: "local", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappingSilences(alert)) - ) - expect(mappingResult.length).toEqual(2) - // checking type to be undefined means that the silence is not local - expect(mappingResult[0].type).toEqual(undefined) - expect(mappingResult[1].type).toEqual("local") - }) -}) - -describe("updateLocalItems", () => { - it("removes local silences whose alert reference (defined by alertFingerprint) has in silencedBy the silence itself and a silence with same id exist also as external silences", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - savedLocalSilences: useSilencesLocalItems(), - savedAlerts: useAlertsItems(), - }), - { wrapper } - ) - - // create local silences - const silence = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence, - id: "test1local", - alertFingerprint: "12345", - }) - ) - const silence2 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence2, - id: "test2local", - alertFingerprint: "non_existing_alert", - }) - ) - // check if the local silence are saved - expect(Object.keys(store.result.current.savedLocalSilences).length).toEqual( - 2 - ) - // create an alert without any silencedBy so we just have the local silences - const status = createFakeAlertStatustWith({ - silencedBy: ["test1local"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "12345" }) - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // check if the alert is saved - expect(store.result.current.savedAlerts.length).toEqual(1) - // trigger update local items by setting new external silences - const externalSilence = createFakeSilenceWith({ id: "test1local" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [externalSilence], - itemsHash: { [externalSilence.id]: externalSilence }, - itemsByState: { active: [externalSilence] }, - }) - ) - // check local items - expect(Object.keys(store.result.current.savedLocalSilences).length).toEqual( - 1 - ) - expect(store.result.current.savedLocalSilences["test2local"].id).toEqual( - "test2local" - ) - }) - - it("keeps local silences if silence with same id does not exist yet in external silences", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - savedLocalSilences: useSilencesLocalItems(), - savedAlerts: useAlertsItems(), - }), - { wrapper } - ) - - // create local silences - const silence = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence, - id: "test1local", - alertFingerprint: "12345", - }) - ) - const silence2 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence2, - id: "test2local", - alertFingerprint: "non_existing_alert", - }) - ) - // check if the local silence are saved - expect(Object.keys(store.result.current.savedLocalSilences).length).toEqual( - 2 - ) - // create an alert without any silencedBy so we just have the local silences - const status = createFakeAlertStatustWith({ - silencedBy: ["test1local"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "12345" }) - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // check if the alert is saved - expect(store.result.current.savedAlerts.length).toEqual(1) - // trigger update local items by setting new external silences - const externalSilence = createFakeSilenceWith({ - id: "different_id_then_test1local", - }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [externalSilence], - itemsHash: { [externalSilence.id]: externalSilence }, - itemsByState: { active: [externalSilence] }, - }) - ) - // check local items - expect(Object.keys(store.result.current.savedLocalSilences).length).toEqual( - 2 - ) - expect(store.result.current.savedLocalSilences["test1local"].id).toEqual( - "test1local" - ) - expect(store.result.current.savedLocalSilences["test2local"].id).toEqual( - "test2local" - ) - }) -}) - -describe("getMappedState", () => { - it("retuns supressed (processing) if a local silence is found", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create extern silences adding an id to the object - const silence = createFakeSilenceWith({ id: "external" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence], - itemsHash: { external: silence }, - itemsByState: { active: [silence] }, - }) - ) - // create local silence adding per attribute the id and the alert fingerprint - const silence2 = createFakeSilenceWith() - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence2, - id: "local", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappedState(alert)) - ) - expect(mappingResult["type"]).toEqual("suppressed") - expect(mappingResult["isProcessing"]).toEqual(true) - }) - - it("retuns just the alert.status.state if no local silences found", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create extern silences adding an id to the object - const silence = createFakeSilenceWith({ id: "external" }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence], - itemsHash: { external: silence }, - itemsByState: { active: [silence] }, - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getMappedState(alert)) - ) - expect(mappingResult["type"]).toEqual(alert?.status?.state) - expect(mappingResult["isProcessing"]).toEqual(false) - }) -}) - -describe("getExpiredSilences", () => { - it("returns all silences which are expired matching the alert labels but omitting the excludeLabels", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // set the excluded labels - act(() => store.result.current.silenceActions.setExcludedLabels(["pod"])) - // create an alert with custom status - const alert = createFakeAlertWith({ - fingerprint: "123", - labels: { - severity: "critical", - support_group: "containers", - service: "automation", - pod: "test", - }, - }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create external silences with different labels (service compute) - const silence = createFakeSilenceWith({ - id: "test1", - status: { - state: "expired", - }, - matchers: [ - { name: "severity", value: "critical", isRegex: false }, - { name: "support_group", value: "compute", isRegex: false }, - { name: "service", value: "compute", isRegex: false }, - ], - }) - // create an external silences with matching labels - const silence2 = createFakeSilenceWith({ - id: "test2", - status: { - state: "expired", - }, - matchers: [ - { name: "severity", value: "critical", isRegex: false }, - { name: "support_group", value: "containers", isRegex: false }, - { name: "service", value: "automation", isRegex: false }, - ], - }) - // create an external silences with less labels but matching - const silence3 = createFakeSilenceWith({ - id: "test3", - status: { - state: "expired", - }, - matchers: [ - { name: "severity", value: "info", isRegex: false }, - { name: "support_group", value: "containers", isRegex: false }, - ], - }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence, silence2, silence3], - itemsHash: { test1: silence, test2: silence2, test3: silence3 }, - itemsByState: { expired: [silence, silence2, silence3] }, - }) - ) - // get mapping silences - let expResult = null - act( - () => - (expResult = - store.result.current.silenceActions.getExpiredSilences(alert)) - ) - expect(expResult.length).toEqual(1) - expect(expResult[0].id).toEqual("test2") - }) -}) - -describe("getLatestMappingSilence", () => { - it("returns the silence with the latest endsAt timestamp when local", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create extern silences adding an id to the object - const silence = createFakeSilenceWith({ - id: "external", - endsAt: "2023-06-21T15:17:28.327Z", - }) - const silence2 = createFakeSilenceWith({ - id: "external2", - endsAt: "2023-06-21T16:18:28.327Z", - }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence, silence2], - itemsHash: { external: silence, external2: silence2 }, - itemsByState: { active: [silence, silence2] }, - }) - ) - // create local silence adding per attribute the id and the alert fingerprint - const silence3 = createFakeSilenceWith({ - endsAt: "2023-06-21T19:17:28.327Z", - }) - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence3, - id: "local", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getLatestMappingSilence(alert)) - ) - expect(mappingResult.id).toEqual("local") - }) - - it("returns the silence with the latest endsAt timestamp when external", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - alertActions: useAlertsActions(), - silenceActions: useSilencesActions(), - }), - { wrapper } - ) - - // create an alert with custom status - const status = createFakeAlertStatustWith({ - silencedBy: ["external", "external2"], - }) - const alert = createFakeAlertWith({ status: status, fingerprint: "123" }) - // set the alert - act(() => - store.result.current.alertActions.setAlertsData({ - items: [alert], - counts: countAlerts([alert]), - }) - ) - // create extern silences adding an id to the object - const silence = createFakeSilenceWith({ - id: "external", - endsAt: "2023-06-21T15:17:28.327Z", - }) - const silence2 = createFakeSilenceWith({ - id: "external2", - endsAt: "2023-06-21T20:18:28.327Z", - }) - act(() => - store.result.current.silenceActions.setSilences({ - items: [silence, silence2], - itemsHash: { external: silence, external2: silence2 }, - itemsByState: { active: [silence, silence2] }, - }) - ) - // create local silence adding per attribute the id and the alert fingerprint - const silence3 = createFakeSilenceWith({ - endsAt: "2023-06-21T19:17:28.327Z", - }) - act(() => - store.result.current.silenceActions.addLocalItem({ - silence: silence3, - id: "local", - alertFingerprint: "123", - }) - ) - // get mapping silences - let mappingResult = null - act( - () => - (mappingResult = - store.result.current.silenceActions.getLatestMappingSilence(alert)) - ) - expect(mappingResult.id).toEqual("external2") - }) -}) - -describe("setExcludedLabels", () => { - it("return empty array as default", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - actions: useSilencesActions(), - excludedLabels: useSilencesExcludedLabels(), - }), - { wrapper } - ) - expect(store.result.current.excludedLabels).toEqual([]) - }) - - it("accepts array of strings containing the labels to use", () => { - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - actions: useSilencesActions(), - excludedLabels: useSilencesExcludedLabels(), - }), - { wrapper } - ) - - act(() => { - store.result.current.actions.setExcludedLabels([ - "pod", - "pod_name", - "instance", - ]) - }) - - expect(store.result.current.excludedLabels).toEqual([ - "pod", - "pod_name", - "instance", - ]) - }) - - it("warn the user if labels are different then an array of strings", () => { - const spy = jest.spyOn(console, "warn").mockImplementation(() => {}) - - const wrapper = ({ children }) => {children} - const store = renderHook( - () => ({ - actions: useSilencesActions(), - excludedLabels: useSilencesExcludedLabels(), - }), - { wrapper } - ) - - act(() => - store.result.current.actions.setExcludedLabels("pod,pod_name,instance") - ) - - expect(spy).toHaveBeenCalledTimes(1) - expect(spy).toHaveBeenCalledWith( - "[supernova]::setExcludedLabels: labels object is not an array of strings" - ) - spy.mockRestore() - }) -}) diff --git a/apps_deprecated/supernova/src/lib/createUserActivitySlice.js b/apps_deprecated/supernova/src/lib/createUserActivitySlice.js deleted file mode 100644 index 903996ac7..000000000 --- a/apps_deprecated/supernova/src/lib/createUserActivitySlice.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import produce from "immer" - -const createUserActivitySlice = (set, get) => ({ - userActivity: { - isActive: true, - - actions: { - setIsActive: (activity) => { - set( - (state) => ({ - userActivity: { ...state.userActivity, isActive: activity }, - }), - false, - "userActivity.setIsActive" - ) - }, - }, - }, -}) - -export default createUserActivitySlice diff --git a/apps_deprecated/supernova/src/lib/fakeObjects.js b/apps_deprecated/supernova/src/lib/fakeObjects.js deleted file mode 100644 index b8030d1d0..000000000 --- a/apps_deprecated/supernova/src/lib/fakeObjects.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const refAlert = { - annotations: { - description: - "vSphere High Availability (HA) has detected a possible host failure for `node014-bb164.cc.na-us-1.cloud.sap`. (vc-a-0.cc.na-us-1.cloud.sap).", - summary: - "vSphere High Availability (HA) has detected a possible host failure for `node014-bb164.cc.na-us-1.cloud.sap`. (vc-a-0.cc.na-us-1.cloud.sap).", - }, - endsAt: "2023-06-21T13:04:01.855Z", - fingerprint: "62cab9a4fd5732ee", - receivers: [ - { name: "elastic" }, - { name: "awx" }, - { name: "pagerduty_compute" }, - { name: "octobus" }, - { name: "support_group_alerts_critical_compute" }, - { name: "pagerduty_vmware" }, - { name: "slack_vmware_critical" }, - ], - startsAt: "2023-06-21T12:13:31.855Z", - status: { - inhibitedBy: [], - silencedBy: [], - state: "active", - }, - updatedAt: "2023-06-21T13:00:01.969Z", - generatorURL: - "https://prometheus-vmware-vc-a-0.na-us-1.cloud.sap/graph?g0.expr=vrops_hostsystem_alert_info%7Balert_name%3D%22vSphere+High+Availability+%28HA%29+has+detected+a+possible+host+failure%22%7D+and+on+%28hostsystem%29+vrops_hostsystem_runtime_maintenancestate%7Bstate%21~%22inMaintenance%22%2Cvccluster%21~%22.%2Acontrolplane-swift%22%7D&g0.tab=1", - labels: { - alert_impact: "HEALTH", - alert_level: "CRITICAL", - alert_name: - "vSphere High Availability (HA) has detected a possible host failure", - alertname: "HADetectedAPossibleHostFailure", - cluster: "s-na-us-1", - cluster_type: "scaleout", - collector: "vrops-vc-a-0-host", - context: "node014-bb164.cc.na-us-1.cloud.sap failure", - datacenter: "na-us-1a", - description: - "A vSphere HA master agent considers a host to have failed if it loses contact with the vSphere HA agent on the host, the host does not respond to pings on any of the management interfaces, and the master does not observe any datastore heartbeats. This problem can occur when a computer on the network is configured to have the same IP address as one of the ESX/ESXi hosts in a HA cluster. In this situation, the HA agent receives invalid data and generates errors. The HA agent does not function properly until it is reconfigured. The frequency of this problem depends on how often the IP address conflict occurs.", - hostsystem: "node014-bb164.cc.na-us-1.cloud.sap", - job: "vrops-exporter", - meta: "vSphere High Availability (HA) has detected a possible host failure for `node014-bb164.cc.na-us-1.cloud.sap`. (vc-a-0.cc.na-us-1.cloud.sap).", - no_alert_on_absence: "true", - playbook: "docs/devops/alert/vcenter/#hadetectedapossiblehostfailure", - prometheus: "vmware-monitoring/vmware-vc-a-0", - recommendation_1: - "Find the computer that has the duplicate IP address and reconfigure it to have a different IP address. This fault will be cleared and the alert canceled when the underlying problem is resolved and the vSphere HA master agent is able to connect to the HA agent on the host. NOTE: You can use the Duplicate IP warning in the /var/log/vmkernel log file on an ESX host or the /var/log/messages log file on an ESXi host to identify the computer that has the duplicate IP address.", - region: "na-us-1", - service: "compute", - severity: "critical", - status: "active", - support_group: "compute", - symptom_1_data: - "{'condition': {'faultEvents': ['com.vmware.vc.HA.DasHostFailedEvent'], 'faultKey': 'fault|host|ha', 'type': 'CONDITION_FAULT'}, 'severity': 'CRITICAL'}", - symptom_1_name: "vSphere HA detected a host failure", - tier: "vmware", - vccluster: "productionbb164", - vcenter: "vc-a-0.cc.na-us-1.cloud.sap", - }, -} - -const refAlertStatus = { - inhibitedBy: [], - silencedBy: [], - state: "active", -} - -const refSilence = { - duration: "2", - comment: "Test description", - createdBy: "Jane Doe", - status: { - state: "active", - }, - matchers: [ - { name: "cluster", value: "s-na-us-1", isRegex: false }, - { name: "cluster_type", value: "scaleout", isRegex: false }, - { - name: "context", - value: "node014-bb164.cc.na-us-1.cloud.sap failure", - isRegex: false, - }, - { name: "job", value: "vrops-exporter", isRegex: false }, - { name: "region", value: "na-us-1", isRegex: false }, - { name: "service", value: "compute", isRegex: false }, - { name: "severity", value: "critical", isRegex: false }, - { name: "support_group", value: "compute", isRegex: false }, - { name: "tier", value: "vmware", isRegex: false }, - ], - startsAt: "2023-06-21T13:17:28.327Z", - endsAt: "2023-06-21T15:17:28.327Z", -} - -export const createFakeSilenceWith = (props = {}) => { - return { ...refSilence, ...props } -} - -export const createFakeAlertStatustWith = (props = {}) => { - return { ...refAlertStatus, ...props } -} - -export const createFakeAlertWith = (props = {}) => { - return { ...refAlert, ...props } -} diff --git a/apps_deprecated/supernova/src/lib/utils.js b/apps_deprecated/supernova/src/lib/utils.js deleted file mode 100644 index df609af76..000000000 --- a/apps_deprecated/supernova/src/lib/utils.js +++ /dev/null @@ -1,155 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const severityToSemanticName = (severity) => { - switch (severity) { - case "critical": - return "danger" - case "warning": - return "warning" - case "info": - return "info" - default: - return severity - } -} - -export const descriptionParsed = (text) => { - if (!text) return "" - // urls in descriptions follow the schema: - // Parse description and replace urls with a-tags - const regexUrl = /<(http[^>|]+)\|([^>]+)>/g - const urlParsed = text.replace(regexUrl, `$2`) - - // replace text wrapped in *..* by strong tags - const regexBold = /\*(.*)\*/g - const boldParsed = urlParsed.replace(regexBold, `$1`) - - const regexCode = /`(.*)`/g - return boldParsed.replace(regexCode, `$1`) -} - -// Capitalize first char, underscores to spaces, camel case to spaces, all words except the first to lower case -export const humanizeString = (value) => { - if (!value) { - return value - } - - const camelCaseMatch = /([A-Z])/g - const underscoreMatch = /_/g - - const camelCaseToSpaces = value.replace(camelCaseMatch, " $1") - const underscoresToSpaces = camelCaseToSpaces.replace(underscoreMatch, " ") - - // all together now (also capitalize first word and lowercase all other words) - const humanized = - underscoresToSpaces.charAt(0).toUpperCase() + - underscoresToSpaces.slice(1).toLowerCase() - - return humanized -} - -// sort silences by state -// { -// active: [...], pending: [...], expired:[...], ... -// } -export const sortSilencesByState = (silences) => { - const sortedSilences = {} - - if (!silences || silences.length === 0) return {} - - silences.forEach((silences) => { - const state = silences.status?.state - if (!sortedSilences[state]) sortedSilences[state] = [] // init - sortedSilences[state].push(silences) - }) - return sortedSilences -} - -// count alerts and create a map -// { -// global: { total: number, critical: number, ...}, -// regions: { -// "eu-de-1": { total: number, critical: {total: number, suppressed: number}, warning: {...}, ...} -// }, ... -// } -export const countAlerts = (alerts) => { - const counts = { global: { total: 0 }, regions: {} } - - if (!alerts || alerts.length === 0) return counts - - // run through each alert once and adjust different types of counts as necessary - alerts.forEach((alert) => { - // total number of alerts - counts.global.total += 1 - - const region = alert.labels?.region - const severity = alert.labels?.severity - const state = alert.status?.state - - // global count per severity - counts.global[severity] = counts.global[severity] || 0 // init - counts.global[severity] += 1 - - // count per region and severity - counts.regions[region] = counts.regions[region] || {} // init - counts.regions[region].total = counts.regions[region].total || 0 // init - counts.regions[region].total += 1 - - // total count per region and severity - counts.regions[region][severity] = counts.regions[region][severity] || {} // init - counts.regions[region][severity]["total"] = - counts.regions[region][severity]?.total || 0 // init - counts.regions[region][severity]["total"] += 1 - // suppressed per region and severity - if (state === "suppressed") { - counts.regions[region][severity].suppressed = - counts.regions[region][severity]?.suppressed || 0 // init - counts.regions[region][severity].suppressed += 1 - } - }) - - return counts -} - -/** - * This method sorts the alerts first by severity (critical -> warning -> others), then by status, then by startsAt timestamp and finally by region - * @param {array} items, a list of alerts - * @returns {array} sorted alerts - */ -export const sortAlerts = (items) => { - const importantSeverities = ["critical", "warning"] - - return items.sort((a, b) => { - if ( - (a.labels?.severity === "critical" && - b.labels?.severity !== "critical") || - (a.labels?.severity === "warning" && - importantSeverities.indexOf(b.labels?.severity) < 0) - ) - return -1 - else if ( - a.labels?.severity === b.labels?.severity && - a.status?.state !== b.status?.state && - a.status?.state - ) - return a.status?.state.localeCompare(b.status?.state) - else if ( - a.labels?.severity === b.labels?.severity && - a.status?.state === b.status?.state && - a.startsAt !== b.startsAt && - b.startsAt - ) - return b.startsAt?.localeCompare(a.startsAt) - else if ( - a.labels?.severity === b.labels?.severity && - a.status?.state === b.status?.state && - a.startsAt === b.startsAt && - a.labels?.region - ) - return a.labels?.region?.localeCompare(b.labels?.region) - else return 1 - }) -} diff --git a/apps_deprecated/supernova/src/styles.scss b/apps_deprecated/supernova/src/styles.scss deleted file mode 100644 index 77cc678a9..000000000 --- a/apps_deprecated/supernova/src/styles.scss +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -/* Do not remove these tailwind directives. Without them styles won't work as expected */ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* If necessary, app styles can be added below */ - -.inline-code { - @apply bg-theme-badge-default; - @apply text-theme-default; - @apply text-sm; - @apply rounded; - @apply px-1; - @apply py-0.5; -} - -// datagrid row hover style -// REMOVE THIS ONCE DATAGRID COMPONENT SUPPORTS HOVER -.alerts { - .juno-datagrid-row:hover { - .juno-datagrid-cell { - @apply bg-theme-background-lvl-1; - } - } - - .juno-datagrid-row.active { - .juno-datagrid-cell { - @apply bg-theme-background-lvl-2; - } - } -} diff --git a/apps_deprecated/supernova/src/workers/alerts.js b/apps_deprecated/supernova/src/workers/alerts.js deleted file mode 100644 index 817149618..000000000 --- a/apps_deprecated/supernova/src/workers/alerts.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import ApiService from "../api/apiService" -import { get } from "../api/client" -import { sortAlerts, countAlerts } from "../lib/utils" - -let compareAlertString - -/** - * @param {string} endpoint - * @param {object} options - * @returns {function} fetch function - */ -const fetchAction = (endpoint, options = {}) => { - return get(`${endpoint}/alerts`, { params: options.params }).then((items) => { - // sort alerts - let alerts = sortAlerts(items) - - // copy additional filter options to labels for easier filter selection - // because the alert object is nested this makes it a lot easier to filter, since we only use what is present in alert.labels - alerts.forEach((alert) => { - if (alert.labels) { - alert.labels.status = alert.status?.state - } - }) - - // slice if limit provided - if (options?.limit) { - if (options?.debug) - console.info("Alerts service: limit set: ", options?.limit) - alerts = alerts.slice(0, options?.limit) - } - - // check if new loaded alerts are different from the last response - const newCompareString = JSON.stringify(alerts) - if (options?.debug) - console.info( - "Alerts service: any changes?", - compareAlertString !== newCompareString - ) - if (compareAlertString !== newCompareString) { - compareAlertString = newCompareString - - if (options?.debug) console.info("Alerts service: inform listener") - // inform listener to receive new alerts - self.postMessage({ - action: "ALERTS_UPDATE", - alerts, - counts: countAlerts(alerts), - }) - } else { - if (options?.debug) console.info("Alerts service: no change found") - } - }) -} - -const alertsService = new ApiService({ - serviceName: "alerts", - debug: true, - onFetchStart: () => self.postMessage({ action: "ALERTS_FETCH_START" }), - onFetchEnd: () => self.postMessage({ action: "ALERTS_FETCH_END" }), - onFetchError: (error) => { - self.postMessage({ action: "ALERTS_FETCH_ERROR", error: error.message }) - }, -}) - -self.onmessage = (e) => { - const action = e.data.action - - switch (action) { - case "ALERTS_CONFIGURE": - // require at least apiEndpoint to update the fetch method - if (e.data?.fetchVars?.apiEndpoint) { - // update the fetch function - e.data["fetchFn"] = () => - fetchAction( - e.data?.fetchVars.apiEndpoint, - e.data?.fetchVars.options || {} - ) - } - alertsService.configure(e.data) - break - case "ALERTS_FETCH": - alertService.fetch() - break - } -} diff --git a/apps_deprecated/supernova/src/workers/silences.js b/apps_deprecated/supernova/src/workers/silences.js deleted file mode 100644 index f6661150f..000000000 --- a/apps_deprecated/supernova/src/workers/silences.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import ApiService from "../api/apiService" -import { get } from "../api/client" -import { sortSilencesByState } from "../lib/utils" - -const fetchAction = (endpoint) => { - return get(`${endpoint}/silences`, {}).then((items) => { - // convert items to hash to easear access - const itemsHash = items.reduce((itemsHash, silence) => { - itemsHash[silence.id] = silence - return itemsHash - }, {}) - - // split items by state (active, pending and expired) - // https://github.com/prometheus/alertmanager/blob/main/types/types.go#L434 - const itemsByState = sortSilencesByState(items) - - self.postMessage({ - action: "SILENCES_UPDATE", - silences: items, - silencesHash: itemsHash, - silencesBySate: itemsByState, - }) - }) -} - -const silenceService = new ApiService({ - serviceName: "silences", - debug: true, - onFetchStart: () => self.postMessage({ action: "SILENCES_FETCH_START" }), - onFetchEnd: () => self.postMessage({ action: "SILENCES_FETCH_END" }), - onFetchError: (error) => { - self.postMessage({ action: "SILENCES_FETCH_ERROR", error: error.message }) - }, -}) - -self.onmessage = (e) => { - const action = e.data.action - - switch (action) { - case "SILENCES_CONFIGURE": - if (e.data?.apiEndpoint) { - e.data["fetchFn"] = () => fetchAction(e.data?.apiEndpoint) - } - silenceService.configure(e.data) - break - case "SILENCES_FETCH": - silenceService.fetch() - break - } -} diff --git a/apps_deprecated/supernova/tailwind.config.js b/apps_deprecated/supernova/tailwind.config.js deleted file mode 100644 index 81b1f8fef..000000000 --- a/apps_deprecated/supernova/tailwind.config.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// opacity helper to make custom colors work with opacity -function withOpacity(variableName) { - return ({ opacityVariable, opacityValue }) => { - if (opacityValue !== undefined) { - return `rgba(var(${variableName}), ${opacityValue})` - } - if (opacityVariable !== undefined) { - return `rgba(var(${variableName}), var(${opacityVariable}, 1))` - } - return `rgb(var(${variableName}))` - } -} - -module.exports = { - presets: [ - require("juno-ui-components/build/lib/tailwind.config"), // important, do not change - ], - prefix: "", // important, do not change - content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], - corePlugins: { - preflight: false, // important, do not change - }, - theme: {}, - plugins: [], -} diff --git a/apps_deprecated/template/.gitignore b/apps_deprecated/template/.gitignore deleted file mode 100644 index 362e8faa9..000000000 --- a/apps_deprecated/template/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules -secretProps -public/build diff --git a/apps_deprecated/template/LICENSE b/apps_deprecated/template/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/apps_deprecated/template/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/apps_deprecated/template/README.md b/apps_deprecated/template/README.md deleted file mode 100644 index 20c235763..000000000 --- a/apps_deprecated/template/README.md +++ /dev/null @@ -1,46 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/juno](https://github.com/cloudoperators/juno) for the latest updates and active development. - -# Template App - -This is the standard app template for microfrontends. Use this as a basis for new juno microfrontend apps. - -## Instructions - -1. Copy the `template` folder, rename to name of your app -2. Change the name in `package.json` from "template" to your app's name -3. Change `URL_STATE_KEY` in `App.js` to your app's name - -## Usage - -### load via script tag - -```js - -``` - -Most of the time using `latest` as `VERSION` and `data-version` is what you want to do. Alternatively you can see all published versions at `https://JUNO_CDN_HOSTNAME/manifest.json`. - -`YOUR_APP_NAME` must be the name you specified in your `package.json` (see above) - -Custom properties can be passed to the app via data properties on the script tag. See example `data-props-myprop` below. Custom properties can be accessed in your App.js via `props`. Use only lowercase letters and no special characters in custom prop names. - -Example: - -```js - -``` - -More information about options [here](https://github.com/sapcc/juno/blob/main/apps/widget-loader/README.md) diff --git a/apps_deprecated/template/__mocks__/client.js b/apps_deprecated/template/__mocks__/client.js deleted file mode 100644 index 84531d3c2..000000000 --- a/apps_deprecated/template/__mocks__/client.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { JSDOM } from "jsdom" -const dom = new JSDOM() -global.document = dom.window.document -global.window = dom.window diff --git a/apps_deprecated/template/__mocks__/fileMock.js b/apps_deprecated/template/__mocks__/fileMock.js deleted file mode 100644 index 27ce65aca..000000000 --- a/apps_deprecated/template/__mocks__/fileMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = "test-file-stub" diff --git a/apps_deprecated/template/__mocks__/styleMock.js b/apps_deprecated/template/__mocks__/styleMock.js deleted file mode 100644 index d74516001..000000000 --- a/apps_deprecated/template/__mocks__/styleMock.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = {} diff --git a/apps_deprecated/template/babel.config.js b/apps_deprecated/template/babel.config.js deleted file mode 100644 index 0719e2fec..000000000 --- a/apps_deprecated/template/babel.config.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - env: { - test: { - presets: ["@babel/preset-env", "@babel/preset-react"], - plugins: [["babel-plugin-transform-import-meta", { module: "ES6" }]], - }, - }, -} diff --git a/apps_deprecated/template/esbuild.config.js b/apps_deprecated/template/esbuild.config.js deleted file mode 100644 index d2862fda1..000000000 --- a/apps_deprecated/template/esbuild.config.js +++ /dev/null @@ -1,205 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const esbuild = require("esbuild") -const fs = require("node:fs/promises") -const pkg = require("./package.json") -const postcss = require("postcss") -const sass = require("sass") -const { transform } = require("@svgr/core") -const url = require("postcss-url") -// this function generates app props based on package.json and propSecrets.json -const appProps = require("../../helpers/appProps") - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) - -const isProduction = process.env.NODE_ENV === "production" -// If the jspm server fails and we cannot use external packages -// in our import map then IGNORE_EXTERNALS (global env variable) -// should be set to true -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" -// in dev environment we prefix output file with public -let outfile = `${isProduction ? "" : "public/"}${pkg.main || pkg.module}` -// get output from outputfile -let outdir = outfile.slice(0, outfile.lastIndexOf("/")) -const args = process.argv.slice(2) -const watch = args.indexOf("--watch") >= 0 -const serve = args.indexOf("--serve") >= 0 - -// helpers for console log -const green = "\x1b[32m%s\x1b[0m" -const yellow = "\x1b[33m%s\x1b[0m" -const clear = "\x1b[2J\x1b[H" - -const build = async () => { - // delete build folder and re-create it as an empty folder - await fs.rm(outdir, { recursive: true, force: true }) - await fs.mkdir(outdir, { recursive: true }) - - // build app - let ctx = await esbuild.context({ - bundle: true, - minify: isProduction, - // target: ["es2020"], - target: ["es2020"], //["chrome64", "firefox67", "safari11.1", "edge79"], - format: "esm", - platform: "browser", - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - loader: { ".js": "jsx" }, - sourcemap: !isProduction, - // here we exclude package from bundle which are defined in peerDependencies - // our importmap generator uses also the peerDependencies to create the importmap - // it means all packages defined in peerDependencies are in browser available via the importmap - external: - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [], - entryPoints: [pkg.source], - outdir, - // this step is important for performance reason. - // the main file (index.js) contains minimal code needed to - // load the app via dynamic import (splitting: true) - splitting: true, - // we suport only esm! - format: "esm", - plugins: [ - // minimal plugin to log the recompiling process. - { - name: "start/end", - setup(build) { - build.onStart(() => { - console.log(yellow, "Compiling...") - }) - build.onEnd(() => console.log(green, "Done!")) - }, - }, - - // this custom plugin rewrites SVG imports to - // dataurls, paths or react components based on the - // search param and size - { - name: "svg-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(svg)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - let loader = "text" - if (args.suffix === "?url") { - // as URL - const maxSize = 10240 // 10Kb - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - } else { - // as react component - // use react component loader (jsx) - loader = "jsx" - contents = await transform(contents, { - plugins: ["@svgr/plugin-jsx"], - }) - } - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin rewrites image imports to - // dataurls or urls based on the size - { - name: "image-loader", - setup(build) { - build.onLoad( - // consider only .svg files - { filter: /.\.(png|jpg|jpeg|gif)$/, namespace: "file" }, - async (args) => { - let contents = await fs.readFile(args.path) - const maxSize = 10240 // 10Kb - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - // use dataurl loader for small files and file loader for big files! - loader = contents.length <= maxSize ? "dataurl" : "file" - - return { contents, loader } - } - ) - }, - }, - - // this custom plugin parses the style files - { - name: "parse-styles", - setup(build) { - build.onLoad( - // consider only .scss and .css files - { filter: /.\.(css|scss)$/, namespace: "file" }, - async (args) => { - let content - // handle scss, convert to css - if (args.path.endsWith(".scss")) { - const result = sass.renderSync({ file: args.path }) - content = result.css - } else { - // read file content - content = await fs.readFile(args.path) - } - - // postcss plugins - const plugins = [ - require("tailwindcss"), - require("autoprefixer"), - // rewrite urls inside css - url({ - url: "inline", - // maxSize: 10, // use dataurls if files are smaller than 10k - // fallback: "copy", // if files are bigger use copy method - // assetsPath: "./build/assets", - // useHash: true, - // optimizeSvgEncode: true, - }), - ] - - const { css } = await postcss(plugins).process(content, { - from: args.path, - to: outdir, - }) - // built-in loaders: js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary - return { contents: css, loader: "text" } - } - ) - }, - }, - ], - }) - - // watch and serve - if (watch || serve) { - if (watch) await ctx.watch() - if (serve) { - // generate app props based on package.json and secretProps.json - await fs.writeFile( - `./${outdir}/appProps.js`, - `export default ${JSON.stringify(appProps())}` - ) - - let { host, port } = await ctx.serve({ - host: "0.0.0.0", - port: parseInt(process.env.APP_PORT || process.env.PORT || 3000), - servedir: "public", - }) - console.log("serve on", `${host}:${port}`) - } - } else { - await ctx.rebuild() - await ctx.dispose() - } -} - -build() diff --git a/apps_deprecated/template/jest.config.js b/apps_deprecated/template/jest.config.js deleted file mode 100644 index cdc33f045..000000000 --- a/apps_deprecated/template/jest.config.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - transform: { "\\.[jt]sx?$": "babel-jest" }, - testEnvironment: "jsdom", - setupFilesAfterEnv: ["/setupTests.js"], - transformIgnorePatterns: [ - "node_modules/(?!(juno-ui-components|url-state-router|communicator|oauth|url-state-provider|messages-provider|policy-engine)/)", - ], - moduleNameMapper: { - // Jest currently doesn't support resources with query parameters. - // Therefore we add the optional query parameter matcher at the end - // https://github.com/facebook/jest/issues/4181 - "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)(\\?.+)?$": - require.resolve("./__mocks__/fileMock"), - "\\.(css|less|scss)$": require.resolve("./__mocks__/styleMock"), - }, -} diff --git a/apps_deprecated/template/package.json b/apps_deprecated/template/package.json deleted file mode 100644 index 341f91197..000000000 --- a/apps_deprecated/template/package.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "name": "template", - "version": "1.0.3", - "author": "UI-Team", - "contributors": [ - "Andreas Pfau", - "Arturo Reuschenbach Pucernau" - ], - "repository": "https://github.com/sapcc/juno/tree/main/apps/template", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/juno for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "source": "src/index.js", - "module": "build/index.js", - "private": true, - "devDependencies": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@svgr/core": "^7.0.0", - "@svgr/plugin-jsx": "^7.0.0", - "@tanstack/react-query": "4.28.0", - "@testing-library/dom": "^8.19.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "assert": "^2.0.0", - "autoprefixer": "^10.4.2", - "babel-jest": "^29.3.1", - "babel-plugin-transform-import-meta": "^2.2.0", - "jest": "^29.3.1", - "jest-environment-jsdom": "^29.3.1", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.14.1/package.tgz", - "luxon": "^2.3.0", - "postcss": "^8.4.21", - "postcss-url": "^10.1.3", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-test-renderer": "18.2.0", - "react-error-boundary": "^4.0.12", - "sass": "^1.60.0", - "shadow-dom-testing-library": "^1.7.1", - "tailwindcss": "^3.3.1", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "util": "^0.12.4", - "zustand": "4.5.2", - "esbuild": "^0.19.5" - }, - "scripts": { - "test": "jest", - "start": "NODE_ENV=development node esbuild.config.js --serve --watch", - "build": "NODE_ENV=production node esbuild.config.js", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prestart": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "peerDependencies": { - "@tanstack/react-query": "4.28.0", - "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.14.1/package.tgz", - "luxon": "^2.3.0", - "prop-types": "^15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", - "zustand": "4.5.2" - }, - "importmapExtras": { - "zustand/middleware": "4.3.7" - }, - "appProps": { - "urlStateKey": { - "value": "", - "type": "optional", - "description": "Replace this with your app's name. Default is 'template'." - }, - "theme": { - "value": "theme-dark", - "type": "optional", - "description": "Override the default theme. Possible values are theme-light or theme-dark (default)" - }, - "endpoint": { - "value": "", - "type": "required", - "description": "Endpoint URL of the API" - }, - "embedded": { - "value": "false", - "type": "optional", - "description": "Set to true if app is to be embedded in another existing app or page, like e.g. Elektra. If set to true the app won't render a page header/footer and instead render only the content. The default value is false." - } - }, - "appPreview": true -} diff --git a/apps_deprecated/template/public/favicon-16x16.png b/apps_deprecated/template/public/favicon-16x16.png deleted file mode 100644 index 584c1f5670776819e633f02d7bcad17889cf0a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 691 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>+Zq|9g&CL_8S?xXvV9mB85#DqGe`a0wC|h?SIGGR1sRjP-CguTE(^4SR1|nb z76ZjjfiUBlZKZ}lLG}_)Usv|0JRE!yY_I=+l>`bEdb&7R*tavAI)umX%Sbx@K$*o%^vPMWs+_+I%^6=9d8HSm&xSbTI z1YZVPu3F+6QIe8al4_M)lnSI6j0}tnbq$Sl4J<+oO{|PetPISw4GgRd48*3guSU_3 zo1c=IR*73f`icGGKn;>08-nxGO3D+9QW?t2%k?tzvWt@w3sUv+i_&MmvylQS3a<)@ zC<#g|S12gTPs_|nRVb+}NL9!zC`o2usF?Hk6AwpWn1;qF|I=qYp9V27D|725a|bP0 Hl+XkKST@R^ diff --git a/apps_deprecated/template/public/favicon-32x32.png b/apps_deprecated/template/public/favicon-32x32.png deleted file mode 100644 index 6aaa25bc6844c07229dc5899b14ddd54b9523ccb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1048 zcmbV|ZA?>V9K}z$(pFw26?v6az{)$94hSO*g%l`I5KEm5XJ#p-bO^oHi$#X4vdNrI z2_hRHFUpF{_=0Az7&RHV##M@Q470I?RGicS28JbbYLM=d?8`pv%bw(UPX7Pr{Bn}> zNnUP-tCO!20M|^hNXjUG<#Gw;6&a4+W@MErB_{>A+Tgq-cU<{Yh^09|wE)n61iWNc z`e~q&1ZH;wi7kK^)qZ_j62MB%lgQE-!~ZyB5bmA&hx6qjAq1(>hzJIHIQ#CzNQbz-Tk#1=x{{I04ps zg6oKxbBN&Mrxvu9nZ`6R6vT=^kAB5S@FW zNQd) zEv})zE{}G+h^S!+AU>*mdV zV*k^JVSF-0DY69fz}U~yTU*w$C!5x|I2674nJXvz3hPiv*wOJJ%lm)Kz3LjQqy(Sd z3Fuqu+yB`9^~ih#N~=wSdhZRph*pXhrl_~poclb`;jT&Gv?0JaIGN(V(6B^I&(F;9 zviKK+?-*Wk>V_uQ{4(>farEj_Nj!I|z2u35&;zp{Ph1+cEDt?wbn@>? z=v9sEJhFJqKahwzuaCHPJw3osQI!{b%#m#=X-#&EtkT`ndrv=Kcy3^?{z3Beo$b#q zmD?8EqWd(LyEXP@OJiw<%J%BfqOOeIIJFc_z9)CDC>FDs-Zs){1$42TRwgR6N=6_g zg)xya!bmbf789E&j7=ot!$~rcB-b@_F8m89*A%Nu4*WNuGJWI406r@T`I-`1C)X;W z)9Iqr6=nMra!MJc(W*|*C;2j_9o4b|S}ND^DXpeNy+_HX4^T?JnxYjzRr@2G3wQ5Z zAtA$C%_EssDTpBFD1|dGh?m{8mf-P4`q*!aiJ-4!eDnBylX1l8Z{(Qu;xk!MnDz3Y TZK-k1OawC1az&R@ch~(5_Pbxd diff --git a/apps_deprecated/template/public/favicon.ico b/apps_deprecated/template/public/favicon.ico deleted file mode 100644 index 9ebc4bb2e04736789f9fcfe03121b296c693079a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHOc~DkW6h8=vpa^PaX3JM9iaLr~+M@BPg-&UinG_1xqN9VFP8qhyVv3gI5)y)q zTINC;R?|K;#Z=Q?rdcjEfL2psi+^QPO{eqwE|2&4e8Bs@_ib;6J9D_-d+*+Je)rsS zw{s6fQ4~#SX(YLes`?X+A|jWo@j02OR^BB`j_>ngh)SfuKq(_tXtogEds07@wedGr zzRwh@rmJplpzU=``%W`${FrIleN26aGbMIs`5p@TOXSoGJtveUB&};Tx#jC|A*LG_ zG41`GX~z#t*Uo0@5FHArF33-gz4hJZSf5CcVNu%YJgjw z6?WGUracWzyMAW6WN4_dS(OK@>5XlGO&t+Zbqiipx}UPZDz9*rJ0_ShR%bO~A9#hr zzU3%WY^QMH@_-h3_=2)hvD5l*q zW--@al459QQcid2PTLeyU!zA+Owd_+jT$7c2behY2~(YeQ@t)2cUB8>)U~ zns~SK+R*Jhri!oieptGbsdqnTwWE7)rblb^HsCDt$m>kg?`KNCjcN20rt#TKBPT^} zyW--RW-McR=10997#Bv$d?0f1YwK3hxlGs3V=8<}=BE?Q@#n0JeEeEFw7g>{rX|}| zI~Hwm9)9CIyY~I?;m0`Cbn0t9{5qxoy?=y$zl#0k!~2zdUvX>Yu})}f_0%Q)>p|mZ z%!iI+TK^GKZiyOq*JLu?FrNwM!pA?=#~*ZOtmo_RIqMZK__z|f+T*3k#yP6^RUM;o zt~36I{`-xzC$pDJKeNr`XO&KQ*tkB7~p4`p09jR^AB`CxdkYr24s`lfsIc~$F=9p9_|!Ttl|aO-z^J5griCrm@ep4~=`Z>V#e z<8E21<_@h5-Z{n!e68>mM22tPTz@!6r%e!_{OxKjLOys5Q+yZm@}bssyS(;(Xt#lI z+JNqZc3wXK`^k{6)q&GfonU|7!T75Md$xn|BTfK!kl#A64aXa?OGe{`)ctkfY%`d1 z60o|3jA^z!{38@hxq;vf?72c_3H=bswgj7Tn*lex!+5}$#=Z7Qp>VDb+WZbIh!X&| zX6au%r4yY-o}_|pD2}KG&(TCh$fNWekL{^t4HV&%L0>g^7CqJ@7rknF*7S}zEtim6 zs3}fMV!2vLUFBN=^-ViYWe5JFbswsDp&otA&$+(O2WN!;L80YBi9*ISNFM4u@c~bt zRQ|Z&p4||iklF}9tW#vibYw!DMdd?A3*TF?)qQ9(HtB{EG68+u>oS zZpNLe4@ON6j}9>YH+{jht(K`zN_a3JCKGX`xHlMcYj}Kyh_ig+pz4c?Z=|n@Vn3I^V6D872ktS}eZaJI7ZdKqu)b<{ZLl+A+17p|J^_6&BExze@Poe? z_ldv&|2AYJZUc9$R`m})SR={~sIl2+fHe$=p+L;Cub5lX1Lh^n4QNkm^CbFfavoFF zDWHQw}8`_-?><8mC^-78D9Hji$h~+Q+T*(gBdX9d>n8Y5{+y9SsbYX?e z;THSIyM4Ys!;g>n=wahke5Efo<*Tgr@`1HwrBAj043BQH|2%AY4h%d-?7xe`D8E2t z`$(L?&dzPXV`tOQ^|DVgBD(2^8P8oEB7`k^di)d(uQRy?VcE5Voa4@j_)Z zvyiF(W!`11JcCCA6}@bwtXY``PpkmW*mi6TXEem1`pX0R$Q7?i47d1n{N;hThmyC{ zSrKcnzkINlnO|nDzF90PVnJ5F&4hSXGYp6qS@{OjWA8G}DmE`O)U9G{jQT)K2mZ$o z`zJHL-tQ0(1iL`oBjQ^SdoXUMwYo-L@cY>5TO%*?-xv$N<5G1{x6DTUO;R_Zk;f?? P_&~0wZjp_d33dMme?Bb{ diff --git a/apps_deprecated/template/public/index.html b/apps_deprecated/template/public/index.html deleted file mode 100644 index 92e703e23..000000000 --- a/apps_deprecated/template/public/index.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - Template Dev - - - - - -
- - diff --git a/apps_deprecated/template/secretProps.template.json b/apps_deprecated/template/secretProps.template.json deleted file mode 100644 index 51d73b7c8..000000000 --- a/apps_deprecated/template/secretProps.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "urlStateKey": "template", - "theme": "theme-dark", - "endpoint": "https://endpoint/api/v1" -} diff --git a/apps_deprecated/template/setupTests.js b/apps_deprecated/template/setupTests.js deleted file mode 100644 index db44c9038..000000000 --- a/apps_deprecated/template/setupTests.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom" diff --git a/apps_deprecated/template/src/App.js b/apps_deprecated/template/src/App.js deleted file mode 100644 index b541dd2c2..000000000 --- a/apps_deprecated/template/src/App.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { AppShell, AppShellProvider, CodeBlock } from "juno-ui-components" -import StoreProvider from "./components/StoreProvider" -import { QueryClient, QueryClientProvider } from "@tanstack/react-query" -import AppContent from "./AppContent" -import styles from "./styles.scss" -import { ErrorBoundary } from "react-error-boundary" - -const App = (props = {}) => { - const preErrorClasses = ` - custom-error-pre - border-theme-error - border - h-full - w-full - ` - - // Create query client which it can be used from overall in the app - // set default endpoint to fetch data - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - meta: { - endpoint: props.endpoint || props.currentHost || "", - }, - }, - }, - }) - - const fallbackRender = ({ error }) => { - return ( -
- - {error?.message || error?.toString() || "An error occurred"} - -
- ) - } - - return ( - - - - - - - - ) -} - -const StyledApp = (props) => { - return ( - - {/* load styles inside the shadow dom */} - - - - - - ) -} - -export default StyledApp diff --git a/apps_deprecated/template/src/App.test.js b/apps_deprecated/template/src/App.test.js deleted file mode 100644 index 2760e4877..000000000 --- a/apps_deprecated/template/src/App.test.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { render, act, waitFor } from "@testing-library/react" -// support shadow dom queries -// https://reactjsexample.com/an-extension-of-dom-testing-library-to-provide-hooks-into-the-shadow-dom/ -import { screen } from "shadow-dom-testing-library" -import App from "./App" - -test("renders app", async () => { - await act(() => render()) - - let loginTitle = await screen.queryAllByShadowText(/Converged Cloud/i) - expect(loginTitle.length > 0).toBe(true) -}) diff --git a/apps_deprecated/template/src/AppContent.js b/apps_deprecated/template/src/AppContent.js deleted file mode 100644 index 1fee22829..000000000 --- a/apps_deprecated/template/src/AppContent.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Container } from "juno-ui-components" - -// This is your starting point of tour application -// see several examples in the exampleApp -const AppContent = (props) => { - return ( - -
Hello World!!!
-
- ) -} - -export default AppContent diff --git a/apps_deprecated/template/src/assets/.gitkeep b/apps_deprecated/template/src/assets/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps_deprecated/template/src/components/StoreProvider.js b/apps_deprecated/template/src/components/StoreProvider.js deleted file mode 100644 index cea02ae0c..000000000 --- a/apps_deprecated/template/src/components/StoreProvider.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { createContext, useContext } from "react" -import { useStore as create } from "zustand" -import createStore from "../lib/store" - -const StoreContext = createContext() -const StoreProvider = ({ options, children }) => ( - - {children} - -) - -const useAppStore = (selector) => create(useContext(StoreContext), selector) - -export const useGlobalsUrlStateKey = () => - useAppStore((state) => state.globals.urlStateKey) -export const useGlobalsActions = () => - useAppStore((state) => state.globals.actions) - -export default StoreProvider diff --git a/apps_deprecated/template/src/hooks/.gitkeep b/apps_deprecated/template/src/hooks/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps_deprecated/template/src/index.js b/apps_deprecated/template/src/index.js deleted file mode 100644 index f6f988315..000000000 --- a/apps_deprecated/template/src/index.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createRoot } from "react-dom/client" -import React from "react" - -// export mount and unmount functions -export const mount = (container, options = {}) => { - import("./App").then((App) => { - mount.root = createRoot(container) - mount.root.render(React.createElement(App.default, options?.props)) - }) -} - -export const unmount = () => mount.root && mount.root.unmount() diff --git a/apps_deprecated/template/src/lib/store/createGlobalsSlice.js b/apps_deprecated/template/src/lib/store/createGlobalsSlice.js deleted file mode 100644 index 86f7b091a..000000000 --- a/apps_deprecated/template/src/lib/store/createGlobalsSlice.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const createGlobalsSlice = (set, get, options) => ({ - globals: { - urlStateKey: options.urlStateKey || "template", - - actions: { - setUrlStateKey: (newUrlStateKey) => - set((state) => ({ - globals: { ...state.globals, urlStateKey: newUrlStateKey }, - })), - }, - }, -}) - -export default createGlobalsSlice diff --git a/apps_deprecated/template/src/lib/store/createGlobalsSlice.test.js b/apps_deprecated/template/src/lib/store/createGlobalsSlice.test.js deleted file mode 100644 index 44fbd786c..000000000 --- a/apps_deprecated/template/src/lib/store/createGlobalsSlice.test.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { renderHook, act } from "@testing-library/react" -import StoreProvider, { - useGlobalsActions, - useGlobalsUrlStateKey, -} from "../../components/StoreProvider" - -describe("createGlobalsSlice", () => { - describe("setUrlStateKey", () => { - it("examples a basic test", () => { - const wrapper = ({ children }) => ( - {children} - ) - const store = renderHook( - () => ({ - globalsActions: useGlobalsActions(), - urlStateKey: useGlobalsUrlStateKey(), - }), - { wrapper } - ) - - act(() => { - store.result.current.globalsActions.setUrlStateKey("example app") - }) - - expect(store.result.current.urlStateKey).toEqual("example app") - }) - }) -}) diff --git a/apps_deprecated/template/src/lib/store/index.js b/apps_deprecated/template/src/lib/store/index.js deleted file mode 100644 index b8d3cea19..000000000 --- a/apps_deprecated/template/src/lib/store/index.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createStore } from "zustand" -import { devtools } from "zustand/middleware" -import createGlobalsSlice from "./createGlobalsSlice" - -export default () => - createStore( - devtools((set, get, options) => ({ - ...createGlobalsSlice(set, get, options), - })) - ) diff --git a/apps_deprecated/template/src/styles.scss b/apps_deprecated/template/src/styles.scss deleted file mode 100644 index 7ebe08bad..000000000 --- a/apps_deprecated/template/src/styles.scss +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -/* Do not remove these tailwind directives. Without them styles won't work as expected */ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* If necessary, app styles can be added below */ diff --git a/apps_deprecated/template/tailwind.config.js b/apps_deprecated/template/tailwind.config.js deleted file mode 100644 index 81b1f8fef..000000000 --- a/apps_deprecated/template/tailwind.config.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// opacity helper to make custom colors work with opacity -function withOpacity(variableName) { - return ({ opacityVariable, opacityValue }) => { - if (opacityValue !== undefined) { - return `rgba(var(${variableName}), ${opacityValue})` - } - if (opacityVariable !== undefined) { - return `rgba(var(${variableName}), var(${opacityVariable}, 1))` - } - return `rgb(var(${variableName}))` - } -} - -module.exports = { - presets: [ - require("juno-ui-components/build/lib/tailwind.config"), // important, do not change - ], - prefix: "", // important, do not change - content: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], - corePlugins: { - preflight: false, // important, do not change - }, - theme: {}, - plugins: [], -} diff --git a/ci/pipeline.yaml.erb b/ci/pipeline.yaml.erb index b4a1c2785..c6f0e31b4 100644 --- a/ci/pipeline.yaml.erb +++ b/ci/pipeline.yaml.erb @@ -10,24 +10,11 @@ } ASSETS = { - #"auth": { type: "package", path: "packages/auth", monorepo: false }, - #"assets-overview": { type: "package", path: "packages/assets-overview", monorepo: false}, - #"user-activity": { type: "package", path: "packages/user-activity", monorepo: false}, "volta": { type: "package", path: "packages/volta", monorepo: false}, "whois": { type: "package", path: "packages/whois", monorepo: false}, - #"widget-loader": { type: "package", path: "packages/widget-loader", monorepo: false}, - #"playground": { type: "package", path: "packages/playground", monorepo: false}, - #"policy-engine": { type: "package", path: "packages/policy-engine"}, } CLOUDOPERATOR_ASSETS = { - #"communicator": { type: "package", path: "packages/communicator", monorepo: true}, - #"messages-provider": { type: "package", path: "packages/messages-provider", monorepo: true}, - #"ui-components": { type: "package", path: "packages/ui-components", monorepo: true}, - #"oauth": { type: "package", path: "packages/oauth", monorepo: true}, - #"url-state-provider": { type: "package", path: "packages/url-state-provider", monorepo: true}, - #"url-state-router": { type: "package", path: "packages/url-state-router", monorepo: true}, - #"utils": { type: "package", path: "packages/utils", monorepo: true}, } HA_REGIONS = ["eu-de-1","eu-de-2","eu-nl-1","ap-ae-1","ap-jp-2","ap-au-1","la-br-1","na-us-1","na-us-2"] diff --git a/docs/build_and_host_app.md b/docs/build_and_host_app.md index 615ae0605..194104bb1 100644 --- a/docs/build_and_host_app.md +++ b/docs/build_and_host_app.md @@ -38,7 +38,7 @@ npm -v "prop-types": "^15.8.1", "react": "18.2.0", "react-dom": "^18.2.0", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", + "@cloudoperators/juno-url-state-provider-v1": "1.3.2", "zustand": "^4.1.1" }, ``` @@ -54,7 +54,7 @@ npm -v "devDependencies": { ... "juno-ui-components": "https://assets.juno.global.cloud.sap/libs/juno-ui-components@2.13.8/package.tgz", - "url-state-provider": "https://assets.juno.global.cloud.sap/libs/url-state-provider@1.3.2/package.tgz", + "@cloudoperators/juno-url-state-provider-v1": "1.3.2", ... }, ``` diff --git a/libs_deprecated/communicator/.gitignore b/libs_deprecated/communicator/.gitignore deleted file mode 100644 index 378eac25d..000000000 --- a/libs_deprecated/communicator/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build diff --git a/libs_deprecated/communicator/LICENSE b/libs_deprecated/communicator/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/libs_deprecated/communicator/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/libs_deprecated/communicator/README.md b/libs_deprecated/communicator/README.md deleted file mode 100644 index 9380438c9..000000000 --- a/libs_deprecated/communicator/README.md +++ /dev/null @@ -1,176 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/juno](https://github.com/cloudoperators/juno) for the latest updates and active development. - -# Communicator - -The "Communicator" library empowers seamless message exchange across various contexts, including multiple tabs on the same origin, by utilizing events. It offers a versatile range of communication options, including broadcast events for widespread interaction and one-to-one messaging capabilities. - -The library employs a set of methods, each complementing its counterpart: - -- **broadcast <-> watch**: These methods enable efficient communication between sender and receiver. When a sender employs the `broadcast` method to transmit an event, it must be monitored by a recipient using the `watch` method. This mechanism ensures that information is disseminated to the intended audience. - -- **get <-> onGet**: These methods are tailor-made for one-to-one communication, allowing precise exchanges between sender and recipient. Similar to broadcast and watch, if a sender utilizes the `get` method, the corresponding recipient should listen and respond using the `onGet` method. This approach ensures that data flows seamlessly in a directed manner. - -The Communicator library introduces the `crossWindow` option, which enhances its capabilities by enabling cross-tab communication. This feature facilitates communication between tabs, providing additional flexibility and expanding the library's utility. - -## Installation - -You can install the library in various ways: - -1. Via `package.json`: - - ```json - "dependencies": { - "communicator": "https://assets.juno.global.cloud.sap/libs/communicator@latest/package.tgz" - } - ``` - -2. Via `import`: - - ```javascript - import { - broadcast, - watch, - get, - onGet, - } from "https://assets.juno.global.cloud.sap/libs/communicator@latest/build/index.js" - ``` - -3. Via `importmap`: - - ```html - - - - ``` - -## Usage - -To use the library, you can import the necessary functions: - -```javascript -import { broadcast, watch, get, onGet } from "communicator" -``` - -### `broadcast(name, data, options) ⇒ void` - -Use this function to send messages via BroadcastChannel across different contexts, such as multiple tabs on the same origin. - -- `name` (required): The message name. -- `data` (required, null is allowed): The message data. -- `options` (optional): An object with options - - `debug` (boolean, false by default): Set this to `true` for debugging purposes. - - `crossWindow` (boolean, false by default): Set this to `true` to enable cross-window communication. - -Example: - -```javascript -import { broadcast } from "communicator" - -broadcast( - "AUTH_TOKEN_UPDATED", - { token: "TOKEN" }, - { - debug: true, - crossWindow: false, - } -) -``` - -### `watch(name, callback, options) ⇒ function` - -Register a listener for a specific message. Messages are observed across contexts. - -- `name` (required): The message name. -- `callback` (required): A function that is executed when a message is sent for the registered name. It should have the following signature: `(data, { sourceWindowId, thisWindowId }) => void`. - -For the `options` object, you can mention that it includes the following properties: - -- `debug` (boolean, false by default): Set this to `true` for debugging purposes. - -Example: - -```javascript -import { watch } from "communicator" - -const unwatch = watch( - "AUTH_TOKEN_UPDATED", - (data, { sourceWindowId, thisWindowId }) => { - // Receive message data - console.log(data) - }, - { - debug: false, // Default - } -) - -// To unregister the listener, call unwatch() -unwatch() -``` - -### `get(name, callback, options) ⇒ function` - -Request a message by name and receive the data with the callback. - -- `name` (required): The message name. -- `callback` (required): A function that is executed upon receiving a response. -- `options` (optional): An object with the following properties: - - `getOptions` (object): An object that allows customization of the get request. - - `debug` (boolean, false by default): Set this to `true` for debugging purposes. - -Example: - -```javascript -import { get } from "communicator" - -const cancel = get( - "AUTH_TOKEN_UPDATED", - (data, { sourceWindowId, thisWindowId }) => { - // Receive message data - console.log(data) - }, - { - debug: false, // Default - } -) - -// To cancel the request, call cancel() -cancel() -``` - -### `onGet(name, callback, options) ⇒ function` - -Use this function to respond to get messages. - -- `name` (required): The message name. -- `callback` (required): A function that is executed when get events occur and returns the data. -- `options` (optional): An object with the following properties: - - - `debug` (boolean, false by default): Set this to `true` for debugging purposes. - -Example: - -```javascript -import { onGet } from "communicator" - -const unwatch = onGet( - "AUTH_TOKEN_UPDATED", - (getOptions, { sourceWindowId, thisWindowId }) => { - // Return data - return { name: "test" } - }, - { - debug: false, // Default - } -) - -// To unregister the response, call unwatch() -unwatch() -``` diff --git a/libs_deprecated/communicator/dev/build.js b/libs_deprecated/communicator/dev/build.js deleted file mode 100644 index ce05871b9..000000000 --- a/libs_deprecated/communicator/dev/build.js +++ /dev/null @@ -1,183 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// src/index.js -var uniqString = () => Math.random().toString(36).substring(2); -window.__junoCommunicatorTabId = window.__junoCommunicatorTabId || uniqString(); -window.__junoEventListeners = window.__junoEventListeners || { - broadcast: {}, - get: {} -}; -var log = (...params) => console.log("Communicator Debug:", ...params); -var warn = (...params) => console.warn("Communicator Warning:", ...params); -var error = (...params) => console.error("Communicator Error:", ...params); -var addListener = (type, event, listener) => { - if (!window.__junoEventListeners[type]?.[event]) { - window.__junoEventListeners[type][event] = []; - } - window.__junoEventListeners[type][event].push(listener); -}; -var removeListener = (type, event, listener) => { - if (!window.__junoEventListeners[type]?.[event]) - return; - window.__junoEventListeners[type][event] = window.__junoEventListeners[type][event].filter((l) => l !== listener); -}; -var listenerWrapper = (callback) => (data, options = {}) => { - return new Promise(async (resolve) => { - callback(data, options); - resolve(); - }); -}; -if (typeof BroadcastChannel === "undefined") { - console.log( - "BroadcastChannel is not supported in this browser. Use fake BroadcastChannel." - ); - window.BroadcastChannel = function() { - return { - postMessage: () => null, - onmessage: () => null, - close: () => null - }; - }; -} else { - console.log("BroadcastChannel is supported in this browser."); -} -var crossWindowEventBridge = new BroadcastChannel( - "__JUNO_CROSS_WINDOW_EVENT_BRIDGE__" -); -crossWindowEventBridge.onmessage = (e) => { - const { type, name, data, sourceWindowId } = e.data || {}; - if (type === "broadcast") { - window.__junoEventListeners["broadcast"]?.[name]?.forEach((listener) => { - try { - listener(data, { - crossWindow: true, - sourceWindowId, - thisWindowId: window.__junoCommunicatorTabId - }); - } catch (e2) { - warn(e2); - } - }); - } -}; -var broadcast = (name, data, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(broadcast) the message name must be given."); - if (data === void 0) - data = null; - const { debug, crossWindow: crossWindow2 = false, ...unknownOptions } = options || {}; - const unknownOptionsKeys = Object.keys(unknownOptions); - if (unknownOptionsKeys.length > 0) - warn(`(broadcast) unknown options: ${unknownOptionsKeys.join(", ")}`); - if (debug != void 0 && typeof debug !== "boolean") - warn("(broadcast) debug must be a boolean"); - if (typeof crossWindow2 !== "boolean") - warn("(broadcast) crossWindow must be a boolean"); - if (debug) { - console.log("===================1"); - log( - `broadcast ${crossWindow2 ? "cross-window" : "intra-window"} message ${name} with data `, - data - ); - console.log("===================2"); - } - window.__junoEventListeners["broadcast"]?.[name]?.forEach((listener) => { - try { - listener(data, { - sourceWindowId: window.__junoCommunicatorTabId, - thisWindowId: window.__junoCommunicatorTabId - }); - } catch (e) { - warn(e); - } - }); - if (crossWindow2) { - crossWindowEventBridge.postMessage({ - type: "broadcast", - name, - data, - sourceWindowId: window.__junoCommunicatorTabId - }); - } - } catch (e) { - error(e.message); - } -}; -var watch = (name, callback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(watch) the message name must be given."); - if (typeof callback !== "function") - throw new Error("(watch) the callback parameter must be a function."); - const { debug, ...unknownOptions } = options || {}; - const unknownOptionsKeys = Object.keys(unknownOptions); - if (unknownOptionsKeys.length > 0) - warn(`(watch) unknown options: ${unknownOptionsKeys.join(", ")}`); - if (debug) - log( - `watch for ${crossWindow ? "cross-window" : "intra-window"} message ${name}` - ); - addListener("broadcast", name, listenerWrapper(callback)); - return () => removeListener("broadcast", name, listenerWrapper(callback)); - } catch (e) { - error(e.message); - } -}; -var get = (name, callback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(get) the message name must be given."); - if (typeof callback !== "function") - throw new Error("(get) the callback parameter must be a function."); - const { debug, getOptions, ...unknownOptions } = options || {}; - const unknownOptionsKeys = Object.keys(unknownOptions); - if (unknownOptionsKeys.length > 0) - warn(`(get) unknown options: ${unknownOptionsKeys.join(", ")}`); - if (debug) - log(`get data for intra-window message ${name}`); - if (window.__junoEventListeners["get"]?.[name]?.length === 0) - return; - window.__junoEventListeners["get"][name]?.forEach((listener) => { - try { - const data = listener(options?.getOptions); - callback(data, { - sourceWindowId: window.__junoCommunicatorTabId, - thisWindowId: window.__junoCommunicatorTabId - }); - } catch (e) { - warn(e); - } - }); - } catch (e) { - error(e.message); - } -}; -var onGet = (name, callback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(onGet) the message name must be given."); - if (typeof callback !== "function") - throw new Error("(onGet) the callback parameter must be a function."); - const { debug, crossWindow: crossWindow2 = false, ...unknownOptions } = options || {}; - const unknownOptionsKeys = Object.keys(unknownOptions); - if (unknownOptionsKeys.length > 0) - warn(`(onGet) unknown options: ${unknownOptionsKeys.join(", ")}`); - if (debug) - log(`send data for intra-window message ${name}`); - addListener("get", name, listenerWrapper(callback)); - return () => removeListener("get", name, listenerWrapper(callback)); - } catch (e) { - error(e.message); - } -}; -export { - broadcast, - get, - onGet, - watch -}; -//# sourceMappingURL=build.js.map diff --git a/libs_deprecated/communicator/dev/build.js.map b/libs_deprecated/communicator/dev/build.js.map deleted file mode 100644 index a537077c0..000000000 --- a/libs_deprecated/communicator/dev/build.js.map +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": 3, - "sources": ["../src/index.js"], - "sourcesContent": ["/**\n *\n * @returns epoch timestamp (count of seconds since 1970)\n */\nconst uniqString = () => Math.random().toString(36).substring(2)\n\n// create an uniq id for current window (current context)\n// this id is used to identify the current when intra-window communication is used\nwindow.__junoCommunicatorTabId = window.__junoCommunicatorTabId || uniqString()\n\nwindow.__junoEventListeners = window.__junoEventListeners || {\n broadcast: {},\n get: {},\n}\n\nconst log = (...params) => console.log(\"Communicator Debug:\", ...params)\nconst warn = (...params) => console.warn(\"Communicator Warning:\", ...params)\nconst error = (...params) => console.error(\"Communicator Error:\", ...params)\n\nconst addListener = (type, event, listener) => {\n if (!window.__junoEventListeners[type]?.[event]) {\n window.__junoEventListeners[type][event] = []\n }\n window.__junoEventListeners[type][event].push(listener)\n}\n\nconst removeListener = (type, event, listener) => {\n if (!window.__junoEventListeners[type]?.[event]) return\n window.__junoEventListeners[type][event] = window.__junoEventListeners[type][\n event\n ].filter((l) => l !== listener)\n}\n\nconst listenerWrapper =\n (callback) =>\n (data, options = {}) => {\n // Create a promise that will be resolved when the listener is executed\n return new Promise(async (resolve) => {\n callback(data, options)\n resolve()\n })\n }\n\nif (typeof BroadcastChannel === \"undefined\") {\n // BroadcastChannel is not available\n console.log(\n \"BroadcastChannel is not supported in this browser. Use fake BroadcastChannel.\"\n )\n window.BroadcastChannel = function () {\n return {\n postMessage: () => null,\n onmessage: () => null,\n close: () => null,\n }\n }\n} else {\n // BroadcastChannel is available\n console.log(\"BroadcastChannel is supported in this browser.\")\n}\n\nconst crossWindowEventBridge = new BroadcastChannel(\n \"__JUNO_CROSS_WINDOW_EVENT_BRIDGE__\"\n)\n\ncrossWindowEventBridge.onmessage = (e) => {\n const { type, name, data, sourceWindowId } = e.data || {}\n\n if (type === \"broadcast\") {\n window.__junoEventListeners[\"broadcast\"]?.[name]?.forEach((listener) => {\n try {\n listener(data, {\n crossWindow: true,\n sourceWindowId,\n thisWindowId: window.__junoCommunicatorTabId,\n })\n } catch (e) {\n warn(e)\n }\n })\n }\n}\n\n/**\n * Send messages via BroadcastChannel across contexts (e.g. several tabs on\n * the same origin). The last message is stored by default. However, it\n * is possible to influence the storage period using the expire option.\n * @param {string} name\n * @param {any} data\n * @param {object} options (optional) allowed options are debug:undefined|boolean and expires:undefined|number\n * @returns void\n */\nconst broadcast = (name, data, options = {}) => {\n try {\n if (typeof name !== \"string\")\n throw new Error(\"(broadcast) the message name must be given.\")\n if (data === undefined) data = null\n\n const { debug, crossWindow = false, ...unknownOptions } = options || {}\n const unknownOptionsKeys = Object.keys(unknownOptions)\n if (unknownOptionsKeys.length > 0)\n warn(`(broadcast) unknown options: ${unknownOptionsKeys.join(\", \")}`)\n if (debug != undefined && typeof debug !== \"boolean\")\n warn(\"(broadcast) debug must be a boolean\")\n if (typeof crossWindow !== \"boolean\")\n warn(\"(broadcast) crossWindow must be a boolean\")\n\n if (debug) {\n console.log(\"===================1\")\n log(\n `broadcast ${\n crossWindow ? \"cross-window\" : \"intra-window\"\n } message ${name} with data `,\n data\n )\n console.log(\"===================2\")\n }\n\n window.__junoEventListeners[\"broadcast\"]?.[name]?.forEach((listener) => {\n try {\n listener(data, {\n sourceWindowId: window.__junoCommunicatorTabId,\n thisWindowId: window.__junoCommunicatorTabId,\n })\n } catch (e) {\n warn(e)\n }\n })\n\n if (crossWindow) {\n crossWindowEventBridge.postMessage({\n type: \"broadcast\",\n name,\n data,\n sourceWindowId: window.__junoCommunicatorTabId,\n })\n }\n } catch (e) {\n error(e.message)\n }\n}\n\n/**\n * Register a listener for a specific message. Messages are observed\n * across contexts (e.g. several tabs on the same origin).\n * If a current saved message already exists for the name,\n * then the listener is executed immediately with this message.\n * The expires option set by the \"send\" method has an effect here.\n * In addition, the age of the listened messages can be determined\n * with the youngerThan option.\n * @param {string} name\n * @param {function} callback:(data) => void\n * @param {object} options\n * @returns {function} unregister:()=>void, a function to stop listening\n */\nconst watch = (name, callback, options = {}) => {\n try {\n if (typeof name !== \"string\")\n throw new Error(\"(watch) the message name must be given.\")\n if (typeof callback !== \"function\")\n throw new Error(\"(watch) the callback parameter must be a function.\")\n\n const { debug, ...unknownOptions } = options || {}\n const unknownOptionsKeys = Object.keys(unknownOptions)\n if (unknownOptionsKeys.length > 0)\n warn(`(watch) unknown options: ${unknownOptionsKeys.join(\", \")}`)\n\n if (debug)\n log(\n `watch for ${\n crossWindow ? \"cross-window\" : \"intra-window\"\n } message ${name}`\n )\n\n addListener(\"broadcast\", name, listenerWrapper(callback))\n\n return () => removeListener(\"broadcast\", name, listenerWrapper(callback))\n } catch (e) {\n error(e.message)\n }\n}\n\n/**\n * This function implements a 1:1 communication\n * @param {string} name\n * @param {function} callback\n * @param {object} options\n * @returns cancel function\n */\nconst get = (name, callback, options = {}) => {\n try {\n if (typeof name !== \"string\")\n throw new Error(\"(get) the message name must be given.\")\n if (typeof callback !== \"function\")\n throw new Error(\"(get) the callback parameter must be a function.\")\n const { debug, getOptions, ...unknownOptions } = options || {}\n const unknownOptionsKeys = Object.keys(unknownOptions)\n if (unknownOptionsKeys.length > 0)\n warn(`(get) unknown options: ${unknownOptionsKeys.join(\", \")}`)\n if (debug) log(`get data for intra-window message ${name}`)\n\n if (window.__junoEventListeners[\"get\"]?.[name]?.length === 0) return\n\n // console.log(\"==============get\", window.__junoEventListeners[\"get\"]?.[name])\n window.__junoEventListeners[\"get\"][name]?.forEach((listener) => {\n try {\n const data = listener(options?.getOptions)\n callback(data, {\n sourceWindowId: window.__junoCommunicatorTabId,\n thisWindowId: window.__junoCommunicatorTabId,\n })\n } catch (e) {\n warn(e)\n }\n })\n } catch (e) {\n error(e.message)\n }\n}\n\n/**\n * Listen to get messages\n * @param {string} name\n * @param {function} callback\n * @param {object} options\n * @returns cancel function\n */\nconst onGet = (name, callback, options = {}) => {\n try {\n if (typeof name !== \"string\")\n throw new Error(\"(onGet) the message name must be given.\")\n if (typeof callback !== \"function\")\n throw new Error(\"(onGet) the callback parameter must be a function.\")\n const { debug, crossWindow = false, ...unknownOptions } = options || {}\n const unknownOptionsKeys = Object.keys(unknownOptions)\n if (unknownOptionsKeys.length > 0)\n warn(`(onGet) unknown options: ${unknownOptionsKeys.join(\", \")}`)\n if (debug) log(`send data for intra-window message ${name}`)\n\n addListener(\"get\", name, listenerWrapper(callback))\n\n return () => removeListener(\"get\", name, listenerWrapper(callback))\n } catch (e) {\n error(e.message)\n }\n}\n\nexport { broadcast, watch, get, onGet }\n"], - "mappings": ";AAIA,IAAM,aAAa,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC;AAI/D,OAAO,0BAA0B,OAAO,2BAA2B,WAAW;AAE9E,OAAO,uBAAuB,OAAO,wBAAwB;AAAA,EAC3D,WAAW,CAAC;AAAA,EACZ,KAAK,CAAC;AACR;AAEA,IAAM,MAAM,IAAI,WAAW,QAAQ,IAAI,uBAAuB,GAAG,MAAM;AACvE,IAAM,OAAO,IAAI,WAAW,QAAQ,KAAK,yBAAyB,GAAG,MAAM;AAC3E,IAAM,QAAQ,IAAI,WAAW,QAAQ,MAAM,uBAAuB,GAAG,MAAM;AAE3E,IAAM,cAAc,CAAC,MAAM,OAAO,aAAa;AAC7C,MAAI,CAAC,OAAO,qBAAqB,IAAI,IAAI,KAAK,GAAG;AAC/C,WAAO,qBAAqB,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,EAC9C;AACA,SAAO,qBAAqB,IAAI,EAAE,KAAK,EAAE,KAAK,QAAQ;AACxD;AAEA,IAAM,iBAAiB,CAAC,MAAM,OAAO,aAAa;AAChD,MAAI,CAAC,OAAO,qBAAqB,IAAI,IAAI,KAAK;AAAG;AACjD,SAAO,qBAAqB,IAAI,EAAE,KAAK,IAAI,OAAO,qBAAqB,IAAI,EACzE,KACF,EAAE,OAAO,CAAC,MAAM,MAAM,QAAQ;AAChC;AAEA,IAAM,kBACJ,CAAC,aACD,CAAC,MAAM,UAAU,CAAC,MAAM;AAEtB,SAAO,IAAI,QAAQ,OAAO,YAAY;AACpC,aAAS,MAAM,OAAO;AACtB,YAAQ;AAAA,EACV,CAAC;AACH;AAEF,IAAI,OAAO,qBAAqB,aAAa;AAE3C,UAAQ;AAAA,IACN;AAAA,EACF;AACA,SAAO,mBAAmB,WAAY;AACpC,WAAO;AAAA,MACL,aAAa,MAAM;AAAA,MACnB,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF,OAAO;AAEL,UAAQ,IAAI,gDAAgD;AAC9D;AAEA,IAAM,yBAAyB,IAAI;AAAA,EACjC;AACF;AAEA,uBAAuB,YAAY,CAAC,MAAM;AACxC,QAAM,EAAE,MAAM,MAAM,MAAM,eAAe,IAAI,EAAE,QAAQ,CAAC;AAExD,MAAI,SAAS,aAAa;AACxB,WAAO,qBAAqB,WAAW,IAAI,IAAI,GAAG,QAAQ,CAAC,aAAa;AACtE,UAAI;AACF,iBAAS,MAAM;AAAA,UACb,aAAa;AAAA,UACb;AAAA,UACA,cAAc,OAAO;AAAA,QACvB,CAAC;AAAA,MACH,SAASA,IAAP;AACA,aAAKA,EAAC;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAWA,IAAM,YAAY,CAAC,MAAM,MAAM,UAAU,CAAC,MAAM;AAC9C,MAAI;AACF,QAAI,OAAO,SAAS;AAClB,YAAM,IAAI,MAAM,6CAA6C;AAC/D,QAAI,SAAS;AAAW,aAAO;AAE/B,UAAM,EAAE,OAAO,aAAAC,eAAc,OAAO,GAAG,eAAe,IAAI,WAAW,CAAC;AACtE,UAAM,qBAAqB,OAAO,KAAK,cAAc;AACrD,QAAI,mBAAmB,SAAS;AAC9B,WAAK,gCAAgC,mBAAmB,KAAK,IAAI,GAAG;AACtE,QAAI,SAAS,UAAa,OAAO,UAAU;AACzC,WAAK,qCAAqC;AAC5C,QAAI,OAAOA,iBAAgB;AACzB,WAAK,2CAA2C;AAElD,QAAI,OAAO;AACT,cAAQ,IAAI,sBAAsB;AAClC;AAAA,QACE,aACEA,eAAc,iBAAiB,0BACrB;AAAA,QACZ;AAAA,MACF;AACA,cAAQ,IAAI,sBAAsB;AAAA,IACpC;AAEA,WAAO,qBAAqB,WAAW,IAAI,IAAI,GAAG,QAAQ,CAAC,aAAa;AACtE,UAAI;AACF,iBAAS,MAAM;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB,cAAc,OAAO;AAAA,QACvB,CAAC;AAAA,MACH,SAAS,GAAP;AACA,aAAK,CAAC;AAAA,MACR;AAAA,IACF,CAAC;AAED,QAAIA,cAAa;AACf,6BAAuB,YAAY;AAAA,QACjC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,GAAP;AACA,UAAM,EAAE,OAAO;AAAA,EACjB;AACF;AAeA,IAAM,QAAQ,CAAC,MAAM,UAAU,UAAU,CAAC,MAAM;AAC9C,MAAI;AACF,QAAI,OAAO,SAAS;AAClB,YAAM,IAAI,MAAM,yCAAyC;AAC3D,QAAI,OAAO,aAAa;AACtB,YAAM,IAAI,MAAM,oDAAoD;AAEtE,UAAM,EAAE,OAAO,GAAG,eAAe,IAAI,WAAW,CAAC;AACjD,UAAM,qBAAqB,OAAO,KAAK,cAAc;AACrD,QAAI,mBAAmB,SAAS;AAC9B,WAAK,4BAA4B,mBAAmB,KAAK,IAAI,GAAG;AAElE,QAAI;AACF;AAAA,QACE,aACE,cAAc,iBAAiB,0BACrB;AAAA,MACd;AAEF,gBAAY,aAAa,MAAM,gBAAgB,QAAQ,CAAC;AAExD,WAAO,MAAM,eAAe,aAAa,MAAM,gBAAgB,QAAQ,CAAC;AAAA,EAC1E,SAAS,GAAP;AACA,UAAM,EAAE,OAAO;AAAA,EACjB;AACF;AASA,IAAM,MAAM,CAAC,MAAM,UAAU,UAAU,CAAC,MAAM;AAC5C,MAAI;AACF,QAAI,OAAO,SAAS;AAClB,YAAM,IAAI,MAAM,uCAAuC;AACzD,QAAI,OAAO,aAAa;AACtB,YAAM,IAAI,MAAM,kDAAkD;AACpE,UAAM,EAAE,OAAO,YAAY,GAAG,eAAe,IAAI,WAAW,CAAC;AAC7D,UAAM,qBAAqB,OAAO,KAAK,cAAc;AACrD,QAAI,mBAAmB,SAAS;AAC9B,WAAK,0BAA0B,mBAAmB,KAAK,IAAI,GAAG;AAChE,QAAI;AAAO,UAAI,qCAAqC,MAAM;AAE1D,QAAI,OAAO,qBAAqB,KAAK,IAAI,IAAI,GAAG,WAAW;AAAG;AAG9D,WAAO,qBAAqB,KAAK,EAAE,IAAI,GAAG,QAAQ,CAAC,aAAa;AAC9D,UAAI;AACF,cAAM,OAAO,SAAS,SAAS,UAAU;AACzC,iBAAS,MAAM;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB,cAAc,OAAO;AAAA,QACvB,CAAC;AAAA,MACH,SAAS,GAAP;AACA,aAAK,CAAC;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH,SAAS,GAAP;AACA,UAAM,EAAE,OAAO;AAAA,EACjB;AACF;AASA,IAAM,QAAQ,CAAC,MAAM,UAAU,UAAU,CAAC,MAAM;AAC9C,MAAI;AACF,QAAI,OAAO,SAAS;AAClB,YAAM,IAAI,MAAM,yCAAyC;AAC3D,QAAI,OAAO,aAAa;AACtB,YAAM,IAAI,MAAM,oDAAoD;AACtE,UAAM,EAAE,OAAO,aAAAA,eAAc,OAAO,GAAG,eAAe,IAAI,WAAW,CAAC;AACtE,UAAM,qBAAqB,OAAO,KAAK,cAAc;AACrD,QAAI,mBAAmB,SAAS;AAC9B,WAAK,4BAA4B,mBAAmB,KAAK,IAAI,GAAG;AAClE,QAAI;AAAO,UAAI,sCAAsC,MAAM;AAE3D,gBAAY,OAAO,MAAM,gBAAgB,QAAQ,CAAC;AAElD,WAAO,MAAM,eAAe,OAAO,MAAM,gBAAgB,QAAQ,CAAC;AAAA,EACpE,SAAS,GAAP;AACA,UAAM,EAAE,OAAO;AAAA,EACjB;AACF;", - "names": ["e", "crossWindow"] -} diff --git a/libs_deprecated/communicator/dev/index.html b/libs_deprecated/communicator/dev/index.html deleted file mode 100644 index e21248f37..000000000 --- a/libs_deprecated/communicator/dev/index.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - Communicator Dev - - - - - -

Communicator Dev Test

-
- - diff --git a/libs_deprecated/communicator/dev/index.js b/libs_deprecated/communicator/dev/index.js deleted file mode 100644 index 1f02658e6..000000000 --- a/libs_deprecated/communicator/dev/index.js +++ /dev/null @@ -1,170 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const buttonCss = - "padding: 10px; margin: 0 10px; background-color: rgb(67 75 95); border: 1px solid rgb(67 75 95); color: white; border-radius: 5px; cursor: pointer" -const displayCss = "margin: 20px 10px 0 10px;" - -import("./build.js").then(({ broadcast, watch, get, onGet }) => { - console.log("================READY") - - self.broadcast = broadcast - self.watch = watch - self.get = get - self.onGet = onGet - - const root = document.getElementById("root") - - Tester(root) -}) - -const logTemplate = ({ source, target, text, data }) => ` -
-
- Date: ${new Date().toLocaleString()} - Source tab: ${source} - Target tab: ${target} -
-

${text}

-
- ${JSON.stringify(data, null, 2)} -
-
` - -const Tester = (root) => { - const buttonGet = document.createElement("button") - const buttonBroadcast = document.createElement("button") - const buttonGetIntraWindow = document.createElement("button") - const buttonBroadcastIntraWindow = document.createElement("button") - - buttonGet.style.cssText = buttonCss - buttonBroadcast.style.cssText = buttonCss - buttonGetIntraWindow.style.cssText = buttonCss - buttonBroadcastIntraWindow.style.cssText = buttonCss - - const display = document.createElement("div") - display.style.cssText = displayCss - const header = `
Log
` - display.innerHTML = header - const content = document.createElement("div") - content.id = "content" - display.appendChild(content) - - const log = (source, target, text, data) => { - content.innerHTML = `${content.innerHTML}
${logTemplate({ - source, - target, - text, - data, - })}` - } - - watch( - "TEST_BROADCAST", - (data, { sourceWindowId, thisWindowId }) => { - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (watch): receive data for event TEST_BROADCAST from ${sourceWindowId}`, - data - ) - }, - { crossWindow: true } - ) - - watch( - "TEST_BROADCAST_INTRA_WINDOW", - (data, { sourceWindowId, thisWindowId }) => { - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (watch): receive data for event TEST_BROADCAST_INTRA_WINDOW from ${sourceWindowId}`, - data - ) - } - ) - - onGet( - "TEST_GET", - (getOptions, { sourceWindowId, thisWindowId }) => { - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (onGet): send data for event TEST_GET to ${sourceWindowId}`, - getOptions - ) - return `data for event TEST_GET` - }, - { crossWindow: true, debug: false } - ) - - onGet( - "TEST_GET_INTRA_WINDOW", - (getOptions, { sourceWindowId, thisWindowId }) => { - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (onGet): send data for event TEST_GET_INTRA_WINDOW to ${sourceWindowId}`, - getOptions - ) - return `data for event TEST_GET_INTRA_WINDOW` - } - ) - - buttonGet.innerHTML = "GET (CROSS WINDOW)" - buttonGet.addEventListener("click", () => { - log("", "", `Requesting data for event TEST_GET`, "") - get( - "TEST_GET", - (data, { sourceWindowId, thisWindowId }) => - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (get): receive data for event TEST_GET from ${sourceWindowId}`, - data - ), - { - debug: false, - crossWindow: true, - } - ) - }) - - buttonBroadcast.innerHTML = "BROADCAST (CROSS WINDOW)" - buttonBroadcast.addEventListener("click", () => { - log("", "", `Broadcasting data for event TEST_BROADCAST`, "") - broadcast("TEST_BROADCAST", `TEST_BROADCAST_DATA`, { - debug: false, - crossWindow: true, - }) - }) - - buttonGetIntraWindow.innerHTML = "GET (INTRA WINDOW)" - buttonGetIntraWindow.addEventListener("click", () => { - log("", "", `Requesting data for event TEST_GET_INTRA_WINDOW`, "") - get("TEST_GET_INTRA_WINDOW", (data, { sourceWindowId, thisWindowId }) => - log( - sourceWindowId, - thisWindowId, - `${thisWindowId} (get): receive data for event TEST_GET_INTRA_WINDOW from ${sourceWindowId}`, - data - ) - ) - }) - - buttonBroadcastIntraWindow.innerHTML = "BROADCAST (INTRA WINDOW)" - buttonBroadcastIntraWindow.addEventListener("click", () => { - log("", "", `Broadcasting data for event TEST_BROADCAST_INTRA_WINDOW`, "") - broadcast("TEST_BROADCAST_INTRA_WINDOW", `TEST_BROADCAST_INTRA_WINDOW_DATA`) - }) - - root.appendChild(buttonGet) - root.appendChild(buttonBroadcast) - root.appendChild(buttonGetIntraWindow) - root.appendChild(buttonBroadcastIntraWindow) - - root.appendChild(display) - //console.log(root) -} diff --git a/libs_deprecated/communicator/esbuild.config.js b/libs_deprecated/communicator/esbuild.config.js deleted file mode 100644 index b2bd17d78..000000000 --- a/libs_deprecated/communicator/esbuild.config.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const esbuild = require("esbuild") -const pkg = require("./package.json") - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) - -const isProduction = process.env.NODE_ENV === "production" -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" -const DEV_FOLDER = "dev" -const outfile = isProduction ? pkg.module : `${DEV_FOLDER}/build.js` -const args = process.argv.slice(2) -const watch = args.indexOf("--watch") >= 0 - -esbuild - .context({ - entryPoints: [pkg.source], - outfile, - bundle: true, - minify: isProduction, - target: ["es2020"], - format: "esm", - sourcemap: true, - external: - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [], - }) - .then(async (ctx) => { - if (watch) { - ctx.watch() - console.log("watching...") - ctx - .serve({ - host: "0.0.0.0", - port: parseInt(process.env.APP_PORT), - servedir: DEV_FOLDER, - }) - .then(({ host, port }) => console.log("serve on", `${host}:${port}`)) - } else { - await ctx.rebuild() - await ctx.dispose() - } - }) - .catch((error) => console.error(error)) diff --git a/libs_deprecated/communicator/package.json b/libs_deprecated/communicator/package.json deleted file mode 100644 index d0f1adb67..000000000 --- a/libs_deprecated/communicator/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "communicator", - "version": "2.2.6", - "description": "Send and receive across tabs", - "author": "UI-Team", - "contributors": [ - "Andreas Pfau" - ], - "repository": "https://github.com/sapcc/juno/tree/main/libs/communicator", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/juno for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "source": "src/index.js", - "main": "build/index.js", - "module": "build/index.js", - "scripts": { - "dev": "NODE_ENV=development node ./esbuild.config.js --watch", - "build": "NODE_ENV=production node ./esbuild.config.js", - "test": "jest", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "predev": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "devDependencies": { - "@babel/preset-env": "^7.20.2", - "babel-jest": "^29.4.2", - "esbuild": "^0.17.6", - "jest": "^29.4.2" - }, - "babel": { - "presets": [ - "@babel/preset-env" - ] - }, - "jest": { - "testEnvironment": "jsdom", - "verbose": true, - "transform": { - "\\.js$": "babel-jest" - }, - "watchPathIgnorePatterns": [ - "/dev/", - "/build/" - ] - } -} diff --git a/libs_deprecated/communicator/src/index.js b/libs_deprecated/communicator/src/index.js deleted file mode 100644 index 2ab3fec20..000000000 --- a/libs_deprecated/communicator/src/index.js +++ /dev/null @@ -1,290 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const CHANNEL_PREFIX = "JUNO_COMMUNICATOR#" -/** - * - * @returns epoch timestamp (count of seconds since 1970) - */ -const uniqString = () => Math.random().toString(36).substring(2) - -// create an uniq id for current window (current context) -// this id is used to identify the current when intra-window communication is used -window.__junoCommunicatorTabId = window.__junoCommunicatorTabId || uniqString() - -window.__junoEventListeners = window.__junoEventListeners || { - broadcast: {}, - get: {}, -} - -const log = (...params) => console.log("Communicator Debug:", ...params) -const warn = (...params) => console.warn("Communicator Warning:", ...params) -const error = (...params) => console.error("Communicator Error:", ...params) - -const addListener = (type, event, listener) => { - if (!window.__junoEventListeners[type]?.[event]) { - window.__junoEventListeners[type][event] = [] - } - window.__junoEventListeners[type][event].push(listener) -} - -const removeListener = (type, event, listener) => { - if (!window.__junoEventListeners[type]?.[event]) return - window.__junoEventListeners[type][event] = window.__junoEventListeners[type][ - event - ].filter((l) => l !== listener) -} - -// encapsulate the listener in a wrapper that returns a promise -// we don't want to wait for the listener to be executed -const listenerWrapper = - (callback) => - (data, options = {}) => { - // Create a promise that will be resolved when the listener is executed - return new Promise(async (resolve) => { - const result = callback(data, options) - resolve(result) - }) - } - -if (typeof BroadcastChannel === "undefined") { - // BroadcastChannel is not available - console.log( - "BroadcastChannel is not supported in this browser. Use fake BroadcastChannel." - ) - window.BroadcastChannel = function () { - return { - postMessage: () => null, - onmessage: () => null, - close: () => null, - } - } -} else { - // BroadcastChannel is available - console.log("BroadcastChannel is supported in this browser.") -} - -const crossWindowEventBridge = new BroadcastChannel( - "__JUNO_CROSS_WINDOW_EVENT_BRIDGE__" -) - -crossWindowEventBridge.onmessage = (e) => { - const { type, name, data, sourceWindowId } = e.data || {} - - if (type === "broadcast") { - window.__junoEventListeners["broadcast"]?.[name]?.forEach((listener) => { - try { - listener(data, { - crossWindow: true, - sourceWindowId, - thisWindowId: window.__junoCommunicatorTabId, - }) - } catch (e) { - warn(e) - } - }) - } -} - -/** - * Send messages via BroadcastChannel across contexts (e.g. several tabs on - * the same origin). The last message is stored by default. However, it - * is possible to influence the storage period using the expire option. - * @param {string} name - * @param {any} data - * @param {object} options (optional) allowed options are debug:undefined|boolean and expires:undefined|number - * @returns void - */ -const broadcast = (name, data, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(broadcast) the message name must be given.") - if (data === undefined) data = null - - const { - debug, - crossWindow = false, - consumerID, - ...unknownOptions - } = options || {} - const unknownOptionsKeys = Object.keys(unknownOptions) - if (unknownOptionsKeys.length > 0) - warn(`(broadcast) unknown options: ${unknownOptionsKeys.join(", ")}`) - if (debug != undefined && typeof debug !== "boolean") - warn("(broadcast) debug must be a boolean") - if (typeof crossWindow !== "boolean") - warn("(broadcast) crossWindow must be a boolean") - - // backward compatibility - name = CHANNEL_PREFIX + name - - if (debug) { - log( - `${consumerID ? `(${consumerID})` : ""} broadcast ${ - crossWindow ? "cross-window" : "intra-window" - } message ${name} with data `, - data - ) - // log(`${consumerID ? `(${consumerID})` : ""} broadcast EVENT: ${name}`) - } - - window.__junoEventListeners["broadcast"]?.[name]?.forEach((listener) => { - try { - listener(data, { - sourceWindowId: window.__junoCommunicatorTabId, - thisWindowId: window.__junoCommunicatorTabId, - }) - } catch (e) { - warn(e) - } - }) - - if (crossWindow) { - crossWindowEventBridge.postMessage({ - type: "broadcast", - name, - data, - sourceWindowId: window.__junoCommunicatorTabId, - }) - } - } catch (e) { - error(e.message) - } -} - -/** - * Register a listener for a specific message. Messages are observed - * across contexts (e.g. several tabs on the same origin). - * If a current saved message already exists for the name, - * then the listener is executed immediately with this message. - * The expires option set by the "send" method has an effect here. - * In addition, the age of the listened messages can be determined - * with the youngerThan option. - * @param {string} name - * @param {function} callback:(data) => void - * @param {object} options - * @returns {function} unregister:()=>void, a function to stop listening - */ -const watch = (name, callback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(watch) the message name must be given.") - if (typeof callback !== "function") - throw new Error("(watch) the callback parameter must be a function.") - - const { debug, consumerID, ...unknownOptions } = options || {} - const unknownOptionsKeys = Object.keys(unknownOptions) - if (unknownOptionsKeys.length > 0) - warn(`(watch) unknown options: ${unknownOptionsKeys.join(", ")}`) - - // backward compatibility - name = CHANNEL_PREFIX + name - - if (debug) { - log(`${consumerID ? `(${consumerID})` : ""} watch for message ${name}`) - // log(`${consumerID ? `(${consumerID})` : ""} watch EVENT: ${name}`) - } - - addListener("broadcast", name, listenerWrapper(callback)) - - return () => removeListener("broadcast", name, listenerWrapper(callback)) - } catch (e) { - error(e.message) - } -} - -/** - * This function implements a 1:1 communication - * @param {string} name - * @param {function} callback - * @param {object} options - * @returns cancel function - */ -const get = (name, callback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(get) the message name must be given.") - if (typeof callback !== "function") - throw new Error("(get) the callback parameter must be a function.") - const { debug, getOptions, consumerID, ...unknownOptions } = options || {} - const unknownOptionsKeys = Object.keys(unknownOptions) - if (unknownOptionsKeys.length > 0) - warn(`(get) unknown options: ${unknownOptionsKeys.join(", ")}`) - - // backward compatibility - name = CHANNEL_PREFIX + "GET:" + name - - if (debug) { - log( - `${ - consumerID ? `(${consumerID})` : "" - } get data for intra-window message ${name}` - ) - // log(`${consumerID ? `(${consumerID})` : ""} get EVENT: ${name}`) - } - - if (window.__junoEventListeners["get"]?.[name]?.length === 0) return - - // console.log("==============get", window.__junoEventListeners["get"]?.[name]) - window.__junoEventListeners["get"][name]?.forEach((onGetListener) => { - try { - // get data from onGetListener - onGetListener(options?.getOptions).then((data) => { - callback(data, { - sourceWindowId: window.__junoCommunicatorTabId, - thisWindowId: window.__junoCommunicatorTabId, - }) - }) - } catch (e) { - warn(e) - } - }) - } catch (e) { - error(e.message) - } -} - -/** - * Listen to get messages - * @param {string} name - * @param {function} callback - * @param {object} options - * @returns cancel function - */ -const onGet = (name, getDataCallback, options = {}) => { - try { - if (typeof name !== "string") - throw new Error("(onGet) the message name must be given.") - if (typeof getDataCallback !== "function") - throw new Error("(onGet) the callback parameter must be a function.") - const { debug, consumerID, ...unknownOptions } = options || {} - const unknownOptionsKeys = Object.keys(unknownOptions) - if (unknownOptionsKeys.length > 0) - warn(`(onGet) unknown options: ${unknownOptionsKeys.join(", ")}`) - - // backward compatibility - name = CHANNEL_PREFIX + "GET:" + name - - if (debug) { - log( - `${ - consumerID ? `(${consumerID})` : "" - } send data for intra-window message ${name}` - ) - // log(`${consumerID ? `(${consumerID})` : ""} onGet EVENT: ${name}`) - } - - // is a function (data, options = {}) => data - const onGetListener = listenerWrapper(getDataCallback) - - addListener("get", name, onGetListener) - - return () => removeListener("get", name, listenerWrapper(getDataCallback)) - } catch (e) { - error(e.message) - } -} - -export { broadcast, watch, get, onGet } diff --git a/libs_deprecated/communicator/src/index.test.js b/libs_deprecated/communicator/src/index.test.js deleted file mode 100644 index 16f011ef6..000000000 --- a/libs_deprecated/communicator/src/index.test.js +++ /dev/null @@ -1,216 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -test("HI", () => expect(true).toEqual(true)) -globalThis.console.log = jest.fn() -globalThis.console.warn = jest.fn() -globalThis.console.error = jest.fn() - -const bc = { - postMessage: jest.fn(), - close: jest.fn(() => true), -} - -globalThis.BroadcastChannel = jest.fn().mockImplementation(() => { - return bc -}) - -const { broadcast, watch, get, onGet } = require("./index") - -describe("Communicator", () => { - afterEach(() => { - jest.clearAllMocks() - }) - - // ################ BROADCAST ##################### - describe("broadcast", () => { - test("log error on missing name", () => { - broadcast() - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(broadcast) the message name must be given." - ) - }) - test("log warning on missing data", () => { - let callback = jest.fn() - watch("TEST", callback) - broadcast("TEST", "data") - expect(callback).toHaveBeenCalledWith("data", { - sourceWindowId: expect.anything(), - thisWindowId: expect.anything(), - }) - }) - - test("unknown options", () => { - broadcast("TEST", { test: "test" }, { unknownOption: true }) - expect(globalThis.console.warn).toHaveBeenCalledWith( - "Communicator Warning:", - "(broadcast) unknown options: unknownOption" - ) - }) - - test("create new broadcast channel", () => { - let callback = jest.fn() - watch("TEST_12345", callback) - broadcast("TEST_12345", { name: "test" }) - expect(callback).toHaveBeenCalledWith({ name: "test" }, expect.anything()) - }) - - test("include options in message payload", () => { - let callback = jest.fn() - watch("TEST_123456", callback) - broadcast("TEST_123456", { name: "test" }, { debug: true }) - expect(callback).toHaveBeenCalledWith( - { name: "test" }, - { sourceWindowId: expect.anything(), thisWindowId: expect.anything() } - ) - }) - - test("log error if wrong debug value", () => { - broadcast("TEST", { name: "test" }, { debug: "true" }) - - expect(globalThis.console.warn).toHaveBeenCalledWith( - "Communicator Warning:", - "(broadcast) debug must be a boolean" - ) - }) - - test("close channel after broadcast", () => { - broadcast("TEST", { name: "test" }, { crossWindow: true }) - - expect(bc.postMessage).toHaveBeenCalled() - }) - }) - - // ################## WATCH ################### - describe("watch", () => { - test("log error on missing name", () => { - watch() - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(watch) the message name must be given." - ) - }) - test("log error on missing callback", () => { - watch("TEST") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(watch) the callback parameter must be a function." - ) - }) - - test("log error if callback is not a function", () => { - watch("TEST", "callback") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(watch) the callback parameter must be a function." - ) - }) - - test("unknown options", () => { - watch("TEST", () => null, { unknownOption: true }) - expect(globalThis.console.warn).toHaveBeenCalledWith( - "Communicator Warning:", - "(watch) unknown options: unknownOption" - ) - }) - - test("watch for events", () => { - let callback = jest.fn() - watch("TEST", callback) - broadcast("TEST") - expect(callback).toHaveBeenCalled() - }) - - test("multiple watchers", () => { - let callback1 = jest.fn() - let callback2 = jest.fn() - watch("TEST", callback1) - watch("TEST", callback2) - broadcast("TEST") - expect(callback1).toHaveBeenCalled() - expect(callback2).toHaveBeenCalled() - }) - }) - - // ############### GET ################## - describe("get", () => { - test("log error on missing name", () => { - get() - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(get) the message name must be given." - ) - }) - test("log error on missing callback", () => { - get("TEST") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(get) the callback parameter must be a function." - ) - }) - - test("log error if callback is not a function", () => { - get("TEST", "callback") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(get) the callback parameter must be a function." - ) - }) - - test("unknown options", () => { - get("TEST", () => null, { unknownOption: true }) - expect(globalThis.console.warn).toHaveBeenCalledWith( - "Communicator Warning:", - "(get) unknown options: unknownOption" - ) - }) - - test("execute callback", () => { - let callback = jest.fn() - onGet("TEST_12345", callback) - get("TEST_12345", callback) - expect(callback).toHaveBeenCalled() - }) - }) - - // ############### ON GET ################## - describe("onGet", () => { - test("log error on missing name", () => { - onGet() - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(onGet) the message name must be given." - ) - }) - - test("log error on missing callback", () => { - onGet("TEST") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(onGet) the callback parameter must be a function." - ) - }) - test("log error if callback is not a function", () => { - onGet("TEST", "callback") - expect(globalThis.console.error).toHaveBeenCalledWith( - "Communicator Error:", - "(onGet) the callback parameter must be a function." - ) - }) - test("unknown options", () => { - onGet("TEST", () => null, { unknownOption: true }) - expect(globalThis.console.warn).toHaveBeenCalledWith( - "Communicator Warning:", - "(onGet) unknown options: unknownOption" - ) - }) - - test("returns a function", () => { - const cancel = onGet("TEST", () => null) - expect(typeof cancel).toEqual("function") - }) - }) -}) diff --git a/libs_deprecated/juno-ui-components/.gitignore b/libs_deprecated/juno-ui-components/.gitignore deleted file mode 100644 index 15003e7a7..000000000 --- a/libs_deprecated/juno-ui-components/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/build -/node_modules -/storybook-static diff --git a/libs_deprecated/juno-ui-components/.npmignore b/libs_deprecated/juno-ui-components/.npmignore deleted file mode 100644 index 7a4b23010..000000000 --- a/libs_deprecated/juno-ui-components/.npmignore +++ /dev/null @@ -1,9 +0,0 @@ -.storybook -src -test -.babelrc -.gitignore -.npm -postcss.config.js -rollup* -setupTests diff --git a/libs_deprecated/juno-ui-components/.storybook/.babelrc b/libs_deprecated/juno-ui-components/.storybook/.babelrc deleted file mode 100644 index 7f27b1c49..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -{ - "presets": ["@babel/env", "@babel/preset-react"] -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/Decorator.jsx b/libs_deprecated/juno-ui-components/.storybook/juno-addon/Decorator.jsx deleted file mode 100644 index ea91cbe92..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/Decorator.jsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import "../../src/global.scss" -import { StyleProvider } from "../../src/components/StyleProvider" -import { ContentContainer } from "../../src/components/ContentContainer/index" -import { Container } from "../../src/components/Container/index" -import React, { useEffect } from "react" -import { useChannel, addons } from "@storybook/preview-api" -import { getCurrentTheme, getCurrentThemeMode } from "./themes" - -const fixBodyBg = () => { - document.body.style.setProperty( - "background-color", - getCurrentTheme().appContentBg, - "important" - ) -} - -fixBodyBg() - -export default (Story, context) => { - const [theme, setTheme] = React.useState("theme-" + getCurrentThemeMode()) - - useEffect(() => { - const updateThemeClass = (mode) => { - // console.log("=======UPDATE JUNO THEME CLASS=======", mode) - setTheme(`theme-${mode}`) - fixBodyBg() - } - const channel = addons.getChannel() - if (channel) { - channel.on("JUNO_THEME_CHANGE", updateThemeClass) - } - updateThemeClass(getCurrentThemeMode()) - return () => { - if (channel) channel.off("JUNO_THEME_CHANGE", updateThemeClass) - } - }, []) - - return ( - - - - - - - - ) -} diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/DocsContainer.jsx b/libs_deprecated/juno-ui-components/.storybook/juno-addon/DocsContainer.jsx deleted file mode 100644 index 58d319b46..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/DocsContainer.jsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { DocsContainer as BaseContainer } from "@storybook/addon-docs" -import { JUNO_THEME_CHANGE } from "./constants" -import { getCurrentTheme } from "./themes" - -export default ({ theme, ...props }) => { - // store the current theme in state so that we can update the theme when the theme changes - const [currentTheme, setCurrentTheme] = React.useState(getCurrentTheme()) - - // listen for theme change events and update the theme in state - React.useEffect(() => { - const updateDocsTheme = (mode) => setCurrentTheme(getCurrentTheme()) - - // get channel from context and listen to our custom event - // the event is emitted from the theme toggle tool - const channel = props.context?.channel - if (channel) { - channel.on(JUNO_THEME_CHANGE, updateDocsTheme) - } - return () => { - // remove the listener when the component unmounts - if (channel) channel.off(JUNO_THEME_CHANGE, updateDocsTheme) - } - }, []) - - return -} diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/README.md b/libs_deprecated/juno-ui-components/.storybook/juno-addon/README.md deleted file mode 100644 index 608710e39..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Juno UI Theme Switcher Addon for Storybook - -## Overview - -The **Juno UI Theme Switcher** is a Storybook addon designed specifically for Juno UI. It provides a seamless way to switch between dark and light themes, not just within the preview section but globally throughout your Storybook environment. This powerful addon ensures that your UI components are presented in the right theme, making it an essential tool for development and testing. - -## How It Works - -### 1. Conversion of Variables.scss - -The process begins with the conversion of the `Variables.scss` file into CSS. The resulting CSS file is then placed in a static folder named "assets." This conversion and file placement take place within the `main.js` file. The `Variables.css` file contains color variables for both dark and light modes. - -### 2. Theme Selection - -The theme is selected based on the class added to the `` element. When the class `theme-dark` is applied, the dark theme variables are used. Conversely, when `theme-light` is applied, the light theme variables are used. - -### 3. Integration with Storybook - -The Theme Switcher addon integrates with Storybook through various components: - -#### - Link Element in Manager UI - -Using the DOM API, a link element is added to the Manager UI of Storybook. This link element loads the CSS variables required for the selected theme. Simultaneously, the appropriate theme class is added to the ``. - -#### - Theme Switcher Button - -The addon defines a Theme Switcher button. When this button is clicked, it changes the theme class in the Manager UI and sends an event with the new theme mode using the Channel API. This process occurs in the `manager.js` file. - -#### - Variables in Preview Part - -In the Preview section (`preview.js`), the Variables CSS file is loaded into the `` of the iframe using a link tag. The corresponding theme class is applied to the ``. Additionally, a listener is defined using the Channel API, which listens for Theme Change Events triggered in the Manager UI. It dynamically updates the theme class in the Preview section to match the selected theme. - -### 4. Theme-Aware Decorator - -In addition to the theme switching functionality, the Theme Switcher addon defines a decorator. This decorator serves two crucial purposes: - -- **Styles for Juno Components**: Juno components are encapsulated within the shadow root by default. This means styles must be applied within the Shadow DOM. The decorator uses a StyleProvider from Juno UI to supply styles to Juno components, ensuring they are rendered correctly. - -- **Dynamic Theme Mode**: The decorator also listens for theme mode changes and updates the theme mode within the StyleProvider, ensuring that Juno components are always styled correctly for the selected theme. - -With the Juno UI Theme Switcher addon for Storybook, you can efficiently develop and test your Juno UI components in the desired theme, enhancing your workflow and user interface testing. diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/ThemeToggle.jsx b/libs_deprecated/juno-ui-components/.storybook/juno-addon/ThemeToggle.jsx deleted file mode 100644 index 35f0b2dbc..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/ThemeToggle.jsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { addons, types } from "@storybook/manager-api" -const ADDON_ID = "juno-addon" -const TOOL_ID = `${ADDON_ID}/theme-toggle` -import { Icons, IconButton } from "@storybook/components" -import { JUNO_THEME_CHANGE } from "./constants" -import { dark, getCurrentThemeMode, light, setCurrentThemeMode } from "./themes" - -addons.register(ADDON_ID, (api) => { - addons.add(TOOL_ID, { - type: types.TOOL, - title: "Toggle Dark Mode", - matches: ({ viewMode }) => viewMode === "story" || viewMode === "docs", - - render: () => { - const [mode, setMode] = React.useState(getCurrentThemeMode()) - - const toggleTheme = React.useCallback(() => { - const newMode = mode === "dark" ? "light" : "dark" - api.emit(JUNO_THEME_CHANGE, newMode) - setMode(newMode) - setCurrentThemeMode(newMode) - api.setOptions({ - theme: newMode === "dark" ? dark : light, - }) - }, [mode]) - - return ( - { - toggleTheme() - }} - > - - - ) - }, - }) -}) diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/constants.js b/libs_deprecated/juno-ui-components/.storybook/juno-addon/constants.js deleted file mode 100644 index f6b409c92..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/constants.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// export const THEME_PARAM_KEY = "junoThemeMode" -export const STORAGE_KEY = "__junoThemeMode" - -export const JUNO_THEME_CHANGE = "JUNO_THEME_CHANGE" - -export const ICON_DATA_URL = - "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEuNzEwNzIgMEMwLjc2NTkxNiAwIDAgMC43NjU5MTQgMCAxLjcxMDcyVjQ4LjI4OTNDMCA0OS4yMzQxIDAuNzY1OTE0IDUwIDEuNzEwNzIgNTBIOC42MDE2M0M2Ljg4NjIgNDcuODYgNS44NjAxMSA0NS4xNDM2IDUuODYwMTEgNDIuMTg3NkM1Ljg2MDExIDM1LjgxMTkgMTAuNjMzNSAzMC41NTEgMTYuODAxNSAyOS43ODM4QzE3LjU3NzUgMjMuMTMxNSAyMy4yMzIzIDE3Ljk2ODkgMzAuMDkyOSAxNy45Njg5QzM0LjgzNDQgMTcuOTY4OSAzOSAyMC40MzQ4IDQxLjM3NzEgMjQuMTU0MUM0Mi4zMTM1IDIzLjk1OTYgNDMuMjgzNyAyMy44NTczIDQ0LjI3NzggMjMuODU3M0M0Ni4zMTM5IDIzLjg1NzMgNDguMjQ5OCAyNC4yODYzIDUwIDI1LjA1ODhWMS43MTA3MkM1MCAwLjc2NTkxNiA0OS4yMzQxIDAgNDguMjg5MyAwSDEuNzEwNzJaTTUwIDI4LjkyNDFDNDguMzQyNCAyNy44ODE3IDQ2LjM4MDUgMjcuMjc4OCA0NC4yNzc4IDI3LjI3ODhDNDMuNTE4OSAyNy4yNzg4IDQyLjc4MiAyNy4zNTY4IDQyLjA3MzIgMjcuNTA0TDM5Ljc2NDIgMjcuOTgzOEwzOC40OTQyIDI1Ljk5NjdDMzYuNzE5MiAyMy4yMTk0IDMzLjYxODUgMjEuMzkwMyAzMC4wOTI5IDIxLjM5MDNDMjQuOTg4OCAyMS4zOTAzIDIwLjc3NzEgMjUuMjMyMyAyMC4xOTk5IDMwLjE4MDNMMTkuODg4NyAzMi44NDc2TDE3LjIyMzggMzMuMTc5MUMxMi43NDc2IDMzLjczNTkgOS4yODE1NSAzNy41NTk2IDkuMjgxNTUgNDIuMTg3NkM5LjI4MTU1IDQ1LjUwOSAxMS4wNjcxIDQ4LjQxNzQgMTMuNzMxMSA1MEg0OC4yODkzQzQ5LjIzNDEgNTAgNTAgNDkuMjM0MSA1MCA0OC4yODkzVjI4LjkyNDFaIiBmaWxsPSIjRjBBQjAwIj48L3BhdGg+PC9zdmc+" -export const LOGO_DARK_DATA_URL = - "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iNDUiIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyMDAgNDUiPgogIDxwYXRoIGZpbGw9IiNGMEFCMDAiIGQ9Ik0xLjQgMEExLjQgMS40IDAgMCAwIDAgMS40djQyLjAwM2ExLjQgMS40IDAgMCAwIDEuNCAxLjRoNi4zMDdhMTEuMTUzIDExLjE1MyAwIDAgMS0yLjQ1Ny03YzAtNS43MTMgNC4yNzctMTAuNDI3IDkuODA1LTExLjExNS42OTUtNS45NiA1Ljc2Mi0xMC41ODcgMTEuOTEtMTAuNTg3IDQuMjQ4IDAgNy45OCAyLjIxIDEwLjExMSA1LjU0Mi44NC0uMTc0IDEuNzA5LS4yNjYgMi42LS4yNjYgMS44MjQgMCAzLjU2LjM4NSA1LjEyOCAxLjA3N1YxLjRhMS40IDEuNCAwIDAgMC0xLjQtMS40SDEuNFoiLz4KICA8cGF0aCBmaWxsPSIjRjBBQjAwIiBkPSJNNDQuODA0IDI1LjYwNmE5Ljk2MyA5Ljk2MyAwIDAgMC03LjE1OC0xLjIybC0xLjg5LjM5Mi0xLjA0LTEuNjI3YTkuMTkzIDkuMTkzIDAgMCAwLTE2Ljg4IDMuODYxbC0uMjU1IDIuMTg0LTIuMTguMjdhOC40MDMgOC40MDMgMCAwIDAtMy41OTYgMTUuMzM3aDMxLjU5OGExLjQgMS40IDAgMCAwIDEuNC0xLjRWMjUuNjA2WiIvPgogIDxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xNzQuMDMzIDM3di00LjUxOGgzLjM2VjE1LjQ1NmgtMy4zNnYtNC41MThoMTIuMzk2djQuNTE4aC0zLjM2MXYxNy4wMjZoMy4zNjFWMzdoLTEyLjM5NlptLTE5LjU0MS0yNi4wNjJ2MTUuOThjMCAxLjg0My4zNjEgMy4yMjQgMS4wODMgNC4xNDUuNzIyLjg5NiAxLjkyOSAxLjM0NCAzLjYyMiAxLjM0NCAxLjY5MyAwIDIuOS0uNDQ4IDMuNjIyLTEuMzQ0LjcyMi0uOTIgMS4wODMtMi4zMDIgMS4wODMtNC4xNDR2LTE1Ljk4aDUuNTI2VjI2LjMyYzAgMS45MTctLjE4NyAzLjU4NS0uNTYxIDUuMDA0LS4zNDggMS4zOTQtLjkzMyAyLjU1MS0xLjc1NCAzLjQ3Mi0uODIyLjg5Ni0xLjg4IDEuNTY4LTMuMTc0IDIuMDE2LTEuMjk1LjQyMy0yLjg3NS42MzUtNC43NDIuNjM1cy0zLjQ0OC0uMjEyLTQuNzQyLS42MzVjLTEuMjk0LS40NDgtMi4zNTItMS4xMi0zLjE3NC0yLjAxNi0uODIxLS45Mi0xLjQxOS0yLjA3OC0xLjc5Mi0zLjQ3Mi0uMzQ4LTEuNDItLjUyMy0zLjA4Ny0uNTIzLTUuMDA0VjEwLjkzOGg1LjUyNlptLTI3LjYyMSAyNi41MWMtMS40NDQgMC0yLjczOS0uMjM2LTMuODg0LS43MWE3LjkyIDcuOTIgMCAwIDEtMi44NzUtMi4wNTNjLS43NzEtLjg5Ni0xLjM2OS0xLjk3OS0xLjc5Mi0zLjI0OC0uNDIzLTEuMjctLjYzNS0yLjY4OS0uNjM1LTQuMjU3IDAtMS41NjguMjEyLTIuOTg3LjYzNS00LjI1Ni40MjMtMS4yNyAxLjAyMS0yLjM0IDEuNzkyLTMuMjExYTcuOTIgNy45MiAwIDAgMSAyLjg3NS0yLjA1NGMxLjE0NS0uNDczIDIuNDQtLjcxIDMuODg0LS43MSAxLjQ0MyAwIDIuNzI1LjIzNyAzLjg0NS43MWE3LjUxNCA3LjUxNCAwIDAgMSAyLjg3NSAyLjA1NGMuNzk3Ljg3IDEuNDA3IDEuOTQxIDEuODMgMy4yMS40MjMgMS4yNy42MzUgMi42ODkuNjM1IDQuMjU3IDAgMS41NjgtLjIxMiAyLjk4Ny0uNjM1IDQuMjU3LS40MjMgMS4yNy0xLjAzMyAyLjM1Mi0xLjgzIDMuMjQ4LS43NzEuODk2LTEuNzMgMS41OC0yLjg3NSAyLjA1NC0xLjEyLjQ3My0yLjQwMi43MS0zLjg0NS43MVptMC00LjM2OGMxLjA5NSAwIDEuOTQxLS4zMzcgMi41MzgtMS4wMDkuNTk4LS42NzIuODk3LTEuNjMuODk3LTIuODc1di0zLjk5NWMwLTEuMjQ0LS4yOTktMi4yMDMtLjg5Ny0yLjg3NS0uNTk3LS42NzItMS40NDMtMS4wMDgtMi41MzgtMS4wMDgtMS4wOTYgMC0xLjk0Mi4zMzYtMi41MzkgMS4wMDgtLjU5OC42NzItLjg5NyAxLjYzLS44OTcgMi44NzV2My45OTVjMCAxLjI0NS4yOTkgMi4yMDMuODk3IDIuODc1LjU5Ny42NzIgMS40NDMgMS4wMDkgMi41MzkgMS4wMDlaTTk2LjY3NSAzN1YxNy4zOThoNS41MjZ2My4zMjNoLjIyNGMuMzQ5LTEuMDIuOTU5LTEuOTA0IDEuODMtMi42NTEuODcxLS43NDcgMi4wNzgtMS4xMiAzLjYyMi0xLjEyIDIuMDE2IDAgMy41MzQuNjcyIDQuNTU1IDIuMDE2IDEuMDQ1IDEuMzQ0IDEuNTY4IDMuMjYgMS41NjggNS43NVYzN2gtNS41MjZWMjUuMTY0YzAtMS4yNy0uMTk5LTIuMjAzLS41OTctMi44LS4zOTktLjYyMy0xLjEwOC0uOTM0LTIuMTI5LS45MzRhNC42IDQuNiAwIDAgMC0xLjMwNi4xODcgMy4yNiAzLjI2IDAgMCAwLTEuMTU4LjUyM2MtLjMyNC4yNDgtLjU4NS41Ni0uNzg0LjkzMy0uMTk5LjM0OS0uMjk5Ljc2LS4yOTkgMS4yMzJWMzdoLTUuNTI2Wm0tMTAuNjY3LTMuMjg2aC0uMTg3Yy0uMTc0LjQ5OC0uNDEuOTcxLS43MSAxLjQyYTQuNDU2IDQuNDU2IDAgMCAxLTEuMDgyIDEuMTk0IDUuMTQgNS4xNCAwIDAgMS0xLjYwNi44MjFjLS41OTcuMi0xLjI5NC4zLTIuMDkuMy0yLjAxNyAwLTMuNTQ4LS42Ni00LjU5My0xLjk4LTEuMDItMS4zNDQtMS41MzEtMy4yNi0xLjUzMS01Ljc1VjE3LjM5OGg1LjUyNnYxMS44MzZjMCAxLjE5NC4yMTIgMi4xMTUuNjM1IDIuNzYzLjQyMy42NDcgMS4xNDUuOTcgMi4xNjUuOTcuNDI0IDAgLjg0Ny0uMDYyIDEuMjctLjE4NmEzLjg2OSAzLjg2OSAwIDAgMCAxLjEyLS41MjNjLjMyNC0uMjQ5LjU4NS0uNTQ4Ljc4NC0uODk2LjItLjM0OC4yOTktLjc2LjI5OS0xLjIzMlYxNy4zOThoNS41MjZWMzdoLTUuNTI2di0zLjI4NlpNNjkuMTQ2IDEwLjkzOHYxOC41MmMwIDEuMTk1LS4xOTkgMi4yOS0uNTk3IDMuMjg1YTYuNjMgNi42MyAwIDAgMS0xLjY4IDIuNTAyYy0uNzQ3LjY3Mi0xLjY1NiAxLjIwNy0yLjcyNiAxLjYwNi0xLjA0Ni4zNzMtMi4yNC41Ni0zLjU4NC41Ni0xLjI5NSAwLTIuNDQtLjE3NS0zLjQzNi0uNTIzYTcuNjA5IDcuNjA5IDAgMCAxLTIuNTM5LTEuNDkzIDguMDE4IDguMDE4IDAgMCAxLTEuNzE3LTIuMzE2IDEwLjIzMiAxMC4yMzIgMCAwIDEtLjkzNC0yLjk4Nmw1LjMwMi0xLjA0NmMuNDI0IDIuMjY1IDEuNTA2IDMuMzk4IDMuMjQ5IDMuMzk4LjgyMSAwIDEuNTE4LS4yNjIgMi4wOS0uNzg0LjU5OC0uNTIzLjg5Ny0xLjM0NS44OTctMi40NjVWMTUuNDkzaC03LjkxNnYtNC41NTVoMTMuNTkxWiIvPgo8L3N2Zz4K" - -export const LOGO_LIGHT_DATA_URL = - "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iNDUiIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyMDAgNDUiPgogIDxwYXRoIGZpbGw9IiNGMEFCMDAiIGQ9Ik0xLjQgMEExLjQgMS40IDAgMCAwIDAgMS40djQyLjAwM2ExLjQgMS40IDAgMCAwIDEuNCAxLjRoNi4zMDdhMTEuMTUzIDExLjE1MyAwIDAgMS0yLjQ1Ny03YzAtNS43MTMgNC4yNzctMTAuNDI3IDkuODA1LTExLjExNS42OTUtNS45NiA1Ljc2Mi0xMC41ODcgMTEuOTEtMTAuNTg3IDQuMjQ4IDAgNy45OCAyLjIxIDEwLjExMSA1LjU0Mi44NC0uMTc0IDEuNzA5LS4yNjYgMi42LS4yNjYgMS44MjQgMCAzLjU2LjM4NSA1LjEyOCAxLjA3N1YxLjRhMS40IDEuNCAwIDAgMC0xLjQtMS40SDEuNFoiLz4KICA8cGF0aCBmaWxsPSIjRjBBQjAwIiBkPSJNNDQuODA0IDI1LjYwNmE5Ljk2MyA5Ljk2MyAwIDAgMC03LjE1OC0xLjIybC0xLjg5LjM5Mi0xLjA0LTEuNjI3YTkuMTkzIDkuMTkzIDAgMCAwLTE2Ljg4IDMuODYxbC0uMjU1IDIuMTg0LTIuMTguMjdhOC40MDMgOC40MDMgMCAwIDAtMy41OTYgMTUuMzM3aDMxLjU5OGExLjQgMS40IDAgMCAwIDEuNC0xLjRWMjUuNjA2WiIvPgogIDxwYXRoIGZpbGw9IiMwMDAiIGQ9Ik0xNzQuMDMzIDM3di00LjUxOGgzLjM2VjE1LjQ1NmgtMy4zNnYtNC41MThoMTIuMzk2djQuNTE4aC0zLjM2MXYxNy4wMjZoMy4zNjFWMzdoLTEyLjM5NlptLTE5LjU0MS0yNi4wNjJ2MTUuOThjMCAxLjg0My4zNjEgMy4yMjQgMS4wODMgNC4xNDUuNzIyLjg5NiAxLjkyOSAxLjM0NCAzLjYyMiAxLjM0NCAxLjY5MyAwIDIuOS0uNDQ4IDMuNjIyLTEuMzQ0LjcyMi0uOTIgMS4wODMtMi4zMDIgMS4wODMtNC4xNDR2LTE1Ljk4aDUuNTI2VjI2LjMyYzAgMS45MTctLjE4NyAzLjU4NS0uNTYxIDUuMDA0LS4zNDggMS4zOTQtLjkzMyAyLjU1MS0xLjc1NCAzLjQ3Mi0uODIyLjg5Ni0xLjg4IDEuNTY4LTMuMTc0IDIuMDE2LTEuMjk1LjQyMy0yLjg3NS42MzUtNC43NDIuNjM1cy0zLjQ0OC0uMjEyLTQuNzQyLS42MzVjLTEuMjk0LS40NDgtMi4zNTItMS4xMi0zLjE3NC0yLjAxNi0uODIxLS45Mi0xLjQxOS0yLjA3OC0xLjc5Mi0zLjQ3Mi0uMzQ4LTEuNDItLjUyMy0zLjA4Ny0uNTIzLTUuMDA0VjEwLjkzOGg1LjUyNlptLTI3LjYyMSAyNi41MWMtMS40NDQgMC0yLjczOS0uMjM2LTMuODg0LS43MWE3LjkyIDcuOTIgMCAwIDEtMi44NzUtMi4wNTNjLS43NzEtLjg5Ni0xLjM2OS0xLjk3OS0xLjc5Mi0zLjI0OC0uNDIzLTEuMjctLjYzNS0yLjY4OS0uNjM1LTQuMjU3IDAtMS41NjguMjEyLTIuOTg3LjYzNS00LjI1Ni40MjMtMS4yNyAxLjAyMS0yLjM0IDEuNzkyLTMuMjExYTcuOTIgNy45MiAwIDAgMSAyLjg3NS0yLjA1NGMxLjE0NS0uNDczIDIuNDQtLjcxIDMuODg0LS43MSAxLjQ0MyAwIDIuNzI1LjIzNyAzLjg0NS43MWE3LjUxNCA3LjUxNCAwIDAgMSAyLjg3NSAyLjA1NGMuNzk3Ljg3IDEuNDA3IDEuOTQxIDEuODMgMy4yMS40MjMgMS4yNy42MzUgMi42ODkuNjM1IDQuMjU3IDAgMS41NjgtLjIxMiAyLjk4Ny0uNjM1IDQuMjU3LS40MjMgMS4yNy0xLjAzMyAyLjM1Mi0xLjgzIDMuMjQ4LS43NzEuODk2LTEuNzMgMS41OC0yLjg3NSAyLjA1NC0xLjEyLjQ3My0yLjQwMi43MS0zLjg0NS43MVptMC00LjM2OGMxLjA5NSAwIDEuOTQxLS4zMzcgMi41MzgtMS4wMDkuNTk4LS42NzIuODk3LTEuNjMuODk3LTIuODc1di0zLjk5NWMwLTEuMjQ0LS4yOTktMi4yMDMtLjg5Ny0yLjg3NS0uNTk3LS42NzItMS40NDMtMS4wMDgtMi41MzgtMS4wMDgtMS4wOTYgMC0xLjk0Mi4zMzYtMi41MzkgMS4wMDgtLjU5OC42NzItLjg5NyAxLjYzLS44OTcgMi44NzV2My45OTVjMCAxLjI0NS4yOTkgMi4yMDMuODk3IDIuODc1LjU5Ny42NzIgMS40NDMgMS4wMDkgMi41MzkgMS4wMDlaTTk2LjY3NSAzN1YxNy4zOThoNS41MjZ2My4zMjNoLjIyNGMuMzQ5LTEuMDIuOTU5LTEuOTA0IDEuODMtMi42NTEuODcxLS43NDcgMi4wNzgtMS4xMiAzLjYyMi0xLjEyIDIuMDE2IDAgMy41MzQuNjcyIDQuNTU1IDIuMDE2IDEuMDQ1IDEuMzQ0IDEuNTY4IDMuMjYgMS41NjggNS43NVYzN2gtNS41MjZWMjUuMTY0YzAtMS4yNy0uMTk5LTIuMjAzLS41OTctMi44LS4zOTktLjYyMy0xLjEwOC0uOTM0LTIuMTI5LS45MzRhNC42IDQuNiAwIDAgMC0xLjMwNi4xODcgMy4yNiAzLjI2IDAgMCAwLTEuMTU4LjUyM2MtLjMyNC4yNDgtLjU4NS41Ni0uNzg0LjkzMy0uMTk5LjM0OS0uMjk5Ljc2LS4yOTkgMS4yMzJWMzdoLTUuNTI2Wm0tMTAuNjY3LTMuMjg2aC0uMTg3Yy0uMTc0LjQ5OC0uNDEuOTcxLS43MSAxLjQyYTQuNDU2IDQuNDU2IDAgMCAxLTEuMDgyIDEuMTk0IDUuMTQgNS4xNCAwIDAgMS0xLjYwNi44MjFjLS41OTcuMi0xLjI5NC4zLTIuMDkuMy0yLjAxNyAwLTMuNTQ4LS42Ni00LjU5My0xLjk4LTEuMDItMS4zNDQtMS41MzEtMy4yNi0xLjUzMS01Ljc1VjE3LjM5OGg1LjUyNnYxMS44MzZjMCAxLjE5NC4yMTIgMi4xMTUuNjM1IDIuNzYzLjQyMy42NDcgMS4xNDUuOTcgMi4xNjUuOTcuNDI0IDAgLjg0Ny0uMDYyIDEuMjctLjE4NmEzLjg2OSAzLjg2OSAwIDAgMCAxLjEyLS41MjNjLjMyNC0uMjQ5LjU4NS0uNTQ4Ljc4NC0uODk2LjItLjM0OC4yOTktLjc2LjI5OS0xLjIzMlYxNy4zOThoNS41MjZWMzdoLTUuNTI2di0zLjI4NlpNNjkuMTQ2IDEwLjkzOHYxOC41MmMwIDEuMTk1LS4xOTkgMi4yOS0uNTk3IDMuMjg1YTYuNjMgNi42MyAwIDAgMS0xLjY4IDIuNTAyYy0uNzQ3LjY3Mi0xLjY1NiAxLjIwNy0yLjcyNiAxLjYwNi0xLjA0Ni4zNzMtMi4yNC41Ni0zLjU4NC41Ni0xLjI5NSAwLTIuNDQtLjE3NS0zLjQzNi0uNTIzYTcuNjA5IDcuNjA5IDAgMCAxLTIuNTM5LTEuNDkzIDguMDE4IDguMDE4IDAgMCAxLTEuNzE3LTIuMzE2IDEwLjIzMiAxMC4yMzIgMCAwIDEtLjkzNC0yLjk4Nmw1LjMwMi0xLjA0NmMuNDI0IDIuMjY1IDEuNTA2IDMuMzk4IDMuMjQ5IDMuMzk4LjgyMSAwIDEuNTE4LS4yNjIgMi4wOS0uNzg0LjU5OC0uNTIzLjg5Ny0xLjM0NS44OTctMi40NjVWMTUuNDkzaC03LjkxNnYtNC41NTVoMTMuNTkxWiIvPgo8L3N2Zz4K" diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/manager.js b/libs_deprecated/juno-ui-components/.storybook/juno-addon/manager.js deleted file mode 100644 index 38331e7ad..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/manager.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import "./ThemeToggle" -import { addons } from "@storybook/manager-api" -import { getCurrentTheme } from "./themes" -import { ICON_DATA_URL } from "./constants" - -// -const favicon = document.head.querySelector("link[rel='icon']") -if (favicon) favicon.setAttribute("href", ICON_DATA_URL) - -addons.setConfig({ - theme: getCurrentTheme(), - toolbar: { - "storybook/background": { hidden: true }, - }, -}) - -console.log("Juno Addon Loaded") diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/preview.js b/libs_deprecated/juno-ui-components/.storybook/juno-addon/preview.js deleted file mode 100644 index 0a8a1f342..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/preview.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import Decorator from "./Decorator" -import { getCurrentTheme } from "./themes" -import DocsContainer from "./DocsContainer" - -import { - Title, - Subtitle, - Description, - Primary, - ArgsTable, - PRIMARY_STORY, - Stories, -} from "@storybook/addon-docs" - -export const decorators = [Decorator] - -export default { - parameters: { - docs: { - theme: getCurrentTheme(), - container: DocsContainer, - }, - }, -} diff --git a/libs_deprecated/juno-ui-components/.storybook/juno-addon/themes.js b/libs_deprecated/juno-ui-components/.storybook/juno-addon/themes.js deleted file mode 100644 index d2583fc7d..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/juno-addon/themes.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { create } from "@storybook/theming/create" -import { - LOGO_DARK_DATA_URL, - LOGO_LIGHT_DATA_URL, - STORAGE_KEY, -} from "./constants" -// import { themes } from "@storybook/theming" -// console.log(themes.dark) - -const staticOptions = { - brandTitle: "Juno UI", - brandUrl: "https://assets.juno.global.cloud.sap", - brandTarget: "_self", - // Fonts - fontBase: - '"Nunito Sans", -apple-system, ".SFNSText-Regular", "San Francisco", BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif', - fontCode: - 'ui-monospace, Menlo, Monaco, "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Droid Sans Mono", "Courier New", monospace', -} - -const dark = create({ - ...staticOptions, - base: "dark", - brandImage: LOGO_DARK_DATA_URL, - // - colorPrimary: "rgb(15, 167, 180)", - colorSecondary: "rgb(21, 208, 224)", - - // UI - appBg: "rgb(36, 42, 49)", - appContentBg: "rgb(18, 25, 32)", - appBorderColor: "rgba(255,255,255,.1)", - appBorderRadius: 4, - - //Buttons - booleanBg: "rgb(23, 30, 37)", - booleanSelectedBg: "#2E3438", - buttonBg: "rgb(23, 30, 37)", - buttonBorder: "rgba(255,255,255,.1)", - - // Text colors - textColor: "rgb(187,187,187)", - textInverseColor: "rgb(76, 76, 76)", - - // Toolbar default and active colors - barTextColor: "rgb(187,187,187)", - barSelectedColor: "rgb(187,187,187)", - barBg: "rgb(36, 42, 49)", - - // Form colors - inputBg: "rgb(23, 30, 37)", - inputBorder: "rgba(255,255,255,.1)", - inputTextColor: "rgb(187, 187, 187)", - inputBorderRadius: 2, - - // Menu - - textMutedColor: "rgb(122, 122, 122)", -}) - -const light = create({ - ...staticOptions, - base: "light", - brandImage: LOGO_LIGHT_DATA_URL, - - // - colorPrimary: "rgb(30, 106, 146)", - colorSecondary: "rgb(0, 125, 184)", - - // UI - appBg: "rgb(249, 249, 249)", - appContentBg: "rgb(255, 255, 255)", - appBorderColor: "rgba(64, 64, 64, .1)", - appBorderRadius: 4, - - //Buttons - booleanBg: "rgb(233, 233, 233)", - booleanSelectedBg: "#2E3438", - buttonBg: "rgb(233, 233, 233)", - buttonBorder: "rgba(64, 64, 64, .1)", - - // Text colors - textColor: "rgb(76, 76, 76)", - textInverseColor: "rgb(76, 76, 76)", - - // Toolbar default and active colors - barTextColor: "rgb(76, 76, 76)", - barSelectedColor: "rgb(76, 76, 76)", - barBg: "rgb(249, 249, 249)", - - // Form colors - inputBg: "rgb(233, 233, 233)", - inputBorder: "rgba(64, 64, 64, .1)", - inputTextColor: "rgb(76, 76, 76)", - inputBorderRadius: 2, - - // Menu - - textMutedColor: "rgb(122, 122, 122)", -}) - -const setCurrentThemeMode = (mode) => localStorage.setItem(STORAGE_KEY, mode) -const getCurrentThemeMode = () => localStorage.getItem(STORAGE_KEY) || "dark" -const getCurrentTheme = () => (getCurrentThemeMode() === "dark" ? dark : light) - -export { - dark, - light, - getCurrentTheme, - setCurrentThemeMode, - getCurrentThemeMode, -} diff --git a/libs_deprecated/juno-ui-components/.storybook/main.js b/libs_deprecated/juno-ui-components/.storybook/main.js deleted file mode 100644 index d4232a2c6..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/main.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @type { import('@storybook/react-webpack5').StorybookConfig } */ - -const path = require("path") -const globImporter = require("node-sass-glob-importer") - -const config = { - stories: ["../src/docs/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], - addons: [ - "@storybook/addon-links", - "@storybook/addon-essentials", - "@storybook/addon-docs", - "@storybook/addon-mdx-gfm", - "./juno-addon", - ], - webpackFinal: async (config) => { - // Default rule for images /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/ - // Exclude SVG files so that they can be loaded via svgr - const fileLoaderRule = config.module.rules.find( - (rule) => rule.test && rule.test.test(".svg") - ) - fileLoaderRule.exclude = /\.svg$/ - - config.module.rules.push({ - test: /\.svg$/i, - type: "asset", - resourceQuery: /url/, // import filename: *.svg?url - }) - - config.module.rules.push({ - test: /\.svg$/i, - enforce: "pre", - issuer: /\.jsx?$/, - resourceQuery: { not: [/url/] }, // exclude react component if import filename *.svg?url - loader: require.resolve("@svgr/webpack"), - options: { - svgo: false, - titleProp: true, - }, - }) - - // this is for background svgs in css - config.module.rules.push({ - test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, - issuer: /\.s?css$/, - type: "asset", - }) - - // other images - config.module.rules.push({ - test: /\.(png|jpg)$/i, - type: "asset", - }) - - config.module.rules.push({ - test: /\.scss$/, - use: [ - "css-loader", - { - loader: "postcss-loader", - // important! use local installed postcss (version 8) - options: { - implementation: require("postcss"), - }, - }, - { - loader: "sass-loader", - options: { - sassOptions: { - importer: globImporter(), - }, - }, - }, - ], - include: [path.resolve(__dirname, "../src")], - }) - - return config - }, - - framework: { - name: "@storybook/react-webpack5", - options: {}, - }, - docs: { - autodocs: true, - }, -} -export default config diff --git a/libs_deprecated/juno-ui-components/.storybook/preview.js b/libs_deprecated/juno-ui-components/.storybook/preview.js deleted file mode 100644 index 71d87aa36..000000000 --- a/libs_deprecated/juno-ui-components/.storybook/preview.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// import { useDarkMode } from "storybook-dark-mode" -// import { DocsContainer } from "./components/DocsContainer" -// import { themes } from "@storybook/theming" - -// import { -// Title, -// Subtitle, -// Description, -// Primary, -// ArgsTable, -// PRIMARY_STORY, -// Stories, -// } from "@storybook/addon-docs" -// import React from "react" -// import "../src/global.scss" -// import { StyleProvider } from "../src/components/StyleProvider" -// import { ContentArea } from "../src/components/ContentArea/index" -// import { Container } from "../src/components/Container/index" - -// export const parameters = { -// options: { -// storySort: { -// order: ["Components", "Forms", "Layout", "*", "WiP", "Internal"], -// method: "alphabetical", -// }, -// }, -// actions: { argTypesRegex: "^on[A-Z].*" }, -// backgrounds: { disable: true }, -// darkMode: { -// stylePreview: true, -// classTarget: "html", -// darkClass: "theme-dark", -// lightClass: "theme-light", -// // one additional piece of the puzzle to make dark mode work properly is the preview-head.html in this folder -// // in there we are able to set the background color of stories using inbuilt CSS escape hatches. -// // See documentation here: https://github.com/storybookjs/storybook/blob/master/addons/docs/docs/theming.md#storybook-theming -// }, -// docs: { -// /** -// * A custom docs container seems to be necessary because we want the docs container theme to switch depending on -// * the result of the useDarkMode hook from the storybook-dark-mode addon. -// * See more info in ./components/DocsContainer -// */ -// container: DocsContainer, -// /** -// * We're using a custom docs page setup here at the moment because by default the storybook docspage renders the first -// * story from the stories file as a special "primary" story that is adjustable with the args table but it does not -// * include the primary story below with the list of other stories. This leads to the description for the primary -// * story not being displayed anywhere on the docspage which is annoying. Therefore I've adjusted the default Docs Page -// * to include the primary story with the story list. There's an open issue that might fix this issue and render the -// * need for a custom page obsolete: https://github.com/storybookjs/storybook/issues/8093 -// * -// * Also there's still an open issue regarding the descriptions of stories. Ideally it would be possible to write standard -// * jsdoc descriptions for stories but currently this doesn't work. Instead you have to pass the description as a parameter. -// * This issue is here: https://github.com/storybookjs/storybook/issues/8527 -// */ -// page: () => ( -// <> -// -// <Subtitle /> -// <Description /> -// <Primary /> -// <ArgsTable story={PRIMARY_STORY} /> -// <Stories includePrimary={true} title="" /> -// </> -// ), -// // ensure that decorators aren't rendered for dynamic code display in stories -// // if decorators should be rendered for a story or component add the below to the component's config under parameters: { docs: { source: ...} } -// // and set excludeDecorators to false -// source: { -// type: "dynamic", -// excludeDecorators: true, -// }, -// }, -// controls: { -// expanded: true, -// matchers: { -// //color: /(background|color)$/i, // comment out to prevent storybook from rendering their custom color input -// date: /Date$/, -// }, -// }, -// } -// import "../src/global.scss" - -/** @type { import('@storybook/react').Preview } */ -const preview = { - parameters: { - // layout: "centered", - options: { - storySort: { - order: ["Components", "Forms", "Layout", "*", "WiP", "Internal"], - method: "alphabetical", - }, - }, - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - expanded: true, - matchers: { - //color: /(background|color)$/i, // comment out to prevent storybook from rendering their custom color input - date: /Date$/, - }, - }, - }, -} - -export default preview diff --git a/libs_deprecated/juno-ui-components/LICENSE b/libs_deprecated/juno-ui-components/LICENSE deleted file mode 100644 index 261eeb9e9..000000000 --- a/libs_deprecated/juno-ui-components/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/libs_deprecated/juno-ui-components/README.md b/libs_deprecated/juno-ui-components/README.md deleted file mode 100644 index 2117ccf48..000000000 --- a/libs_deprecated/juno-ui-components/README.md +++ /dev/null @@ -1,61 +0,0 @@ -## ⚠️ Deprecated - -This application is deprecated and no longer maintained. Please refer to [cloudoperators/juno](https://github.com/cloudoperators/juno) for the latest updates and active development. - -# Juno UI Components Library - -## Installation - -To include Juno UI components as a dev dependency in your app install with npm: - -```bash -npm add --dev juno-ui-components -``` - -…or declare manually as a dev-dependency: - -```js -// package.json -"devDependencies": { - ... - "juno-ui-components": ">= 0" - ... -} -``` - -```bash -npm --workspaces install -``` - -## Working With Tailwind - -Juno comes with [Tailwind](https://tailwindcss.com/) included, so when using Juno you automatically can use tailwind in your project. - -To be able to make full use of the predefined colors and other custom properties from the Juno UI components library you will need to include the ui components tailwind config into your application's tailwind config like this: - -```js -module.exports = { - presets: [ - require("juno-ui-components/build/lib/tailwind.config") - ], - ... -} -``` - -Doing this lets you use Tailwind classnames from the Juno UI Components library. - -## Development - -In order to work ON (NOT WITH) the Juno Design System and its components run storybook with: - -```bash -npm -w juno-ui-components run storybook -``` - -or just run from the root directory of this repository `npm run ui-components` - -Run the test suite: - -```bash -npm -w juno-ui-components run test -``` diff --git a/libs_deprecated/juno-ui-components/babel.config.json b/libs_deprecated/juno-ui-components/babel.config.json deleted file mode 100644 index 3e71ca2d5..000000000 --- a/libs_deprecated/juno-ui-components/babel.config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "presets": ["@babel/preset-react"], - "env": { - "test": { - "presets": ["@babel/env"] - } - }, - "plugins": ["@babel/plugin-transform-parameters"] -} diff --git a/libs_deprecated/juno-ui-components/lib/variables.scss b/libs_deprecated/juno-ui-components/lib/variables.scss deleted file mode 100644 index 0edb699fc..000000000 --- a/libs_deprecated/juno-ui-components/lib/variables.scss +++ /dev/null @@ -1,635 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -// Juno - -/* Color Definitions */ -/* The Mother of Colors – The single source of truth of colors in Juno. - Here we define all relevant colors as triples of their rgb values. - We use these to generate CSS variables: one is the triple itself for use with tailwind opacity functions, one is the rgb( r, g, b) color definition for direct use. - -*/ - -/* Global Color Definitions */ -$color-map: ( - - "white": (255, 255, 255), - "black": (0, 0, 0), - - "sap-grey-1": (255, 255, 255), - "sap-grey-2": (225, 225, 225), - "sap-grey-3": (204, 204, 204), - "sap-grey-4": (153, 153, 153), - "sap-grey-5": (127, 127, 127), - "sap-grey-6": (102, 102, 102), - "sap-grey-7": (75, 75, 75), - "sap-grey-8": (0, 0, 0), - - "sap-blue-1": (15, 170, 25), - "sap-blue-2": (0, 143, 211), - "sap-blue-3": (0, 118, 203), - "sap-blue-4": (15, 70, 167), - "sap-blue-5": (0, 50, 131), - "sap-blue-6": (0, 25, 90), - - "sap-gold": (240, 171, 0), - - "sap-purple-1": (220, 0, 150), - "sap-purple-2": (190, 0, 140), - "sap-purple-3": (151, 10, 130), - "sap-purple-4": (118, 10, 133), - "sap-purple-5": (69, 21, 126), - "sap-purple-6": (60, 20, 100), - - "sap-green-1": (188, 220, 80), - "sap-green-2": (147, 201, 57), - "sap-green-3": (79, 184, 28), - "sap-green-4": (52, 139, 38), - "sap-green-5": (36, 114, 48), - "sap-green-6": (15, 75, 60), - - "sap-orange-1": (255, 175, 0), - "sap-orange-2": (250, 145, 0), - "sap-orange-3": (235, 115, 0), - "sap-orange-4": (227, 85, 0), - "sap-orange-5": (208, 69, 18), - "sap-orange-6": (188, 54, 24), - - "juno-grey-blue-1": (64, 70, 75), - "juno-grey-blue-2": (48, 54, 60), - "juno-grey-blue-3": (41, 47, 54), - "juno-grey-blue-4": (38, 44, 51), - "juno-grey-blue-5": (36, 42, 49), - "juno-grey-blue-6": (31, 38, 45), - "juno-grey-blue-7": (28, 35, 42), - "juno-grey-blue-8": (23, 30, 37), - "juno-grey-blue-9": (18, 25, 32), - "juno-grey-blue-10": (13, 20, 28), - "juno-grey-blue-11": (0, 8, 16), - - "juno-grey-light-1": (249, 249, 249), - "juno-grey-light-2": (247, 247, 247), - "juno-grey-light-3": (244, 244, 244), - "juno-grey-light-4": (241, 241, 241), - "juno-grey-light-5": (238, 238, 238), - "juno-grey-light-6": (235, 235, 235), - "juno-grey-light-7": (233, 233, 233), - "juno-grey-light-8": (230, 230, 230), - "juno-grey-light-9": (227, 227, 227), - "juno-grey-light-10": (215, 215, 215), - - "juno-blue-1": (203, 232, 247), - "juno-blue-2": (165, 211, 234), - "juno-blue-3": (137, 201, 232), - "juno-blue-4": (67, 162, 208), - "juno-blue-5": (0, 125, 184), - "juno-blue-6": (30, 106, 146), - "juno-blue-7": (10, 103, 153), - "juno-blue-8": (7, 85, 128), - "juno-blue-9": (5, 70, 105), - "juno-blue-10": (3, 55, 84), - - "juno-turquoise-1": (197, 247, 255), - "juno-turquoise-2": (132, 241, 255), - "juno-turquoise-3": (25, 232, 250), - "juno-turquoise-4": (22, 217, 234), - "juno-turquoise-5": (21, 208, 224), - "juno-turquoise-6": (15, 167, 180), - "juno-turquoise-7": (9, 133, 144), - "juno-turquoise-8": (5, 100, 109), - "juno-turquoise-9": (2, 69, 75), - "juno-turquoise-10": (1, 41, 4), - - "juno-primary-blue-1": (15, 170, 255), - "juno-primary-blue-2": (0, 143, 211), - "juno-primary-blue-3": (0, 118, 203), - "juno-primary-blue-4": (15, 70, 167), - "juno-primary-blue-5": (0, 50, 131), - "juno-primary-blue-6": (0, 25, 90), - -); - -/* Light Theme Color Definitions */ -$light-theme-color-map: ( - "accent": (0, 118, 203), - - "info": (0, 118, 203), - "success": (79, 184, 28), - "warning": (255, 175, 0), - "danger": (199, 0, 0), - "error": (199, 0, 0), - - "juno-text-light": (150, 150, 150), - "juno-text-default": (76, 76, 76), - "juno-text-high": (64, 64, 64), - "juno-text-highest": (0, 0, 0), - "juno-text-disabled": (183, 183, 183), - - "juno-primary-danger-1": (235, 146, 146), - "juno-primary-danger-2": (218, 93, 93), - "juno-primary-danger-3": (213, 64, 64), - "juno-primary-danger-4": (199, 0, 0), - "juno-primary-danger-5": (165,11,11), -); - -/* Dark Theme Color Definitions */ -$dark-theme-color-map: ( - "accent": (21, 208, 224), - - "info": (21, 208, 224), - "success": (59, 255, 91), - "warning": (255, 198, 0), - "danger": (255, 65, 16), - "error": (255, 65, 16), - - "juno-text-light": (122, 122, 122), - "juno-text-default": (187, 187, 187), - "juno-text-high": (222, 223, 224), - "juno-text-highest": (255, 254, 253), - "juno-text-disabled": (92, 92, 92), - - "juno-primary-danger-1": (231, 163, 137), - "juno-primary-danger-2": (222, 126, 91), - "juno-primary-danger-3": (208, 69, 18), - "juno-primary-danger-4": (187, 62, 16), - "juno-primary-danger-5": (164, 54, 14), -); - - - -/* Global Color Variables */ -:root, -:host { - - @each $name, $value in $color-map { - --color-#{$name}: rgb(#{$value}); - --color-#{$name}-raw: #{$value}; - } - -} - -/* Light Theme Color Variables */ -.theme-light { - @each $name, $value in $light-theme-color-map { - --color-#{$name}: rgb(#{$value}); - --color-#{$name}-raw: #{$value}; - } -} - -/* Dark Theme Color Variables */ -.theme-dark { - @each $name, $value in $dark-theme-color-map { - --color-#{$name}: rgb(#{$value}); - --color-#{$name}-raw: #{$value}; - } -} - - -/* Color Assignments */ - -/* ----- LIGHT THEME ----- */ -.theme-light { - // LT Background Colors - --color-background-lvl-0: var(--color-white); - --color-background-lvl-1: var(--color-juno-grey-light-1); - --color-background-lvl-2: var(--color-juno-grey-light-3); - --color-background-lvl-3: var(--color-juno-grey-light-7); - --color-background-lvl-4: var(--color-juno-grey-light-9); - --color-background-lvl-5: var(--color-juno-grey-light-10); - - --color-background-lvl-0-raw: var(--color-white-raw); - --color-background-lvl-1-raw: var(--color-juno-grey-light-1-raw); - --color-background-lvl-2-raw: var(--color-juno-grey-light-3-raw); - --color-background-lvl-3-raw: var(--color-juno-grey-light-7-raw); - --color-background-lvl-4-raw: var(--color-juno-grey-light-9-raw); - --color-background-lvl-5-raw: var(--color-juno-grey-light-10-raw); - - // LT Global - --color-global-bg: var(--color-juno-grey-light-1); - --color-global-bg-raw: var(--color-juno-grey-light-1-raw); - - --color-global-text: var(--color-juno-text-default-raw); - --color-content-area-bg: var(--color-background-lvl-0); - --color-content-area-bg-raw: var(--color-background-lvl-0-raw); - // LT FOCUS - --color-focus: var(--color-accent); - --color-focus-raw: var(--color-accent-raw); - // LT Text - --color-text-highest: var(--color-juno-text-highest); - --color-text-high: var(--color-juno-text-high); - --color-text-default: var(--color-juno-text-default); - --color-text-light: var(--color-juno-text-light); - --color-text-disabled: var(--color-juno-text-disabled); - --color-text-link: var(--color-accent); - --color-text-highest-raw: var(--color-juno-text-highest-raw); - --color-text-high-raw: var(--color-juno-text-high-raw); - --color-text-default-raw: var(--color-juno-text-default-raw); - --color-text-light-raw: var(--color-juno-text-light-raw); - --color-text-disabled-raw: var(--color-juno-text-disabled-raw); - --color-text-link-raw: var(--color-accent-raw); - - // LT Badge - --color-badge-default-bg: var(--color-juno-grey-light-3); - - // LT Button - // LT Primary Button - --color-button-primary-text: var(--color-white); - --color-button-primary-bg: var(--color-juno-primary-blue-3); - // |-- LT Primary Button :hover - --color-button-primary-hover-text: var(--color-white); - --color-button-primary-hover-bg: var(--color-juno-primary-blue-2); - // |-- LT Primary Button :active - --color-button-primary-active-text: var(--color-white); - --color-button-primary-active-bg: var(--color-juno-primary-blue-5); - - // LT Default Button - --color-button-default-text: var(--color-text-high); - --color-button-default-bg: var(--color-background-lvl-4); - --color-button-default-border: var(--color-background-lvl-4); - // |-- LT Default Button :hover - --color-button-default-hover-text: var(--color-text-high); - --color-button-default-hover-bg: var(--color-background-lvl-3); - --color-button-default-hover-border: var(--color-background-lvl-3); - // |-- LT Default Button :active - --color-button-default-active-text: var(--color-text-high); - --color-button-default-active-bg: var(--color-background-lvl-2); - --color-button-default-active-border: var(--color-background-lvl-4); - - // LT Subdued Button - --color-button-subdued-text: var(--color-text-default); - --color-button-subdued-icon: var(--color-text-default); - --color-button-subdued-bg: var(--color-background-lvl-3); - --color-button-subdued-border: var(--color-background-lvl-4); - // |-- LT Subdued Button :hover - --color-button-subdued-hover-text: var(--color-text-default); - --color-button-subdued-hover-bg: var(--color-background-lvl-1); - --color-button-subdued-hover-border: var(--color-background-lvl-4); - // |-- LT Subdued Button :active - --color-button-subdued-active-text: var(--color-text-default); - --color-button-subdued-active-bg: var(--color-background-lvl-0); - --color-button-subdued-active-border: var(--color-background-lvl-4); - - // LT Primary Danger Button - --color-button-primary-danger-text: var(--color-white); - --color-button-primary-danger-bg: var(--color-juno-primary-danger-4); - // |-- LT Primary Danger Button :hover - --color-button-primary-danger-hover-text: var(--color-white); - --color-button-primary-danger-hover-bg: var(--color-juno-primary-danger-3); - // |-- LT Primary Danger Button :active - --color-button-primary-danger-active-text: var(--color-white); - --color-button-primary-danger-active-bg: var(--color-juno-primary-danger-5); - - // LT Icon - --color-icon-danger: var(--color-juno-red-raw); - --color-icon-info: var(--color-accent-raw); - --color-icon-success: var(--color-sap-green-raw); - --color-icon-warning: var(--color-warning-raw); - // LT Message - --color-message-danger-border: var(--color-danger-raw); - --gradient-message-danger-bg: linear-gradient( - 90deg, - rgb(255, 231, 224) 0%, - rgb(255, 180, 158) 100% - ); - --color-message-default-border: var(--color-info-raw); - --gradient-message-default-bg: linear-gradient( - 90deg, - rgb(229, 244, 248) 0%, - rgb(46, 168, 196) 100% - ); - --color-message-error-border: var(--color-error-raw); - --gradient-message-error-bg: linear-gradient( - 90deg, - rgb(255, 231, 224) 0%, - rgb(255, 180, 158) 100% - ); - --color-message-warning-border: var(--color-warning-raw); - --gradient-message-warning-bg: linear-gradient( - 90deg, - rgb(253, 245, 226) 0%, - rgb(255, 231, 147) 100% - ); - --color-message-success-border: var(--color-success-raw); - --gradient-message-success-bg: linear-gradient( - 90deg, - rgb(230, 247, 233) 0%, - rgb(170, 229, 180) 100% - ); - - // LT Introbox - --color-introbox-bg: var(--color-background-lvl-2-raw); - --color-introbox-border: var(--color-accent-raw); - // LT (Text-) Input - --color-textinput-bg: var(--color-background-lvl-3-raw); - --color-textinput-default-border: var(--color-background-lvl-4-raw); - --color-textinput-text: var(--color-juno-text-high-raw); - --color-textinput-placeholder-text: var(--color-juno-text-high-raw); - --color-textinput-focus-border: var(--color-accent-raw); - --color-textinput-autofill-text: var(--color-black); - --color-textinput-autofill-bg: var(--color-juno-blue-1); - --color-textinput-autofill-label: var(--color-juno-text-default); - // LT Select - --color-select-bg: var(--color-background-lvl-3-raw); - // LT Checkbox - --color-checkbox-bg: var(--color-background-lvl-5-raw); - --color-checkbox-checked-color: var(--color-accent-raw); - // LT Radio - --color-radio-bg: var(--color-background-lvl-5-raw); - --color-radio-checked-bg: var(--color-accent-raw); - // LT Switch - --color-switch-default-border: var(--color-juno-text-default-raw); - --color-switch-handle-bg: var(--color-juno-text-default-raw); - --color-switch-handle-checked-bg: var(--color-accent-raw); - // LT Required - --color-required-bg: var(--color-accent-raw); - // LT Spinner - --color-spinner-primary: var(--color-accent-raw); - // LT Syntax Highlighting - --color-syntax-highlight-base00: var(--color-codeblock-bg); // bg - --color-syntax-highlight-base01: var(--color-juno-grey-light-3); // ? - --color-syntax-highlight-base02: var(--color-sap-grey-3); // lines and boxes - --color-syntax-highlight-base03: var(--color-sap-grey-3); - --color-syntax-highlight-base04: var(--color-sap-grey-3); - --color-syntax-highlight-base05: var(--color-juno-text-high); - --color-syntax-highlight-base06: red; - --color-syntax-highlight-base07: var(--color-juno-text-high); - --color-syntax-highlight-base08: var(--color-juno-grey-blue-6); // NULL - --color-syntax-highlight-base09: var(--color-juno-blue-4); // String value - --color-syntax-highlight-base0A: var(--color-juno-grey-blue-6); // NaN - --color-syntax-highlight-base0B: var(--color-juno-blue-4); // float value - --color-syntax-highlight-base0C: var(--color-sap-gold); // array index - --color-syntax-highlight-base0D: var(--color-sap-gold); // expanded icon - --color-syntax-highlight-base0E: var(--color-juno-blue-4); - // LT bool + collapsed icon - --color-syntax-highlight-base0F: var(--color-juno-blue-4); // integer value - // LT DataGrid - --color-datagridrow-selected: var(--color-accent-raw); - // LT DataList - --color-datalist-row-border: var(--color-background-lvl-1-raw); - --color-datalistrow-selected: var(--color-accent-raw); - // LT CodeBlock - --color-codeblock-bg: var(--color-background-lvl-2-raw); - --color-codeblock-bar-border: var(--color-background-lvl-4-raw); - // LT Panel - // --color-panel-bg-raw: var(--color-white-raw); - --color-panel-bg: rgba(252, 252, 252, 0.8); - // LT TabNavigation - --color-tabnavigation-top-bg: var(--color-juno-grey-light-5-raw); - --color-tabnavigation-content-bottom-border: var(--color-background-lvl-4-raw); - // LT Filters - --color-filters-bg: var(--color-background-lvl-1-raw); - --color-filter-input-bg: var(--color-background-lvl-0-raw); - --color-filter-input-border: var(--color-background-lvl-4-raw); - --color-filter-input-textinput-bg: transparent; - --color-filter-pill-border: var(--color-background-lvl-4-raw); - --color-filter-pill-key-bg: var(--color-background-lvl-4-raw); - // LT Modal - --color-modal-backdrop-bg: rgba(0, 0, 0, 0.2); - // LT Box - --color-box-bg: var(--color-background-lvl-1); - --color-box-border: var(--color-background-lvl-3); - // DT SideNavigation - --color-sidenavigation-item-active: var(--color-black); - --color-sidenavigation-item-active-bg: var(--color-background-lvl-0); - // DT TopNavigation - --color-topnavigation-item-active: var(--color-black); - --color-topnavigation-item-bg: var(--color-sap-grey-1); - --color-topnavigation-item-active-bg: var(--color-sap-grey-3); - - // DT Datepicker - --color-datepicker-calendar-bg: var(--color-background-lvl-1); - -} - -/* ----- LIGHT THEME END -----*/ -/* ----- */ -/* ----- */ -/* ----- */ -/* ----- */ -/* ----- DARK THEME ----- */ - -.theme-dark { - // DT Background Colors - --color-background-lvl-0: var(--color-juno-grey-blue-9); - --color-background-lvl-1: var(--color-juno-grey-blue-7); - --color-background-lvl-2: var(--color-juno-grey-blue-5); - --color-background-lvl-3: var(--color-juno-grey-blue-3); - --color-background-lvl-4: var(--color-juno-grey-blue-2); - --color-background-lvl-5: var(--color-juno-grey-blue-1); - - --color-background-lvl-0-raw: var(--color-juno-grey-blue-9-raw); - --color-background-lvl-1-raw: var(--color-juno-grey-blue-7-raw); - --color-background-lvl-2-raw: var(--color-juno-grey-blue-5-raw); - --color-background-lvl-3-raw: var(--color-juno-grey-blue-3-raw); - --color-background-lvl-4-raw: var(--color-juno-grey-blue-2-raw); - --color-background-lvl-5-raw: var(--color-juno-grey-blue-1-raw); - - // DT Global - --color-global-bg: var(--color-juno-grey-blue-10); - --color-global-bg-raw: var(--color-juno-grey-blue-10-raw); - - --color-global-text: var(--color-juno-text-default-raw); - --color-content-area-bg: var(--color-background-lvl-0); - --color-content-area-bg-raw: var(--color-background-lvl-0-raw); - - // DT FOCUS - --color-focus: var(--color-accent); - --color-focus-raw: var(--color-accent-raw); - --color-focus-border: var(--color-accent-raw); - // DT Text - --color-text-highest: var(--color-juno-text-highest); - --color-text-high: var(--color-juno-text-high); - --color-text-default: var(--color-juno-text-default); - --color-text-light: var(--color-juno-text-light); - --color-text-disabled: var(--color-juno-text-disabled); - --color-text-link: var(--color-accent); - --color-text-highest-raw: var(--color-juno-text-highest-raw); - --color-text-high-raw: var(--color-juno-text-high-raw); - --color-text-default-raw: var(--color-juno-text-default-raw); - --color-text-light-raw: var(--color-juno-text-light-raw); - --color-text-disabled-raw: var(--color-juno-text-disabled-raw); - --color-text-link-raw: var(--color-accent-raw); - - // DT Badge - --color-badge-default-bg: var(--color-juno-grey-blue-3); - - // DT Button - // DT Primary Button - --color-button-primary-bg: var(--color-juno-turquoise-7); - --color-button-primary-text: var(--color-white); - // |-- DT Primary Button :hover - --color-button-primary-hover-bg: var(--color-juno-turquoise-5); - --color-button-primary-hover-text: var(--color-white); - // |-- DT Primary Button :active - --color-button-primary-active-bg: var(--color-juno-turquoise-9); - --color-button-primary-active-text: var(--color-white); - - // DT Default Button - --color-button-default-text: var(--color-text-high); - --color-button-default-icon: var(--color-text-high); - --color-button-default-bg: var(--color-background-lvl-5); - --color-button-default-border: var(--color-background-lvl-5); - // |-- DT Default Button :hover - --color-button-default-hover-text: var(--color-text-high); - --color-button-default-hover-bg: var(--color-background-lvl-3); - --color-button-default-hover-border: var(--color-background-lvl-3); - // |-- DT Default Button :active - --color-button-default-active-text: var(--color-text-high); - --color-button-default-active-bg: var(--color-background-lvl-2); - --color-button-default-active-border: var(--color-background-lvl-4); - - // DT Subdued Button - --color-button-subdued-text: var(--color-text-default); - --color-button-subdued-icon: var(--color-text-default); - --color-button-subdued-bg: var(--color-background-lvl-3); - --color-button-subdued-border: var(--color-background-lvl-4); - // |-- DT Subdued Button :hover - --color-button-subdued-hover-text: var(--color-text-default); - --color-button-subdued-hover-bg: var(--color-background-lvl-2); - --color-button-subdued-hover-border: var(--color-background-lvl-4); - // |-- DT Subdued Button :active - --color-button-subdued-active-text: var(--color-text-default); - --color-button-subdued-active-bg: var(--color-background-lvl-0); - --color-button-subdued-active-border: var(--color-background-lvl-4); - - // DT Primary-Danger Button - --color-button-primary-danger-text: var(--color-white); - --color-button-primary-danger-bg: var(--color-juno-primary-danger-4); - // |-- DT Primary Danger Button :hover - --color-button-primary-danger-hover-text: var(--color-white); - --color-button-primary-danger-hover-bg: var(--color-juno-primary-danger-3); - // |-- DT Primary Danger Button :active - --color-button-primary-danger-active-text: var(--color-white); - --color-button-primary-danger-active-bg: var(--color-juno-primary-danger-5); - - // DT Icon - --color-icon-danger: var(--color-juno-red-5-raw); - --color-icon-info: var(--color-accent-raw); - --color-icon-success: var(--color-sap-green-5-raw); - --color-icon-warning: var(--color-warning-raw); - // DT Message - --color-message-danger-border: var(--color-danger-raw); - --gradient-message-danger-bg: linear-gradient( - 90deg, - rgb(57, 39, 38) 0%, - rgb(124, 48, 30) 100% - ); - --color-message-default-border: var(--color-info-raw); - --gradient-message-default-bg: linear-gradient( - 90deg, - rgb(28, 57, 65) 0%, - rgb(25, 108, 119) 100% - ); - --color-message-error-border: var(--color-error-raw); - --gradient-message-error-bg: linear-gradient( - 90deg, - rgb(57, 39, 38) 0%, - rgb(124, 48, 30) 100% - ); - --color-message-warning-border: var(--color-warning-raw); - --gradient-message-warning-bg: linear-gradient( - 90deg, - rgb(57, 56, 36) 0%, - rgb(124, 104, 24) 100% - ); - --color-message-success-border: var(--color-success-raw); - --gradient-message-success-bg: linear-gradient( - 90deg, - rgb(32, 55, 46) 0%, - rgb(39, 102, 57) 100% - ); - // DT Introbox - --color-introbox-bg: var(--color-background-lvl-2-raw); - --color-introbox-border: var(--color-accent-raw); - // DT (Text-)Input - --color-textinput-bg: var(--color-background-lvl-3-raw); - --color-textinput-default-border: var(--color-background-lvl-4-raw); - --color-textinput-text: var(--color-juno-text-high-raw); - --color-textinput-placeholder-text: var(--color-juno-text-high-raw); - --color-textinput-focus-border: var(--color-accent-raw); - --color-textinput-autofill-text: var(--color-black); - --color-textinput-autofill-bg: var(--color-juno-blue-1); - --color-textinput-autofill-label: var(--color-black); - // DT Select - --color-select-bg: var(--color-background-lvl-4-raw); - // DT Checkbox - --color-checkbox-bg: var(--color-background-lvl-5-raw); - --color-checkbox-checked-color: var(--color-accent-raw); - // DT Radio - --color-radio-bg: var(--color-background-lvl-5-raw); - --color-radio-checked-bg: var(--color-accent-raw); - // DT Switch - --color-switch-default-border: var(--color-juno-text-high-raw); - --color-switch-handle-bg: var(--color-juno-text-high-raw); - --color-switch-handle-checked-bg: var(--color-accent-raw); - --color-switch-hover-border: var(--color-accent-raw); - // DT Required - --color-required-bg: var(--color-accent-raw); - // DT Spinner - --color-spinner-primary: var(--color-accent-raw); - // DT Syntax Highlighting - --color-syntax-highlight-base00: var(--color-codeblock-bg); // bg - --color-syntax-highlight-base01: var(--color-juno-grey-blue-3); // ? - --color-syntax-highlight-base02: #bbb; // lines and boxes - --color-syntax-highlight-base03: var(--color-sap-grey-3); - --color-syntax-highlight-base04: var(--color-sap-grey-3); - --color-syntax-highlight-base05: #dedfe0; - --color-syntax-highlight-base06: red; - --color-syntax-highlight-base07: #dedfe0; - --color-syntax-highlight-base08: var(--color-juno-grey-blue-6); // NULL - --color-syntax-highlight-base09: var(--color-juno-blue-4); // String value - --color-syntax-highlight-base0A: var(--color-juno-grey-blue-6); // NaN - --color-syntax-highlight-base0B: var(--color-juno-blue-4); // float value - --color-syntax-highlight-base0C: var(--color-sap-gold); // array index - --color-syntax-highlight-base0D: var(--color-sap-gold); // DT expanded icon - --color-syntax-highlight-base0E: var(--color-juno-blue-4); // DT bool + collapsed icon - --color-syntax-highlight-base0F: var(--color-juno-blue-4); // integer value - // DT DataGrid - --color-datagridrow-selected: var(--color-accent-raw); - // DT DataList - --color-datalist-row-border: var(--color-background-lvl-1-raw); - --color-datalistrow-selected: var(--color-accent-raw); - // DT CodeBlock - --color-codeblock-bg: var(--color-background-lvl-2-raw); - --color-codeblock-bar-border: var(--color-background-lvl-4-raw); - // DT Panel - --color-panel-bg: rgba(var(--color-juno-grey-blue-11-raw), 0.75); - - // DT TabNavigation - --color-tabnavigation-top-bg: var(--color-juno-grey-blue-8-raw); - --color-tabnavigation-content-bottom-border: var(--color-background-lvl-4-raw); - // DT Filters - --color-filters-bg: var(--color-background-lvl-1-raw); - --color-filter-input-bg: var(--color-background-lvl-0-raw); - --color-filter-input-border: var(--color-background-lvl-4-raw); - --color-filter-input-textinput-bg: transparent; - --color-filter-pill-border: var(--color-background-lvl-4-raw); - --color-filter-pill-key-bg: var(--color-background-lvl-4-raw); - // DT Modal - --color-modal-backdrop-bg: rgba(60, 70, 75, 0.6); - // DT Box - --color-box-bg: var(--color-background-lvl-1); - --color-box-border: var(--color-background-lvl-3); - // DT SideNavigation - --color-sidenavigation-item-active: var(--color-white); - --color-sidenavigation-item-active-bg: var(--color-background-lvl-0); - // DT TopNavigation - --color-topnavigation-item-active: var(--color-white); - --color-topnavigation-item-bg: var(--color-juno-grey-blue-7); - --color-topnavigation-item-active-bg: var(--color-juno-grey-blue-2); - // DT Datepicker - --color-datepicker-calendar-bg: var(--color-background-lvl-1); -} - -/* ----- DARK THEME END ----- */ - -// Grid configuration -:root, -:host { - --grid-columns: 12; - --grid-row-margin-x: -0.5rem; - --grid-column-flex-grow: 0; - --grid-column-flex-shrink: 1; - --grid-column-flex-basis: auto; - --grid-column-default-width: 8.333333%; -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/package.json b/libs_deprecated/juno-ui-components/package.json deleted file mode 100644 index cdb10c0c4..000000000 --- a/libs_deprecated/juno-ui-components/package.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "name": "juno-ui-components", - "private": true, - "main": "build/index.js", - "module": "build/index.js", - "source": "src/index.js", - "style": "build/lib/variables.css", - "version": "2.14.0", - "files": [ - "src/colors.css", - "tailwind.config.js" - ], - "author": "UI-Team", - "contributors": [ - "Esther Schmitz", - "Franz Heidl" - ], - "repository": "https://github.com/sapcc/juno/tree/main/libs/juno-ui-components", - "deprecationWarning": "\u001b[1;31m\u001b[5m\n\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n ⚠️ WARNING: This package is deprecated and no longer maintained! ⚠️\n\n Please refer to https://github.com/cloudoperators/juno for the latest updates and active development.\n\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n\n\n\u001b[0m", - "license": "Apache-2.0", - "devDependencies": { - "@babel/plugin-transform-parameters": "^7.22.5", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@floating-ui/react": "^0.25.1", - "@headlessui-float/react": "^0.11.2", - "@headlessui/react": "^1.7.15", - "@material-design-icons/svg": "^0.14.4", - "@mdx-js/react": "^2.0.0", - "@rollup/plugin-babel": "^6.0.3", - "@rollup/plugin-commonjs": "^24.0.0", - "@rollup/plugin-node-resolve": "^15.1.3", - "@storybook/addon-docs": "^7.5.3", - "@storybook/addon-essentials": "^7.5.3", - "@storybook/addon-interactions": "^7.5.3", - "@storybook/addon-links": "^7.5.3", - "@storybook/addon-mdx-gfm": "^7.5.3", - "@storybook/addon-postcss": "^2.0.0", - "@storybook/blocks": "^7.5.3", - "@storybook/manager-api": "^7.5.3", - "@storybook/react": "^7.5.3", - "@storybook/react-webpack5": "^7.5.3", - "@storybook/testing-library": "^0.2.2", - "@svgr/rollup": "^6.2.1", - "@svgr/webpack": "^6.2.1", - "@testing-library/dom": "^8.19.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "add": "^2.0.6", - "autoprefixer": "^10.4.2", - "babel-jest": "^29.3.1", - "babel-loader": "^8.2.3", - "css-loader": "^6.6.0", - "focus-trap-react": "^10.2.3", - "glob": "^8.1.0", - "jest": "^29.3.1", - "jest-environment-jsdom": "^29.3.1", - "node-sass-glob-importer": "^3.0.2", - "postcss": "^8.4.6", - "postcss-loader": "^6.2.1", - "prop-types": "15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-jss": "^10.8.1", - "react-tabs": "^4.2.1", - "regenerator-runtime": "^0.13.9", - "rollup": "^3.4.0", - "rollup-plugin-analyzer": "^4.0.0", - "rollup-plugin-babel-minify": "^10.0.0", - "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-includepaths": "^0.2.4", - "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-postcss": "^4.0.2", - "sass": "^1.49.7", - "sass-loader": "^12.4.0", - "storybook": "^7.6.17", - "style-loader": "^3.3.1", - "tailwindcss": "^3.3.1", - "flatpickr": "4.6.13" - }, - "peerDependencies": { - "prop-types": "15.8.1", - "react": "18.2.0", - "react-dom": "18.2.0" - }, - "scripts": { - "storybook": "storybook dev -p $APP_PORT --ci --no-open", - "build-storybook": "storybook build", - "build": "rollup -c", - "test": "jest", - "test:watch": "jest --watchAll", - "preinstall": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prestorybook": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "prebuild-storybook": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'", - "pretest:watch": "node -e 'console.log(require(\"./package.json\").deprecationWarning)'" - }, - "jest": { - "verbose": true, - "testEnvironment": "jsdom", - "transformIgnorePatterns": [ - "node_modules/(?!(react-merge-refs)/)" - ], - "setupFilesAfterEnv": [ - "./setupTests.js" - ], - "transform": { - "\\.[jt]sx?$": "babel-jest", - "\\.mjs$": "babel-jest", - "^.+\\.svg$": "<rootDir>/test/__mocks__/svg.js" - }, - "moduleNameMapper": { - "^.+\\.(css|scss)$": "<rootDir>/test/__mocks__/styleMock.js", - "@material-design-icons/svg/.+\\.svg$": "<rootDir>/test/__mocks__/svgLib.js" - } - } -} diff --git a/libs_deprecated/juno-ui-components/postcss.config.js b/libs_deprecated/juno-ui-components/postcss.config.js deleted file mode 100644 index 0627e0e4b..000000000 --- a/libs_deprecated/juno-ui-components/postcss.config.js +++ /dev/null @@ -1,8 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -module.exports = { - plugins: [require("tailwindcss"), require("autoprefixer")], -} diff --git a/libs_deprecated/juno-ui-components/rollup.config.js b/libs_deprecated/juno-ui-components/rollup.config.js deleted file mode 100644 index c38f584ec..000000000 --- a/libs_deprecated/juno-ui-components/rollup.config.js +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -const { babel } = require("@rollup/plugin-babel") -const del = require("rollup-plugin-delete") -const postcss = require("rollup-plugin-postcss") -const pkg = require("./package.json") -const fs = require("fs") -const minify = require("rollup-plugin-babel-minify") -const analyze = require("rollup-plugin-analyzer") -const { nodeResolve } = require("@rollup/plugin-node-resolve") -const commonjs = require("@rollup/plugin-commonjs") -const svgr = require("@svgr/rollup") -const glob = require("glob") -const { - generateTailwindThemeClassesJson, -} = require("./src/docs/ColorPalette/generateTailwindThemeClassesJson") - -// generates tailwind classes for documentation usages. -generateTailwindThemeClassesJson() - -// IMPORTANT! -// package.json is single source of truth policy - -if (!/.+\/.+\.js/.test(pkg.module)) - throw new Error( - "module value is incorrect, use DIR/FILE.js like build/index.js" - ) -const buildDir = pkg.module.slice(0, pkg.module.lastIndexOf("/")) -// filename is extracted from module key in package.json -// because of single source of truth policy -const filename = pkg.module.slice( - pkg.module.lastIndexOf("/") + 1, - pkg.module.lastIndexOf(".") -) - -const isProduction = process.env.NODE_ENV === "production" -const IGNORE_EXTERNALS = process.env.IGNORE_EXTERNALS === "true" - -// define plugins here to use it in different configs -const plugins = [ - svgr({ - svgo: false, - titleProp: true, - }), - postcss({ - config: { - path: "./postcss.config.js", - }, - extract: false, - minimize: false, //true, - inject: false, - extensions: [".scss", ".css"], - use: ["sass", "glob-imports"], - loaders: [ - // custom loader!!! to load all scss files in globals.scss - { - name: "glob-imports", - test: /\.(sass|scss)$/, - process({ code }) { - // handle glob import - return new Promise((resolve, reject) => { - const match = [...code.matchAll(/@import\s+(.*\*+.*);/g)] - match.forEach((m) => { - const files = glob.sync("./src/" + m[1].replace(/"|'/g, "")) - let result = files.map((f) => `@import "${f}";`).join("\n") - code = code.replace(m[0], result) - }) - resolve({ code }) - }) - }, - }, - ], - }), - - nodeResolve(), - babel({ - // babelrc: false, - // // exclude: "node_modules/**", - // presets: ["@babel/preset-react"], - babelHelpers: "bundled", - }), - commonjs(), - - minify({ comments: false }), - analyze({ - summaryOnly: true, - limit: 0, - }), -] - -const config = [ - // bundle all components - { - input: fs.readdirSync("./src/components").reduce((map, file) => { - map[file] = `src/components/${file}/index.js` - return map - }, {}), - output: [ - // { dir: "lib", format: "cjs", preserveModules: false }, - { - dir: buildDir, - format: "esm", - preserveModules: false, - compact: true, - }, - ], - - plugins: [del({ targets: [`${buildDir}/**/*`] }), ...plugins], - }, - { - input: "tailwind.config.js", - output: { - file: `${buildDir}/lib/tailwind.config.js`, - }, - }, - { - input: pkg.source, - output: { - file: `${buildDir}/index.js`, - format: "esm", - preserveModules: false, - compact: true, - }, - plugins, - - external: ["react", "react-dom", "prop-types"].concat( - isProduction && !IGNORE_EXTERNALS - ? Object.keys(pkg.peerDependencies || {}) - : [] - ), - }, - { - input: "lib/variables.scss", - output: { - file: `${buildDir}/lib/variables.css`, - }, - plugins: [ - postcss({ - config: { - path: "./postcss.config.js", - }, - extract: true, - minimize: true, - inject: false, - }), - ], - }, -] - -module.exports = config diff --git a/libs_deprecated/juno-ui-components/setupTests.js b/libs_deprecated/juno-ui-components/setupTests.js deleted file mode 100644 index d59db8eee..000000000 --- a/libs_deprecated/juno-ui-components/setupTests.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import "@testing-library/jest-dom" -import "regenerator-runtime/runtime" - -/* -Mock ResizeObserver. -Required to test Radix-UI-based components. -https://github.com/ZeeCoder/use-resize-observer/issues/40 -https://stackoverflow.com/questions/64558062/how-to-mock-resizeobserver-to-work-in-unit-tests-using-react-testing-library -*/ -class ResizeObserver { - observe() {} - unobserve() {} - disconnect() {} -} - -window.ResizeObserver = ResizeObserver - - -/** - * Required to test Radix-UI-based components: - * JSDOM doesn't implement PointerEvent so we need to mock our own implementation - * Default to mouse left click interaction - * https://github.com/radix-ui/primitives/issues/1822 - * https://github.com/jsdom/jsdom/pull/2666 - */ - -class MockPointerEvent extends Event { - constructor(type, props) { - super(type, props) - this.button = props.button || 0 - this.ctrlKey = props.ctrlKey || false - this.pointerType = props.pointerType || "mouse" - } -} - -window.PointerEvent = MockPointerEvent -window.HTMLElement.prototype.scrollIntoView = jest.fn() -window.HTMLElement.prototype.releasePointerCapture = jest.fn() -window.HTMLElement.prototype.hasPointerCapture = jest.fn() diff --git a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.component.js b/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.component.js deleted file mode 100644 index f00ad41c8..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.component.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const containerStyles = ` - jn-flex - jn-flex-col - jn-h-full -` - -/** - * Only needed if you want to build your app's scaffold manually. In most cases it is better to use the AppShell component instead. - * Body of the app. Treat this like the body tag of an html page. - */ -export const AppBody = ({ className, children, ...props }) => { - return ( - <div - className={`juno-body ${containerStyles} ${className}`} - {...props} - > - {children} - </div> - ) -} - -AppBody.propTypes = { - /** Add custom class name */ - className: PropTypes.string, -} - -AppBody.defaultProps = { - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.stories.js b/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.stories.js deleted file mode 100644 index 964f638a3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.stories.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { AppBody } from './index.js'; - -export default { - title: 'Internal/AppBody', - component: AppBody, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => <AppBody {...args}></AppBody>; - -export const Body = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Only needed if you want to build your app's scaffold manually. In most cases it is better to use the AppShell component instead. Body of the app. Treat this like the body tag of an html page.", - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.test.js b/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.test.js deleted file mode 100644 index e7c4faf55..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppBody/AppBody.test.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { AppBody } from "./index" - -describe("AppBody", () => { - test("renders an app body", async () => { - render(<AppBody data-testid="app-body" />) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByTestId("app-body")).toHaveClass("juno-body") - }) - - test("renders an app body with flex column", async () => { - render(<AppBody data-testid="app-body" />) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByTestId("app-body")).toHaveClass( - "jn-flex-col" - ) - }) - - test("renders an app body with full height", async () => { - render(<AppBody data-testid="app-body" />) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByTestId("app-body")).toHaveClass("jn-h-full") - }) - - test("renders children as passed", async () => { - render( - <AppBody data-testid="app-body"> - <button></button> - </AppBody> - ) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render( - <AppBody data-testid="app-body" className="my-custom-classname" /> - ) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByTestId("app-body")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render(<AppBody data-testid="app-body" data-lolol="some-prop" />) - expect(screen.getByTestId("app-body")).toBeInTheDocument() - expect(screen.getByTestId("app-body")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/AppBody/index.js b/libs_deprecated/juno-ui-components/src/components/AppBody/index.js deleted file mode 100644 index a26de8d50..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppBody/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { AppBody } from "./AppBody.component" diff --git a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.component.js b/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.component.js deleted file mode 100644 index d9559e857..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.component.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const introStyles = ` - jn-pt-16 - jn-pb-14 - jn-text-xl - in-pr-[45%] -` - -/** - * OBSOLETE: Will be deleted! - */ -export const AppIntro = ({ className, children, ...props }) => { - return ( - <div className={`juno-app-intro ${introStyles} ${className}`} {...props}> - {children} - </div> - ) -} - -AppIntro.propTypes = { - /** Add custom class name */ - className: PropTypes.string, -} - -AppIntro.defaultProps = { - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.stories.js b/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.stories.js deleted file mode 100644 index 7516f13e0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.stories.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { AppIntro } from './index.js'; - -export default { - title: 'Layout/AppIntro', - component: AppIntro, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => ( - <AppIntro {...args}> - Intro text here. Explain what this app is in a short lead text. Lorem ipsum dolor sit amet. At - vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata - sanctus est. Lorem ipsum dolor sit amet. - </AppIntro> -); - -export const Intro = { - render: Template, - - parameters: { - docs: { - description: { - story: 'OBSOLETE: Will be deleted!', - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.test.js b/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.test.js deleted file mode 100644 index 10650dbaf..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppIntro/AppIntro.test.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { AppIntro } from "./index" - -describe("AppIntro", () => { - test("renders an app intro", async () => { - render(<AppIntro data-testid="app-intro" />) - expect(screen.getByTestId("app-intro")).toBeInTheDocument() - expect(screen.getByTestId("app-intro")).toHaveClass("juno-app-intro") - }) - - test("renders children as passed", async () => { - render( - <AppIntro data-testid="app-intro"> - <button></button> - </AppIntro> - ) - expect(screen.getByTestId("app-intro")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<AppIntro data-testid="app-intro" className="my-custom-classname" />) - expect(screen.getByTestId("app-intro")).toBeInTheDocument() - expect(screen.getByTestId("app-intro")).toHaveClass("my-custom-classname") - }) - - test("renders all props", async () => { - render(<AppIntro data-testid="app-intro" data-lolol="some-prop" />) - expect(screen.getByTestId("app-intro")).toBeInTheDocument() - expect(screen.getByTestId("app-intro")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/AppIntro/index.js b/libs_deprecated/juno-ui-components/src/components/AppIntro/index.js deleted file mode 100644 index 57440f414..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppIntro/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { AppIntro } from "./AppIntro.component" diff --git a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.component.js b/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.component.js deleted file mode 100644 index c6626778d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.component.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { AppBody } from "../AppBody/index" -import { PageHeader } from "../PageHeader/index" -import { MainContainer } from "../MainContainer/index" -import { MainContainerInner } from "../MainContainerInner/index" -import { ContentContainer } from "../ContentContainer/index" -import { ContentHeading } from "../ContentHeading/index" -import { ContentArea } from "../ContentArea/index" -import { PageFooter } from "../PageFooter/index" -import { SideNavigation } from "../SideNavigation/" - -/** - * Body of the app. Treat this like the body tag of an html page. - */ -export const AppShell = ({ - children, - className, - contentHeading, - embedded, - fullWidthContent, - pageHeader, - pageFooter, - sideNavigation, - topNavigation, - ...props -}) => { - - // Determine whether to pass set fullWidth to true in embedded mode or not: - // In non-embedded mode, fullWidthContent should default to false, unless explicitly set to true. - // In embedded mode though, fullWidthContent should default to true, unless explicitly passed as false. - - return ( - <AppBody className={className} {...props}> - - { contentHeading && contentHeading.length ? - console.warn("AppShell: The contentHeading prop is obsolete and will be removed in a future version. In order to render a content heading, use a ContentHeading element as a child in your main content.") - : - "" - } - - { embedded ? - <MainContainer> - <MainContainerInner fullWidth={fullWidthContent === false ? false : true} hasSideNav={ sideNavigation ? true : false }> - { sideNavigation && sideNavigation } - <ContentContainer> - {children} - </ContentContainer> - </MainContainerInner> - </MainContainer> - - : - - <> - { pageHeader && (typeof pageHeader === 'string' || pageHeader instanceof String) ? - <PageHeader heading={pageHeader} /> - : - pageHeader - } - { topNavigation && topNavigation } - {/* Wrap everything except page header and footer and navigations in a main container. Add top margin to MainContainerInner as we are not in embedded mode here. */} - <MainContainer> - <MainContainerInner fullWidth={fullWidthContent === true ? true : false } hasSideNav={ sideNavigation ? true : false } className="jn-mt-[3.875rem]"> - { sideNavigation && sideNavigation } - {/* Content Container. This is the place to add the app's main content. Render left margin only if no SideNavigation is present. */} - <ContentContainer className={ sideNavigation ? "" : "jn-ml-8"}> - {children} - </ContentContainer> - </MainContainerInner> - </MainContainer> - - { pageFooter ? - pageFooter - : - <PageFooter /> - } - </> - } - - </AppBody> - ) -} - -AppShell.propTypes = { - /** Pass either the `<PageHeader>` component or if you don't need to add any content to the page header pass a string to be used as the app name in the standard page header. */ - pageHeader: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.element - ]), - /** Optional. If specified pass a `<PageFooter>` component. If undefined will use default PageFooter */ - pageFooter: PropTypes.element, - /** Optional. If specified expects a `<TopNavigation>` component. If undefined no top navigation is rendered. */ - topNavigation: PropTypes.element, - /** Optional. If specified expects a `<SideNavigation>` component. If undefined no side navigation is rendered. */ - sideNavigation: PropTypes.element, - /** OBSOLETE: The contentHeading prop is obsolete and will be removed in a future version. In order to render a content heading, use a `<ContentHeading>` element as a child in your main content. */ - contentHeading: PropTypes.string, - /** Optional: Defaults to false. Set embedded to true if app is to be rendered embedded in another app/page. - * In this case only the content area and children are rendered, no header/footer or remaining layout components */ - embedded: PropTypes.bool, - /** Whether the main page / view content can spread over the full available width of the viewport or not. Default is `false` (resulting in a width-constrained, centred content column on very wide screens) UNLESS the AppShell is rendered with embedded as true, then the main content will be full-width by default. In embedded mode, `fullWidthContent` can still be passed as `false` explicitly. */ - fullWidthContent: PropTypes.bool, - /** Add a custom class name */ - className: PropTypes.string, -} - -AppShell.defaultProps = { - pageHeader: <PageHeader />, - pageFooter: <PageFooter />, - topNavigation: undefined, - sideNavigation: undefined, - contentHeading: "", - embedded: false, - fullWidthContent: undefined, - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.stories.js b/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.stories.js deleted file mode 100644 index 4e94b7a70..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.stories.js +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { AppShell } from "./index.js" -import { PageHeader } from "../PageHeader/index" -import { PageFooter } from "../PageFooter/index" -import { SideNavigation } from "../SideNavigation/" -import { SideNavigationItem } from "../SideNavigationItem/" -import { TopNavigation } from "../TopNavigation/index" -import { TopNavigationItem } from "../TopNavigationItem/index" -import { TabNavigation } from "../TabNavigation/index" -import { TabNavigationItem } from "../TabNavigationItem/index" -import { ContentHeading } from "../ContentHeading/index" - -export default { - title: "Layout/AppShell", - component: AppShell, - argTypes: { - pageHeader: { - control: false - }, - pageFooter: { - control: false - }, - topNavigation: { - control: false - }, - sideNavigation: { - control: false - }, - children: { - control: false - }, - }, -} - -const Template = ({children, ...args}) => <AppShell {...args}> - { children } - </AppShell> - -export const Default = Template.bind({}) -Default.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with content heading and default header and footer.", - }, - }, -} -Default.args = { - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const AppName = Template.bind({}) -AppName.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with provided app name for the header and default footer.", - }, - }, -} -AppName.args = { - pageHeader: "My App", - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const CustomPageHeader = Template.bind({}) -CustomPageHeader.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with custom page header and default footer.", - }, - }, -} -CustomPageHeader.args = { - pageHeader: <PageHeader heading="My Custom Header" />, - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const CustomPageFooter = Template.bind({}) -CustomPageFooter.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with default header and custom footer.", - }, - }, -} -CustomPageFooter.args = { - pageFooter: <PageFooter>My custom footer</PageFooter>, - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const WithSideNavigation = Template.bind({}) -WithSideNavigation.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with a side navigation.", - }, - }, -} -WithSideNavigation.args = { - sideNavigation: <SideNavigation> - <SideNavigationItem active label="Item 1"/> - <SideNavigationItem label="Item 2" /> - <SideNavigationItem label="Item 3" /> - </SideNavigation>, - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const WithTopNavigation = Template.bind({}) -WithTopNavigation.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with top navigation.", - }, - }, -} -WithTopNavigation.args = { - topNavigation: <TopNavigation> - <TopNavigationItem - icon="home" - label="Home" - /> - <TopNavigationItem - active - label="Navigation Item" - /> - </TopNavigation>, - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const WithSideAndTopNavigation = Template.bind({}) -WithSideAndTopNavigation.parameters = { - docs: { - description: { - story: - "Responsive shell for your application with both a top navigation and side navigation.", - }, - }, -} -WithSideAndTopNavigation.args = { - topNavigation: <TopNavigation> - <TopNavigationItem - icon="home" - label="Home" - /> - <TopNavigationItem - active - label="Navigation Item" - /> - </TopNavigation>, - sideNavigation: <SideNavigation> - <SideNavigationItem active label="Item 1"/> - <SideNavigationItem label="Item 2" /> - <SideNavigationItem label="Item 3" /> - </SideNavigation>, - children: [ - <ContentHeading key="1">My Page</ContentHeading>, - <p key="2">Content goes here</p> - ] -} - -export const WithTabNavigation = Template.bind({}) -WithTabNavigation.parameters = {} -WithTabNavigation.args = { - children: [ - <TabNavigation key="1"> - <TabNavigationItem label="Item 1" active /> - <TabNavigationItem label="Item 2" /> - <TabNavigationItem label="Item 3" /> - </TabNavigation>, - <ContentHeading key="2">My Page</ContentHeading> - ] - -} diff --git a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.test.js b/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.test.js deleted file mode 100644 index 7c6671ef9..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShell/AppShell.test.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { cleanup, render, screen } from "@testing-library/react" -import { AppShell } from "./index" -import { PageHeader } from "../PageHeader/PageHeader.component" -import { PageFooter } from "../PageFooter/PageFooter.component" -import { TopNavigation } from "../TopNavigation/TopNavigation.component" -import { SideNavigation } from "../SideNavigation/SideNavigation.component" - -describe("AppShell", () => { - - afterEach(() => { - cleanup(); - jest.clearAllMocks() - }) - - test("renders an app shell", async () => { - render(<AppShell data-testid="app-shell" />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("app-shell")).toHaveClass("juno-body") - }) - - test("logs a deprecation warning to the console when user passed obsolete contentHeading prop", async () => { - const consoleWarnSpy = jest.spyOn(console, 'warn') - render(<AppShell contentHeading="My Content Heading" />) - expect(consoleWarnSpy).toHaveBeenCalled() - expect(consoleWarnSpy).toHaveBeenCalledWith( - "AppShell: The contentHeading prop is obsolete and will be removed in a future version. In order to render a content heading, use a ContentHeading element as a child in your main content." - ) - }) - - test("renders an app shell with page header passed as String", async () => { - render(<AppShell data-testid="app-shell" pageHeader="My Page Header" />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByText("My Page Header")).toBeInTheDocument() - }) - - test("renders an app shell with page header passed as component", async () => { - render(<AppShell data-testid="app-shell" pageHeader={<PageHeader data-testid="page-header" heading="My Page Header" />} />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("page-header")).toBeInTheDocument() - expect(screen.getByText("My Page Header")).toBeInTheDocument() - }) - - test("renders an app shell with custom page footer passed as component", async () => { - render(<AppShell data-testid="app-shell" pageFooter={<PageFooter data-testid="page-footer">My Page Footer</PageFooter>} />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("page-footer")).toBeInTheDocument() - expect(screen.getByText("My Page Footer")).toBeInTheDocument() - }) - - test("renders an app shell with top navigation passed as component", async () => { - render(<AppShell data-testid="app-shell" topNavigation={<TopNavigation data-testid="top-navigation"></TopNavigation>} />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("top-navigation")).toBeInTheDocument() - }) - - test("renders an app shell with a side navigation passed as a component", async () => { - render( - <AppShell - data-testid="app-shell" - sideNavigation={<SideNavigation />} - /> - ) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByRole("navigation")).toBeInTheDocument() - expect(screen.getByRole("navigation")).toHaveClass("juno-sidenavigation") - }) - - test("renders an app shell with both a side and a top navigation as passed", async () => { - render( - <AppShell - data-testid="app-shell" - sideNavigation={<SideNavigation data-testid="side-nav" />} - topNavigation={<TopNavigation data-testid="top-nav" />} - /> - ) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getAllByRole("navigation")).toHaveLength(2) - expect(screen.getByTestId("side-nav")).toBeInTheDocument() - expect(screen.getByTestId("top-nav")).toBeInTheDocument() - }) - - test("renders an embeddable app shell without page heading or footer", async () => { - render(<AppShell data-testid="app-shell" embedded={true} pageHeader={<PageHeader data-testid="page-header" heading="My Page Heading" />} pageFooter={<PageFooter data-testid="page-footer">My Page Footer</PageFooter>} />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.queryByTestId("page-header")).not.toBeInTheDocument() - expect(screen.queryByText("My Page Heading")).not.toBeInTheDocument() - expect(screen.queryByTestId("page-footer")).not.toBeInTheDocument() - expect(screen.queryByText("My Page Footer")).not.toBeInTheDocument() - }) - - test("renders children as passed", async () => { - render( - <AppShell data-testid="app-shell"> - <button></button> - </AppShell> - ) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - - // The following test whether the MainContainerInner element rendered by AppShell does the right thing depending of props passed to AppShell: - test("does not render a fullwidth main container in non-embedded mode by default", async () => { - render(<AppShell><button></button></AppShell>) - expect(document.querySelector(".juno-main-inner")).not.toHaveClass("juno-main-inner-fullwidth") - }) - - test("renders a fullwidth main container in non-embedded mode if passed explicitly", async () => { - render(<AppShell fullWidthContent={true}><button></button></AppShell>) - expect(document.querySelector(".juno-main-inner")).toHaveClass("juno-main-inner-fullwidth") - }) - - test("renders a fullwidth main inner container in embedded mode by default", async () => { - render(<AppShell embedded><button></button></AppShell>) - expect(document.querySelector(".juno-main-inner")).toHaveClass("juno-main-inner-fullwidth") - }) - - test("renders a non-fullwidth, size-restricted main inner container in embedded mode if passed explicitly", async () => { - render(<AppShell embedded fullWidthContent={false}><button></button></AppShell>) - expect(document.querySelector(".juno-main-inner")).not.toHaveClass("juno-main-inner-fullwidth") - }) - - test("renders a custom className", async () => { - render(<AppShell data-testid="app-shell" className="my-custom-classname" />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("app-shell")).toHaveClass("my-custom-classname") - }) - - test("renders all props", async () => { - render(<AppShell data-testid="app-shell" data-lolol="some-prop" />) - expect(screen.getByTestId("app-shell")).toBeInTheDocument() - expect(screen.getByTestId("app-shell")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/AppShell/index.js b/libs_deprecated/juno-ui-components/src/components/AppShell/index.js deleted file mode 100644 index d6146507a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { AppShell } from "./AppShell.component" diff --git a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.component.js b/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.component.js deleted file mode 100644 index eab5cf74a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.component.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -import { StyleProvider } from "../StyleProvider/StyleProvider.component" -import { ShadowRoot } from "../ShadowRoot/ShadowRoot.component" -import { PortalProvider } from "../PortalProvider/PortalProvider.component" - -/** - * This provider acts as a wrapper for Juno apps. It renders a StyleProvider and PortalProvider - */ -export const AppShellProvider = ({ - shadowRoot, - shadowRootMode, - stylesWrapper, - theme, - children, -}) => { - const Wrapper = React.useCallback( - ({ children }) => - shadowRoot ? ( - <ShadowRoot mode={shadowRootMode}>{children}</ShadowRoot> - ) : ( - children - ), - [shadowRoot, shadowRootMode] - ) - return ( - <Wrapper> - <StyleProvider - theme={theme} - stylesWrapper={shadowRoot ? "inline" : stylesWrapper} - > - <PortalProvider>{children}</PortalProvider> - </StyleProvider> - </Wrapper> - ) -} - -AppShellProvider.propTypes = { - /** Whether the app is rendered inside a ShadowRoot. Only choose false if the app is meant to run as a stand-alone application. */ - shadowRoot: PropTypes.bool, - /** Shadow root mode */ - shadowRootMode: PropTypes.oneOf(["open", "closed"]), - /** Where app stylesheets are imported. This is only relevant if shadowRoot === false. If you use a ShadowRoot the styles must be inline. */ - stylesWrapper: PropTypes.oneOf(["head", "inline"]), - /** theme: theme-dark or theme-light */ - theme: PropTypes.string, -} - -// define default values -AppShellProvider.defaultProps = { - shadowRoot: true, - shadowRootMode: "open", - stylesWrapper: "inline", - theme: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.stories.js b/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.stories.js deleted file mode 100644 index 2e51c9beb..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.stories.js +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { AppShellProvider } from '.'; -import { CodeBlock } from '../CodeBlock/index.js'; -import { Message } from '../Message/Message.component'; - -export default { - title: 'Layout/AppShellProvider', - component: AppShellProvider, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => <AppShellProvider {...args}>{args.children}</AppShellProvider>; - -export const Default = { - render: Template, - - args: { - children: [ - <Message key={0}>Juno styles are added inline</Message>, - <CodeBlock key={1}> - {` - export default (props) => { - return ( - <AppShellProvider> - <style>{/* app styles */}</style> - <App {...props} /> - </AppShellProvider> - ) - }`} - </CodeBlock>, - ], - }, -}; - -export const NoShadowRoot = { - render: Template, - - args: { - shadowRoot: false, - children: [ - <Message key={0}>No ShadowRoot, but the styles are still inline (default)</Message>, - <CodeBlock key={1}> - {` - export default (props) => { - return ( - <AppShellProvider shadowRoot={false}> - <style>{/* app styles */}</style> - <App {...props} /> - </AppShellProvider> - ) - }`} - </CodeBlock>, - ], - }, -}; - -export const StylesInHead = { - render: Template, - - args: { - shadowRoot: false, - stylesWrapper: 'head', - children: [ - <Message key={0}>Juno styles are added to the head tag</Message>, - <CodeBlock key={1}> - {` - export default (props) => { - return ( - <AppShellProvider shadowRoot={false} stylesWrapper="head"> - <style>{/* app styles */}</style> - <App {...props} /> - </AppShellProvider> - ) - }`} - </CodeBlock>, - ], - }, -}; - -export const StylesInline = { - render: Template, - - args: { - shadowRoot: false, - stylesWrapper: 'inline', - children: [ - <Message key={0}>Juno style are added inline</Message>, - <CodeBlock key={1}> - {` - export default (props) => { - return ( - <AppShellProvider shadowRoot={false} stylesWrapper="inline"> - <style>{/* app styles */}</style> - <App {...props} /> - </AppShellProvider> - ) - }`} - </CodeBlock>, - ], - }, -}; - -export const ThemeLight = { - render: Template, - - args: { - theme: 'theme-light', - children: [ - <Message key={0}>Light Theme</Message>, - <CodeBlock key={1}>{` - <AppShellProvider theme="theme-light"> - <style>{/* app styles */}</style> - <App> - {/* App Body */} - </App> - </AppShellProvider>`}</CodeBlock>, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.test.js b/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.test.js deleted file mode 100644 index 909cdda7d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/AppShellProvider.test.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { AppShellProvider } from "./index" - -describe("AppShellProvider", () => { - test("renders an AppShellProvider wrapper div with 'theme-dark' theme class by default", async () => { - render(<AppShellProvider shadowRoot={false} />) - expect(document.querySelector(".juno-app-body")).toHaveClass("theme-dark") - }) - - test("renders an AppShellProvider wrapper div with theme class as passed", async () => { - render(<AppShellProvider shadowRoot={false} theme="my-theme" />) - expect(document.querySelector("div.juno-app-body")).toHaveClass("my-theme") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/index.js b/libs_deprecated/juno-ui-components/src/components/AppShellProvider/index.js deleted file mode 100644 index 3af34f51c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/AppShellProvider/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { AppShellProvider } from "./AppShellProvider.component" diff --git a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.component.js b/libs_deprecated/juno-ui-components/src/components/Badge/Badge.component.js deleted file mode 100644 index 4a0451dfb..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.component.js +++ /dev/null @@ -1,135 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -import { Icon, knownIcons } from "../Icon/Icon.component.js" - -const badgeBaseStyles = ` - jn-rounded - jn-text-sm - jn-text-theme-default - jn-py-0.5 - jn-px-1 - jn-justify-center - jn-items-center -` - -const defaultStyles = `jn-bg-theme-badge-default` - -const infoStyles = `jn-bg-theme-info/25` - -const successStyles = `jn-bg-theme-success/25` - -const warningStyles = `jn-bg-theme-warning/25` - -const dangerStyles = `jn-bg-theme-danger/25` - -const criticalStyles = `jn-bg-theme-danger/70 jn-text-theme-high` - -const errorStyles = `jn-bg-theme-error/25` - -const iconStyles = `jn-mr-1 jn-items-center` - -const knownVariants = [ - "info", - "success", - "warning", - "danger", - "error", - "critical", -] - -const getVariantStyle = (variant) => { - switch (variant) { - case "info": - return infoStyles - case "success": - return successStyles - case "warning": - return warningStyles - case "danger": - return dangerStyles - case "error": - return errorStyles - case "critical": - return criticalStyles - default: - return defaultStyles - } -} - -/** -A Badge component to visually indicate properties or states of an entity. Besides the default, there are also semantic versions. Can optionally contain an icon to emphasize their meaning. -*/ -export const Badge = ({ - variant, - icon, - text, - className, - children, - ...props -}) => { - const getIcon = (icon, variant) => { - if (icon && knownIcons.includes(icon)) { - // if icon is an available icon, return as passed: - return icon - } else if (icon === true) { - // otherwise return icon as per variant if === "true" (map if not congruent!): - return variant - } else { - return null - } - } - - const getIconColor = (icon, variant) => { - if (icon === true) { - // if icon is set to true this means the icon will be chosen according to the variant. In this case make sure the color matches the variant - return `jn-text-theme-${variant}` - } else { - return undefined - } - } - - return ( - <span - className={` - juno-badge - juno-badge-${variant} - ${badgeBaseStyles} - ${getVariantStyle(variant)} - ${icon ? "jn-inline-flex" : ""} - ${className}`} - {...props} - > - {icon ? ( - <Icon - icon={getIcon(icon, variant)} - size="1.125rem" - className={`${iconStyles}`} - color={getIconColor(icon, variant)} - /> - ) : null} - {children ? children : text} - </span> - ) -} - -Badge.propTypes = { - variant: PropTypes.oneOf(["default", ...knownVariants]), - icon: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(knownIcons)]), - text: PropTypes.string, - className: PropTypes.string, - children: PropTypes.node, -} - -Badge.defaultProps = { - variant: "default", - icon: false, - text: "", - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.stories.js b/libs_deprecated/juno-ui-components/src/components/Badge/Badge.stories.js deleted file mode 100644 index f58713f20..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.stories.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Badge } from './index'; -import { knownIcons } from '../Icon/Icon.component.js'; - -export default { - title: 'Components/Badge', - component: Badge, - parameters: { - text: 'default', - }, - argTypes: { - icon: { - options: ['default', ...knownIcons], - control: { type: 'select' }, - }, - children: { - control: false, - }, - }, -}; - -export const WithDefaultIcon = { - args: { - text: 'With Icon', - icon: true, - }, -}; - -export const Info = { - args: { - variant: 'info', - text: 'info', - }, -}; -export const InfoWithIcon = { - args: { - variant: 'info', - text: 'info', - icon: true, - }, -}; - -export const Success = { - args: { - variant: 'success', - text: 'success', - }, -}; - -export const SuccessWithIcon = { - args: { variant: 'success', text: 'success', icon: true }, -}; - -export const Warning = { args: { variant: 'warning', text: 'warning' } }; - -export const WarningWithIcon = { - args: { - variant: 'warning', - text: 'warning', - icon: true, - }, -}; - -export const Danger = { - args: { - variant: 'danger', - text: 'danger', - }, -}; - -export const DangerWithIcon = { - args: { - variant: 'danger', - text: 'danger', - icon: true, - }, -}; - -export const Error = { - args: { - variant: 'error', - text: 'error', - }, -}; - -export const ErrorWithIcon = { - args: { - variant: 'error', - text: 'error', - icon: true, - }, -}; - -export const DefaultWithAnyIcon = { - args: { - text: 'deleted', - icon: 'deleteForever', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.test.js b/libs_deprecated/juno-ui-components/src/components/Badge/Badge.test.js deleted file mode 100644 index aec1a239e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Badge/Badge.test.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Badge } from "./index" - -describe("Badge", () => { - test("renders a badge with text as passed", async () => { - render(<Badge text="default badge" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveTextContent("default badge") - }) - - test("renders a badge with children", async () => { - render(<Badge data-testid="badge">Children inside</Badge>) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveTextContent("Children inside") - }) - - test("renders an info badge variant as passed", async () => { - render(<Badge variant="info" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-info") - }) - - test("renders a success badge variant as passed", async () => { - render(<Badge variant="success" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-success") - }) - - test("renders a warning badge variant as passed", async () => { - render(<Badge variant="warning" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-warning") - }) - - test("renders a danger badge variant as passed", async () => { - render(<Badge variant="danger" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-danger") - }) - - test("renders an error badge variant as passed", async () => { - render(<Badge variant="error" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-error") - }) - - test("renders a critical badge variant as passed", async () => { - render(<Badge variant="critical" data-testid="badge" />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveClass("juno-badge-critical") - }) - - test("renders a default icon as passed", async () => { - render(<Badge icon={true} />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveClass("juno-icon-default") - }) - - test("renders the correct variant-specific icon as passed", async () => { - render(<Badge variant="warning" icon={true} />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveClass("juno-icon-warning") - }) - - test("renders any available icon as passed", async () => { - render(<Badge icon="comment" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveClass("juno-icon-comment") - }) - - test("renders all props as passed", async () => { - render(<Badge data-testid="badge" data-lolol={true} />) - expect(screen.getByTestId("badge")).toBeInTheDocument() - expect(screen.getByTestId("badge")).toHaveAttribute("data-lolol") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Badge/index.js b/libs_deprecated/juno-ui-components/src/components/Badge/index.js deleted file mode 100644 index 8bc09e27b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Badge/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Badge } from "./Badge.component" diff --git a/libs_deprecated/juno-ui-components/src/components/Box/Box.component.js b/libs_deprecated/juno-ui-components/src/components/Box/Box.component.js deleted file mode 100644 index 66847f38d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Box/Box.component.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const boxstyles = ` - jn-text-sm - jn-rounded - jn-bg-theme-box-default - jn-border - jn-border-theme-box-default -` - -/* When adjusting the padding update tests accordingly as we are testing for rendering padded and unpadded Box */ -const boxpadding = ` - jn-py-1 - jn-px-2 -` -/** -A generic Box element with padding and a light border. - -Use for annotations, further explanations, and remarks where Message or InfoBox would be visually too emphasized. - -Will typically contain (small) text, but can be passed any child element(s) as desired. -*/ -export const Box = ({ - children, - unpad, - className, - ...props -}) => { - return ( - <div className={`juno-box ${boxstyles} ${ unpad ? "" : boxpadding } ${className}`} {...props} > - { children } - </div> - ) -} - -Box.propTypes = { - children: PropTypes.node, - unpad: PropTypes.bool, - className: PropTypes.string, -} - -Box.defaultProps = { - children: null, - unpad: false, - className: "", -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Box/Box.stories.js b/libs_deprecated/juno-ui-components/src/components/Box/Box.stories.js deleted file mode 100644 index fcd15c1d8..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Box/Box.stories.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Box } from './index'; - -export default { - title: 'Components/Box', - component: Box, - argTypes: {}, -}; - -export const Default = { - parameters: { - docs: { - description: { - story: 'A default Box', - }, - }, - }, - - args: { - children: 'Some content in a Box.', - }, -}; - -export const UnpaddedBox = { - parameters: { - docs: { - description: { - story: 'To remove the padding, set `unpad` prop.', - }, - }, - }, - - args: { - children: 'Unpadded Box', - unpad: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Box/Box.test.js b/libs_deprecated/juno-ui-components/src/components/Box/Box.test.js deleted file mode 100644 index d3c8c26ba..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Box/Box.test.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Box } from "./index" - - -describe("Box", () => { - - test("renders a box with children", async () => { - render(<Box data-testid="box" >Children inside</Box>) - expect(screen.getByTestId("box")).toBeInTheDocument() - expect(screen.getByTestId("box")).toHaveTextContent("Children inside") - }) - - test("renders a padded Box by default", async () => { - render(<Box data-testid="box"/>) - expect(screen.getByTestId("box")).toBeInTheDocument() - expect(screen.getByTestId("box")).toHaveClass('jn-py-1') - expect(screen.getByTestId("box")).toHaveClass('jn-px-2') - }) - - test("renders an unpadded Box as passed", async () => { - render(<Box data-testid="box" unpad />) - expect(screen.getByTestId("box")).toBeInTheDocument() - expect(screen.getByTestId("box")).not.toHaveClass('jn-py-1') - expect(screen.getByTestId("box")).not.toHaveClass('jn-px-2') - }) - - test("renders all classNames as passed", async () => { - render(<Box data-testid="box" className="my-custom-class"/>) - expect(screen.getByTestId("box")).toBeInTheDocument() - expect(screen.getByTestId("box")).toHaveClass('my-custom-class') - }) - - test("renders all props as passed", async () => { - render(<Box data-testid="box" data-lolol={true}/>) - expect(screen.getByTestId("box")).toBeInTheDocument() - expect(screen.getByTestId("box")).toHaveAttribute('data-lolol') - }) - -}) - diff --git a/libs_deprecated/juno-ui-components/src/components/Box/index.js b/libs_deprecated/juno-ui-components/src/components/Box/index.js deleted file mode 100644 index 44663c5dc..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Box/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Box } from "./Box.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.component.js b/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.component.js deleted file mode 100644 index b7d8c182e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.component.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { Children } from "react" -import PropTypes from "prop-types" -import { BreadcrumbItem } from "../BreadcrumbItem/index" -import { Stack } from "../Stack/Stack.component" -import { Icon } from "../Icon/Icon.component" - -const breadcrumbstyles = ` - -` -/** Generic breadcrumb component. Use this to Wrap `Breadcrumb` items or custom children in a breadcrumb. */ -export const Breadcrumb = ({ children, className, ...props }) => { - const breadcrumbArray = Children.toArray(children) - const breadcrumbArrayWithSeparators = [] - - breadcrumbArray.forEach((child, i) => { - breadcrumbArrayWithSeparators.push( - <React.Fragment key={i}> - <BreadcrumbItem {...child.props} /> - {i < breadcrumbArray.length - 1 ? <Icon icon="chevronRight" /> : null} - </React.Fragment> - ) - }) - - return ( - <Stack - className={`juno-breadcrumb ${breadcrumbstyles} ${className}`} - gap="1" - key="stck" - {...props} - > - {breadcrumbArrayWithSeparators} - </Stack> - ) -} - -Breadcrumb.propTypes = { - /** Pass a custom className */ - className: PropTypes.string, - /** The children to render. Typically use the BreadcrumbItem component. */ - children: PropTypes.node, -} - -Breadcrumb.defaultProps = { - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.stories.js b/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.stories.js deleted file mode 100644 index 3ef170b69..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.stories.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Breadcrumb } from "./index" -import { BreadcrumbItem } from "../BreadcrumbItem/index" -// import { Default as Item } from '../BreadcrumbItem/BreadcrumbItem.stories'; -// import { Home as HomeItem } from '../BreadcrumbItem/BreadcrumbItem.stories'; -// import { Active as ActiveItem } from '../BreadcrumbItem/BreadcrumbItem.stories'; -// import { Disabled as DisabledItem } from '../BreadcrumbItem/BreadcrumbItem.stories'; -// import { WithIcon as ItemWithIcon } from '../BreadcrumbItem/BreadcrumbItem.stories'; - -const Template = ({ children, ...args }) => { - return <Breadcrumb {...args}>{children}</Breadcrumb> -} - -export default { - title: "Components/Breadcrumb/Breadcrumb", - component: Breadcrumb, - argTypes: { - children: { - control: false, - }, - }, -} - -export const Default = { - render: Template, - args: { - children: [ - <BreadcrumbItem key="1" label="" icon="home" />, - <BreadcrumbItem key="2" label="Breadcrumb Item" />, - <BreadcrumbItem key="3" label="Breadcrumb Item with Icon" icon="place" />, - <BreadcrumbItem key="4" label="Disabled Item " disabled />, - <BreadcrumbItem key="5" label="Active Item" active />, - ], - }, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.test.js b/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.test.js deleted file mode 100644 index bac69c660..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/Breadcrumb.test.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Breadcrumb } from "./index" - - -describe("Breadcrumb", () => { - - test("renders a breadcrumb with text as passed", async () => { - render(<Breadcrumb data-testid="breadcrumb" />) - expect(screen.getByTestId("breadcrumb")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumb")).toHaveClass("juno-breadcrumb") - }) - - test("renders a custom className as passed", async () => { - render(<Breadcrumb data-testid="breadcrumb" className="my-custom-class" />) - expect(screen.getByTestId("breadcrumb")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumb")).toHaveClass('my-custom-class') - }) - - test("renders all props as passed", async () => { - render(<Breadcrumb data-testid="breadcrumb" data-lolol={true}/>) - expect(screen.getByTestId("breadcrumb")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumb")).toHaveAttribute('data-lolol') - }) - -}) - diff --git a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/index.js b/libs_deprecated/juno-ui-components/src/components/Breadcrumb/index.js deleted file mode 100644 index 3ae139fa1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Breadcrumb/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Breadcrumb } from "./Breadcrumb.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.js b/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.js deleted file mode 100644 index 0323fb293..000000000 --- a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.component.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { Icon } from "../Icon/index.js" -import { knownIcons } from "../Icon/Icon.component.js" - -const breadcrumbitemstyles = ` - jn-text-sm - jn-text-theme-high - jn-flex - jn-gap-1 - jn-items-center -` - -const breadcrumblinkstyles = ` - jn-text-theme-high - jn-inline-flex -` - -const disabledstyles = ` - jn-text-theme-disabled - jn-pointer-events-none -` - -/** An individual item in a breadcrumb */ -export const BreadcrumbItem = ({ - icon, - href, - label, - ariaLabel, - active, - children, - onClick, - disabled, - className, - ...props -}) => { - - const icn = icon ? <Icon icon={icon} size="18" color="jn-text-theme-default" className={ label && label.length ? "jn-mr-1" : "" } /> : null - - const handleClick = (event) => { - onClick && onClick(event) - } - - return ( - - children ? - children - : - <span className={ - `juno-breadcrumb-item - ${breadcrumbitemstyles} - ${ disabled ? "juno-breadcrumb-item-disabled" : "" } - ${ active ? "juno-breadcrumb-item-active" : "" } - ${className}` - } {...props} - > - { active || disabled ? - <> - { icn } - { label } - </> - : - <a href={href} - className={`${breadcrumblinkstyles} `} - aria-label={ariaLabel || label} - onClick={ handleClick } - > - { icn } - { label } - </a> - } - </span> - - ) -} - -BreadcrumbItem.propTypes = { - /** pass an icon name */ - icon: PropTypes.oneOf(knownIcons), - /** The link of the path/route/page the breacrumb item points to */ - href: PropTypes.string, - /** The text to render in the breadcumb item */ - label: PropTypes.string, - /** Pass an aria-label */ - ariaLabel: PropTypes.string, - /** Whether the item is the last / active item */ - active: PropTypes.bool, - /** Pass an onClick handler */ - onClick: PropTypes.func, - /** Whether the item is disabled */ - disabled: PropTypes.bool, - /** Pass a custom className */ - className: PropTypes.string, - /** The children of the item */ - children: PropTypes.node, -} - -BreadcrumbItem.defaultProps = { - icon: null, - href: "#", - label: "Item", - ariaLabel: "", - active: false, - onClick: undefined, - disabled: false, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.stories.js b/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.stories.js deleted file mode 100644 index c7f24c4c5..000000000 --- a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.stories.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { BreadcrumbItem } from './index'; -import { knownIcons } from '../Icon/Icon.component.js'; - -const Template = (args) => { - return <BreadcrumbItem {...args} />; -}; - -export default { - title: 'Components/Breadcrumb/BreadcrumbItem', - component: BreadcrumbItem, - argTypes: { - icon: { - options: ['default', ...knownIcons], - control: { type: 'select' }, - }, - children: { - control: false, - }, - }, -}; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'A default breadcrumb item', - }, - }, - }, - - args: { - label: 'Breadcrumb Item', - }, -}; - -export const WithIcon = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Pass any available icon name to render an additional icon for the item.', - }, - }, - }, - - args: { - icon: 'place', - label: 'Breadcrumb Item with Icon', - }, -}; - -export const Active = { - render: Template, - - parameters: { - docs: { - description: { - story: 'An active item represents the current page.', - }, - }, - }, - - args: { - label: 'Active Breadcrumb Item', - active: true, - }, -}; - -export const Disabled = { - render: Template, - - parameters: { - docs: { - description: { - story: 'A disabled breadcrumb item.', - }, - }, - }, - - args: { - label: 'Disabled Breadcrumb Item', - disabled: true, - }, -}; - -export const Home = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Typically the first item in a breadcrumb.', - }, - }, - }, - - args: { - label: '', - icon: 'home', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.test.js b/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.test.js deleted file mode 100644 index b8776076c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/BreadcrumbItem.test.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { BreadcrumbItem } from "./index" -import { Button } from "../Button/index" - - -describe("BreadcrumbItem", () => { - - test("renders a breadcrumb item with text as passed", async () => { - render(<BreadcrumbItem data-testid="breadcrumbitem" />) - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveClass("juno-breadcrumb-item") - }) - - test("returns children as passed", async () => { - render( - <BreadcrumbItem> - <Button label="Test Button"/> - </BreadcrumbItem>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveTextContent("Test Button") - }) - - test("renders an icon as passed", async () => { - render(<BreadcrumbItem icon="help" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("title", "Help") - }) - - test("renders a label as passed", async () => { - render(<BreadcrumbItem data-testid="breadcrumbitem" label="My Item" />) - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveTextContent("My Item") - }) - - test("renders an aria-label as passed", async () => { - render(<BreadcrumbItem href="#" ariaLabel="My Item" />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("aria-label", "My Item") - }) - - test("renders the label as aria-label by default", async () => { - render(<BreadcrumbItem href="#" label="My Item" />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("aria-label", "My Item") - }) - - test("renders an active item that is not a link as passed", async () => { - render(<BreadcrumbItem href="#" active data-testid="breadcrumbitem"/>) - expect(screen.queryByRole("link")).not.toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveClass("juno-breadcrumb-item-active") - }) - - test("renders a disabled item as passed", async () => { - const onClickSpy = jest.fn() - render(<BreadcrumbItem href="#" disabled data-testid="breadcrumbitem" onClick={onClickSpy} />) - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveClass("juno-breadcrumb-item-disabled") - screen.getByTestId("breadcrumbitem").click() - expect(onClickSpy).not.toHaveBeenCalled() - }) - - test("executes an onClick handler as passed", async () => { - const onClickSpy = jest.fn() - render(<BreadcrumbItem onClick={onClickSpy} />) - screen.getByRole("link").click() - expect(onClickSpy).toHaveBeenCalled() - }) - - test("renders a custom className as passed", async () => { - render(<BreadcrumbItem data-testid="breadcrumbitem" className="my-custom-class" />) - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveClass('my-custom-class') - }) - - test("renders all props as passed", async () => { - render(<BreadcrumbItem data-testid="breadcrumbitem" data-lolol={true}/>) - expect(screen.getByTestId("breadcrumbitem")).toBeInTheDocument() - expect(screen.getByTestId("breadcrumbitem")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/index.js b/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/index.js deleted file mode 100644 index 7dd3339a4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/BreadcrumbItem/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { BreadcrumbItem } from "./BreadcrumbItem.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Button/Button.component.js b/libs_deprecated/juno-ui-components/src/components/Button/Button.component.js deleted file mode 100644 index 3a8520ca0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Button/Button.component.js +++ /dev/null @@ -1,241 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import "./button.scss" -import { Icon } from "../Icon/index.js" -import { knownIcons } from "../Icon/Icon.component.js" -import { Spinner } from "../Spinner/index.js" - -const btnBase = ` - jn-font-bold - jn-inline-flex - jn-justify-center - jn-items-center - jn-rounded - jn-shadow-sm - jn-w-auto - focus:jn-outline-none - focus-visible:jn-ring-2 - focus-visible:jn-ring-theme-focus - focus-visible:jn-ring-offset-1 - focus-visible:jn-ring-offset-theme-focus - disabled:jn-opacity-50 - disabled:jn-cursor-not-allowed - disabled:jn-pointer-events-none -` - -const btnSmallBase = ` - jn-text-sm - jn-leading-5 -` - -const btnDefaultBase = ` - jn-text-base - jn-leading-6 -` - -const btnSmallDefaultPadding = ` - jn-py-[0.3125rem] - jn-px-[0.5rem] -` - -const btnSmallSubduedPadding = ` - jn-py-[0.25rem] - jn-px-[0.4375rem] -` - -const btnDefaultPadding = ` - jn-py-[0.4375rem] - jn-px-[0.625rem] -` - -const btnDefaultSubduedPadding = ` - jn-py-[0.375rem] - jn-px-[0.5625rem] -` - -const getButtonPadding = (size, variant) => { - if (size === "small") { - return (variant === "subdued" ? `${btnSmallSubduedPadding}` : `${btnSmallDefaultPadding}`) - } else { - return (variant === "subdued" ? `${btnDefaultSubduedPadding}`: `${btnDefaultPadding}`) - } -} - -const btnIconSmall = ` - jn-mr-2 -` - -const btnIconDefault = ` - jn-mr-2 -` - -const iconClasses = (size) => { - if (size === "small") { - return `${btnIconSmall}` - } else { - return `${btnIconDefault}` - } -} - -const progressClass = (progress) => { - const progClass = progress ? `in-progress` : `` - return progClass -} - -const spinnerColorClass = (variant, disabled) => { - switch ( variant ) { - case "default": - return "jn-text-theme-accent" - case "primary": - return "jn-text-white" - case "primary-danger": - return "jn-text-white" - default: - return "" - } -} - -/** - * The basic button component. Use this for `onClick` interactions. - */ -export const Button = React.forwardRef( - ( - { - label, - title, - variant, - size, - disabled, - href, - icon, - className, - onClick, - children, - progress, - progressLabel, - ...props - }, - ref - ) => { - const theVariant = variant || "default" - const titleValue = title || label || "" - - const buttonIcon = progress ? ( - <Spinner - size={ size === "small" ? "1.125rem" : "1.5rem" } - color={`${spinnerColorClass(theVariant, disabled)}`} - /> - ) : icon ? ( - <Icon - icon={icon} - className={`juno-button-icon ${ - label || children ? iconClasses(size) : "" - } `} - size={ size === "small" ? "1.125rem" : "1.5rem" } - /> - ) : null - - const buttonLabel = - progress && progressLabel ? progressLabel : label || children - - const handleClick = (event) => { - onClick && onClick(event) - } - - const button = ( - <button - type="button" - className={` - juno-button - juno-button-${theVariant} - juno-button-${size}-size - ${btnBase} - ${ size === 'small' ? btnSmallBase : btnDefaultBase } - ${ getButtonPadding(size, variant) } - ${progressClass(progress)} - ${className}` - } - disabled={disabled} - onClick={handleClick} - title={titleValue} - ref={ref} - {...props} - > - {buttonIcon} - {buttonLabel} - </button> - ) - - const anchor = ( - <a - href={href} - role="button" - className={` - juno-button - juno-button-${theVariant} - juno-button-${size}-size - ${btnBase} - ${ size === 'small' ? btnSmallBase : btnDefaultBase } - ${ getButtonPadding(size, variant) } - ${progressClass(progress)} - ${className} - `} - disabled={disabled} - onClick={onClick} - title={titleValue} - ref={ref} - {...props} - > - {buttonIcon} - {buttonLabel} - </a> - ) - - return href ? anchor : button - } -) - -Button.propTypes = { - /** Choose a variant for your purpose. May leave empty to get default button. */ - variant: PropTypes.oneOf(["primary", "primary-danger", "default", "subdued"]), - /** Leave empty for default size */ - size: PropTypes.oneOf(["small", "default"]), - /** Whether the button is disabled */ - disabled: PropTypes.bool, - /** Optionally specify an href. This will turn the Button into an <a> element */ - href: PropTypes.string, - /** Button label can be passed like this or as children */ - label: PropTypes.string, - /** Specify title for accessibility. Gets value of label if no title specified */ - title: PropTypes.string, - /** Pass the name of an icon the button should show. Can be any icon included with Juno. */ - icon: PropTypes.oneOf(knownIcons), - /** Pass a className */ - className: PropTypes.string, - /** Click handler */ - onClick: PropTypes.func, - /** Set to true to disable */ - disabled: PropTypes.bool, - /** Whether the button action is in progress */ - progress: PropTypes.bool, - /** Display an alternative label while the button action is in progress */ - progressLabel: PropTypes.string, -} - -Button.defaultProps = { - variant: undefined, - size: "default", - disabled: null, - icon: null, - className: "", - href: null, - title: null, - onClick: undefined, - progress: false, - progressLabel: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/Button/Button.stories.js b/libs_deprecated/juno-ui-components/src/components/Button/Button.stories.js deleted file mode 100644 index ffac07892..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Button/Button.stories.js +++ /dev/null @@ -1,453 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Button } from './index'; -import { Icon } from '../Icon/index.js'; -import { knownIcons } from '../Icon/Icon.component.js'; -import { ContentArea } from '../ContentArea/index'; -import { Container } from '../Container/index'; - -export default { - title: 'Components/Button', - component: Button, - argTypes: { - icon: { - options: ['default', ...knownIcons], - control: { type: 'select' }, - }, - variant: { - options: ['default', 'primary', 'primary-danger', 'subdued'], - control: { type: 'select' }, - }, - }, -}; - -export const Default = { - parameters: { - docs: { - description: { - story: 'The default button is a neutral button that can be used multiple times on a page', - }, - }, - }, - - args: { - label: 'Default', - }, -}; - -export const Subdued = { - parameters: { - docs: { - description: { - story: - 'A subdued button variant, mostly used to create contrast to an primary button concerning the same usage context, or when multiple default buttons would be too much.', - }, - }, - }, - - args: { - variant: 'subdued', - label: 'Subdued', - }, -}; - -export const Primary = { - parameters: { - docs: { - description: { - story: - 'Only use the primary button **maximum once per page** for the preferred user action', - }, - }, - }, - - args: { - variant: 'primary', - label: 'Primary', - }, -}; - -export const PrimaryDanger = { - parameters: { - docs: { - description: { - story: 'Use this button sparingly and only for dangerous or destructive actions', - }, - }, - }, - - args: { - variant: 'primary-danger', - label: 'Primary Danger', - }, -}; - -export const DefaultSize = { - args: { - label: 'Default', - }, -}; - -export const Small = { - args: { - size: 'small', - label: 'Small', - }, -}; - -export const Disabled = { - parameters: { - docs: { - description: { story: 'Disable any button by adding `disabled` to it.' }, - }, - }, - - args: { - ...Default.args, - label: 'Default Disabled', - disabled: true, - }, -}; - -export const SubduedDisabled = { - parameters: { - docs: { - description: { story: 'Disable any button by adding `disabled` to it.' }, - }, - }, - - args: { - ...Subdued.args, - label: 'Subdued Disabled', - disabled: true, - }, -}; - -export const PrimaryDisabled = { - parameters: { - docs: { - description: { story: 'Disable any button by adding `disabled` to it.' }, - }, - }, - - args: { - ...Primary.args, - label: 'Primary Disabled', - disabled: true, - }, -}; - -export const PrimaryDangerDisabled = { - parameters: { - docs: { - description: { - story: 'Disable a Primary Danger button by adding `disabled` to it.', - }, - }, - }, - - args: { - ...PrimaryDanger.args, - disabled: true, - }, -}; - -export const DefaultWithIcon = { - parameters: { - docs: { - story: 'Default Button with icon', - }, - }, - - args: { - ...Default.args, - label: 'Default with Icon', - icon: 'warning', - }, -}; - -export const SubduedWithIcon = { - parameters: { - docs: { - description: { - story: 'Subdued Button with Icon', - }, - }, - }, - - args: { - ...Subdued.args, - icon: 'warning', - label: 'Subdued with Icon', - }, -}; - -export const SmallWithIcon = { - parameters: { - docs: { - description: { - story: 'Small Button with Icon', - }, - }, - }, - - args: { - ...Small.args, - icon: 'warning', - }, -}; - -export const IconOnlyButton = {}; -(IconOnlyButton.docs = { - description: { - story: 'A button with a Icon but no label. The icon name can be passed as a prop.', - }, -}), - (IconOnlyButton.args = { - icon: 'warning', - }); - -export const IconOnlyAsChild = {}; -(IconOnlyAsChild.docs = { - description: { - story: - 'A button with a Icon but no label, an Icon can also be passed as a child. Hover, active, etc. states of the icon ave to be handled manually when passing an icon as a child though.', - }, -}), - (IconOnlyAsChild.args = { - children: <Icon />, - }); - -export const LinkAsButton = { - parameters: { - docs: { - description: { - story: - 'If you want to render a link that looks like a button pass an "href" to the Button. All other props work the same as for regular buttons', - }, - }, - }, - - args: { - ...Primary.args, - label: 'Link as button', - href: '#link', - }, -}; - -export const LinkAsButtonWithIcon = { - parameters: { - docs: { - description: { - story: 'Link styled as a button including an icon.', - }, - }, - }, - - args: { - ...Primary.args, - icon: 'warning', - label: 'Link as button with Icon', - href: '#', - }, -}; - -export const DefaultButtonInProgress = { - parameters: { - docs: { - description: { - story: 'Default Button with an action in progress', - }, - }, - }, - - args: { - ...Default.args, - progress: true, - }, -}; - -export const IconButtonInProgress = { - parameters: { - docs: { - description: { - story: 'Icon Button with an action in progress', - }, - }, - }, - - args: { - ...Default.args, - label: 'Default with Icon', - icon: 'warning', - progress: true, - }, -}; - -export const DefaultButtonInProgressWithProgressLabel = { - parameters: { - docs: { - description: { - story: - 'Default Button with an action in oprogress and an alternate label while in progress', - }, - }, - }, - - args: { - ...Default.args, - label: 'Default with Icon', - icon: 'warning', - progress: true, - progressLabel: 'In Progress…', - }, -}; - -export const SubduedButtonInProgress = { - parameters: { - docs: { - description: { - story: 'Subdued Button with an action in progress', - }, - }, - }, - - args: { - ...Subdued.args, - progress: true, - progressLabel: 'Subdued Button in Progress…', - }, -}; - -export const PrimaryButtonWithIconInProgress = { - parameters: { - docs: { - description: { - story: 'Primary Button with action in progress', - }, - }, - }, - - args: { - ...Primary.args, - progress: true, - progressLabel: 'Primary Button in Progress…', - }, -}; - -export const PrimaryDangerButtonInProgress = { - parameters: { - docs: { - description: { - story: 'Primary Danger Button with action in progress', - }, - }, - }, - - args: { - ...PrimaryDanger.args, - progress: true, - progressLabel: 'Primary Danger Button in Progress…', - }, -}; - -export const LinkAsButtonInProgress = { - parameters: { - docs: { - description: { - story: - 'Link as button with action in progress. Should hardly ever be used, just to check consistent styling.', - }, - }, - }, - - args: { - ...LinkAsButton.args, - progress: true, - progressLabel: 'Link as button in Progress…', - }, -}; - -export const LinkAsButtonWithIconInProgress = { - parameters: { - docs: { - description: { - story: - 'Link as button with an icon and action in progress. Should hardly ever be used, just to check consistent styling.', - }, - }, - }, - - args: { - ...LinkAsButtonWithIcon.args, - progress: true, - progressLabel: 'Link as button with Icon in Progress…', - }, -}; - -export const DisabledInProgress = { - parameters: { - docs: { - description: { - story: 'Disabled Default Button in Progress', - }, - }, - }, - - args: { - ...Disabled.args, - progress: true, - }, -}; - -export const PrimaryDisabledInProgress = { - parameters: { - docs: { - description: { - story: 'Disabled Primnary Button with action in progress', - }, - }, - }, - - args: { - ...PrimaryDisabled.args, - progress: true, - progressLabel: 'Disabled Primary Button in Progress…', - }, -}; - -export const PrimaryDangerDisabledInProgress = { - parameters: { - docs: { - description: { - story: 'Disabled Primary Danger Button in Progress…', - }, - }, - }, - - args: { - ...PrimaryDangerDisabled.args, - progress: true, - progressLabel: 'Disabled Primary Danger Button in Progress…', - }, -}; - -export const SmallInProgress = { - parameters: { - docs: { - description: { - story: 'Small Button in Progress', - }, - }, - }, - - args: { - ...Small.args, - progress: true, - progressLabel: 'Small in Progress…', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Button/Button.test.js b/libs_deprecated/juno-ui-components/src/components/Button/Button.test.js deleted file mode 100644 index 14ee7f6c2..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Button/Button.test.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Button } from "./index" - -describe("Button", () => { - test("renders a button with text passed as label", async () => { - render(<Button label="Click me"></Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveTextContent("Click me") - }) - - test("renders a button with text passed as children", async () => { - render(<Button>Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveTextContent("Click me") - }) - - test("renders a disabled button as passed", async () => { - render(<Button disabled />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute("disabled") - }) - - // it seems we can't properly check whether it's an <a> element that is being rendered - // so for now ensure that it responds to the button aria role and has an href attribute - test("renders an <a> element with role button if href is passed", async () => { - render(<Button href="http://blah.com" />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute("href") - }) - - test("onclick handler is called as passed", () => { - const onClickSpy = jest.fn() - render(<Button onClick={onClickSpy} />) - screen.getByRole("button").click() - expect(onClickSpy).toHaveBeenCalled() - }) - - test("onclick handler is not called when disabled", () => { - const onClickSpy = jest.fn() - render(<Button disabled onClick={onClickSpy} />) - screen.getByRole("button").click() - expect(onClickSpy).not.toHaveBeenCalled() - }) - - test("renders a title", async () => { - render(<Button title="Click me title">Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute( - "title", - "Click me title" - ) - }) - - test("renders label as title if no title given", async () => { - render(<Button label="Click me label">Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute( - "title", - "Click me label" - ) - }) - - test("renders a default button", async () => { - render(<Button>Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-button-default") - }) - - test("renders a primary button", async () => { - render(<Button variant="primary">Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-button-primary") - }) - - test("renders a primary-danger button", async () => { - render(<Button variant="primary-danger">Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-button-primary-danger") - }) - - test("renders a disabled button", async () => { - render(<Button disabled>Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute("disabled") - }) - - test("renders an icon as passed", async () => { - render(<Button icon="warning">Click Me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "warning") - }) - - test("renders a small button", async () => { - render(<Button size="small">Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-button-small-size") - }) - - test("renders a default sized button", async () => { - render(<Button>Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-button-default-size") - }) - - test("renders a custom className as passed", async () => { - render(<Button className="my-custom-classname">Click me</Button>) - expect(screen.getByRole("button")).toHaveClass("my-custom-classname") - }) - - test("renders a default in progress button as passed", async () => { - render(<Button progress={true}>Click me</Button>) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("in-progress") - expect(screen.getByRole("progressbar")).toHaveClass("juno-spinner") - }) - - test("renders a default in progress button with a progressLabel as passed", async () => { - render( - <Button progress={true} progressLabel="In Progress…"> - Click me - </Button> - ) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("in-progress") - expect(screen.getByRole("button")).toHaveTextContent("In Progress…") - }) - - test("renders all props as passed", async () => { - render(<Button id="button-1" data-lolol={true} />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute("id", "button-1") - expect(screen.getByRole("button")).toHaveAttribute("data-lolol") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Button/button.scss b/libs_deprecated/juno-ui-components/src/components/Button/button.scss deleted file mode 100644 index 471bea4d0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Button/button.scss +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -// handle button colours here, not in tw because of overall complexity, mostly singular colors, gradients, etc; and conflicting bg-colors and bg-images: - - -.juno-button-default { - background-color: var(--color-button-default-bg); - color: var(--color-button-default-text); - - &:hover { - background-color: var(--color-button-default-hover-bg); - color: var(--color-button-default-hover-text); - } - - &:active { - background-color: var(--color-button-default-active-bg); - border-color: var(--color-button-default-active-border); - color: var(--color-button-default-active-text); - } - -} - -.juno-button-subdued { - background-color: var(--color-button-subdued-bg); - border: 1px solid var(--color-button-subdued-border); - color: var(--color-button-subdued-text); - - &:hover { - background-color: var(--color-button-subdued-hover-bg); - border-color: var(--color-button-subdued-hover-border); - color: var(--color-button-subdued-hover-text); - } - - &:active { - background-color: var(--color-button-subdued-active-bg); - border-color: var(--color-button-subdued-active-border); - color: var(--color-button-subdued-active-text); - } - -} - -.juno-button-primary { - background-color: var(--color-button-primary-bg); - color: var(--color-button-primary-text); - - &:hover { - background-color: var(--color-button-primary-hover-bg); - color: var(--color-button-primary-hover-text); - } - - &:active { - background-color: var(--color-button-primary-active-bg); - color: var(--color-button-primary-active-text); - } - -} - -.juno-button-primary-danger { - background-color: var(--color-button-primary-danger-bg); - color: var(--color-button-primary-danger-text); - - &:hover { - background-color: var(--color-button-primary-danger-hover-bg); - color: var(--color-button-primary-danger-hover-text); - } - - &:active { - background-color: var(--color-button-primary-danger-active-bg); - color: var(--color-button-primary-danger-active-text); - } - -} diff --git a/libs_deprecated/juno-ui-components/src/components/Button/index.js b/libs_deprecated/juno-ui-components/src/components/Button/index.js deleted file mode 100644 index 43a0e64e4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Button/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Button } from "./Button.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.component.js b/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.component.js deleted file mode 100644 index 8b09503f0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.component.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { Stack } from "../Stack/Stack.component" - -const buttonrowstyles = ` - jn-flex - jn-flex-row - jn-justify-end - jn-gap-2 -` - -/** A container to hold one or multiple buttons and space and align them. */ -export const ButtonRow = ({ - children, - className, - ...props -}) => { - return ( - <Stack gap="2" distribution="end" className={`juno-button-row ${className}`} {...props} > - {children} - </Stack> - ) -} - -ButtonRow.propTypes = { - /** Add a class to the ButtonRow */ - className: PropTypes.string, - /** Children to render in the ButtonRow */ - children: PropTypes.node, -} - -ButtonRow.defaultProps = { - children: null, - className: "", -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.stories.js b/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.stories.js deleted file mode 100644 index 2f3007380..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.stories.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { ButtonRow } from "./index.js" -import { Button } from "../Button/index.js" - -export default { - title: "Forms/ButtonRow", - component: ButtonRow, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, -} - -const Template = ({ children, ...args }) => ( - <ButtonRow {...args}>{children}</ButtonRow> -) - -export const Default = { - render: Template, - - args: { - name: "Default ButtonRow", - children: [ - <Button label="Cancel" title="Cancel" />, - <Button label="Save" title="Save" variant="primary" />, - ], - }, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.test.js b/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.test.js deleted file mode 100644 index ec2b62073..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ButtonRow/ButtonRow.test.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Button } from "../Button/index" -import { ButtonRow } from "./index" - -describe("ButtonRow", () => { - - - test("renders a ButtonRow", async () => { - render(<ButtonRow data-testid="button-row" />) - expect(screen.getByTestId("button-row")).toBeInTheDocument() - }) - - test("renders children as passed", async () => { - render( - <ButtonRow> - <Button label="My Button" title="My Button" /> - </ButtonRow> - ) - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<ButtonRow data-testid="my-button-row" className="my-classname" />) - expect(screen.getByTestId("my-button-row")).toHaveClass("my-classname") - }) - - test("renders all props as passed", async () => { - render(<ButtonRow data-testid="my-button-row" data-lolol="some-prop" />) - expect(screen.getByTestId("my-button-row")).toHaveAttribute("data-lolol", 'some-prop') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ButtonRow/index.js b/libs_deprecated/juno-ui-components/src/components/ButtonRow/index.js deleted file mode 100644 index 471af06ba..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ButtonRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ButtonRow } from "./ButtonRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.component.js b/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.component.js deleted file mode 100644 index 2fed6ad0d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.component.js +++ /dev/null @@ -1,380 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect, useMemo, useContext, useId } from "react" -import PropTypes from "prop-types" -import { CheckboxGroupContext } from "../CheckboxGroup/CheckboxGroup.component" -import { Label } from "../Label/index" -import { Icon } from "../Icon/Icon.component" -import { FormHint } from "../FormHint/FormHint.component" - -const wrapperStyles = ` - jn-inline-flex - jn-items-center -` - -const inputstyles = ` - jn-w-4 - jn-h-4 - jn-opacity-0 - jn-z-50 -` - -const mockcheckboxstyles = ` - jn-relative - jn-w-4 - jn-h-4 - jn-rounded-sm - jn-bg-theme-checkbox - jn-cursor-pointer - focus:jn-outline-none - focus:jn-ring-2 - focus:jn-ring-theme-focus -` - -const mockfocusstyles = ` - jn-ring-2 - jn-ring-theme-focus -` - -const mockcheckmarkstyles = ` - jn-absolute - jn-top-0 - jn-left-0 - jn-text-theme-checkbox-checked - jn-fill-current -` - - -const mockindeterminatestyles = ` - jn-absolute - jn-w-2 - jn-h-0.5 - jn-top-1.5 - jn-left-[.2rem] - jn-inline-block - jn-bg-theme-focus -` - -const mockdisabledstyles = ` - jn-pointer-events-none - jn-opacity-50 - jn-cursor-not-allowed -` - -const noBorderStyles = ` - jn-border - jn-border-transparent -` - -const errorstyles = ` - jn-border - jn-border-theme-error -` - -const successstyles = ` - jn-border - jn-border-theme-success -` - -const labelStyles = ` - jn-leading-0 - jn-ml-2 -` - -const iconStyles = ` - jn-ml-1 -` - -const hintStyles = ` - jn-mt-0 - jn-ml-6 -` - - - -export const Checkbox = ({ - checked, - className, - disabled, - errortext, - helptext, - id, - indeterminate, - invalid, - label, - name, - onChange, - onClick, - required, - successtext, - valid, - value, - ...props -}) => { - - // Utility - const isNotEmptyString = (str) => { - return !(typeof str === 'string' && str.trim().length === 0) - } - - const uniqueId = () => ( - "juno-checkbox-" + useId() - ) - - // Consume and deconstruct the context so we won't get errors but 'undefined' when trying to access a group context property in case there is none: - const checkboxGroupContext = useContext(CheckboxGroupContext) - const { - selectedOptions: groupSelectedOptions, - name: groupName, - disabled: groupDisabled, - handleCheckboxChange: groupHandleCheckboxChange, - updateSelectedValue: updateGroupSelectedValue, - } = checkboxGroupContext || {} - - // Lazily initialise the Checkbox: - const initialChecked = () => { - if (checkboxGroupContext) { - if (groupSelectedOptions && groupSelectedOptions.includes(value)) { - return true - } else { - return false - } - } else { - return checked ? true : false - } - } - - - const [isChecked, setIsChecked] = useState( initialChecked() ) - const [isIndeterminate, setIsIndeterminate] = useState(false) - const [hasFocus, setHasFocus] = useState(false) - const [isInvalid, setIsInvalid] = useState(false) - const [isValid, setIsValid] = useState(false) - - // Run once to update the parent state to respect and reflect the checked prop if we are in a group context, but parent has no selected options set via its prop: - useEffect(() => { - if (checked && checkboxGroupContext) { - updateGroupSelectedValue(value) - } - }, [] ) - - useEffect(() => { - if (!checkboxGroupContext) { - setIsChecked(checked) - } - }, [checked] ) - - const invalidated = useMemo( - () => invalid || (errortext && isNotEmptyString(errortext) ? true : false), - [invalid, errortext] - ) - const validated = useMemo( - () => valid || (successtext && isNotEmptyString(successtext) ? true : false), - [valid, successtext] - ) - - useEffect( () => { - setIsIndeterminate(indeterminate) - }, [indeterminate]) - - useEffect( () => { - setIsInvalid(invalidated) - }, [invalidated]) - - useEffect( () => { - setIsValid(validated) - }, [validated]) - - const handleChange = (event) => { - setIsChecked(!isChecked) - // If we are in a context, update : - if (groupHandleCheckboxChange && typeof groupHandleCheckboxChange === "function") { - groupHandleCheckboxChange(value) - } - - onChange && onChange(event) - } - - const handleClick = (event) => { - onClick && onClick(event) - } - - const handleFocus = () => { - setHasFocus(true) - } - - const handleBlur = () => { - setHasFocus(false) - } - - const determineChecked = () => { - if (checkboxGroupContext) { - return groupSelectedOptions && groupSelectedOptions.includes(value) ? true : false - } else { - return isChecked - } - } - - const theId = id || uniqueId() - - return ( - <div className="jn-checkbox-outer"> - <div className={`jn-checkbox-wrapper ${wrapperStyles}`}> - <div - className={` - juno-checkbox - ${mockcheckboxstyles} - ${ hasFocus ? mockfocusstyles : "" } - ${ groupDisabled || disabled ? mockdisabledstyles : "" } - ${ isInvalid ? errorstyles : "" } - ${ isValid ? successstyles : "" } - ${ isInvalid || isValid ? "" : noBorderStyles } - ${className} - `} - {...props} - > - { determineChecked() ? <svg - xmlns="http://www.w3.org/2000/svg" - className={`${mockcheckmarkstyles}`} - width="16" - height="16" - viewBox="0 0 16 16"> - <polygon points="5.75 11.15 2.6 8 1.55 9.05 5.75 13.25 14.75 4.25 13.7 3.2"/> - </svg> - : - "" } - <input - checked={ determineChecked() } - className={` - ${inputstyles} - ${ isInvalid ? "juno-checkbox-invalid" : ""} - ${ isValid ? "juno-checkbox-valid" : ""} - ${ groupDisabled || disabled ? "jn-cursor-not-allowed" : ""} - `} - disabled={ groupDisabled || disabled } - id={theId} - name={groupName || name} - onBlur={handleBlur} - onChange={handleChange} - onClick={handleClick} - onFocus={handleFocus} - type="checkbox" - value={value} - /> - { isIndeterminate && !determineChecked() ? - <div className={`${mockindeterminatestyles}`}></div> - : - "" } - </div> - { label && isNotEmptyString(label) ? - <> - <Label - text={label} - htmlFor={theId} - disabled={groupDisabled || disabled} - required={required} - className={`${labelStyles}`} - /> - {isInvalid ? ( - <Icon - icon="dangerous" - color="jn-text-theme-error" - size="1.125rem" - className={` - ${iconStyles} - ${ groupDisabled || disabled ? "jn-opacity-50" :""} - `} - /> - ) : ""} - {isValid ? ( - <Icon - icon="checkCircle" - color="jn-text-theme-success" - size="1.125rem" - className={` - ${iconStyles} - ${disabled ? "jn-opacity-50" :""} - `} - /> - ) : ""} - </> - : - "" - } - </div> - { errortext && isNotEmptyString(errortext) ? - <FormHint text={errortext} variant="error" className={`${hintStyles}`} /> - : - "" - } - { successtext && isNotEmptyString(successtext) ? - <FormHint text={successtext} variant="success" className={`${hintStyles}`} /> - : - "" - } - { helptext && isNotEmptyString(helptext) ? - <FormHint text={helptext} className={`${hintStyles}`} /> - : - "" - } - </div> - ) -} - -Checkbox.propTypes = { - /** Whether the Checkbox is checked */ - checked: PropTypes.bool, - /** Pass a custom className */ - className: PropTypes.string, - /** Whether the Checkbox is disabled */ - disabled: PropTypes.bool, - /** A text to render when the Checkbox has an error or could not be validated */ - errortext: PropTypes.node, - /** A helptext to render to explain meaning and significance of the Checkbox */ - helptext: PropTypes.node, - /** The id of the Radio. An id will be automatically generated if not passed. */ - id: PropTypes.string, - /** Whether the Checkbox is indeterminate. Applicable ONLY if the Checkbox represents multiple child Checkboxes with non--identical checked state. */ - indeterminate: PropTypes.bool, - /** Whether the Checkbox was validated unsuccessfully */ - invalid: PropTypes.bool, - /** The label of the Checkbox */ - label: PropTypes.string, - /** The name of the Checkbox */ - name: PropTypes.string, - /** handler to be executed when the Checkbox changes. */ - onChange: PropTypes.func, - /** handler to be executed when the Checkbox is clicked. */ - onClick: PropTypes.func, - /** Whether the Checkbox is required */ - required: PropTypes.bool, - /** A text to render when the Checkbox was successfully validated */ - successtext: PropTypes.node, - /** Whether the Checkbox was successfully validated */ - valid: PropTypes.bool, - /** The value of the Checkbox */ - value: PropTypes.string, -} - -Checkbox.defaultProps = { - checked: false, - className: "", - disabled: false, - errortext: "", - helptext: "", - id: "", - indeterminate: false, - invalid: false, - label: undefined, - name: "", - onChange: undefined, - onClick: undefined, - required: false, - successtext: "", - valid: false, - value: undefined, -} - diff --git a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.stories.js b/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.stories.js deleted file mode 100644 index c28421cc3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.stories.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Checkbox } from './index.js'; - -export default { - title: 'Forms/Checkbox/Checkbox', - component: Checkbox, - argTypes: { - errortext: { - control: false, - }, - helptext: { - control: false, - }, - successtext: { - control: false, - }, - }, -}; - -export const Default = { - args: {}, -}; - -export const Checked = { - args: { - checked: true, - }, -}; - -export const WithLabel = { - args: { - label: 'Checkbox with Label', - }, -}; - -export const Required = { - args: { - required: true, - label: 'Required Checkbox', - }, -}; - -export const Disabled = { - args: { - disabled: true, - }, -}; - -export const Indeterminate = { - args: { - indeterminate: true, - }, -}; - -export const Valid = { - args: { - valid: true, - }, -}; - -export const Invalid = { - args: { - invalid: true, - }, -}; - -export const ValidWithLabel = { - args: { - valid: true, - label: 'Validated checkbox with label and icon', - successtext: 'This option is valid.', - helptext: 'Validation icons will only show when there is a label on the Checkbox', - }, -}; - -export const InvalidWithLabel = { - args: { - invalid: true, - label: 'Invalidated checkbox with label and icon', - errortext: 'This option is invalid.', - helptext: 'Validation icons will only show when there is a label on the Checkbox', - }, -}; - -export const IndeterminateWithLabel = { - args: { - indeterminate: true, - label: 'Indeterminate checkbox with label', - helptext: - 'A checkbox can be indeterminate as parent of multiple checkboxes with mixed checked states', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.test.js b/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.test.js deleted file mode 100644 index dc48ffb6b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Checkbox/Checkbox.test.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen, fireEvent } from "@testing-library/react" -import { act } from 'react-dom/test-utils'; -import { Checkbox } from "./index" - - -describe("Checkbox", () => { - - test("renders a valid html input type checkbox", async () => { - render(<Checkbox />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute('type', "checkbox") - }) - - test("renders a checkbox with a name as passed", async () => { - render(<Checkbox name="My Checkbox" />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute('name', "My Checkbox") - }) - - test("renders a checkbox with a label", async () => { - render(<Checkbox label="My Checkbox" id="my-checkbox"/>) - expect(screen.getByLabelText("My Checkbox")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toHaveTextContent("My Checkbox") - }) - - test("renders a checkbox with an id as passed", async () => { - render(<Checkbox id="my-checkbox" />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute('id', "my-checkbox") - }) - - test("renders a Checkbox with an auto-generated id if no id was passed", async () => { - render(<Checkbox />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute('id') - expect(screen.getByRole("checkbox").getAttribute("id")).toMatch("juno-checkbox") - }) - - test("renders a Checkbox with an associated label with an id as passed", async () => { - render(<Checkbox id="my-checkbox" label="My Checkbox"/>) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByLabelText("My Checkbox")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toHaveTextContent("My Checkbox") - }) - - test("renders a Checkbox with a label associated by an auto-generated id if no id was passed ", async () => { - render(<Checkbox label="This is a Checkbox" />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByLabelText("This is a Checkbox")).toBeInTheDocument() - }) - - test("renders a checkbox with a value as passed", async () => { - render(<Checkbox value="ValueAsPassed" />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute('value', "ValueAsPassed") - }) - - test("renders a checked checkbox as passed", async () => { - act(() => { - render(<Checkbox checked={true} />) - }) - const checkbox = screen.getByRole('checkbox') - expect(checkbox).toBeInTheDocument() - expect(checkbox).toBeChecked() - }) - - test("renders no checked attribute if false", async () => { - act(() => { - render(<Checkbox checked={false} />) - }) - const checkbox = screen.getByRole('checkbox') - expect(checkbox).toBeInTheDocument() - expect(checkbox).not.toBeChecked() - }) - - test("renders a disabled checkbox as passed", async () => { - render(<Checkbox disabled />) - const checkbox = screen.getByRole('checkbox') - expect(checkbox).toBeInTheDocument() - expect(checkbox).toBeDisabled() - }) - - test("renders an invalid Checkbox as passed", async () => { - render(<Checkbox invalid />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-invalid") - }) - - test("renders a valid Checkbox as passed", async () => { - render(<Checkbox valid />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-valid") - }) - - test("renders a helptext as passed", async () => { - render(<Checkbox helptext="this is a helptext"/>) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass("juno-form-hint-help") - expect(document.querySelector(".juno-form-hint")).toHaveTextContent("this is a helptext") - }) - - test("renders a successtext as passed and validates the Checkbox", async () => { - render(<Checkbox successtext="great success!" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass("juno-form-hint-success") - expect(document.querySelector(".juno-form-hint")).toHaveTextContent("great success!") - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-valid") - }) - - test("renders an errortext as passed and invalidates the Checkbox", async () => { - render(<Checkbox errortext="this is an error!" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass("juno-form-hint-error") - expect(document.querySelector(".juno-form-hint")).toHaveTextContent("this is an error!") - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-invalid") - }) - - test("fires handler on change as passed", async () => { - const onChangeSpy = jest.fn(); - render(<Checkbox onChange={onChangeSpy} />); - act(() => { - screen.getByRole('checkbox').click(); - }) - expect(onChangeSpy).toHaveBeenCalled(); - }) - - test("fires handler on click as passed", async () => { - const onClickSpy = jest.fn(); - render(<Checkbox onClick={onClickSpy} />); - act(() => { - screen.getByRole('checkbox').click(); - }) - expect(onClickSpy).toHaveBeenCalled(); - }) - - test("does not fire a handler on change when disabled", async () => { - const onChangeSpy = jest.fn(); - render(<Checkbox onChange={onChangeSpy} disabled />); - act(() => { - screen.getByRole('checkbox').click(); - }) - expect(onChangeSpy).not.toHaveBeenCalled(); - }) - - test("does not fire a handler on click when disabled", async () => { - const onClickSpy = jest.fn(); - render(<Checkbox onClick={onClickSpy} disabled />); - act(() => { - screen.getByRole('checkbox').click(); - }) - expect(onClickSpy).not.toHaveBeenCalled(); - }) - - test("renders a custom className as passed", async () => { - render(<Checkbox data-testid="23" className="my-custom-classname" />) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveClass('my-custom-classname') - }) - - test("renders all props as passed", async () => { - render(<Checkbox id="check-1" data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Checkbox/index.js b/libs_deprecated/juno-ui-components/src/components/Checkbox/index.js deleted file mode 100644 index 9bb072a7d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Checkbox/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Checkbox } from "./Checkbox.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.component.js b/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.component.js deleted file mode 100644 index a9eb05386..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.component.js +++ /dev/null @@ -1,271 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect, useMemo, createContext, useId } from "react" -import PropTypes from "prop-types" -import { Label } from "../Label/index.js" -import { Icon } from "../Icon/index" -import { FormHint } from "../FormHint/index" - -const checkboxgroupstyles = ` - jn-mb-4 - jn-last:mb-0 -` - -const checkboxgrouplabelstyles = ` - jn-inline-block - jn-mb-1 -` - -const groupstyles = ` - jn-relative - jn-rounded - jn-border - jn-py-1 -` - -const defaultgroupstyles = ` - jn-border-transparent -` - -const validgroupstyles = ` - jn-border-theme-success - jn-px-2 -` - -const invalidgroupstyles = ` - jn-border-theme-error - jn-px-2 -` - -const errortextstyles = ` - jn-text-xs - jn-text-theme-error - jn-mb-2 -` - -const successtextstyles = ` - jn-text-xs - jn-text-theme-success - jn-mb-2 -` - -const iconstyles = ` - jn-absolute - jn-right-2 - jn-top-1.5 -` - - -export const CheckboxGroupContext = createContext() - -export const CheckboxGroup = ({ - children, - className, - disabled, - errortext, - helptext, - id, - invalid, - label, - name, - onChange, - required, - selected, - successtext, - valid, - ...props -}) => { - - // Utility - const isNotEmptyString = (str) => { - return !(typeof str === 'string' && str.trim().length === 0) - } - - const uniqueId = () => ( - "juno-checkboxgroup-" + useId() - ) - - // Create unique identifiers for use with name and id of the group: - const groupName = name || uniqueId() - const groupId = id || uniqueId() - - // Init state variables: - const [selectedOptions, setSelectedOptions] = useState(selected) // undefined, empty array or array of values - const [isValid, setIsValid] = useState(false) - const [isInvalid, setIsInvalid] = useState(false) - - const validated = useMemo( - () => valid || (successtext && successtext.length ? true : false), - [valid, successtext] - ) - const invalidated = useMemo( - () => invalid || (errortext && errortext.length ? true : false), - [invalid, errortext] - ) - - useEffect(() => { - if (selected) { - setSelectedOptions(selected) - } - }, [selected]) - - useEffect(() => { - setIsValid(validated) - }, [validated]) - - useEffect(() => { - setIsInvalid(invalidated) - }, [invalidated]) - - // Callback function to be passed via context to individual checkboxes: - const handleCheckboxChange = (value) => { - const changedValue = value - if (selectedOptions && selectedOptions.includes(value)) { - setSelectedOptions( selectedOptions.filter((value) => {return value !== changedValue}) ) - } else if (selectedOptions && !selectedOptions.includes(value)) { - setSelectedOptions( (selectedOptions) => [...selectedOptions, changedValue] ) - } else { - setSelectedOptions([changedValue]) - } - onChange && onChange(value) - } - - // Callback function to be passed via the context to child Checkboxes so they can add their value to the groups' selectedOptions array in case selected has not been set on the parent (otherwise the parent select will trump whatever is set on the child in a group context). Called ONLY ONCE during initialization of the child Checkbox when we DON't want to execute any additional onChange handlers just yet: - const updateSelectedValue = (value) => { - if (!selected) { - setSelectedOptions( (selectedOptions) => [...selectedOptions || [], value] ) - } - } - - return ( - <CheckboxGroupContext.Provider - value={ - { - selectedOptions: selectedOptions, - name: groupName, - disabled: disabled, - handleCheckboxChange: handleCheckboxChange, - updateSelectedValue: updateSelectedValue, - } - } - > - <div - className={` - juno-checkboxgroup - ${ isValid ? "juno-checkboxgroup-valid" : "" } - ${ isInvalid ? "juno-checkboxgroup-invalid" : "" } - ${checkboxgroupstyles} - ${className} - `} - id={groupId} - role="group" - {...props} - > - { - label && isNotEmptyString(label) ? - <Label - text={label} - htmlFor={groupId} - disabled={disabled} - required={required} - /> - : - "" - } - <div - className={` - juno-checkbox-group-options - ${ groupstyles } - ${ isValid ? validgroupstyles : "" } - ${ isInvalid ? invalidgroupstyles : ""} - ${ isValid || isInvalid ? "" : defaultgroupstyles } - `} - > - {isInvalid ? ( - <Icon - icon="dangerous" - color="jn-text-theme-error" - className={`${iconstyles}`} - /> - ) : ""} - {isValid ? ( - <Icon - icon="checkCircle" - color="jn-text-theme-success" - className={`${iconstyles}`} - /> - ) : ""} - - { children } - - </div> - { errortext && isNotEmptyString(errortext) ? - <FormHint text={errortext} variant="error" /> - : - "" - } - { successtext && isNotEmptyString(successtext) ? - <FormHint text={successtext} variant="success" /> - : - "" - } - { helptext && isNotEmptyString(helptext) ? - <FormHint text={helptext} /> - : - "" - } - </div> - </CheckboxGroupContext.Provider> - ) - -} - -CheckboxGroup.propTypes = { - /** The Checkbox children of the CheckboxGroup */ - children: PropTypes.node, - /** Pass a custom className */ - className: PropTypes.string, - /** Whether all Checkboxes in the group are disabled */ - disabled: PropTypes.bool, - /** Text to display in case validation failed or there is an error. Will set the whole group to invalid when passed. */ - errortext: PropTypes.node, - /** A text to render to further explain meaning and significance of the group */ - helptext: PropTypes.node, - /** The id of the group. If not passed, a unique id will be created and used for the group as a whole. */ - id: PropTypes.string, - invalid: PropTypes.bool, - /*+ The label of the whole group. */ - label: PropTypes.string, - /** The name of all checkboxes in the group. If not passed, a unique name identifier will be created and used for the group as a whole. */ - name: PropTypes.string, - /** An onChange handler to execute when the selection of options changes */ - onChange: PropTypes.func, - /** Whether a selection in the group is required */ - required: PropTypes.bool, - /** Array of values of individual selected options in the group */ - selected: PropTypes.array, - /** Text to display in case validation is successful. When passed, will set the whole group to valid. */ - successtext: PropTypes.node, - /** Whether the CheckboxGroup was successfully validated */ - valid: PropTypes.bool, -} - -CheckboxGroup.defaultProps = { - children: null, - className: "", - disabled: false, - errortext: "", - helptext: "", - id: "", - invalid: false, - label: undefined, - name: "", - onChange: undefined, - required: false, - selected: undefined, - successtext: "", - valid: false, -} diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.stories.js b/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.stories.js deleted file mode 100644 index 6d6efe63a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.stories.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { CheckboxGroup } from './index.js'; -import { CheckboxRow } from '../CheckboxRow/index.js'; -import { Checkbox } from '../Checkbox/index.js'; - -export default { - title: 'Forms/Checkbox/CheckboxGroup', - component: CheckboxGroup, - argTypes: { - items: { - table: { - disable: true, - }, - }, - errortext: { - control: false, - }, - helptext: { - control: false, - }, - successtext: { - control: false, - }, - children: { - control: false, - }, - selected: { - control: false, - }, - }, -}; - -const Template = ({ children, ...args }) => <CheckboxGroup {...args}>{children}</CheckboxGroup>; - -export const Default = { - render: Template, - - args: { - children: [ - <Checkbox value="val-1" label="Option 1" key="1" />, - <Checkbox value="val-2" label="Option 2" key="2" />, - <Checkbox value="val-3" label="Option 3" key="3" />, - ], - }, -}; - -export const Selected = { - render: Template, - - args: { - selected: ['val-2'], - children: [ - <Checkbox value="val-1" label="Option 1" key="1" />, - <Checkbox value="val-2" label="Option 2" key="2" />, - <Checkbox value="val-3" label="Option 3" key="3" />, - ], - }, -}; - -export const IndividuallyChecked = { - render: Template, - - args: { - children: [ - <Checkbox value="val-1" label="Option 1" key="1" />, - <Checkbox value="val-2" label="Option 2" key="2" checked />, - <Checkbox value="val-3" label="Option 3" key="3" checked />, - <Checkbox value="val-4" label="Option 4" key="4" />, - ], - }, -}; - -export const WithLabel = { - render: Template, - - args: { - name: 'Labelled ChechboxGroup', - label: 'A Labelled CheckboxGroup', - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const Required = { - render: Template, - - args: { - name: 'Required Labelled ChechboxGroup', - label: 'A Required, Labelled CheckboxGroup', - required: true, - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const Disabled = { - render: Template, - - args: { - label: 'A disabled CheckboxGroup', - disabled: true, - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const ValidCheckboxGroup = { - render: Template, - - args: { - name: 'valid-checkbox-group', - label: 'A valid CheckboxGroup', - valid: true, - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const WithHelptext = { - render: Template, - - args: { - name: 'checkbox-group-with-helptext', - label: 'A CheckboxGroup with helptext', - helptext: 'A helptext', - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const WithHelptextAsNode = { - render: Template, - - args: { - name: 'checkbox-group-with-helptext-as-node', - label: 'A CheckboxGroup with helptext as node', - helptext: ( - <> - This is a helptext with a <a href="#">Link</a> - </> - ), - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const WithSuccesstext = { - render: Template, - - args: { - name: 'checkbox-group-with-success', - label: 'A CheckboxGroup with successful validation', - successtext: 'This group is valid.', - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const InvalidCheckboxGroup = { - render: Template, - - args: { - name: 'invalid-checkbox-group', - label: 'An invalid CheckboxGroup', - invalid: true, - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; - -export const WithErrortext = { - render: Template, - - args: { - name: 'checkbox-group-with-error', - label: 'A CheckboxGroup with an Error', - errortext: 'This group has an error.', - children: [ - <Checkbox value="val-1" id="c-1" label="Option 1" key="1" />, - <Checkbox value="val-2" id="c-2" label="Option 2" key="2" />, - <Checkbox value="val-3" id="c-3" label="Option 3" key="3" />, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.test.js b/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.test.js deleted file mode 100644 index 0bfb8bb36..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/CheckboxGroup.test.js +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen, fireEvent } from "@testing-library/react" -import { CheckboxGroup } from "./index" -import { Checkbox } from "../Checkbox/index" - -describe("CheckboxGroup", () => { - - test("renders a CheckboxGroup container", async () => { - render( - <CheckboxGroup name="my-checkboxgroup" data-testid="checkbox-group"> - </CheckboxGroup> - ) - expect(screen.getByTestId("checkbox-group")).toBeInTheDocument() - }) - - test("renders a CheckboxGroup with an id as passed ", async () => { - render(< CheckboxGroup data-testid="group" id="my-checkboxgroup-1"/>) - expect(screen.getByTestId("group")).toBeInTheDocument() - expect(screen.getByTestId("group")).toHaveAttribute("id", "my-checkboxgroup-1") - }) - - test("renders a CheckboxGroup with an auto-generated id if no id is passed", async () => { - render(< CheckboxGroup data-testid="group"/>) - expect(screen.getByTestId("group")).toBeInTheDocument() - expect(screen.getByTestId("group")).toHaveAttribute("id") - expect(screen.getByTestId("group").getAttribute("id")).toMatch("juno-checkboxgroup") - }) - - test("renders a CheckboxGroup with an associated label as passed", async () => { - render( - <CheckboxGroup name="my-checkboxgroup" label="My Group of Checkboxes"> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByText("My Group of Checkboxes")).toBeInTheDocument() - }) - - test("renders a required label as passed", async () => { - render( - <CheckboxGroup name="my-checkboxgroup" label="my-labeled-checkboxgroup" required > - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(document.querySelector('.juno-required')).toBeInTheDocument() - }) - - test("does not render any checkboxes if no children passed", async () => { - render( - <CheckboxGroup name="my-checkboxgroup"> - </CheckboxGroup> - ) - expect(() => { - screen.getByRole("checkbox"); - }).toThrow() - }) - - test("renders Checkboxes as passed", async () => { - render( - <CheckboxGroup> - <Checkbox /> - <Checkbox /> - <Checkbox /> - </CheckboxGroup> - ) - expect(screen.getAllByRole("checkbox")).toHaveLength(3) - }) - - test("renders individually named Checkboxes as passed", async () => { - render( - <CheckboxGroup name="my-checkboxgroup"> - <Checkbox /> - <Checkbox /> - <Checkbox /> - </CheckboxGroup> - ) - expect(screen.getAllByRole("checkbox")).toHaveLength(3) - }) - - test("renders Checkboxes with an auto-generated name if no name was passed", async () => { - render( - <CheckboxGroup> - <Checkbox /> - <Checkbox /> - </CheckboxGroup> - ) - const checkboxes = screen.getAllByRole("checkbox") - checkboxes.forEach( checkbox => expect(checkbox).toHaveAttribute('name') ) - }) - - test("renders Checkboxes as passed", async () => { - render( - <CheckboxGroup name="my-checkboxgroup"> - <Checkbox /> - </CheckboxGroup> - ) - expect(screen.getByRole("checkbox")).toHaveAttribute("name", "my-checkboxgroup") - }) - - test("renders checked Checkboxes as passed", async () => { - render( - <CheckboxGroup selected={["test-checkbox"]}> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("checkbox")).toBeChecked() - }) - - test("renders disabled child Checkboxes as passed", async () => { - render( - <CheckboxGroup disabled > - <Checkbox id="c-1" /> - <Checkbox id="c-2" /> - </CheckboxGroup> - ) - expect(document.getElementById("c-1")).toBeDisabled() - expect(document.getElementById("c-2")).toBeDisabled() - }) - - test("renders a valid CheckboxGroup as passed", async () => { - render( - <CheckboxGroup valid> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveClass("juno-checkboxgroup-valid") - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders a valid CheckboxGroup when successtext is passed", async () => { - render( - <CheckboxGroup successtext="Great Success!"> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveClass("juno-checkboxgroup-valid") - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - expect(screen.getByText("Great Success!")).toBeInTheDocument() - }) - - test("renders an invalid CheckboxGroup as passed", async () => { - render( - <CheckboxGroup invalid> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveClass("juno-checkboxgroup-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders an invalid CheckboxGroup when errortext is passed", async () => { - render( - <CheckboxGroup errortext="Big Error!"> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveClass("juno-checkboxgroup-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - expect(screen.getByText("Big Error!")).toBeInTheDocument() - }) - - test("renders a helptext as passed", async () => { - render( - <CheckboxGroup helptext="This is a helpful text"> - <Checkbox /> - <Checkbox /> - </CheckboxGroup> - ) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass("juno-form-hint-help") - expect(document.querySelector(".juno-form-hint")).toHaveTextContent("This is a helpful text") - }) - - test("renders a custom className", async () => { - render( - <CheckboxGroup name="my-checkboxgroup" className="my-custom-classname"> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveClass("my-custom-classname") - }) - - test("renders all props", async () => { - render( - <CheckboxGroup name="my-checkboxgroup" data-lolol="some-prop"> - <Checkbox value="test-checkbox"/> - </CheckboxGroup> - ) - expect(screen.getByRole("group")).toBeInTheDocument() - expect(screen.getByRole("group")).toHaveAttribute("data-lolol", 'some-prop') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/index.js b/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/index.js deleted file mode 100644 index 957fa556b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxGroup/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { CheckboxGroup } from "./CheckboxGroup.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.component.js b/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.component.js deleted file mode 100644 index 2094dc2b6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.component.js +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect, useMemo } from "react" -import PropTypes from "prop-types" -import { Checkbox } from "../Checkbox/index.js" -import { withDeprecationWarning } from '../withDeprecationWarning/index.js' - -/** DEPRECATED: A single checkbox, associated label, and structural markup. This component is DEPRECATED, use Checkbox instead. */ -const CheckboxRow = ({ - value, - checked, - indeterminate, - name, - label, - id, - helptext, - required, - disabled, - invalid, - errortext, - valid, - successtext, - className, - onChange, - ...props -}) => { - return ( - <Checkbox - value={value} - checked={checked} - indeterminate={indeterminate} - name={name} - label={label} - id={id} - helptext={helptext} - disabled={disabled} - required={required} - invalid={invalid} - valid={valid} - errortext={errortext} - successtext={successtext} - className={className} - onChange={onChange} - {...props} - /> - ) -} - -CheckboxRow.propTypes = { - /** Optional initial value */ - value: PropTypes.string, - /** Pass checked state */ - checked: PropTypes.bool, - /** Whether the checkbox is indeterminate */ - indeterminate: PropTypes.bool, - /** Name attribute of the checkbox element */ - name: PropTypes.string, - /** Label text */ - label: PropTypes.string, - /** Id */ - id: PropTypes.string, - /** Help text */ - helptext: PropTypes.node, - /** Specify whether the checkbox is required */ - required: PropTypes.bool, - /** Disable the Checkbox */ - disabled: PropTypes.bool, - /** Whether the CheckboxRow is invalid */ - invalid: PropTypes.bool, - /** The error text to render with the CheckboxRow. If passed, the Checkbox row will be set to invalid automatically. */ - errortext: PropTypes.node, - /** Whether the CheckboxRow is valid */ - valid: PropTypes.bool, - /** The text to render when the field is validated. If passed, the Checkbox will be set to valid automatically. */ - successtext: PropTypes.node, - /** Pass a custom className */ - className: PropTypes.string, - /** Pass a handler to the checkbox element */ - onChange: PropTypes.func, -} - -CheckboxRow.defaultProps = { - value: "", - checked: false, - indeterminate: false, - name: null, - label: null, - id: null, - helptext: null, - required: null, - disabled: false, - invalid: false, - errortext: "", - valid: false, - successtext: "", - className: "", - onChange: undefined, -} - -export default withDeprecationWarning(CheckboxRow, "CheckboxRow is deprecated and will be removed in future versions. To be future-proof, use Checkbox instead.") \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.stories.js b/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.stories.js deleted file mode 100644 index 0c2de48b8..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.stories.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { CheckboxRow } from './index.js'; - -export default { - title: 'Deprecated/CheckboxRow', - component: CheckboxRow, - parameters: { - docs: { - description: { - component: - 'DEPRECATED: A radio row containing a radio, associated label, and structural markup. This component is DEPRECATED, use Radio instead.', - }, - }, - }, - argTypes: {}, -}; - -export const Default = { - args: { - label: 'Default Checkbox Row', - id: 'default', - }, -}; - -export const Checked = { - args: { - label: 'Checked CheckboxRow', - id: 'checked', - checked: true, - }, -}; - -export const WithHelpText = { - args: { - name: 'my-input', - label: 'Checkbox Row with Help text', - helptext: 'Oh so helpful helptext', - id: 'withHelptext', - }, -}; - -export const WithHelpTextWithLink = { - args: { - name: 'my-input', - label: 'Checkbox Row with Help text', - helptext: ( - <> - Helptext with a <a href="#">Link</a> - </> - ), - id: 'withHelptext-withLink', - }, -}; - -export const Required = { - args: { - label: 'Required Checkbox Row', - required: true, - id: 'required', - }, -}; - -export const Disabled = { - args: { - label: 'Disabled Checkbox Row', - id: 'disabled-checkbox-row', - disabled: true, - }, -}; - -export const Invalid = { - args: { - label: 'Invalid Checkbox', - id: 'invalid-checkbox-row', - invalid: true, - }, -}; - -export const WithErrorText = { - args: { - label: 'Checkbox invalidated by errortext', - id: 'invalid-checkbox-by-errortext', - errortext: 'Pass an errortext to invalidate a CheckboxRow', - }, -}; - -export const Valid = { - args: { - label: 'Valid Checkbox', - id: 'valid-checkbox-row', - valid: true, - }, -}; - -export const WithSuccessText = { - args: { - label: 'Checkbox validated by successtext', - id: 'valid-checkbox-by-successtext', - successtext: 'Pass a successtext to validate a CheckboxRow', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.test.js b/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.test.js deleted file mode 100644 index 52b9cac57..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/CheckboxRow.test.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { act } from 'react-dom/test-utils' -import { CheckboxRow } from "./index" - -describe("CheckboxRow", () => { - - - test("renders a checkbox row", async () => { - render(<CheckboxRow data-testid="checkbox-row" />) - expect(screen.getByTestId("checkbox-row")).toBeInTheDocument() - }) - - test("renders a checked checkbox as passed", async () => { - act(() => { - render(<CheckboxRow checked />) - }) - expect(screen.getByRole("checkbox")).toBeChecked() - }) - - test("renders a checkbox row with a value as passed", async () => { - render(<CheckboxRow value="my-value" />) - expect(screen.getByRole("checkbox")).toHaveAttribute("value", 'my-value') - }) - - test("renders a checkbox row with a name as passed", async () => { - render(<CheckboxRow name="my-checkbox" />) - expect(screen.getByRole("checkbox")).toHaveAttribute("name", 'my-checkbox') - }) - - test("renders a checkbox row with an id as passed", async () => { - render(<CheckboxRow id="my-checkbox" />) - expect(screen.getByRole("checkbox")).toHaveAttribute("id", 'my-checkbox') - }) - - test("renders a checkbox row with a checkbox and an associated label with an id as passed", async () => { - render(<CheckboxRow data-testid="my-checkbox-row" label="My Checkbox Row" id="checkbox-row" />) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByLabelText("My Checkbox Row")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveAttribute("id", 'checkbox-row') - }) - - test("renders a help text as passed", async () => { - render(<CheckboxRow helptext="Helptext goes here" />) - expect(screen.getByText("Helptext goes here")).toBeInTheDocument() - }) - - test("renders a helpt text with a link as passed", async () => { - render(<CheckboxRow helptext={<a href="#">Link</a>} />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("href", "#") - expect(screen.getByRole("link")).toHaveTextContent("Link") - }) - - test("renders a required label as passed", async () => { - render(<CheckboxRow label="Required Input" required />) - expect(document.querySelector('.juno-required')).toBeInTheDocument() - }) - - test("renders a disabled Checkbox as passed", async () => { - act(() => { - render(<CheckboxRow disabled />) - }) - expect(screen.getByRole("checkbox")).toBeDisabled() - }) - - test("renders an invalid CheckboxRow as passed", async () => { - act(() => { - render(<CheckboxRow invalid label="invalid checkbox"/>) - }) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders an invalid CheckRow with an error text as passed", async () => { - render(<CheckboxRow errortext="This is an error text" label="Checkbox"/>) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - expect(screen.getByText("This is an error text")).toBeInTheDocument() - }) - - test("renders a valid CheckboxRow as passed", async () => { - act(() => { - render(<CheckboxRow valid label="valid checkbox"/>) - }) - expect(screen.getByRole("checkbox")).toBeInTheDocument() - expect(screen.getByRole("checkbox")).toHaveClass("juno-checkbox-valid") - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<CheckboxRow data-testid="my-checkbox-row" className="my-classname" />) - expect(screen.getByTestId("my-checkbox-row")).toHaveClass("my-classname") - }) - - test("renders all props as passed", async () => { - render(<CheckboxRow data-testid="my-checkbox-row" data-lolol="some-prop" />) - expect(screen.getByTestId("my-checkbox-row")).toHaveAttribute("data-lolol", 'some-prop') - }) - - test("fire handler on change as passed", async () => { - const onChangeSpy = jest.fn(); - render(<CheckboxRow onChange={onChangeSpy} />); - act(() => { - screen.getByRole('checkbox').click(); - }) - expect(onChangeSpy).toHaveBeenCalled(); - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/index.js b/libs_deprecated/juno-ui-components/src/components/CheckboxRow/index.js deleted file mode 100644 index c21067cd1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CheckboxRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { default as CheckboxRow } from "./CheckboxRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Code/Code.component.js b/libs_deprecated/juno-ui-components/src/components/Code/Code.component.js deleted file mode 100644 index 957f9ee8b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Code/Code.component.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const codeStyles = ` - jn-bg-theme-code-block - jn-text-sm -` - -/** A basic inline <code> component. - * Accepts "content" prop or renders children as passed. - */ -export const Code = ({ content, children, className, ...props }) => { - return ( - <code className={`juno-code ${codeStyles} ${className}`} {...props}> - {content || children} - </code> - ) -} - -Code.propTypes = { - content: PropTypes.string, - className: PropTypes.string, - children: PropTypes.node, -} - -Code.defaultProps = { - content: "", - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Code/Code.stories.js b/libs_deprecated/juno-ui-components/src/components/Code/Code.stories.js deleted file mode 100644 index 089a215fe..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Code/Code.stories.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { Code } from './index.js'; - -export default { - title: 'Components/Code', - component: Code, - argTypes: { - children: { - control: false, - }, - }, -}; - -export const Default = { - parameters: { - docs: { - description: { - story: 'Default inline code', - }, - }, - }, - - args: { - content: '<span>Some code passed as content prop.</span>', - }, -}; - -export const WithChildren = { - parameters: { - docs: { - description: { - story: 'Inline code with children', - }, - }, - }, - - args: { - children: '<Code>Some code with children</Code>', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Code/Code.test.js b/libs_deprecated/juno-ui-components/src/components/Code/Code.test.js deleted file mode 100644 index ba13134e7..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Code/Code.test.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Code } from "./index" - -describe("Code", () => { - test("renders inline code with content as passed", async () => { - render(<Code data-testid="code" content="some example code" />) - expect(screen.getByTestId("code")).toBeInTheDocument() - expect(screen.getByTestId("code")).toHaveTextContent("some example code") - }) - - test("renders inline code with children as passed", async () => { - render(<Code data-testid="code">Some example code as children</Code>) - expect(screen.getByTestId("code")).toBeInTheDocument() - expect(screen.getByTestId("code")).toHaveTextContent( - "Some example code as children" - ) - }) - - test("renders inline code with content as passed when both content and children were passed", async () => { - render( - <Code data-testid="code" content="Content is go"> - Children are meh - </Code> - ) - expect(screen.getByTestId("code")).toBeInTheDocument() - expect(screen.getByTestId("code")).toHaveTextContent("Content is go") - expect(screen.getByTestId("code")).not.toHaveTextContent("Children are meh") - }) - - test("renders inline code with a className as passed", async () => { - render(<Code data-testid="code" className="my-code-class"></Code>) - expect(screen.getByTestId("code")).toBeInTheDocument() - expect(screen.getByTestId("code")).toHaveClass("my-code-class") - }) - - test("renders inline code with all props as passed", async () => { - render(<Code data-testid="code" data-lolol="code-lang-js"></Code>) - expect(screen.getByTestId("code")).toBeInTheDocument() - expect(screen.getByTestId("code")).toHaveAttribute( - "data-lolol", - "code-lang-js" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Code/index.js b/libs_deprecated/juno-ui-components/src/components/Code/index.js deleted file mode 100644 index 89882583a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Code/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Code } from "./Code.component.js" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.component.js b/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.component.js deleted file mode 100644 index e4b57fd0c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.component.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect, useRef } from "react" -import PropTypes from "prop-types" -import { JsonViewer } from "../JsonViewer/JsonViewer.component" -import { Icon } from "../Icon/index" - -const wrapperStyles = ` - jn-bg-theme-code-block - jn-rounded -` - -const preStyles = (wrap) => { - return ` - jn-p-6 - ${ - wrap - ? "jn-break-words jn-break-all jn-whitespace-pre-wrap" - : "jn-overflow-x-auto" - } - ` -} - -const sizeStyles = (size) => { - switch (size) { - case "small": - return ` - juno-codeblock-pre-small - jn-max-h-64 - jn-overflow-y-auto - ` - case "medium": - return ` - juno-codeblock-pre-medium - jn-max-h-[32rem] - jn-overflow-y-auto - ` - case "large": - return ` - juno-codeblock-pre-large - jn-max-h-[56rem] - jn-overflow-y-auto - ` - default: - return `` - } -} - -const codeStyles = ` - jn-bg-theme-code-block - jn-text-sm -` - -const headingStyles = ` - jn-text-sm - jn-border-b-[1px] - jn-border-theme-codeblock-bar - jn-h-[3.4375rem] - jn-flex -` - -const headingInnerStyles = ` - jn-flex - jn-font-bold - jn-px-[1.5625rem] - jn-items-center -` - -const bottomBarStyles = ` - jn-flex - jn-justify-end - jn-px-3 - jn-py-2 - jn-border-t-[1px] - jn-border-theme-codeblock-bar -` - -const copyTextStyles = ` - jn-font-bold - jn-text-sm - jn-mr-4 - jn-mt-1 -` - -const jsonStyles = ` - jn-bg-theme-code-block -` - -const jsonViewStyles = { - fontFamily: "IBM Plex Mono", - fontSize: "0.875rem", - padding: "1.5rem", -} - -const jsonTheme = { - base00: "var(--color-syntax-highlight-base00)", //bg - base01: "var(--color-syntax-highlight-base01)", //? - base02: "var(--color-syntax-highlight-base02)", //lines and boxes - base03: "var(--color-syntax-highlight-base03)", - base04: "var(--color-syntax-highlight-base04)", - base05: "var(--color-syntax-highlight-base05)", - base06: "var(--color-syntax-highlight-base06)", - base07: "var(--color-syntax-highlight-base07)", - base08: "var(--color-syntax-highlight-base08)", // NULL - base09: "var(--color-syntax-highlight-base09)", // String value - base0A: "var(--color-syntax-highlight-base0A)", // NaN - base0B: "var(--color-syntax-highlight-base0B)", // float value - base0C: "var(--color-syntax-highlight-base0C)", // index - base0D: "var(--color-syntax-highlight-base0D)", // expanded icon - base0E: "var(--color-syntax-highlight-base0E)", // bool + collapsed icon - base0F: "var(--color-syntax-highlight-base0F)", // integer value -} - -/** A basic CodeBlock component. Accepts a content prop or children. Will render a pre-wrapped code element. */ -export const CodeBlock = ({ - content, - children, - heading, - wrap, - size, - copy, - lang, - className, - ...props -}) => { - const [isCopied, setIsCopied] = useState(false) - const timeoutRef = React.useRef(null) - - React.useEffect(() => { - return () => clearTimeout(timeoutRef.current) // clear when component is unmounted - }, []) - - const theCode = useRef(null) - - const handleCopyClick = () => { - const textToCopy = - lang === "json" - ? JSON.stringify(content || children) - : theCode.current.textContent - navigator.clipboard.writeText(textToCopy) - setIsCopied(true) - clearTimeout(timeoutRef.current) // clear any possibly existing Refs - timeoutRef.current = setTimeout(() => setIsCopied(false), 1000) - } - - return ( - <div - className={`juno-code-block ${wrapperStyles} ${ - lang ? `juno-code-block-lang-${lang}` : "" - } ${className}`} - data-lang={lang || null} - {...props} - > - {heading && heading.length ? ( - <div className={`juno-codeblock-heading ${headingStyles}`}> - <span className={`${headingInnerStyles}`}>{heading}</span> - </div> - ) : ( - "" - )} - {lang === "json" ? ( - <JsonViewer - data={content} - expanded={3} - theme={jsonTheme} - style={jsonViewStyles} - /> - ) : ( - <pre - className={`juno-code-block-pre ${preStyles(wrap)} ${sizeStyles( - size - )}`} - > - <code className={`${codeStyles}`} ref={theCode}> - {content || children} - </code> - </pre> - )} - - {copy ? ( - <div className={`juno-codeblock-bottombar ${bottomBarStyles}`}> - <span className={`${copyTextStyles}`}> - {isCopied ? "Copied!" : ""} - </span> - <Icon icon="contentCopy" onClick={handleCopyClick} /> - </div> - ) : ( - "" - )} - </div> - ) -} - -CodeBlock.propTypes = { - /** The content to render. Will override children if passed. */ - content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), - /** The children to render. Will be overridden by content prop if passed as well. */ - children: PropTypes.oneOfType([PropTypes.node, PropTypes.object]), - /** Pass at title to render. Will look like a single tab. */ - heading: PropTypes.string, - /** Set whether the code should wrap or not. Default is true. */ - wrap: PropTypes.bool, - /** Set the size of the CodeBlock. Default is "auto" */ - size: PropTypes.oneOf(["auto", "small", "medium", "large"]), - /** Render a button to copy the code to the clipboard. Defaults to true */ - copy: PropTypes.bool, - /** Pass a lang prop. Passing "json" will render a fully-featured JsonView. Will also add a data-lang-attribute to the codeblock */ - lang: PropTypes.string, - /** Add a custom className to the wrapper of the CodeBlock */ - className: PropTypes.string, -} - -CodeBlock.defaultProps = { - content: "", - children: null, - wrap: true, - size: "auto", - copy: true, - lang: "", - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.stories.js b/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.stories.js deleted file mode 100644 index 1813adb6b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.stories.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { CodeBlock } from './index.js'; -import { Tabs } from '../Tabs/index.js'; -import { TabList } from '../TabList/index.js'; -import { Tab } from '../Tab/index.js'; -import { Default as TabStory } from '../Tab/Tab.stories.js'; -import { TabPanel } from '../TabPanel/index.js'; - -export default { - title: 'Components/CodeBlock', - component: CodeBlock, - argTypes: { - size: { - options: ['auto', 'small', 'medium', 'large'], - control: { type: 'select' }, - }, - children: { - control: false, - }, - }, -}; - -const TabsTemplate = ({ tabs, codeBlocks, ...args }) => ( - <Tabs variant="codeblocks"> - <TabList> - {tabs.map((tab, t) => ( - <Tab {...tab} key={`t-${t}`}></Tab> - ))} - </TabList> - {codeBlocks.map((codeBlock, c) => ( - <TabPanel> - <CodeBlock {...codeBlock} key={`c-${c}`} /> - </TabPanel> - ))} - </Tabs> -); - -export const Default = { - parameters: { - docs: { - description: { - story: 'Default code block', - }, - }, - }, - - args: { - content: 'Some code goes here', - }, -}; - -export const DefaultWithChildren = { - parameters: { - docs: { - description: { - story: 'Code Block with children', - }, - }, - }, - - args: { - lang: 'html', - children: `<html lang="en"> - <head> - <title="Multi-line Html" /> - </head> - <body> - <main> - </main> - </body> - </html>`, - }, -}; - -export const DefaultWithHeading = { - parameters: { - docs: { - description: { - story: 'Code Block with Heading WIP', - }, - }, - }, - - args: { - children: `<CodeBlock> - <p>some code here</p> - </CodeBlock>`, - heading: 'CodeBlock.jsx', - }, -}; - -export const FixedSize = { - parameters: { - docs: { - description: { - story: 'Fixed size CodeBlock with overflow scrollbars', - }, - }, - }, - - args: { - size: 'small', - content: ` -------- BEGIN CERTIFICATE -------- - 30818902818100C4A06B7B52F8D17DC1C0 - B47362C64AB799AAE19E245A7559E9CEEC - 7D8AA4DF07CB0B21FDFD763C63A313A668 - FE9D764ED913C51A676788DB62AF624F42 - 2C2F112C1316922AA5D37823CD9F43D1FC - 54513D14B2-9E36991F08A042C42EAAEEE - 5FE8E2CB10167174A359CEBF6FACC2C9CA - 933AD403137EE2C3F4CBED9460129C72B0 - 030100030818902818100C4A06B7B52F8D - 17DC1CCB47362C64AB799AAE19E245A755 - 9E9CEEC7D8AA4DF07CB0B21FDFD763C63A - 313A668FE9D764ED913C51A676788DB62A - F624F422C2F112C1316922AA5D37823CD9 - F43D1FC54513D14B2-9E36991F08A042C4 - 2EAAEEE5FE8E2CB10167174A359CEBF6FA - CC2C9CA933AD403137E2C3F4CBED946012 - 9C72B020301000 - -------- END CERTIFICATE -------- `, - }, -}; - -export const NonWrappingCodeBlock = { - parameters: { - docs: { - description: { - story: 'Pass `wrap={false}` to disable line-wrapping', - }, - }, - }, - - args: { - wrap: false, - children: - '-------- BEGIN CERTIFICATE -------- 30818902818100C4A06B7B52F8D17DC1CCB47362C64AB799AAE19E245A7559E9CEEC7D8AA4DF07CB0B21FDFD763C63A313A668FE9D764ED913C51A676788DB62AF624F422C2F112C1316922AA5D37823CD9F43D1FC54513D14B2-9E36991F08A042C42EAAEEE5FE8E2CB10167174A359CEBF6FACC2C9CA933AD403137EE2C3F4CBED9460129C72B02030100030818902818100C4A06B7B52F8D17DC1CCB47362C64AB799AAE19E245A7559E9CEEC7D8AA4DF07CB0B21FDFD763C63A313A668FE9D764ED913C51A676788DB62AF624F422C2F112C1316922AA5D37823CD9F43D1FC54513D14B2-9E36991F08A042C42EAAEEE5FE8E2CB10167174A359CEBF6FACC2C9CA933AD403137E2C3F4CBED9460129C72B020301000 -------- END CERTIFICATE --------', - }, -}; - -export const JSONView = { - parameters: { - docs: { - description: { - story: 'Json View', - }, - }, - }, - - args: { - lang: 'json', - heading: 'Json CodeBlock', - content: { - someKey: 'some value', - someOtherKey: 'some other value', - nestedKeys: { - firstNestedKey: 'first nested value', - }, - }, - }, -}; - -export const CodeBlocksWithTabs = { - render: TabsTemplate, - - parameters: { - docs: { - description: { - story: - "Tabbed CodeBlocks can be composed using the `<Tabs>`, `<Tab>`, `<TabList>`, and `<TabPanel>` components. Make sure to pass `variant='codeblocks'` to the `<Tabs>` component.", - }, - }, - }, - - args: { - tabs: [ - { ...TabStory.args, children: 'UserData.jsx', key: 't-0' }, - { ...TabStory.args, children: 'data.json', key: 't-1' }, - { ...TabStory.args, children: 'UserData.html', key: 't-2' }, - ], - codeBlocks: [ - { content: "<UserData name='User' data={data.json} />" }, - { - lang: 'json', - content: { - firstName: 'Joan', - lastName: 'Clarke', - placeOfBirth: 'West Norwood, London, England', - }, - }, - { - content: `<div> - <dl> - <dt>First Name</dt> - <dd>Joan</dd> - <dt>Last Name</dt> - <dd>Clarke</dd> - <dt>Place of Birth</dt> - <dd>West Norwood, London, England</dd> - </dl> - </div>`, - }, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.test.js b/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.test.js deleted file mode 100644 index 9be0d7e40..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CodeBlock/CodeBlock.test.js +++ /dev/null @@ -1,185 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { CodeBlock } from "./index" - -describe("CodeBlock", () => { - test("renders a CodeBlock with content as passed", async () => { - render(<CodeBlock data-testid="codeblock" content="some example code" />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(screen.getByTestId("codeblock")).toHaveTextContent( - "some example code" - ) - }) - - test("renders a CodeBlock with children as passed", async () => { - render( - <CodeBlock data-testid="codeblock">{"some children here"}</CodeBlock> - ) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(screen.getByTestId("codeblock")).toHaveTextContent( - "some children here" - ) - }) - - test("renders a CodeBlock with a lang attribute as passed", async () => { - render(<CodeBlock data-testid="codeblock" lang="javascript" />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(screen.getByTestId("codeblock")).toHaveAttribute( - "data-lang", - "javascript" - ) - }) - - test("renders a wrapping CodeBlock by default", async () => { - render(<CodeBlock data-testid="codeblock" />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(document.querySelector("pre")).toHaveClass("jn-break-words") - expect(document.querySelector("pre")).toHaveClass("jn-break-all") - expect(document.querySelector("pre")).toHaveClass("jn-whitespace-pre-wrap") - expect(document.querySelector("pre")).not.toHaveClass("jn-overflow-x-auto") - }) - - test("renders a non-wrapping CodeBlock as passed", async () => { - render(<CodeBlock data-testid="codeblock" wrap={false} />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(document.querySelector("pre")).not.toHaveClass("jn-break-words") - expect(document.querySelector("pre")).not.toHaveClass("jn-break-all") - expect(document.querySelector("pre")).not.toHaveClass( - "jn-whitespace-pre-wrap" - ) - expect(document.querySelector("pre")).toHaveClass("jn-overflow-x-auto") - }) - - test("renders a CodeBlock without height restrictions by default", async () => { - render(<CodeBlock content="123" />) - expect(document.querySelector("pre")).toBeInTheDocument() - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-small" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-medium" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-large" - ) - }) - - test("renders a small sized CodeBlock as passed", async () => { - render(<CodeBlock content="123" size="small" />) - expect(document.querySelector("pre")).toBeInTheDocument() - expect(document.querySelector("pre")).toHaveClass( - "juno-codeblock-pre-small" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-medium" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-large" - ) - }) - - test("renders a medium sized CodeBlock as passed", async () => { - render(<CodeBlock content="123" size="medium" />) - expect(document.querySelector("pre")).toBeInTheDocument() - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-small" - ) - expect(document.querySelector("pre")).toHaveClass( - "juno-codeblock-pre-medium" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-large" - ) - }) - - test("renders a medium sized CodeBlock as passed", async () => { - render(<CodeBlock content="123" size="large" />) - expect(document.querySelector("pre")).toBeInTheDocument() - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-small" - ) - expect(document.querySelector("pre")).not.toHaveClass( - "juno-codeblock-pre-medium" - ) - expect(document.querySelector("pre")).toHaveClass( - "juno-codeblock-pre-large" - ) - }) - - test("renders a heading as passed", async () => { - render( - <CodeBlock - data-testid="codeblock" - content="123" - heading="Look, a CodeBlock!" - /> - ) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect( - document.querySelector(".juno-codeblock-heading") - ).toBeInTheDocument() - expect(document.querySelector(".juno-codeblock-heading")).toHaveTextContent( - "Look, a CodeBlock!" - ) - }) - - test("renders a JSONView as passed", async () => { - const testJson = { - someKey: "some value", - someOtherKey: 12, - } - render(<CodeBlock data-testid="codeblock" lang="json" content={testJson} />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(screen.getByTestId("codeblock")).toHaveAttribute("data-lang", "json") - expect(document.querySelector("[data-json-viewer]")).toBeInTheDocument() - }) - - test("renders a JSONView as passed with children", async () => { - const testObj = { - someKey: "some value", - someOtherKey: 12, - } - render( - <CodeBlock data-testid="codeblock" lang="json"> - {testObj} - </CodeBlock> - ) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("juno-code-block") - expect(screen.getByTestId("codeblock")).toHaveAttribute("data-lang", "json") - expect(document.querySelector("[data-json-viewer]")).toBeInTheDocument() - }) - - test("renders a CodeBlock with a Copy button by default", async () => { - render(<CodeBlock />) - expect( - screen.getByRole("button", { name: "contentCopy" }) - ).toBeInTheDocument() - }) - - test("renders a CodeBlock with className as passed", async () => { - render(<CodeBlock data-testid="codeblock" className="my-class" />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveClass("my-class") - }) - - test("renders a CodeBlock with all props as passed", async () => { - render(<CodeBlock data-testid="codeblock" data-lolol="code-lang-js" />) - expect(screen.getByTestId("codeblock")).toBeInTheDocument() - expect(screen.getByTestId("codeblock")).toHaveAttribute( - "data-lolol", - "code-lang-js" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/CodeBlock/index.js b/libs_deprecated/juno-ui-components/src/components/CodeBlock/index.js deleted file mode 100644 index 4a2920a81..000000000 --- a/libs_deprecated/juno-ui-components/src/components/CodeBlock/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { CodeBlock } from "./CodeBlock.component.js" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.component.js b/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.component.js deleted file mode 100644 index 75d199f5e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.component.js +++ /dev/null @@ -1,534 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect, useId, useMemo, createContext } from "react" -import PropTypes from "prop-types" -import { Combobox } from "@headlessui/react" -import { Float } from "@headlessui-float/react" -import { Label } from "../Label/index.js" -import { FormHint } from "../FormHint/index.js" -import { Icon } from "../Icon/index.js" -import { Spinner } from "../Spinner/index.js" -import { flip, offset, shift, size } from '@floating-ui/react-dom' -import { usePortalRef } from "../PortalProvider/index" -import { createPortal } from "react-dom" - -// STYLES - -const inputWrapperStyles = ` - jn-relative -` - -const labelStyles = ` - jn-pointer-events-none - jn-top-2 - jn-left-[0.9375rem] -` - -const inputStyles = ` - jn-rounded-3px - jn-bg-theme-textinput - jn-text-theme-textinput - jn-border - jn-text-base - jn-leading-4 - jn-w-full - jn-px-4 - jn-h-textinput - jn-text-left - jn-overflow-hidden - jn-text-ellipsis - jn-whitespace-nowrap - focus:jn-outline-none - focus:jn-ring-2 - focus:jn-ring-theme-focus -` - -const withLabelInputStyles = ` - jn-pt-[1.125rem] - jn-pb-1 -` - -const noLabelInputStyles = ` - jn-py-4 -` - -const disabledInputStyles = ` - jn-cursor-not-allowed - jn-pointer-events-none - jn-opacity-50 -` - -const defaultBorderStyles = ` - jn-border-theme-textinput-default -` - -const validStyles = ` - jn-border-theme-success -` - -const invalidStyles = ` - jn-border-theme-error -` - -const buttonStyles = ` - jn-absolute - jn-top-0 - jn-right-0 - jn-h-textinput - jn-w-6 - jn-h-4 - jn-border-l-0 - jn-border-y-[1px] - jn-border-r-[1px] - jn-rounded-tr - jn-rounded-br - jn-appearance-none - jn-bg-theme-textinput - jn-text-theme-textinput -` - -const defaultButtonStyles = ` - jn-border-theme-textinput-default -` - -const invalidButtonStyles = ` - jn-border-theme-error -` - -const validButtonStyles = ` - jn-border-theme-success -` - -const disabledButtonStyles = ` - jn-cursor-not-allowed - jn-pointer-events-none - jn-bg-transparent - jn-opacity-50 -` - -const menuStyles = ` - jn-rounded - jn-bg-theme-background-lvl-1 - jn-w-full - jn-overflow-y-auto -` - -const iconContainerStyles = ` - jn-absolute - jn-top-[.4rem] - jn-right-6 -` - -const centeredIconStyles = ` - jn-absolute - jn-top-1/2 - jn-left-1/2 - jn-translate-y-[-50%] - jn-translate-x-[-0.75rem] -` - -// CONTEXT -export const ComboBoxContext = createContext() - -// COMBOBOX -export const ComboBox = ({ - ariaLabel, - children, - className, - defaultValue, - disabled, - error, - errortext, - helptext, - id, - invalid, - loading, - label, - name, - nullable, - onBlur, - onChange, - onFocus, - onInputChange, - placeholder, - required, - successtext, - truncateOptions, - valid, - value, - valueLabel, - width, - ...props -}) => { - - const isNotEmptyString = (str) => { - return !(typeof str === 'string' && str.trim().length === 0) - } - - const theId = id || "juno-combobox-" + useId() - const helptextId = "juno-combobox-helptext-" + useId() - - const [optionValuesAndLabels, setOptionValuesAndLabels] = useState(new Map()) - const [query, setQuery] = useState("") - const [selectedValue, setSelectedValue] = useState(value) - const [isLoading, setIsLoading] = useState(false) - const [hasError, setHasError] = useState(false) - const [hasFocus, setFocus] = useState(false) - const [isInvalid, setIsInvalid] = useState(false) - const [isValid, setIsValid] = useState(false) - - // This callback is for all ComboBoxOptions to send us their value, label and children so we can save them as a map in our state. - // We need this because the Select component wants to display the selected value, label or children in the ComboBox input field - // but from the eventHandler we only get the value, not the label or children - const addOptionValueAndLabel = (value, label, children) => { - // append new entry to optionValuesAndLabels map containing the passed value, label and children - // use callback syntax of setState function here since we want to merge the old state with the new entry - setOptionValuesAndLabels(oldMap => (new Map(oldMap).set(value || children, { val: value, label: label, children: children }))) - } - - const invalidated = useMemo( - () => invalid || (errortext && isNotEmptyString(errortext) ? true : false), - [invalid, errortext] - ) - const validated = useMemo( - () => valid || (successtext && isNotEmptyString(successtext) ? true : false), - [valid, successtext] - ) - - useEffect(() => { - setSelectedValue(value) - }, [value] ) - - useEffect(() => { - setHasError(error) - }, [error]) - - useEffect(() => { - setIsLoading(loading) - }, [loading]) - - useEffect(() => { - setIsInvalid(invalidated) - }, [invalidated]) - - useEffect(() => { - setIsValid(validated) - }, [validated]) - - const handleChange = (value) => { - setSelectedValue(value) - onChange && onChange(value) - } - - const handleInputChange = (event) => { - setQuery(event?.target?.value) - onInputChange && onInputChange(event) - } - - const handleFocus = (event) => { - setFocus(true) - onFocus && onFocus(event) - } - - const handleBlur = (event) => { - setFocus(false) - onBlur && onBlur(event) - } - - const portalContainerRef = usePortalRef() - - // Headless-UI-Float Middleware - const middleware = [ - offset(4), - shift(), - flip(), - size({ - boundary: 'viewport', - apply({availableWidth, availableHeight, elements}) { - Object.assign(elements.floating.style, { - maxWidth: `${availableWidth}px`, - maxHeight: `${availableHeight}px`, - overflowY: "auto" - }) - } - }) - ] - - const filteredChildren = - query === "" - ? children - : children.filter((child) => { - // ensure that we filter on the value that is displayed to the user. Apply the same logic as when rendering - // the options, i.e. match children if present, if not match label, lastly if neither label nor children exist, then check value - const optionDisplayValue = child.props.children?.toString() || child.props.label || child.props.value - return optionDisplayValue?.toLowerCase().includes(query.toLowerCase()) - } - ) - - - return ( - - - <ComboBoxContext.Provider value={{ - selectedValue: selectedValue, - truncateOptions: truncateOptions, - addOptionValueAndLabel: addOptionValueAndLabel - }} - > - - <div - className={` - juno-combobox-wrapper - jn-relative - ${ width == "auto" ? "jn-inline-block" : "jn-block" } - ${ width == "auto" ? "jn-w-auto" : "jn-w-full" } - `} - > - <Combobox - defaultValue={defaultValue} - disabled={ disabled || isLoading || hasError } - name={name} - nullable={nullable} - onChange={handleChange} - value={ selectedValue || defaultValue } - {...props} - > - - <Float - composable - adaptiveWidth - middleware={middleware} - > - - <Float.Reference> - <div - className={` - juno-combobox-input-wrapper - ${ inputWrapperStyles } - ${ disabled ? "jn-cursor-not-allowed" : "" } - `} - > - - { label && isNotEmptyString(label) && !isLoading && !hasError ? - <Label - text={label} - disabled={disabled} - required={required} - htmlFor={theId} - className={`${labelStyles}`} - floating - minimized={ placeholder || hasFocus || (query && isNotEmptyString(query) || (selectedValue && isNotEmptyString(selectedValue)) ) ? true : false} - /> - : - "" - } - - <Combobox.Input - autoComplete="off" - aria-label={ ariaLabel || label } - aria-describedby={ helptext ? helptextId : "" } - disabled={ disabled || isLoading || hasError } - id={theId} - onBlur={handleBlur} - onChange={handleInputChange} - onFocus={handleFocus} - placeholder={ !isLoading && !hasError ? placeholder : ""} - displayValue={ - (val) => - optionValuesAndLabels.get(val)?.children || optionValuesAndLabels.get(val)?.label || valueLabel || val - - - } // Headless-UI expects a callback here - className={` - juno-combobox-input - ${inputStyles} - ${ label && isNotEmptyString(label) ? withLabelInputStyles : noLabelInputStyles } - ${ disabled ? disabledInputStyles : "" } - ${ isInvalid ? "juno-combobox-invalid " + invalidStyles : "" } - ${ isValid ? "juno-combobox-valid " + validStyles : "" } - ${ isValid || isInvalid ? "" : defaultBorderStyles } - ${ isLoading ? "juno-combobox-loading jn-cursor-not-allowed" : "" } - ${ hasError ? "juno-combobox-error jn-cursor-not-allowed" : "" } - ${className} - `} - /> - - { - isLoading || hasError ? - <span className={`${centeredIconStyles}`}> - { isLoading ? - <Spinner className={"jn-cursor-not-allowed"} /> - : - <Icon icon="errorOutline" color="jn-text-theme-error" className={"jn-cursor-not-allowed"} /> - } - </span> - : - isValid || isInvalid ? - <span className={` - juno-combobox-icon-container - ${iconContainerStyles} - ${ disabled ? "jn-opacity-50" : "" } - `}> - <Icon - icon={ isValid ? "checkCircle" : "dangerous" } - color={ isValid ? "jn-text-theme-success" : "jn-text-theme-error" } - /> - </span> - : - "" - } - - { !hasError && !isLoading ? - - <Combobox.Button - disabled={disabled} - className={` - juno-combobox-toggle - ${buttonStyles} - ${ disabled ? disabledButtonStyles : "" } - ${ isInvalid ? "juno-combobox-toggle-invalid " + invalidButtonStyles : "" } - ${ isValid ? "juno-combobox-toggle-valid " + validButtonStyles : "" } - ${ isValid || isInvalid ? "" : defaultButtonStyles } - `} - > - {({open}) => ( - <Icon icon={ open ? "expandLess": "expandMore"} /> - )} - </Combobox.Button> - - : "" - } - </div> - </Float.Reference> - - - { createPortal( - <Float.Content> - <Combobox.Options - unmount={false} - className={` - juno-combobox-options - ${menuStyles} - `} - > - { filteredChildren } - </Combobox.Options> - </Float.Content> - , portalContainerRef ? portalContainerRef : document.body - )} - - </Float> - - </Combobox> - - { errortext && isNotEmptyString(errortext) ? - <FormHint text={errortext} variant="error"/> - : - "" - } - { successtext && isNotEmptyString(successtext) ? - <FormHint text={successtext} variant="success"/> - : - "" - } - { helptext && isNotEmptyString(helptext) ? - <FormHint text={helptext} id={helptextId} /> - : - "" - } - - </div> - - </ComboBoxContext.Provider> - - ) - -} - - -ComboBox.propTypes = { - /** The aria-label of the ComboBox. Defaults to the label if label was passed. */ - ariaLabel: PropTypes.string, - /** The children to Render. Use `ComboBox.Option` elements. */ - children: PropTypes.node, - /** A custom className. Will be passed to the text input element of the ComboBox */ - className: PropTypes.string, - /** Pass a defaultValue to use as an uncontrolled Component that will handle its state internally */ - defaultValue: PropTypes.string, - /** Whether the ComboBox is disabled */ - disabled: PropTypes.bool, - /** Whether the ComboBox has an error. Note this refers to an internal error like failing to load options etc., to indicate failed validation use `invalid` instead. */ - error: PropTypes.bool, - /** An errortext to display when the ComboBox failed validation or an internal error occurred. */ - errortext: PropTypes.node, - /** A helptext to render to explain meaning and significance of the ComboBox */ - helptext: PropTypes.node, - /** The Id of the ComboBox. Will be assigned to the text input part of the ComboBox. If not passed, an id will be auto-generated. */ - id: PropTypes.string, - /** Whether the ComboBox failed validation */ - invalid: PropTypes.bool, - /** The label of the ComboBox */ - label: PropTypes.string, - /** Whether the ComboBox is busy loading options */ - loading: PropTypes.bool, - /** The name attribute of the ComboBox when used as part of a form */ - name: PropTypes.string, - /** Whether the ComboBox can be reset to having no value selected by manually clearing the text and clicking outside of the ComboBox. Default is TRUE. When set to FALSE, the selected value can only be changed by selecting another value after the initial selection, but never back to no selected value at all. */ - nullable: PropTypes.bool, - /** A handler to execute when the ComboBox looses focus */ - onBlur: PropTypes.func, - /** A handler to execute when the ComboBox' selected value changes */ - onChange: PropTypes.func, - /** A handler to execute when the ComboBox input receives focus */ - onFocus: PropTypes.func, - /** Handler to execute when the ComboBox text input value changes */ - onInputChange: PropTypes.func, - /** A placeholder to render in the text input */ - placeholder: PropTypes.string, - /** Whether the ComboBox is required */ - required: PropTypes.bool, - /** A text to display in case the ComboBox was successfully validated. Will set the ComboBox to `valid` when passed. */ - successtext: PropTypes.node, - /** Whether the option labels should be truncated in case they are longer/wider than the available space in an option or not. Default is FALSE. */ - truncateOptions: PropTypes.bool, - /** Whether the ComboBox was successfully validated */ - valid: PropTypes.bool, - /** The selected value of the ComboBox in Controlled Mode. */ - value: PropTypes.string, - /** The label of the passed value or defaultValue. If you want to use controlled mode or pass as defaultValue in uncontrolled mode and additionally use labels for human-readable SelectOptions, you need to also pass the matching label for the passed value/defaultValue so that the Select component can render itself properly */ - valueLabel: PropTypes.string, - /** The width of the text input. Either 'full' (default) or 'auto'. */ - width: PropTypes.oneOf(["full", "auto"]) -} - -ComboBox.defaultProps = { - ariaLabel: undefined, - children: null, - className: "", - defaultValue: "", - disabled: false, - error: false, - errortext: "", - helptext: "", - id: "", - invalid: false, - label: undefined, - loading: false, - name: "", - nullable: true, - onBlur: undefined, - onChange: undefined, - onFocus: undefined, - onInputChange: undefined, - placeholder: "Select…", - required: false, - successtext: "", - truncateOptions: false, - valid: false, - value: "", - valueLabel: undefined, - width: "full", -} diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.stories.js b/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.stories.js deleted file mode 100644 index b2eb4eed0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.stories.js +++ /dev/null @@ -1,886 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from 'react'; -import { ComboBox } from './index.js'; -import { ComboBoxOption } from '../ComboBoxOption/index.js'; -import { PortalProvider } from '../PortalProvider/PortalProvider.component'; - -export default { - title: 'Forms/ComboBox/ComboBox', - component: ComboBox, - argTypes: { - children: { - control: false, - }, - errortext: { - control: false, - }, - helptext: { - control: false, - }, - successtext: { - control: false, - }, - }, - decorators: [ - (Story) => ( - <div className="jn-pb-12"> - <PortalProvider> - <Story /> - </PortalProvider> - </div> - ), - ], -}; - -const Template = ({ children, ...args }) => { - return <ComboBox {...args}>{children}</ComboBox>; -}; - -const ConstrainedWidthTemplate = ({ children, ...args }) => { - return ( - <div style={{ width: '300px' }}> - <ComboBox {...args}>{children}</ComboBox> - </div> - ); -}; - -const ControlledTemplate = ({ value, children, ...args }) => { - const [v, setV] = useState(value); - - useEffect(() => { - setV(value); - }, [value]); - - return <ComboBox value={v}>{children}</ComboBox>; -}; - -export const Default = { - render: Template, - - args: { - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const ControlledComboBox = { - render: ControlledTemplate, - - args: { - value: 'Houdini', - label: 'A controlled ComboBox', - children: [ - <ComboBoxOption value="Caligari" key="1"> - Caligari - </ComboBoxOption>, - <ComboBoxOption value="Houdini" key="2"> - Houdini - </ComboBoxOption>, - <ComboBoxOption value="Lencia" key="3"></ComboBoxOption>, - ], - }, -}; - -export const UncontrolledComboBox = { - render: Template, - - args: { - defaultValue: 'Lencia', - label: 'An uncontrolled ComboBox', - children: [ - <ComboBoxOption value="Caligari" key="1"> - Caligari - </ComboBoxOption>, - <ComboBoxOption value="Houdini" key="2"> - Houdini - </ComboBoxOption>, - <ComboBoxOption value="Lencia" key="3"></ComboBoxOption>, - ], - }, -}; - -export const WithLabel = { - render: Template, - - args: { - label: 'ComboBox', - placeholder: '', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const WithLabelAndPlaceholder = { - render: Template, - - args: { - label: 'ComboBox', - placeholder: 'Type or select an Option…', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const Required = { - render: Template, - - args: { - label: 'Required ComboBox', - required: true, - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const Valid = { - render: Template, - - args: { - label: 'Valid ComboBox', - valid: true, - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const Invalid = { - render: Template, - - args: { - label: 'invalid ComboBox', - invalid: true, - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const Disabled = { - render: Template, - - args: { - label: 'Disabled ComboBox', - disabled: true, - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const DisabledOption = { - render: Template, - - args: { - label: 'ComboBox with a Disabled Option', - helptext: 'Option Carrots should be disabled', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2" disabled> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - ], - }, -}; - -export const WithHelpText = { - render: Template, - - args: { - label: 'ComboBox', - helptext: 'Helptext to describe meaning and significance of the ComboBox', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const WithHelpTextAsNode = { - render: Template, - - args: { - label: 'ComboBox', - helptext: ( - <> - This is a helptext with a <a href="#">Link</a> - </> - ), - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const WithErrorText = { - render: Template, - - args: { - label: 'ComboBox', - errortext: 'Invalidated by passing an errortext', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const WithSuccessText = { - render: Template, - - args: { - label: 'ComboBox', - successtext: 'Validated by passing a successtext', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - <ComboBoxOption value="Eggplant" key="7"> - Eggplant - </ComboBoxOption>, - <ComboBoxOption value="Zucchini" key="8"> - Zucchini - </ComboBoxOption>, - <ComboBoxOption value="Brussels sprouts" key="9"> - Brussels Sprouts - </ComboBoxOption>, - <ComboBoxOption value="Horseradish" key="10"> - Horseradish - </ComboBoxOption>, - <ComboBoxOption value="Green beans" key="11"> - Green Beans - </ComboBoxOption>, - <ComboBoxOption value="Mushrooms" key="12"> - Mushrooms - </ComboBoxOption>, - <ComboBoxOption value="Leek" key="13"> - Leek - </ComboBoxOption>, - <ComboBoxOption value="Artichokes" key="14"> - Artichokes - </ComboBoxOption>, - <ComboBoxOption value="Peas" key="15"> - Peas - </ComboBoxOption>, - <ComboBoxOption value="Potatoes" key="16"> - Potatoes - </ComboBoxOption>, - ], - }, -}; - -export const NonNullable = { - render: Template, - - args: { - nullable: false, - label: 'Non-Nullable ComboBox', - helptext: - 'This Select can not be reset to having no value selected. The last selected value will remian selected when emptying the input field.', - children: [ - <ComboBoxOption value="Rhubarb" key="1"> - Rhubarb - </ComboBoxOption>, - <ComboBoxOption value="Carrots" key="2"> - Carrots - </ComboBoxOption>, - <ComboBoxOption value="Spinach" key="3"> - Spinach - </ComboBoxOption>, - <ComboBoxOption value="Tomatoes" key="4"> - Tomatoes - </ComboBoxOption>, - <ComboBoxOption value="Cucumbers" key="5"> - Cucumbers - </ComboBoxOption>, - <ComboBoxOption value="Cauliflower" key="6"> - Cauliflower - </ComboBoxOption>, - ], - }, -}; - -export const NonTruncatedOptions = { - render: ConstrainedWidthTemplate, - - args: { - children: [ - <ComboBoxOption - value="Option with a very long title that is so long it will most likely not fit into the menu width, not at all really." - key="1" - ></ComboBoxOption>, - <ComboBoxOption - value="Yet another option with a very long title that is so long it will most likely not fit into the menu width, not at all really." - key="2" - ></ComboBoxOption>, - ], - }, -}; - -export const TruncatedOptions = { - render: ConstrainedWidthTemplate, - - args: { - truncateOptions: true, - children: [ - <ComboBoxOption - value="Option with a very long title that is so long it will most likely not fit into the menu width, not at all really." - key="1" - ></ComboBoxOption>, - <ComboBoxOption - value="Yet another option with a very long title that is so long it will most likely not fit into the menu width, not at all really." - key="2" - ></ComboBoxOption>, - ], - }, -}; - -export const OptionsWithLabels = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'If an option has both a label and a child, then the child is displayed instead of the label', - }, - }, - }, - - args: { - children: [ - <ComboBoxOption value="option1_value" label="Option 1 Label" key="1" />, - <ComboBoxOption value="option2_value" label="Option 2 Label" key="2"> - Option 2 child is displayed instead of label - </ComboBoxOption>, - ], - }, -}; - -export const Loading = { - render: Template, - - args: { - loading: true, - helptext: 'ComboBox busy loading options', - }, -}; - -export const Error = { - render: Template, - - args: { - error: true, - errortext: 'ComboBox having trouble loading options', - }, -}; - -export const ValueAndDefaultValue = { - render: Template, - - args: { - value: 'Option 1', - defaultValue: 'Option 2', - children: [ - <ComboBoxOption value="Option 1" key="1" />, - <ComboBoxOption value="Option 2" key="2" />, - <ComboBoxOption value="Option 3" key="3" />, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.test.js b/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.test.js deleted file mode 100644 index 25958bdb4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBox/ComboBox.test.js +++ /dev/null @@ -1,401 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { cleanup, render, screen, fireEvent } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { ComboBox } from "./index" -import { ComboBoxOption } from "../ComboBoxOption/index" - -const mockOnBlur = jest.fn() -const mockOnChange = jest.fn() -const mockOnFocus = jest.fn() -const mockOnInputChange = jest.fn() - -describe("ComboBox", () => { - afterEach(() => { - cleanup() - jest.clearAllMocks() - }) - - test("renders a ComboBox", async () => { - render(<ComboBox />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute("type", "text") - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-input") - }) - - test("renders a ComboBox with a name as passed", async () => { - render( - <ComboBox name="my-wonderful-combobox"> - <ComboBoxOption value="Option 1">Option 1</ComboBoxOption> - </ComboBox> - ) - expect(screen.getByRole("combobox")).toBeInTheDocument() - /* Here we need to directly select the input, since headless - a) does not add the name to the visible input element but to another, hidden input element it keeps in sync, and - b) react-testing fails when trying to access hidden elements by role: */ - expect( - document.querySelector("input[name='my-wonderful-combobox']") - ).toBeInTheDocument() - }) - - test("renders a ComboBox with a label as passed", async () => { - render(<ComboBox label="My Label" />) - expect(document.querySelector(".juno-label")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toHaveTextContent("My Label") - }) - - test("renders options as passed", async () => { - render( - <ComboBox> - <ComboBoxOption value="Option 1">Option 1</ComboBoxOption> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - const cbutton = screen.getByRole("button") - expect(cbox).toBeInTheDocument() - expect(cbutton).toBeInTheDocument() - await userEvent.click(cbutton) - expect(screen.getByRole("listbox")).toBeInTheDocument() - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveTextContent("Option 1") - }) - - test("renders an id as passed", async () => { - render(<ComboBox id="My Id" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute("id", "My Id") - }) - - test("renders the id of the ComboBox input as the for attribute of the label", async () => { - render(<ComboBox label="the label" />) - const cbox = screen.getByRole("combobox") - const label = document.querySelector(".juno-label") - expect(cbox).toBeInTheDocument() - expect(label).toBeInTheDocument() - expect(label.getAttribute("for")).toMatch(cbox.getAttribute("id")) - expect(screen.getByLabelText("the label")).toBeInTheDocument() - }) - - test("renders an aria-label as passed", async () => { - render(<ComboBox ariaLabel="my aria-label" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute( - "aria-label", - "my aria-label" - ) - }) - - test("renders the label as an aria-label if no aria-label was passed", async () => { - render(<ComboBox label="My Label" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute( - "aria-label", - "My Label" - ) - }) - - test("renders a ComboBox with a placeholder as passed", async () => { - render(<ComboBox placeholder="My Placeholder" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute( - "placeholder", - "My Placeholder" - ) - }) - - test("renders a disabled ComboBox as passed", async () => { - render(<ComboBox disabled />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toBeDisabled() - }) - - test("renders a required ComboBox as passed", async () => { - render(<ComboBox label="My Required ComboBox" required />) - expect(document.querySelector(".juno-label")).toBeInTheDocument() - expect(document.querySelector(".juno-required")).toBeInTheDocument() - }) - - test("renders a validated ComboBox as passed", async () => { - render(<ComboBox valid />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-valid") - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders a validated ComboBox when a successtext was passed", async () => { - render(<ComboBox successtext="Great Success!" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-valid") - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders an invalidated ComboBox as passed", async () => { - render(<ComboBox invalid />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders an invalidated ComboBox when an errortext was passed", async () => { - render(<ComboBox errortext="Oh Snap!" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-invalid") - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders a helptext as passed", async () => { - render(<ComboBox helptext="A helptext goes here" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-help" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "A helptext goes here" - ) - }) - - test("renders an errortext as passed", async () => { - render(<ComboBox errortext="An errortext goes here" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-error" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "An errortext goes here" - ) - }) - - test("renders a successtext as passed", async () => { - render(<ComboBox successtext="A successtext goes here" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-success" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "A successtext goes here" - ) - }) - - test("renders a loading ComboBox with a Spinner as passed", async () => { - render(<ComboBox loading />) - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-loading") - expect(document.querySelector(".juno-spinner")).toBeInTheDocument() - }) - - test("renders a ComboBox in error state with an Error icon as passed", async () => { - render(<ComboBox error />) - expect(screen.getByRole("combobox")).toHaveClass("juno-combobox-error") - expect(screen.getByTitle("Error")).toBeInTheDocument() - }) - - test("fires an onBlur handler as passed when the ComboBox looses focus", async () => { - render(<ComboBox onBlur={mockOnBlur} />) - const user = userEvent.setup() - const cbox = screen.getByRole("combobox") - await user.click(cbox) // focus the element - await user.tab() // blur the element - expect(mockOnBlur).toHaveBeenCalled() - }) - - test("fires an onChange handler as passed when the user selects an option", async () => { - render( - <ComboBox onChange={mockOnChange}> - <ComboBoxOption value="option 1">Option 1</ComboBoxOption> - <ComboBoxOption value="option 2">Option 2</ComboBoxOption> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - const cbutton = screen.getByRole("button") - expect(cbox).toBeInTheDocument() - expect(cbutton).toBeInTheDocument() - await userEvent.click(cbutton) - expect(screen.getByRole("listbox")).toBeInTheDocument() - await userEvent.click(screen.getByRole("option", { name: "Option 2" })) - expect(mockOnChange).toHaveBeenCalled() - }) - - test("fires an onFocus handler as passed when the ComboBox receives focus", async () => { - render(<ComboBox onFocus={mockOnFocus} />) - const cbox = screen.getByRole("combobox") - await userEvent.click(cbox) - expect(mockOnFocus).toHaveBeenCalled() - }) - - test("fires an onInputChange handler when the user types into the ComboBox", async () => { - render( - <ComboBox onInputChange={mockOnInputChange}> - <ComboBoxOption value="something">Something</ComboBoxOption> - <ComboBoxOption value="something else">Something else</ComboBoxOption> - </ComboBox> - ) - const user = userEvent.setup() - const cbox = screen.getByRole("combobox") - await user.type(cbox, "a") - expect(mockOnInputChange).toHaveBeenCalled() - }) - - test("filters options as the user types", async () => { - render( - <ComboBox> - <ComboBoxOption value="aaa" name="aaa"> - aaa - </ComboBoxOption> - <ComboBoxOption value="aab" name="aab"> - aab - </ComboBoxOption> - <ComboBoxOption value="abc" name="abc"> - abc - </ComboBoxOption> - <ComboBoxOption value="123" name="123"> - 123 - </ComboBoxOption> - </ComboBox> - ) - const user = userEvent.setup() - const cbox = screen.getByRole("combobox") - expect(cbox).toBeInTheDocument() - await user.type(cbox, "a") - expect(screen.getByRole("listbox")).toBeInTheDocument() - expect(screen.getByRole("option", { name: "aaa" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "aab" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "abc" })).toBeInTheDocument() - expect( - screen.queryByRole("option", { name: "123" }) - ).not.toBeInTheDocument() - await user.type(cbox, "b") - expect( - screen.queryByRole("option", { name: "aaa" }) - ).not.toBeInTheDocument() - expect(screen.getByRole("option", { name: "aab" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "abc" })).toBeInTheDocument() - expect( - screen.queryByRole("option", { name: "123" }) - ).not.toBeInTheDocument() - await userEvent.clear(cbox) - expect(screen.getByRole("option", { name: "aaa" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "aab" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "abc" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "123" })).toBeInTheDocument() - await user.type(cbox, "1") - expect( - screen.queryByRole("option", { name: "aaa" }) - ).not.toBeInTheDocument() - expect( - screen.queryByRole("option", { name: "aab" }) - ).not.toBeInTheDocument() - expect( - screen.queryByRole("option", { name: "abc" }) - ).not.toBeInTheDocument() - expect(screen.getByRole("option", { name: "123" })).toBeInTheDocument() - }) - - test("selects an option when the user clicks it and closes the menu", async () => { - render( - <ComboBox> - <ComboBoxOption value="aaa" name="aaa"> - aaa - </ComboBoxOption> - <ComboBoxOption value="aab" name="aab"> - aab - </ComboBoxOption> - <ComboBoxOption value="abc" name="abc"> - abc - </ComboBoxOption> - <ComboBoxOption value="123" name="123"> - 123 - </ComboBoxOption> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - const cbutton = screen.getByRole("button") - expect(cbox).toBeInTheDocument() - expect(cbutton).toBeInTheDocument() - await userEvent.click(cbutton) - expect(screen.getByRole("listbox")).toBeInTheDocument() - await userEvent.click(screen.getByRole("option", { name: "abc" })) - expect(screen.queryByRole("listbox")).not.toBeInTheDocument() - expect(cbox).toHaveValue("abc") - }) - - test("works as a controlled component with a value as passed", async () => { - render( - <ComboBox value="aab"> - <ComboBoxOption value="aaa" name="aaa"> - aaa - </ComboBoxOption> - <ComboBoxOption value="aab" name="aab"> - aab - </ComboBoxOption> - <ComboBoxOption value="abc" name="abc"> - abc - </ComboBoxOption> - <ComboBoxOption value="123" name="123"> - 123 - </ComboBoxOption> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - const toggle = screen.getByRole("button") - expect(cbox).toBeInTheDocument() - expect(toggle).toBeInTheDocument() - expect(cbox).toHaveValue("aab") - await userEvent.click(toggle) - expect(screen.getByRole("listbox")).toBeInTheDocument() - const option123 = screen.getAllByRole("option")[3] - expect(option123).toHaveTextContent("123") - await userEvent.click(option123) - expect(cbox).toHaveValue("123") - }) - - test("works as an uncontrolled component with a defaultValue as passed", async () => { - render( - <ComboBox defaultValue="abc"> - <ComboBoxOption>aaa</ComboBoxOption> - <ComboBoxOption>aab</ComboBoxOption> - <ComboBoxOption>abc</ComboBoxOption> - <ComboBoxOption>123</ComboBoxOption> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - const toggle = screen.getByRole("button") - expect(cbox).toBeInTheDocument() - expect(toggle).toBeInTheDocument() - expect(cbox).toHaveValue("abc") - await userEvent.click(toggle) - expect(screen.getByRole("listbox")).toBeInTheDocument() - const option123 = screen.getAllByRole("option")[3] - expect(option123).toHaveTextContent("123") - await userEvent.click(option123) - expect(cbox).toHaveValue("123") - }) - - // Caution: The below test basically tests headless-ui behaviour, not our logic. This is here only for testing consistency and so that we know should headless ever change their behaviour: - test("works as a controlled component using value when both value and defaultValue have been passed", async () => { - render( - <ComboBox defaultValue="option 1" value="option 2"> - <ComboBoxOption value="option 1" /> - <ComboBoxOption value="option 2" /> - </ComboBox> - ) - const cbox = screen.getByRole("combobox") - expect(cbox).toBeInTheDocument() - expect(cbox).toHaveValue("option 2") - }) - - test("renders a ComboBox with a custom className as passed", async () => { - render(<ComboBox className="my-combobox" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("my-combobox") - }) - - // Skipping because if we pass generic props to the ComboBox component it will be passed to the abstract headless Combobox component, but will not end up in the DOM: - test.skip("renders all props as passed", async () => { - render(<ComboBox data-lolo="1234" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute("data-lolo", "1234") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBox/index.js b/libs_deprecated/juno-ui-components/src/components/ComboBox/index.js deleted file mode 100644 index 1f4828da1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBox/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ComboBox } from "./ComboBox.component.js" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.component.js b/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.component.js deleted file mode 100644 index 4e39ccc55..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.component.js +++ /dev/null @@ -1,123 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { Fragment, useState, useEffect, useContext } from "react" -import PropTypes from "prop-types" -import { Combobox } from "@headlessui/react" -import { ComboBoxContext } from "../ComboBox/ComboBox.component" -import { Icon } from "../Icon/Icon.component" - - -const optionStyles = ` - jn-flex - jn-pt-[0.6875rem] - jn-pb-[0.5rem] - jn-pr-[0.875rem] - jn-select-none - data-[headlessui-state=active]:jn-outline-none - data-[headlessui-state=active]:jn-ring-2 - data-[headlessui-state=active]:jn-ring-inset - data-[headlessui-state=active]:jn-ring-theme-focus - data-[headlessui-state=active]:jn-bg-theme-background-lvl-3 -` - -const unselectedOptionStyles = ` - jn-text-theme-default - jn-pl-[2.375rem] -` - -const selectedOptionStyles = ` - jn-text-theme-accent - jn-pl-3.5 -` - -const selectedIconStyles = ` - jn-inline-block - jn-mr-1.5 -` - -const disabledOptionLabelStyles = ` - jn-opacity-50 - jn-cursor-not-allowed -` - -const truncateOptionStyles = ` - jn-block - jn-h-6 - jn-overflow-hidden - jn-text-ellipsis - jn-whitespace-nowrap -` - -export const ComboBoxOption = ({ - children, - disabled, - value, - label, - className, - ...props -}) => { - - const comboBoxContext = useContext(ComboBoxContext) - const { - selectedValue: selectedValue, - truncateOptions: truncateOptions, - addOptionValueAndLabel: addOptionValueAndLabel - } = comboBoxContext || {} - - // send option metadata to the ComboBox parent component via Context - useEffect(() => { - addOptionValueAndLabel(value, label, children) - }, [value, label, children]) - - const theValue = value || children - - return ( - <Combobox.Option - value={theValue} - disabled={disabled} - as={Fragment} - > - <li - className={` - juno-combobox-option - ${ optionStyles} - ${ selectedValue === value ? selectedOptionStyles : unselectedOptionStyles } - ${ disabled ? "jn-cursor-not-allowed" : "" } - ${ className } - `} - {...props} - > - { selectedValue === theValue ? <Icon icon="check" size="18" className={`${selectedIconStyles}`} /> : "" } - <span - className={` - ${ disabled ? disabledOptionLabelStyles : "" } - ${ truncateOptions ? truncateOptionStyles : "" } - `} - > - { children || label || value } - </span> - </li> - - </Combobox.Option> - ) -} - - -ComboBoxOption.propTypes = { - children: PropTypes.string, - disabled: PropTypes.bool, - value: PropTypes.string, - label: PropTypes.string, - className: PropTypes.string, -} - -ComboBoxOption.defaultProps = { - children: undefined, - disabled: false, - value: "", - label: undefined, - className: "", -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.stories.js b/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.stories.js deleted file mode 100644 index 19111cdce..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.stories.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { ComboBox } from '../ComboBox/ComboBox.component'; -import { ComboBoxOption } from '../ComboBoxOption/ComboBoxOption.component'; - -export default { - title: 'Forms/ComboBox/ComboBoxOption', - component: ComboBoxOption, - argTypes: {}, -}; - -const Template = (args) => { - return ( - <ComboBox> - <ComboBoxOption {...args} /> - </ComboBox> - ); -}; - -export const Default = { - render: Template, - - args: { - value: 'Option 1', - }, -}; - -export const Disabled = { - render: Template, - - args: { - disabled: true, - value: 'Disabled Option', - }, -}; - -export const ChildrenOnly = { - render: Template, - - args: { - children: 'Option 1', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.test.js b/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.test.js deleted file mode 100644 index 9be5e7c25..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/ComboBoxOption.test.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { cleanup, render, screen } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { ComboBox } from "../ComboBox/ComboBox.component" -import { ComboBoxOption } from "../ComboBoxOption/ComboBoxOption.component" - - -describe("ComboBoxOption", () => { - - afterEach(() => { - cleanup(); - jest.clearAllMocks(); - }); - - test("renders a ComboBoxOption", async () => { - render( - <ComboBox> - <ComboBoxOption value="Option 1" /> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveTextContent("Option 1") - }) - - test("renders a ComboBoxOption with label as passed", async () => { - render( - <ComboBox> - <ComboBoxOption value="option 1 value" label="Option 1 Label" /> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveTextContent("Option 1 Label") - }) - - test("renders a ComboBoxOption with children as passed", async () => { - render( - <ComboBox> - <ComboBoxOption value="option 1 value">Option 1 child</ComboBoxOption> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveTextContent("Option 1 child") - }) - - test("renders a ComboBoxOption with children if both label and children are passed", async () => { - render( - <ComboBox> - <ComboBoxOption value="option 1 value" label="Option 1 Label">Option 1 child</ComboBoxOption> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveTextContent("Option 1 child") - }) - - test("renders a className as passed", async () => { - render( - <ComboBox> - <ComboBoxOption className="my-fancy-class"/> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveClass("my-fancy-class") - }) - - test("renders all props as passed", async () => { - render( - <ComboBox> - <ComboBoxOption data-lolol="123"/> - </ComboBox> - ) - const toggle = screen.getByRole("button") - expect(toggle).toBeInTheDocument() - await userEvent.click(toggle) - expect(screen.getByRole("option")).toBeInTheDocument() - expect(screen.getByRole("option")).toHaveAttribute("data-lolol", "123") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/index.js b/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/index.js deleted file mode 100644 index d24e1f852..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ComboBoxOption/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ComboBoxOption } from "./ComboBoxOption.component.js" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Container/Container.component.js b/libs_deprecated/juno-ui-components/src/components/Container/Container.component.js deleted file mode 100644 index 356519ea3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Container/Container.component.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const containerStyles = (px, py) => { - return ` - ${ px ? "jn-px-6 " : " " } - ${ py ? " jn-py-6" : "" } - ` -} - -/** - * A very basic layout container with padding. - */ -export const Container = ({ - px, - py, - className, - children, - ...props -}) => { - return ( - <div - className={`juno-container ${containerStyles(px, py)} ${className}`} - {...props} - > - {children} - </div> - ) -} - -Container.propTypes = { - /** Choose false if you don't want horizontal padding to be added. */ - px: PropTypes.bool, - /** Set to true to add vertical padding. */ - py: PropTypes.bool, - /** Add custom class name */ - className: PropTypes.string, - children: PropTypes.node, -} - -Container.defaultProps = { - px: true, - py: false, - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Container/Container.stories.js b/libs_deprecated/juno-ui-components/src/components/Container/Container.stories.js deleted file mode 100644 index 6751085d0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Container/Container.stories.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { Container } from './index.js'; - -export default { - title: 'Layout/Container', - component: Container, - argTypes: { - children: { - control: false, - }, - }, - parameters: { - docs: { - description: { - component: - 'A very basic layout element with padding. By default has padding all around. Can be set to have only vertical padding.', - }, - }, - }, -}; - -const Template = (args) => <Container {...args}>Content goes here</Container>; - -export const Basic = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Section for content displayed in the main content area. Has padding. Typically you will want to use one of these sections to wrap your main content inside as the content area itself doesn't have padding to allow for full-width content or content to be placed at the very top or bottom.", - }, - }, - }, - - args: {}, -}; - -export const WithVerticalPadding = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'A content container with vertical padding added. This will add padding to both the top and the bottom of the container.', - }, - }, - }, - - args: { - py: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Container/Container.test.js b/libs_deprecated/juno-ui-components/src/components/Container/Container.test.js deleted file mode 100644 index 8a40eef40..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Container/Container.test.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Container } from "./index" - -describe("Container", () => { - - test("renders children as passed", async () => { - render( - <Container data-testid="container"> - <button></button> - </Container> - ) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a container with horizontal padding by default", async () => { - render(<Container data-testid="container" />) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByTestId("container")).toHaveClass("jn-px-6") - expect(screen.getByTestId("container")).not.toHaveClass("jn-py-6") - }) - - test("renders a container without horizontal padding as passed", async () => { - render(<Container data-testid="container" px={false} />) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByTestId("container")).not.toHaveClass("jn-px-6") - expect(screen.getByTestId("container")).not.toHaveClass("jn-py-6") - }) - - test("renders a container with vertical padding as passed", async () => { - render(<Container data-testid="container" py={true} />) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByTestId("container")).toHaveClass("jn-px-6") - expect(screen.getByTestId("container")).toHaveClass("jn-py-6") - }) - - test("renders a custom className", async () => { - render( - <Container - data-testid="container" - className="my-custom-classname" - /> - ) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByTestId("container")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render(<Container data-testid="container" data-lolol="some-prop" />) - expect(screen.getByTestId("container")).toBeInTheDocument() - expect(screen.getByTestId("container")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Container/index.js b/libs_deprecated/juno-ui-components/src/components/Container/index.js deleted file mode 100644 index ae48fba60..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Container/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Container } from "./Container.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.component.js b/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.component.js deleted file mode 100644 index 39b47c33a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.component.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { withDeprecationWarning } from '../withDeprecationWarning/index.js' - -const containerStyles = ` - jn-bg-theme-content-area-bg - jn-relative - jn-grow -` - - - -/** - * Deprecated: This component used to be used internally by AppShell but has been removed there since. It was only needed to manually scaffold an app. Use AppShell to scaffold an app layout.. - */ -export const ContentArea = ({ className, children, ...props }) => { - - return ( - <div - className={`juno-content-area ${containerStyles} ${className}`} - {...props} - > - {children} - </div> - ) -} - -ContentArea.propTypes = { - /** Add custom class name */ - className: PropTypes.string, - children: PropTypes.node, -} - -ContentArea.defaultProps = { - className: "", - children: null, -} - -export default withDeprecationWarning(ContentArea, "ContentArea is deprecated and will be removed in future versions. To be future-proof, use AppShell to scaffold an app layout.") diff --git a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.stories.js b/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.stories.js deleted file mode 100644 index 4bfb82b4a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.stories.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" - -import { ContentArea } from "./index.js" - -export default { - title: "Deprecated/ContentArea", - component: ContentArea, - argTypes: { - children: { - control: false - }, - }, -} - -const Template = (args) => ( - <ContentArea {...args}>Content goes here</ContentArea> -) - -export const Basic = Template.bind({}) -Basic.parameters = { - docs: { - description: { - story: - "Deprecated: This component used to be used internally by AppShell but has been removed there since. It was only needed to manually scaffold an app. Use AppShell to scaffold an app layout.", - }, - }, -} -Basic.args = {} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.test.js b/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.test.js deleted file mode 100644 index 062f5a9d9..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentArea/ContentArea.test.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { ContentArea } from "./index" - -describe("ContentArea", () => { - test("renders a content area", async () => { - render(<ContentArea data-testid="content-area" />) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByTestId("content-area")).toHaveClass( - "juno-content-area" - ) - }) - - test("renders a deprecation warning to the console", async () => { - const consoleWarnSpy = jest.spyOn(console, 'warn') - render(<ContentArea/>) - expect(consoleWarnSpy).toHaveBeenCalled() - expect(consoleWarnSpy).toHaveBeenCalledWith( - "ContentArea is deprecated and will be removed in future versions. To be future-proof, use AppShell to scaffold an app layout." - ) - consoleWarnSpy.mockRestore() - }) - - test("renders a content area with content area background color", async () => { - render(<ContentArea data-testid="content-area" />) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByTestId("content-area")).toHaveClass("jn-bg-theme-content-area-bg") - }) - - test("renders a content area with flex grow", async () => { - render(<ContentArea data-testid="content-area" />) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByTestId("content-area")).toHaveClass("jn-grow") - }) - - test("renders children as passed", async () => { - render( - <ContentArea data-testid="content-area"> - <button></button> - </ContentArea> - ) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render( - <ContentArea - data-testid="content-area" - className="my-custom-classname" - /> - ) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByTestId("content-area")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render( - <ContentArea data-testid="content-area" data-lolol="some-prop" /> - ) - expect(screen.getByTestId("content-area")).toBeInTheDocument() - expect(screen.getByTestId("content-area")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContentArea/index.js b/libs_deprecated/juno-ui-components/src/components/ContentArea/index.js deleted file mode 100644 index fc03983c3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentArea/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { default as ContentArea } from "./ContentArea.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.js deleted file mode 100644 index af3e0c15e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.component.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - - -const toolbarStyles = ` - jn-bg-theme-background-lvl-1 - jn-py-3 - jn-px-6 - jn-flex - jn-items-center - jn-justify-end -` - -/** - * This is the main toolbar of the content area. Add main actions for the current page here. - */ -export const ContentAreaToolbar = ({ - className, - children, - ...props -}) => { - return ( - <div - className={`juno-content-area-toolbar ${toolbarStyles} ${className}`} - {...props} - > - {children} - </div> - ) -} - -ContentAreaToolbar.propTypes = { - /** Add custom class name */ - className: PropTypes.string, - children: PropTypes.node, -} - -ContentAreaToolbar.defaultProps = { - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.stories.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.stories.js deleted file mode 100644 index 019c9f166..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.stories.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { ContentAreaToolbar } from './index.js'; -import { Button } from '../Button/index.js'; - -export default { - title: 'Layout/ContentAreaToolbar', - component: ContentAreaToolbar, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => ( - <ContentAreaToolbar {...args}> - <Button>Main Action</Button> - </ContentAreaToolbar> -); - -export const Basic = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'This is the main toolbar of the content area. Add main actions, search bar, filters for the current page here.', - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.test.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.test.js deleted file mode 100644 index 62b7c8985..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/ContentAreaToolbar.test.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { ContentAreaToolbar } from "./index" - -describe("ContentAreaToolbar", () => { - test("renders a content area toolbar", async () => { - render(<ContentAreaToolbar data-testid="content-area-toolbar" />) - expect(screen.getByTestId("content-area-toolbar")).toBeInTheDocument() - expect(screen.getByTestId("content-area-toolbar")).toHaveClass("juno-content-area-toolbar") - }) - - test("renders children as passed", async () => { - render( - <ContentAreaToolbar data-testid="content-area-toolbar"> - <button></button> - </ContentAreaToolbar> - ) - expect(screen.getByTestId("content-area-toolbar")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render( - <ContentAreaToolbar - data-testid="content-area-toolbar" - className="my-custom-classname" - /> - ) - expect(screen.getByTestId("content-area-toolbar")).toBeInTheDocument() - expect(screen.getByTestId("content-area-toolbar")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render( - <ContentAreaToolbar data-testid="content-area-toolbar" data-lolol="some-prop" /> - ) - expect(screen.getByTestId("content-area-toolbar")).toBeInTheDocument() - expect(screen.getByTestId("content-area-toolbar")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/index.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/index.js deleted file mode 100644 index 397f1281c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaToolbar/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ContentAreaToolbar } from "./ContentAreaToolbar.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.component.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.component.js deleted file mode 100644 index 6d6223c81..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.component.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const containerStyles = ` - jn-relative - jn-grow - jn-flex - jn-flex-col - jn-overflow-hidden -` - -/** - * OBSOLETE: Will be deleted! - */ -export const ContentAreaWrapper = ({ className, children, ...props }) => { - return ( - <div - className={`juno-content-area-wrapper ${containerStyles} ${className}`} - {...props} - > - {children} - </div> - ) -} - -ContentAreaWrapper.propTypes = { - /** Add custom class name */ - className: PropTypes.string, - children: PropTypes.node, -} - -ContentAreaWrapper.defaultProps = { - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.stories.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.stories.js deleted file mode 100644 index 991253549..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.stories.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { ContentAreaWrapper } from './index.js'; -import { ContentArea } from '../ContentArea/index.js'; -import { ContentAreaToolbar } from '../ContentAreaToolbar/index.js'; -import { Button } from '../Button/index.js'; - -export default { - title: 'Internal/ContentAreaWrapper', - component: ContentAreaWrapper, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => ( - <ContentAreaWrapper {...args}> - <ContentAreaToolbar> - <Button>Example</Button> - </ContentAreaToolbar> - <ContentArea>Content goes here</ContentArea> - </ContentAreaWrapper> -); - -export const Basic = { - render: Template, - - parameters: { - docs: { - description: { - story: 'OBSOLETE: Will be deleted!', - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.test.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.test.js deleted file mode 100644 index 135829aef..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/ContentAreaWrapper.test.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { ContentAreaWrapper } from "./index" - -describe("ContentAreaWrapper", () => { - test("renders a content area wrapper", async () => { - render(<ContentAreaWrapper data-testid="content-area-wrapper" />) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByTestId("content-area-wrapper")).toHaveClass("juno-content-area-wrapper") - }) - - test("renders a content area with flex grow", async () => { - render(<ContentAreaWrapper data-testid="content-area-wrapper" />) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByTestId("content-area-wrapper")).toHaveClass("jn-grow") - }) - - test("renders a content area with flex col layout", async () => { - render(<ContentAreaWrapper data-testid="content-area-wrapper" />) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByTestId("content-area-wrapper")).toHaveClass("jn-flex-col") - }) - - test("renders children as passed", async () => { - render( - <ContentAreaWrapper data-testid="content-area-wrapper"> - <button></button> - </ContentAreaWrapper> - ) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render( - <ContentAreaWrapper - data-testid="content-area-wrapper" - className="my-custom-classname" - /> - ) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByTestId("content-area-wrapper")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render( - <ContentAreaWrapper data-testid="content-area-wrapper" data-lolol="some-prop" /> - ) - expect(screen.getByTestId("content-area-wrapper")).toBeInTheDocument() - expect(screen.getByTestId("content-area-wrapper")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/index.js b/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/index.js deleted file mode 100644 index 2e4f46d4d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentAreaWrapper/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ContentAreaWrapper } from "./ContentAreaWrapper.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.component.js b/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.component.js deleted file mode 100644 index 09f1ffbb6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.component.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - - -const containerStyles = ` - jn-flex-col - jn-grow - jn-bg-[right_top_1rem] - jn-bg-no-repeat - jn-bg-theme-content-area-bg - jn-relative -` - -/** - * Only needed if you want to build your app's scaffold manually. In most cases it is better to use the AppShell component instead. - * A container for app content. Will be centered on the screen when browser window is wider than the max breakpoint width. - */ -export const ContentContainer = ({ className, children, ...props }) => { - return ( - <div className={`juno-content-container ${containerStyles} ${className}`} {...props}> - {children} - </div> - ) -} - -ContentContainer.propTypes = { - /** Add custom class name */ - className: PropTypes.string, - children: PropTypes.node, -} - -ContentContainer.defaultProps = { - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.stories.js b/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.stories.js deleted file mode 100644 index 339c1c501..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.stories.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; - -import { ContentContainer } from './index.js'; - -export default { - title: 'Internal/ContentContainer', - component: ContentContainer, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = (args) => <ContentContainer {...args}>content</ContentContainer>; - -export const Centered = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Only needed if you want to build your app's scaffold manually. In most cases it is better to use the AppShell component instead. A wrapper for content components. Parent of ContentArea. Width will grow to the maximum breakpoint width and then be centered on the page if the browser is wider.", - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.test.js b/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.test.js deleted file mode 100644 index 70464ae7e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentContainer/ContentContainer.test.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { ContentContainer } from "./index" - -describe("ContentContainer", () => { - test("renders a content container", async () => { - render(<ContentContainer data-testid="content-container" />) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByTestId("content-container")).toHaveClass("juno-content-container") - }) - - test("renders a content container with flex col layout", async () => { - render(<ContentContainer data-testid="content-container" />) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByTestId("content-container")).toHaveClass("jn-flex-col") - }) - - test("renders a content container with flex grow", async () => { - render(<ContentContainer data-testid="content-container" />) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByTestId("content-container")).toHaveClass("jn-grow") - }) - - test("renders children as passed", async () => { - render( - <ContentContainer data-testid="content-container" > - <button></button> - </ContentContainer> - ) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<ContentContainer data-testid="content-container" className="my-custom-classname" />) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByTestId("content-container")).toHaveClass("my-custom-classname") - }) - - test("renders all props", async () => { - render(<ContentContainer data-testid="content-container" data-lolol="some-prop" />) - expect(screen.getByTestId("content-container")).toBeInTheDocument() - expect(screen.getByTestId("content-container")).toHaveAttribute("data-lolol", "some-prop") - }) - -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContentContainer/index.js b/libs_deprecated/juno-ui-components/src/components/ContentContainer/index.js deleted file mode 100644 index e77f3a250..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentContainer/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ContentContainer } from "./ContentContainer.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.component.js b/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.component.js deleted file mode 100644 index cac169d32..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.component.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const headingStyles = ` - jn-font-bold - jn-text-lg - jn-text-theme-high - jn-pb-2 -` - -/** - - *The main heading of a page/View. Pass as a child into `<AppShell>` or, when scaffolding manually, into `<ContentContainer>`. - */ -export const ContentHeading = ({ heading, className, children, ...props }) => { - return ( - <h1 - className={`juno-content-heading ${headingStyles} ${className}`} - {...props} - > - {children || heading} - </h1> - ) -} - -ContentHeading.propTypes = { - /** Optionally render children. If children are present, heading will be ignored */ - children: PropTypes.node, - /** Text to use as a title */ - heading: PropTypes.string, - /** Add custom class name */ - className: PropTypes.string, -} - -ContentHeading.defaultProps = { - heading: "", - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.stories.js b/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.stories.js deleted file mode 100644 index aed32bf77..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.stories.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { ContentHeading } from "./index.js" -import { Button } from "../Button/index.js" - -export default { - title: "Internal/ContentHeading", - component: ContentHeading, - argTypes: { - children: { - control: false - }, - }, -} - -const Template = (args) => <ContentHeading {...args} /> - -export const Default = Template.bind({}) -Default.parameters = { - docs: { - description: { - story: - "The the main heading of the content area of a page/view.", - }, - }, -} -Default.args = { - heading: "My Page Heading", -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.test.js b/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.test.js deleted file mode 100644 index 63b77c3ef..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentHeading/ContentHeading.test.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { ContentHeading } from "./index" - -describe("ContentHeading", () => { - test("renders a content heading", async () => { - render(<ContentHeading heading="My Heading" />) - expect(screen.getByRole("heading")).toBeInTheDocument() - expect(screen.getByRole("heading")).toHaveClass( - "juno-content-heading" - ) - }) - - test("renders a content heading with the given text", async () => { - render(<ContentHeading heading="My Heading" />) - expect(screen.getByRole("heading")).toHaveTextContent("My Heading") - }) - - test("renders children as passed", async () => { - render( - <ContentHeading > - <button></button> - </ContentHeading> - ) - expect(screen.getByRole("heading")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render( - <ContentHeading - className="my-custom-classname" - /> - ) - expect(screen.getByRole("heading")).toBeInTheDocument() - expect(screen.getByRole("heading")).toHaveClass( - "my-custom-classname" - ) - }) - - test("renders all props", async () => { - render( - <ContentHeading - data-lolol="some-prop" - /> - ) - expect(screen.getByRole("heading")).toBeInTheDocument() - expect(screen.getByRole("heading")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContentHeading/index.js b/libs_deprecated/juno-ui-components/src/components/ContentHeading/index.js deleted file mode 100644 index ded12626d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContentHeading/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ContentHeading } from "./ContentHeading.component" diff --git a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.component.js b/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.component.js deleted file mode 100644 index 24c514429..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.component.js +++ /dev/null @@ -1,94 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { Icon } from "../Icon/index.js" -import { Menu } from "@headlessui/react" -import { Float } from "@headlessui-float/react" - -/* -TODO: - -* close on [ESC] (prop?) -* close on click outside (prop?) -* keyboard navigation: arrow up/down moves focus -* for toggle styles (hover, active, etc.) -> expand icon (interactive) component or handle here (aka are these styles generically useful or specific to this component?) -* a11y -* docstrings -* fix stories -* don't ALWAYS render button!?! -*/ - -const menuStyles = ` - jn-overflow-hidden - jn-flex - jn-flex-col - jn-rounded - jn-bg-theme-background-lvl-1 -` - -const toggleStyles = ` - hover:jn-text-theme-accent - active:jn-text-theme-accent -` - -const toggleOpenStyle = ` - jn-text-theme-accent -` - -/** A context menu with a toggle. */ - -export const ContextMenu = ({ - icon, - className, - children, - open, - ...props -}) => { - const [isOpen, setIsOpen] = useState(false) - - const handleClick = (event) => { - setIsOpen(!isOpen) - } - - useEffect(() => { - setIsOpen(open) - }, [open]) - - return ( - <Menu> - <Float> - <Menu.Button - onClick={handleClick} - className={` - juno-contextmenu-toggle - ${toggleStyles} - ${ isOpen ? toggleOpenStyle : "" } - `}> - <Icon icon="moreVert"/> - </Menu.Button> - <Menu.Items - className={`${menuStyles}`} - > - {children} - </Menu.Items> - </Float> - </Menu> - ) -} - - -ContextMenu.propTypes = { - className: PropTypes.string, - children: PropTypes.node, - open: PropTypes.bool, -} - -ContextMenu.defaultProps = { - className: "", - children: null, - open: false, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.stories.js b/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.stories.js deleted file mode 100644 index de8c3e6aa..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.stories.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { ContextMenu } from "./index.js" -import { MenuItem } from "../MenuItem/MenuItem.component" -import { Button } from "../Button/index" -import { PortalProvider } from "../PortalProvider/PortalProvider.component" - -export default { - title: "WiP/ContextMenu/ContextMenu", - component: ContextMenu, - argTypes: { - children: { - control: false, - }, - }, -} - -const Template = ({ children, ...args }) => ( - <ContextMenu {...args}>{children}</ContextMenu> -) - -const PortalTemplate = ({ children, ...args }) => ( - <PortalProvider> - <PortalProvider.Portal> - <ContextMenu {...args}>{children}</ContextMenu> - </PortalProvider.Portal> - </PortalProvider> -) - -export const Default = { - render: Template, - - args: { - children: [ - <MenuItem - key="1" - label="Juno on Github" - href="https://github.com/sapcc/juno" - />, - <MenuItem key="2" label="This item does nothing" icon="help" />, - <MenuItem - key="3" - label="Disabled Item" - href="https://github.com/sapcc/juno" - disabled - />, - <MenuItem key="4"> - <Button - key={0} - label="Button as Child of MenuItem" - variant="subdued" - size="small" - className="jn-w-full" - /> - </MenuItem>, - <MenuItem - key="5" - onClick={() => {}} - label="Button as Item with OnClick" - icon="help" - />, - ], - }, -} - -export const InsidePortal = { - render: PortalTemplate, - - args: { - children: [ - <MenuItem - key="1" - label="Juno on Github" - href="https://github.com/sapcc/juno" - />, - <MenuItem key="2" label="This item does nothing" />, - <MenuItem - key="3" - label="Disabled Item" - href="https://github.com/sapcc/juno" - disabled - />, - <MenuItem key="4"> - <Button - key={0} - label="Button as Child of MenuItem" - variant="subdued" - size="small" - className="jn-w-full" - /> - </MenuItem>, - ], - }, -} diff --git a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.test.js b/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.test.js deleted file mode 100644 index 9748c2719..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContextMenu/ContextMenu.test.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { ContextMenu } from "./index.js" - -describe("ContextMenu", () => { - test("renders a ContextMenu Toggle", async () => { - render(<ContextMenu />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveClass("juno-contextmenu-toggle") - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("title", "More") - }) - - test("toggles Context Menu on click", async () => { - render(<ContextMenu />) - expect(screen.queryByRole("menu")).not.toBeInTheDocument() - await userEvent.click(screen.getByRole("button")) - expect(screen.getByRole("menu")).toBeInTheDocument() - await userEvent.click(screen.getByRole("button")) - expect(screen.queryByRole("menu")).not.toBeInTheDocument() - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/ContextMenu/index.js b/libs_deprecated/juno-ui-components/src/components/ContextMenu/index.js deleted file mode 100644 index 61bc91401..000000000 --- a/libs_deprecated/juno-ui-components/src/components/ContextMenu/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ContextMenu } from "./ContextMenu.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.component.js b/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.component.js deleted file mode 100644 index d3f5f8936..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.component.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" - -const dataGridStyles = ` - jn-grid - jn-items-stretch -` - -const gridTemplate = (columns, columnMaxSize, columnMinSize, minContentColumns, gridColumnTemplate) => { - let styles - - // gridColumnTemplate was passed. Return it and ignore all other settings - if (gridColumnTemplate && gridColumnTemplate.length > 0) { - styles = { gridTemplateColumns: gridColumnTemplate } - return styles - } - - let generatedTemplate = "" - // if a configuration for min-content columns has been passed iteratively generate the gridTemplateColumn sizes, - // else generate a simpler statement using the repeat function - if ( minContentColumns && Array.isArray(minContentColumns) && minContentColumns.length > 0 ) { - // for each configured column check if it should have normal or min-content sizing and add the respective string to the template string - [...Array(columns)].map((_, i) => { - generatedTemplate += minContentColumns.includes(i) ? 'min-content ' : `minmax(${columnMinSize}, ${columnMaxSize}) ` - }) - } else { - generatedTemplate = `repeat(${columns}, minmax(${columnMinSize}, ${columnMaxSize}))` - } - - styles = { gridTemplateColumns: generatedTemplate } - return styles -} - -const DataGridContext = React.createContext() - -export const useDataGridContext = () => React.useContext(DataGridContext) - -// TODO: allow for passing in props addItems, addItemsLabel, search, etc.: -/** The DataGrid component is the main way to display lists of items that have a bunch of metadata that you want to display. - */ -export const DataGrid = ({ - columns, - columnMaxSize, - columnMinSize, - minContentColumns, - gridColumnTemplate, - cellVerticalAlignment, - className, - children, - ...props -}) => { - const dataGridConf = { - cellVerticalAlignment: cellVerticalAlignment - // selectable: selectable - } - return ( - <DataGridContext.Provider value={dataGridConf}> - <div - className={`juno-datagrid ${dataGridStyles} ${className}`} - style={gridTemplate(columns, columnMaxSize, columnMinSize, minContentColumns, gridColumnTemplate)} - role="grid" - {...props} > - {children} - </div> - </DataGridContext.Provider> - ) -} - -DataGrid.propTypes = { - /** Set number of columns */ - columns: PropTypes.number, - /** Set column max sizing. Default: auto. For equally sized columns use "1fr" */ - columnMaxSize: PropTypes.string, - /** Set column minimum size. Default: 0px */ - columnMinSize: PropTypes.string, - /** Specify which columns should be sized by minimum content size (i.e. as small as possible). Pass an array of column numbers (first column is 0) */ - minContentColumns: PropTypes.arrayOf(PropTypes.number), - /** Set the grid column template in CSS grid 'grid-template-columns' notation. If this prop is passed, all other template props (columns, columnMaxSize, - * columnMinSize, minContentColumns) are ignored. The easiest case where you might need this is e.g. if you want to set specific column widths for some - * or all columns, e.g. "20% auto auto 10%" (The first column is set to 20%, the next two to auto size, the last to 10%). */ - gridColumnTemplate: PropTypes.string, - /** Set the vertical alignment for all GridCells. Default: center. PLEASE NOTE: the center alignment is achieved by using a flexbox column layout, - * which means that all child elements of the cell will be stacked vertically. To avoid this, wrap the elements in their own div */ - cellVerticalAlignment: PropTypes.oneOf(["center", "top"]), - /** Children to render in the DataGrid */ - children: PropTypes.node, - /** Add a class name */ - className: PropTypes.string, -} - -DataGrid.defaultProps = { - columns: 1, - columnMaxSize: "auto", - columnMinSize: "0px", - minContentColumns: undefined, - gridColumnTemplate: undefined, - cellVerticalAlignment: "center", - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.stories.js deleted file mode 100644 index 17d7dd1e2..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.stories.js +++ /dev/null @@ -1,242 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGrid } from './index.js'; -import { DataGridRow } from '../DataGridRow/index.js'; -import { DataGridCell } from '../DataGridCell/index.js'; -// import { DataGridCheckboxCell } from "../DataGridCheckboxCell/index.js" -import { DataGridHeadCell } from '../DataGridHeadCell/index.js'; -import { ContentArea } from '../ContentArea/index.js'; -import { Container } from '../Container/index.js'; -import { PreseletedWithSearch as FiltersStory } from '../Filters/Filters.stories'; -import { Filters } from '../Filters/index.js'; -import { DataGridToolbar } from '../DataGridToolbar/index.js'; -import { Default as DataGridToolbarStory } from '../DataGridToolbar/DataGridToolbar.stories'; -import { Button } from '../Button/index.js'; - -export default { - title: 'Components/DataGrid/DataGrid', - component: DataGrid, - argTypes: { - children: { - control: false, - }, - }, -}; - -const defaultColumns = 3; - -const Template = ({ hideHead, includeColSpanRow, withToolbar, withFilters, ...args }) => ( - <> - {withFilters && <Filters {...FiltersStory.args}></Filters>} - {withToolbar && ( - <DataGridToolbar {...DataGridToolbarStory.args}> - <Button variant="primary">Add new</Button> - </DataGridToolbar> - )} - <DataGrid {...args}> - {!hideHead && ( - <DataGridRow> - {[...Array(args.columns || defaultColumns)].map((_, c) => ( - <DataGridHeadCell key={`h_${c}`}>{`Head cell ${c}`}</DataGridHeadCell> - ))} - </DataGridRow> - )} - {!includeColSpanRow && - [...Array(4)].map((_, r) => ( - <DataGridRow key={`b_${r}`}> - {[...Array(args.columns || defaultColumns)].map((_, c) => ( - <DataGridCell key={`b_${r}_${c}`}> - {c === args.columns - 2 - ? `Cell ${r}-${c} has more content than others` - : `Cell ${r}-${c}`} - </DataGridCell> - ))} - </DataGridRow> - ))} - {includeColSpanRow && ( - <DataGridRow> - <DataGridCell colSpan={args.columns}> - This is a cell with colspan spanning all available columns - </DataGridCell> - </DataGridRow> - )} - </DataGrid> - </> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGrid for displaying data. Example with 5 columns.', - }, - }, - }, - - args: { - columns: 5, - }, -}; - -export const EqualColumnSize = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Example: change column max size to '1fr'. This ensures that all columns get the same width, even if some columns have more content than others", - }, - }, - }, - - args: { - columns: 5, - columnMaxSize: '1fr', - }, -}; - -export const ColumnMinSize = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Example: set a minimum width for columns. Columns will always be at least this wide, even if they have very little content. This may cause horizontal scrollbars if the DataGrid doesn't fit into the container anymore", - }, - }, - }, - - args: { - columns: 5, - columnMinSize: '300px', - }, -}; - -export const MinimumSizedColumns = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'Example: specify some columns that should be as small as possible (typically used for when you have a cell that contains only a button and you want to ensure the cell is only exactly as wide as the button', - }, - }, - }, - - args: { - columns: 5, - minContentColumns: [0, 4], - }, -}; - -export const CustomGridTemplate = { - render: Template, - - parameters: { - docs: { - description: { - story: - "Example: specify a completely custom css grid column template. The value passed is used for the css 'grid-template-columns' property. All other settings are ignored", - }, - }, - }, - - args: { - gridColumnTemplate: `20% repeat(${defaultColumns - 1}, auto)`, - }, -}; - -export const NoHead = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Without head cells', - }, - }, - }, - - args: { - columns: 5, - hideHead: true, - }, -}; - -export const ColSpanCell = { - render: Template, - - parameters: { - docs: { - description: { - story: 'With a col span cell', - }, - }, - }, - - args: { - columns: 5, - includeColSpanRow: true, - }, -}; - -export const WithToolbar = { - render: Template, - - parameters: { - docs: { - description: { - story: 'With toolbar', - }, - }, - }, - - args: { - columns: 5, - withToolbar: true, - }, -}; - -export const WithFilters = { - render: Template, - - parameters: { - docs: { - description: { - story: 'With filters', - }, - }, - }, - - args: { - columns: 5, - withFilters: true, - }, -}; - -export const WithToolbarAndFilters = { - render: Template, - - parameters: { - docs: { - description: { - story: 'With toolbar and filters', - }, - }, - }, - - args: { - columns: 5, - withFilters: true, - withToolbar: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.test.js b/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.test.js deleted file mode 100644 index acb42f929..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGrid/DataGrid.test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGrid } from "./index" - -describe("DataGrid", () => { - - test("renders a DataGrid", async () => { - render(<DataGrid />) - expect(screen.getByRole("grid")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGrid className="my-custom-class"/>) - expect(screen.getByRole("grid")).toBeInTheDocument() - expect(screen.getByRole("grid")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGrid/index.js b/libs_deprecated/juno-ui-components/src/components/DataGrid/index.js deleted file mode 100644 index f4cdec996..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGrid/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGrid } from "./DataGrid.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.component.js deleted file mode 100644 index 8152cd3a7..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.component.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { forwardRef } from "react" -import PropTypes from "prop-types" - -import { useDataGridContext } from "../DataGrid/DataGrid.component.js" - -const cellBaseStyles = (nowrap, cellVerticalAlignment) => { - return ` - ${nowrap ? "jn-whitespace-nowrap" : ""} - ${ - cellVerticalAlignment === "center" - ? ` - jn-justify-center - jn-flex - jn-flex-col - ` - : "" - } - jn-px-5 - jn-py-3 - jn-border-b - jn-border-theme-background-lvl-2 - jn-h-full - ` -} - -const cellCustomStyles = (colSpan) => { - let styles - if (colSpan) { - styles = { gridColumn: `span ${colSpan} / span ${colSpan}` } - } - return styles -} - -export const DataGridCell = forwardRef( - ({ colSpan, nowrap, className, children, ...props }, ref) => { - const dataGridContext = useDataGridContext() || {} - const cellVerticalAlignment = dataGridContext.cellVerticalAlignment - - return ( - <div - className={`juno-datagrid-cell ${cellBaseStyles( - nowrap, - cellVerticalAlignment - )} ${className}`} - style={cellCustomStyles(colSpan)} - role="gridcell" - ref={ref} - {...props} - > - {children} - </div> - ) - } -) - -DataGridCell.propTypes = { - /** Add a col span to the cell. This works like a colspan in a normal html table, so you have to take care not to place too many cells in a row if some of them have a colspan. */ - colSpan: PropTypes.number, - /** Set nowrap to true if the cell content shouldn't wrap (this is achieved by adding white-space: nowrap;) */ - nowrap: PropTypes.bool, - /** Children to render in the DataGridCell */ - children: PropTypes.node, - /** Add a classname */ - className: PropTypes.string, -} - -DataGridCell.defaultProps = { - colSpan: undefined, - nowrap: false, - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.stories.js deleted file mode 100644 index a7702edbe..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.stories.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGrid } from '../DataGrid/index.js'; -import { DataGridRow } from '../DataGridRow/index.js'; -import { DataGridCell } from './index.js'; - -export default { - title: 'Components/DataGrid/DataGridCell', - component: DataGridCell, - argTypes: { - children: { - control: false, - }, - }, - decorators: [ - (story) => ( - <DataGrid columns={3}> - <DataGridRow>{story()}</DataGridRow> - </DataGrid> - ), - ], - parameters: { - docs: { - source: { - excludeDecorators: false, - }, - }, - }, -}; - -const Template = (args) => <DataGridCell {...args}></DataGridCell>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridCell for use in DataGrid', - }, - }, - }, - - args: { - children: ['DataGridCell'], - }, -}; - -export const NoWrap = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridCell with nowrap option (content has white-space: nowrap;)', - }, - }, - }, - - args: { - nowrap: true, - children: ['DataGridCell does not wrap'], - }, -}; - -export const ColSpan = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridCell with colspan', - }, - }, - }, - - args: { - colSpan: 3, - children: ['DataGridCell with colspan'], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.test.js deleted file mode 100644 index 026a62b3e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCell/DataGridCell.test.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridCell } from "./index" - -describe("DataGridCell", () => { - - test("renders a DataGridCell", async () => { - render(<DataGridCell />) - expect(screen.getByRole("gridcell")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGridCell className="my-custom-class"/>) - expect(screen.getByRole("gridcell")).toBeInTheDocument() - expect(screen.getByRole("gridcell")).toHaveClass("my-custom-class") - }) - - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCell/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridCell/index.js deleted file mode 100644 index 5ffb934c2..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridCell } from "./DataGridCell.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.component.js deleted file mode 100644 index 099e8c1fa..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.component.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { Checkbox } from "../Checkbox/Checkbox.component.js" -import { DataGridCell } from "../DataGridCell/DataGridCell.component.js" - -export const DataGridCheckboxCell = ({ - selected, - disabled, - className, - onChange, - ...props -}) => { - return ( - <DataGridCell className={`juno-datagrid-checkbox-cell ${className}`} {...props}> - <Checkbox disabled={disabled} checked={selected} onChange={onChange} /> - </DataGridCell> - ) -} - -DataGridCheckboxCell.propTypes = { - /** Whether the row this cell belongs to is selected */ - selected: PropTypes.bool, - /** Whether the item is disabled */ - disabled: PropTypes.bool, - /** Add a classname to the cell */ - className: PropTypes.string, - /** Handler to change the selected state of the row */ - onChange: PropTypes.func, -} - -DataGridCheckboxCell.defaultProps = { - selected: false, - disabled: false, - className: "", - onChange: undefined, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.stories.js deleted file mode 100644 index aadeab1db..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.stories.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGrid } from '../DataGrid/index.js'; -import { DataGridRow } from '../DataGridRow/index.js'; -import { DataGridCheckboxCell } from './index.js'; - -export default { - title: 'WiP/DataGrid/DataGridCheckboxCell', - component: DataGridCheckboxCell, - argTypes: { - children: { - control: false, - }, - }, - decorators: [ - (story) => ( - <DataGrid columns={3}> - <DataGridRow>{story()}</DataGridRow> - </DataGrid> - ), - ], - parameters: { - docs: { - source: { - excludeDecorators: false, - }, - }, - }, -}; - -const Template = (args) => <DataGridCheckboxCell {...args}></DataGridCheckboxCell>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridCheckboxCell for use in DataGrid', - }, - }, - }, - - args: {}, -}; - -export const Disabled = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Disabled Juno DataGridCheckboxCell for use in DataGrid', - }, - }, - }, - - args: { - disabled: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.test.js deleted file mode 100644 index 88b33bc60..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/DataGridCheckboxCell.test.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridCheckboxCell } from "./index" - -describe("DataGridCheckboxCell", () => { - - // test("renders a DataGridCheckboxCell containing a checkbox", async () => { - // const tablerow = document.createElement('tr') - // const {container} = render(<DataGridCheckboxCell data-testid="my-datagridcell" />, - // { container: document.body.appendChild(tablerow)}) - // expect(screen.getByTestId("my-datagridcell")).toBeInTheDocument() - // expect(screen.getByRole('checkbox')).toBeInTheDocument() - // }) - - // test("renders a DataGridCheckboxCell containing a checked checkbox if passed", async () => { - // const tablerow = document.createElement('tr') - // const {container} = render(<DataGridCheckboxCell data-testid="my-datagridcell" selected />, - // { container: document.body.appendChild(tablerow)}) - // expect(screen.getByRole('checkbox')).toBeInTheDocument() - // expect(screen.getByRole('checkbox')).toBeChecked() - // }) - - test("renders a DataGridCheckboxCell", async () => { - render(<DataGridCheckboxCell />) - expect(screen.getByRole("gridcell")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGridCheckboxCell className="my-custom-class"/>) - expect(screen.getByRole("gridcell")).toBeInTheDocument() - expect(screen.getByRole("gridcell")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/index.js deleted file mode 100644 index b1339882a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridCheckboxCell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridCheckboxCell } from "./DataGridCheckboxCell.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.component.js deleted file mode 100644 index c48f1e3f6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.component.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -export const DataGridFoot = ({ - className, - children, - ...props -}) => { - return ( - <tfoot className={`juno-datagrid-foot ${className}`} {...props}> - {children} - </tfoot> - ) -} - -DataGridFoot.propTypes = { - /** Children to render in the DataGridFoot */ - children: PropTypes.node, - /** Add a classname */ - className: PropTypes.string, -} - -DataGridFoot.defaultProps = { - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.stories.js deleted file mode 100644 index 3f736a59a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.stories.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGridFoot } from './index.js'; -import { DataGridCell } from '../DataGridCell/index.js'; -import { Default as DataGridCellStory } from '../DataGridCell/DataGridCell.stories.js'; - -export default { - title: 'WiP/DataGrid/DataGridFoot', - component: DataGridFoot, - argTypes: { - children: { - control: false, - }, - }, - decorators: [(story) => <table>{story()}</table>], - parameters: { - docs: { - source: { - excludeDecorators: false, - }, - }, - }, -}; - -const Template = ({ items, ...args }) => ( - <DataGridFoot {...args}> - {/* {items.map((item, i) => ( - <DataGridFootRow key={`f_${i}`}> - {item.items.map((cell, c) => ( - <DataGridCell {...cell} key={`f_${i}_${c}`} /> - ))} - </DataGridFootRow> - ))} */} - </DataGridFoot> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridFoot for use in DataGrid', - }, - }, - }, - - args: {}, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.test.js deleted file mode 100644 index 7b706b27f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/DataGridFoot.test.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridFoot } from "./index" - -describe("DataGridFoot", () => { - - test("renders a DataGridFoot", async () => { - const table = document.createElement('table') - const {container} = render(<DataGridFoot data-testid="my-datagridfoot"/>, - { container: document.body.appendChild(table)}) - expect(screen.getByTestId("my-datagridfoot")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - const table = document.createElement('table') - const {container} = render(<DataGridFoot data-testid="my-datagridfoot" className="my-custom-class"/>, - { container: document.body.appendChild(table)}) - expect(screen.getByTestId("my-datagridfoot")).toBeInTheDocument() - expect(screen.getByTestId("my-datagridfoot")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridFoot/index.js deleted file mode 100644 index afad71a5f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridFoot/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridFoot } from "./DataGridFoot.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.component.js deleted file mode 100644 index dcc6ea3ca..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.component.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { forwardRef } from "react" -import PropTypes from "prop-types" -import { DataGridCell } from "../DataGridCell/index.js" - -const headCellBaseStyles = ` - jn-font-bold - jn-text-theme-high - jn-bg-theme-background-lvl-1 - jn-border-theme-background-lvl-0 -` - -const sortIconStyles = ` - jn-ml-2 -` - -export const DataGridHeadCell = forwardRef( - ( - { - // sortable, - colSpan, - nowrap, - className, - children, - ...props - }, - ref - ) => { - return ( - <DataGridCell - colSpan={colSpan} - nowrap={nowrap} - className={`juno-datagrid-head-cell ${headCellBaseStyles} ${className}`} - role="columnheader" - ref={ref} - {...props} - > - {children} - </DataGridCell> - // <div - // className={`juno-datagrid-head-cell ${headCellBaseStyles} ${className}`} - // role="columnheader" - // {...props}> - // {children} - // {/* { sortable ? <Icon size={'1rem'} className={`${sortIconStyles}`}/> : ''} */} - // </div> - ) - } -) - -DataGridHeadCell.propTypes = { - /** Whether the DataGrid should be sortable by this column */ - // sortable: PropTypes.bool, - /** Add a col span to the cell. This works like a colspan in a normal html table, so you have to take care not to place too many cells in a row if some of them have a colspan. */ - colSpan: PropTypes.number, - /** Set nowrap to true if the cell content shouldn't wrap (this is achieved by adding white-space: nowrap;) */ - nowrap: PropTypes.bool, - /** Children to render in the DataGridHeadCell */ - children: PropTypes.node, - /** Add a classname */ - className: PropTypes.string, -} - -DataGridHeadCell.defaultProps = { - // sortable: false, - colSpan: undefined, - nowrap: false, - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.stories.js deleted file mode 100644 index 1ccc0ca81..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.stories.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGrid } from '../DataGrid/index.js'; -import { DataGridRow } from '../DataGridRow/index.js'; -import { DataGridHeadCell } from './index.js'; - -export default { - title: 'Components/DataGrid/DataGridHeadCell', - component: DataGridHeadCell, - argTypes: { - children: { - control: false, - }, - }, - decorators: [ - (story) => ( - <DataGrid columns={3}> - <DataGridRow>{story()}</DataGridRow> - </DataGrid> - ), - ], - parameters: { - docs: { - source: { - excludeDecorators: false, - }, - }, - }, -}; - -const Template = (args) => <DataGridHeadCell {...args}></DataGridHeadCell>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridHeadCell for use in DataGrid', - }, - }, - }, - - args: { - children: ['DataGridHeadCell'], - }, -}; - -export const NoWrap = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridHeadCell with nowrap option (content has white-space: nowrap;)', - }, - }, - }, - - args: { - nowrap: true, - children: ['DataGridHeadCell does not wrap'], - }, -}; - -export const ColSpan = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridHeadCell with colspan', - }, - }, - }, - - args: { - colSpan: 3, - children: ['DataGridHeadCell with colspan'], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.test.js deleted file mode 100644 index fb641d661..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/DataGridHeadCell.test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridHeadCell } from "./index" - -describe("DataGridHeadCell", () => { - - test("renders a DataGridHeadCell", async () => { - render(<DataGridHeadCell />) - expect(screen.getByRole("columnheader")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGridHeadCell className="my-custom-class"/>) - expect(screen.getByRole("columnheader")).toBeInTheDocument() - expect(screen.getByRole("columnheader")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/index.js deleted file mode 100644 index 9bea4b235..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridHeadCell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridHeadCell } from "./DataGridHeadCell.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.component.js deleted file mode 100644 index 4950314c4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.component.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { forwardRef } from "react" -import PropTypes from "prop-types" - -const rowBaseStyle = ` - jn-contents -` -// const rowSelectedStyle = ` -// jn-bg-theme-datagridrow-selected -// ` - -export const DataGridRow = forwardRef( - ({ selected, disabled, className, children, onChange, ...props }, ref) => { - // const dataGridContext = useDataGridContext() || {} - // const selectable = dataGridContext.selectable - - // const [isSelected, setIsSelected] = useState(false) - // useEffect( () => { - // setIsSelected(selected) - // }, [selected]) - - // const toggleSelected = (event) => { - // setIsSelected(!isSelected) - // onChange(event) - // } - - // ${ selectable && isSelected ? rowSelectedStyle : '' } - return ( - <div - className={`juno-datagrid-row ${rowBaseStyle} ${className}`} - role="row" - ref={ref} - {...props} - > - {/* { selectable ? <DataGridCheckboxCell selected={selected} disabled={disabled} onChange={toggleSelected} /> : null } */} - {children} - </div> - ) - } -) - -DataGridRow.propTypes = { - // /** Whether the row / item is selected (only relevant in a `selectable` DataGrid */ - // selected: PropTypes.bool, - // /** Whether the row/item is disabled (only relevant in a `selectable` DataGrid */ - // disabled: PropTypes.bool, - /** Children to render in the DataGridRow */ - children: PropTypes.node, - /** Add a classname */ - className: PropTypes.string, - // /** Pass a handler to be executed when selected state changes */ - // onChange: PropTypes.func, -} - -DataGridRow.defaultProps = { - // selected: false, - // disabled: false, - className: "", - children: null, - // onChange: undefined, -} diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.stories.js deleted file mode 100644 index a2084677d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.stories.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataGridRow } from './index.js'; -import { DataGridCell } from '../DataGridCell/index.js'; -import { Default as DataGridCellStory } from '../DataGridCell/DataGridCell.stories.js'; -import { DataGrid } from '../DataGrid/index.js'; - -const columns = 5; - -export default { - title: 'Components/DataGrid/DataGridRow', - component: DataGridRow, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, - decorators: [(story) => <DataGrid columns={columns}>{story()}</DataGrid>], - parameters: { - docs: { - source: { - excludeDecorators: false, - }, - }, - }, -}; - -const Template = ({ items, ...args }) => ( - <DataGridRow {...args}> - {items.map((item, i) => ( - <DataGridCell {...item} key={`${i}`} /> - ))} - </DataGridRow> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataGridRow for use in DataGrid', - }, - }, - }, - - args: { - items: Array(columns).fill({ ...DataGridCellStory.args }), - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.test.js deleted file mode 100644 index 719f93755..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridRow/DataGridRow.test.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridRow } from "./index" - -describe("DataGridRow", () => { - - test("renders a DataGridRow", async () => { - render(<DataGridRow />) - expect(screen.getByRole("row")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGridRow className="my-custom-class"/>) - expect(screen.getByRole("row")).toBeInTheDocument() - expect(screen.getByRole("row")).toHaveClass("my-custom-class") - }) - - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridRow/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridRow/index.js deleted file mode 100644 index 59cccabe6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridRow } from "./DataGridRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.component.js b/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.component.js deleted file mode 100644 index b7ce287e7..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.component.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const datagridtoolbarstyles = ` - jn-flex - jn-items-center - jn-bg-theme-background-lvl-1 - jn-py-3 - jn-px-6 - jn-mb-px -` - -const childrenWrapperStyles = ` - jn-ml-auto -` - -/** This is the toolbar for use with a DataGrid. This is the place where you would put buttons and other controls that affect the items in the DataGrid (e.g. triggering batch actions). Optionally a search input can be added. */ -export const DataGridToolbar= ({ - search, - className, - children, - ...props -}) => { - return ( - <div className={`juno-datagrid-toolbar ${datagridtoolbarstyles} ${className}`} {...props} > - { search && - <div> - {search} - </div> - } - <div className={childrenWrapperStyles}> - {children} - </div> - </div> - ) -} - -DataGridToolbar.propTypes = { - /** Pass an optional SearchInput component */ - search: PropTypes.node, - /** Children to render in the DataGridToolbar */ - children: PropTypes.node, - /** Add a classname */ - className: PropTypes.string, -} - -DataGridToolbar.defaultProps = { - search: undefined, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.stories.js b/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.stories.js deleted file mode 100644 index 1153a26c6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.stories.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Button } from '../Button/index.js'; -import { ButtonRow } from '../ButtonRow/index.js'; -import { DataGridToolbar } from './index.js'; -import { SearchInput } from '../SearchInput/SearchInput.component'; - -export default { - title: 'Components/DataGrid/DataGridToolbar', - component: DataGridToolbar, - argTypes: { - children: { - control: false, - }, - search: { - control: false, - }, - }, -}; - -const Template = (args) => ( - <DataGridToolbar {...args}> - <ButtonRow> - <Button variant="subdued">Add other</Button> - <Button>Add new</Button> - </ButtonRow> - </DataGridToolbar> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Optional toolbar for use in DataGrid. Use ButtonRow for multiple buttons', - }, - }, - }, - - args: {}, -}; - -export const WithSearch = { - render: Template, - - parameters: { - docs: { - description: { - story: 'DataGridToolbar with optional search input', - }, - }, - }, - - args: { - search: ( - <SearchInput - onSearch={() => { - console.log('Searching…'); - }} - /> - ), - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.test.js b/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.test.js deleted file mode 100644 index 36a473d8f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/DataGridToolbar.test.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataGridToolbar } from "./index" -import { SearchInput } from "../SearchInput/index" - -describe("DataGridToolbar", () => { - - test("renders a DataGridToolbar", async () => { - render(<DataGridToolbar data-testid="my-datagridtoolbar" />) - expect(screen.getByTestId("my-datagridtoolbar")).toBeInTheDocument() - }) - - test("renders a SearchInput as passed", async () => { - render(<DataGridToolbar search={<SearchInput/>}></DataGridToolbar>) - expect(screen.getByRole("searchbox")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataGridToolbar data-testid="my-datagridtoolbar" className="my-custom-class" />) - expect(screen.getByTestId("my-datagridtoolbar")).toBeInTheDocument() - expect(screen.getByTestId("my-datagridtoolbar")).toHaveClass("my-custom-class") - }) - - test("renders all props as passed", async () => { - render(<DataGridToolbar data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/index.js b/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/index.js deleted file mode 100644 index 6ac06c21b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataGridToolbar/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataGridToolbar } from "./DataGridToolbar.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.component.js b/libs_deprecated/juno-ui-components/src/components/DataList/DataList.component.js deleted file mode 100644 index 246d974ad..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.component.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const DataListContext = React.createContext() - -export const useDataListContext = () => React.useContext(DataListContext) - -export const DataList = ({ - selectable, - className, - children, - ...props -}) => { - const dataListConf = { - selectable: selectable - } - return ( - <DataListContext.Provider value={dataListConf}> - <div className={`juno-datalist-container`}> - <ul className={`juno-datalist ${className}`} {...props} > - {children} - </ul> - </div> - </DataListContext.Provider> - ) -} - -DataList.propTypes = { - /** Whether the items of a DataList should be selectable */ - selectable: PropTypes.bool, - /** Custom classname */ - className: PropTypes.string, - /** Children to render in the DataList */ - children: PropTypes.node, -} - -DataList.defaultProps = { - selectable: false, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.stories.js b/libs_deprecated/juno-ui-components/src/components/DataList/DataList.stories.js deleted file mode 100644 index 3f30c8447..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.stories.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataList } from './index.js'; -import { DataListRow } from '../DataListRow/index.js'; -import { DataListCell } from '../DataListCell/index.js'; -import { Default as DataListRowStory } from '../DataListRow/DataListRow.stories.js'; -import { Default as DataListCellStory } from '../DataListCell/DataListCell.stories.js'; -import { Selectable as SelectableDataListRowStory } from '../DataListRow/DataListRow.stories.js'; -import { AutoWidth as AutoWidthDataListRowStory } from '../DataListRow/DataListRow.stories.js'; -import { PercentageWidths as PercentageWidthsDataListRowStory } from '../DataListRow/DataListRow.stories.js'; -import { GridFitted as GridFittedDataListRowStory } from '../DataListRow/DataListRow.stories.js'; - -export default { - title: 'Deprecated/DataList/DataList', - component: DataList, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, - parameters: { - docs: { - description: { - component: 'DataList is deprecated and will be removed. Please use DataGrid instead.', - }, - }, - }, -}; - -const Template = ({ items, ...args }) => ( - <DataList {...args}> - {items.map((item, i) => ( - <DataListRow key={`${i}`}> - {item.items.map((cell, c) => ( - <DataListCell {...cell} key={`${i}_${c}`} /> - ))} - </DataListRow> - ))} - </DataList> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Default Juno DataList for displaying data', - }, - }, - }, - - args: { - items: [ - { ...DataListRowStory.args }, - { ...DataListRowStory.args }, - { ...DataListRowStory.args }, - { ...DataListRowStory.args }, - { ...DataListRowStory.args }, - ], - }, -}; - -export const Selectable = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Selectable Juno DataList for displaying and selecting data', - }, - }, - }, - - args: { - selectable: true, - items: [ - { ...SelectableDataListRowStory.args }, - { ...SelectableDataListRowStory.args }, - { ...SelectableDataListRowStory.args }, - { ...SelectableDataListRowStory.args }, - { ...SelectableDataListRowStory.args }, - ], - }, -}; - -export const Auto = { - render: Template, - - parameters: { - docs: { - description: { - story: "Juno DataList with one column set to 'auto' to maximize its width", - }, - }, - }, - - args: { - items: [ - { ...AutoWidthDataListRowStory.args }, - { ...AutoWidthDataListRowStory.args }, - { ...AutoWidthDataListRowStory.args }, - { ...AutoWidthDataListRowStory.args }, - { ...AutoWidthDataListRowStory.args }, - ], - }, -}; - -export const Percentage = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataList with percentage-based column widths', - }, - }, - }, - - args: { - items: [ - { ...PercentageWidthsDataListRowStory.args }, - { ...PercentageWidthsDataListRowStory.args }, - { ...PercentageWidthsDataListRowStory.args }, - { ...PercentageWidthsDataListRowStory.args }, - { ...PercentageWidthsDataListRowStory.args }, - ], - }, -}; - -export const GridFitted = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataList with grid column-based column widths', - }, - }, - }, - - args: { - items: [ - { ...GridFittedDataListRowStory.args }, - { ...GridFittedDataListRowStory.args }, - { ...GridFittedDataListRowStory.args }, - { ...GridFittedDataListRowStory.args }, - { ...GridFittedDataListRowStory.args }, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.test.js b/libs_deprecated/juno-ui-components/src/components/DataList/DataList.test.js deleted file mode 100644 index ca69f7727..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataList/DataList.test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataList } from "./index" - -describe("DataList", () => { - - test("renders a DataList", async () => { - render(<DataList data-testid="my-datalist" />) - expect(screen.getByTestId("my-datalist")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataList data-testid="my-datalist" className="my-custom-class" />) - expect(screen.getByTestId("my-datalist")).toBeInTheDocument() - expect(screen.getByTestId("my-datalist")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataList/index.js b/libs_deprecated/juno-ui-components/src/components/DataList/index.js deleted file mode 100644 index 0d373d23d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataList/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataList } from "./DataList.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.component.js b/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.component.js deleted file mode 100644 index 316743589..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.component.js +++ /dev/null @@ -1,151 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const datalistcellbasestyles = ` - jn-flex - jn-p-2 - jn-overflow-hidden - jn-overflow-ellipsis - jn-grow-0 - jn-shrink-0 - jn-flex-basis-auto -` - -const datalistcellautostyles = ` - jn-grow - jn-shrink-0 - jn-flex-basis-0 -` - -const datalistcellgridstyles = ` - jn-p-grid-column -` - -const cols_1 = ` - jn-w-grid-col-1 -` - -const cols_2 = ` - jn-w-grid-col-2 -` - -const cols_3 = ` - jn-w-grid-col-3 -` - -const cols_4 = ` - jn-w-grid-col-4 -` - -const cols_5 = ` - jn-w-grid-col-6 -` - -const cols_6 = ` - jn-w-grid-col-6 -` - -const cols_7 = ` - jn-w-grid-col-7 -` - -const cols_8 = ` - jn-w-grid-col-8 -` - -const cols_9 = ` - jn-w-grid-col-9 -` - -const cols_10 = ` - jn-w-grid-col-10 -` - -const cols_11 = ` - jn-w-grid-col-11 -` - -const cols_12 = ` - jn-w-grid-col-12 -` - -const colsClass = (cols) => { -switch (cols) { - case 1: - return cols_1 - case 2: - return cols_2 - case 3: - return cols_3 - case 4: - return cols_4 - case 5: - return cols_5 - case 6: - return cols_6 - case 7: - return cols_7 - case 8: - return cols_8 - case 9: - return cols_9 - case 10: - return cols_10 - case 11: - return cols_11 - case 12: - return cols_12 - default: null -} -} - -export const DataListCell = ({ - cols, - width, - auto, - className, - children, - ...props -}) => { - // auto cell: - const autoStyles = { - flexGrow: "1", - flexShrink: "0", - flexBasis: "0" - } - // width cell: - const widthStyles = width ? { width: width + '%', flexGrow: "0", flexShrink: "0", flexBasis: width + '%' } : {} - // width overrides auto: - const cellStyles = width ? widthStyles : ( auto ? autoStyles : {} ) - return ( - <div className={`juno-datalist-cell ${datalistcellbasestyles} ${cols ? colsClass(cols) : '' } ${className}`} style={cellStyles} {...props} > - {children} - </div> - ) -} - -DataListCell.propTypes = { - /** The number of columns to span the column over when fitting to the grid. */ - cols: PropTypes.number, - /** The width in percent as a number without "%" for auto-layout grids TODO: or "auto". If a width is given, it will override the "cols" prop. */ - width: PropTypes.number, - /** Whether the colum should set an auto width */ - auto: PropTypes.bool, - /** Custom classname */ - className: PropTypes.string, - /** Children to render in the DataListCell */ - children: PropTypes.node, -} - -DataListCell.defaultProps = { - cols: null, - width: null, - auto: false, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.stories.js b/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.stories.js deleted file mode 100644 index c7d3b9e48..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.stories.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataListCell } from './index.js'; - -export default { - title: 'Deprecated/DataList/DataListCell', - component: DataListCell, - argTypes: { - children: { - control: false, - }, - }, - parameters: { - docs: { - description: { - component: 'DataList is deprecated and will be removed. Please use DataGrid instead.', - }, - }, - }, -}; - -const Template = (args) => <DataListCell {...args}></DataListCell>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataListCell for displaying data', - }, - }, - }, - - args: { - children: ['DataListCell'], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.test.js b/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.test.js deleted file mode 100644 index 6c96b3f2c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCell/DataListCell.test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataListCell } from "./index" - -describe("DataListCell", () => { - - test("renders a DataListCell", async () => { - render(<DataListCell data-testid="my-datalistcell" />) - expect(screen.getByTestId("my-datalistcell")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataListCell data-testid="my-datalistcell" className="my-custom-class" />) - expect(screen.getByTestId("my-datalistcell")).toBeInTheDocument() - expect(screen.getByTestId("my-datalistcell")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCell/index.js b/libs_deprecated/juno-ui-components/src/components/DataListCell/index.js deleted file mode 100644 index 6e7a95108..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataListCell } from "./DataListCell.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.component.js b/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.component.js deleted file mode 100644 index 8a3638862..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.component.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { Checkbox } from "../Checkbox/Checkbox.component.js" -import { DataListCell } from "../DataListCell/DataListCell.component.js" - -const datalistcheckboxcellbasestyles = ` - jn-flex - jn-flex-col - jn-justify-center -` - -export const DataListCheckboxCell = ({ - selected, - disabled, - onChange, - className, - children, - ...props -}) => { - return ( - <DataListCell className={`juno-datalist-checkbox-cell ${datalistcheckboxcellbasestyles} ${className}`} {...props} > - <Checkbox disabled={disabled} checked={selected} onChange={onChange} /> - </DataListCell> - ) -} - -DataListCheckboxCell.propTypes = { - /** Whether the item this cell belongs to is selected */ - selected: PropTypes.bool, - /** Whether the item is disabled */ - disabled: PropTypes.bool, - /** Custom classname */ - className: PropTypes.string, - /** Children to render in the DataListCell */ - children: PropTypes.node, - /** Handler to execute when selected state changes */ - onChange: PropTypes.func, -} - -DataListCell.defaultProps = { - selected: false, - disabled: false, - className: "", - children: null, - onChange: undefined, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.stories.js b/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.stories.js deleted file mode 100644 index 6d8f6c3f5..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.stories.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataListCheckboxCell } from './index.js'; - -export default { - title: 'Deprecated/DataList/DataListCheckboxCell', - component: DataListCheckboxCell, - argTypes: { - children: { - control: false, - }, - }, - parameters: { - docs: { - description: { - component: 'DataList is deprecated and will be removed. Please use DataGrid instead.', - }, - }, - }, -}; - -const Template = (args) => <DataListCheckboxCell {...args}></DataListCheckboxCell>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataListCheckboxCell for use in DataList', - }, - }, - }, - - args: {}, -}; - -export const Disabled = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Disabled Juno DataListCheckboxCell for use in DataList', - }, - }, - }, - - args: { - disabled: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.test.js b/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.test.js deleted file mode 100644 index acd41d292..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/DataListCheckboxCell.test.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataListCheckboxCell } from "./index" - -describe("DataListCheckboxCell", () => { - - test("renders a DataListCheckboxCell containing a checkbox", async () => { - render(<DataListCheckboxCell data-testid="my-datalistcell" />) - expect(screen.getByTestId("my-datalistcell")).toBeInTheDocument() - expect(screen.getByRole('checkbox')).toBeInTheDocument() - }) - - test("renders a DataListCheckboxCell containing a checked checkbox if passed", async () => { - render(<DataListCheckboxCell data-testid="my-datalistcell" selected />) - expect(screen.getByRole('checkbox')).toBeInTheDocument() - expect(screen.getByRole('checkbox')).toBeChecked() - }) - - test("renders a custom className", async () => { - render(<DataListCheckboxCell data-testid="my-datalistcell" className="my-custom-class"/>) - expect(screen.getByTestId("my-datalistcell")).toBeInTheDocument() - expect(screen.getByTestId("my-datalistcell")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/index.js b/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/index.js deleted file mode 100644 index 7f7c2ac34..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListCheckboxCell/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataListCheckboxCell } from "./DataListCheckboxCell.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.component.js b/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.component.js deleted file mode 100644 index 896ad5aff..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.component.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { useDataListContext } from "../DataList/DataList.component.js" -import { DataListCheckboxCell } from "../DataListCheckboxCell/DataListCheckboxCell.component.js" - -const datalistrowbasestyles = ` - jn-flex - jn-rounded-[3px] - jn-border - jn-border-theme-datalist-row - jn-mb-2 -` - -const rowselectedstyle = ` - jn-bg-theme-datalistrow-selected -` - -export const DataListRow = ({ - selected, - disabled, - onChange, - className, - children, - ...props -}) => { - const dataListContext = useDataListContext() || {} - const selectable = dataListContext.selectable - - const [isSelected, setIsSelected] = useState(false) - useEffect( () => { - setIsSelected(selected) - }, [selected]) - - const toggleSelected = (event) => { - setIsSelected(!isSelected) - onChange(event) - } - - return ( - <li className={`juno-datalist-row ${datalistrowbasestyles} ${ selectable && isSelected ? rowselectedstyle : '' }${className}`} {...props} > - { selectable ? <DataListCheckboxCell selected={selected} disabled={disabled} onChange={toggleSelected} /> : null } - {children} - </li> - ) -} - -DataListRow.propTypes = { - /** Custom classname */ - className: PropTypes.string, - /** Children to render in the DataListRow */ - children: PropTypes.node, -} - -DataListRow.defaultProps = { - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.stories.js b/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.stories.js deleted file mode 100644 index 8ba320c2e..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.stories.js +++ /dev/null @@ -1,160 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DataListRow } from './index.js'; -import { DataListCell } from '../DataListCell/index.js'; -import { DataListCheckboxCell } from '../DataListCheckboxCell/index.js'; -import { Default as DataListCellStory } from '../DataListCell/DataListCell.stories.js'; -import { Default as DataListCheckboxCellStory } from '../DataListCheckboxCell/DataListCheckboxCell.stories.js'; - -export default { - title: 'Deprecated/DataList/DataListRow', - component: DataListRow, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, - parameters: { - docs: { - description: { - component: 'DataList is deprecated and will be removed. Please use DataGrid instead.', - }, - }, - }, -}; - -const Template = ({ items, ...args }) => ( - <DataListRow {...args}> - {items.map((item, i) => ( - <DataListCell {...item} key={`${i}`} /> - ))} - </DataListRow> -); - -const SelectableTemplate = ({ items, ...args }) => ( - <DataListRow {...args}> - <DataListCheckboxCell /> - {items.map((item, i) => ( - <DataListCell {...item} key={`${i}`} /> - ))} - </DataListRow> -); - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Juno DataListRow for displaying data', - }, - }, - }, - - args: { - items: [ - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - ], - }, -}; - -export const Selectable = { - render: SelectableTemplate, - - parameters: { - docs: { - description: { - story: - 'Selectable DataListRow for displaying and selecting data. Note that highlighting the row will not work when rendered outside a DataList. ', - }, - }, - }, - - args: { - items: [ - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - ], - }, -}; - -export const AutoWidth = { - render: Template, - - parameters: { - docs: { - description: { - story: "Row with one cell set to 'auto' in oder to maximize its width", - }, - }, - }, - - args: { - items: [ - { ...DataListCellStory.args }, - { ...DataListCellStory.args, auto: true, children: 'Auto DataListCell' }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - { ...DataListCellStory.args }, - ], - }, -}; - -export const PercentageWidths = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Row with Cells set to individual percentage widths', - }, - }, - }, - - args: { - items: [ - { ...DataListCellStory.args, width: 10 }, - { ...DataListCellStory.args, width: 45 }, - { ...DataListCellStory.args, width: 25 }, - { ...DataListCellStory.args, width: 10 }, - { ...DataListCellStory.args, width: 10 }, - ], - }, -}; - -export const GridFitted = { - render: Template, - - parameters: { - docs: { - description: { - story: 'Row with cells fitted to the Grid', - }, - }, - }, - - args: { - items: [ - { ...DataListCellStory.args, cols: 1, children: 'cols 1' }, - { ...DataListCellStory.args, cols: 6, children: 'cols 6' }, - { ...DataListCellStory.args, cols: 3, children: 'cols 3' }, - { ...DataListCellStory.args, cols: 2, children: 'cols 2' }, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.test.js b/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.test.js deleted file mode 100644 index ce0ae96bc..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListRow/DataListRow.test.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { DataListRow } from "./index" - -describe("DataListRow", () => { - - test("renders a DataListRow", async () => { - render(<DataListRow data-testid="my-datalistrow" />) - expect(screen.getByTestId("my-datalistrow")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<DataListRow data-testid="my-datalistrow" className="my-custom-class" />) - expect(screen.getByTestId("my-datalistrow")).toBeInTheDocument() - expect(screen.getByTestId("my-datalistrow")).toHaveClass("my-custom-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DataListRow/index.js b/libs_deprecated/juno-ui-components/src/components/DataListRow/index.js deleted file mode 100644 index 7203e011c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DataListRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DataListRow } from "./DataListRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.component.js b/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.component.js deleted file mode 100644 index cd9c41afe..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.component.js +++ /dev/null @@ -1,711 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useEffect, useRef, useId, useMemo, useState } from "react" -import PropTypes from "prop-types" -import flatpickr from "flatpickr" -import { FormHint } from "../FormHint/" -import { Icon } from "../Icon/" -import { Label } from "../Label/" -import "./datetimepicker.scss" - -/* -TODO: -* add enable prop (or leave out if no success) -* add position prop (if possible, otherwise leave out) -* Allow to use the expected date format as a placeholder in the input element (placeholder="dateFormat" or smth similar?) when direct input is enabled? -*/ - -const inputWrapperStyles = ` - jn-relative -` - -const inputStyles = ` - jn-bg-theme-textinput - jn-bg-no-repeat - jn-bg-[top_0.375rem_right_1rem] - jn-text-theme-textinput - jn-fill-theme-textinput-default - jn-border - jn-text-base - jn-leading-4 - jn-px-4 - jn-h-textinput - jn-rounded-3px - focus:jn-outline-none - focus:jn-ring-2 - focus:jn-ring-theme-focus - disabled:jn-opacity-50 - disabled:jn-cursor-not-allowed - autofill:jn-bg-theme-textinput-autofill - autofill:jn-text-theme-textinput-autofill -` - -const inputWithLabelStyles = ` - jn-pt-[1.125rem] - jn-pb-1 -` - -const inputWithoutLabelStyles = ` - jn-py-4 -` - -const inputDefaultBorderStyles = ` - jn-border-theme-textinput-default -` - -const inputInvalidStyles = ` - jn-border-theme-error -` - -const inputValidStyles = ` - jn-border-theme-success -` - -const labelStyles = ` - peer-autofill:jn-text-theme-textinput-autofill-label - jn-pointer-events-none - jn-top-2 - jn-left-[0.9375rem] -` - -const iconContainerStyles = ` - jn-absolute - jn-inline-flex - jn-top-2 - jn-right-[2.75rem] - jn-gap-1.5 -` - -/** A all-purpose date and time picker component. Highly configurable, based on Flatpickr. */ - -export const DateTimePicker = ({ - allowInput, - allowInvalidPreload, - ariaDateFormat, - className, - conjunction, - dateFormat, - defaultHour, - defaultMinute, - defaultDate, - defaultValue, - disable, - disabled, - enableSeconds, - enableTime, - errortext, - helptext, - hourIncrement, - id, - invalid, - label, - locale, - maxDate, - minDate, - minuteIncrement, - mode, - monthSelectorType, - name, - noCalendar, - onBlur, - onChange, - onClear, - onClose, - onFocus, - onMonthChange, - onOpen, - onReady, - onYearChange, - placeholder, - required, - shorthandCurrentMonth, - showMonths, - successtext, - time_24hr, - valid, - value, - weekNumbers, - width, - ...props -}) => { - // always generate auto-id string using the useId hook to avoid "more hooks than in previous render" error when removing custom id: - const autoId = "juno-datetimepicker-" + useId() - const theId = id && id.length ? id : autoId - - const fpRef = useRef(null) // the dom node flatpickr instance will be bound to - let flatpickrInstanceRef = useRef({}) // The actual flatpickr instance - const calendarTargetRef = useRef(null) // The DOM node the flatpickr calendar should be rendered to - - const [theDate, setTheDate] = useState({}) - const [hasFocus, setHasFocus] = useState(false) - const [isOpen, setIsOpen] = useState(false) - const [isInvalid, setIsInvalid] = useState(false) - const [isValid, setIsValid] = useState(false) - - const updateFlatpickrInstance = (newKeys) => - (flatpickrInstanceRef.current = { - ...flatpickrInstanceRef.current, - ...Object.keys(newKeys).reduce((a, key) => { - a[key] = newKeys[key] - return a - }, {}), - }) - - const invalidated = useMemo( - () => (invalid || (errortext && errortext.length) ? true : false), - [invalid, errortext] - ) - const validated = useMemo( - () => (valid || (successtext && successtext.length) ? true : false), - [valid, successtext] - ) - - useEffect(() => { - setIsInvalid(invalidated) - }, [invalidated]) - - useEffect(() => { - setIsValid(validated) - }, [validated]) - - const handleBlur = () => { - setHasFocus(false) - onBlur && onBlur(theDate.selectedDate, theDate.selectedDateStr) - } - - const handleChange = (selectedDate, dateStr, instance) => { - setTheDate({ selectedDate: selectedDate, selectedDateStr: dateStr }) - onChange && onChange(selectedDate, dateStr) - } - - const handleClose = (selectedDate, dateStr, instance) => { - setIsOpen(false) - onClose && onClose(selectedDate, dateStr) - } - - const handleMonthChange = (selectedDate, dateStr, instance) => { - setTheDate({ selectedDate: selectedDate, selectedDateStr: dateStr }) - onMonthChange && onMonthChange(selectedDate, dateStr) - } - - const handleOpen = (selectedDate, dateStr, instance) => { - setIsOpen(true) - onOpen && onOpen(selectedDate, dateStr) - } - - const handleReady = (selectedDate, dateStr, instance) => { - onReady && onReady(selectedDate, dateStr) - } - - const handleYearChange = (selectedDate, dateStr, instance) => { - setTheDate({ selectedDate: selectedDate, selectedDateStr: dateStr }) - onYearChange && onYearChange(selectedDate, dateStr) - } - - const handleInputFocus = () => { - setHasFocus(true) - onFocus && onFocus(theDate.selectedDate, theDate.selectedDateStr) - } - - const handleClearIconClick = () => { - setTheDate({}) - flatpickrInstanceRef.current?.clear() - onClear && onClear([], "") - } - - // Create stringified versions of the value prop and its aliases in order to use them in a useEffect dependency array later. - const stringifiedValue = JSON.stringify(value) - const stringifiedDefaultDate = JSON.stringify(defaultDate) - const stringifiedDefaultValue = JSON.stringify(defaultValue) - - // Function to determine the date format. Will return the dateFormat if passed as a prop, or a useful defaultFormat depending on whether the DateTimePicker is set to show the time, seconds, or no calendar at all (time picker only). - const getDateFormat = () => { - const defaultDateFormat = enableTime - ? noCalendar - ? enableSeconds - ? "H:i:S" - : "H:i" - : enableSeconds - ? "Y-m-d H:i:S" - : "Y-m-d H:i" - : "Y-m-d" - - const theDateFormat = - dateFormat === undefined ? defaultDateFormat : dateFormat - - return theDateFormat - } - - const theDateFormat = getDateFormat() - - const createFlatpickrInstance = () => { - const options = { - allowInput: allowInput, - allowInvalidPreload: allowInvalidPreload, - ariaDateFormat: ariaDateFormat, - appendTo: calendarTargetRef.current, - conjunction: conjunction, - dateFormat: theDateFormat, - defaultDate: defaultDate || defaultValue, - defaultHour: defaultHour, - defaultMinute: defaultMinute, - disable: disable, - enableSeconds: enableSeconds, - enableTime: enableTime, - hourIncrement: hourIncrement, - locale: locale, - maxDate: maxDate, - minDate: minDate, - minuteIncrement: minuteIncrement, - mode: mode, - monthSelectorType, - noCalendar: noCalendar, - onChange: handleChange, - onClose: handleClose, - onMonthChange: handleMonthChange, - onOpen: handleOpen, - onReady: handleReady, - onYearChange: handleYearChange, - positionElement: calendarTargetRef.current, - shorthandCurrentMonth: shorthandCurrentMonth, - showMonths: showMonths, - time_24hr: time_24hr, - weekNumbers: weekNumbers, - } - const FP = - calendarTargetRef && fpRef.current && flatpickr(fpRef.current, options) - updateFlatpickrInstance(FP) - } - - const destroyFlatpickrInstance = () => { - flatpickrInstanceRef.current.destroy() - setTheDate({}) - flatpickrInstanceRef = null // Not sure if this is actually necessary? - } - - useEffect(() => { - createFlatpickrInstance() - return () => { - destroyFlatpickrInstance() - } - }, []) - - /* - Some config options on the flatpickr instance can not be set with immediate effect, a new instance needs to be created. - For the corresponding props we have some logic that makes sure we destroy the current instance and create a new one only when absolutely necessary. Also, we need to reduce doing that to only once, even if multiple of the props were updated at the same time for the sake of efficiency, and to make sure we do not call event handlers more often than needed and expected by the user. - */ - - // Store current props that will require creating a new instance when their value changes: - const prevRerenderingProps = useRef({ - allowInput: allowInput, - defaultHour: defaultHour, - defaultMinute: defaultMinute, - enableTime: enableTime, - enableSeconds: enableSeconds, - hourIncrement: hourIncrement, - minuteIncrement: minuteIncrement, - mode: mode, - noCalendar: noCalendar, - weekNumbers: weekNumbers, - }) - - // Apply a use effect to handle the logic bound to the props that require creating a new faltpickr instance: - useEffect(() => { - // set a variable to be set to true once we know we need to destroy the current instance and create a new one: - let hasChanged = false - - // For each of the props… - Object.keys(prevRerenderingProps.current).forEach((propKey) => { - const prevValue = prevRerenderingProps.current[propKey] - const currentValue = { - allowInput, - defaultHour, - defaultMinute, - enableTime, - enableSeconds, - hourIncrement, - minuteIncrement, - mode, - monthSelectorType, - noCalendar, - showMonths, - weekNumbers, - }[propKey] - - // … we need to check whether their value has actually changed - if (prevValue !== currentValue) { - hasChanged = true - } - }) - - // After we have checked if any one or multiple of the relevant props have changed, we actually destroy the curent instance and create a new one: - if (hasChanged) { - flatpickrInstanceRef?.current?.destroy() - createFlatpickrInstance() - } - - // Also make sure we update our stored props in order to be ready for the next update: - prevRerenderingProps.current = { - allowInput: allowInput, - defaultHour: defaultHour, - defaultMinute: defaultMinute, - enableTime: enableTime, - enableSeconds: enableSeconds, - hourIncrement: hourIncrement, - minuteIncrement: minuteIncrement, - mode: mode, - monthSelectorType: monthSelectorType, - noCalendar: noCalendar, - showMonths: showMonths, - weekNumbers: weekNumbers, - } - }, [ - allowInput, - defaultHour, - defaultMinute, - enableTime, - enableSeconds, - hourIncrement, - minuteIncrement, - mode, - monthSelectorType, - noCalendar, - showMonths, - weekNumbers, - ]) - - // useEffects for props that represent config options that can be set on an existing flatpickr instance with immediate effect: - useEffect(() => { - flatpickrInstanceRef.current?.set( - "allowInvalidPreload", - allowInvalidPreload - ) - }, [allowInvalidPreload]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("ariaDateFormat", ariaDateFormat) - }, [ariaDateFormat]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("conjunction", conjunction) - }, [conjunction]) - - useEffect(() => { - const newDateFormat = getDateFormat() - flatpickrInstanceRef.current?.set("dateFormat", newDateFormat) - }, [dateFormat]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("disable", disable) - }, [disable]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("hourIncrement", hourIncrement) - }, [hourIncrement]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("locale", locale) - }, [locale]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("maxDate", maxDate) - }, [maxDate]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("minDate", minDate) - }, [minDate]) - - useEffect(() => { - flatpickrInstanceRef.current?.set( - "shorthandCurrentMonth", - shorthandCurrentMonth - ) - }, [shorthandCurrentMonth]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("time_24hr", time_24hr) - }, [time_24hr]) - - // Update the flatpickr instance whenever the value prop (or any of its aliases) changes, and force the flatpickr instance to fire onChange event. These props may contain an array of one or multiple objects. These will never pass React's identity comparison, and will be regarded as a new object with any render regardless of their contents, thus creating an endless loop by updating the flatpickr instance updating the parent state (via onChange above) updating the flatpickr instance (…). We prevent this by checking on the stringified versions of the props in the dependency array. - useEffect(() => { - flatpickrInstanceRef.current?.setDate( - value || defaultDate || defaultValue, - true // enforce firing change event that in turn will update our state via handleChange. - ) - }, [stringifiedValue, stringifiedDefaultDate, stringifiedDefaultValue]) - - useEffect(() => { - flatpickrInstanceRef.current?.set("weekNumbers", weekNumbers) - }, [weekNumbers]) - - return ( - <div - className={` - juno-datetimepicker-wrapper - ${width == "auto" ? "jn-inline-block" : "jn-block"} - ${width == "auto" ? "jn-w-auto" : "jn-w-full"} - `} - > - <div - className={`juno-datetimepicker-input-wrapper ${inputWrapperStyles}`} - > - <input - className={` - juno-datetimepicker-input - ${inputStyles} - ${label ? inputWithLabelStyles : inputWithoutLabelStyles} - ${ - isInvalid - ? "juno-datetimepicker-input-invalid " + inputInvalidStyles - : "" - } - ${ - isValid - ? "juno-datetimepicker-input-valid" + inputValidStyles - : "" - } - ${isValid || isInvalid ? "" : inputDefaultBorderStyles} - ${width == "auto" ? "jn-w-auto" : "jn-w-full"} - ${ - enableTime && noCalendar - ? "juno-datetimepicker-input-timepicker" - : "juno-datetimepicker-input-default" - } - ${className} - `} - data-mode={mode} - disabled={disabled} - id={theId} - name={name && name.length ? name : null} - onBlur={handleBlur} - onChange={handleChange} - onFocus={handleInputFocus} - placeholder={placeholder} - ref={fpRef} - type="text" - {...props} - /> - - {label && label.length ? ( - <Label - text={label} - htmlFor={theId} - className={`${labelStyles}`} - disabled={disabled} - required={required} - floating - minimized={ - placeholder || - isOpen || - theDate.selectedDate?.length || - theDate.selectedDateStr?.length - ? true - : false - } - /> - ) : ( - "" - )} - - <div - className={`juno-datetimepicker-icon-container ${iconContainerStyles}`} - > - {theDate.selectedDate?.length || theDate.selectedDateStr?.length ? ( - <Icon - icon="close" - onClick={handleClearIconClick} - disabled={disabled} - title="Clear" - /> - ) : ( - "" - )} - {isInvalid ? ( - <Icon icon="dangerous" color="jn-text-theme-error" /> - ) : ( - "" - )} - {isValid ? ( - <Icon icon="checkCircle" color="jn-text-theme-success" /> - ) : ( - "" - )} - </div> - </div> - <div ref={calendarTargetRef}></div> - - {errortext && errortext.length ? ( - <FormHint text={errortext} variant="error" className="jn-mt-0" /> - ) : ( - "" - )} - {successtext && successtext.length ? ( - <FormHint text={successtext} variant="success" className="jn-mt-0" /> - ) : ( - "" - )} - {helptext && helptext.length ? ( - <FormHint text={helptext} className="jn-mt-0" /> - ) : ( - "" - )} - </div> - ) -} - -const datePropType = PropTypes.oneOfType([ - PropTypes.string, - PropTypes.array, - PropTypes.object, - PropTypes.number, -]) - -DateTimePicker.propTypes = { - /** Whether the DateTimePicker input element allows direct user keyboard input. Default is `false`. */ - allowInput: PropTypes.bool, - /** Allows the preloading of an invalid date (e.g. a date that hass been disable by passing `disable`). When disabled, the field will be cleared if the provided date is invalid */ - allowInvalidPreload: PropTypes.bool, - /** How the `aria-label` date for each day in the calendar will be formed. Uses the same rules/tokens as `dateFormat´ as described here: https://flatpickr.js.org/formatting/. When changing this, make sure the outcome makes sense when using a screenreader.*/ - ariaDateFormat: PropTypes.string, - /** Pass custom classNames. These will be appended to the input element of the DateTimePicker. */ - className: PropTypes.string, - /** A custom string to separate individual dates in `multiple` mode. */ - conjunction: PropTypes.string, - /** A string of characters to customize how a date will be formatted in the input field. Available options: https://flatpickr.js.org/formatting/ */ - dateFormat: PropTypes.string, - /** Sets the default date of the DateTimePicker. Same as `value`, only here for compatibility with the original Flatpickr library. If both `value` and `defaultDate` are being passed, `value` will win. Date Objects, timestamps, ISO date strings, chronological date strings `YYYY-MM-DD HH:MM` (must be compatible to current `dateFormat`), and the shortcut `today` are all accepted. */ - defaultDate: datePropType, - /** The initial value of the hour input element. Only effective if time is enabled. Note this will only set the hour input element to the value specified. Setting this options will not set a selected value on the DateTimePicker. */ - defaultHour: PropTypes.number, - /** The initial value of the minute input element. Only effective if time is enabled. Note this will only set the minute input element to the value specified. Setting this options will not set a selected value on the DateTimePicker. */ - defaultMinute: PropTypes.number, - /** Same as value, defaultDate */ - defaultValue: datePropType, - /** Pass an array of dates, date strings, date ranges or functions to disable dates. More on disabling dates: https://flatpickr.js.org/examples/#disabling-specific-dates */ - disable: PropTypes.array, - /** Whether the DateTimePicker is disabled */ - disabled: PropTypes.bool, - /** Whether to show seconds when showing a time picker. */ - enableSeconds: PropTypes.bool, - /** Whether to show a time picker. */ - enableTime: PropTypes.bool, - /** A text to render when the DateTimePicker has an error or could not be validated. */ - errortext: PropTypes.node, - /** A helptext to render to explain meaning and significance of the DateTimePicker. */ - helptext: PropTypes.node, - /** The step for the hour input. Only has an effect when a time picker is enabled via `enableTime`. */ - hourIncrement: PropTypes.number, - /** The id of the DateTimePicker input element. If none is passed, an automatically generated id will be used. */ - id: PropTypes.string, - /** Whether the DateTimePicker selected date was negatively validated. */ - invalid: PropTypes.bool, - /** The label of the DateTimePicker input element. */ - label: PropTypes.string, - /** Localization string or object. Can be used to set starting day of the week, e.g. Mondays instead of Sundays. More on localization: https://flatpickr.js.org/localization/ */ - locale: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), - /** The maximum / latest date a user can select (inclusive). */ - maxDate: datePropType, - /** The minimum / earliest date a user can select (inclusive). */ - minDate: datePropType, - /** The step for the minute input. Only has an effect when a time picker is enabled via `enableTime`. */ - minuteIncrement: PropTypes.number, - /** The mode of the Datepicker. */ - mode: PropTypes.oneOf(["single", "multiple", "range"]), - /** Whether to show a dropdown to select the current month. Default is "static". If `showMonths` is set to be greater than 1, it will always be displayed as static. Arrows to scroll through the months as well as through years will still be displayed and working. */ - monthSelectorType: PropTypes.oneOf(["static", "dropdown"]), - /** The name of the DateTimePicker input element */ - name: PropTypes.string, - /** Set to `true` to not display a calendar at all. To create a time picker, set `enableTime` to true, too. */ - noCalendar: PropTypes.bool, - /** A handler to be executed when the DateTimePicker input element looses focus. */ - onBlur: PropTypes.func, - /** A handler to be executed when the selected date(s), date range or time changes */ - onChange: PropTypes.func, - /** A handler to be executed when the DateTimePicker value is reset by clicking the clear icon. The onChnage handler will be fired in this event too, onClear is more specific. */ - onClear: PropTypes.func, - /** A handler to be executed when the DateTimePicker calendar closes */ - onClose: PropTypes.func, - /** A handler to be executed when the DateTimePicker input element receives focus. */ - onFocus: PropTypes.func, - /** A handler to be executed when the selected month changes */ - onMonthChange: PropTypes.func, - /** A handler to be executed when the DateTimePicker calendar opens */ - onOpen: PropTypes.func, - /** A handler to be executed when the DateTimePicker component is ready */ - onReady: PropTypes.func, - /** A handler to be executed when the selected year changes */ - onYearChange: PropTypes.func, - /** The placeholder of the DateTimePicker input element */ - placeholder: PropTypes.string, - /** Whether the DateTimePicker should be marked as required. Requires a `Label` to be set. */ - required: PropTypes.bool, - /** Whether the current month in the date picker should be displayed as shorthand, e.g. "Jan" instead of "January" */ - shorthandCurrentMonth: PropTypes.bool, - /** The number of months to show in the date picker */ - showMonths: PropTypes.number, - /** A text to render when the DateTimePicker was successfully validated */ - successtext: PropTypes.node, - /** Displays time picker in 24 hour mode without AM/PM selection when enabled. Requires `enableTime` to be set, too. Default is `false`. */ - time_24hr: PropTypes.bool, - /** Whether the DateTimePicker has been successfully validated */ - valid: PropTypes.bool, - /** The value of the datepicker. Date Objects, timestamps, ISO date strings, chronological date strings `YYYY-MM-DD HH:MM` (must be compatible to current `dateFormat`), and the shortcut `today` are all accepted. */ - value: datePropType, - /** Whether to render week numbers. Default is `false`. */ - weekNumbers: PropTypes.bool, - /** The width of the datepicker input. Either 'full' (default) or 'auto'. */ - width: PropTypes.oneOf(["full", "auto"]), -} - -DateTimePicker.defaultProps = { - allowInput: false, - allowInvalidPreload: false, - ariaDateFormat: "F j, Y", - className: "", - conjunction: ", ", - dateFormat: undefined, - defaultHour: 12, - defaultMinute: 0, - defaultDate: null, - defaultValue: "", - disable: [], - disabled: false, - enableSeconds: false, - enableTime: false, - errortext: "", - helptext: "", - hourIncrement: 1, - id: "", - invalid: false, - label: "", - locale: null, - maxDate: null, - minDate: null, - minuteIncrement: 1, - mode: "single", - monthSelectorType: "static", - name: "", - noCalendar: false, - onBlur: undefined, - onChange: undefined, - onClear: undefined, - onClose: undefined, - onFocus: undefined, - onMonthChange: undefined, - onOpen: undefined, - onReady: undefined, - onYearChange: undefined, - placeholder: "", - required: false, - shorthandCurrentMonth: false, - showMonths: 1, - successtext: "", - time_24hr: false, - valid: false, - value: "", - weekNumbers: false, - width: "full", -} diff --git a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.stories.js b/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.stories.js deleted file mode 100644 index 947e6174b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.stories.js +++ /dev/null @@ -1,500 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState } from "react" -import { DateTimePicker } from "./index.js" -import { PortalProvider } from "../PortalProvider/PortalProvider.component" -import { Form } from "../Form/" - -export default { - title: "WIP/DateTimePicker/DateTimePicker", - component: DateTimePicker, - argTypes: { - mode: { - options: ["single", "multiple", "range", "time"], - control: { type: "select" }, - }, - value: { - control: false, - }, - errortext: { - control: false, - }, - helptext: { - control: false, - }, - successtext: { - control: false, - }, - monthSelectorType: { - options: ["dropdown", "static"], - control: { type: "radio" }, - }, - width: { - options: ["auto", "full"], - control: { type: "radio" }, - }, - disable: { - control: false, - }, - }, -} - -// Not in use yet, useful for "enable" story once we have it, pls leave here: -const daysFromToday = (n) => { - const today = new Date() - return new Date(today.setDate(today.getDate() + n)) -} - -const Template = ({ ...args }) => <DateTimePicker {...args} /> - -export const Default = Template.bind({}) -Default.args = {} - -export const WithLabel = Template.bind({}) -WithLabel.args = { - label: "Select a date", -} - -export const Required = Template.bind({}) -Required.args = { - label: "Select a date", - required: true, -} - -export const Disabled = Template.bind({}) -Disabled.args = { - label: "Select a date", - disabled: true, -} - -export const WithPlaceholder = Template.bind({}) -WithPlaceholder.args = { - placeholder: "Select a date…", -} - -export const WithValue = Template.bind({}) -WithValue.parameters = { - docs: { - description: { - story: - "Set the selected date of the datePicker. `value`, `defaultValue`, and `defaultDate` do the exact same thing and can be used interchangeably.", - }, - }, -} -WithValue.args = { - value: new Date(), -} - -export const WithDefaultDate = Template.bind({}) -WithDefaultDate.parameters = { - docs: { - description: { - story: - "Set the selected date of the datePicker. `value`, `defaultValue`, and `defaultDate` do the exact same thing and can be used interchangeably.", - }, - }, -} -WithDefaultDate.args = { - defaultDate: new Date(), -} - -export const WithDefaultHourAndMinute = Template.bind({}) -WithDefaultHourAndMinute.parameters = { - docs: { - description: { - story: - "Pass `defaultHour` and `defaultMinute` to set default values for the date and time input elements. Note: this will not set a selected date with these values in the DateTimePicker input element, the user still has to make a selection.", - }, - }, -} -WithDefaultHourAndMinute.args = { - defaultHour: 9, - defaultMinute: 13, - enableTime: true, - helptext: - "The hour and minute input elements in the dropdown calendar have been set to default values (09:13 AM).", -} - -export const WithDefaultValue = Template.bind({}) -WithDefaultValue.parameters = { - docs: { - description: { - story: - "Set the selected date of the datePicker. `value`, `defaultValue`, and `defaultDate` do the exact same thing and can be used interchangeably.", - }, - }, -} -WithDefaultValue.args = { - defaultValue: new Date(), -} - -export const WithValueAsDateString = Template.bind({}) -WithValueAsDateString.parameters = { - docs: { - description: { - story: - 'Pass a string as a `value`, `defaultValue`, or `defaultDate` that is compatible with the current `dateFormat` prop, e.g. `"2024-01-24"` if the current `dateFormat` is `"Y-m-d"` (as is the default). The DateTimePicker component will not convert these.', - }, - }, -} -WithValueAsDateString.args = { - value: "2024-01-24", -} - -export const WithValueAsIsoDateString = Template.bind({}) -WithValueAsIsoDateString.parameters = { - docs: { - description: { - story: - "Pass an ISO-compatible date string to display the corresponding date in the Datepicker.", - }, - }, -} -WithValueAsIsoDateString.args = { - value: "2034-02-26T19:40:03.243Z", -} - -export const WithValueAsTimestamp = Template.bind({}) -WithValueAsTimestamp.parameters = { - docs: { - description: { - story: - "Pass a timestamp with milliseconds as `value` to display the corresponding date in the Datepicker.", - }, - }, -} -WithValueAsTimestamp.args = { - value: 1706273787000, -} - -export const WithValueAsTodayShortcut = Template.bind({}) -WithValueAsTodayShortcut.parameters = { - docs: { - description: { - story: - 'Pass `"today"` as `value` as a shortcut to display the current Date in the Datepicker.', - }, - }, -} -WithValueAsTodayShortcut.args = { - value: "today", -} - -export const WithCustomDateFormat = Template.bind() -WithCustomDateFormat.parameters = {} -WithCustomDateFormat.args = { - value: "today", - dateFormat: "F d, Y", -} - -export const WithTime = Template.bind({}) -WithTime.parameters = { - docs: { - description: { - story: - "To also show a time picker to allow users to select a date and a time, set `enableTime` to `true`. Set the `dateFormat` accordingly to have the selected time reflected in the DateTimePicker input element. More about formatting dates here: https://flatpickr.js.org/formatting/.", - }, - }, -} -WithTime.args = { - enableTime: true, -} - -export const WithTimeAndSeconds = Template.bind({}) -WithTimeAndSeconds.parameters = { - docs: { - description: { - story: - "To allow selecting seconds when showing a time picker, set `enableSeconds` to `true`. To reflect seconds in the selected date in the DateTimePicker, adjust the `dateFormat` accordingly: https://flatpickr.js.org/formatting/.", - }, - }, -} -WithTimeAndSeconds.args = { - enableTime: true, - enableSeconds: true, -} - -export const WithTimeWithCustomHourIncrement = Template.bind({}) -WithTimeWithCustomHourIncrement.parameters = { - docs: { - description: { - story: - "Set a custom hour increment by which to change the hour in the respective element.", - }, - }, -} -WithTimeWithCustomHourIncrement.args = { - enableTime: true, - hourIncrement: 6, - helptext: "The hour input of this DateTimePicker has a 6 hour increment.", -} - -export const WithTimeWithCustomMinuteIncrement = Template.bind({}) -WithTimeWithCustomMinuteIncrement.parameters = { - docs: { - description: { - story: - "Set a custom minute increment by which to change the minute in the respective element.", - }, - }, -} -WithTimeWithCustomMinuteIncrement.args = { - enableTime: true, - minuteIncrement: 5, - helptext: "The minute input of this DateTimePicker has a 5 minute increment.", -} - -export const With24hTime = Template.bind({}) -With24hTime.parameters = { - docs: { - description: { - story: - "Set the time picker to use 24h time mode without AM/PM selection.", - }, - }, -} -With24hTime.args = { - enableTime: true, - time_24hr: true, -} - -export const ShowTwoMonths = Template.bind({}) -ShowTwoMonths.parameters = { - docs: { - description: { - story: - "Set the number of months to be displayed side by side in the calendar.", - }, - }, -} -ShowTwoMonths.args = { - showMonths: 2, -} - -export const WithWeekNumbers = Template.bind({}) -WithWeekNumbers.parameters = { - docs: { - description: { - story: - "Set `weekNumbers` to `true` to display week numbers in the calendar.", - }, - }, -} -WithWeekNumbers.args = { - weekNumbers: true, -} - -export const WithShorthandCurrentMonth = Template.bind({}) -WithShorthandCurrentMonth.parameters = { - docs: { - description: { - story: - "Set `shorthandCurrentMonth` to `true` to show shorthand month names, e.g. 'Jan' instead of 'January'.", - }, - }, -} -WithShorthandCurrentMonth.args = { - shorthandCurrentMonth: true, -} - -export const WithMonthSelectorDropdown = Template.bind({}) -WithMonthSelectorDropdown.parameters = { - docs: { - description: { - story: - 'Set `monthSelectorType` to "dropdown" in order to show a select element to switch months in the calndar.', - }, - }, -} -WithMonthSelectorDropdown.args = { - monthSelectorType: "dropdown", -} - -export const AllowInput = Template.bind({}) -AllowInput.parameters = { - docs: { - description: { - story: - "Set `allowInput` to `true` to allow direct user input by typing into the DateTimePicker input element.", - }, - }, -} -AllowInput.args = { - allowInput: true, -} - -export const Multiple = Template.bind({}) -Multiple.parameters = { - docs: { - description: { - story: 'To select multiple dates, set `mode` to "multiple".', - }, - }, -} -Multiple.args = { - mode: "multiple", -} - -export const Range = Template.bind({}) -Range.parameters = { - docs: { - description: { - story: - 'To select a date range instead of individual date(s), set `mode` to "range".', - }, - }, -} -Range.args = { - mode: "range", -} - -export const TimePicker = Template.bind({}) -TimePicker.parameters = { - docs: { - description: { - story: - "In order to create a pure timepicker, set the `dateFormat` accordingly, and set `noCalendar` and `enableTime` to `true`. If seconds are required, set `enableSeconds` to `true`.", - }, - }, -} -TimePicker.args = { - enableTime: true, - noCalendar: true, - enableSeconds: true, -} - -export const WithMinDate = Template.bind({}) -WithMinDate.parameters = { - docs: { - description: { - story: "Set a `minDate` to allow selecting only later dates.", - }, - }, -} -WithMinDate.args = { - minDate: new Date(), - helptext: "Only dates in the future including today can be selected.", -} - -export const WithMaxDate = Template.bind({}) -WithMaxDate.parameters = { - docs: { - description: { - story: "Set a `maxDate` to allow selecting only earlier dates.", - }, - }, -} -WithMaxDate.args = { - maxDate: new Date(), - helptext: "Only dates in the past including today can be selected.", -} - -export const DisableDate = Template.bind({}) -;(DisableDate.parameters = { - docs: { - description: { - story: - "Pass an array of dates to be disabled, making it impossible for the user to select these dates.", - }, - }, -}), - (DisableDate.args = { - disable: [new Date()], - helptext: "The current date (today) can not be selected.", - }) - -export const DisableByFunction = Template.bind({}) -DisableByFunction.parameters = { - docs: { - description: { - story: - "Pass an array of functions such as `function(date) {// return true to disable date}` as `disable` to be run for each date in the calendar in order to disable dates that match custom criteria. Pass a locale string or object to modify the sequence of week days rendered in the calendar.", - }, - }, -} -DisableByFunction.args = { - disable: [ - function (date) { - return date.getDay() === 0 || date.getDay() === 6 - }, - ], - locale: { - firstDayOfWeek: 1, // set week to start on Monday - }, - helptext: - "Only work days can be selected, week in calendar starts with Monday.", -} - -export const Valid = Template.bind({}) -Valid.args = { - valid: true, -} - -export const Invalid = Template.bind({}) -Invalid.args = { - invalid: true, -} - -export const WithErrortext = Template.bind({}) -WithErrortext.args = { - errortext: "This DateTimePicker has an error or is invalid.", -} - -export const WithSuccesstext = Template.bind({}) -WithSuccesstext.args = { - successtext: "This DateTimePicker was susccessfully validated.", -} - -export const WithHelptext = Template.bind({}) -WithHelptext.args = { - helptext: "Some useful information goes here.", -} - -export const InvalidPreload = Template.bind({}) -InvalidPreload.parameters = { - docs: { - description: { - story: - "Normally, the text input element oif the datepicker would be cleared when passing a date as `value` or `defaultDate` that is disabled from selection. By setting `allowInvalidPreload` such dates can be initially displayed in the datepicker, even though they are not available for user selection in the calendar.", - }, - }, -} -InvalidPreload.args = { - allowInvalidPreload: true, - value: "2024-01-30", - disable: ["2024-01-30"], - helptext: - "The datpicker initially shows Jan 30, 2024 as value even though this date has been set as disabled and thus can not be selected by a user.", -} - -const ControlledTemplate = ({ ...args }) => { - const [testState, setTestState] = useState({ date: { end: null } }) - - const handleChange = (dObj, dStr) => { - setTestState({ date: { end: dObj } }) - } - - return ( - <DateTimePicker - {...args} - onChange={handleChange} - value={testState?.date?.end} - /> - ) -} - -export const ControlledDateTimePicker = { - render: ControlledTemplate, - parameters: { - docs: { - description: { - story: - "Example of controlled usage, using the date object array as returned by the onChange handler in the parent story state. This used to create an endless loop and should be fixed now.", - }, - }, - }, - args: {}, -} diff --git a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.test.js b/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.test.js deleted file mode 100644 index ae0d466d4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/DateTimePicker.test.js +++ /dev/null @@ -1,684 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { cleanup, render, screen, fireEvent } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { DateTimePicker } from "./index" - -const mockOnOpen = jest.fn() -const mockOnClear = jest.fn() -const mockOnClose = jest.fn() -const mockOnChange = jest.fn() -const mockOnMonthChange = jest.fn() -const mockOnYearChange = jest.fn() -const mockOnValueUpdate = jest.fn() - -describe("DateTimePicker", () => { - afterEach(() => { - cleanup() - jest.clearAllMocks() - }) - - test("renders a DateTimePicker", async () => { - render(<DateTimePicker />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("type", "text") - expect(screen.getByRole("textbox")).toHaveClass("juno-datetimepicker-input") - }) - - test("renders a label as passed", async () => { - render( - <DateTimePicker label="The DateTimePicker Label" id="my-textinput" /> - ) - expect(document.querySelector(".juno-label")).toBeInTheDocument() - expect(document.querySelector(".juno-label")).toHaveTextContent( - "The DateTimePicker Label" - ) - }) - - test("renders an id as passed", async () => { - render(<DateTimePicker id="my-datetimepicker" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "id", - "my-datetimepicker" - ) - }) - - test("renders a name as passed", async () => { - render(<DateTimePicker name="my-name" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("name", "my-name") - }) - - test("renders a DateTimePicker with an auto-generated id if no id is passed", async () => { - render(<DateTimePicker />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("id") - expect(screen.getByRole("textbox").getAttribute("id")).toMatch( - "juno-datetimepicker" - ) - }) - - test("renders a DateTimePicker with a label associated by an id as passed", async () => { - render(<DateTimePicker label="The DateTimePicker Label" id="dp-1" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("id") - expect(screen.getByRole("textbox").getAttribute("id")).toMatch("dp-1") - expect( - screen.getByLabelText("The DateTimePicker Label") - ).toBeInTheDocument() - }) - - test("renders a DateTimePicker with a label associated by an auto-generated id if no id was passed ", async () => { - render(<DateTimePicker label="This is a DateTimePicker" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect( - screen.getByLabelText("This is a DateTimePicker") - ).toBeInTheDocument() - }) - - test("renders a DateTimePicker with a placholder as passed", async () => { - render(<DateTimePicker placeholder="This is a placeholder" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "placeholder", - "This is a placeholder" - ) - }) - - test("renders a disabled DateTimePicker as passed", async () => { - render(<DateTimePicker disabled />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toBeDisabled() - }) - - test("renders a Clear button if passed and when a date is set", async () => { - render(<DateTimePicker value="2027-01-12" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByTitle("Clear")).toBeInTheDocument() - }) - - test("does not render a Clear button when no date is set", async () => { - render(<DateTimePicker />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.queryByTitle("Clear")).not.toBeInTheDocument() - }) - - test("renders a DateTimePicker marked as required", async () => { - // DateTimePicker needs a label passed since the Label subcomponent is responsible for rendering the Required marker: - render(<DateTimePicker label="Required DateTimePicker" required />) - expect(document.querySelector(".juno-required")).toBeInTheDocument() - }) - - test("renders a helptext as passed", async () => { - render(<DateTimePicker helptext="this is a helptext" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-help" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "this is a helptext" - ) - }) - - test("renders a valid DateTimePicker as passed", async () => { - render(<DateTimePicker valid />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveClass( - "juno-datetimepicker-input-valid" - ) - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders an invalid DateTimePicker as passed", async () => { - render(<DateTimePicker invalid />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveClass( - "juno-datetimepicker-input-invalid" - ) - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders a successtext as passed and validates the element", async () => { - render(<DateTimePicker successtext="great success!" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-success" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "great success!" - ) - expect(screen.getByRole("textbox")).toHaveClass( - "juno-datetimepicker-input-valid" - ) - expect(screen.getByTitle("CheckCircle")).toBeInTheDocument() - }) - - test("renders an errortext as passed and invalidates the element", async () => { - render(<DateTimePicker errortext="this is an error!" />) - expect(document.querySelector(".juno-form-hint")).toBeInTheDocument() - expect(document.querySelector(".juno-form-hint")).toHaveClass( - "juno-form-hint-error" - ) - expect(document.querySelector(".juno-form-hint")).toHaveTextContent( - "this is an error!" - ) - expect(screen.getByRole("textbox")).toHaveClass( - "juno-datetimepicker-input-invalid" - ) - expect(screen.getByTitle("Dangerous")).toBeInTheDocument() - }) - - test("renders a DateTimePicker with a time picker as passed", async () => { - render(<DateTimePicker enableTime={true} dateFormat="Y-m-d H:i:S" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(document.querySelector(".flatpickr-time")).toBeInTheDocument() - expect(screen.getByLabelText("Hour")).toBeInTheDocument() - expect(screen.getByLabelText("Minute")).toBeInTheDocument() - }) - - test("renders a DateTimePicker with a time picker with seconds as passed", async () => { - render(<DateTimePicker enableTime={true} enableSeconds={true} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(document.querySelector(".flatpickr-time")).toBeInTheDocument() - expect(screen.getByLabelText("Hour")).toBeInTheDocument() - expect(screen.getByLabelText("Minute")).toBeInTheDocument() - // We need to check for the flatpickr className as flatpickr does not assign an aria-label to the seconds input: - expect(document.querySelector(".flatpickr-second")).toBeInTheDocument() - }) - - test("displays the date as passed as a date object", async () => { - render(<DateTimePicker value={new Date(2099, 0, 1)} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2099-01-01") - }) - - test("displays the date as passed as a date string", async () => { - render(<DateTimePicker value="2024-01-26" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-26") - }) - - test("diplays the date as passed as an ISO date string", async () => { - render(<DateTimePicker value="2034-02-26T19:40:03.243Z" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2034-02-26") - }) - - test("displays the date as passed as a timestamp", async () => { - render(<DateTimePicker value={1706273787000} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-26") - }) - - test("displays the date as passed by shortcut 'today'", async () => { - render(<DateTimePicker value="today" />) - const today = new Date() - const year = today.getFullYear() - const month = (today.getMonth() + 1).toString().padStart(2, "0") - const day = today.getDate().toString().padStart(2, "0") - const todayAsString = `${year}-${month}-${day}` - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue(todayAsString) - }) - - test("displays the date in a custom format as passed", async () => { - render(<DateTimePicker dateFormat="F d Y" value={1706273787000} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("January 26 2024") - }) - - test("uses the default dateFormat (Y-m-d) in default (non-time picker) mode)", async () => { - const today = new Date() - const fullYear = today.getFullYear() - const month = (today.getMonth() + 1).toString().padStart(2, "0") - const day = today.getDate().toString().padStart(2, "0") - const todayAsString = `${fullYear}-${month}-${day}` - render(<DateTimePicker value={today} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue(todayAsString) - }) - - test("uses the correct default dateFormat (Y-m-d H:i) in date-time-picker mode without seconds", async () => { - const now = new Date() - const fullYear = now.getFullYear() - const month = (now.getMonth() + 1).toString().padStart(2, "0") - const day = now.getDate().toString().padStart(2, "0") - const hours = now.getHours().toString().padStart(2, "0") - const minutes = now.getMinutes().toString().padStart(2, "0") - const nowAsString = `${fullYear}-${month}-${day} ${hours}:${minutes}` - render(<DateTimePicker enableTime value={now} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue(nowAsString) - }) - - test("uses the correct default dateFormat (Y-m-d H:i:S) in date-time-picker mode with seconds enabled", async () => { - const now = new Date() - const fullYear = now.getFullYear() - const month = (now.getMonth() + 1).toString().padStart(2, "0") - const day = now.getDate().toString().padStart(2, "0") - const hours = now.getHours().toString().padStart(2, "0") - const minutes = now.getMinutes().toString().padStart(2, "0") - const seconds = now.getSeconds().toString().padStart(2, "0") - const nowAsStringWithSeconds = `${fullYear}-${month}-${day} ${hours}:${minutes}:${seconds}` - render(<DateTimePicker enableTime enableSeconds value={now} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue(nowAsStringWithSeconds) - }) - - test("uses the correct default dateFormat (H:i) in time-picker-only mode without seconds", async () => { - const now = new Date() - const hours = now.getHours().toString().padStart(2, "0") - const minutes = now.getMinutes().toString().padStart(2, "0") - const nowAsStringWithOnlyHoursAndMinutes = `${hours}:${minutes}` - render(<DateTimePicker enableTime noCalendar value={now} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue( - nowAsStringWithOnlyHoursAndMinutes - ) - }) - - test("uses the correct defaultDateFormat (H:i:S) in time-picker-only mode with seconds enabled", async () => { - const now = new Date() - const hours = now.getHours().toString().padStart(2, "0") - const minutes = now.getMinutes().toString().padStart(2, "0") - const seconds = now.getSeconds().toString().padStart(2, "0") - const nowAsStringWithOnlyHoursMinutesAndSeconds = `${hours}:${minutes}:${seconds}` - render(<DateTimePicker enableTime enableSeconds noCalendar value={now} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue( - nowAsStringWithOnlyHoursMinutesAndSeconds - ) - }) - - test("displays the date as passed as defaultDate instead of value or defaultDate", async () => { - render(<DateTimePicker defaultDate={new Date(2099, 0, 1)} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2099-01-01") - }) - - test("displays the date as passed as defaultValue instead of value or defaultDate", async () => { - render(<DateTimePicker defaultValue={new Date(2099, 0, 1)} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2099-01-01") - }) - - test("updates the date accordingly when value changes", async () => { - const { rerender } = render( - <DateTimePicker value={new Date(2024, 0, 12)} /> - ) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-12") - rerender(<DateTimePicker value={new Date(2025, 7, 18)} />) - expect(screen.getByRole("textbox")).toHaveValue("2025-08-18") - }) - - test("updates the date accordingly when defaultValue changes", async () => { - const { rerender } = render( - <DateTimePicker defaultValue={new Date(2024, 0, 12)} /> - ) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-12") - rerender(<DateTimePicker defaultValue={new Date(2025, 7, 18)} />) - expect(screen.getByRole("textbox")).toHaveValue("2025-08-18") - }) - - test("updates the date accordingly when defaultDate changes", async () => { - const { rerender } = render( - <DateTimePicker defaultDate={new Date(2024, 0, 12)} /> - ) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-12") - rerender(<DateTimePicker defaultDate={new Date(2025, 7, 18)} />) - expect(screen.getByRole("textbox")).toHaveValue("2025-08-18") - }) - - test("allows typing in the field when configured to do so", async () => { - render(<DateTimePicker allowInput />) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - expect(input).toHaveValue("") - await userEvent.click(input) - await user.type(input, "12") - expect(input).toHaveValue("12") - }) - - test("updates accordingly when the allowInput prop changes", async () => { - const { rerender } = render(<DateTimePicker />) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - expect(input).toHaveValue("") - expect(input).toHaveAttribute("readonly", "readonly") - rerender(<DateTimePicker allowInput />) - expect(input).toBeInTheDocument() - expect(input).toHaveValue("") - expect(input).not.toHaveAttribute("readonly") - await userEvent.click(input) - await user.type(input, "123") - expect(input).toHaveValue("123") - }) - - test("renders a DateTimePicker with week numbers as passed", async () => { - render(<DateTimePicker weekNumbers />) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - // click to open the calendar: - await user.click(input) - expect(document.querySelector(".flatpickr-weekwrapper")).toBeInTheDocument() - expect(document.querySelector(".flatpickr-weekday")).toBeInTheDocument() - expect(document.querySelector(".flatpickr-weekday")).toHaveTextContent("Wk") - expect(document.querySelector(".flatpickr-weeks")).toBeInTheDocument() - expect(document.querySelector(".flatpickr-weeks").childElementCount).toBe(6) - }) - - test("renders a DateTimePicker in single mode per default", async () => { - render(<DateTimePicker />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-mode", "single") - }) - - test("renders a DateTimePicker in multiple mode as passed", async () => { - render(<DateTimePicker mode="multiple" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-mode", "multiple") - }) - - test("renders a DateTimePicker in range mode as passed", async () => { - render(<DateTimePicker mode="range" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-mode", "range") - }) - - test("Updates the mode accordingly when the mode prop changes", async () => { - const { rerender } = render(<DateTimePicker />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-mode", "single") - rerender(<DateTimePicker mode="range" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-mode", "range") - }) - - test("allows setting an otherwise invalid value on first load as configured ", async () => { - render( - <DateTimePicker - value="2024-01-30" - disable={["2024-01-30"]} - allowInvalidPreload - /> - ) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("2024-01-30") - }) - - test("clicking the clear button clears the input", async () => { - render(<DateTimePicker value="2024-01-31" />) - const input = screen.getByRole("textbox") - const clearButton = screen.getByTitle("Clear") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - expect(input).toHaveValue("2024-01-31") - expect(clearButton).toBeInTheDocument() - await user.click(clearButton) - expect(input).toHaveValue("") - }) - - test("sets a custom aria-label format for calendar dates as passed", async () => { - render(<DateTimePicker ariaDateFormat="l, F j, Y" />) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - // click to open the calendar: - await user.click(input) - //Match something like "Monday, January 31, 2024" to pattern like [word, comma, space, word, space, one or two-digit number, comma, space, four-digit number] assuming this is precise enough: - expect( - document.querySelectorAll(".flatpickr-day")[0].getAttribute("aria-label") - ).toMatch(new RegExp(/^\b\w+\b, \b\w+\b \d{1,2}, \d{4}$/)) - }) - - test("uses a custom conjunction between dates in multiple mode as passed", async () => { - render( - <DateTimePicker - mode="multiple" - conjunction=" || " - value={["2024-02-01", "2099-03-12"]} - /> - ) - const input = screen.getByRole("textbox") - expect(input).toBeInTheDocument() - expect(input).toHaveValue("2024-02-01 || 2099-03-12") - }) - - test("updates the displayed value accordingly when the conjunction prop changes", async () => { - const { rerender } = render( - <DateTimePicker mode="multiple" value={["2024-02-01", "2099-03-12"]} /> - ) - const input = screen.getByRole("textbox") - expect(input).toBeInTheDocument() - expect(input).toHaveValue("2024-02-01, 2099-03-12") - rerender( - <DateTimePicker - mode="multiple" - value={["2024-02-01", "2099-03-12"]} - conjunction=" --- " - /> - ) - expect(input).toHaveValue("2024-02-01 --- 2099-03-12") - }) - - test("sets a default hour as passed", async () => { - render( - <DateTimePicker - enableTime={true} - dateFormat="Y-m-d H:i" - defaultHour={5} - /> - ) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - await user.click(input) - const hourInput = document.querySelector("input.flatpickr-hour") - expect(hourInput).toHaveValue(5) - }) - - test("sets a default minute as passed", async () => { - render( - <DateTimePicker enableTime dateFormat="Y-m-d H:i" defaultMinute={13} /> - ) - const input = screen.getByRole("textbox") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - await user.click(input) - const minuteInput = document.querySelector("input.flatpickr-minute") - expect(minuteInput).toHaveValue(13) - }) - - test("opens a calendar when clicking in the datepicker field", async () => { - render(<DateTimePicker />) - const input = screen.getByRole("textbox") - const calendar = document.querySelector(".flatpickr-calendar") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - expect(calendar).toBeInTheDocument() - expect(calendar).not.toHaveClass("open") - await user.click(input) - expect(calendar).toHaveClass("open") - }) - - test("uses a custom hour increment as passed", async () => { - render( - <DateTimePicker enableTime dateFormat="Y-m-d H:i" hourIncrement={6} /> - ) - const hourInput = document.querySelector("input.flatpickr-hour") - expect(hourInput).toHaveAttribute("step", "6") - }) - - test("uses a custom minute increment as passed", async () => { - render( - <DateTimePicker enableTime dateFormat="Y-m-d H:i" minuteIncrement={7} /> - ) - const hourInput = document.querySelector("input.flatpickr-minute") - expect(hourInput).toHaveAttribute("step", "7") - }) - - test("does not allow selection of dates before a minDate as passed", async () => { - // Select yesterday element in calendar by label (formed like "January 31, 2024"), and test if disabled. - const user = userEvent.setup() - const today = new Date() - const yesterday = new Date() - yesterday.setDate(yesterday.getDate() - 1) - const fullMonth = yesterday.toLocaleString("default", { month: "long" }) - const day = yesterday.getDate() - const fullYear = yesterday.getFullYear() - const yesterdayLabel = `${fullMonth} ${day}, ${fullYear}` - render(<DateTimePicker minDate={today} />) - const input = screen.getByRole("textbox") - await user.click(input) - const yesterdayEl = screen.getByLabelText(yesterdayLabel) - expect(yesterdayEl).toHaveClass("flatpickr-disabled") - }) - - test("allows selection of dates after a minDate as passed", async () => { - const user = userEvent.setup() - const today = new Date() - const tomorrow = new Date() - tomorrow.setDate(tomorrow.getDate() + 1) - const fullMonth = tomorrow.toLocaleString("default", { month: "long" }) - const day = tomorrow.getDate() - const fullYear = tomorrow.getFullYear() - const tomorrowLabel = `${fullMonth} ${day}, ${fullYear}` - render(<DateTimePicker minDate={today} />) - const input = screen.getByRole("textbox") - await user.click(input) - const yesterdayEl = screen.getByLabelText(tomorrowLabel) - expect(yesterdayEl).not.toHaveClass("flatpickr-disabled") - }) - - test("does not allow selection of dates after a maxDate as passed", async () => { - const user = userEvent.setup() - const today = new Date() - const tomorrow = new Date() - tomorrow.setDate(tomorrow.getDate() + 1) - const tomorrowFullMonth = tomorrow.toLocaleString("default", { - month: "long", - }) - const tomorrowDay = tomorrow.getDate() - const tomorrowFullYear = tomorrow.getFullYear() - const tomorrowLabel = `${tomorrowFullMonth} ${tomorrowDay}, ${tomorrowFullYear}` - render(<DateTimePicker maxDate={today} />) - const input = screen.getByRole("textbox") - await user.click(input) - const tomorrowEl = screen.getByLabelText(tomorrowLabel) - expect(tomorrowEl).toHaveClass("flatpickr-disabled") - }) - - test("allows selection of dates before a maxDate as passed", async () => { - const user = userEvent.setup() - const today = new Date() - const tomorrow = new Date() - tomorrow.setDate(tomorrow.getDate() + 1) - const todayFullMonth = today.toLocaleString("default", { month: "long" }) - const todayDay = today.getDate() - const todayFullYear = today.getFullYear() - const todayLabel = `${todayFullMonth} ${todayDay}, ${todayFullYear}` - render(<DateTimePicker maxDate={tomorrow} />) - const input = screen.getByRole("textbox") - await user.click(input) - const todayEl = screen.getByLabelText(todayLabel) - expect(todayEl).not.toHaveClass("flatpickr-disabled") - }) - - test("renders a time picker only if configured to do so", async () => { - render(<DateTimePicker enableTime noCalendar />) - expect(document.querySelector(".flatpickr-days")).not.toBeInTheDocument() - expect(document.querySelector("input.flatpickr-hour")).toBeInTheDocument() - expect(document.querySelector("input.flatpickr-minute")).toBeInTheDocument() - }) - - test("executes an onOpen handler when the user clicks the Datepicker and the calendar opens", async () => { - const user = userEvent.setup() - render(<DateTimePicker onOpen={mockOnOpen} />) - const input = screen.getByRole("textbox") - await user.click(input) - expect(mockOnOpen).toHaveBeenCalled() - }) - - test("closes the calendar and executes an onClose handler when the user clicks outside the calendar", async () => { - const user = userEvent.setup() - render(<DateTimePicker onClose={mockOnClose} />) - const input = screen.getByRole("textbox") - await user.click(input) - await user.click(document.body) - expect(mockOnClose).toHaveBeenCalled() - }) - - test("executes an onClear handler when the user clears the DateTimePicker by clicking the clear icon", async () => { - render(<DateTimePicker value="2024-01-31" onClear={mockOnClear} />) - const input = screen.getByRole("textbox") - const clearButton = screen.getByTitle("Clear") - const user = userEvent.setup() - expect(input).toBeInTheDocument() - expect(input).toHaveValue("2024-01-31") - expect(clearButton).toBeInTheDocument() - await user.click(clearButton) - expect(mockOnClear).toHaveBeenCalled() - }) - - test("executes an onChange handler when the user changes the selected date", async () => { - const user = userEvent.setup() - const today = new Date() - const tomorrow = new Date() - tomorrow.setDate(tomorrow.getDate() + 1) - const tomorrowFullMonth = tomorrow.toLocaleString("default", { - month: "long", - }) - const tomorrowDay = tomorrow.getDate() - const tomorrowFullYear = tomorrow.getFullYear() - const tomorrowLabel = `${tomorrowFullMonth} ${tomorrowDay}, ${tomorrowFullYear}` - render(<DateTimePicker value={today} onChange={mockOnChange} />) - const input = screen.getByRole("textbox") - await user.click(input) - const tomorrowEl = screen.getByLabelText(tomorrowLabel) - await user.click(tomorrowEl) - expect(mockOnChange).toHaveBeenCalled() - }) - - test("executes an onYearChange handler when the user changes the year", async () => { - const user = userEvent.setup() - render(<DateTimePicker onYearChange={mockOnYearChange} />) - const input = screen.getByRole("textbox") - await user.click(input) - const yearInputUp = document.querySelector(".numInputWrapper > .arrowUp") - await user.click(yearInputUp) - expect(mockOnYearChange).toHaveBeenCalled() - }) - - test("executes an onMonthChange handler when the user changes the month by clicking an arrow", async () => { - const user = userEvent.setup() - render(<DateTimePicker onMonthChange={mockOnMonthChange} />) - const input = screen.getByRole("textbox") - await user.click(input) - const nextMonthButton = document.querySelector(".flatpickr-next-month") - await user.click(nextMonthButton) - expect(mockOnMonthChange).toHaveBeenCalled() - }) - - test("renders a className as passed", async () => { - render(<DateTimePicker className="my-custom-class" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveClass("my-custom-class") - }) - - test("renders other props as passed", async () => { - render(<DateTimePicker data-lolol="527" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute("data-lolol", "527") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/datetimepicker.scss b/libs_deprecated/juno-ui-components/src/components/DateTimePicker/datetimepicker.scss deleted file mode 100644 index 089f71a3c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/datetimepicker.scss +++ /dev/null @@ -1,831 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -.theme-dark { - .juno-datetimepicker-input-default { - background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'rgb(222%2C%20223%2C%20224)'%3E%3Cpath%20d%3D'M20%203h-1V1h-2v2H7V1H5v2H4c-1.1%200-2%20.9-2%202v16c0%201.1.9%202%202%202h16c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2zm0%2018H4V8h16v13z'%2F%3E%3C%2Fsvg%3E"); - } - .juno-datetimepicker-input-timepicker { - background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'rgb(222%2C%20223%2C%20224)'%3E%3Cpath%20d%3D'M11.99%202C6.47%202%202%206.48%202%2012s4.47%2010%209.99%2010C17.52%2022%2022%2017.52%2022%2012S17.52%202%2011.99%202zM12%2020c-4.42%200-8-3.58-8-8s3.58-8%208-8%208%203.58%208%208-3.58%208-8%208z'%2F%3E%3Cpath%20d%3D'M12.5%207H11v6l5.25%203.15.75-1.23-4.5-2.67z'%2F%3E%3C%2Fsvg%3E"); - } -} - -.theme-light { - .juno-datetimepicker-input-default { - background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'rgb(64%2C%2064%2C%2064)'%3E%3Cpath%20d%3D'M20%203h-1V1h-2v2H7V1H5v2H4c-1.1%200-2%20.9-2%202v16c0%201.1.9%202%202%202h16c1.1%200%202-.9%202-2V5c0-1.1-.9-2-2-2zm0%2018H4V8h16v13z'%2F%3E%3C%2Fsvg%3E"); - } - .juno-datetimepicker-input-timepicker { - background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'24'%20height%3D'24'%20viewBox%3D'0%200%2024%2024'%20fill%3D'rgb(64%2C%2064%2C%2064)'%3E%3Cpath%20d%3D'M11.99%202C6.47%202%202%206.48%202%2012s4.47%2010%209.99%2010C17.52%2022%2022%2017.52%2022%2012S17.52%202%2011.99%202zM12%2020c-4.42%200-8-3.58-8-8s3.58-8%208-8%208%203.58%208%208-3.58%208-8%208z'%2F%3E%3Cpath%20d%3D'M12.5%207H11v6l5.25%203.15.75-1.23-4.5-2.67z'%2F%3E%3C%2Fsvg%3E"); - } -} - -.flatpickr-calendar { - background: transparent; - color: var(--color-text-default); - opacity: 0; - display: none; - text-align: center; - visibility: hidden; - padding: 0; - -webkit-animation: none; - animation: none; - direction: ltr; - border: 0; - font-size: 0.875rem; - line-height: 1.5rem; - border-radius: 5px; - position: absolute; - width: 307.875px; - -webkit-box-sizing: border-box; - box-sizing: border-box; - -ms-touch-action: manipulation; - touch-action: manipulation; - background: var(--color-datepicker-calendar-bg); - // -webkit-box-shadow: 1px 0 0 #20222c, -1px 0 0 #20222c, 0 1px 0 #20222c, 0 -1px 0 #20222c, 0 3px 13px rgba(0,0,0,0.08); - // box-shadow: 1px 0 0 #20222c, -1px 0 0 #20222c, 0 1px 0 #20222c, 0 -1px 0 #20222c, 0 3px 13px rgba(0,0,0,0.08); -} -.flatpickr-calendar.open, -.flatpickr-calendar.inline { - opacity: 1; - max-height: 640px; - visibility: visible; -} -.flatpickr-calendar.open { - display: inline-block; - z-index: 99999; - margin-top: 2px; -} -.flatpickr-calendar.open:not(.inline) { - &[style]:not(.inline) { - top: auto !important; - left: auto !important; - } -} -.flatpickr-calendar.animate.open { - -webkit-animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1); - animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.flatpickr-calendar.inline { - display: block; - position: relative; - top: 2px; -} -.flatpickr-calendar.static { - position: absolute; - top: calc(100% + 2px); -} -.flatpickr-calendar.static.open { - z-index: 999; - display: block; -} -.flatpickr-calendar.multiMonth - .flatpickr-days - .dayContainer:nth-child(n + 1) - .flatpickr-day.inRange:nth-child(7n + 7) { - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -.flatpickr-calendar.multiMonth - .flatpickr-days - .dayContainer:nth-child(n + 2) - .flatpickr-day.inRange:nth-child(7n + 1) { - -webkit-box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6; - box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6; -} -.flatpickr-calendar .hasWeeks .dayContainer, -.flatpickr-calendar .hasTime .dayContainer { - border-bottom: 0; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.flatpickr-calendar .hasWeeks .dayContainer { - border-left: 0; -} -.flatpickr-calendar.hasTime .flatpickr-time { - height: 40px; - // border-top: 1px solid #20222c; -} -.flatpickr-calendar.noCalendar.hasTime .flatpickr-time { - height: auto; -} -// .flatpickr-calendar:before, -// .flatpickr-calendar:after { -// position: absolute; -// display: block; -// pointer-events: none; -// border: solid transparent; -// content: ''; -// height: 0; -// width: 0; -// left: 22px; -// } -// .flatpickr-calendar.rightMost:before, -// .flatpickr-calendar.arrowRight:before, -// .flatpickr-calendar.rightMost:after, -// .flatpickr-calendar.arrowRight:after { -// left: auto; -// right: 22px; -// } -// .flatpickr-calendar.arrowCenter:before, -// .flatpickr-calendar.arrowCenter:after { -// left: 50%; -// right: 50%; -// } -// .flatpickr-calendar:before { -// border-width: 5px; -// margin: 0 -5px; -// } -// .flatpickr-calendar:after { -// border-width: 4px; -// margin: 0 -4px; -// } -// .flatpickr-calendar.arrowTop:before, -// .flatpickr-calendar.arrowTop:after { -// bottom: 100%; -// } -// .flatpickr-calendar.arrowTop:before { -// border-bottom-color: #20222c; -// } -// .flatpickr-calendar.arrowTop:after { -// border-bottom-color: #3f4458; -// } -// .flatpickr-calendar.arrowBottom:before, -// .flatpickr-calendar.arrowBottom:after { -// top: 100%; -// } -// .flatpickr-calendar.arrowBottom:before { -// border-top-color: #20222c; -// } -// .flatpickr-calendar.arrowBottom:after { -// border-top-color: #3f4458; -//} -.flatpickr-calendar:focus { - outline: 0; -} -.flatpickr-wrapper { - position: relative; - display: inline-block; -} -.flatpickr-months { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -} -.flatpickr-months .flatpickr-month { - background: var(--color-datepicker-calendar-bg); - color: #fff; - fill: #fff; - height: 34px; - line-height: 1; - text-align: center; - position: relative; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - overflow: hidden; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; -} -.flatpickr-months .flatpickr-prev-month, -.flatpickr-months .flatpickr-next-month { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - text-decoration: none; - cursor: pointer; - position: absolute; - top: 0; - height: 34px; - padding: 10px; - z-index: 3; - color: #fff; - fill: #fff; -} -.flatpickr-months .flatpickr-prev-month.flatpickr-disabled, -.flatpickr-months .flatpickr-next-month.flatpickr-disabled { - display: none; -} -.flatpickr-months .flatpickr-prev-month i, -.flatpickr-months .flatpickr-next-month i { - position: relative; -} -.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month, -.flatpickr-months .flatpickr-next-month.flatpickr-prev-month { - /* - /*rtl:begin:ignore*/ - /* - */ - left: 0; - /* - /*rtl:end:ignore*/ - /* - */ -} -/* - /*rtl:begin:ignore*/ -/* - /*rtl:end:ignore*/ -.flatpickr-months .flatpickr-prev-month.flatpickr-next-month, -.flatpickr-months .flatpickr-next-month.flatpickr-next-month { - /* - /*rtl:begin:ignore*/ - /* - */ - right: 0; - /* - /*rtl:end:ignore*/ - /* - */ -} -/* - /*rtl:begin:ignore*/ -/* - /*rtl:end:ignore*/ -.flatpickr-months .flatpickr-prev-month:hover, -.flatpickr-months .flatpickr-next-month:hover { - color: #eee; -} -.flatpickr-months .flatpickr-prev-month:hover svg, -.flatpickr-months .flatpickr-next-month:hover svg { - fill: #f64747; -} -.flatpickr-months .flatpickr-prev-month svg, -.flatpickr-months .flatpickr-next-month svg { - width: 14px; - height: 14px; -} -.flatpickr-months .flatpickr-prev-month svg path, -.flatpickr-months .flatpickr-next-month svg path { - -webkit-transition: fill 0.1s; - transition: fill 0.1s; - fill: inherit; -} -.numInputWrapper { - position: relative; - height: auto; -} -.numInputWrapper input, -.numInputWrapper span { - display: inline-block; -} -.numInputWrapper input { - width: 100%; -} -.numInputWrapper input::-ms-clear { - display: none; -} -.numInputWrapper input::-webkit-outer-spin-button, -.numInputWrapper input::-webkit-inner-spin-button { - margin: 0; - -webkit-appearance: none; -} -.numInputWrapper span { - position: absolute; - right: 0; - width: 14px; - padding: 0 4px 0 2px; - height: 50%; - line-height: 50%; - opacity: 0; - cursor: pointer; - border: 1px solid rgba(255, 255, 255, 0.15); - -webkit-box-sizing: border-box; - box-sizing: border-box; -} -.numInputWrapper span:hover { - background: rgba(192, 187, 167, 0.1); -} -.numInputWrapper span:active { - background: rgba(192, 187, 167, 0.2); -} -.numInputWrapper span:after { - display: block; - content: ""; - position: absolute; -} -.numInputWrapper span.arrowUp { - top: 0; - border-bottom: 0; -} -.numInputWrapper span.arrowUp:after { - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-bottom: 4px solid rgba(255, 255, 255, 0.6); - top: 26%; -} -.numInputWrapper span.arrowDown { - top: 50%; -} -.numInputWrapper span.arrowDown:after { - border-left: 4px solid transparent; - border-right: 4px solid transparent; - border-top: 4px solid rgba(255, 255, 255, 0.6); - top: 40%; -} -.numInputWrapper span svg { - width: inherit; - height: auto; -} -.numInputWrapper span svg path { - fill: rgba(255, 255, 255, 0.5); -} -.numInputWrapper:hover { - background: rgba(192, 187, 167, 0.05); -} -.numInputWrapper:hover span { - opacity: 1; -} -.flatpickr-current-month { - font-size: 135%; - line-height: inherit; - font-weight: 300; - color: inherit; - position: absolute; - width: 75%; - left: 12.5%; - padding: 7.48px 0 0 0; - line-height: 1; - height: 34px; - display: inline-block; - text-align: center; - -webkit-transform: translate3d(0px, 0px, 0px); - transform: translate3d(0px, 0px, 0px); -} -.flatpickr-current-month span.cur-month { - font-family: inherit; - font-weight: 700; - color: inherit; - display: inline-block; - margin-left: 0.5ch; - padding: 0; -} -.flatpickr-current-month span.cur-month:hover { - background: rgba(192, 187, 167, 0.05); -} -.flatpickr-current-month .numInputWrapper { - width: 6ch; - width: 7ch\0; - display: inline-block; -} -.flatpickr-current-month .numInputWrapper span.arrowUp:after { - border-bottom-color: #fff; -} -.flatpickr-current-month .numInputWrapper span.arrowDown:after { - border-top-color: #fff; -} -.flatpickr-current-month input.cur-year { - background: transparent; - -webkit-box-sizing: border-box; - box-sizing: border-box; - color: inherit; - cursor: text; - padding: 0 0 0 0.5ch; - margin: 0; - display: inline-block; - font-size: inherit; - font-family: inherit; - font-weight: 300; - line-height: inherit; - height: auto; - border: 0; - border-radius: 0; - vertical-align: initial; - -webkit-appearance: textfield; - -moz-appearance: textfield; - appearance: textfield; -} -.flatpickr-current-month input.cur-year:focus { - outline: 0; -} -.flatpickr-current-month input.cur-year[disabled], -.flatpickr-current-month input.cur-year[disabled]:hover { - font-size: 100%; - color: rgba(255, 255, 255, 0.5); - background: transparent; - pointer-events: none; -} -.flatpickr-current-month .flatpickr-monthDropdown-months { - appearance: menulist; - background: var(--color-datepicker-calendar-bg); - border: none; - border-radius: 0; - box-sizing: border-box; - cursor: pointer; - font-size: inherit; - font-family: inherit; - font-weight: 300; - height: auto; - line-height: inherit; - margin: -1px 0 0 0; - outline: none; - padding: 0 0 0 0.5ch; - position: relative; - vertical-align: initial; - -webkit-box-sizing: border-box; - -webkit-appearance: menulist; - -moz-appearance: menulist; - width: auto; -} -.flatpickr-current-month .flatpickr-monthDropdown-months:focus, -.flatpickr-current-month .flatpickr-monthDropdown-months:active { - outline: none; -} -.flatpickr-current-month .flatpickr-monthDropdown-months:hover { - background: rgba(192, 187, 167, 0.05); -} -.flatpickr-current-month - .flatpickr-monthDropdown-months - .flatpickr-monthDropdown-month { - background-color: #3f4458; - outline: none; - padding: 0; -} -.flatpickr-weekdays { - background: transparent; - text-align: center; - overflow: hidden; - width: 100%; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -webkit-align-items: center; - -ms-flex-align: center; - align-items: center; - height: 28px; -} -.flatpickr-weekdays .flatpickr-weekdaycontainer { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; -} -span.flatpickr-weekday { - cursor: default; - font-size: 90%; - // background: #3f4458; - color: var(--color-text-default); - line-height: 1; - margin: 0; - text-align: center; - display: block; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - font-weight: bolder; -} -.dayContainer, -.flatpickr-weeks { - padding: 1px 0 0 0; -} -.flatpickr-days { - position: relative; - overflow: hidden; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-align: start; - -webkit-align-items: flex-start; - -ms-flex-align: start; - align-items: flex-start; - width: 307.875px; -} -.flatpickr-days:focus { - outline: 0; -} -.dayContainer { - padding: 0; - outline: 0; - text-align: left; - width: 307.875px; - min-width: 307.875px; - max-width: 307.875px; - -webkit-box-sizing: border-box; - box-sizing: border-box; - display: inline-block; - display: -ms-flexbox; - display: -webkit-box; - display: -webkit-flex; - display: flex; - -webkit-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-wrap: wrap; - -ms-flex-pack: justify; - -webkit-justify-content: space-around; - justify-content: space-around; - -webkit-transform: translate3d(0px, 0px, 0px); - transform: translate3d(0px, 0px, 0px); - opacity: 1; -} -.dayContainer + .dayContainer { - -webkit-box-shadow: -1px 0 0 #20222c; - box-shadow: -1px 0 0 #20222c; -} -.flatpickr-day { - background: none; - border: 1px solid transparent; - border-radius: 150px; - -webkit-box-sizing: border-box; - box-sizing: border-box; - color: var(--color-text-default); - cursor: pointer; - font-weight: 400; - width: 14.2857143%; - -webkit-flex-basis: 14.2857143%; - -ms-flex-preferred-size: 14.2857143%; - flex-basis: 14.2857143%; - max-width: 39px; - height: 39px; - line-height: 39px; - margin: 0; - display: inline-block; - position: relative; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; - text-align: center; -} -.flatpickr-day.inRange, -.flatpickr-day.prevMonthDay.inRange, -.flatpickr-day.nextMonthDay.inRange, -.flatpickr-day.today.inRange, -.flatpickr-day.prevMonthDay.today.inRange, -.flatpickr-day.nextMonthDay.today.inRange, -.flatpickr-day:hover, -.flatpickr-day.prevMonthDay:hover, -.flatpickr-day.nextMonthDay:hover, -.flatpickr-day:focus, -.flatpickr-day.prevMonthDay:focus, -.flatpickr-day.nextMonthDay:focus { - cursor: pointer; - outline: 0; - background: #646c8c; - border-color: #646c8c; -} -.flatpickr-day.today { - border-color: var(--color-text-default); -} -.flatpickr-day.today:hover, -.flatpickr-day.today:focus { - border-color: var(--color-text-default); - background: #eee; - color: var(--color-text-default); -} -.flatpickr-day.selected, -.flatpickr-day.startRange, -.flatpickr-day.endRange, -.flatpickr-day.selected.inRange, -.flatpickr-day.startRange.inRange, -.flatpickr-day.endRange.inRange, -.flatpickr-day.selected:focus, -.flatpickr-day.startRange:focus, -.flatpickr-day.endRange:focus, -.flatpickr-day.selected:hover, -.flatpickr-day.startRange:hover, -.flatpickr-day.endRange:hover, -.flatpickr-day.selected.prevMonthDay, -.flatpickr-day.startRange.prevMonthDay, -.flatpickr-day.endRange.prevMonthDay, -.flatpickr-day.selected.nextMonthDay, -.flatpickr-day.startRange.nextMonthDay, -.flatpickr-day.endRange.nextMonthDay { - background: var(--color-accent); - -webkit-box-shadow: none; - box-shadow: none; - color: #fff; - border-color: var(--color-accent); -} -.flatpickr-day.selected.startRange, -.flatpickr-day.startRange.startRange, -.flatpickr-day.endRange.startRange { - border-radius: 50px 0 0 50px; -} -.flatpickr-day.selected.endRange, -.flatpickr-day.startRange.endRange, -.flatpickr-day.endRange.endRange { - border-radius: 0 50px 50px 0; -} -.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n + 1)), -.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n + 1)), -.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n + 1)) { - -webkit-box-shadow: -10px 0 0 #80cbc4; - box-shadow: -10px 0 0 #80cbc4; -} -.flatpickr-day.selected.startRange.endRange, -.flatpickr-day.startRange.startRange.endRange, -.flatpickr-day.endRange.startRange.endRange { - border-radius: 50px; -} -.flatpickr-day.inRange { - border-radius: 0; - -webkit-box-shadow: -5px 0 0 #646c8c, 5px 0 0 #646c8c; - box-shadow: -5px 0 0 #646c8c, 5px 0 0 #646c8c; -} -.flatpickr-day.flatpickr-disabled, -.flatpickr-day.flatpickr-disabled:hover, -.flatpickr-day.prevMonthDay, -.flatpickr-day.nextMonthDay, -.flatpickr-day.notAllowed, -.flatpickr-day.notAllowed.prevMonthDay, -.flatpickr-day.notAllowed.nextMonthDay { - color: rgba(255, 255, 255, 0.3); - background: transparent; - border-color: transparent; - cursor: default; -} -.flatpickr-day.flatpickr-disabled, -.flatpickr-day.flatpickr-disabled:hover { - cursor: not-allowed; - color: rgba(255, 255, 255, 0.1); -} -.flatpickr-day.week.selected { - border-radius: 0; - -webkit-box-shadow: -5px 0 0 #80cbc4, 5px 0 0 #80cbc4; - box-shadow: -5px 0 0 #80cbc4, 5px 0 0 #80cbc4; -} -.flatpickr-day.hidden { - visibility: hidden; -} -.rangeMode .flatpickr-day { - margin-top: 1px; -} -.flatpickr-weekwrapper { - float: left; -} -.flatpickr-weekwrapper .flatpickr-weeks { - padding: 0 12px; - -webkit-box-shadow: 1px 0 0 #20222c; - box-shadow: 1px 0 0 #20222c; -} -.flatpickr-weekwrapper .flatpickr-weekday { - float: none; - width: 100%; - line-height: 28px; -} -.flatpickr-weekwrapper span.flatpickr-day, -.flatpickr-weekwrapper span.flatpickr-day:hover { - display: block; - width: 100%; - max-width: none; - color: rgba(255, 255, 255, 0.3); - background: transparent; - cursor: default; - border: none; -} -.flatpickr-innerContainer { - display: block; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-sizing: border-box; - box-sizing: border-box; - overflow: hidden; -} -.flatpickr-rContainer { - display: inline-block; - padding: 0; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} -.flatpickr-time { - text-align: center; - outline: 0; - display: block; - height: 0; - line-height: 40px; - max-height: 40px; - -webkit-box-sizing: border-box; - box-sizing: border-box; - overflow: hidden; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; -} -.flatpickr-time:after { - content: ""; - display: table; - clear: both; -} -.flatpickr-time .numInputWrapper { - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; - width: 40%; - height: 40px; - float: left; -} -.flatpickr-time .numInputWrapper span.arrowUp:after { - border-bottom-color: rgba(255, 255, 255, 0.95); -} -.flatpickr-time .numInputWrapper span.arrowDown:after { - border-top-color: rgba(255, 255, 255, 0.95); -} -.flatpickr-time.hasSeconds .numInputWrapper { - width: 26%; -} -.flatpickr-time.time24hr .numInputWrapper { - width: 49%; -} -.flatpickr-time input { - background: transparent; - -webkit-box-shadow: none; - box-shadow: none; - border: 0; - border-radius: 0; - text-align: center; - margin: 0; - padding: 0; - height: inherit; - line-height: inherit; - color: var(--color-text-default); - font-size: 14px; - position: relative; - -webkit-box-sizing: border-box; - box-sizing: border-box; - -webkit-appearance: textfield; - -moz-appearance: textfield; - appearance: textfield; -} -.flatpickr-time input.flatpickr-hour { - font-weight: bold; -} -.flatpickr-time input.flatpickr-minute, -.flatpickr-time input.flatpickr-second { - font-weight: 400; -} -.flatpickr-time input:focus { - outline: 0; - border: 0; -} -.flatpickr-time .flatpickr-time-separator, -.flatpickr-time .flatpickr-am-pm { - height: inherit; - float: left; - line-height: inherit; - color: rgba(255, 255, 255, 0.95); - font-weight: bold; - width: 2%; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-align-self: center; - -ms-flex-item-align: center; - align-self: center; -} -.flatpickr-time .flatpickr-am-pm { - outline: 0; - width: 18%; - cursor: pointer; - text-align: center; - font-weight: 400; -} -.flatpickr-time input:hover, -.flatpickr-time .flatpickr-am-pm:hover, -.flatpickr-time input:focus, -.flatpickr-time .flatpickr-am-pm:focus { - background: #6a7395; -} -.flatpickr-input[readonly] { - cursor: pointer; -} -@-webkit-keyframes fpFadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} -@keyframes fpFadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} diff --git a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/index.js b/libs_deprecated/juno-ui-components/src/components/DateTimePicker/index.js deleted file mode 100644 index 8b93e8fd1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/DateTimePicker/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { DateTimePicker } from "./DateTimePicker.component.js" diff --git a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.component.js b/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.component.js deleted file mode 100644 index b451b6d2f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.component.js +++ /dev/null @@ -1,232 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { NativeSelect } from "../NativeSelect/NativeSelect.component" -import { NativeSelectOption } from "../NativeSelectOption/NativeSelectOption.component" -import { TextInput } from "../TextInput/TextInput.component" -import { Icon } from "../Icon/Icon.component" - -const wrapperStyles = ` - jn-flex - jn-relative - jn-p-px - jn-border - jn-rounded - jn-bg-theme-filter-input -` - -const defaultWrapperStyles = ` - jn-border-theme-filter-input -` - -const errorWrapperStyles = ` - jn-border-theme-error -` - -const selectStyles = ` - jn-rounded-r-none -` - -const textInputStyles = ` - jn-grow - jn-rounded-l-none - jn-pr-16 - !jn-bg-theme-filter-input-textinput - focus:jn-z-40 -` - -const iconWrapperStyles = ` - jn-absolute - jn-flex - jn-right-2 - jn-top-1.5 - jn-z-50 -` - -/** --- Deprectated. For new implementations, use InputGroup and combine/compose input components as you need them. -- -A special Input to select key and value of a filter. -*/ -export const FilterInput = ({ - keyLabel, - options, - valueLabel, - className, - selectedFilterKey, - onSelectedFilterKeyChange, - filterValue, - valuePlaceholder, - onFilterValueChange, - onClear, - onKeyPress, - onFilter, - loading, - error, - ...props -}) => { - const [selectedFilter, setSelectedFilter] = useState(selectedFilterKey) - const [value, setValue] = useState(filterValue) - const [isLoading, setIsLoading] = useState(options.length < 1 || loading) - const [hasError, setHasError] = useState(error) - - useEffect(() => { - setValue(filterValue) - }, [filterValue]) - - useEffect(() => { - setSelectedFilter(selectedFilterKey) - }, [selectedFilterKey]) - - // Reset the (text input) value whenever the component is loading: - useEffect(() => { - if (options.length < 1 || loading) { - setIsLoading(true) - setValue("") - } else { - setIsLoading(false) - } - }, [options, loading]) - - useEffect(() => { - setHasError(error) - }, [error]) - - // Reset the (text input) value whenever the selected Filter key changes: - const handleSelectedFilterChange = (event) => { - setSelectedFilter(event.target.value) - setValue("") - onSelectedFilterKeyChange && onSelectedFilterKeyChange(event) - } - - const handleFilterValueChange = (event) => { - setValue(event.target.value) - onFilterValueChange && onFilterValueChange(event) - } - - const handleClearClick = (event) => { - setValue("") - onClear && onClear(event) - } - - const handleFilterClick = () => { - onFilter && onFilter(value) - } - - const handleKeyPress = (event) => { - if (event.key === "Enter" && onFilter) { - onFilter && onFilter(value) - } - onKeyPress && onKeyPress(event) - } - - return ( - <div - className={`juno-filter-input ${wrapperStyles} ${ - isLoading ? "juno-filter-input-loading " : "" - } ${hasError ? "juno-filter-input-error " : ""} ${ - hasError ? errorWrapperStyles : defaultWrapperStyles - } ${className}`} - {...props} - > - <div> - <NativeSelect - className={`juno-filter-input-select ${selectStyles}`} - aria-label={keyLabel} - value={selectedFilter} - onChange={handleSelectedFilterChange} - loading={isLoading} - error={hasError} - > - // First "Placeholder" option: - <NativeSelectOption label={keyLabel || "Select Filter"} value="" /> - // Options representing actual filter key values: - {options.map((option, i) => ( - <NativeSelectOption - label={option.label} - value={option.key} - key={`${i}`} - {...option} - /> - ))} - </NativeSelect> - </div> - <TextInput - value={value} - className={`${textInputStyles}`} - aria-label={valueLabel} - onChange={handleFilterValueChange} - onKeyPress={handleKeyPress} - disabled={isLoading || hasError} - placeholder={isLoading ? "Loading Filter Options…" : valuePlaceholder} - /> - <div className={`${iconWrapperStyles}`}> - {value && value.length ? ( - <Icon - icon="close" - title="Clear" - size="18" - className={`jn-mr-2`} - onClick={handleClearClick} - /> - ) : null} - <Icon - icon="filterAlt" - title="Filter" - disabled={isLoading || hasError} - onClick={handleFilterClick} - /> - </div> - </div> - ) -} - -FilterInput.propTypes = { - /** The label to display on the Filter Key Select */ - keyLabel: PropTypes.string, - /** The options for the Filter Select: `[{Label: "Filter 1", key: "filter-1"}, {...}]` - The array MUST have a length in order for the component to render. - */ - options: PropTypes.arrayOf(PropTypes.object), - /** The key of the current filter */ - selectedFilterKey: PropTypes.string, - /** Pass a handler to be executed when the filter key changes */ - onSelectedFilterKeyChange: PropTypes.func, - /** The aria-label of the Filter Value Text Input */ - valueLabel: PropTypes.string, // TODO -> valueLabel - /** The current value of the Filter Input */ - filterValue: PropTypes.string, - /** Optional: pass a placeholder for the filter value text input */ - valuePlaceholder: PropTypes.string, - /** Pass a handler to be executed when the filter value changes */ - onFilterValueChange: PropTypes.func, - /** Pass a handler to execute when the Filter Value Clear button is clicked */ - onClear: PropTypes.func, - /** Whether the filter is currently loading */ - loading: PropTypes.bool, - /** Pass a className to the wrapping element */ - className: PropTypes.string, - /** Pass a handler to execute when the Filter Value Filter button is clicked */ - onFilter: PropTypes.func, - /** Whether the FilterInput has an error */ - error: PropTypes.bool, -} - -FilterInput.defaultProps = { - keyLabel: "Select Filter", - options: [], - selectedFilterKey: "", - onSelectedFilterKeyChange: undefined, - valueLabel: "Filter by Value", - filterValue: "", - valuePlaceholder: "", - onFilterValueChange: undefined, - onClear: undefined, - onFilter: undefined, - loading: false, - className: "", - error: false, -} diff --git a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.stories.js b/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.stories.js deleted file mode 100644 index 462de25f3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.stories.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { FilterInput } from './index.js'; - -export default { - title: 'Deprecated/Filter/FilterInput', - component: FilterInput, - argTypes: {}, -}; - -export const Default = { - args: { - valuePlaceholder: 'Enter a value', - options: [ - { label: 'Filter 1', key: 'filter-1' }, - { label: 'Filter 2', key: 'filter-2', disabled: true }, - { label: 'Filter 3', key: 'filter-3' }, - ], - }, -}; - -export const Preselected = { - args: { - keyLabel: 'Select a fancy Filter', - selectedFilterKey: 'filter-2', - options: [ - { label: 'Filter 1', key: 'filter-1' }, - { label: 'Filter 2', key: 'filter-2' }, - { label: 'Filter 3', key: 'filter-3' }, - ], - }, -}; - -export const Loading = { - args: { - options: [], - loading: true, - }, -}; - -export const WithError = { - args: { - options: [], - error: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.test.js b/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.test.js deleted file mode 100644 index 68cca4ea4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterInput/FilterInput.test.js +++ /dev/null @@ -1,281 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen, fireEvent } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { FilterInput } from "./index" - -describe("FilterInput", () => { - test("renders a FilterInput", async () => { - render(<FilterInput data-testid="filter-input" />) - expect(screen.getByTestId("filter-input")).toBeInTheDocument() - expect(screen.getByTestId("filter-input")).toHaveClass("juno-filter-input") - }) - - test("renders a FilterInput with a Select and a TextInput", async () => { - render(<FilterInput />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toBeInTheDocument() - }) - - test("renders a Select with an aria-label as passed", async () => { - render(<FilterInput keyLabel={"my select"} />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveAttribute( - "aria-label", - "my select" - ) - }) - - test("renders a Select with a default option selected if no selectedFilterKey is passed", async () => { - render(<FilterInput />) - expect( - screen.getByRole("option", { name: "Select Filter" }) - ).toBeInTheDocument() - expect(screen.getByRole("option", { name: "Select Filter" }).selected).toBe( - true - ) - }) - - test("renders a Select with a default option as passed", async () => { - render(<FilterInput keyLabel="My Custom Key Label" />) - expect( - screen.getByRole("option", { name: "My Custom Key Label" }) - ).toBeInTheDocument() - expect( - screen.getByRole("option", { name: "My Custom Key Label" }).selected - ).toBe(true) - }) - - test("renders a select with options and values as passed", async () => { - render( - <FilterInput - options={[ - { label: "option 1", value: "option-1" }, - { label: "option 2", value: "option-2" }, - ]} - /> - ) - expect(screen.getByRole("option", { name: "option 1" })).toHaveValue( - "option-1" - ) - expect(screen.getByRole("option", { name: "option 2" })).toHaveValue( - "option-2" - ) - }) - - test("renders a select with arbitrary props for options", async () => { - render( - <FilterInput - options={[ - { label: "option 1", value: "option-1", disabled: true }, - { label: "option 2", value: "option-2" }, - ]} - /> - ) - expect(screen.getByRole("option", { name: "option 1" })).toHaveValue( - "option-1" - ) - expect(screen.getByRole("option", { name: "option 1" })).toBeDisabled() - }) - - test("renders a text input with an aria-label as passed", async () => { - render(<FilterInput valueLabel={"my value input"} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "aria-label", - "my value input" - ) - }) - - test("renders a text input with a placeholder as passed", async () => { - render( - <FilterInput - options={[ - { label: "option 1", value: "option-1", disabled: true }, - { label: "option 2", value: "option-2" }, - ]} - valuePlaceholder={"my value placeholder"} - /> - ) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "placeholder", - "my value placeholder" - ) - }) - - test("renders a selected filter as passed", async () => { - const filterOptions = [ - { label: "OS", value: "byOs" }, - { label: "Region", value: "byRegion" }, - ] - render(<FilterInput options={filterOptions} selectedFilterKey="byRegion" />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("option", { name: "Region" }).selected).toBe(true) - }) - - test("allows users to change the filter key", async () => { - const filters = [ - { label: "OS", value: "byOs" }, - { label: "Region", value: "byRegion" }, - { label: "Time Zone", value: "byTimezone" }, - ] - render(<FilterInput options={filters} />) - await userEvent.selectOptions( - screen.getByRole("combobox"), - screen.getByRole("option", { name: "Time Zone" }) - ) - expect(screen.getByRole("option", { name: "Time Zone" }).selected).toBe( - true - ) - }) - - test("should reset the filter value when the selected filter key changes", async () => { - const filters = [ - { label: "OS", value: "byOs" }, - { label: "Region", value: "byRegion" }, - { label: "Time Zone", value: "byTimezone" }, - ] - render(<FilterInput options={filters} filterValue="MacOS" />) - expect(screen.getByRole("textbox")).toHaveValue("MacOS") - await userEvent.selectOptions( - screen.getByRole("combobox"), - screen.getByRole("option", { name: "Region" }) - ) - expect(screen.getByRole("textbox")).toHaveValue("") - }) - - test("executes a handler as passed when selected filter key changes", async () => { - const handleSelectedFilterChange = jest.fn() - const filters = [ - { label: "OS", key: "byOs" }, - { label: "Region", key: "byRegion" }, - { label: "Time Zone", key: "byTimezone" }, - ] - render( - <FilterInput - options={filters} - selectedFilterKey="byRegion" - onSelectedFilterKeyChange={handleSelectedFilterChange} - /> - ) - expect(screen.getByRole("option", { name: "Region" }).selected).toBe(true) - await userEvent.selectOptions( - screen.getByRole("combobox"), - screen.getByRole("option", { name: "OS" }) - ) - expect(screen.getByRole("option", { name: "OS" }).selected).toBe(true) - expect(handleSelectedFilterChange).toHaveBeenCalledTimes(1) - }) - - test("renders a FilterInput with a value as passed", async () => { - const opts = [{ label: "something", key: "something" }] - render(<FilterInput options={opts} filterValue="123abc" />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("123abc") - }) - - test("renders a Close button when the Input has a value", async () => { - const opts = [{ label: "something", key: "something" }] - render(<FilterInput options={opts} filterValue="123" />) - expect(screen.getByTitle("Clear")).toBeInTheDocument() - }) - - test("executes a handler as passed when the input value changes", async () => { - const opts = [{ label: "A Filter", key: "a-filter" }] - const handleFilterValueChange = jest.fn() - render( - <FilterInput - options={opts} - onFilterValueChange={handleFilterValueChange} - /> - ) - await userEvent.type(screen.getByRole("textbox"), "987") - expect(handleFilterValueChange).toHaveBeenCalledTimes(3) - }) - - test("empties the field when Clear button is clicked", async () => { - const opts = [{ label: "something", key: "something" }] - render(<FilterInput options={opts} filterValue="abc" />) - expect(screen.getByTitle("Clear")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("abc") - await userEvent.click(screen.getByTitle("Clear")) - expect(screen.getByRole("textbox")).toHaveValue("") - }) - - test("executes onFilter handler as passed when Filter icon is clicked and return the text input value", async () => { - const handleFilter = jest.fn() - const opts = [{ label: "A Filter", key: "a-filter" }] - render( - <FilterInput options={opts} filterValue="abc" onFilter={handleFilter} /> - ) - await userEvent.click(screen.getByTitle("Filter")) - expect(handleFilter).toHaveBeenCalledTimes(1) - expect(handleFilter).toHaveBeenCalledWith("abc") - }) - - test("executes onFilter handler as passed when the input has focus and the user presses enter and return the text input value", async () => { - const handleFilter = jest.fn() - const opts = [{ label: "A Filter", key: "a-filter" }] - render( - <FilterInput options={opts} filterValue="abc" onFilter={handleFilter} /> - ) - await userEvent.type(screen.getByRole("textbox"), "{enter}") - expect(handleFilter).toHaveBeenCalledTimes(1) - expect(handleFilter).toHaveBeenCalledWith("abc") - }) - - test("renders loading filter input as passed", async () => { - render(<FilterInput loading />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByRole("textbox")).toBeDisabled() - expect(screen.getByRole("progressbar")).toBeInTheDocument() - }) - - test("renders a loading filter if passed options are present but empty", async () => { - const filters = [] - render(<FilterInput options={filters} />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByRole("textbox")).toBeDisabled() - expect(screen.getByRole("progressbar")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeDisabled() - }) - - test("renders loading filter as passed even if options are present and not empty", async () => { - const opts = [{ label: "A Filter", key: "a-filter" }] - render(<FilterInput options={opts} loading />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByRole("textbox")).toBeDisabled() - expect(screen.getByRole("progressbar")).toBeInTheDocument() - }) - - test("renders a filter input with an error as passed", async () => { - const opts = [{ label: "A Filter", key: "a-filter" }] - render(<FilterInput options={opts} error />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByRole("textbox")).toBeDisabled() - expect(screen.getByTitle("Error")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeDisabled() - }) - - test("renders a custom class to the row as passed", async () => { - render( - <FilterInput data-testid="filter-input" className="my-custom-class" /> - ) - expect(screen.getByTestId("filter-input")).toBeInTheDocument() - expect(screen.getByTestId("filter-input")).toHaveClass("my-custom-class") - }) - - test("renders all props as passed", async () => { - render(<FilterInput data-testid="filter-input" data-lolol="some-prop" />) - expect(screen.getByTestId("filter-input")).toBeInTheDocument() - expect(screen.getByTestId("filter-input")).toHaveAttribute( - "data-lolol", - "some-prop" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/FilterInput/index.js b/libs_deprecated/juno-ui-components/src/components/FilterInput/index.js deleted file mode 100644 index bcf866f65..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterInput/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { FilterInput } from "./FilterInput.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.component.js b/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.component.js deleted file mode 100644 index 3fbb74e5f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.component.js +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" -import { Icon } from "../Icon/Icon.component.js" - -const filterpillStyles = ` - jn-inline-flex - jn-basis-auto - jn-shrink - jn-items-center - jn-flex-nowrap - jn-text-xs - jn-p-px - jn-border - jn-rounded - jn-mr-2 - jn-border-theme-filter-pill - last:jn-mr-0 -` - -const filterkeyStyles = ` - jn-bg-theme-filter-pill-key - jn-px-1 - jn-py-0.5 - jn-rounded-sm - jn-text-theme-high - jn-inline-block -` - -const filtervalueStyles = ` - jn-px-1 - jn-py-0.5 - jn-text-theme-high - jn-inline-block -` - -/** --- Deprecated. For new implementations, use Pill instead.--\n -A Pill to represent Key and Value of a filter. Can be closed to un-apply the filter represented. -Mostly to be used inside a Filters component in conjunction with FilterInput. */ -export const FilterPill = ({ - uid, - filterKey, - filterKeyLabel, - filterValue, - filterValueLabel, - onClose, - className, - ...props -}) => { - const handleCloseClick = () => { - onClose && onClose(uid || filterKey) - } - - return ( - <div - className={`juno-filterpill ${filterpillStyles} ${className}`} - {...props} - > - <span className={`${filterkeyStyles}`}> - {filterKeyLabel || filterKey} - </span> - <span className={`${filtervalueStyles}`}> - {filterValueLabel || filterValue} - </span> - <Icon icon="close" size="18" onClick={handleCloseClick} /> - </div> - ) -} - -FilterPill.propTypes = { - /** The unique identifier of the pill. Returned by the onClose callback */ - uid: PropTypes.string, - /** The key of the filter the pill represents. Returned by the onClose callback if uid undefined */ - filterKey: PropTypes.string.isRequired, - /** The visible label to describe the filter key. If not set filterKey is used */ - filterKeyLabel: PropTypes.string, - /** The value of filter the pill represents */ - filterValue: PropTypes.string.isRequired, - /** The visible label to describe the filter value. If not set filterValue is used */ - filterValueLabel: PropTypes.string, - /** add custom classNames */ - className: PropTypes.string, - /** Pass a handler to be executed when closing the FilterPill */ - onClose: PropTypes.func, -} - -FilterPill.defaultProps = { - uid: "", - filterKey: "", - filterKeyLabel: "", - filterValue: "", - filterValueLabel: "", - onClose: undefined, - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.stories.js b/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.stories.js deleted file mode 100644 index 32c91be24..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.stories.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { FilterPill } from './index.js'; - -export default { - title: 'Deprecated/Filter/FilterPill', - component: FilterPill, - argTypes: {}, -}; - -export const Default = { - args: { - filterKey: 'os', - filterKeyLabel: 'OS', - filterValue: 'mac_os', - filterValueLabel: 'Mac OS', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.test.js b/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.test.js deleted file mode 100644 index d33543200..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterPill/FilterPill.test.js +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { FilterPill } from "./index" - -describe("FilterPill", () => { - test("renders a FilterPill", async () => { - render( - <FilterPill - data-testid="my-filterpill" - filterKey="TheRequiredKey" - filterValue="TheRequiredValue" - /> - ) - expect(screen.getByTestId("my-filterpill")).toBeInTheDocument() - expect(screen.getByTestId("my-filterpill")).toHaveClass("juno-filterpill") - }) - - test("renders a filter key label as passed", async () => { - render( - <FilterPill - filterKeyLabel="My FilterPill Key" - filterKey="TheRequiredKey" - filterValue="TheRequiredValue" - /> - ) - expect(screen.getByText("My FilterPill Key")).toBeInTheDocument() - }) - - test("renders a filter key if filter key label missing", async () => { - render( - <FilterPill - filterKey="my_filterPill_key" - filterValue="TheRequiredValue" - /> - ) - expect(screen.getByText("my_filterPill_key")).toBeInTheDocument() - }) - - test("renders nothing if filter key label not set", async () => { - // the attribute filterKey and filterValue are required keep them empty to test render nothing - render(<FilterPill data-testid="23" filterKey="" filterValue="" />) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveTextContent("") - }) - - test("renders a filter value label as passed", async () => { - render( - <FilterPill - filterValue="TheRequiredValue" - filterValueLabel="My FilterPill Value" - filterKey="TheRequiredKey" - /> - ) - expect(screen.getByText("My FilterPill Value")).toBeInTheDocument() - }) - - test("renders a filter value if value label missing", async () => { - render( - <FilterPill - filterKey="TheRequiredKey" - filterValue="my_filterPill_value" - /> - ) - expect(screen.getByText("my_filterPill_value")).toBeInTheDocument() - }) - - test("renders nothing if filter value or value label not given", async () => { - // the attribute filterKey and filterValue are required keep them empty to test render nothing - render(<FilterPill data-testid="23" filterKey="" filterValue="" />) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveTextContent("") - }) - - test("an onClose handler is called as passed and returns the uid", () => { - const handleClose = jest.fn() - render( - <FilterPill - uid="uidAbc" - filterKey="TheRequiredKey" - filterValue="TheRequiredValue" - onClose={handleClose} - /> - ) - screen.getByRole("button").click() - expect(handleClose).toHaveBeenCalledTimes(1) - expect(handleClose).toHaveBeenCalledWith("uidAbc") - }) - - test("an onClose handler is called as passed and returns the filterKey if uid missing", () => { - const handleClose = jest.fn() - render( - <FilterPill - filterKey="abc" - filterValue="TheRequiredValue" - onClose={handleClose} - /> - ) - screen.getByRole("button").click() - expect(handleClose).toHaveBeenCalledTimes(1) - expect(handleClose).toHaveBeenCalledWith("abc") - }) - - test("renders a custom className", async () => { - render( - <FilterPill - data-testid="my-filterpill" - filterKey="TheRequiredKey" - filterValue="TheRequiredValue" - className="my-custom-class" - /> - ) - expect(screen.getByTestId("my-filterpill")).toBeInTheDocument() - expect(screen.getByTestId("my-filterpill")).toHaveClass("my-custom-class") - }) - - test("renders all props as passed", async () => { - render( - <FilterPill - data-testid="23" - filterKey="TheRequiredKey" - filterValue="TheRequiredValue" - data-lolol={true} - /> - ) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute("data-lolol") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/FilterPill/index.js b/libs_deprecated/juno-ui-components/src/components/FilterPill/index.js deleted file mode 100644 index fbe4060a0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FilterPill/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { FilterPill } from "./FilterPill.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.component.js b/libs_deprecated/juno-ui-components/src/components/Filters/Filters.component.js deleted file mode 100644 index c7d35d204..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.component.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { FilterInput } from "../FilterInput/FilterInput.component" - -const filterStyles = ` - jn-mb-px - jn-bg-theme-filters - jn-rounded-t - jn-pt-4 - jn-px-4 - jn-pb-2 -` - -const inputWrapperStyles = ` - jn-w-full - jn-flex - jn-mb-2 -` - -const searchWrapperStyles = ` - jn-ml-auto -` - -const filterPillWrapperStyles = ` - jn-flex - jn-flex-wrap -` - -const errortextStyles = ` - jn-text-theme-error - jn-text-sm - jn-mt-[-0.25rem] - jn-mb-1.5 -` -/** --- Deprecated. For new implementations, combine and compose Input Group, Inputs and Pills as needed. -- -A component to hold a FilterInput, resulting FilterPills, and optional SearchBar for any filter-able content. -*/ - -export const Filters = ({ - search, - filters, - selectedFilterKey, - onSelectedFilterKeyChange, - filterValue, - valuePlaceholder, - onFilterValueChange, - onFilter, - onFilterClear, - children, - className, - loading, - error, - errortext, - ...props -}) => { - const [isLoading, setIsLoading] = useState(false) - const [hasError, setHasError] = useState(false) - - useEffect(() => { - // AP: empty string and boolean results in empty string - // "" && true => "" - // This causes hasError to become a string. Further down, hasError is - // passed on to the TextInput, whose type check logs a warning - // To prevet that check the type of errortext instead! - setHasError( - error || (typeof errortext === "string" && errortext.length > 0) - ) - }, [error, errortext]) - - useEffect(() => { - setIsLoading(loading) - }, [loading]) - - return ( - <div - className={`juno-filters ${ - hasError ? "juno-filters-error " : "" - } ${filterStyles} ${className}`} - {...props} - > - <div className={`juno-filters-input-wrapper ${inputWrapperStyles}`}> - {filters && filters.options ? ( - <FilterInput - keyLabel={filters.keyLabel} - valueLabel={filters.valueLabel} - options={filters.options} - selectedFilterKey={selectedFilterKey} - onSelectedFilterKeyChange={onSelectedFilterKeyChange} - filterValue={filterValue} - valuePlaceholder={valuePlaceholder} - onFilterValueChange={onFilterValueChange} - onFilter={onFilter} - onClear={onFilterClear} - loading={isLoading} - error={hasError} - /> - ) : null} - {search ? ( - <div className={`${searchWrapperStyles}`}>{search}</div> - ) : null} - </div> - {hasError && errortext ? ( - <div className={`juno-filters-errortext ${errortextStyles}`}> - {errortext} - </div> - ) : ( - "" - )} - <div className={`${filterPillWrapperStyles}`}>{children}</div> - </div> - ) -} - -Filters.propTypes = { - /** Pass a SearchInput component */ - search: PropTypes.node, - /** Pass an object describing the filter keyLabel, valueLabel, and the available filter options: - `{ keyLabel: "Select a Filter",` - `valueLabel: "Enter a Value",` - `options: [{label: "Filter 1", key: "filter-1"}, {...}] }` - */ - filters: PropTypes.object, - /** The key of the currently selected filter */ - selectedFilterKey: PropTypes.string, - /** Pass a handler to be executed when the filter key changes */ - onSelectedFilterKeyChange: PropTypes.func, - /** The value of the FilterInput */ - filterValue: PropTypes.string, - /** Optional: Pass a placeholder for the filter value text input */ - valuePlaceholder: PropTypes.string, - /** Pass a handler to be executed whenever the value of the filter value input changes */ - onFilterValueChange: PropTypes.func, - /** Pass a handler to be executed once the user clicks the filter button */ - onFilter: PropTypes.func, - /** Pas a handler to be executed once the Filter input is cleared */ - onFilterClear: PropTypes.func, - /** add custom classNames */ - className: PropTypes.string, - /** Whether the filters are currently loading */ - loading: PropTypes.bool, - /** Whether the filters have an error */ - error: PropTypes.bool, - /** The error message to display. When passed, error is set to true automatically */ - errortext: PropTypes.string, -} - -Filters.defaultProps = { - search: null, - filters: null, - selectedFilterKey: "", - onSelectedFilterKeyChange: undefined, - filterValue: "", - valuePlaceholder: "", - onFilter: undefined, - onFilterValueChange: undefined, - onFilterClear: undefined, - className: "", - loading: false, - error: false, - errortext: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.stories.js b/libs_deprecated/juno-ui-components/src/components/Filters/Filters.stories.js deleted file mode 100644 index db544f9d5..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.stories.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Filters } from './index.js'; -import { FilterPill } from '../FilterPill/FilterPill.component'; -import { SearchInput } from '../SearchInput/SearchInput.component'; - -export default { - title: 'Deprecated/Filter/Filters', - component: Filters, - argTypes: {}, -}; - -const PillsTemplate = (args) => ( - <Filters {...args}> - {args.filters && args.filters.options && args.filters.options.length - ? args.filters.options.map((filter, i) => ( - <FilterPill - filterKey={filter.key} - filterKeyLabel={filter.label} - filterValue={`value_${i}`} - filterValueLabel={`Value ${i}`} - key={`filter-${i}`} - onClose={() => console.log(filter.key, 'closing')} - /> - )) - : null} - </Filters> -); - -export const Default = { - args: { - valuePlaceholder: 'Enter a value', - filters: { - keyLabel: 'Select a Filter', - options: [{ key: 'filter-1', label: 'Filter 1' }], - }, - }, -}; - -export const Loading = { - args: { - filters: { - keyLabel: 'Select a Filter', - options: [], - }, - loading: true, - }, -}; - -export const WithPills = { - render: PillsTemplate, - - args: { - filters: { - keyLabel: 'Select a Filter', - options: [ - { key: 'filter-01', label: 'Filter 1' }, - { key: 'filter-02', label: 'Filter 2' }, - { key: 'filter-03', label: 'Filter 3' }, - ], - }, - }, -}; - -export const ErrorWithPills = { - render: PillsTemplate, - - args: { - filters: { - options: [ - { key: 'filter-01', label: 'Filter 1' }, - { key: 'filter-02', label: 'Filter 2' }, - { key: 'filter-03', label: 'Filter 3' }, - ], - }, - error: true, - }, -}; - -export const PreseletedWithSearch = { - args: { - selectedFilterKey: 'filter-2', - search: ( - <SearchInput - onSearch={() => { - console.log('Searching…'); - }} - /> - ), - filters: { - keyLabel: 'Select a Filter', - options: [ - { key: 'filter-01', label: 'Filter 1' }, - { key: 'filter-02', label: 'Filter 2' }, - { key: 'filter-03', label: 'Filter 3' }, - ], - }, - }, -}; - -export const SearchOnly = { - args: { - search: ( - <SearchInput - onSearch={() => { - console.log('Searching…'); - }} - /> - ), - }, -}; - -const searchProps = { - onSearch: () => { - console.log('Searching…'); - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.test.js b/libs_deprecated/juno-ui-components/src/components/Filters/Filters.test.js deleted file mode 100644 index a988c07f3..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Filters/Filters.test.js +++ /dev/null @@ -1,204 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import userEvent from "@testing-library/user-event" -import { Filters } from "./index" -import { SearchInput } from "../SearchInput/index" - -describe("Filters", () => { - test("renders Filters", async () => { - render(<Filters data-testid="my-filters" />) - expect(screen.getByTestId("my-filters")).toBeInTheDocument() - expect(screen.getByTestId("my-filters")).toHaveClass("juno-filters") - }) - - test("renders a FilterInput when filter prop is passed", async () => { - const filters = { options: [{ label: "option 1", value: "option-1" }] } - render(<Filters filters={filters} />) - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toHaveClass("juno-filter-input-select") - }) - - test("renders Select with options as passed", async () => { - const filters = { - keyLabel: "Filter", - options: [ - { label: "option 1", value: "option-1" }, - { label: "option 2", value: "option-2" }, - ], - } - render(<Filters filters={filters} />) - expect(screen.getByRole("option", { name: "Filter" })).toBeInTheDocument() - expect(screen.getByRole("option", { name: "option 1" })).toHaveValue( - "option-1" - ) - expect(screen.getByRole("option", { name: "option 2" })).toHaveValue( - "option-2" - ) - }) - - test("renders a Select with selected filter key as passed", async () => { - const filters = { - options: [ - { label: "option 1", value: "option-1" }, - { label: "option 2", value: "option-2" }, - ], - } - render(<Filters filters={filters} selectedFilterKey="option-2" />) - expect(screen.getByRole("option", { name: "option 2" }).selected).toBe(true) - }) - - test("renders a Filter value text input with an aria-label as passed", async () => { - const filters = { valueLabel: "Enter a filter value", options: [] } - render(<Filters filters={filters} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "aria-label", - "Enter a filter value" - ) - }) - - test("renders a Filter vlaue text input witn a placeholder as passed", async () => { - const filters = { - valueLabel: "Enter a filter value", - options: [ - { label: "option 1", value: "option-1" }, - { label: "option 2", value: "option-2" }, - ], - } - render(<Filters valuePlaceholder="my placeholder" filters={filters} />) - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveAttribute( - "placeholder", - "my placeholder" - ) - }) - - test("renders a Filter value as passed", async () => { - const filters = { options: [{ label: "option 1", value: "option-1" }] } - render(<Filters filters={filters} filterValue="abc" />) - expect(screen.getByRole("textbox")).toHaveValue("abc") - }) - - test("executes a handler as passed when the filter input value changes", async () => { - const handleFilterValueChange = jest.fn() - const filters = { options: [{ label: "option 1", value: "option-1" }] } - render( - <Filters - filters={filters} - onFilterValueChange={handleFilterValueChange} - /> - ) - await userEvent.type(screen.getByRole("textbox"), "123") - expect(handleFilterValueChange).toHaveBeenCalledTimes(3) - }) - - test("executes a handler as passed when the filter icon is clicked", async () => { - const handleFilter = jest.fn() - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render(<Filters filters={filters} onFilter={handleFilter} />) - await userEvent.click(screen.getByTitle("Filter")) - expect(handleFilter).toHaveBeenCalledTimes(1) - }) - - test("executes a handler as passed when the input has focus and the user presses enter", async () => { - const handleFilter = jest.fn() - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render(<Filters filters={filters} onFilter={handleFilter} />) - await userEvent.type(screen.getByRole("textbox"), "{enter}") - expect(handleFilter).toHaveBeenCalledTimes(1) - expect(handleFilter).toHaveBeenCalledTimes(1) - }) - - test("clears the filter input and executes a handler as passed when the filter input clear icon is clicked", async () => { - const handleClear = jest.fn() - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render( - <Filters - filters={filters} - filterValue="some option" - onFilterClear={handleClear} - /> - ) - expect(screen.getByRole("textbox")).toHaveValue("some option") - await userEvent.click(screen.getByTitle("Clear")) - expect(screen.getByRole("textbox")).toHaveValue("") - expect(handleClear).toHaveBeenCalledTimes(1) - }) - - test("renders a SearchInput as passed", async () => { - render(<Filters search={<SearchInput />}></Filters>) - expect(screen.getByRole("searchbox")).toBeInTheDocument() - }) - - test("renders loading Filters as passed", async () => { - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render(<Filters filters={filters} loading />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByRole("progressbar")).toBeInTheDocument() - }) - - test("renders Filters with an error as passed", async () => { - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render(<Filters data-testid="my-filters" filters={filters} error />) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByTestId("my-filters")).toBeInTheDocument() - expect(screen.getByTestId("my-filters")).toHaveClass("juno-filters-error") - expect(screen.getByRole("button")).toBeDisabled() - }) - - test("renders Filters with error and an errortext as passed", async () => { - const filters = { - label: "Filter", - options: [{ label: "option 1", value: "option-1" }], - } - render( - <Filters - data-testid="my-filters" - filters={filters} - errortext="These Filters have an error" - /> - ) - expect(screen.getByRole("combobox")).toBeDisabled() - expect(screen.getByTestId("my-filters")).toBeInTheDocument() - expect(screen.getByTestId("my-filters")).toHaveClass("juno-filters-error") - expect( - document.querySelector(".juno-filters-errortext") - ).toBeInTheDocument() - expect(document.querySelector(".juno-filters-errortext")).toHaveTextContent( - "These Filters have an error" - ) - expect(screen.getByRole("button")).toBeDisabled() - }) - - test("renders a custom className", async () => { - render(<Filters data-testid="my-filters" className="my-custom-class" />) - expect(screen.getByTestId("my-filters")).toBeInTheDocument() - expect(screen.getByTestId("my-filters")).toHaveClass("my-custom-class") - }) - - test("renders all props as passed", async () => { - render(<Filters data-testid="23" data-lolol={true} />) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute("data-lolol") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Filters/index.js b/libs_deprecated/juno-ui-components/src/components/Filters/index.js deleted file mode 100644 index 727d1239c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Filters/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Filters } from "./Filters.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Form/Form.component.js b/libs_deprecated/juno-ui-components/src/components/Form/Form.component.js deleted file mode 100644 index 6a99a0acc..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Form/Form.component.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const formStyles = ` - jn-mb-8 -` - -const formHeading = ` - jn-text-2xl - jn-font-bold - jn-mb-4 -` - -/** A Form to hold FormSections and/or FormGroups with an optional title. */ -export const Form = ({ - title, - className, - children, - ...props -}) => { - return ( - <form - className={`juno-form ${formStyles} ${className}`} - {...props} - > - {title ? <h1 className={`juno-form-heading ${formHeading}`}>{title}</h1> : ""} - {children} - </form> - ) -} - -Form.propTypes = { - /** Title to be rendered in the Form`. */ - title: PropTypes.string, - /** Custom className */ - className: PropTypes.string, - /** Children to render in the form */ - children: PropTypes.node, -} - -Form.defaultProps = { - title: null, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Form/Form.stories.js b/libs_deprecated/juno-ui-components/src/components/Form/Form.stories.js deleted file mode 100644 index 16f09003f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Form/Form.stories.js +++ /dev/null @@ -1,132 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Form } from './index.js'; -import { FormRow } from '../FormRow/index.js'; -import { FormSection } from '../FormSection/index.js'; -import { FormHint } from '../FormHint/index.js'; -import { TextInput } from '../TextInput/index.js'; -import { Select } from '../Select/index.js'; -import { SelectOption } from '../SelectOption/index.js'; -import { Switch } from '../Switch/index.js'; -import { Textarea } from '../Textarea/index.js'; -import { RadioGroup } from '../RadioGroup/index.js'; -import { Radio } from '../Radio/index.js'; -import { CheckboxGroup } from '../CheckboxGroup/index.js'; -import { Checkbox } from '../Checkbox/index.js'; -import { Button } from '../Button/index.js'; -import { ButtonRow } from '../ButtonRow/index.js'; -import { IntroBox } from '../IntroBox/index.js'; - -export default { - title: 'Forms/Form', - component: Form, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, -}; - -const Template = ({ children, ...args }) => <Form {...args}>{children}</Form>; - -export const Default = { - render: Template, - - args: { - title: 'A Simple Form', - children: [ - <FormRow key="f-1"> - <TextInput label="First Name" id="first-name" /> - </FormRow>, - <FormRow key="f-2"> - <TextInput label="Last Name" id="last-name" /> - </FormRow>, - <FormRow key="f-3"> - <TextInput label="Email" id="email" type="email" required /> - </FormRow>, - <ButtonRow key="f-4"> - <Button>Cancel</Button> - <Button variant="primary">Submit</Button> - </ButtonRow>, - ], - }, -}; - -export const ComplexForm = { - render: Template, - - args: { - title: 'A Complex Form', - children: [ - <IntroBox text="In order to get to know you, we need to talk about colors." key="ib-1" />, - <FormSection title="First Section of the Form" key="fs-1"> - <FormRow key="fr-1"> - <Select label="Your Favorite Color" placeholder="Select your favorite color…" id="color"> - <SelectOption value="red" key="so-1"> - Red - </SelectOption> - <SelectOption value="blue" key="so-2"> - Blue - </SelectOption> - <SelectOption value="other" key="so-3"> - Other - </SelectOption> - </Select> - <FormHint text="Your favorite color to the best of your knowledge" /> - </FormRow> - <FormRow key="fr-2"> - <TextInput label="First Name" id="first-name" /> - </FormRow> - <FormRow key="fr-3"> - <TextInput label="Last Name" id="last-name" /> - </FormRow> - </FormSection>, - <FormSection title="Second Section of the Form" key="fs-2"> - <RadioGroup - name="color-radios" - label="In case you are not sure, select your true favorite color:" - > - <Radio key="r-1" id="color-red" label="Red" value="red" /> - <Radio key="r-2" id="color-blue" label="Blue" value="blue" /> - <Radio key="r-3" id="color-green" label="Green" value="green" /> - <Radio key="r-4" id="color-yellow" label="Yellow" value="yellow" /> - </RadioGroup> - <CheckboxGroup name="all-about-red" label="What is your opinion towards the color Red?"> - <Checkbox key="c-1" id="overrated" label="Red is vastly overrated" value="overrated" /> - <Checkbox key="c-2" id="blackisred" label="Black is better" value="blackisbetter" /> - </CheckboxGroup> - <FormRow key="fr-4"> - <Textarea - label="Your Message" - id="message" - placeholder="If there is something else we should know about you – now is the time!" - /> - </FormRow> - <FormRow> - <TextInput invalid value="Error!" /> - <FormHint variant="error" text="A textInput with an error for no reason whatsoever." /> - </FormRow> - <FormRow key="fr-5"> - <Switch label="Wake me up at 4.30am" id="wakey" /> - </FormRow> - <FormRow key="fr-6"> - <Switch label="Send me an email, too" id="email-too" /> - </FormRow> - </FormSection>, - <ButtonRow key="br-1"> - <Button>Cancel</Button> - <Button variant="primary-danger">Clear</Button> - <Button variant="primary">Submit</Button> - </ButtonRow>, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Form/Form.test.js b/libs_deprecated/juno-ui-components/src/components/Form/Form.test.js deleted file mode 100644 index 1e40d00ac..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Form/Form.test.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { Form } from "./index" - -describe("Form", () => { - - test("renders a Form", async () => { - render(<Form data-testid="my-form" />) - expect(screen.getByTestId("my-form")).toBeInTheDocument() - }) - - test("renders a title", async () => { - render(<Form data-testid="my-form" title="My Form" />) - expect(screen.getByTestId("my-form")).toBeInTheDocument() - expect(screen.getByRole("heading")).toHaveClass("juno-form-heading") - expect(screen.getByRole("heading")).toHaveTextContent("My Form") - }) - - test("renders a custom className", async () => { - render(<Form data-testid="my-form" className="my-custom-class" />) - expect(screen.getByTestId("my-form")).toBeInTheDocument() - expect(screen.getByTestId("my-form")).toHaveClass("my-custom-class") - }) - - test("renders children as passed", async () => { - render(<Form data-testid="my-form"><button></button></Form>) - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders all props as passed", async () => { - render(<Form data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Form/index.js b/libs_deprecated/juno-ui-components/src/components/Form/index.js deleted file mode 100644 index 81b06a027..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Form/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Form } from "./Form.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.component.js b/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.component.js deleted file mode 100644 index 37bcf2c95..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.component.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const baseStyles = ` - jn-text-xs - jn-mt-1 -` - -const variantStyles = (variant) => { - switch (variant) { - case "success": - return "jn-text-theme-success" - case "error": - return "jn-text-theme-error" - default: - return "jn-text-theme-light" - } -} - -export const FormHint = ({ - children, - text, - variant, - className, - ...props -}) => { - return ( - <div - className={` - juno-form-hint - juno-form-hint-${variant} - ${ baseStyles } - ${ variantStyles(variant) } - ${ className } - `} - {...props} - > - { children || text } - </div> - ) -} - - -FormHint.propTypes = { - /** The children to render as a hint associated with a form element */ - children: PropTypes.node, - /** The text to render. If both children and text are passed, children will rendered */ - text: PropTypes.node, - /** The variant of the the hint. Defaults to 'help'. */ - variant: PropTypes.oneOf(["help", "error", "success"]), - /** Pass a custom className */ - className: PropTypes.string, -} - - -FormHint.defaultProps = { - children: null, - text: "", - variant: "help", - className: undefined, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.stories.js b/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.stories.js deleted file mode 100644 index 1caa83d97..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.stories.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { FormHint } from './index.js'; - -export default { - title: 'Forms/FormHint', - component: FormHint, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = ({ children, ...args }) => <FormHint {...args}>{children}</FormHint>; - -export const Default = { - render: Template, - - args: { - text: 'A simple hint to be associated with a form input', - }, -}; - -export const WithChildren = { - render: Template, - - args: { - children: ( - <> - A FormHint with a <a href="#">Link</a>. - </> - ), - }, -}; - -export const WithTextAsChildren = { - render: Template, - - args: { - text: ( - <> - A FormHint with a <a href="#">Link</a>. - </> - ), - }, -}; - -export const ErrorVariant = { - render: Template, - - args: { - variant: 'error', - text: 'A FormHint containing an error or invalidation message', - }, -}; - -export const SuccessVariant = { - render: Template, - - args: { - variant: 'success', - text: 'A FormHint containg a success or validation message', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.test.js b/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.test.js deleted file mode 100644 index 3e1bbb25f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormHint/FormHint.test.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { FormHint } from "./index" - -describe("FormHint", () => { - - test("renders a FormHint", async () => { - render(<FormHint data-testid="my-form-hint" />) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - }) - - test("renders children as passed", async () => { - render(<FormHint data-testid="my-form-hint"><button></button></FormHint>) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a text as passed", async () => { - render(<FormHint data-testid="my-form-hint" text="My form-related message"/>) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveTextContent("My form-related message") - }) - - test("renders children if both children and text have been passed", async () => { - render( - <FormHint data-testid="my-form-hint" text="123"> - <>abc</> - </FormHint> - ) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveTextContent("abc") - expect(screen.getByTestId("my-form-hint")).not.toHaveTextContent("123") - }) - - test("renders a help message by default", async () => { - render(<FormHint data-testid="my-form-hint" />) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-help") - }) - - test("renders an error message as passed", async () => { - render(<FormHint data-testid="my-form-hint" variant="error" />) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-error") - }) - - test("renders a success message as passed", async () => { - render(<FormHint data-testid="my-form-hint" variant="success" />) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveClass("juno-form-hint-success") - }) - - test("renders a custom className", async () => { - render(<FormHint data-testid="my-form-hint" className="my-custom-class" />) - expect(screen.getByTestId("my-form-hint")).toBeInTheDocument() - expect(screen.getByTestId("my-form-hint")).toHaveClass("my-custom-class") - }) - - test("renders all props as passed", async () => { - render(<FormHint data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormHint/index.js b/libs_deprecated/juno-ui-components/src/components/FormHint/index.js deleted file mode 100644 index d62338c7d..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormHint/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { FormHint } from "./FormHint.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.component.js b/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.component.js deleted file mode 100644 index 0353732ed..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.component.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react' -import PropTypes from 'prop-types' - -const formRowStyles = ` - jn-mb-2 -` - -/** -A generic FormRow component. -Used to layout and structure forms. Pass Form elements such as TextInput, Textarea, Select, or Radio and CheckboxGroups as children. -*/ -export const FormRow = ({ - children, - className, - ...props -}) => { - return ( - <div className={`juno-form-row ${formRowStyles} ${className}`} {...props}> - {children} - </div> -)} - -FormRow.propTypes = { - /** The children to render in the formRow. Typically, these will be Input components such as TextInput, Textarea, Select, or Radio and CheckboxGroups*/ - children: PropTypes.node, - /** Add a custom className to a FormRow */ - className: PropTypes.string, -} - - -FormRow.defaultProps = { - children: null, - className: "", -} - diff --git a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.stories.js b/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.stories.js deleted file mode 100644 index 42c254e03..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.stories.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { FormRow } from './index.js'; -import { TextInput } from '../TextInput/index.js'; - -export default { - title: 'Forms/FormRow', - component: FormRow, - argTypes: { - children: { - control: false, - }, - }, -}; - -const Template = ({ children, ...args }) => <FormRow {...args}>{children}</FormRow>; - -export const Default = { - render: Template, - - args: { - children: [<TextInput label="TextInput in a FormRow" placeholder="Your input here…" key="1" />], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.test.js b/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.test.js deleted file mode 100644 index c9b5fceb0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormRow/FormRow.test.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { FormRow } from "./index" - -describe("FormSection", () => { - - test("renders a FormRow", async () => { - render(<FormRow data-testid="my-form-row" />) - expect(screen.getByTestId("my-form-row")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<FormRow data-testid="my-form-row" className="my-custom-class" />) - expect(screen.getByTestId("my-form-row")).toBeInTheDocument() - expect(screen.getByTestId("my-form-row")).toHaveClass("my-custom-class") - }) - - test("renders children as passed", async () => { - render(<FormRow><button></button></FormRow>) - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders all props as passed", async () => { - render(<FormRow data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormRow/index.js b/libs_deprecated/juno-ui-components/src/components/FormRow/index.js deleted file mode 100644 index 580a65a38..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { FormRow } from "./FormRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.component.js b/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.component.js deleted file mode 100644 index 756d92ed0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.component.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - - -const formSection = ` - jn-mb-8 - jn-last:mb-0 -` - -const formSectionHeading = ` - jn-text-lg - jn-font-bold - jn-mb-4 -` - -/** A Form section to group form elements inside complex forms with an optional title. */ -export const FormSection = ({ - - title, - children, - className, - ...props -}) => { - return ( - <section - className={`juno-form-section ${formSection} ${className}`} - {...props} - > - {title ? <h1 className={`juno-formsection-heading ${formSectionHeading}`}>{title}</h1> : ""} - {children} - </section> - ) -} - -FormSection.propTypes = { - /** Title, will be rendering as an `<h1>`. */ - title: PropTypes.string, - /** Pass a custpm className */ - className: PropTypes.string, - /** Children to render in the form section */ - children: PropTypes.node, -} - -FormSection.defaultProps = { - title: null, - className: "", - children: null, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.stories.js b/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.stories.js deleted file mode 100644 index c90639b94..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.stories.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { FormSection } from '../FormSection/FormSection.component'; -import { FormRow } from '../FormRow/FormRow.component'; -import { TextInput } from '../TextInput/TextInput.component'; - -export default { - title: 'Forms/FormSection', - component: FormSection, - argTypes: { - items: { - table: { - disable: true, - }, - }, - children: { - control: false, - }, - }, -}; - -const Template = ({ children, ...args }) => <FormSection {...args}>{children}</FormSection>; - -export const Default = { - render: Template, - - args: { - children: [ - <FormRow key="1"> - <TextInput label="Address Line 1" /> - </FormRow>, - <FormRow key="2"> - <TextInput label="Address Line 2" /> - </FormRow>, - ], - }, -}; - -export const WithTitle = { - render: Template, - - args: { - title: 'Form Section With Title', - children: [ - <FormRow key="1"> - <TextInput label="Address Line 1" /> - </FormRow>, - <FormRow key="2"> - <TextInput label="Address Line 2" /> - </FormRow>, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.test.js b/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.test.js deleted file mode 100644 index 92448c6f4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormSection/FormSection.test.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { FormSection } from "./index" - -describe("FormSection", () => { - - test("renders a FormSection", async () => { - render(<FormSection data-testid="my-formsection" />) - expect(screen.getByTestId("my-formsection")).toBeInTheDocument() - }) - - test("renders a title", async () => { - render(<FormSection data-testid="my-form-section" title="My Form Section" />) - expect(screen.getByTestId("my-form-section")).toBeInTheDocument() - expect(screen.getByRole("heading")).toHaveClass("juno-formsection-heading") - expect(screen.getByRole("heading")).toHaveTextContent("My Form Section") - }) - - test("renders a custom className", async () => { - render(<FormSection data-testid="my-formsection" className="my-custom-class" />) - expect(screen.getByTestId("my-formsection")).toBeInTheDocument() - expect(screen.getByTestId("my-formsection")).toHaveClass("my-custom-class") - }) - - test("renders children as passed", async () => { - render(<FormSection><button></button></FormSection>) - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders all props as passed", async () => { - render(<FormSection data-testid="23" data-lolol={true}/>) - expect(screen.getByTestId("23")).toBeInTheDocument() - expect(screen.getByTestId("23")).toHaveAttribute('data-lolol') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/FormSection/index.js b/libs_deprecated/juno-ui-components/src/components/FormSection/index.js deleted file mode 100644 index 0e9fd4dda..000000000 --- a/libs_deprecated/juno-ui-components/src/components/FormSection/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { FormSection } from "./FormSection.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.component.js b/libs_deprecated/juno-ui-components/src/components/Grid/Grid.component.js deleted file mode 100644 index e2a0ecf40..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.component.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -/** -A general-use grid. Use in conjunction with GridColumn and GridRow. -*/ - -export const Grid = ({ - auto, - children, - className, - ...props -}) => { - // auto grid overrides for columns: - const autoStyles = { - "--grid-column-flex-grow": "1", - "--grid-column-flex-shrink": "0", - "--grid-column-flex-basis": "0", - "--grid-column-default-width": "auto", - } - // Override column vars in case 'auto' was passed: - const gridStyles = auto ? autoStyles : {} - return ( - <div className={`juno-grid ${className}`} style={gridStyles} {...props} > - {children} - </div> - ) -} - - -Grid.propTypes = { - /** Whether columns should auto-size or not, default is false. This effectively overrides the 12-columns default grid */ - auto: PropTypes.bool, - /** The children to render in the grid */ - children: PropTypes.node, - /** Add a class to the grid container */ - className: PropTypes.string, -} - -Grid.defaultProps = { - auto: false, - className: "", - children: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.stories.js b/libs_deprecated/juno-ui-components/src/components/Grid/Grid.stories.js deleted file mode 100644 index c573acf1c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.stories.js +++ /dev/null @@ -1,159 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Grid } from './index.js'; -import { GridRow } from '../GridRow/GridRow.component.js'; -import { GridColumn } from '../GridColumn/GridColumn.component.js'; - -export default { - title: 'Layout/Grid/Grid', - component: Grid, - argTypes: { - children: { - control: false, - }, - }, - decorators: [(Story) => <Story className="jn-bg-juno-blue-3 jn-text-juno-grey-blue" />], -}; - -// for the decorator to work like this (passing props to the story) we have to access the passed props from the decorator -// from the context. This might be storybook 6.x-specific. Double check when we upgrade to storybook 7.x -const Template = (args, context) => <Grid {...args} className={context.className}></Grid>; - -export const Default = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'By default, Juno uses a 12-column fluid grid. Columns can be made to span multiple columns by passing `cols={n}`.', - }, - }, - }, - - args: { - children: [ - <GridRow key="1"> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - </GridRow>, - <GridRow key="2"> - <GridColumn>Column</GridColumn> - <GridColumn cols={3}>Column cols-3</GridColumn> - <GridColumn cols={5}>Column cols-6</GridColumn> - <GridColumn cols={2}>Column cols-2</GridColumn> - </GridRow>, - ], - }, -}; - -export const Auto = { - render: Template, - - parameters: { - docs: { - description: { - story: - 'By passing `auto` to the grid, all of its contained columns will automatically size to share available space equally. Columns with `cols={n}` will switch their behaviour to auto-size.', - }, - }, - }, - - args: { - auto: true, - children: [ - <GridRow key="1"> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - </GridRow>, - <GridRow key="2"> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - </GridRow>, - <GridRow key="3"> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - <GridColumn>Column</GridColumn> - </GridRow>, - ], - }, -}; - -export const MixedGrid = { - render: Template, - - args: { - children: ( - <GridRow> - <GridColumn>Column</GridColumn> - <GridColumn auto>Auto Column</GridColumn> - <GridColumn width={10}>Column 10%</GridColumn> - <GridColumn cols={3}>Column cols-3</GridColumn> - </GridRow> - ), - }, -}; - -export const MixedAutoGrid = { - render: Template, - - args: { - auto: true, - children: ( - <GridRow> - <GridColumn>Column</GridColumn> - <GridColumn auto>Auto Column</GridColumn> - <GridColumn width={10}>Column 10%</GridColumn> - <GridColumn cols={3}>Column cols-3</GridColumn> - </GridRow> - ), - }, -}; - -export const NestedGrid = { - render: Template, - - args: { - children: ( - <GridRow> - <GridColumn cols={3}>Column cols-3</GridColumn> - <GridColumn cols={9}> - <Grid> - <GridRow> - <GridColumn width={33.333333} className="bg-juno-blue-2"> - Nested Column 33.333333% - </GridColumn> - <GridColumn width={66.666666} className="bg-juno-blue-2"> - Nested Column 66.666666% - </GridColumn> - </GridRow> - </Grid> - </GridColumn> - </GridRow> - ), - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.test.js b/libs_deprecated/juno-ui-components/src/components/Grid/Grid.test.js deleted file mode 100644 index fd9f5f341..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Grid/Grid.test.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { Grid} from "./index" - -describe("Grid", () => { - - test("renders a Grid container", async () => { - render(<Grid data-testid="my-grid" />) - expect(screen.getByTestId("my-grid")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<Grid data-testid="my-grid" className="my-grid-class" />) - expect(screen.getByTestId("my-grid")).toHaveClass("my-grid-class") - }) - - test("has modified CSS variables in a style tag for auto grids", async () => { - render(<Grid data-testid="my-auto-grid" auto />) - expect(screen.getByTestId("my-auto-grid")).toHaveAttribute("style") - expect(document.querySelector('.juno-grid').style.getPropertyValue('--grid-column-flex-grow')).toBe('1') - expect(document.querySelector('.juno-grid').style.getPropertyValue('--grid-column-flex-shrink')).toBe('0') - expect(document.querySelector('.juno-grid').style.getPropertyValue('--grid-column-flex-basis')).toBe('0') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Grid/index.js b/libs_deprecated/juno-ui-components/src/components/Grid/index.js deleted file mode 100644 index 2527a3fb9..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Grid/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Grid } from "./Grid.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.component.js b/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.component.js deleted file mode 100644 index 3b79913b2..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.component.js +++ /dev/null @@ -1,152 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const autoColumnStyles = ` - jn-grow - jn-shrink-0 - jn-flex-basis-0 -` -const widthColumnStyles = ` - jn-grow-0 - jn-shrink-1 - jn-flex-basis-auto -` - -const columnBaseStyles = ` - jn-flex-grid-column - jn-p-grid-column -` - -const cols_1 = ` - jn-w-grid-col-1 -` - -const cols_2 = ` - jn-w-grid-col-2 -` - -const cols_3 = ` - jn-w-grid-col-3 -` - -const cols_4 = ` - jn-w-grid-col-4 -` - -const cols_5 = ` - jn-w-grid-col-6 -` - -const cols_6 = ` - jn-w-grid-col-6 -` - -const cols_7 = ` - jn-w-grid-col-7 -` - -const cols_8 = ` - jn-w-grid-col-8 -` - -const cols_9 = ` - jn-w-grid-col-9 -` - -const cols_10 = ` - jn-w-grid-col-10 -` - -const cols_11 = ` - jn-w-grid-col-11 -` - -const cols_12 = ` - jn-w-grid-col-12 -` - -const colsClass = (cols) => { - switch (cols) { - case 1: - return cols_1 - case 2: - return cols_2 - case 3: - return cols_3 - case 4: - return cols_4 - case 5: - return cols_5 - case 6: - return cols_6 - case 7: - return cols_7 - case 8: - return cols_8 - case 9: - return cols_9 - case 10: - return cols_10 - case 11: - return cols_11 - case 12: - return cols_12 - default: - return "jn-w-grid-column-default" - } -} - -/** -A grid column to be used inside a Grid. -*/ - -export const GridColumn = ({ - width, - cols, - auto, - className, - children, - ...props -}) => { - // auto column: - const autoStyles = { - flexGrow: "1", - flexShrink: "0", - flexBasis: "0" - } - // width column: - const widthStyles = width ? { width: width + '%', flexGrow: "0", flexShrink: "0", flexBasis: width + '%' } : {} - // width overrides auto: - const columnStyles = width ? widthStyles : ( auto ? autoStyles : {} ) - return ( - <div className={`juno-grid-column ${columnBaseStyles} ${colsClass(cols)} ${className}`} style={columnStyles} {...props} > - {children} - </div> - ) -} - - -GridColumn.propTypes = { - /** The number of columns to span the column over. */ - cols: PropTypes.number, - /** The width in percent as a number without "%" for auto-layout grids TODO: or "auto". If a width is given, it will override the "cols" prop. */ - width: PropTypes.number, - /** Whether the colum should set an auto width */ - auto: PropTypes.bool, - /** Add a class to a grid column */ - className: PropTypes.string, - /** Children to be rendered in the column element */ - children: PropTypes.node -} - -GridColumn.defaultProps = { - width: null, - cols: null, - auto: false, - className: "", -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.stories.js b/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.stories.js deleted file mode 100644 index ecc5a080c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.stories.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { GridColumn } from './index.js'; - -export default { - title: 'Layout/Grid/GridColumn', - component: GridColumn, - argTypes: { - children: { - control: false, - }, - }, - decorators: [(Story) => <Story className="jn-bg-juno-blue-3 jn-text-juno-grey-blue" />], -}; - -// for the decorator to work like this (passing props to the story) we have to access the passed props from the decorator -// from the context. This might be storybook 6.x-specific. Double check when we upgrade to storybook 7.x -const Template = (args, context) => ( - <GridColumn {...args} className={context.className}></GridColumn> -); - -export const Default = { - render: Template, - - args: { - children: 'Column', - }, -}; - -export const AutoColumn = { - render: Template, - - args: { - auto: true, - children: 'Auto Column', - }, -}; - -export const WidthColumn = { - render: Template, - - args: { - width: 50, - children: 'Column 50%', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.test.js b/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.test.js deleted file mode 100644 index df89c9bb1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridColumn/GridColumn.test.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { GridColumn} from "./index" - -describe("GridColumn", () => { - - test("renders a Grid row", async () => { - render(<GridColumn data-testid="my-grid-column" />) - expect(screen.getByTestId("my-grid-column")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<GridColumn data-testid="my-grid-column" className="my-grid-column-class" />) - expect(screen.getByTestId("my-grid-column")).toHaveClass("my-grid-column-class") - }) - - test("renders modified 'auto' styles when passed", async () => { - render(<GridColumn data-testid="my-auto-column" auto />) - expect(screen.getByTestId("my-auto-column")).toHaveAttribute("style") - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('flex-grow')).toBe('1') - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('flex-shrink')).toBe('0') - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('flex-basis')).toBe('0px') - }) - - test("renders width-related styles in a style tag when passed", async () => { - render(<GridColumn data-testid="my-width-column" width={73} />) - expect(screen.getByTestId("my-width-column")).toHaveAttribute("style") - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('width')).toBe('73%') - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('flex-shrink')).toBe('0') - expect(document.querySelector('.juno-grid-column').style.getPropertyValue('flex-basis')).toBe('73%') - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/GridColumn/index.js b/libs_deprecated/juno-ui-components/src/components/GridColumn/index.js deleted file mode 100644 index 09e5a13c4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridColumn/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { GridColumn } from "./GridColumn.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.component.js b/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.component.js deleted file mode 100644 index 73660a3db..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.component.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const gridRowBaseStyles = ` - jn-flex - jn-flex-wrap - jn-m-grid-row -` -/** -A grid row to hold GridColumn elements inside a Grid. -*/ -export const GridRow = ({ - children, - className, - ...props -}) => { - return ( - <div className={`juno-grid-row ${gridRowBaseStyles} ${className}`} {...props} > - {children} - </div> - ) -} - - -GridRow.propTypes = { - /** The children to render in the grid row */ - children: PropTypes.node, - /** Add a class to the grid row */ - className: PropTypes.string, -} - -GridRow.defaultProps = { - children: null, - className: "" -} diff --git a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.stories.js b/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.stories.js deleted file mode 100644 index 434714855..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.stories.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { GridRow } from './index.js'; -import { GridColumn } from '../GridColumn/GridColumn.component.js'; - -export default { - title: 'Layout/Grid/GridRow', - component: GridRow, - argTypes: { - children: { - control: false, - }, - }, - decorators: [(Story) => <Story className="jn-bg-juno-blue-3 jn-text-juno-grey-blue" />], -}; - -// for the decorator to work like this (passing props to the story) we have to access the passed props from the decorator -// from the context. This might be storybook 6.x-specific. Double check when we upgrade to storybook 7.x -const Template = ({ columns, ...args }, context) => ( - <GridRow {...args} className={context.className}></GridRow> -); - -export const Default = { - render: Template, - - args: { - children: [ - <GridColumn key="1">Column</GridColumn>, - <GridColumn key="2">Column</GridColumn>, - <GridColumn key="3">Column</GridColumn>, - <GridColumn key="4">Column</GridColumn>, - <GridColumn key="5">Column</GridColumn>, - <GridColumn key="6">Column</GridColumn>, - <GridColumn key="7">Column</GridColumn>, - <GridColumn key="8">Column</GridColumn>, - <GridColumn key="9">Column</GridColumn>, - <GridColumn key="10">Column</GridColumn>, - <GridColumn key="11">Column</GridColumn>, - <GridColumn key="12">Column</GridColumn>, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.test.js b/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.test.js deleted file mode 100644 index ca3bc0a4a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridRow/GridRow.test.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { GridRow} from "./index" - -describe("GridRow", () => { - - test("renders a Grid row", async () => { - render(<GridRow data-testid="my-grid-row" />) - expect(screen.getByTestId("my-grid-row")).toBeInTheDocument() - }) - - test("renders a custom className", async () => { - render(<GridRow data-testid="my-grid-row" className="my-grid-row-class" />) - expect(screen.getByTestId("my-grid-row")).toHaveClass("my-grid-row-class") - }) - -}) \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/GridRow/index.js b/libs_deprecated/juno-ui-components/src/components/GridRow/index.js deleted file mode 100644 index 9a43e32f6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/GridRow/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { GridRow } from "./GridRow.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.component.js b/libs_deprecated/juno-ui-components/src/components/Icon/Icon.component.js deleted file mode 100644 index a82e1f991..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.component.js +++ /dev/null @@ -1,826 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { forwardRef } from "react" -import PropTypes from "prop-types" - -/* Import Icons here. The icon svgs in the icons folder correspond to the respective "xyz_24px.svg" from material-ui icons. - */ -import AccessTime from "@material-design-icons/svg/filled/access_time.svg" -import AccountCircle from "@material-design-icons/svg/filled/account_circle.svg" -import AddCircle from "@material-design-icons/svg/filled/add_circle.svg" -import AutoAwesomeMosaic from "@material-design-icons/svg/filled/auto_awesome_mosaic.svg" -import AutoAwesomeMotion from "@material-design-icons/svg/filled/auto_awesome_motion.svg" -import Bolt from "@material-design-icons/svg/filled/bolt.svg" -import CalendarToday from "@material-design-icons/svg/filled/calendar_today.svg" -import Cancel from "@material-design-icons/svg/filled/cancel.svg" -import Check from "@material-design-icons/svg/filled/check.svg" -import CheckCircle from "@material-design-icons/svg/filled/check_circle.svg" -import ChevronLeft from "@material-design-icons/svg/outlined/chevron_left.svg" -import ChevronRight from "@material-design-icons/svg/outlined/chevron_right.svg" -import Close from "@material-design-icons/svg/filled/close.svg" -import ContentCopy from "@material-design-icons/svg/outlined/content_copy.svg" -import Danger from "./icons/juno-danger.svg" -import Dangerous from "@material-design-icons/svg/filled/dangerous.svg" -import Download from "@material-design-icons/svg/filled/download.svg" -import DeleteForever from "@material-design-icons/svg/filled/delete_forever.svg" -import Description from "@material-design-icons/svg/filled/description.svg" -import DNS from "@material-design-icons/svg/filled/dns.svg" -import Edit from "@material-design-icons/svg/filled/edit.svg" -import Error from "@material-design-icons/svg/filled/dangerous.svg" -import ErrorOutline from "@material-design-icons/svg/outlined/error_outline.svg" -import ExitToApp from "@material-design-icons/svg/outlined/exit_to_app.svg" -import ExpandLess from "@material-design-icons/svg/outlined/expand_less.svg" -import ExpandMore from "@material-design-icons/svg/outlined/expand_more.svg" -import FilterAlt from "@material-design-icons/svg/filled/filter_alt.svg" -import Forum from "@material-design-icons/svg/filled/forum.svg" -import Help from "@material-design-icons/svg/filled/help.svg" -import Home from "./icons/home_sharp.svg" -import Info from "@material-design-icons/svg/filled/info.svg" -import Comment from "@material-design-icons/svg/filled/comment.svg" -import ManageAccounts from "@material-design-icons/svg/filled/manage_accounts.svg" -import MonitorHeart from "@material-design-icons/svg/outlined/monitor_heart.svg" -import MoreVert from "@material-design-icons/svg/outlined/more_vert.svg" -import NotificationsOff from "@material-design-icons/svg/outlined/notifications_off.svg" -import OpenInBrowser from "@material-design-icons/svg/outlined/open_in_browser.svg" -import OpenInNew from "@material-design-icons/svg/outlined/open_in_new.svg" -import Place from "./icons/place.svg" -import Success from "@material-design-icons/svg/filled/check_box.svg" -import Search from "@material-design-icons/svg/outlined/search.svg" -import SeverityLow from "./icons/juno_severity_low.svg" -import SeverityMedium from "./icons/juno_severity_medium.svg" -import SeverityHigh from "./icons/juno_severity_high.svg" -import SeverityCritical from "./icons/juno_severity_critical.svg" -import Warning from "@material-design-icons/svg/filled/warning.svg" -import Widgets from "@material-design-icons/svg/filled/widgets.svg" - -/** -Generic Icon component. -*/ -// hover style needs to be revisited. only works if no icon color was passed -const anchorIconStyles = ` - jn-text-current - hover:jn-text-theme-high - focus:jn-outline-none - focus-visible:jn-ring-2 - focus-visible:jn-ring-theme-focus - focus-visible:jn-ring-offset-1 - focus-visible:jn-ring-offset-theme-focus - disabled:jn-opacity-50 - disabled:jn-cursor-not-allowed -` - -// hover style needs to be revisited. only works if no icon color was passed -const buttonIconStyles = ` - hover:jn-text-theme-high - focus:jn-outline-none - focus-visible:jn-ring-2 - focus-visible:jn-ring-theme-focus - focus-visible:jn-ring-offset-1 - focus-visible:jn-ring-offset-theme-focus - disabled:jn-opacity-50 - disabled:jn-cursor-not-allowed -` - -const wrapperStyles = ` - jn-leading-none -` -// export all known icons as an array of their names to be used with PropTypes here and from other components: -export const knownIcons = [ - "accessTime", - "accountCircle", - "addCircle", - "autoAwesomeMosaic", - "autoAwesomeMotion", - "bolt", - "calendarToday", - "cancel", - "check", - "checkCircle", - "chevronLeft", - "chevronRight", - "close", - "comment", - "contentCopy", - "danger", - "dangerous", - "default", - "deleteForever", - "description", - "dns", - "download", - "edit", - "error", - "errorOutline", - "exitToApp", - "expandLess", - "expandMore", - "filterAlt", - "forum", - "help", - "home", - "info", - "manageAccounts", - "monitorHeart", - "moreVert", - "notificationsOff", - "openInBrowser", - "openInNew", - "place", - "search", - "severityLow", - "severityMedium", - "severityHigh", - "severityCritical", - "success", - "warning", - "widgets", -] - -const getColoredSizedIcon = ({ - icon, - color, - size, - title, - iconClassName, - ...iconProps -}) => { - const iconClass = `juno-icon juno-icon-${icon} jn-fill-current ${color} ${iconClassName}` - - switch (icon) { - case "accessTime": - return ( - <AccessTime - width={size} - height={size} - className={iconClass} - alt="time" - title={title ? title : "Time"} - role="img" - {...iconProps} - /> - ) - case "accountCircle": - return ( - <AccountCircle - width={size} - height={size} - className={iconClass} - alt="account" - title={title ? title : "Account"} - role="img" - {...iconProps} - /> - ) - case "addCircle": - return ( - <AddCircle - width={size} - height={size} - className={iconClass} - alt="add" - title={title ? title : "Add"} - role="img" - {...iconProps} - /> - ) - case "autoAwesomeMosaic": - return ( - <AutoAwesomeMosaic - width={size} - height={size} - className={iconClass} - alt="mosaic" - title={title ? title : "Mosaic"} - role="img" - {...iconProps} - /> - ) - case "autoAwesomeMotion": - return ( - <AutoAwesomeMotion - width={size} - height={size} - className={iconClass} - alt="items stacked behind each other" - title={title ? title : "Items stacked behind each other"} - role="img" - {...iconProps} - /> - ) - case "bolt": - return ( - <Bolt - width={size} - height={size} - className={iconClass} - alt="bolt" - title={title ? title : "Bolt"} - role="img" - {...iconProps} - /> - ) - case "calendarToday": - return ( - <CalendarToday - width={size} - height={size} - className={iconClass} - alt="calendar" - title={title ? title : "Calendar"} - role="img" - {...iconProps} - /> - ) - case "cancel": - return ( - <Cancel - width={size} - height={size} - className={iconClass} - alt="cancel" - title={title ? title : "Cancel"} - role="img" - {...iconProps} - /> - ) - case "check": - return ( - <Check - width={size} - height={size} - className={iconClass} - alt="check" - title={title ? title : "Check"} - role="img" - {...iconProps} - /> - ) - case "checkCircle": - return ( - <CheckCircle - width={size} - height={size} - className={iconClass} - alt="checkCircle" - title={title ? title : "CheckCircle"} - role="img" - {...iconProps} - /> - ) - case "chevronLeft": - return ( - <ChevronLeft - width={size} - height={size} - className={iconClass} - alt="chevronLeft" - title={title ? title : "ChevronLeft"} - role="img" - {...iconProps} - /> - ) - case "chevronRight": - return ( - <ChevronRight - width={size} - height={size} - className={iconClass} - alt="chevronRight" - title={title ? title : "ChevronRight"} - role="img" - {...iconProps} - /> - ) - case "close": - return ( - <Close - width={size} - height={size} - className={iconClass} - alt="close" - title={title ? title : "Close"} - role="img" - {...iconProps} - /> - ) - case "comment": - return ( - <Comment - width={size} - height={size} - className={iconClass} - alt="comment" - title={title ? title : "Comment"} - role="img" - {...iconProps} - /> - ) - case "contentCopy": - return ( - <ContentCopy - width={size} - height={size} - className={iconClass} - alt="copy" - title={title ? title : "Copy"} - role="img" - {...iconProps} - /> - ) - case "danger": - return ( - <Danger - width={size} - height={size} - className={iconClass} - alt="danger" - title={title ? title : "Danger"} - role="img" - {...iconProps} - /> - ) - case "dangerous": - return ( - <Dangerous - width={size} - height={size} - className={iconClass} - alt="dangerous" - title={title ? title : "Dangerous"} - role="img" - {...iconProps} - /> - ) - case "deleteForever": - return ( - <DeleteForever - width={size} - height={size} - className={iconClass} - alt="delete forever" - title={title ? title : "Delete Forever"} - role="img" - {...iconProps} - /> - ) - case "description": - return ( - <Description - width={size} - height={size} - className={iconClass} - alt="description" - title={title ? title : "Description"} - role="img" - {...iconProps} - /> - ) - case "dns": - return ( - <DNS - width={size} - height={size} - className={iconClass} - alt="service" - title={title ? title : "Service"} - role="img" - {...iconProps} - /> - ) - case "download": - return ( - <Download - width={size} - height={size} - className={iconClass} - alt="download" - title={title ? title : "download"} - role="img" - {...iconProps} - /> - ) - case "edit": - return ( - <Edit - width={size} - height={size} - className={iconClass} - alt="edit" - title={title ? title : "Edit"} - role="img" - {...iconProps} - /> - ) - case "error": - return ( - <Error - width={size} - height={size} - className={iconClass} - alt="error" - title={title ? title : "Error"} - role="img" - {...iconProps} - /> - ) - case "errorOutline": - return ( - <ErrorOutline - width={size} - height={size} - className={iconClass} - alt="error outline" - title={title ? title : "Error"} - role="img" - {...iconProps} - /> - ) - case "exitToApp": - return ( - <ExitToApp - width={size} - height={size} - className={iconClass} - alt="exit to other app" - title={title ? title : "Exit to app"} - role="img" - {...iconProps} - /> - ) - case "expandLess": - return ( - <ExpandLess - width={size} - height={size} - className={iconClass} - alt="expand less" - title={title ? title : "Expand Less"} - role="img" - {...iconProps} - /> - ) - case "expandMore": - return ( - <ExpandMore - width={size} - height={size} - className={iconClass} - alt="expand more" - title={title ? title : "Expand More"} - role="img" - {...iconProps} - /> - ) - case "filterAlt": - return ( - <FilterAlt - width={size} - height={size} - className={iconClass} - alt="filter" - title={title ? title : "Filter"} - role="img" - {...iconProps} - /> - ) - case "forum": - return ( - <Forum - width={size} - height={size} - className={iconClass} - alt="forum" - title={title ? title : "Forum"} - role="img" - {...iconProps} - /> - ) - case "help": - return ( - <Help - width={size} - height={size} - className={iconClass} - alt="help" - title={title ? title : "Help"} - role="img" - {...iconProps} - /> - ) - case "home": - return ( - <Home - width={size} - height={size} - className={iconClass} - alt="home" - title={title ? title : "Home"} - role="img" - {...iconProps} - /> - ) - case "info": - return ( - <Info - width={size} - height={size} - className={iconClass} - alt="info" - title={title ? title : "Info"} - role="img" - {...iconProps} - /> - ) - case "manageAccounts": - return ( - <ManageAccounts - width={size} - height={size} - className={iconClass} - alt="user account configuration" - title={title ? title : "User account configuration"} - role="img" - {...iconProps} - /> - ) - case "monitorHeart": - return ( - <MonitorHeart - width={size} - height={size} - className={iconClass} - alt="heart monitor" - title={title ? title : "Heart monitor"} - role="img" - {...iconProps} - /> - ) - case "moreVert": - return ( - <MoreVert - width={size} - height={size} - className={iconClass} - alt="more" - title={title ? title : "More"} - role="img" - {...iconProps} - /> - ) - case "notificationsOff": - return ( - <NotificationsOff - width={size} - height={size} - className={iconClass} - alt="notifications off" - title={title ? title : "Notifications off"} - role="img" - {...iconProps} - /> - ) - case "openInBrowser": - return ( - <OpenInBrowser - width={size} - height={size} - className={iconClass} - alt="open in browser" - title={title ? title : "Open in browser"} - role="img" - {...iconProps} - /> - ) - case "openInNew": - return ( - <OpenInNew - width={size} - height={size} - className={iconClass} - alt="open in new tab" - title={title ? title : "Open in new tab"} - role="img" - {...iconProps} - /> - ) - case "place": - return ( - <Place - width={size} - height={size} - className={iconClass} - alt="location" - title={title ? title : "Location"} - role="img" - {...iconProps} - /> - ) - case "search": - return ( - <Search - width={size} - height={size} - className={iconClass} - alt="search" - title={title ? title : "Search"} - role="img" - {...iconProps} - /> - ) - case "severityLow": - return ( - <SeverityLow - width={size} - height={size} - className={iconClass} - alt="Severity low" - title={title ? title : "Severity Low"} - role="img" - {...iconProps} - /> - ) - case "severityMedium": - return ( - <SeverityMedium - width={size} - height={size} - className={iconClass} - alt="Severity medium" - title={title ? title : "Severity Medium"} - role="img" - {...iconProps} - /> - ) - case "severityHigh": - return ( - <SeverityHigh - width={size} - height={size} - className={iconClass} - alt="Severity high" - title={title ? title : "Severity High"} - role="img" - {...iconProps} - /> - ) - case "severityCritical": - return ( - <SeverityCritical - width={size} - height={size} - className={iconClass} - alt="Severity critical" - title={title ? title : "Severity Critical"} - role="img" - {...iconProps} - /> - ) - case "success": - return ( - <Success - width={size} - height={size} - className={iconClass} - alt="success" - title={title ? title : "Success"} - role="img" - {...iconProps} - /> - ) - case "widgets": - return ( - <Widgets - width={size} - height={size} - className={iconClass} - alt="widgets" - title={title ? title : "Widgets"} - role="img" - {...iconProps} - /> - ) - case "warning": - return ( - <Warning - width={size} - height={size} - className={iconClass} - alt="warning" - title={title ? title : "Warning"} - role="img" - {...iconProps} - /> - ) - case "default": // keep explicit default case to allow consuming components to use 'default' w/o throwing warnings - return ( - <Help - width={size} - height={size} - className={iconClass} - alt="help" - title={title ? title : "Help"} - role="img" - {...iconProps} - /> - ) - default: - return ( - <Help - width={size} - height={size} - className={iconClass} - alt="help" - title={title ? title : "Help"} - role="img" - {...iconProps} - /> - ) - } -} - -export const Icon = forwardRef( - ( - { icon, color, size, title, className, href, disabled, onClick, ...props }, - ref - ) => { - // if href or onClick was passed, then we want to add the passed classes and passed arbitrary props to the button or anchor - // otherwise add the passed classes/props to the icon itself - const iconClassName = href || onClick ? "" : className - const iconProps = href || onClick ? {} : props - - const icn = getColoredSizedIcon({ - icon, - color, - size, - title, - iconClassName, - ...iconProps, - }) - - const handleClick = (event) => { - onClick && onClick(event) - } - - const button = ( - <button - onClick={handleClick} - className={`juno-icon-button ${buttonIconStyles} ${className}`} - aria-label={title || icon} - disabled={disabled} - ref={ref} - {...props} - > - {icn} - </button> - ) - - const anchor = ( - <a - href={href} - className={`juno-icon-link ${anchorIconStyles} ${className}`} - aria-label={title || icon} - ref={ref} - {...props} - > - {icn} - </a> - ) - - /* render an <a> if href was passed, otherwise render button if onClick was passes, otherwise render plain icon: */ - /* if plain icon, add ref to the icon. In the other cases the ref goes on the anchor or button */ - return href ? anchor : onClick ? button : <span ref={ref}>{icn}</span> - } -) - -Icon.propTypes = { - /** The icon to display */ - icon: PropTypes.oneOf(knownIcons), - /** By default, Icons will use the `color` of the current context. In order to use a different color just for the icon, a text color class can be passed. These begin with "jn-text-". */ - color: PropTypes.string, - /** The size of the icon as a number of pixels (without "px": "16" will render an icon of 16px x 16px)*/ - size: PropTypes.string, - /** The title of the icon. Important for accessibility, will also show as a tooltip: */ - title: PropTypes.string, - /** A custom className */ - className: PropTypes.string, - /** Optionally specify an href. This will render the Icon inside an <code><a></code> element with the given url. */ - href: PropTypes.string, - /** Disable the Icon. Only applicable when rendering as a button by passing an onClick handler, too. */ - disabled: PropTypes.bool, - /** Optionally specify a click handler. This will render the icon inside a <code><button></code> with the given handler. */ - onClick: PropTypes.func, -} - -Icon.defaultProps = { - icon: null, - color: "", - size: "24", - title: "", - className: "", - href: "", - disabled: false, - onClick: undefined, -} diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.stories.js b/libs_deprecated/juno-ui-components/src/components/Icon/Icon.stories.js deleted file mode 100644 index c32c7df70..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.stories.js +++ /dev/null @@ -1,403 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Icon } from './index.js'; - -export default { - title: 'Components/Icon', - component: Icon, - argTypes: {}, - parameters: { - docs: { - description: { - component: - "A generic icon component. Accepts text color classes for color. Please note that the 'jn-' prefix for tailwind classes is only necessary within the juno ui design system itself. When using icons in your own applications use the normal tailwing-generated text color classes starting with 'text-'", - }, - }, - }, -}; - -export const Default = { - args: { - icon: 'help', - color: 'jn-global-text', - }, -}; - -export const Info_Colored = { - args: { - icon: 'info', - color: 'jn-text-theme-info', - }, -}; - -export const Danger_Colored = { - args: { - icon: 'danger', - color: 'jn-text-theme-danger', - }, -}; - -export const Success_Colored = { - args: { - icon: 'success', - color: 'jn-text-theme-success', - }, -}; - -export const Warning_Colored = { - args: { - icon: 'warning', - color: 'jn-text-theme-warning', - }, -}; - -export const ThemeColor = { - args: { - icon: 'help', - color: 'jn-global-text', - }, -}; - -export const Smaller = { - args: { - ...Default.args, - icon: 'help', - size: '18', - }, -}; - -export const Larger = { - args: { - ...Default.args, - icon: 'help', - size: '64', - }, -}; - -export const IconAsLink = { - args: { - ...Default.args, - href: '#', - title: 'The Icon is a link', - }, -}; - -export const IconAsButton = { - args: { - ...Default.args, - title: 'The Icon is a button', - onClick: () => { - console.log('click'); - }, - }, -}; - -export const Account_Circle = { - args: { - ...Default.args, - icon: 'accountCircle', - }, -}; - -export const Add_Circle = { - args: { - ...Default.args, - icon: 'addCircle', - }, -}; - -export const Auto_Awesome_Mosaic = { - args: { - ...Default.args, - icon: 'autoAwesomeMosaic', - }, -}; - -export const Auto_Awesome_Motion = { - args: { - ...Default.args, - icon: 'autoAwesomeMotion', - }, -}; - -export const Bolt = { - args: { - ...Default.args, - icon: 'bolt', - }, -}; - -export const Cancel = { - args: { - ...Default.args, - icon: 'cancel', - }, -}; - -export const Check = { - args: { - icon: 'check', - }, -}; - -export const CheckCircle = { - args: { - icon: 'checkCircle', - }, -}; - -export const ChevronLeft = { - args: { - icon: 'chevronLeft', - }, -}; - -export const ChevronRight = { - args: { - icon: 'chevronRight', - }, -}; - -export const Close = { - args: { - icon: 'close', - }, -}; - -export const Comment = { - args: { - ...Default.args, - icon: 'comment', - }, -}; - -export const ContentCopy = { - args: { - icon: 'contentCopy', - }, -}; - -export const Danger = { - args: { - ...Default.args, - icon: 'danger', - }, -}; - -export const Dangerous = { - args: { - icon: 'dangerous', - }, -}; - -export const DeleteForever = { - args: { - icon: 'deleteForever', - }, -}; - -export const Description = { - args: { - ...Default.args, - icon: 'description', - }, -}; - -export const DNS = { - args: { - ...Default.args, - icon: 'dns', - }, -}; - -export const Download = { - args: { - icon: 'download', - }, -}; - -export const Edit = { - args: { - ...Default.args, - icon: 'edit', - }, -}; - -export const Error = { - args: { - ...Default.args, - icon: 'dangerous', - }, -}; - -export const Error_Outline = { - args: { - ...Default.args, - icon: 'errorOutline', - }, -}; - -export const Exit_To_App = { - args: { - ...Default.args, - icon: 'exitToApp', - }, -}; - -export const Expand_Less = { - args: { - ...Default.args, - icon: 'expandLess', - }, -}; - -export const Expand_More = { - args: { - ...Default.args, - icon: 'expandMore', - }, -}; - -export const Filter_Alt = { - args: { - ...Default.args, - icon: 'filterAlt', - }, -}; - -export const Forum = { - args: { - ...Default.args, - icon: 'forum', - }, -}; - -export const Help = { - args: { - ...Default.args, - icon: 'help', - }, -}; - -export const Home = { - args: { - ...Default.args, - icon: 'home', - }, -}; - -export const Info = { - args: { - ...Default.args, - icon: 'info', - }, -}; - -export const Manage_Accounts = { - args: { - ...Default.args, - icon: 'manageAccounts', - }, -}; - -export const Monitor_Heart = { - args: { - ...Default.args, - icon: 'monitorHeart', - }, -}; - -export const More_Vert = { - args: { - ...Default.args, - icon: 'moreVert', - }, -}; - -export const Notifications_Off = { - args: { - ...Default.args, - icon: 'notificationsOff', - }, -}; - -export const Open_In_Browser = { - args: { - ...Default.args, - icon: 'openInBrowser', - }, -}; - -export const Open_In_New = { - args: { - ...Default.args, - icon: 'openInNew', - }, -}; - -export const Place = { - args: { - ...Default.args, - icon: 'place', - }, -}; - -export const Search = { - args: { - ...Default.args, - icon: 'search', - }, -}; - -export const SeverityLow = { - args: { - ...Default.args, - icon: 'severityLow', - }, -}; - -export const SeverityMedium = { - args: { - ...Default.args, - icon: 'severityMedium', - }, -}; - -export const SeverityHigh = { - args: { - ...Default.args, - icon: 'severityHigh', - }, -}; - -export const SeverityCritical = { - args: { - ...Default.args, - icon: 'severityCritical', - }, -}; - -export const Success = { - args: { - ...Default.args, - icon: 'success', - }, -}; - -export const Warning = { - args: { - ...Default.args, - icon: 'warning', - }, -}; - -export const Widgets = { - args: { - ...Default.args, - icon: 'widgets', - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.test.js b/libs_deprecated/juno-ui-components/src/components/Icon/Icon.test.js deleted file mode 100644 index c68e4faac..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/Icon.test.js +++ /dev/null @@ -1,381 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { Icon } from "./index" - -describe("Icon", () => { - test("renders an Icon as passed", async () => { - render(<Icon icon="warning" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "warning") - }) - - test("renders a custom className as passed", async () => { - render(<Icon className="my-custom-class" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveClass("my-custom-class") - }) - - test("renders a default icon when none was passed", async () => { - render(<Icon />) - expect(screen.getByRole("img")).toBeInTheDocument() - // note: currently the default icon is the help icon - expect(screen.getByRole("img")).toHaveAttribute("alt", "help") - }) - - test("renders an Icon with no text class by default so that text color is inherited from context", async () => { - render(<Icon />) - expect(screen.getByRole("img")).toBeInTheDocument() - // check that there is no class that contains 'text-' - expect(screen.getByRole("img")).not.toHaveAttribute( - "class", - expect.stringContaining("text-") - ) - }) - - test("renders an Icon with color as passed", async () => { - render(<Icon color="text-juno-blue" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveClass("text-juno-blue") - }) - - test("renders an Icon with default size", async () => { - render(<Icon />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("width", "24") - expect(screen.getByRole("img")).toHaveAttribute("height", "24") - }) - - test("renders an Icon with size as passed", async () => { - render(<Icon size="48" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("width", "48") - expect(screen.getByRole("img")).toHaveAttribute("height", "48") - }) - - test("renders a custom alt text instead of default when passed", async () => { - render(<Icon alt="my super custom icon alt text" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute( - "alt", - "my super custom icon alt text" - ) - }) - - // Test individual icons: - - test("renders an accessTime icon", async () => { - render(<Icon icon="accessTime" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "time") - }) - - test("renders an accountCircle icon", async () => { - render(<Icon icon="accountCircle" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "account") - }) - - test("renders an addCircle icon", async () => { - render(<Icon icon="addCircle" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "add") - }) - - test("renders a autoAwesomeMosaic icon", async () => { - render(<Icon icon="autoAwesomeMosaic" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "mosaic") - }) - - test("renders a autoAwesomeMotion icon", async () => { - render(<Icon icon="autoAwesomeMotion" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute( - "alt", - "items stacked behind each other" - ) - }) - - test("renders a bolt icon", async () => { - render(<Icon icon="bolt" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "bolt") - }) - - test("renders a cancel icon", async () => { - render(<Icon icon="cancel" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "cancel") - }) - - test("renders a check icon", async () => { - render(<Icon icon="check" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "check") - }) - - test("renders a checkCircle icon", async () => { - render(<Icon icon="checkCircle" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "checkCircle") - }) - - test("renders a chevronLeft icon", async () => { - render(<Icon icon="chevronLeft" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "chevronLeft") - }) - - test("renders a chevronRight icon", async () => { - render(<Icon icon="chevronRight" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "chevronRight") - }) - - test("renders a close icon", async () => { - render(<Icon icon="close" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "close") - }) - - test("renders a copy icon", async () => { - render(<Icon icon="contentCopy" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "copy") - }) - - test("renders a danger icon", async () => { - render(<Icon icon="danger" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "danger") - }) - - test("renders a dangerous icon", async () => { - render(<Icon icon="dangerous" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "dangerous") - }) - - test("renders a deleteForever icon", async () => { - render(<Icon icon="deleteForever" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "delete forever") - }) - - test("renders a description icon", async () => { - render(<Icon icon="description" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "description") - }) - - test("renders a dns icon", async () => { - render(<Icon icon="dns" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "service") - }) - - test("renders an edit icon", async () => { - render(<Icon icon="edit" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "edit") - }) - - test("renders an error icon", async () => { - render(<Icon icon="error" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "error") - }) - - test("renders an outlined error icon", async () => { - render(<Icon icon="errorOutline" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "error outline") - }) - - test("renders an exitToApp icon", async () => { - render(<Icon icon="exitToApp" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "exit to other app") - }) - - test("renders an expandLess icon", async () => { - render(<Icon icon="expandLess" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "expand less") - }) - - test("renders an expandMore icon", async () => { - render(<Icon icon="expandMore" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "expand more") - }) - - test("renders an filterAlt icon", async () => { - render(<Icon icon="filterAlt" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "filter") - }) - - test("renders an forum icon", async () => { - render(<Icon icon="forum" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "forum") - }) - - test("renders a forum help icon", async () => { - render(<Icon icon="help" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "help") - }) - - test("renders a Home icon", async () => { - render(<Icon icon="home" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "home") - }) - - test("renders an info icon", async () => { - render(<Icon icon="info" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "info") - }) - - test("renders a comment icon", async () => { - render(<Icon icon="comment" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "comment") - }) - - test("renders a manageAccounts icon", async () => { - render(<Icon icon="manageAccounts" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute( - "alt", - "user account configuration" - ) - }) - - test("renders an openInBrowser icon", async () => { - render(<Icon icon="openInBrowser" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "open in browser") - }) - - test("renders a place icon", async () => { - render(<Icon icon="place" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "location") - }) - - test("renders a search icon", async () => { - render(<Icon icon="search" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "search") - }) - - test("renders a success icon", async () => { - render(<Icon icon="success" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "success") - }) - - test("renders a warning icon", async () => { - render(<Icon icon="warning" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("alt", "warning") - }) - - test("renders a custom title", async () => { - render(<Icon title="My custom title" />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("title", "My custom title") - }) - - test("renders an <a> element if href is passed as prop", async () => { - render(<Icon href="#" />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("href", "#") - }) - - test("renders an <a> element with correct aria-label-attribute as passed", async () => { - render(<Icon href="#" title="my link title" />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute( - "aria-label", - "my link title" - ) - }) - - test("renders an <a> element with correct aria-label-attribute fallback if not passed", async () => { - render(<Icon href="#" icon="warning" />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("aria-label", "warning") - }) - - test("renders a <button> element if a click handler is passed", async () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} />) - expect(screen.getByRole("button")).toBeInTheDocument() - }) - - test("renders a <button> element with correct aria-label-attribute as passed", async () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} title="my-button-title" />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute( - "aria-label", - "my-button-title" - ) - }) - - test("renders a <button> element with correct aria-label-attribute fallback if not passed", async () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} icon="warning" />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveAttribute("aria-label", "warning") - }) - - test("renders a disabled button element as passed", async () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} disabled />) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeDisabled() - }) - - test("an onClick handler is called as passed", () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} />) - screen.getByRole("button").click() - expect(handleClick).toHaveBeenCalled() - }) - - test("does not execute onClick handler when disabled", async () => { - const handleClick = jest.fn() - render(<Icon onClick={handleClick} disabled />) - screen.getByRole("button").click() - expect(handleClick).not.toHaveBeenCalled() - }) - - test("renders an <a> element and ignore onClick handler if both href and onClick handler are passed", async () => { - const handleClick = jest.fn() - render(<Icon href="#" onClick={handleClick} />) - expect(screen.getByRole("link")).toBeInTheDocument() - expect(screen.getByRole("link")).toHaveAttribute("href", "#") - screen.getByRole("link").click() - expect(handleClick).not.toHaveBeenCalled() - }) - - // Test all props: - - test("renders all props as passed", async () => { - render(<Icon id="icon-1" data-lolol={true} />) - expect(screen.getByRole("img")).toBeInTheDocument() - expect(screen.getByRole("img")).toHaveAttribute("id", "icon-1") - expect(screen.getByRole("img")).toHaveAttribute("data-lolol") - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/home_sharp.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/home_sharp.svg deleted file mode 100644 index add764f0b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/home_sharp.svg +++ /dev/null @@ -1,6 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8h5z"/></svg> \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno-danger.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno-danger.svg deleted file mode 100644 index cb8cfcd53..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno-danger.svg +++ /dev/null @@ -1,8 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <path d="M22,17.9999996 L22,19.9999996 L2,19.9999996 L2,17.9999996 L22,17.9999996 Z M12,6.428571 C14.7642857,6.428571 17.0146825,8.23991359 17.1375716,10.5179164 L17.1428571,10.7142853 L17.1428571,16.7142853 L6.85714286,16.7142853 L6.85714286,10.7142853 L6.86242835,10.5179164 C6.98531746,8.23991359 9.23571429,6.428571 12,6.428571 Z M12,7.71428529 L12,15.428571 L15.8571429,15.428571 L15.8571429,11.1428567 L15.851803,10.960591 C15.745448,9.15003461 14.0636603,7.71428529 12,7.71428529 Z M19.075912,3.96838198 L20.490712,5.38218198 L18.370012,7.50438202 L16.955212,6.09058202 L19.075912,3.96838198 Z M4.956739,3.939208 L7.078039,6.060508 L5.663839,7.474708 L3.542539,5.353408 L4.956739,3.939208 Z M13,1.428571 L13,4.428571 L11,4.428571 L11,1.428571 L13,1.428571 Z"></path> -</svg> \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_critical.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_critical.svg deleted file mode 100644 index 7bd6316f8..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_critical.svg +++ /dev/null @@ -1,10 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M15.7956 22H14.5955L15.7956 14.2222H11.5955C10.8994 14.2222 10.9114 13.8667 11.1395 13.4889C11.3675 13.1111 11.1995 13.4 11.2235 13.3556C12.7715 10.8222 15.0995 7.04445 18.1956 2H19.3956L18.1956 9.77778H22.3957C22.9837 9.77778 23.0677 10.1444 22.9597 10.3444L22.8757 10.5111C18.1476 18.1667 15.7956 22 15.7956 22Z"/> -<path d="M2 17H8V23H2V17Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M2 1L2 15H8V1H2Z"/> -</svg> diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_high.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_high.svg deleted file mode 100644 index 5cc08d58b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_high.svg +++ /dev/null @@ -1,11 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M15.7956 22H14.5955L15.7956 14.2222H11.5955C10.8994 14.2222 10.9114 13.8667 11.1395 13.4889C11.3675 13.1111 11.1995 13.4 11.2235 13.3556C12.7715 10.8222 15.0995 7.04444 18.1956 2L19.3956 2L18.1956 9.77778H22.3957C22.9837 9.77778 23.0677 10.1444 22.9597 10.3444L22.8757 10.5111C18.1476 18.1667 15.7956 22 15.7956 22Z"/> -<path d="M2 17H8V23H2V17Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9V15H8V9H2Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M2 1V7H8V1H2Z"/> -</svg> diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_low.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_low.svg deleted file mode 100644 index 9ce2c516c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_low.svg +++ /dev/null @@ -1,11 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M15.7956 22H14.5955L15.7956 14.2222H11.5955C10.8994 14.2222 10.9114 13.8667 11.1395 13.4889C11.3675 13.1111 11.1995 13.4 11.2235 13.3556C12.7715 10.8222 15.0995 7.04444 18.1956 2L19.3956 2L18.1956 9.77778H22.3957C22.9837 9.77778 23.0677 10.1444 22.9597 10.3444L22.8757 10.5111C18.1476 18.1667 15.7956 22 15.7956 22Z"/> -<path d="M2 17H8V23H2V17Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M7 10H3V14H7V10ZM2 9V15H8V9H2Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2H3V6H7V2ZM2 1V7H8V1H2Z"/> -</svg> diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_medium.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_medium.svg deleted file mode 100644 index 15473d1a0..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/juno_severity_medium.svg +++ /dev/null @@ -1,11 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M15.7956 22H14.5955L15.7956 14.2222H11.5955C10.8994 14.2222 10.9114 13.8667 11.1395 13.4889C11.3675 13.1111 11.1995 13.4 11.2235 13.3556C12.7715 10.8222 15.0995 7.04444 18.1956 2L19.3956 2L18.1956 9.77778H22.3957C22.9837 9.77778 23.0677 10.1444 22.9597 10.3444L22.8757 10.5111C18.1476 18.1667 15.7956 22 15.7956 22Z"/> -<path d="M2 17H8V23H2V17Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9V15H8V9H2Z"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M7 2H3V6H7V2ZM2 1V7H8V1H2Z"/> -</svg> diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/icons/place.svg b/libs_deprecated/juno-ui-components/src/components/Icon/icons/place.svg deleted file mode 100644 index f65fb8ae4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/icons/place.svg +++ /dev/null @@ -1,6 +0,0 @@ -<!-- - ~ SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - ~ SPDX-License-Identifier: Apache-2.0 ---> - -<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg> \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Icon/index.js b/libs_deprecated/juno-ui-components/src/components/Icon/index.js deleted file mode 100644 index fe9173ac6..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Icon/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { Icon } from "./Icon.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.component.js b/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.component.js deleted file mode 100644 index e063a7262..000000000 --- a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.component.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import { Stack } from "../Stack/index" -import "./input-group.scss" -import PropTypes from "prop-types" - - - -/** A component to visually group Buttons, TextInput, and Select elements. */ -export const InputGroup = ({ - children, - className, - variant, - disabled, - ...props -}) => { - - const modifiedChildren = () => { - return React.Children.map(children, (child) => { - const ownVariant = child.props.variant || variant - const ownDisabled = child.props.disabled || disabled - return React.cloneElement(child, { - variant: ownVariant, - disabled: ownDisabled - }) - }) - } - - return ( - <Stack className={`juno-input-group juno-input-group-${variant} ${ disabled ? "juno-input-group-disabled" : "" } ${className}`} {...props}> - { modifiedChildren() } - </Stack> - ) -} - -InputGroup.propTypes = { - /** The children to render */ - children: PropTypes.node, - /** Pass a className to the group */ - className: PropTypes.string, - /** Passing a variant prop to the group will set all child Buttons and Select elements to use that variant, unless specified otherwise on the individual child component */ - variant: PropTypes.oneOf(["default", "primary", "primary-danger", "subdued"]), - /** Disable all elements in the InputGroup */ - disabled: PropTypes.bool, -} - -InputGroup.defaultProps = { - children: null, - className: undefined, - variant: "default", - disabled: false, -} diff --git a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.stories.js b/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.stories.js deleted file mode 100644 index 0b024c4a1..000000000 --- a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.stories.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { InputGroup } from './index.js'; -import { Button } from '../Button/index'; -import { NativeSelect } from '../NativeSelect/index'; -import { NativeSelectOption } from '../NativeSelectOption/index'; -import { TextInput } from '../TextInput/index'; - -export default { - title: 'WiP/InputGroup', - component: InputGroup, - argTypes: { - children: { - control: false, - }, - }, -}; - -export const Default = { - args: { - children: [<Button label="Button 1" />, <Button>Button 2</Button>, <Button label="Button 3" />], - }, -}; - -export const PrimaryInputGroup = { - args: { - variant: 'primary', - children: [ - <Button label="Primary Button" />, - <Button label="Primary Button" />, - <Button label="Primary Button" />, - ], - }, -}; - -export const PrimaryDangerInputGroup = { - args: { - variant: 'primary-danger', - children: [ - <Button label="Primary Danger Button" />, - <Button label="Primary Danger Button" variant="primary" />, - <Button label="Primary Danger Button" />, - ], - }, -}; - -export const SubduedInputGroup = { - args: { - variant: 'subdued', - children: [ - <Button label="Subdued Button" />, - <Button label="Subdued Button" />, - <Button label="Subdued Button" />, - ], - }, -}; - -export const Disabled = { - args: { - disabled: true, - children: [<Button label="Button" />, <Button label="Button" />, <Button label="Button" />], - }, -}; - -export const IconButtons = { - args: { - children: [<Button icon="home" />, <Button icon="help" />, <Button icon="forum" />], - }, -}; - -export const TextInputWithButton = { - args: { - children: [<TextInput placeholder="Enter a value…" />, <Button label="Submit" />], - }, -}; - -export const MultipleTextInputsWithButton = { - args: { - children: [ - <TextInput placeholder="First Name" />, - <TextInput placeholder="Last Name" />, - <Button label="Submit" />, - ], - }, -}; - -export const ButtonWithOptions = { - args: { - children: [ - <Button label="Button with Options" />, - <NativeSelect> - <NativeSelectOption value="1" label="Action 1" /> - <NativeSelectOption value="2" label="Action 2" /> - </NativeSelect>, - ], - }, -}; - -export const SelectWithTextInput = { - args: { - children: [ - <NativeSelect> - <NativeSelectOption value="1" label="Action 1" /> - <NativeSelectOption value="2" label="Action 2" /> - </NativeSelect>, - <TextInput placeholder="Value…" />, - ], - }, -}; - -export const TextInputWithButtonAndOptions = { - args: { - children: [ - <TextInput placeholder="Enter Value…" />, - <Button label="Submit" />, - <NativeSelect placeholder="Other Actions…"> - <NativeSelectOption value="1" label="Save" /> - <NativeSelectOption value="2" label="Delete" /> - </NativeSelect>, - ], - }, -}; - -export const SelectWithSelect = { - args: { - children: [ - <NativeSelect> - <NativeSelectOption value="1" label="Action 1" /> - <NativeSelectOption value="2" label="Action 2" /> - </NativeSelect>, - <NativeSelect> - <NativeSelectOption value="2-1" label="Action 1" /> - <NativeSelectOption value="2-2" label="Action 2" /> - </NativeSelect>, - ], - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.test.js b/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.test.js deleted file mode 100644 index a31890bfc..000000000 --- a/libs_deprecated/juno-ui-components/src/components/InputGroup/InputGroup.test.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { InputGroup } from "./index" -import { Button } from "../Button/index" -import { TextInput } from "../TextInput/index" -import { NativeSelect } from "../NativeSelect/index" -import { NativeSelectOption } from "../NativeSelectOption/index" - -describe("InputGroup", () => { - - test("renders an InputGroup", async () => { - render(<InputGroup />) - expect(document.querySelector(".juno-input-group")).toBeInTheDocument() - }) - - test("renders children as passed", async () => { - render( - <InputGroup> - <Button label="A Button" /> - <TextInput value="some value"/> - <NativeSelect> - <NativeSelectOption label="A Select Option" value="sel-opt-1" /> - <NativeSelectOption label="Another Select Option" value="sel-opt-2" /> - </NativeSelect> - </InputGroup> - ) - expect(document.querySelector(".juno-input-group")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toHaveTextContent("A Button") - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toHaveValue("some value") - expect(screen.getByRole("combobox")).toBeInTheDocument() // use listbox for radix-based select - }) - - test("renders child button variants as passed to parent", async () => { - render( - <InputGroup variant="primary-danger"> - <Button label="first" /> - <Button label="second" /> - <Button label="third" /> - </InputGroup> - ) - expect(screen.getByRole("button", { name: "first" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "first" })).toHaveClass("juno-button-primary-danger") - expect(screen.getByRole("button", { name: "second" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "second" })).toHaveClass("juno-button-primary-danger") - expect(screen.getByRole("button", { name: "third" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "third" })).toHaveClass("juno-button-primary-danger") - }) - - test("allows child button variant to override variant passed to parent", async () => { - render( - <InputGroup variant="primary-danger"> - <Button label="first" /> - <Button label="second" variant="primary"/> - <Button label="third" /> - </InputGroup> - ) - expect(screen.getByRole("button", { name: "first" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "first" })).toHaveClass("juno-button-primary-danger") - expect(screen.getByRole("button", { name: "second" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "second" })).not.toHaveClass("juno-button-primary-danger") - expect(screen.getByRole("button", { name: "second" })).toHaveClass("juno-button-primary") - expect(screen.getByRole("button", { name: "third" })).toBeInTheDocument() - expect(screen.getByRole("button", { name: "third" })).toHaveClass("juno-button-primary-danger") - }) - - test("disables all child elements as passed to parent", async () => { - render( - <InputGroup disabled> - <Button /> - <TextInput /> - <NativeSelect> - <NativeSelectOption label="A Select Option" value="sel-opt-1" /> - <NativeSelectOption label="Another Select Option" value="sel-opt-2" /> - </NativeSelect> - </InputGroup> - ) - expect(screen.getByRole("button")).toBeInTheDocument() - expect(screen.getByRole("button")).toBeDisabled() - expect(screen.getByRole("textbox")).toBeInTheDocument() - expect(screen.getByRole("textbox")).toBeDisabled() - expect(screen.getByRole("combobox")).toBeInTheDocument() - expect(screen.getByRole("combobox")).toBeDisabled() - }) - - test("renders a className a spassed", async () => { - render(<InputGroup className="my-class" />) - expect(document.querySelector(".juno-input-group")).toBeInTheDocument() - expect(document.querySelector(".juno-input-group")).toHaveClass("my-class") - }) - - test("renders all props as passed", async () => { - render(<InputGroup data-test="my-prop" />) - expect(document.querySelector(".juno-input-group")).toBeInTheDocument() - expect(document.querySelector(".juno-input-group")).toHaveAttribute("data-test", "my-prop") - }) - -}) - \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/InputGroup/index.js b/libs_deprecated/juno-ui-components/src/components/InputGroup/index.js deleted file mode 100644 index fb7cb5f96..000000000 --- a/libs_deprecated/juno-ui-components/src/components/InputGroup/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { InputGroup} from "./InputGroup.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/InputGroup/input-group.scss b/libs_deprecated/juno-ui-components/src/components/InputGroup/input-group.scss deleted file mode 100644 index d62f2f93a..000000000 --- a/libs_deprecated/juno-ui-components/src/components/InputGroup/input-group.scss +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors -// SPDX-License-Identifier: Apache-2.0 - -.juno-input-group { - - // remove border-radius where necessary - .juno-button, - .juno-textinput, - // this is weird for selects as is since these are inside a wrapper each and thus all qualify as first child, and potentially harder for radix-ui based selects, as we would need to select the Select button child?: - .juno-select { - &:not(:first-child, :last-child) { - border-radius: 0; - } - &:first-child { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - &:last-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - } - - // prevent double-borders for identical buttons next to each other: - .juno-button-default + .juno-button-default, - .juno-button-primary + .juno-button-primary, - .juno-button-default-primary-danger + .juno-button-primary-danger, - .juno-button-subdued + .juno-button-subdued { - border-left: 0; - } - -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.component.js b/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.component.js deleted file mode 100644 index fbf44d02c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.component.js +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from "react" -import PropTypes from "prop-types" - -const introbox = (variant, heroImage) => { - return ` - jn-bg-theme-introbox - jn-text-theme-default - jn-flex - jn-rounded-l - jn-overflow-hidden - jn-mb-8 - - ${ - variant === "hero" && heroImage - ? ` - jn-bg-right-top - jn-bg-no-repeat - ` - : "" - } - ` -} - -const introboxBorder = ` - jn-border-l-4 - jn-border-theme-introbox -` - -const introboxContent = (variant, heroImage) => { - return ` - ${heroImage ? `jn-pl-4 jn-pr-56` : `jn-px-4`} - - ${ - variant === "hero" - ? ` - jn-text-xl - jn-min-h-[8rem] - jn-py-4 - jn-flex - jn-flex-col - jn-justify-center - ` - : ` - jn-py-3 - ` - } - ` -} - -const introboxHeading = ` - jn-font-bold -` - -/** -* An Introbox holds generally important information to help understand the contents, purpose, or state of a whole page or view, or individual sections on longer pages. -Use sparingly, there should never be any two or more subsequent instances of Introbox as direct siblings/neighbors on an individual view. -*/ -export const IntroBox = ({ - title, - text, - variant, - heroImage, - className, - children, - ...props -}) => { - - - const isHeroWithImage = React.useMemo(() => { - return heroImage && variant === "hero" - }, [variant, heroImage]) - - return ( - <div - className={`juno-introbox ${introbox(variant, heroImage)} ${className}`} - style={isHeroWithImage ? {backgroundImage: `${heroImage}`} : {}} - {...props} - > - <div className={`${introboxBorder}`}></div> - <div className={`${introboxContent(variant, heroImage)}`}> - {title ? <h1 className={`${introboxHeading}`}>{title}</h1> : ""} - {children ? children : <p>{text}</p>} - </div> - </div> - ) -} - -IntroBox.propTypes = { - /** Pass an optional title */ - title: PropTypes.string, - /** Pass a string of text to be rendered as contents. Alternatively, contents can be passed as children (see below) */ - text: PropTypes.string, - /** Pass a custom class */ - variant: PropTypes.oneOf(["default", "hero"]), - /** optional "hero" flavor image for hero variant. Specify as css bg image string pointing to an image in your app (see template app for an example). Will always be positioned top and right */ - heroImage: PropTypes.string, - /** Pass a custom class */ - className: PropTypes.string, - /** Pass child nodes to be rendered as contents */ - children: PropTypes.node, -} - -IntroBox.defaultProps = { - title: null, - text: null, - variant: "default", - heroImage: null, - className: "", -} diff --git a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.stories.js b/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.stories.js deleted file mode 100644 index 969a00ee8..000000000 --- a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.stories.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { IntroBox } from './index.js'; -import heroImage from '../../img/app_bg_example.svg?url'; - -export default { - title: 'Components/IntroBox', - component: IntroBox, - argTypes: { - children: { - control: false, - }, - }, -}; - -export const Default = { - args: { - text: 'Default IntroBox.', - }, -}; - -export const WithTitle = { - args: { - title: 'IntroBox', - text: 'IntroBox with title.', - }, -}; - -export const Hero = { - args: { - title: 'IntroBox', - text: 'Hero IntroBox has a larger font size and more padding', - variant: 'hero', - }, -}; - -export const HeroWithBGImage = { - args: { - title: 'IntroBox', - text: 'Hero IntroBox with background image. Background image must be referenced as a css bg image string. Import svg images with query param ?url.', - variant: 'hero', - heroImage: `url(${heroImage})`, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.test.js b/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.test.js deleted file mode 100644 index 6ad0547c4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/IntroBox/IntroBox.test.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { IntroBox } from "./index" - -describe("IntroBox", () => { - test("renders an IntroBox", async () => { - render(<IntroBox data-testid="my-introbox" />) - expect(screen.getByTestId("my-introbox")).toBeInTheDocument() - }) - - test("renders an IntroBox with background image as passed if variant hero", async () => { - render( - <IntroBox - data-testid="my-introbox" - variant="hero" - heroImage="url('bg-fake-img')" - /> - ) - expect(screen.getByTestId("my-introbox")).toHaveStyle({backgroundImage: "url('bg-fake-img')"}) - }) - - test("renders an IntroBox without background image as passed if variant is not hero", async () => { - render( - <IntroBox - data-testid="my-introbox" - heroImage="url('bg-fake-img')" - /> - ) - expect(screen.getByTestId("my-introbox")).not.toHaveStyle({backgroundImage: "url('bg-fake-img')"}) - }) - - test("renders a title as passed", async () => { - render(<IntroBox data-testid="my-introbox" title="My IntroBox Heading" />) - expect(screen.getByTestId("my-introbox")).toHaveTextContent( - "My IntroBox Heading" - ) - }) - - test("renders a text as passed", async () => { - render( - <IntroBox data-testid="my-introbox" text="My IntroBox text goes here." /> - ) - expect( - screen.getByText((content, element) => { - return ( - element.tagName.toLowerCase() === "p" && - content.startsWith("My IntroBox text goes here.") - ) - }) - ).toBeTruthy() - }) - - test("renders a custom class as passed", async () => { - render(<IntroBox data-testid="my-introbox" className="my-custom-class" />) - expect(screen.getByTestId("my-introbox")).toHaveClass("my-custom-class") - }) - - test("renders children passed as children", async () => { - render( - <IntroBox data-testid="my-introbox"> - <div>My Introbox text in a div goes here!</div> - </IntroBox> - ) - expect( - screen.getByText((content, element) => { - return ( - element.tagName.toLowerCase() === "div" && - content.startsWith("My Introbox text in a div goes here!") - ) - }) - ).toBeTruthy() - }) - - test("renders text as passed as children if both children and 'text' prop were passed", async () => { - render( - <IntroBox data-testid="my-introbox" text="I should not be here."> - {"My Introbox children text goes here!"} - </IntroBox> - ) - expect(screen.getByTestId("my-introbox")).toHaveTextContent( - "My Introbox children text goes here!" - ) - }) - - test("renders other props as passed", async () => { - render( - <IntroBox data-testid="my-introbox" name="My shiny little IntroBox" /> - ) - expect(screen.getByTestId("my-introbox")).toHaveAttribute( - "name", - "My shiny little IntroBox" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/IntroBox/index.js b/libs_deprecated/juno-ui-components/src/components/IntroBox/index.js deleted file mode 100644 index 1c94008d4..000000000 --- a/libs_deprecated/juno-ui-components/src/components/IntroBox/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { IntroBox } from "./IntroBox.component" \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.component.js b/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.component.js deleted file mode 100644 index b4bdb7e30..000000000 --- a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.component.js +++ /dev/null @@ -1,543 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import PropTypes, { exact } from "prop-types" -import React, { useContext, useLayoutEffect } from "react" -import * as themes from "./themes" -import { SearchInput } from "../SearchInput/SearchInput.component" - -// DEFAULT THEME (DARK) -const DEFAULT_THEME = { - base00: "var(--color-syntax-highlight-base00)", // background - base01: "var(--color-syntax-highlight-base01)", // toolbar: border, background - base02: "var(--color-syntax-highlight-base02)", // border, type background, border - base03: "var(--color-syntax-highlight-base03)", // - - base04: "var(--color-syntax-highlight-base04)", // size - base05: "var(--color-syntax-highlight-base05)", // types: "undefined" - base06: "var(--color-syntax-highlight-base06)", // - - base07: "var(--color-syntax-highlight-base07)", // key, brace - base08: "var(--color-syntax-highlight-base08)", // types: "NaN" - base09: "var(--color-syntax-highlight-base09)", // ..., types: "string" - base0A: "var(--color-syntax-highlight-base0A)", // types: "null", "regex" - base0B: "var(--color-syntax-highlight-base0B)", // types: "float" - base0C: "var(--color-syntax-highlight-base0C)", // array index - base0D: "var(--color-syntax-highlight-base0D)", // expanded icon, types: "date", "function" - base0E: "var(--color-syntax-highlight-base0E)", // collapsed icon, types: "boolean" - base0F: "var(--color-syntax-highlight-base0F)", // copy icon, types: "integer" -} - -// indent size in pixel -const INDENTATION_SIZE = 5 -// default truncate size -const DEFAULT_TRUNCATE_LENGTH = 100 - -// map of color keys to theme -const colorMap = (theme) => ({ - background: theme.base00, - ellipsis: theme.base09, - brace: theme.base07, - key: theme.base07, - index: theme.base0C, - size: theme.base04, - border: theme.base02, - highlight: { - foreground: theme.base06, - background: theme.base02, - }, - toolbar: { - border: theme.base01, - background: theme.base01, - foreground: theme.base07, - }, - icon: { - expanded: theme.base0D, - collapsed: theme.base0E, - expandAll: theme.base0E, - }, - dataType: { - boolean: theme.base0E, - date: theme.base0D, - float: theme.base0B, - function: theme.base0D, - integer: theme.base0F, - string: theme.base09, - nan: theme.base08, - null: theme.base0A, - undefined: theme.base05, - regexp: theme.base0A, - background: theme.base02, - }, -}) - -// get type of value -const type = (value) => { - if (value === null) return "null" - if (Array.isArray(value)) return "array" - if (value instanceof RegExp) return "regex" - if (value instanceof Date) return "date" - const t = (typeof value).toLowerCase() - if (t === "number") { - if (Number.isNaN(value)) return "nan" - return Number.isInteger(value) ? "integer" : "float" - } else return t -} - -// Theme context to provide colors, ident size ect. in component tree -const ThemeContext = React.createContext(DEFAULT_THEME) - -// this component renders the expand icon depends on the expanded prop -// per entry -const ExpandIcon = ({ expanded }) => { - const { colors } = useContext(ThemeContext) - return ( - <svg - fill={expanded ? colors.icon.expanded : colors.icon.collapsed} - width="1em" - height="1em" - viewBox="0 0 1792 1792" - style={{ - verticalAlign: "middle", - color: "var(--color-syntax-highlight-base0E)", - height: "1em", - width: "1em", - }} - > - <title>Expand/Collapse - {expanded ? ( - - ) : ( - - )} - - ) -} - -// Toolbar Icon -const ExpandAllIcon = () => { - const { colors } = useContext(ThemeContext) - return ( - - Expand All - - - ) -} - -// Toolbar Icon -const CollapseAllIcon = () => { - const { colors } = useContext(ThemeContext) - return ( - - Collapse All - - - ) -} - -const StringWithHighlight = ({ value }) => { - const { colors, searchTerm } = useContext(ThemeContext) - - const highlight = React.useMemo(() => { - if ( - value === undefined || - value === null || - !searchTerm || - searchTerm === "" - ) - return null - - try { - const startIndex = value - .toString() - .toLowerCase() - .indexOf(searchTerm.toLowerCase()) - - if (startIndex < 0) return null - - return { start: startIndex, end: startIndex + searchTerm.length } - } catch (e) { - console.debug("JsonViewer:", e) - return null - } - }, [searchTerm]) - - return highlight ? ( - <> - {value.slice(0, highlight.start)} - - {value.slice(highlight.start, highlight.end)} - - {value.slice(highlight.end)} - - ) : ( - value - ) -} - -// Key label (left side) with highlight functionality -const NameLabel = ({ name }) => { - const { colors } = useContext(ThemeContext) - const isIndex = typeof name === "number" - const color = isIndex ? colors.index : colors.key - const label = isIndex ? name : `"${name}"` - - return ( - - {" "} - - - - {" : "} - - ) -} - -// this component show the right side of the json, type + value -// for null, NaN and undefined values a background is shown -// value label (left side) with highlight functionality -const TypeValueLabel = ({ type, value }) => { - const { colors, truncate } = useContext(ThemeContext) - let undefinedValue = ["nan", "null", "undefined"].includes(type) - let label = type === "string" ? `"${value}"` : `${value}` - if (truncate) { - const length = truncate === true ? DEFAULT_TRUNCATE_LENGTH : truncate - if (label.length > length) label = label.slice(0, length - 3) + "..." - } - - return ( - - {!undefinedValue && ( - - {type} - - )} - - - - - ) -} - -const Toolbar = () => { - const { colors, searchTerm, onExpandAll, onSearch } = useContext(ThemeContext) - - return ( -
- - onExpandAll(true)}> - - - onExpandAll(false)}> - - - - - onSearch(e.target.value)} - clear - onClear={() => onSearch(null)} - /> -
- ) -} - -// This component renders a row of json entry -const JsonData = ({ name, value, nestedLevel = 0 }) => { - const { colors, expanded, searchTerm, indentWidth, expandAll } = - useContext(ThemeContext) - const [isExpanded, setIsExpanded] = React.useState( - expanded === true || (expanded !== false && expanded > nestedLevel) - ) - - useLayoutEffect(() => { - if (!expandAll) return - setIsExpanded(expandAll.expanded) - }, [expandAll]) - - useLayoutEffect(() => { - if (value && searchTerm) { - try { - if (JSON.stringify(value).indexOf(searchTerm) > 0) setIsExpanded(true) - } catch (e) {} - } - }, [searchTerm]) - - const dataType = React.useMemo(() => type(value), [value]) - - const children = React.useMemo(() => { - if (dataType === "array") - return value.map((v, i) => ({ name: i, value: v })) - if (dataType === "object") - return Object.keys(value).map((key, i) => ({ - name: key, - value: value[key], - })) - return null - }, [dataType, value]) - - const ExpandButton = React.useCallback( - ({ children }) => ( - { - setIsExpanded(!isExpanded) - }} - > - {children} - - ), - [isExpanded, setIsExpanded] - ) - - return ( -
-
- {/* Expand Button */} - {children && ( - <> - - - {" "} - - )} - {/* NAME */} - {(name || name === 0) && } - - {/* show type and value if no children */} - {!children ? ( - // atomic value, not an array nor an object - - ) : ( - <> - - {dataType === "array" ? "[" : "{"} - - {!isExpanded && ( - <> - {/* Expand Icon */} - - ... - - - {dataType === "array" ? "]" : "}"} - - - )} - - {" "} - {children?.length} {children?.length === 1 ? "item" : "items"} - - - {isExpanded && ( - <> - {/* sub items */} -
- {children?.map((entry, i) => ( - - ))} -
- - {dataType === "array" ? "]" : "}"} - - - )} - - )} -
-
- ) -} - -/** A component to render json data in a nice way. */ -export const JsonViewer = ({ - data, - showRoot, - toolbar, - theme, - expanded, - indentWidth, - style, - truncate, - className, - ...props -}) => { - const currentTheme = (typeof theme === "string" && themes[theme]) || { - ...DEFAULT_THEME, - ...theme, - } - const colors = colorMap(currentTheme) - const [searchTerm, setSearchTerm] = React.useState("") - const [expandAll, setExpandAll] = React.useState(null) - - return ( - - setExpandAll({ expanded: v, timestamp: Date.now() }), - onSearch: (v) => setSearchTerm(v), - }} - > -
- {toolbar && } - -
-
- ) -} - -JsonViewer.propTypes = { - /** Pass a valid json. Required. */ - // data: PropTypes.object.isRequired, - data: PropTypes.oneOfType([PropTypes.object, PropTypes.array]).isRequired, - /** pass a styles object */ - style: PropTypes.object, - /** show toolbar */ - toolbar: PropTypes.bool, - /** show root key */ - showRoot: PropTypes.bool, - /** dark, light or map of colors - * - * @param base00 background - * @param base01 NOT used - * @param base02 border, NaN,null, undefined background - * @param base03 NOT used - * @param base04 size (x items) - * @param base05 type "undefined" - * @param base06 NOT used - * @param base07 key, brace - * @param base08 type "NaN" - * @param base09 ellipsis (...), type "string" - * @param base0A types: "null", "regex" - * @param base0B type "float" - * @param base0C index - * @param base0D expanded icon, types: "date", "function" - * @param base0E collapsed icon, types: "boolean" - * @param base0F copy icon, type "integer" - */ - theme: PropTypes.oneOfType([ - PropTypes.shape({ - base00: PropTypes.string, - base01: PropTypes.string, - base02: PropTypes.string, - base03: PropTypes.string, - base04: PropTypes.string, - base05: PropTypes.string, - base06: PropTypes.string, - base07: PropTypes.string, - base08: PropTypes.string, - base09: PropTypes.string, - base0A: PropTypes.string, - base0B: PropTypes.string, - base0C: PropTypes.string, - base0D: PropTypes.string, - base0E: PropTypes.string, - base0F: PropTypes.string, - }), - PropTypes.oneOf(["dark", "light"]), - ]), - /** expanded can be true|false or a number. The number denotes the hierarchy level to which the object is expanded. */ - expanded: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]), - // cut strings after max length is reached, default length is 100 characters, if set to true. Or specifcy a different character length. */ - truncate: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), - /* indent width */ - indentWidth: PropTypes.number, - /* add custom classes */ - className: PropTypes.string, -} - -JsonViewer.defaultProps = { - showRoot: false, - indentWidth: 4, - toolbar: false, - expanded: 1, - truncate: false, - style: undefined, - data: {}, - theme: null, -} diff --git a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.stories.js b/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.stories.js deleted file mode 100644 index f516fbf97..000000000 --- a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.stories.js +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { JsonViewer } from './index.js'; - -export default { - title: 'Components/JsonViewer', - component: JsonViewer, - description: 'TEST', - argTypes: {}, - parameters: { - controls: { sort: 'alpha' }, - }, -}; - -const data = { - id: 9, - date: new Date(), - getPrice: () => `$12`, - regex: /^(.+)$/, - nan: NaN, - null: null, - title: 'Infinix INBOOK', - description: 'Infinix Inbook X1 Ci3 10th 8GB...', - price: 1099, - discountPercentage: 11.83, - rating: 4.54, - stock: 96, - available: true, - array: [], - brand: 'Infinix', - category: 'laptops', - thumbnail: 'https://i.dummyjson.com/data/products/9/thumbnail.jpg', - test: 'https://i.dummyjson.com/data/products/9/thumbnail.jpg?xxxxxxxxxxxxxxxxnnnnnnnnnnnnnnnnnnnnnnnndddddddddddddddddddddddddddddddd', - test2: - 'LoremipsumdolorsitametconsectetueradipiscingelitAeneancommodoligulaegetdolorAeneanmassaCumsociisnatoquepenatibusetmagnisdisparturientmontesnasceturridiculus', - images: [ - 'https://i.dummyjson.com/data/products/9/1.jpg', - 'https://i.dummyjson.com/data/products/9/2.png', - 'https://i.dummyjson.com/data/products/9/3.png', - 'https://i.dummyjson.com/data/products/9/4.jpg', - 'https://i.dummyjson.com/data/products/9/thumbnail.jpg', - ], -}; - -const dataAsArray = [{hello: ["word", "world", "wod"], foo: "bar"}, {arrays: "are", fun: "to", work: "with, too"}]; - -export const Default = { - args: { - data, - }, -}; - -export const ArrayData = { - args: { - data: dataAsArray, - }, -}; - -export const Light = { - args: { - theme: 'light', - toolbar: true, - data, - }, -}; - -export const Expanded = { - args: { - expanded: true, - data, - }, -}; - -export const WithToolbar = { - args: { - expanded: 1, - toolbar: true, - data, - }, -}; - -export const CustomTheme = { - args: { - theme: { - base00: 'rgb(39, 40, 34)', - base01: 'rgba(73, 72, 62,0.8)', - base02: 'rgb(73, 72, 62)', - base03: '#93a1a1', - base04: 'rgb(165, 159, 133)', - base05: 'rgb(248, 248, 242)', - base06: '#073642', - base07: 'rgb(249, 248, 245)', - base08: 'rgb(249, 38, 114)', - base09: 'rgb(253, 151, 31)', - base0A: 'rgb(244, 191, 117)', - base0B: 'rgb(166, 226, 46)', - base0C: 'rgb(161, 239, 228)', - base0D: 'rgb(102, 217, 239)', - base0E: 'rgb(174, 129, 255)', - base0F: 'rgb(204, 102, 51)', - }, - data: { ...data, test2: undefined }, - toolbar: true, - truncate: false, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.test.js b/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.test.js deleted file mode 100644 index d484e818c..000000000 --- a/libs_deprecated/juno-ui-components/src/components/JsonViewer/JsonViewer.test.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen } from "@testing-library/react" -import { JsonViewer } from "./index" - -describe("JsonViewer", () => { - test("renders json data", async () => { - await render() - expect(screen.getByTestId("my-json-viewer")).toBeInTheDocument() - }) - - - test("renders a custom class as passed", async () => { - await render() - expect(screen.getByTestId("my-json-viewer")).toHaveClass("my-custom-class") - }) - - test("renders other props as passed", async () => { - await render() - expect(screen.getByTestId("my-json-viewer")).toHaveAttribute( - "name", - "My shiny JsonViewer" - ) - }) -}) diff --git a/libs_deprecated/juno-ui-components/src/components/JsonViewer/index.js b/libs_deprecated/juno-ui-components/src/components/JsonViewer/index.js deleted file mode 100644 index 17a79c07f..000000000 --- a/libs_deprecated/juno-ui-components/src/components/JsonViewer/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export { JsonViewer } from "./JsonViewer.component" diff --git a/libs_deprecated/juno-ui-components/src/components/JsonViewer/themes.js b/libs_deprecated/juno-ui-components/src/components/JsonViewer/themes.js deleted file mode 100644 index 112163045..000000000 --- a/libs_deprecated/juno-ui-components/src/components/JsonViewer/themes.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export const dark = { - base00: "rgb(39, 40, 34)", - base01: "rgb(245, 245, 245)", - base02: "rgb(73, 72, 62)", - base03: "#93a1a1", - base04: "rgb(165, 159, 133)", - base05: "rgb(248, 248, 242)", - base06: "#073642", - base07: "rgb(249, 248, 245)", - base08: "rgb(249, 38, 114)", - base09: "rgb(253, 151, 31)", - base0A: "rgb(244, 191, 117)", - base0B: "rgb(166, 226, 46)", - base0C: "rgb(161, 239, 228)", - base0D: "rgb(102, 217, 239)", - base0E: "rgb(174, 129, 255)", - base0F: "rgb(204, 102, 51)", -} - -export const light = { - base00: "#fff", - base01: "rgb(245, 245, 245)", - base02: "rgb(235, 235, 235)", - base03: "#93a1a1", - base04: "rgba(0, 0, 0, 0.3)", - base05: "#586e75", - base06: "#073642", - base07: "#002b36", - base08: "#d33682", - base09: "#cb4b16", - base0A: "#dc322f", - base0B: "#859900", - base0C: "#6c71c4", - base0D: "#586e75", - base0E: "#2aa198", - base0F: "#268bd2", -} diff --git a/libs_deprecated/juno-ui-components/src/components/Label/Label.component.js b/libs_deprecated/juno-ui-components/src/components/Label/Label.component.js deleted file mode 100644 index 41c532c80..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Label/Label.component.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React, { useRef } from "react" -import PropTypes from "prop-types" - -const labelstyles = ` - jn-text-theme-high - jn-text-base - jn-transform - jn-origin-top-left - jn-transition-all - jn-duration-100 - jn-ease-in-out - jn-z-10 -` - -const floatingStyles = ` - jn-absolute -` - -const minimizedStyles = ` - jn-scale-75 - -jn-translate-y-[0.4375rem] -` - -const requiredstyles = ` - jn-inline-block - jn-w-1 - jn-h-1 - jn-rounded-full - jn-align-top - jn-ml-1 - jn-mt-2 - jn-bg-theme-required -` - -const disabledstyles = ` - jn-opacity-50 - jn-cursor-not-allowed -` - -/** -* A re-usable Label component -*/ - -export const Label = React.forwardRef( - ( - { - text, - htmlFor, - required, - disabled, - floating, - minimized, - className, - ...props - }, forwardedRef ) => { - return ( - - ) -}) - -Label.propTypes = { - /** Pass a string of text to be rendered as contents. Required. */ - text: PropTypes.string, - /** An Id of an input element to associate the label with */ - htmlFor: PropTypes.string, - /** Required */ - required: PropTypes.bool, - /** Pass a className */ - className: PropTypes.string, - /** Label for a disabled input */ - disabled: PropTypes.bool, - /** Whether the label is floating */ - floating: PropTypes.bool, - /** Whether the label is minimized. Requires `floating` set to TRUE, otherwise it will have no effect. */ - minimized: PropTypes.bool, -} - -Label.defaultProps = { - text: "", - htmlFor: undefined, - required: false, - className: "", - disabled: false, - floating: false, - minimized: false, -} \ No newline at end of file diff --git a/libs_deprecated/juno-ui-components/src/components/Label/Label.stories.js b/libs_deprecated/juno-ui-components/src/components/Label/Label.stories.js deleted file mode 100644 index 68a1dad7b..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Label/Label.stories.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { Label } from './index.js'; - -export default { - title: 'Forms/Label', - component: Label, - argTypes: {}, -}; - -export const Default = { - args: { - text: 'My Label', - }, -}; - -export const Disabled = { - args: { - text: 'My disabled label', - disabled: true, - }, -}; - -export const Required = { - args: { - text: 'My required label', - required: true, - }, -}; diff --git a/libs_deprecated/juno-ui-components/src/components/Label/Label.test.js b/libs_deprecated/juno-ui-components/src/components/Label/Label.test.js deleted file mode 100644 index 7efd0a072..000000000 --- a/libs_deprecated/juno-ui-components/src/components/Label/Label.test.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Juno contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as React from "react" -import { render, screen} from "@testing-library/react" -import { Label } from "./index" - -describe("Label", () => { - - test("renders a label with a text as passed", async () => { - render(