瀏覽代碼

added markdown render to expanded template (README.md as placeholder)

jusrhee 5 年之前
父節點
當前提交
794d19a74a

+ 15 - 5
dashboard/package-lock.json

@@ -407,6 +407,14 @@
       "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
       "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
       "dev": true
       "dev": true
     },
     },
+    "@types/markdown-to-jsx": {
+      "version": "6.11.3",
+      "resolved": "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz",
+      "integrity": "sha512-30nFYpceM/ZEvhGiqWjm5quLUxNeld0HCzJEXMZZDpq53FPkS85mTwkWtCXzCqq8s5JYLgM5W392a02xn8Bdaw==",
+      "requires": {
+        "@types/react": "*"
+      }
+    },
     "@types/minimatch": {
     "@types/minimatch": {
       "version": "3.0.3",
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -422,8 +430,7 @@
     "@types/prop-types": {
     "@types/prop-types": {
       "version": "15.7.3",
       "version": "15.7.3",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
-      "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
-      "dev": true
+      "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
     },
     },
     "@types/qs": {
     "@types/qs": {
       "version": "6.9.5",
       "version": "6.9.5",
@@ -434,7 +441,6 @@
       "version": "16.9.49",
       "version": "16.9.49",
       "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz",
       "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.49.tgz",
       "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==",
       "integrity": "sha512-DtLFjSj0OYAdVLBbyjhuV9CdGVHCkHn2R+xr3XkBvK2rS1Y1tkc14XSGjYgm5Fjjr90AxH9tiSzc1pCFMGO06g==",
-      "dev": true,
       "requires": {
       "requires": {
         "@types/prop-types": "*",
         "@types/prop-types": "*",
         "csstype": "^3.0.2"
         "csstype": "^3.0.2"
@@ -2034,8 +2040,7 @@
     "csstype": {
     "csstype": {
       "version": "3.0.3",
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz",
       "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz",
-      "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag==",
-      "dev": true
+      "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag=="
     },
     },
     "cyclist": {
     "cyclist": {
       "version": "1.0.1",
       "version": "1.0.1",
@@ -4306,6 +4311,11 @@
         "object-visit": "^1.0.0"
         "object-visit": "^1.0.0"
       }
       }
     },
     },
+    "markdown-to-jsx": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.0.1.tgz",
+      "integrity": "sha512-0agsmQtnoAzGt2fO8jgoFL5wvDUbpjoIfQffErQZmP66BxaWMBGifsAo0RRuye+2Ydlp7csX6X6HpF2xaL6J1w=="
+    },
     "md5.js": {
     "md5.js": {
       "version": "1.3.5",
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",

+ 2 - 0
dashboard/package.json

@@ -4,11 +4,13 @@
   "private": true,
   "private": true,
   "dependencies": {
   "dependencies": {
     "@types/js-yaml": "^3.12.5",
     "@types/js-yaml": "^3.12.5",
+    "@types/markdown-to-jsx": "^6.11.3",
     "@types/qs": "^6.9.5",
     "@types/qs": "^6.9.5",
     "ace-builds": "^1.4.12",
     "ace-builds": "^1.4.12",
     "axios": "^0.20.0",
     "axios": "^0.20.0",
     "dotenv": "^8.2.0",
     "dotenv": "^8.2.0",
     "js-yaml": "^3.14.0",
     "js-yaml": "^3.14.0",
+    "markdown-to-jsx": "^7.0.1",
     "qs": "^6.9.4",
     "qs": "^6.9.4",
     "react": "^16.13.1",
     "react": "^16.13.1",
     "react-ace": "^9.1.3",
     "react-ace": "^9.1.3",

+ 3 - 0
dashboard/src/main/Main.tsx

@@ -122,6 +122,9 @@ const GlobalStyle = createGlobalStyle`
     background: #202227;
     background: #202227;
     overscroll-behavior-x: none;
     overscroll-behavior-x: none;
   }
   }
+  a {
+    color: #949eff;
+  }
 `;
 `;
 
 
 const StyledMain = styled.div`
 const StyledMain = styled.div`

+ 1 - 0
dashboard/src/main/home/templates/Templates.tsx

@@ -42,6 +42,7 @@ export default class Templates extends Component<PropsType, StateType> {
         this.setState({ loading: false, error: true });
         this.setState({ loading: false, error: true });
       } else {
       } else {
         this.setState({ porterCharts: res.data, loading: false, error: false });
         this.setState({ porterCharts: res.data, loading: false, error: false });
+        console.log(res.data)
       }
       }
     });
     });
   }
   }

+ 18 - 7
dashboard/src/main/home/templates/expanded-template/ExpandedTemplate.tsx

@@ -1,6 +1,7 @@
 import React, { Component } from 'react';
 import React, { Component } from 'react';
 import styled from 'styled-components';
 import styled from 'styled-components';
 import launch from '../../../../assets/launch.svg';
 import launch from '../../../../assets/launch.svg';
+import Markdown from 'markdown-to-jsx';
 
 
 import { PorterChart } from '../../../../shared/types';
 import { PorterChart } from '../../../../shared/types';
 
 
@@ -34,6 +35,19 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
     });
     });
   }
   }
 
 
+  renderMarkdown = () => {
+    let { currentChart } = this.props;
+    if (currentChart.Markdown) {
+      return (
+        <Markdown>{currentChart.Markdown}</Markdown>
+      );
+    } else if (currentChart.Form.Description) {
+      return currentChart.Form.Description;
+    }
+
+    return currentChart.Description;
+  }
+
   render() {
   render() {
     let { Name, Icon, Description } = this.props.currentChart.Form;
     let { Name, Icon, Description } = this.props.currentChart.Form;
     let { currentChart } = this.props;
     let { currentChart } = this.props;
@@ -58,11 +72,7 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
           {this.renderTagList()}
           {this.renderTagList()}
         </TagSection>
         </TagSection>
         <ContentSection>
         <ContentSection>
-          <br />
-          [Add Markdown Support] <br /><br />
-          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br /><br />
-          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br /><br />
-          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. <br /><br />
+          {this.renderMarkdown()}
         </ContentSection>
         </ContentSection>
       </StyledExpandedTemplate>
       </StyledExpandedTemplate>
     );
     );
@@ -70,9 +80,10 @@ export default class ExpandedTemplate extends Component<PropsType, StateType> {
 }
 }
 
 
 const ContentSection = styled.div`
 const ContentSection = styled.div`
-  margin-top: 20px;
+  margin-top: 40px;
   font-size: 14px;
   font-size: 14px;
   line-height: 1.8em;
   line-height: 1.8em;
+  padding-bottom: 100px;
 `;
 `;
 
 
 const Tag = styled.div`
 const Tag = styled.div`
@@ -125,7 +136,7 @@ const Button = styled.div`
   font-size: 13px;
   font-size: 13px;
   padding: 10px 15px;
   padding: 10px 15px;
   border-radius: 3px;
   border-radius: 3px;
-  cursor: not-allowed;
+  cursor: pointer;
   box-shadow: 0 5px 8px 0px #00000010;
   box-shadow: 0 5px 8px 0px #00000010;
   display: flex;
   display: flex;
   flex-direction: row;
   flex-direction: row;

+ 2 - 1
dashboard/src/shared/types.tsx

@@ -68,7 +68,8 @@ export interface PorterChart {
 	Name: string,
 	Name: string,
 	Description: string,
 	Description: string,
 	Icon: string,
 	Icon: string,
-	Form: FormYAML
+  Form: FormYAML,
+  Markdown?: string,
 }
 }
 
 
 // FormYAML represents a chart's values.yaml form abstraction
 // FormYAML represents a chart's values.yaml form abstraction

+ 30 - 12
server/api/template_handler.go

@@ -44,6 +44,7 @@ type PorterChart struct {
 	Description string
 	Description string
 	Icon        string
 	Icon        string
 	Form        FormYAML
 	Form        FormYAML
+	Markdown    string
 }
 }
 
 
 // FormYAML represents a chart's values.yaml form abstraction
 // FormYAML represents a chart's values.yaml form abstraction
@@ -60,7 +61,7 @@ type FormYAML struct {
 			Name     string `yaml:"name,omitempty"`
 			Name     string `yaml:"name,omitempty"`
 			Variable string `yaml:"variable,omitempty"`
 			Variable string `yaml:"variable,omitempty"`
 			Settings struct {
 			Settings struct {
-				Default int `yaml:"default"`
+				Default interface{}
 			} `yaml:"settings,omitempty"`
 			} `yaml:"settings,omitempty"`
 		} `yaml:"contents"`
 		} `yaml:"contents"`
 	} `yaml:"sections"`
 	} `yaml:"sections"`
@@ -68,6 +69,7 @@ type FormYAML struct {
 
 
 // HandleListTemplates retrieves a list of Porter templates
 // HandleListTemplates retrieves a list of Porter templates
 // TODO: test and reduce fragility (handle untar/parse error for individual charts)
 // TODO: test and reduce fragility (handle untar/parse error for individual charts)
+// TODO: separate markdown retrieval into its own query if necessary
 func (app *App) HandleListTemplates(w http.ResponseWriter, r *http.Request) {
 func (app *App) HandleListTemplates(w http.ResponseWriter, r *http.Request) {
 	resp, err := http.Get(baseURL + "index.yaml")
 	resp, err := http.Get(baseURL + "index.yaml")
 	if err != nil {
 	if err != nil {
@@ -93,7 +95,7 @@ func (app *App) HandleListTemplates(w http.ResponseWriter, r *http.Request) {
 			tarURL = baseURL + tarURL
 			tarURL = baseURL + tarURL
 		}
 		}
 
 
-		formData, err := getFormData(tarURL)
+		formData, markdown, err := processTarball(tarURL)
 		if err != nil {
 		if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
 			return
 			return
@@ -104,6 +106,9 @@ func (app *App) HandleListTemplates(w http.ResponseWriter, r *http.Request) {
 		porterChart.Description = indexChart.Description
 		porterChart.Description = indexChart.Description
 		porterChart.Icon = indexChart.Icon
 		porterChart.Icon = indexChart.Icon
 		porterChart.Form = *formData
 		porterChart.Form = *formData
+		if markdown != "" {
+			porterChart.Markdown = markdown
+		}
 
 
 		porterCharts = append(porterCharts, porterChart)
 		porterCharts = append(porterCharts, porterChart)
 	}
 	}
@@ -111,11 +116,11 @@ func (app *App) HandleListTemplates(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(porterCharts)
 	json.NewEncoder(w).Encode(porterCharts)
 }
 }
 
 
-func getFormData(tarURL string) (*FormYAML, error) {
+func processTarball(tarURL string) (*FormYAML, string, error) {
 	resp, err := http.Get(tarURL)
 	resp, err := http.Get(tarURL)
 	if err != nil {
 	if err != nil {
 		fmt.Println(err)
 		fmt.Println(err)
-		return nil, err
+		return nil, "", err
 	}
 	}
 
 
 	defer resp.Body.Close()
 	defer resp.Body.Close()
@@ -125,18 +130,19 @@ func getFormData(tarURL string) (*FormYAML, error) {
 	gzf, err := gzip.NewReader(buf)
 	gzf, err := gzip.NewReader(buf)
 	if err != nil {
 	if err != nil {
 		fmt.Println(err)
 		fmt.Println(err)
-		return nil, err
+		return nil, "", err
 	}
 	}
 
 
-	// Process tarball to generate FormYAML
+	// Process tarball to generate FormYAML and retrieve markdown
 	tarReader := tar.NewReader(gzf)
 	tarReader := tar.NewReader(gzf)
+	markdown := ""
 	for {
 	for {
 		header, err := tarReader.Next()
 		header, err := tarReader.Next()
 		if err == io.EOF {
 		if err == io.EOF {
 			break
 			break
 		} else if err != nil {
 		} else if err != nil {
 			fmt.Println(err)
 			fmt.Println(err)
-			return nil, err
+			return nil, "", err
 		}
 		}
 
 
 		name := header.Name
 		name := header.Name
@@ -145,6 +151,19 @@ func getFormData(tarURL string) (*FormYAML, error) {
 			continue
 			continue
 		case tar.TypeReg:
 		case tar.TypeReg:
 
 
+			// Handle info.md if found
+			if strings.Contains(name, "README.md") {
+				bufMd := new(bytes.Buffer)
+
+				_, err := io.Copy(bufMd, tarReader)
+				if err != nil {
+					fmt.Println(err)
+					return nil, "", err
+				}
+
+				markdown = string(bufMd.Bytes())
+			}
+
 			// Handle form.yaml located in archive
 			// Handle form.yaml located in archive
 			if strings.Contains(name, "form.yaml") {
 			if strings.Contains(name, "form.yaml") {
 				bufForm := new(bytes.Buffer)
 				bufForm := new(bytes.Buffer)
@@ -152,17 +171,16 @@ func getFormData(tarURL string) (*FormYAML, error) {
 				_, err := io.Copy(bufForm, tarReader)
 				_, err := io.Copy(bufForm, tarReader)
 				if err != nil {
 				if err != nil {
 					fmt.Println(err)
 					fmt.Println(err)
-					return nil, err
+					return nil, "", err
 				}
 				}
 
 
 				// Unmarshal yaml byte buffer
 				// Unmarshal yaml byte buffer
 				form := FormYAML{}
 				form := FormYAML{}
 				if err := yaml.Unmarshal(bufForm.Bytes(), &form); err != nil {
 				if err := yaml.Unmarshal(bufForm.Bytes(), &form); err != nil {
 					fmt.Println(err)
 					fmt.Println(err)
-					return nil, err
+					return nil, "", err
 				}
 				}
-
-				return &form, nil
+				return &form, markdown, nil
 			}
 			}
 		default:
 		default:
 			fmt.Printf("%s : %c %s %s\n",
 			fmt.Printf("%s : %c %s %s\n",
@@ -173,5 +191,5 @@ func getFormData(tarURL string) (*FormYAML, error) {
 			)
 			)
 		}
 		}
 	}
 	}
-	return nil, errors.New("no form.yaml found")
+	return nil, "", errors.New("no form.yaml found")
 }
 }