diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index 51c6b0baf..4a57e25d8 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -6,6 +6,69 @@ font-style: normal; } + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Thin.ttf") format("truetype"); + font-weight: 100; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-ExtraLight.ttf") format("truetype"); + font-weight: 200; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Light.ttf") format("truetype"); + font-weight: 300; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Medium.ttf") format("truetype"); + font-weight: 500; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Medium.ttf") format("truetype"); + font-weight: 600; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-SemiBold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Bold.ttf") format("truetype"); + font-weight: 800; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Black.ttf") format("truetype"); + font-weight: 900; + font-style: normal; + } + #storybook-root { height: 100%; } diff --git a/Dockerfile b/Dockerfile index 0a9b3f6a2..2e98330e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM nginx:1.25.0 +FROM nginx:1.27.2 COPY ./dist/ /usr/share/nginx/html/ COPY ./nginx.conf.template /etc/nginx/conf.d/default.conf.template RUN rm /usr/share/nginx/html/index.html -CMD ["/bin/sh" , "-c" , "envsubst '${PLUGIN_API_URL} ${PLUGIN_API_TOKEN}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"] \ No newline at end of file +CMD ["/bin/sh" , "-c" , "cp /etc/nginx/conf.d/default.conf.template /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"] \ No newline at end of file diff --git a/assets/index.web.ejs b/assets/index.web.ejs index bfa5ab8a6..e031f38a5 100644 --- a/assets/index.web.ejs +++ b/assets/index.web.ejs @@ -9,6 +9,69 @@ font-weight: 500; font-style: normal; } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Thin.ttf") format("truetype"); + font-weight: 100; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-ExtraLight.ttf") format("truetype"); + font-weight: 200; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Light.ttf") format("truetype"); + font-weight: 300; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Medium.ttf") format("truetype"); + font-weight: 500; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Medium.ttf") format("truetype"); + font-weight: 600; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-SemiBold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Bold.ttf") format("truetype"); + font-weight: 800; + font-style: normal; + } + + @font-face { + font-family: "Alexandria"; + src: url("/fonts/Alexandria-Black.ttf") format("truetype"); + font-weight: 900; + font-style: normal; + } diff --git a/nginx.conf.template b/nginx.conf.template index efff1e1d5..475513e7d 100644 --- a/nginx.conf.template +++ b/nginx.conf.template @@ -1,15 +1,5 @@ -map "${PLUGIN_API_TOKEN}" $headerValue { - "" ""; - "~*^(.+)$" "Token $1"; -} - server { listen 80; root /usr/share/nginx/html; absolute_redirect off; - - location /api/ { - proxy_pass ${PLUGIN_API_URL}/; - proxy_set_header Authorization $headerValue; - } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8448bf711..a60e0136e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "digma-ui", - "version": "1.1.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digma-ui", - "version": "1.1.0", + "version": "2.0.0", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.25.1", diff --git a/package.json b/package.json index 29ff8a2b1..72c25ee78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "digma-ui", - "version": "1.1.0", + "version": "2.0.0", "description": "Digma UI", "main": "dist/index.js", "scripts": { @@ -15,6 +15,7 @@ "build-storybook": "storybook build", "build:dashboard:dev": "webpack --config webpack.dev.ts --env app=dashboard", "build:documentation:dev": "webpack --config webpack.dev.ts --env app=documentation", + "build:ide-launcher:dev": "webpack --config webpack.dev.ts --env app=ideLauncher", "build:installation-wizard:dev": "webpack --config webpack.dev.ts --env app=installationWizard", "build:main:dev": "webpack --config webpack.dev.ts --env app=main", "build:notifications:dev": "webpack --config webpack.dev.ts --env app=notifications", @@ -24,6 +25,7 @@ "build:dev:web": "webpack --config webpack.dev.ts --env platform=Web", "build:dashboard:prod": "webpack --config webpack.prod.ts --env app=dashboard", "build:documentation:prod": "webpack --config webpack.prod.ts --env app=documentation", + "build:ide-launcher:prod": "webpack --config webpack.prod.ts --env app=ideLauncher", "build:installation-wizard:prod": "webpack --config webpack.prod.ts --env app=installationWizard", "build:main:prod": "webpack --config webpack.prod.ts --env app=main", "build:notifications:prod": "webpack --config webpack.prod.ts --env app=notifications", diff --git a/public/fonts/Alexandria-Black.ttf b/public/fonts/Alexandria-Black.ttf new file mode 100644 index 000000000..a16503cb2 Binary files /dev/null and b/public/fonts/Alexandria-Black.ttf differ diff --git a/public/fonts/Alexandria-Bold.ttf b/public/fonts/Alexandria-Bold.ttf new file mode 100644 index 000000000..911d48c5b Binary files /dev/null and b/public/fonts/Alexandria-Bold.ttf differ diff --git a/public/fonts/Alexandria-ExtraBold.ttf b/public/fonts/Alexandria-ExtraBold.ttf new file mode 100644 index 000000000..ebb205981 Binary files /dev/null and b/public/fonts/Alexandria-ExtraBold.ttf differ diff --git a/public/fonts/Alexandria-ExtraLight.ttf b/public/fonts/Alexandria-ExtraLight.ttf new file mode 100644 index 000000000..3dc2c5454 Binary files /dev/null and b/public/fonts/Alexandria-ExtraLight.ttf differ diff --git a/public/fonts/Alexandria-Light.ttf b/public/fonts/Alexandria-Light.ttf new file mode 100644 index 000000000..2982949de Binary files /dev/null and b/public/fonts/Alexandria-Light.ttf differ diff --git a/public/fonts/Alexandria-Medium.ttf b/public/fonts/Alexandria-Medium.ttf new file mode 100644 index 000000000..c98ee3585 Binary files /dev/null and b/public/fonts/Alexandria-Medium.ttf differ diff --git a/public/fonts/Alexandria-Regular.ttf b/public/fonts/Alexandria-Regular.ttf new file mode 100644 index 000000000..bd9a4552a Binary files /dev/null and b/public/fonts/Alexandria-Regular.ttf differ diff --git a/public/fonts/Alexandria-SemiBold.ttf b/public/fonts/Alexandria-SemiBold.ttf new file mode 100644 index 000000000..73caf111c Binary files /dev/null and b/public/fonts/Alexandria-SemiBold.ttf differ diff --git a/public/fonts/Alexandria-Thin.ttf b/public/fonts/Alexandria-Thin.ttf new file mode 100644 index 000000000..630aa5451 Binary files /dev/null and b/public/fonts/Alexandria-Thin.ttf differ diff --git a/src/components/IdeLauncher/IdeLauncher.stories.tsx b/src/components/IdeLauncher/IdeLauncher.stories.tsx new file mode 100644 index 000000000..5ca0f19cc --- /dev/null +++ b/src/components/IdeLauncher/IdeLauncher.stories.tsx @@ -0,0 +1,19 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { IdeLauncher } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "IDE Launcher/IdeLauncher", + component: IdeLauncher, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: "fullscreen" + } +}; + +export default meta; + +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = {}; diff --git a/src/components/IdeLauncher/index.tsx b/src/components/IdeLauncher/index.tsx new file mode 100644 index 000000000..be52f30ba --- /dev/null +++ b/src/components/IdeLauncher/index.tsx @@ -0,0 +1,171 @@ +import axios from "axios"; +import { useEffect, useState } from "react"; +import { Helmet } from "react-helmet"; +import { useTheme } from "styled-components"; +import { isString } from "../../typeGuards/isString"; +import { getThemeKind } from "../common/App/styles"; +import { Select } from "../common/v3/Select"; +import { SelectItem } from "../common/v3/Select/types"; +import { scanIDEs } from "./scanIDEs"; +import * as s from "./styles"; + +const SELECT_VALUE_DELIMITER = ":"; + +const getURLQueryParams = (url: string) => { + const searchParams = new URLSearchParams(url); + const params: Record = {}; + for (const [key, value] of searchParams.entries()) { + params[key] = value; + } + return params; +}; + +export const IdeLauncher = () => { + const theme = useTheme(); + const themeKind = getThemeKind(theme); + const [isInitialLoading, setInitialLoading] = useState(true); + // const [isOpening, setIsOpening] = useState(false); + const [items, setItems] = useState([]); + const params = getURLQueryParams(window.location.search); + const isMobile = ["Android", "iPhone", "iPad"].some((x) => + window.navigator.userAgent.includes(x) + ); + + const handleSelectChange = (value: string | string[]) => { + const selectedValue = isString(value) ? value : value[0]; + const [port, project] = selectedValue.split(SELECT_VALUE_DELIMITER); + + const pluginParams = Object.entries(params).reduce((acc, [key, value]) => { + const KEY_PREFIX = "plugin."; + if (key.startsWith(KEY_PREFIX)) { + const newKey = key.replace(KEY_PREFIX, ""); + acc[newKey] = value; + } + + return acc; + }, {} as Record); + + axios + .get(`http://localhost:${port}/api/digma/show`, { + params: { ...pluginParams, projectName: project } + }) + .then(() => { + // TODO: handle response + }) + .catch(() => { + // TODO: handle error + }); + + // setIsOpening(true); + + const itemToSelect = items.find((item) => item.value === selectedValue); + setItems( + items.map((item) => ({ ...item, selected: item === itemToSelect })) + ); + }; + + useEffect(() => { + async function getIDEsInfo() { + const ideInfo = await scanIDEs(); + const projects = ideInfo + .filter((x) => x.response.isCentralized) + .flatMap((info) => + info.response.openProjects.map((project) => ({ + ...info, + project: project, + port: info.port + })) + ); + + setItems( + projects.map((x) => ({ + label: `${x.response.name} (${x.project})`, + description: `${x.response.name} (${x.project})`, + value: [x.port, x.project].join(SELECT_VALUE_DELIMITER), + enabled: true, + selected: false + })) + ); + setInitialLoading(false); + } + + if (!isMobile) { + void getIDEsInfo(); + } + }, [isMobile]); + + const selectedItem = items.find((item) => item.selected); + + const renderContent = () => { + if (isMobile) { + return ( + + Failed to open + + This cannot be opened on your mobile device. Please switch to a + desktop with an IDE installed. + + + ); + } + + return isInitialLoading ? ( + <>Scanning running IDEs... + ) : ( + <> + + Select an IDE to view the Digma issue + + {items.length > 0 ? ( + <> + Please select the IDE project you'd like to open all + endpoints in the {params.environment ?? "selected"} environment. + + ) : ( + <>No IDEs with enabled Digma plugin found + )} + + + {items.length > 0 && ( + +