Răsfoiți Sursa

Merge pull request #284 from porter-dev/beta.3.cicd

Fix redirect issue in #282
abelanger5 5 ani în urmă
părinte
comite
123e8f71d1

+ 2 - 11
dashboard/src/main/Main.tsx

@@ -10,7 +10,7 @@ import Register from "./Register";
 import CurrentError from "./CurrentError";
 import Home from "./home/Home";
 import Loading from "components/Loading";
-import { PorterUrls } from "shared/routing";
+import { PorterUrl, PorterUrls } from "shared/routing";
 
 type PropsType = {};
 
@@ -71,15 +71,6 @@ export default class Main extends Component<PropsType, StateType> {
       return <Loading />;
     }
 
-    const authedUrls: PorterUrls[] = [
-      "dashboard",
-      "templates",
-      "integrations",
-      "new-project",
-      "cluster-dashboard",
-      "project-settings",
-    ];
-
     return (
       <Switch>
         <Route
@@ -116,7 +107,7 @@ export default class Main extends Component<PropsType, StateType> {
                   key="home"
                   currentProject={this.context.currentProject}
                   currentCluster={this.context.currentCluster}
-                  currentRoute={urlRoute as PorterUrls}
+                  currentRoute={urlRoute as PorterUrl}
                   logOut={this.handleLogOut}
                 />
               );

+ 26 - 26
dashboard/src/main/home/Home.tsx

@@ -1,35 +1,35 @@
 import React, { Component } from "react";
+import { RouteComponentProps, withRouter } from "react-router";
 import posthog from "posthog-js";
 import styled from "styled-components";
+import * as FullStory from "@fullstory/browser";
 
-import { Context } from "shared/Context";
 import api from "shared/api";
+import { Context } from "shared/Context";
+import { PorterUrl } from "shared/routing";
 import { ClusterType, ProjectType } from "shared/types";
 
-import Sidebar from "./sidebar/Sidebar";
-import Dashboard from "./dashboard/Dashboard";
-import ClusterDashboard from "./cluster-dashboard/ClusterDashboard";
+import ConfirmOverlay from "components/ConfirmOverlay";
 import Loading from "components/Loading";
-import Templates from "./templates/Templates";
+import ClusterDashboard from "./cluster-dashboard/ClusterDashboard";
+import Dashboard from "./dashboard/Dashboard";
 import Integrations from "./integrations/Integrations";
-import UpdateClusterModal from "./modals/UpdateClusterModal";
+import Templates from "./launch/Launch";
 import ClusterInstructionsModal from "./modals/ClusterInstructionsModal";
-import IntegrationsModal from "./modals/IntegrationsModal";
 import IntegrationsInstructionsModal from "./modals/IntegrationsInstructionsModal";
-import NewProject from "./new-project/NewProject";
+import IntegrationsModal from "./modals/IntegrationsModal";
+import Modal from "./modals/Modal";
+import UpdateClusterModal from "./modals/UpdateClusterModal";
 import Navbar from "./navbar/Navbar";
+import NewProject from "./new-project/NewProject";
 import ProjectSettings from "./project-settings/ProjectSettings";
-import ConfirmOverlay from "components/ConfirmOverlay";
-import Modal from "./modals/Modal";
-import * as FullStory from "@fullstory/browser";
-import { Redirect, RouteComponentProps, withRouter } from "react-router";
-import { PorterUrls } from "shared/routing";
+import Sidebar from "./sidebar/Sidebar";
 
 type PropsType = RouteComponentProps & {
   logOut: () => void;
   currentProject: ProjectType;
   currentCluster: ClusterType;
-  currentRoute: PorterUrls;
+  currentRoute: PorterUrl;
 };
 
 type StateType = {
@@ -128,18 +128,18 @@ class Home extends Component<PropsType, StateType> {
   provisionDOCR = (integrationId: number, tier: string, callback?: any) => {
     console.log("Provisioning DOCR...");
     return api
-    .createDOCR(
-      "<token>",
-      {
-        do_integration_id: integrationId,
-        docr_name: this.props.currentProject.name,
-        docr_subscription_tier: tier,
-      },
-      {
-        project_id: this.props.currentProject.id,
-      }
-    )
-    .then(() => callback()); 
+      .createDOCR(
+        "<token>",
+        {
+          do_integration_id: integrationId,
+          docr_name: this.props.currentProject.name,
+          docr_subscription_tier: tier,
+        },
+        {
+          project_id: this.props.currentProject.id,
+        }
+      )
+      .then(() => callback());
   };
 
   provisionDOKS = (integrationId: number, region: string) => {

+ 55 - 34
dashboard/src/main/home/cluster-dashboard/expanded-chart/metrics/AreaChart.tsx

@@ -1,15 +1,19 @@
-import React, { useMemo, useCallback } from 'react';
-import { AreaClosed, Line, Bar } from '@visx/shape';
-import appleStock, { AppleStock } from '@visx/mock-data/lib/mocks/appleStock';
-import { curveMonotoneX } from '@visx/curve';
-import { GridRows, GridColumns } from '@visx/grid';
-import { scaleTime, scaleLinear } from '@visx/scale';
-import { withTooltip, Tooltip, TooltipWithBounds, defaultStyles } from '@visx/tooltip';
-import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withTooltip';
-import { localPoint } from '@visx/event';
-import { LinearGradient } from '@visx/gradient';
-import { max, extent, bisector } from 'd3-array';
-import { timeFormat } from 'd3-time-format';
+import React, { useMemo, useCallback } from "react";
+import { AreaClosed, Line, Bar } from "@visx/shape";
+import appleStock, { AppleStock } from "@visx/mock-data/lib/mocks/appleStock";
+import { curveMonotoneX } from "@visx/curve";
+import { scaleTime, scaleLinear } from "@visx/scale";
+import {
+  withTooltip,
+  Tooltip,
+  TooltipWithBounds,
+  defaultStyles,
+} from "@visx/tooltip";
+import { WithTooltipProvidedProps } from "@visx/tooltip/lib/enhancers/withTooltip";
+import { localPoint } from "@visx/event";
+import { LinearGradient } from "@visx/gradient";
+import { max, extent, bisector } from "d3-array";
+import { timeFormat } from "d3-time-format";
 
 /*
 export const accentColor = '#f5cb42';
@@ -19,15 +23,15 @@ export const accentColorDark = '#949eff';
 type TooltipData = AppleStock;
 
 const stock = appleStock.slice(800);
-export const background = '#3b697800';
-export const background2 = '#20405100';
-export const accentColor = '#949eff';
-export const accentColorDark = '#949eff';
+export const background = "#3b697800";
+export const background2 = "#20405100";
+export const accentColor = "#949eff";
+export const accentColorDark = "#949eff";
 const tooltipStyles = {
   ...defaultStyles,
   background,
-  border: '1px solid white',
-  color: 'white',
+  border: "1px solid white",
+  color: "white",
 };
 
 // util
@@ -36,7 +40,7 @@ const formatDate = timeFormat("%b %d, '%y");
 // accessors
 const getDate = (d: AppleStock) => new Date(d.date);
 const getStockValue = (d: AppleStock) => d.close;
-const bisectDate = bisector<AppleStock, Date>(d => new Date(d.date)).left;
+const bisectDate = bisector<AppleStock, Date>((d) => new Date(d.date)).left;
 
 export type AreaProps = {
   width: number;
@@ -68,7 +72,7 @@ export default withTooltip<AreaProps, TooltipData>(
           range: [margin.left, innerWidth + margin.left],
           domain: extent(stock, getDate) as [Date, Date],
         }),
-      [innerWidth, margin.left],
+      [innerWidth, margin.left]
     );
     const stockValueScale = useMemo(
       () =>
@@ -77,12 +81,16 @@ export default withTooltip<AreaProps, TooltipData>(
           domain: [0, (max(stock, getStockValue) || 0) + innerHeight / 3],
           nice: true,
         }),
-      [margin.top, innerHeight],
+      [margin.top, innerHeight]
     );
 
     // tooltip handler
     const handleTooltip = useCallback(
-      (event: React.TouchEvent<SVGRectElement> | React.MouseEvent<SVGRectElement>) => {
+      (
+        event:
+          | React.TouchEvent<SVGRectElement>
+          | React.MouseEvent<SVGRectElement>
+      ) => {
         const { x } = localPoint(event) || { x: 0 };
         const x0 = dateScale.invert(x);
         const index = bisectDate(stock, x0, 1);
@@ -90,7 +98,11 @@ export default withTooltip<AreaProps, TooltipData>(
         const d1 = stock[index];
         let d = d0;
         if (d1 && getDate(d1)) {
-          d = x0.valueOf() - getDate(d0).valueOf() > getDate(d1).valueOf() - x0.valueOf() ? d1 : d0;
+          d =
+            x0.valueOf() - getDate(d0).valueOf() >
+            getDate(d1).valueOf() - x0.valueOf()
+              ? d1
+              : d0;
         }
         showTooltip({
           tooltipData: d,
@@ -98,7 +110,7 @@ export default withTooltip<AreaProps, TooltipData>(
           tooltipTop: stockValueScale(getStockValue(d)),
         });
       },
-      [showTooltip, stockValueScale, dateScale],
+      [showTooltip, stockValueScale, dateScale]
     );
 
     return (
@@ -112,12 +124,21 @@ export default withTooltip<AreaProps, TooltipData>(
             fill="url(#area-background-gradient)"
             rx={14}
           />
-          <LinearGradient id="area-background-gradient" from={background} to={background2} />
-          <LinearGradient id="area-gradient" from={accentColor} to={accentColor} toOpacity={0} />
+          <LinearGradient
+            id="area-background-gradient"
+            from={background}
+            to={background2}
+          />
+          <LinearGradient
+            id="area-gradient"
+            from={accentColor}
+            to={accentColor}
+            toOpacity={0}
+          />
           <AreaClosed<AppleStock>
             data={stock}
-            x={d => dateScale(getDate(d)) ?? 0}
-            y={d => stockValueScale(getStockValue(d)) ?? 0}
+            x={(d) => dateScale(getDate(d)) ?? 0}
+            y={(d) => stockValueScale(getStockValue(d)) ?? 0}
             yScale={stockValueScale}
             strokeWidth={1}
             stroke="url(#area-gradient)"
@@ -184,12 +205,12 @@ export default withTooltip<AreaProps, TooltipData>(
               left={tooltipLeft}
               style={{
                 ...defaultStyles,
-                background: '#26272f',
-                color: '#aaaabb',
+                background: "#26272f",
+                color: "#aaaabb",
                 width: 100,
                 paddingTop: 35,
-                textAlign: 'center',
-                transform: 'translateX(-60px)',
+                textAlign: "center",
+                transform: "translateX(-60px)",
               }}
             >
               {formatDate(getDate(tooltipData))}
@@ -198,5 +219,5 @@ export default withTooltip<AreaProps, TooltipData>(
         )}
       </div>
     );
-  },
-);
+  }
+);

+ 24 - 20
dashboard/src/main/home/cluster-dashboard/expanded-chart/metrics/MetricsSection.tsx

@@ -1,6 +1,6 @@
 import React, { Component } from "react";
 import styled from "styled-components";
-import ParentSize from '@visx/responsive/lib/components/ParentSize';
+import ParentSize from "@visx/responsive/lib/components/ParentSize";
 
 import { Context } from "shared/Context";
 import { ChartType } from "shared/types";
@@ -13,26 +13,28 @@ type PropsType = {
 };
 
 type StateType = {
-  selectedRange: string,
-  selectedMetricLabel: string,
-  dropdownExpanded: boolean,
+  selectedRange: string;
+  selectedMetricLabel: string;
+  dropdownExpanded: boolean;
 };
 
 export default class ListSection extends Component<PropsType, StateType> {
   state = {
-    selectedRange: '1H',
-    selectedMetricLabel: 'CPU Utilization',
+    selectedRange: "1H",
+    selectedMetricLabel: "CPU Utilization",
     dropdownExpanded: false,
-  }
+  };
 
   renderDropdown = () => {
     if (this.state.dropdownExpanded) {
       return (
         <>
-          <DropdownOverlay onClick={() => this.setState({ dropdownExpanded: false })} />
+          <DropdownOverlay
+            onClick={() => this.setState({ dropdownExpanded: false })}
+          />
           <Dropdown
-            dropdownWidth='200px'
-            dropdownMaxHeight='200px'
+            dropdownWidth="200px"
+            dropdownMaxHeight="200px"
             onClick={() => this.setState({ dropdownExpanded: false })}
           >
             {this.renderOptionList()}
@@ -44,8 +46,8 @@ export default class ListSection extends Component<PropsType, StateType> {
 
   renderOptionList = () => {
     let metricOptions = [
-      { value: 'cpu', label: 'CPU Utilization' },
-      { value: 'ram', label: 'RAM Utilization' },
+      { value: "cpu", label: "CPU Utilization" },
+      { value: "ram", label: "RAM Utilization" },
     ];
     return metricOptions.map(
       (option: { value: string; label: string }, i: number) => {
@@ -69,8 +71,10 @@ export default class ListSection extends Component<PropsType, StateType> {
         <ParentSize>
           {({ width, height }) => <AreaChart width={width} height={height} />}
         </ParentSize>
-        <MetricSelector 
-          onClick={() => this.setState({ dropdownExpanded: !this.state.dropdownExpanded })}
+        <MetricSelector
+          onClick={() =>
+            this.setState({ dropdownExpanded: !this.state.dropdownExpanded })
+          }
         >
           {this.state.selectedMetricLabel}
           <i className="material-icons">arrow_drop_down</i>
@@ -79,12 +83,12 @@ export default class ListSection extends Component<PropsType, StateType> {
         <RangeWrapper>
           <TabSelector
             options={[
-              { value: '1H', label: '1H' }, 
-              { value: '1D', label: '1D' },
-              { value: '1M', label: '1M' }, 
-              { value: '3M', label: '3M' },
-              { value: '1Y', label: '1Y' }, 
-              { value: 'ALL', label: 'ALL' },
+              { value: "1H", label: "1H" },
+              { value: "1D", label: "1D" },
+              { value: "1M", label: "1M" },
+              { value: "3M", label: "3M" },
+              { value: "1Y", label: "1Y" },
+              { value: "ALL", label: "ALL" },
             ]}
             currentTab={this.state.selectedRange}
             setCurrentTab={(x: string) => this.setState({ selectedRange: x })}

+ 42 - 15
dashboard/src/main/home/templates/Templates.tsx → dashboard/src/main/home/launch/Launch.tsx

@@ -11,7 +11,10 @@ import Loading from "components/Loading";
 
 import hardcodedNames from "./hardcodedNameDict";
 
-const tabOptions = [{ label: "Community Templates", value: "community" }];
+const tabOptions = [
+  { label: "Launch service", value: "docker" },
+  { label: "Community Templates", value: "community" },
+];
 
 type PropsType = {};
 
@@ -26,7 +29,7 @@ type StateType = {
 export default class Templates extends Component<PropsType, StateType> {
   state = {
     currentTemplate: null as PorterTemplate | null,
-    currentTab: "community",
+    currentTab: "docker",
     porterTemplates: [] as PorterTemplate[],
     loading: true,
     error: false,
@@ -41,7 +44,11 @@ export default class Templates extends Component<PropsType, StateType> {
           this.state.porterTemplates.sort((a, b) =>
             a.name === "docker" ? -1 : b.name === "docker" ? 1 : 0
           );
-          this.setState({ loading: false });
+          // TODO: properly find "docker" template instead of relying on first
+          this.setState({
+            loading: false,
+            currentTemplate: this.state.porterTemplates[0],
+          });
         });
       })
       .catch(() => this.setState({ loading: false, error: true }));
@@ -82,8 +89,9 @@ export default class Templates extends Component<PropsType, StateType> {
       );
     }
 
-    return this.state.porterTemplates.map(
-      (template: PorterTemplate, i: number) => {
+    return this.state.porterTemplates
+      .filter((t) => t.name.toLowerCase() !== "docker")
+      .map((template: PorterTemplate, i: number) => {
         let { name, icon, description } = template;
         if (hardcodedNames[name]) {
           name = hardcodedNames[name];
@@ -98,11 +106,25 @@ export default class Templates extends Component<PropsType, StateType> {
             <TemplateDescription>{description}</TemplateDescription>
           </TemplateBlock>
         );
-      }
-    );
+      });
+  };
+
+  renderDefaultTemplate = () => {
+    if (this.state.currentTemplate) {
+      return (
+        <ExpandedTemplate
+          currentTemplate={this.state.porterTemplates[0]}
+          setCurrentTemplate={(currentTemplate: PorterTemplate) =>
+            this.setState({ currentTemplate })
+          }
+          skipDescription={true}
+        />
+      );
+    }
+    return null;
   };
 
-  renderContents = () => {
+  renderCommunityTemplates = () => {
     if (this.state.currentTemplate) {
       return (
         <ExpandedTemplate
@@ -113,11 +135,14 @@ export default class Templates extends Component<PropsType, StateType> {
         />
       );
     }
+    return <TemplateList>{this.renderTemplateList()}</TemplateList>;
+  };
 
+  render() {
     return (
       <TemplatesWrapper>
         <TitleSection>
-          <Title>Template Explorer</Title>
+          <Title>Launch</Title>
           <a
             href="https://docs.getporter.dev/docs/porter-templates"
             target="_blank"
@@ -129,16 +154,18 @@ export default class Templates extends Component<PropsType, StateType> {
           options={tabOptions}
           currentTab={this.state.currentTab}
           setCurrentTab={(value: string) =>
-            this.setState({ currentTab: value })
+            this.setState({
+              currentTab: value,
+              currentTemplate:
+                value === "docker" ? this.state.porterTemplates[0] : null,
+            })
           }
         />
-        <TemplateList>{this.renderTemplateList()}</TemplateList>
+        {this.state.currentTab === "docker"
+          ? this.renderDefaultTemplate()
+          : this.renderCommunityTemplates()}
       </TemplatesWrapper>
     );
-  };
-
-  render() {
-    return this.renderContents();
   }
 }
 

+ 15 - 3
dashboard/src/main/home/templates/expanded-template/ExpandedTemplate.tsx → dashboard/src/main/home/launch/expanded-template/ExpandedTemplate.tsx

@@ -11,6 +11,7 @@ import Loading from "components/Loading";
 type PropsType = {
   currentTemplate: PorterTemplate;
   setCurrentTemplate: (x: PorterTemplate) => void;
+  skipDescription?: boolean;
 };
 
 type StateType = {
@@ -35,6 +36,10 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
   };
 
   componentDidMount() {
+    this.fetchTemplateInfo();
+  }
+
+  fetchTemplateInfo = () => {
     this.setState({ loading: true });
     api
       .getTemplateInfo(
@@ -58,7 +63,13 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
         });
       })
       .catch((err) => this.setState({ loading: false, error: true }));
-  }
+  };
+
+  componentDidUpdate = (prevProps: PropsType) => {
+    if (prevProps.currentTemplate !== this.props.currentTemplate) {
+      this.fetchTemplateInfo();
+    }
+  };
 
   renderContents = () => {
     if (this.state.loading) {
@@ -68,11 +79,12 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
         </LoadingWrapper>
       );
     }
-    if (this.state.showLaunchTemplate) {
+    if (this.props.skipDescription || this.state.showLaunchTemplate) {
       return (
         <LaunchTemplate
           currentTemplate={this.props.currentTemplate}
           hideLaunch={() => this.setState({ showLaunchTemplate: false })}
+          hideBackButton={this.props.skipDescription}
           values={this.state.values}
           form={this.state.form}
         />
@@ -119,5 +131,5 @@ const LoadingWrapper = styled.div`
 const StyledExpandedTemplate = styled.div`
   width: calc(90% - 150px);
   min-width: 300px;
-  padding-top: 75px;
+  padding-top: 10px;
 `;

+ 8 - 8
dashboard/src/main/home/templates/expanded-template/LaunchTemplate.tsx → dashboard/src/main/home/launch/expanded-template/LaunchTemplate.tsx

@@ -27,6 +27,7 @@ type PropsType = {
   hideLaunch: () => void;
   values: any;
   form: any;
+  hideBackButton?: boolean;
 };
 
 type StateType = {
@@ -473,15 +474,14 @@ export default class LaunchTemplate extends Component<PropsType, StateType> {
 
     return (
       <StyledLaunchTemplate>
-        <TitleSection>
-          <Flex>
-            <i className="material-icons" onClick={this.props.hideLaunch}>
-              keyboard_backspace
-            </i>
-            <Title>Launch Template</Title>
-          </Flex>
-        </TitleSection>
         <ClusterSection>
+          {this.props.hideBackButton ? null : (
+            <Flex>
+              <i className="material-icons" onClick={this.props.hideLaunch}>
+                keyboard_backspace
+              </i>
+            </Flex>
+          )}
           <Template>
             {icon
               ? this.renderIcon(icon)

+ 0 - 0
dashboard/src/main/home/templates/expanded-template/TemplateInfo.tsx → dashboard/src/main/home/launch/expanded-template/TemplateInfo.tsx


+ 0 - 0
dashboard/src/main/home/templates/hardcodedNameDict.tsx → dashboard/src/main/home/launch/hardcodedNameDict.tsx


+ 18 - 9
dashboard/src/main/home/sidebar/ProjectSection.tsx

@@ -23,20 +23,25 @@ class ProjectSection extends Component<PropsType, StateType> {
   wrapperRef: any = React.createRef();
 
   componentDidMount() {
-    document.addEventListener('mousedown', this.handleClickOutside.bind(this));
+    document.addEventListener("mousedown", this.handleClickOutside.bind(this));
   }
 
   componentWillUnmount() {
-    document.removeEventListener('mousedown', this.handleClickOutside.bind(this));
+    document.removeEventListener(
+      "mousedown",
+      this.handleClickOutside.bind(this)
+    );
   }
 
   handleClickOutside = (e: any) => {
     if (
-      this.wrapperRef && this.wrapperRef.current && !this.wrapperRef.current.contains(e.target)
+      this.wrapperRef &&
+      this.wrapperRef.current &&
+      !this.wrapperRef.current.contains(e.target)
     ) {
       this.setState({ expanded: false });
     }
-  }
+  };
 
   renderOptionList = () => {
     let { setCurrentProject } = this.context;
@@ -46,7 +51,11 @@ class ProjectSection extends Component<PropsType, StateType> {
         <Option
           key={i}
           selected={project.name === this.props.currentProject.name}
-          onClick={() => {this.setState({ expanded: false }); setCurrentProject(project)}}
+          onClick={() => {
+            this.setState({ expanded: false });
+            setCurrentProject(project);
+            this.props.history.push("dashboard");
+          }}
         >
           <ProjectIcon>
             <ProjectImage src={gradient} />
@@ -67,7 +76,9 @@ class ProjectSection extends Component<PropsType, StateType> {
             <Option
               selected={false}
               lastItem={true}
-              onClick={() => { this.props.history.push('new-project') }}
+              onClick={() => {
+                this.props.history.push("new-project");
+              }}
             >
               <ProjectIconAlt>+</ProjectIconAlt>
               <ProjectLabel>Create a Project</ProjectLabel>
@@ -86,9 +97,7 @@ class ProjectSection extends Component<PropsType, StateType> {
     let { currentProject } = this.props;
     if (currentProject) {
       return (
-        <StyledProjectSection
-          ref={this.wrapperRef}
-        >
+        <StyledProjectSection ref={this.wrapperRef}>
           <MainSelector
             onClick={this.handleExpand}
             expanded={this.state.expanded}

+ 3 - 3
dashboard/src/main/home/sidebar/Sidebar.tsx

@@ -112,11 +112,11 @@ class Sidebar extends Component<PropsType, StateType> {
             Dashboard
           </NavButton>
           <NavButton
-            onClick={() => this.props.history.push("templates")}
-            selected={currentView === "templates"}
+            onClick={() => this.props.history.push("launch")}
+            selected={currentView === "launch"}
           >
             <Img src={filter} />
-            Templates
+            Launch
           </NavButton>
           <NavButton
             selected={currentView === "integrations"}

+ 9 - 3
dashboard/src/shared/routing.tsx

@@ -1,8 +1,16 @@
 import { Location } from "history";
 
+export type PorterUrl =
+  | "dashboard"
+  | "launch"
+  | "integrations"
+  | "new-project"
+  | "cluster-dashboard"
+  | "project-settings";
+
 export const PorterUrls = [
   "dashboard",
-  "templates",
+  "launch",
   "integrations",
   "new-project",
   "cluster-dashboard",
@@ -21,5 +29,3 @@ export const setSearchParam = (
     search: urlParams.toString(),
   };
 };
-
-export type PorterUrls = typeof PorterUrls[number];

+ 23 - 25
dashboard/webpack.config.js

@@ -1,7 +1,7 @@
-const path = require('path');
+const path = require("path");
 const HtmlWebpackPlugin = require("html-webpack-plugin");
-const webpack = require('webpack');
-const dotenv = require('dotenv');
+const webpack = require("webpack");
+const dotenv = require("dotenv");
 
 module.exports = () => {
   const env = dotenv.config().parsed;
@@ -11,9 +11,9 @@ module.exports = () => {
   }, {});
 
   return {
-    entry: './src/index.tsx',
-    target: 'web',
-    mode: 'development',
+    entry: "./src/index.tsx",
+    target: "web",
+    mode: "development",
     module: {
       rules: [
         {
@@ -27,33 +27,31 @@ module.exports = () => {
         },
         {
           test: /\.(png|svg|jpg|gif|mp3)$/,
-          use: [
-            'file-loader'
-          ]
+          use: ["file-loader"],
         },
-        { test: /\.css$/, use: [ 'css-loader' ] },
+        { test: /\.css$/, use: ["css-loader"] },
         {
           test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
           use: [
             {
-              loader: 'file-loader',
+              loader: "file-loader",
               options: {
-                name: '[name].[ext]',
-                outputPath: 'fonts/'
-              }
-            }
-          ]
-        }
+                name: "[name].[ext]",
+                outputPath: "fonts/",
+              },
+            },
+          ],
+        },
       ],
     },
     resolve: {
       modules: [path.resolve(__dirname, "src"), "node_modules"],
-      extensions: ['*', '.tsx', '.ts', '.js', '.jsx', '.json'],
+      extensions: ["*", ".tsx", ".ts", ".js", ".jsx", ".json"],
     },
     output: {
-      filename: 'bundle.js',
-      path: path.resolve(__dirname, 'build'),
-      publicPath: '/'
+      filename: "bundle.js",
+      path: path.resolve(__dirname, "build"),
+      publicPath: "/",
     },
     devServer: {
       historyApiFallback: true,
@@ -62,7 +60,7 @@ module.exports = () => {
       new HtmlWebpackPlugin({
         template: path.resolve(__dirname, "src", "index.html"),
       }),
-      new webpack.DefinePlugin(envKeys)
-    ]
-  }
-};
+      new webpack.DefinePlugin(envKeys),
+    ],
+  };
+};