From 999a5094bb4179c35d1a505cdb5572c3e1a2229b Mon Sep 17 00:00:00 2001 From: Himanshu DIxit Date: Sun, 21 Feb 2021 06:23:56 +0530 Subject: [PATCH] Prettify: Add basic indentation hygiene --- frontend/.babelrc | 32 ++-- frontend/README.md | 12 +- frontend/docker-compose.yml | 10 +- frontend/package.json | 3 +- frontend/src/actions/metrics.ts | 7 +- frontend/src/actions/types.ts | 2 +- frontend/src/actions/usage.ts | 11 +- frontend/src/api/graphQuery.js | 4 +- frontend/src/api/metricsAPI.js | 2 +- frontend/src/api/submitForm.js | 4 +- frontend/src/api/tracesAPI.js | 4 +- frontend/src/assets/index.css | 4 +- frontend/src/components/App.tsx | 40 ++-- frontend/src/components/AppWrapper.tsx | 11 +- frontend/src/components/DateTimeSelector.tsx | 150 ++++++++------- frontend/src/components/Signup.tsx | 2 +- frontend/src/components/Test.tsx | 10 +- frontend/src/components/common/Modal.tsx | 32 ++-- .../components/metrics/LatencyLineChart.tsx | 2 +- .../src/components/metrics/ServiceMetrics.tsx | 16 +- .../src/components/metrics/ServicesTable.tsx | 126 ++++++++----- .../src/components/settings/settingsPage.tsx | 43 ++--- .../components/traces/LatencyModalForm.tsx | 5 +- .../src/components/traces/TraceFilter.tsx | 44 +++-- frontend/src/components/traces/TraceGraph.tsx | 10 +- frontend/src/components/traces/TraceList.tsx | 21 ++- .../src/components/usage/UsageExplorer.tsx | 178 ++++++++++++------ frontend/src/constants/app.ts | 4 +- frontend/src/constants/query.ts | 3 +- frontend/src/index.tsx | 5 +- frontend/src/reducers/global.ts | 2 +- frontend/src/utils/app.ts | 4 +- frontend/src/utils/timeUtils.ts | 8 +- frontend/src/utils/token.ts | 6 +- frontend/webpack.config.js | 108 +++++------ frontend/webpack.config.prod.js | 98 +++++----- 36 files changed, 578 insertions(+), 445 deletions(-) diff --git a/frontend/.babelrc b/frontend/.babelrc index 847a76873a..aa9ef302a0 100644 --- a/frontend/.babelrc +++ b/frontend/.babelrc @@ -1,18 +1,16 @@ { - "presets": [ - "@babel/preset-env", - "@babel/preset-react", - "@babel/preset-typescript" - ], - "plugins": [ - "react-hot-loader/babel", - "@babel/plugin-proposal-class-properties" - ], - "env": { - "production": { - "presets": [ - "minify" - ] - } - } -} \ No newline at end of file + "presets": [ + "@babel/preset-env", + "@babel/preset-react", + "@babel/preset-typescript" + ], + "plugins": [ + "react-hot-loader/babel", + "@babel/plugin-proposal-class-properties" + ], + "env": { + "production": { + "presets": ["minify"] + } + } +} diff --git a/frontend/README.md b/frontend/README.md index 7d49534da5..f7b2c32e01 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,14 +1,12 @@ +# Docker - # Docker - **Building image** +**Building image** -```docker-compose up`` +``docker-compose up` / This will also run or -```docker build . -t tagname``` - - +`docker build . -t tagname` **Tag to remote url- Introduce versinoing later on** @@ -16,7 +14,7 @@ or docker tag signoz/frontend:latest 7296823551/signoz:latest ``` - **Running locally** +**Running locally** ``` docker-compose up diff --git a/frontend/docker-compose.yml b/frontend/docker-compose.yml index 4e9043fb08..2a451ded94 100644 --- a/frontend/docker-compose.yml +++ b/frontend/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.9" services: - web: - build: . - image: signoz/frontend:latest - ports: - - "3000:3000" \ No newline at end of file + web: + build: . + image: signoz/frontend:latest + ports: + - "3000:3000" diff --git a/frontend/package.json b/frontend/package.json index b93f67510b..0141493ea0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "NODE_ENV=development webpack serve", "start": "node scripts/start.js", - "build": "webpack --config=webpack.config.prod.js" + "build": "webpack --config=webpack.config.prod.js", + "prettify": "prettier --write ." }, "author": "", "license": "ISC", diff --git a/frontend/src/actions/metrics.ts b/frontend/src/actions/metrics.ts index 1c117696a6..33177772e0 100644 --- a/frontend/src/actions/metrics.ts +++ b/frontend/src/actions/metrics.ts @@ -2,7 +2,7 @@ import { Dispatch } from "redux"; import metricsAPI from "../api/metricsAPI"; import { GlobalTime } from "./global"; import { ActionTypes } from "./types"; -import {Token} from "../utils/token"; +import { Token } from "../utils/token"; import { toUTCEpoch } from "../utils/timeUtils"; export interface servicesListItem { @@ -61,7 +61,8 @@ export interface getFilteredTraceMetricsAction { export const getServicesList = (globalTime: GlobalTime) => { return async (dispatch: Dispatch) => { - let request_string = "services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime; + let request_string = + "services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime; const response = await metricsAPI.get(request_string); @@ -125,7 +126,7 @@ export const getFilteredTraceMetrics = ( return async (dispatch: Dispatch) => { let request_string = "spans/aggregates?start=" + - toUTCEpoch( globalTime.minTime) + + toUTCEpoch(globalTime.minTime) + "&end=" + toUTCEpoch(globalTime.maxTime) + "&" + diff --git a/frontend/src/actions/types.ts b/frontend/src/actions/types.ts index d27e582ea4..12a1ca15f1 100644 --- a/frontend/src/actions/types.ts +++ b/frontend/src/actions/types.ts @@ -10,7 +10,7 @@ import { getUsageDataAction } from "./usage"; import { updateTimeIntervalAction } from "./global"; export enum ActionTypes { - updateTraceFilters= "UPDATE_TRACES_FILTER", + updateTraceFilters = "UPDATE_TRACES_FILTER", updateInput = "UPDATE_INPUT", fetchTraces = "FETCH_TRACES", fetchTraceItem = "FETCH_TRACE_ITEM", diff --git a/frontend/src/actions/usage.ts b/frontend/src/actions/usage.ts index 415038cbf3..356aa2c327 100644 --- a/frontend/src/actions/usage.ts +++ b/frontend/src/actions/usage.ts @@ -14,9 +14,16 @@ export interface getUsageDataAction { payload: usageDataItem[]; } -export const getUsageData = (minTime: number, maxTime: number, step: number, service: string) => { +export const getUsageData = ( + minTime: number, + maxTime: number, + step: number, + service: string, +) => { return async (dispatch: Dispatch) => { - let request_string = `usage?start=${toUTCEpoch(minTime)}&end=${toUTCEpoch(maxTime)}&step=${step}&service=${service ? service : ""}`; + let request_string = `usage?start=${toUTCEpoch(minTime)}&end=${toUTCEpoch( + maxTime, + )}&step=${step}&service=${service ? service : ""}`; //Step can only be multiple of 3600 const response = await metricsAPI.get(request_string); diff --git a/frontend/src/api/graphQuery.js b/frontend/src/api/graphQuery.js index 0aec9c5bce..e1191b1be0 100644 --- a/frontend/src/api/graphQuery.js +++ b/frontend/src/api/graphQuery.js @@ -1,8 +1,8 @@ import axios from "axios"; import { ENVIRONMENT } from "../constants/env"; -import {Token} from "../utils/token"; +import { Token } from "../utils/token"; // No auth for the API export default axios.create({ - baseURL: `${ENVIRONMENT.baseURL}/api/prom/api/v1` + baseURL: `${ENVIRONMENT.baseURL}/api/prom/api/v1`, }); diff --git a/frontend/src/api/metricsAPI.js b/frontend/src/api/metricsAPI.js index 04ca97bf1e..ca1366b7e3 100644 --- a/frontend/src/api/metricsAPI.js +++ b/frontend/src/api/metricsAPI.js @@ -2,5 +2,5 @@ import axios from "axios"; import { ENVIRONMENT } from "../constants/env"; export default axios.create({ - baseURL: `${ENVIRONMENT.baseURL}/api/v1/` + baseURL: `${ENVIRONMENT.baseURL}/api/v1/`, }); diff --git a/frontend/src/api/submitForm.js b/frontend/src/api/submitForm.js index 92b030e59d..e52fc85b41 100644 --- a/frontend/src/api/submitForm.js +++ b/frontend/src/api/submitForm.js @@ -1,12 +1,12 @@ import axios from "axios"; import { ENVIRONMENT } from "../constants/env"; -import {Token} from "../utils/token"; +import { Token } from "../utils/token"; export default axios.create({ // baseURL: 'https://api.telegram.org/bot1518273960:AAHcgVvym9a0Qkl-PKiCI84X1VZaVbkTud0/', // baseURL: 'http://104.211.113.204:8080/api/v1/', // baseURL: "/api/v1/", - baseURL: `${ENVIRONMENT.baseURL}/api/v1/` + baseURL: `${ENVIRONMENT.baseURL}/api/v1/`, }); //https://api.telegram.org/bot1518273960:AAHcgVvym9a0Qkl-PKiCI84X1VZaVbkTud0/sendMessage?chat_id=351813222&text=Hello%20there diff --git a/frontend/src/api/tracesAPI.js b/frontend/src/api/tracesAPI.js index 5eac0da5d4..b8064c91a1 100644 --- a/frontend/src/api/tracesAPI.js +++ b/frontend/src/api/tracesAPI.js @@ -1,6 +1,6 @@ import axios from "axios"; import { ENVIRONMENT } from "../constants/env"; -import {Token} from "../utils/token"; +import { Token } from "../utils/token"; //import { format } from 'path'; export default axios.create({ @@ -8,5 +8,5 @@ export default axios.create({ // baseURL: process.env.QUERY_SERVICE_URL, // console.log('in traces API', process.env.QUERY_SERVICE_URL) // baseURL: "/api/v1/", - baseURL: `${ENVIRONMENT.baseURL}/api/v1/` + baseURL: `${ENVIRONMENT.baseURL}/api/v1/`, }); diff --git a/frontend/src/assets/index.css b/frontend/src/assets/index.css index 4068baefb3..1efc7ce2a1 100644 --- a/frontend/src/assets/index.css +++ b/frontend/src/assets/index.css @@ -1,8 +1,8 @@ @import "~antd/dist/antd.dark.css"; @import "~antd/dist/antd.compact.css"; -.ant-space-item{ - margin-right: 0 !important; +.ant-space-item { + margin-right: 0 !important; } /* #components-layout-demo-side .logo { height: 32px; diff --git a/frontend/src/components/App.tsx b/frontend/src/components/App.tsx index ed03b54aa8..078fda147c 100644 --- a/frontend/src/components/App.tsx +++ b/frontend/src/components/App.tsx @@ -14,7 +14,7 @@ import { DeploymentUnitOutlined, AlignLeftOutlined, AppstoreOutlined, - SettingOutlined + SettingOutlined, } from "@ant-design/icons"; import DateTimeSelector from "Src/components/DateTimeSelector"; @@ -23,14 +23,28 @@ import styled from "styled-components"; const { Content, Footer, Sider } = Layout; -const ServiceMetrics = React.lazy(() => import("Src/components/metrics/ServiceMetricsDef")); -const ServiceMap = React.lazy(() => import("Src/components/servicemap/ServiceMap")); -const TraceDetail = React.lazy(() => import("Src/components/traces/TraceDetail")); -const TraceGraph = React.lazy(() => import("Src/components/traces/TraceGraphDef")); -const UsageExplorer = React.lazy(() => import("Src/components/usage/UsageExplorerDef")); -const ServicesTable = React.lazy(() => import("Src/components/metrics/ServicesTableDef")); - const Signup = React.lazy(() => import('Src/components/Signup')); -const SettingsPage = React.lazy(() => import("Src/components/settings/settingsPage")); +const ServiceMetrics = React.lazy( + () => import("Src/components/metrics/ServiceMetricsDef"), +); +const ServiceMap = React.lazy( + () => import("Src/components/servicemap/ServiceMap"), +); +const TraceDetail = React.lazy( + () => import("Src/components/traces/TraceDetail"), +); +const TraceGraph = React.lazy( + () => import("Src/components/traces/TraceGraphDef"), +); +const UsageExplorer = React.lazy( + () => import("Src/components/usage/UsageExplorerDef"), +); +const ServicesTable = React.lazy( + () => import("Src/components/metrics/ServicesTableDef"), +); +const Signup = React.lazy(() => import("Src/components/Signup")); +const SettingsPage = React.lazy( + () => import("Src/components/settings/settingsPage"), +); //PNOTE //React. lazy currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that tree shaking keeps working and that you don't pull in unused components. @@ -93,7 +107,7 @@ const App = () => { Metrics - }> + }> Traces @@ -115,10 +129,7 @@ const App = () => { }> - + Settings @@ -148,7 +159,6 @@ const App = () => { - diff --git a/frontend/src/components/AppWrapper.tsx b/frontend/src/components/AppWrapper.tsx index 26d9257d53..82964e72cf 100644 --- a/frontend/src/components/AppWrapper.tsx +++ b/frontend/src/components/AppWrapper.tsx @@ -1,18 +1,13 @@ import React, { Suspense, useState } from "react"; import { Spin } from "antd"; -import { - Route, - Switch, - Redirect -} from "react-router-dom"; +import { Route, Switch, Redirect } from "react-router-dom"; import Signup from "./Signup"; const App = React.lazy(() => import("Src/components/App")); const AppWrapper = () => { - - console.log("other") + console.log("other"); return ( - }> + }> diff --git a/frontend/src/components/DateTimeSelector.tsx b/frontend/src/components/DateTimeSelector.tsx index df4433eefa..8b37ae3402 100644 --- a/frontend/src/components/DateTimeSelector.tsx +++ b/frontend/src/components/DateTimeSelector.tsx @@ -40,7 +40,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { const [refreshButtonClick, setRefreshButtoClick] = useState(0); const [form_dtselector] = Form.useForm(); const location = useLocation(); - const updateTimeOnQueryParamChange = ()=>{ + const updateTimeOnQueryParamChange = () => { const timeDurationInLocalStorage = localStorage.getItem( LOCAL_STORAGE.METRICS_TIME_IN_DURATION, ); @@ -48,13 +48,18 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { const urlParams = new URLSearchParams(window.location.search); const intervalInQueryParam = urlParams.get(METRICS_PAGE_QUERY_PARAM.interval); const startTimeString = urlParams.get(METRICS_PAGE_QUERY_PARAM.startTime); - const endTimeString = urlParams.get(METRICS_PAGE_QUERY_PARAM.endTime); + const endTimeString = urlParams.get(METRICS_PAGE_QUERY_PARAM.endTime); // first pref: handle both startTime and endTime - if(startTimeString && startTimeString.length>0 && endTimeString && endTimeString.length>0){ + if ( + startTimeString && + startTimeString.length > 0 && + endTimeString && + endTimeString.length > 0 + ) { const startTime = moment(Number(startTimeString)); const endTime = moment(Number(endTimeString)); - setCustomTime(startTime,endTime,true) + setCustomTime(startTime, endTime, true); } // first pref: handle intervalInQueryParam else if (intervalInQueryParam) { @@ -66,8 +71,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { } else if (timeDurationInLocalStorage) { setMetricsTimeInterval(timeDurationInLocalStorage); } - - } + }; // On URL Change useEffect(() => { @@ -79,22 +83,20 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { updateTimeOnQueryParamChange(); }, []); - const setMetricsTimeInterval= (value: string) => { + const setMetricsTimeInterval = (value: string) => { props.updateTimeInterval(value); setTimeInterval(value); setEndTime(null); setStartTime(null); - window.localStorage.setItem( - LOCAL_STORAGE.METRICS_TIME_IN_DURATION, - value, - ); + window.localStorage.setItem(LOCAL_STORAGE.METRICS_TIME_IN_DURATION, value); }; - const setCustomTime= (startTime: moment.Moment, endTime: moment.Moment, triggeredByURLChange = false) => { - props.updateTimeInterval("custom", [ - startTime.valueOf(), - endTime.valueOf(), - ]); + const setCustomTime = ( + startTime: moment.Moment, + endTime: moment.Moment, + triggeredByURLChange = false, + ) => { + props.updateTimeInterval("custom", [startTime.valueOf(), endTime.valueOf()]); setEndTime(endTime); setStartTime(startTime); }; @@ -105,10 +107,17 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { }); //pass time in URL query param for all choices except custom in datetime picker }; - const updateUrlForCustomTime= (startTime: moment.Moment, endTime: moment.Moment, triggeredByURLChange = false) => { - props.history.push(`?${METRICS_PAGE_QUERY_PARAM.startTime}=${startTime.valueOf()}&${METRICS_PAGE_QUERY_PARAM.endTime}=${endTime.valueOf()}`); - } - + const updateUrlForCustomTime = ( + startTime: moment.Moment, + endTime: moment.Moment, + triggeredByURLChange = false, + ) => { + props.history.push( + `?${METRICS_PAGE_QUERY_PARAM.startTime}=${startTime.valueOf()}&${ + METRICS_PAGE_QUERY_PARAM.endTime + }=${endTime.valueOf()}`, + ); + }; const handleOnSelect = (value: string) => { if (value === "custom") { @@ -131,7 +140,7 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { const startTime = dateTimeRange[0].valueOf(); const endTime = dateTimeRange[1].valueOf(); - updateUrlForCustomTime(moment(startTime),moment(endTime)) + updateUrlForCustomTime(moment(startTime), moment(endTime)); //setting globaltime setRefreshButtonHidden(true); form_dtselector.setFieldsValue({ @@ -146,35 +155,35 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { const timeSinceLastRefresh = () => { const currentTime = moment(); - const lastRefresh = moment(props.globalTime.maxTime / 1000000) + const lastRefresh = moment(props.globalTime.maxTime / 1000000); const duration = moment.duration(currentTime.diff(lastRefresh)); const secondsDiff = Math.floor(duration.asSeconds()); const minutedDiff = Math.floor(duration.asMinutes()); - const hoursDiff = Math.floor(duration.asHours()) + const hoursDiff = Math.floor(duration.asHours()); - if(hoursDiff>0){ - return `Last refresh - ${hoursDiff} hrs ago` - }else if(minutedDiff>0){ - return `Last refresh - ${minutedDiff} mins ago` + if (hoursDiff > 0) { + return `Last refresh - ${hoursDiff} hrs ago`; + } else if (minutedDiff > 0) { + return `Last refresh - ${minutedDiff} mins ago`; } - return `Last refresh - ${secondsDiff} sec ago` + return `Last refresh - ${secondsDiff} sec ago`; }; const handleRefresh = () => { - setRefreshButtoClick(refreshButtonClick+1); + setRefreshButtoClick(refreshButtonClick + 1); setMetricsTimeInterval(timeInterval); }; - useEffect(()=>{ - setRefreshText("") - const interval = setInterval(()=>{ - setRefreshText(timeSinceLastRefresh()) - }, 2000) - return ()=>{ - clearInterval(interval) - } - },[props.location,refreshButtonClick]) + useEffect(() => { + setRefreshText(""); + const interval = setInterval(() => { + setRefreshText(timeSinceLastRefresh()); + }, 2000); + return () => { + clearInterval(interval); + }; + }, [props.location, refreshButtonClick]); const options = [ { value: "custom", label: "Custom" }, @@ -188,36 +197,47 @@ const _DateTimeSelector = (props: DateTimeSelectorProps) => { if (props.location.pathname.startsWith("/usage-explorer")) { return null; } else { - - const inputLabeLToShow = startTime && endTime? (`${startTime.format("YYYY/MM/DD HH:mm")} - ${endTime.format("YYYY/MM/DD HH:mm")}`):timeInterval + const inputLabeLToShow = + startTime && endTime + ? `${startTime.format("YYYY/MM/DD HH:mm")} - ${endTime.format( + "YYYY/MM/DD HH:mm", + )}` + : timeInterval; return ( - - -
- + + + + - - - - - - - {refreshText} - + + +
+ + {refreshText} + { ); }; -export default withRouter(Signup); \ No newline at end of file +export default withRouter(Signup); diff --git a/frontend/src/components/Test.tsx b/frontend/src/components/Test.tsx index 245602371f..04061e803b 100644 --- a/frontend/src/components/Test.tsx +++ b/frontend/src/components/Test.tsx @@ -1,9 +1,5 @@ const Test = () => { - return ( -
- INSIDE PUBLIC CODE -
- ) -} + return
INSIDE PUBLIC CODE
; +}; -export default Test; \ No newline at end of file +export default Test; diff --git a/frontend/src/components/common/Modal.tsx b/frontend/src/components/common/Modal.tsx index c6bf778301..b68dda6812 100644 --- a/frontend/src/components/common/Modal.tsx +++ b/frontend/src/components/common/Modal.tsx @@ -1,20 +1,28 @@ import React, { ReactElement, useState } from "react"; -import { Modal, Button } from 'antd'; +import { Modal, Button } from "antd"; -export const CustomModal = ({title,children, isModalVisible, setIsModalVisible, footer, closable=true}:{ - isModalVisible: boolean, - closable?: boolean, - setIsModalVisible: Function, - footer?: any, - title: string, - children: ReactElement +export const CustomModal = ({ + title, + children, + isModalVisible, + setIsModalVisible, + footer, + closable = true, +}: { + isModalVisible: boolean; + closable?: boolean; + setIsModalVisible: Function; + footer?: any; + title: string; + children: ReactElement; }) => { - return ( <> - {children} diff --git a/frontend/src/components/metrics/LatencyLineChart.tsx b/frontend/src/components/metrics/LatencyLineChart.tsx index d180b6838a..86886dbb42 100644 --- a/frontend/src/components/metrics/LatencyLineChart.tsx +++ b/frontend/src/components/metrics/LatencyLineChart.tsx @@ -187,7 +187,7 @@ class LatencyLineChart extends React.Component { > { - this.props.popupClickHandler(this.state.firstpoint_ts) + this.props.popupClickHandler(this.state.firstpoint_ts); }} > View Traces diff --git a/frontend/src/components/metrics/ServiceMetrics.tsx b/frontend/src/components/metrics/ServiceMetrics.tsx index e99302b1f9..208a243e8b 100644 --- a/frontend/src/components/metrics/ServiceMetrics.tsx +++ b/frontend/src/components/metrics/ServiceMetrics.tsx @@ -31,7 +31,7 @@ interface ServicesMetricsProps extends RouteComponentProps { } const _ServiceMetrics = (props: ServicesMetricsProps) => { - const {servicename} = useParams<{ servicename?: string }>(); + const { servicename } = useParams<{ servicename?: string }>(); useEffect(() => { props.getServicesMetrics(servicename, props.globalTime); props.getTopEndpoints(servicename, props.globalTime); @@ -41,22 +41,18 @@ const _ServiceMetrics = (props: ServicesMetricsProps) => { const tMinus15Min = timestamp / 1000000 - 15 * 60 * 1000; const currentTime = timestamp / 1000000; - props.updateTimeInterval("custom", [ - tMinus15Min, - currentTime, - ]); // updateTimeInterval takes second range in ms -- give -5 min to selected time, + props.updateTimeInterval("custom", [tMinus15Min, currentTime]); // updateTimeInterval takes second range in ms -- give -5 min to selected time, const urlParams = new URLSearchParams(); - urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime,tMinus15Min.toString()) - urlParams.set(METRICS_PAGE_QUERY_PARAM.endTime,currentTime.toString()) - if(servicename){ - urlParams.set(METRICS_PAGE_QUERY_PARAM.service,servicename) + urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime, tMinus15Min.toString()); + urlParams.set(METRICS_PAGE_QUERY_PARAM.endTime, currentTime.toString()); + if (servicename) { + urlParams.set(METRICS_PAGE_QUERY_PARAM.service, servicename); } props.history.push(`/traces?${urlParams.toString()}`); }; - return ( diff --git a/frontend/src/components/metrics/ServicesTable.tsx b/frontend/src/components/metrics/ServicesTable.tsx index c6b14641e0..58751b0e87 100644 --- a/frontend/src/components/metrics/ServicesTable.tsx +++ b/frontend/src/components/metrics/ServicesTable.tsx @@ -32,14 +32,14 @@ const Wrapper = styled.div` `; const TableLoadingWrapper = styled.div` - display: flex; - justify-content: center; - margin-top: 80px; -` + display: flex; + justify-content: center; + margin-top: 80px; +`; const LoadingText = styled.div` - margin-left: 16px; -` + margin-left: 16px; +`; const columns = [ { @@ -81,71 +81,93 @@ const columns = [ const _ServicesTable = (props: ServicesTableProps) => { const search = useLocation().search; const time_interval = new URLSearchParams(search).get("time"); - const [initialDataFetch, setDataFetched] = useState(false) - const [errorObject, setErrorObject] = useState({message: "", isError: false}); - const isEmptyServiceList = !initialDataFetch && props.servicesList.length === 0; + const [initialDataFetch, setDataFetched] = useState(false); + const [errorObject, setErrorObject] = useState({ + message: "", + isError: false, + }); + const isEmptyServiceList = + !initialDataFetch && props.servicesList.length === 0; const refetchFromBackend = isEmptyServiceList || errorObject.isError; - const [skipOnboarding, setSkipOnboarding ] = useState(localStorage.getItem('skip_onboarding') === "true"); + const [skipOnboarding, setSkipOnboarding] = useState( + localStorage.getItem("skip_onboarding") === "true", + ); - const onContinueClick = ()=>{ - localStorage.setItem('skip_onboarding', 'true'); - setSkipOnboarding(true) - } + const onContinueClick = () => { + localStorage.setItem("skip_onboarding", "true"); + setSkipOnboarding(true); + }; function getApiServiceData() { - props.getServicesList(props.globalTime).then(() => { + props + .getServicesList(props.globalTime) + .then(() => { setDataFetched(true); setErrorObject({ message: "", isError: false }); - }).catch((e: string) => { + }) + .catch((e: string) => { setErrorObject({ message: e, isError: true }); setDataFetched(true); }); } useEffect(getApiServiceData, [props.globalTime]); - useEffect(()=>{ - if(props.servicesList.length > 1 ){ - localStorage.removeItem('skip_onboarding') ; + useEffect(() => { + if (props.servicesList.length > 1) { + localStorage.removeItem("skip_onboarding"); } - refetchFromBackend && setTimeout(getApiServiceData, 50000) - }, [props.servicesList,errorObject]) + refetchFromBackend && setTimeout(getApiServiceData, 50000); + }, [props.servicesList, errorObject]); - if(!initialDataFetch){ + if (!initialDataFetch) { return ( - - - Fetching data - - ) + + + Fetching data + + ); } - if(refetchFromBackend && !skipOnboarding){ + if (refetchFromBackend && !skipOnboarding) { return ( - {}} - footer={[ - , - ]} + {}} + footer={[ + , + ]} >
- -
- + +
+
- No instrumentation data.
- Please instrument your application as mentioned here + No instrumentation data. +
+ Please instrument your application as mentioned{" "} + + here +
- ) + ); } return ( @@ -157,9 +179,19 @@ const _ServicesTable = (props: ServicesTableProps) => { /> {props.servicesList[0].numCalls === 0 && ( - + No applications present. Please add instrumentation (follow this - guide) + + guide + + ) + )} ); diff --git a/frontend/src/components/settings/settingsPage.tsx b/frontend/src/components/settings/settingsPage.tsx index 27f69f2de9..65cf5644ae 100644 --- a/frontend/src/components/settings/settingsPage.tsx +++ b/frontend/src/components/settings/settingsPage.tsx @@ -1,72 +1,63 @@ import React, { useEffect, useState } from "react"; -import { Form, Input, Space } from "antd"; +import { Form, Input, Space } from "antd"; import { connect } from "react-redux"; -import { Tooltip } from 'antd'; -import { InfoCircleOutlined,EyeTwoTone,EyeInvisibleOutlined } from '@ant-design/icons'; +import { Tooltip } from "antd"; +import { + InfoCircleOutlined, + EyeTwoTone, + EyeInvisibleOutlined, +} from "@ant-design/icons"; import { StoreState } from "../../reducers"; import { useAuthenticationData } from "../../hooks/authentication"; import { TOKEN_DATE } from "../../../../../sass/frontend/src/constants/accessToken"; -import { Alert } from 'antd'; +import { Alert } from "antd"; -interface SettingsPageProps { -} +interface SettingsPageProps {} const layout = { labelCol: { span: 3 }, wrapperCol: { span: 6 }, }; - const SettingsPage = (props: SettingsPageProps) => { const [form] = Form.useForm(); - useEffect(()=>{ + useEffect(() => { form.setFieldsValue({ - retention_period: "3 days" + retention_period: "3 days", }); - }) - + }); return ( - -
- - +
- + - -
); }; -const mapStateToProps = ( - state: StoreState -): { } => { +const mapStateToProps = (state: StoreState): {} => { return {}; }; -export default connect(mapStateToProps, { - -})(SettingsPage); +export default connect(mapStateToProps, {})(SettingsPage); diff --git a/frontend/src/components/traces/LatencyModalForm.tsx b/frontend/src/components/traces/LatencyModalForm.tsx index 279e3d22e4..91a00b12e3 100644 --- a/frontend/src/components/traces/LatencyModalForm.tsx +++ b/frontend/src/components/traces/LatencyModalForm.tsx @@ -5,12 +5,13 @@ import { Store } from "antd/lib/form/interface"; interface LatencyModalFormProps { onCreate: (values: Store) => void; //Store is defined in antd forms library onCancel: () => void; - latencyFilterValues: {min: string, max: string} + latencyFilterValues: { min: string; max: string }; } const LatencyModalForm: React.FC = ({ onCreate, - onCancel,latencyFilterValues + onCancel, + latencyFilterValues, }) => { const [form] = Form.useForm(); return ( diff --git a/frontend/src/components/traces/TraceFilter.tsx b/frontend/src/components/traces/TraceFilter.tsx index 7947ce7a3d..5f6798ae99 100644 --- a/frontend/src/components/traces/TraceFilter.tsx +++ b/frontend/src/components/traces/TraceFilter.tsx @@ -43,18 +43,21 @@ const _TraceFilter = (props: TraceFilterProps) => { const [serviceList, setServiceList] = useState([]); const [operationList, setOperationsList] = useState([]); const [tagKeyOptions, setTagKeyOptions] = useState([]); - const location = useLocation() + const location = useLocation(); const urlParams = new URLSearchParams(location.search.split("?")[1]); useEffect(() => { - metricsAPI.get("services/list").then((response) => { - setServiceList(response.data); - }).then(()=>{ - const serviceName =urlParams.get(METRICS_PAGE_QUERY_PARAM.service); - if(serviceName){ - handleChangeService(serviceName) + metricsAPI + .get("services/list") + .then((response) => { + setServiceList(response.data); + }) + .then(() => { + const serviceName = urlParams.get(METRICS_PAGE_QUERY_PARAM.service); + if (serviceName) { + handleChangeService(serviceName); } - }); + }); }, []); useEffect(() => { @@ -120,7 +123,10 @@ const _TraceFilter = (props: TraceFilterProps) => { const [loading] = useState(false); const [tagKeyValueApplied, setTagKeyValueApplied] = useState([""]); - const [latencyFilterValues, setLatencyFilterValues] = useState<{min: string, max: string}>({ + const [latencyFilterValues, setLatencyFilterValues] = useState<{ + min: string; + max: string; + }>({ min: "100", max: "500", }); @@ -158,7 +164,7 @@ const _TraceFilter = (props: TraceFilterProps) => { const onLatencyModalApply = (values: Store) => { setModalVisible(false); - const { min, max}= values + const { min, max } = values; props.updateTraceFilters({ ...props.traceFilters, latency: { @@ -167,7 +173,7 @@ const _TraceFilter = (props: TraceFilterProps) => { }, }); - setLatencyFilterValues({min, max}) + setLatencyFilterValues({ min, max }); }; const onTagFormSubmit = (values: any) => { @@ -382,13 +388,15 @@ const _TraceFilter = (props: TraceFilterProps) => { - {modalVisible && { - setModalVisible(false); - }} - />} + {modalVisible && ( + { + setModalVisible(false); + }} + /> + )}
); }; diff --git a/frontend/src/components/traces/TraceGraph.tsx b/frontend/src/components/traces/TraceGraph.tsx index d355a51737..8ce70abaf1 100644 --- a/frontend/src/components/traces/TraceGraph.tsx +++ b/frontend/src/components/traces/TraceGraph.tsx @@ -46,7 +46,7 @@ const _TraceGraph = (props: TraceGraphProps) => { .default() .attr("class", "d3-tip") .html(function (d: any) { - return d.data.name + "
duration: " + d.data.value/1000000+'ms'; + return d.data.name + "
duration: " + d.data.value / 1000000 + "ms"; }); const onClick = (z: any) => { @@ -59,8 +59,8 @@ const _TraceGraph = (props: TraceGraphProps) => { .cellHeight(18) .transitionDuration(500) .inverted(true) - .tooltip(tip) - .minFrameSize(10) + .tooltip(tip) + .minFrameSize(10) .elided(false) .differential(false) .sort(true) @@ -69,7 +69,7 @@ const _TraceGraph = (props: TraceGraphProps) => { // Source flamegraph.js line 557 and 573. // .selfValue(true) .onClick(onClick) - .title("Trace Flame graph"); + .title("Trace Flame graph"); return ( @@ -84,7 +84,7 @@ const _TraceGraph = (props: TraceGraphProps) => { -
+
diff --git a/frontend/src/components/traces/TraceList.tsx b/frontend/src/components/traces/TraceList.tsx index 1ff4e04f9e..2742daec3f 100644 --- a/frontend/src/components/traces/TraceList.tsx +++ b/frontend/src/components/traces/TraceList.tsx @@ -107,11 +107,22 @@ const _TraceList = (props: TraceListProps) => { return ; } else { - - if(isOnboardingSkipped()){ - return ( - No spans found. Please add instrumentation (follow this - guide)) + if (isOnboardingSkipped()) { + return ( + + No spans found. Please add instrumentation (follow this + + guide + + ) + + ); } return
No spans found for given filter!
; } diff --git a/frontend/src/components/usage/UsageExplorer.tsx b/frontend/src/components/usage/UsageExplorer.tsx index efb253f76e..b1171c9f13 100644 --- a/frontend/src/components/usage/UsageExplorer.tsx +++ b/frontend/src/components/usage/UsageExplorer.tsx @@ -3,7 +3,13 @@ import { Bar } from "react-chartjs-2"; import { Card, Form, Select, Space } from "antd"; import { connect } from "react-redux"; -import { getServicesList, getUsageData, GlobalTime, servicesListItem, usageDataItem } from "../../actions"; +import { + getServicesList, + getUsageData, + GlobalTime, + servicesListItem, + usageDataItem, +} from "../../actions"; import { StoreState } from "../../reducers"; import moment from "moment"; import { isOnboardingSkipped } from "../../utils/app"; @@ -20,37 +26,58 @@ interface UsageExplorerProps { const timeDaysOptions = [ { value: 30, label: "Last 30 Days" }, { value: 7, label: "Last week" }, - { value: 1, label: "Last day" } + { value: 1, label: "Last day" }, ]; const interval = [ - { value: 604800, chartDivideMultiplier: 1, label: "Weekly", applicableOn: [timeDaysOptions[0]] }, - { value: 86400, chartDivideMultiplier: 30,label: "Daily", applicableOn: [timeDaysOptions[0],timeDaysOptions[1]] }, - { value: 3600, chartDivideMultiplier: 10,label: "Hours", applicableOn: [timeDaysOptions[2],timeDaysOptions[1]] },, + { + value: 604800, + chartDivideMultiplier: 1, + label: "Weekly", + applicableOn: [timeDaysOptions[0]], + }, + { + value: 86400, + chartDivideMultiplier: 30, + label: "Daily", + applicableOn: [timeDaysOptions[0], timeDaysOptions[1]], + }, + { + value: 3600, + chartDivideMultiplier: 10, + label: "Hours", + applicableOn: [timeDaysOptions[2], timeDaysOptions[1]], + }, + , ]; const _UsageExplorer = (props: UsageExplorerProps) => { - const [selectedTime, setSelectedTime] = useState(timeDaysOptions[1]) - const [selectedInterval, setSelectedInterval] = useState(interval[2]) - const [selectedService, setSelectedService] = useState("") + const [selectedTime, setSelectedTime] = useState(timeDaysOptions[1]); + const [selectedInterval, setSelectedInterval] = useState(interval[2]); + const [selectedService, setSelectedService] = useState(""); useEffect(() => { - if(selectedTime && selectedInterval) { - const maxTime = new Date().getTime() * 1000000 ; - const minTime = (maxTime - (selectedTime.value * 24 * 3600000 * 1000000 ) ); + if (selectedTime && selectedInterval) { + const maxTime = new Date().getTime() * 1000000; + const minTime = maxTime - selectedTime.value * 24 * 3600000 * 1000000; - props.getUsageData(minTime, maxTime, selectedInterval!.value, selectedService); + props.getUsageData( + minTime, + maxTime, + selectedInterval!.value, + selectedService, + ); } - }, [selectedTime,selectedInterval,selectedService]); + }, [selectedTime, selectedInterval, selectedService]); useEffect(() => { - props.getServicesList(props.globalTime); + props.getServicesList(props.globalTime); }, []); - - const data = { - labels: props.usageData.map((s) => moment(s.timestamp/1000000).format("MMM Do h a")), + labels: props.usageData.map((s) => + moment(s.timestamp / 1000000).format("MMM Do h a"), + ), datasets: [ { label: "Span Count", @@ -62,7 +89,6 @@ const _UsageExplorer = (props: UsageExplorerProps) => { ], }; - const options = { scales: { yAxes: [ @@ -82,50 +108,78 @@ const _UsageExplorer = (props: UsageExplorerProps) => { return ( {/* PNOTE - TODO - Keep it in reponsive row column tab */} - - - - + - { + setSelectedTime( + timeDaysOptions.filter((item) => item.value == parseInt(value))[0], + ); + }} + value={selectedTime.label} + > + {timeDaysOptions.map(({ value, label }) => ( + + ))} + + + + + - {interval.filter((interval)=>interval!.applicableOn.includes(selectedTime)).map((item) => ( - + + - - - - - { isOnboardingSkipped() && props.totalCount === 0 ? ( - + {isOnboardingSkipped() && props.totalCount === 0 ? ( + No spans found. Please add instrumentation (follow this - guide) - ): ( - + + guide + + ) + + ) : ( + {`Total count is ${props.totalCount}`} - ) - } - + )} - @@ -134,16 +188,26 @@ const _UsageExplorer = (props: UsageExplorerProps) => { }; const mapStateToProps = ( - state: StoreState -): { totalCount: number; globalTime: GlobalTime; servicesList: servicesListItem[]; usageData: usageDataItem[]; } => { + state: StoreState, +): { + totalCount: number; + globalTime: GlobalTime; + servicesList: servicesListItem[]; + usageData: usageDataItem[]; +} => { let totalCount = 0; - for(let item of state.usageDate){ - totalCount = totalCount+item.count; + for (let item of state.usageDate) { + totalCount = totalCount + item.count; } - return {totalCount:totalCount, usageData: state.usageDate, globalTime: state.globalTime, servicesList: state.servicesList }; + return { + totalCount: totalCount, + usageData: state.usageDate, + globalTime: state.globalTime, + servicesList: state.servicesList, + }; }; export const UsageExplorer = connect(mapStateToProps, { getUsageData: getUsageData, - getServicesList: getServicesList + getServicesList: getServicesList, })(_UsageExplorer); diff --git a/frontend/src/constants/app.ts b/frontend/src/constants/app.ts index 3501c1a424..b3aa3904f5 100644 --- a/frontend/src/constants/app.ts +++ b/frontend/src/constants/app.ts @@ -1,6 +1,4 @@ -export const WITHOUT_SESSION_PATH = [ - "/redirect" -] +export const WITHOUT_SESSION_PATH = ["/redirect"]; export const AUTH0_REDIRECT_PATH = "/redirect"; diff --git a/frontend/src/constants/query.ts b/frontend/src/constants/query.ts index f7736736e9..1f9e72626d 100644 --- a/frontend/src/constants/query.ts +++ b/frontend/src/constants/query.ts @@ -2,6 +2,5 @@ export enum METRICS_PAGE_QUERY_PARAM { interval = "interval", startTime = "startTime", endTime = "endTime", - service = "service" + service = "service", } - diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 294df5589a..fd1faa9ea8 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -10,7 +10,7 @@ import { Auth0Provider } from "@auth0/auth0-react"; import AppWrapper from "Src/components/AppWrapper"; import "Src/assets/index.css"; import { reducers } from "./reducers"; -import {BrowserRouter as Router} from "react-router-dom"; +import { BrowserRouter as Router } from "react-router-dom"; import { AUTH0_CLIENT_ID, AUTH0_DOMAIN } from "./constants/env"; // import Signup from './components/Signup'; // @ts-ignore @@ -31,7 +31,6 @@ ReactDOM.render( - - , + , document.querySelector("#root"), ); diff --git a/frontend/src/reducers/global.ts b/frontend/src/reducers/global.ts index 95d2b8429d..c7ff91e7be 100644 --- a/frontend/src/reducers/global.ts +++ b/frontend/src/reducers/global.ts @@ -3,7 +3,7 @@ import { ActionTypes, Action, GlobalTime } from "../actions"; export const updateGlobalTimeReducer = ( state: GlobalTime = { maxTime: Date.now() * 1000000, - minTime: (Date.now() - 15 * 60 * 1000) * 1000000 + minTime: (Date.now() - 15 * 60 * 1000) * 1000000, }, action: Action, ) => { diff --git a/frontend/src/utils/app.ts b/frontend/src/utils/app.ts index 7d9bae663b..21ae10c624 100644 --- a/frontend/src/utils/app.ts +++ b/frontend/src/utils/app.ts @@ -1 +1,3 @@ -export const isOnboardingSkipped = ()=>{return localStorage.getItem('skip_onboarding') === "true"} \ No newline at end of file +export const isOnboardingSkipped = () => { + return localStorage.getItem("skip_onboarding") === "true"; +}; diff --git a/frontend/src/utils/timeUtils.ts b/frontend/src/utils/timeUtils.ts index aa8d04b7fc..ca2c9d24a2 100644 --- a/frontend/src/utils/timeUtils.ts +++ b/frontend/src/utils/timeUtils.ts @@ -1,4 +1,4 @@ -export const toUTCEpoch = (time: number):number=>{ - const x = new Date() - return (time + x.getTimezoneOffset()*60*1000); -} \ No newline at end of file +export const toUTCEpoch = (time: number): number => { + const x = new Date(); + return time + x.getTimezoneOffset() * 60 * 1000; +}; diff --git a/frontend/src/utils/token.ts b/frontend/src/utils/token.ts index 119266412b..81baa233bb 100644 --- a/frontend/src/utils/token.ts +++ b/frontend/src/utils/token.ts @@ -1,3 +1,3 @@ -export class Token{ - static auth0Token = "" -}; \ No newline at end of file +export class Token { + static auth0Token = ""; +} diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 77c72b59d4..6a7ecc73ae 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -1,58 +1,58 @@ // shared config (dev and prod) const { resolve } = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); -console.log(resolve(__dirname, './src/')); +console.log(resolve(__dirname, "./src/")); module.exports = { - mode: "development", - devtool: "source-map", - entry: resolve(__dirname, "./src/index.tsx"), - devServer: { - historyApiFallback: true, - publicPath: "/", - transportMode: 'ws', - contentBase: [resolve(__dirname, "./public")], - hot: true, - liveReload: false, - inline:true, - port: 3000, - }, - output: { - filename: "js/bundle.[chunkhash].min.js", - path: resolve(__dirname, "./build"), - publicPath: "/", - }, - resolve: { - alias: { - Src: resolve(__dirname, './src/') - }, - extensions: [".ts", ".tsx",".js", ".jsx"], - }, - module: { - rules: [ - { - test: [/\.jsx?$/, /\.tsx?$/], - use: ["babel-loader"], - exclude: /node_modules/, - }, - { - test: /\.css$/, - use: ["style-loader", "css-loader"], - }, - { - test: /\.(scss|sass)$/, - use: ["style-loader", "css-loader", "sass-loader"], - }, - { - test: /\.(jpe?g|png|gif|svg)$/i, - use: [ - "file-loader?hash=sha512&digest=hex&name=img/[chunkhash].[ext]", - "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false", - ], - }, - ], - }, - plugins: [new HtmlWebpackPlugin({ template: "src/index.html.ejs" })], - performance: { - hints: false, - }, -}; \ No newline at end of file + mode: "development", + devtool: "source-map", + entry: resolve(__dirname, "./src/index.tsx"), + devServer: { + historyApiFallback: true, + publicPath: "/", + transportMode: "ws", + contentBase: [resolve(__dirname, "./public")], + hot: true, + liveReload: false, + inline: true, + port: 3000, + }, + output: { + filename: "js/bundle.[chunkhash].min.js", + path: resolve(__dirname, "./build"), + publicPath: "/", + }, + resolve: { + alias: { + Src: resolve(__dirname, "./src/"), + }, + extensions: [".ts", ".tsx", ".js", ".jsx"], + }, + module: { + rules: [ + { + test: [/\.jsx?$/, /\.tsx?$/], + use: ["babel-loader"], + exclude: /node_modules/, + }, + { + test: /\.css$/, + use: ["style-loader", "css-loader"], + }, + { + test: /\.(scss|sass)$/, + use: ["style-loader", "css-loader", "sass-loader"], + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + use: [ + "file-loader?hash=sha512&digest=hex&name=img/[chunkhash].[ext]", + "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false", + ], + }, + ], + }, + plugins: [new HtmlWebpackPlugin({ template: "src/index.html.ejs" })], + performance: { + hints: false, + }, +}; diff --git a/frontend/webpack.config.prod.js b/frontend/webpack.config.prod.js index 32d7aa64fb..82a3c08ecb 100644 --- a/frontend/webpack.config.prod.js +++ b/frontend/webpack.config.prod.js @@ -4,54 +4,52 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); module.exports = { - mode: "production", - devtool: "source-map", - entry: resolve(__dirname, "./src/index.tsx"), - output: { - filename: "js/bundle.[chunkhash].min.js", - path: resolve(__dirname, "./build"), - publicPath: "/", - }, + mode: "production", + devtool: "source-map", + entry: resolve(__dirname, "./src/index.tsx"), + output: { + filename: "js/bundle.[chunkhash].min.js", + path: resolve(__dirname, "./build"), + publicPath: "/", + }, - resolve: { - alias: { - Src: resolve(__dirname, './src/'), - }, - extensions: [".ts", ".tsx",".js", ".jsx"], - }, - module: { - rules: [ - { - test: [/\.jsx?$/, /\.tsx?$/], - use: ["babel-loader"], - exclude: /node_modules/, - }, - { - test: /\.css$/, - use: ["style-loader", "css-loader"], - }, - { - test: /\.(scss|sass)$/, - use: ["style-loader", "css-loader", "sass-loader"], - }, - { - test: /\.(jpe?g|png|gif|svg)$/i, - use: [ - "file-loader?hash=sha512&digest=hex&name=img/[chunkhash].[ext]", - "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false", - ], - }, - ], - }, - plugins: [ - new HtmlWebpackPlugin({ template: "src/index.html.ejs" }), - new CopyPlugin({ - patterns: [ - { from: resolve(__dirname, "public/"), to: "." }, - ], - }) - ], - performance: { - hints: false, - }, -}; \ No newline at end of file + resolve: { + alias: { + Src: resolve(__dirname, "./src/"), + }, + extensions: [".ts", ".tsx", ".js", ".jsx"], + }, + module: { + rules: [ + { + test: [/\.jsx?$/, /\.tsx?$/], + use: ["babel-loader"], + exclude: /node_modules/, + }, + { + test: /\.css$/, + use: ["style-loader", "css-loader"], + }, + { + test: /\.(scss|sass)$/, + use: ["style-loader", "css-loader", "sass-loader"], + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + use: [ + "file-loader?hash=sha512&digest=hex&name=img/[chunkhash].[ext]", + "image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false", + ], + }, + ], + }, + plugins: [ + new HtmlWebpackPlugin({ template: "src/index.html.ejs" }), + new CopyPlugin({ + patterns: [{ from: resolve(__dirname, "public/"), to: "." }], + }), + ], + performance: { + hints: false, + }, +};