From cc7f584b962ff1d86e5f07777878e017d0ddeae5 Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Fri, 8 Jul 2022 10:25:36 +0100 Subject: [PATCH] feat(challenge-editor): make work in gitpod (#46784) * feat(challenge-editor): make work in gitpod * gitpod: make chal-editor ports public * refactor: use .env files to set variables Co-authored-by: Oliver Eyton-Williams --- .gitpod.yml | 6 ++++++ package-lock.json | 21 +++++++++++++++++++ tools/challenge-editor/api/package.json | 4 +++- tools/challenge-editor/api/sample.env | 1 + tools/challenge-editor/api/server.ts | 5 ++++- tools/challenge-editor/client/package.json | 3 ++- tools/challenge-editor/client/sample.env | 1 + .../client/src/components/block/Block.tsx | 3 ++- .../components/buttons/CreateEmptySteps.tsx | 19 +++++++---------- .../src/components/buttons/CreateNextStep.tsx | 11 ++++------ .../src/components/buttons/DeleteStep.tsx | 4 ++-- .../src/components/buttons/InsertStep.tsx | 4 ++-- .../src/components/buttons/SaveChallenge.tsx | 4 ++-- .../components/buttons/UpdateStepTitles.tsx | 11 ++++------ .../client/src/components/editor/Editor.tsx | 3 ++- .../client/src/components/landing/Landing.tsx | 3 ++- .../src/components/superblock/SuperBlock.tsx | 3 ++- .../client/src/utils/handleRequest.ts | 3 +++ 18 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 tools/challenge-editor/api/sample.env create mode 100644 tools/challenge-editor/client/sample.env diff --git a/.gitpod.yml b/.gitpod.yml index 76a4c749236..46ccd89059a 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -14,6 +14,10 @@ ports: onOpen: ignore - port: 9230 # client node debug onOpen: ignore + - port: 3200 # challenge editor api + visibility: public + - port: 3300 # challenge editor client + visibility: public tasks: - before: | @@ -22,6 +26,8 @@ tasks: export HOME_LOCATION=$(gp url 8000) export API_LOCATION=$(gp url 3000) export CYPRESS_BASE_URL=$(gp url 8000) + export REACT_APP_CHALLENGE_EDITOR_API_LOCATION=$(gp url 3200) + export CHALLENGE_EDITOR_CLIENT_LOCATION=$(gp url 3300) ' >> ~/.bashrc; exit; diff --git a/package-lock.json b/package-lock.json index 3674a40009a..15b5a9bfdd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53736,6 +53736,7 @@ "tools/challenge-editor/api": { "name": "@freecodecamp/challenge-editor", "version": "1.0.0", + "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { "cors": "2.8.5", @@ -53745,12 +53746,23 @@ }, "devDependencies": { "@types/express": "4.17.13", + "dotenv": "16.0.1", "typescript": "4.7.4" } }, + "tools/challenge-editor/api/node_modules/dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "tools/challenge-editor/client": { "name": "@freecodecamp/challenge-editor-client", "version": "0.1.0", + "hasInstallScript": true, "dependencies": { "@testing-library/jest-dom": "5.16.4", "@testing-library/react": "12.1.5", @@ -56066,10 +56078,19 @@ "requires": { "@types/express": "4.17.13", "cors": "2.8.5", + "dotenv": "16.0.1", "express": "4.18.1", "gray-matter": "4.0.3", "ts-node": "10.8.2", "typescript": "4.7.4" + }, + "dependencies": { + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true + } } }, "@freecodecamp/challenge-editor-client": { diff --git a/tools/challenge-editor/api/package.json b/tools/challenge-editor/api/package.json index 27ecd15ff2e..f0afdb6a1d7 100644 --- a/tools/challenge-editor/api/package.json +++ b/tools/challenge-editor/api/package.json @@ -4,7 +4,8 @@ "private": true, "description": "Editor to help with new challenge structure", "scripts": { - "start": "ts-node server.ts" + "start": "ts-node server.ts", + "postinstall": "cp ./sample.env ./.env" }, "author": "freeCodeCamp", "license": "BSD-3-Clause", @@ -16,6 +17,7 @@ }, "devDependencies": { "@types/express": "4.17.13", + "dotenv": "16.0.1", "typescript": "4.7.4" } } diff --git a/tools/challenge-editor/api/sample.env b/tools/challenge-editor/api/sample.env new file mode 100644 index 00000000000..e1749a00c07 --- /dev/null +++ b/tools/challenge-editor/api/sample.env @@ -0,0 +1 @@ +CHALLENGE_EDITOR_CLIENT_LOCATION=http://localhost:3300 diff --git a/tools/challenge-editor/api/server.ts b/tools/challenge-editor/api/server.ts index c035e06c0eb..da8e318712e 100644 --- a/tools/challenge-editor/api/server.ts +++ b/tools/challenge-editor/api/server.ts @@ -1,3 +1,6 @@ +import * as dotenv from 'dotenv'; +dotenv.config(); + import cors from 'cors'; import express from 'express'; import { blockRoute } from './routes/blockRoute'; @@ -11,7 +14,7 @@ const app = express(); app.use( cors({ - origin: 'http://localhost:3300' + origin: process.env.CHALLENGE_EDITOR_CLIENT_LOCATION }) ); diff --git a/tools/challenge-editor/client/package.json b/tools/challenge-editor/client/package.json index 9a06d3594d7..a38540d044a 100644 --- a/tools/challenge-editor/client/package.json +++ b/tools/challenge-editor/client/package.json @@ -18,7 +18,8 @@ "lint": "eslint src", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "postinstall": "cp ./sample.env ./.env" }, "browserslist": { "production": [ diff --git a/tools/challenge-editor/client/sample.env b/tools/challenge-editor/client/sample.env new file mode 100644 index 00000000000..207be49823a --- /dev/null +++ b/tools/challenge-editor/client/sample.env @@ -0,0 +1 @@ +REACT_APP_CHALLENGE_EDITOR_API_LOCATION=http://localhost:3200 diff --git a/tools/challenge-editor/client/src/components/block/Block.tsx b/tools/challenge-editor/client/src/components/block/Block.tsx index 48b52fa863b..7c78e59e02b 100644 --- a/tools/challenge-editor/client/src/components/block/Block.tsx +++ b/tools/challenge-editor/client/src/components/block/Block.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import { Link, useParams } from 'react-router-dom'; import { ChallengeData } from '../../../interfaces/ChallengeData'; +import { API_LOCATION } from '../../utils/handleRequest'; import './Block.css'; const Block = () => { @@ -16,7 +17,7 @@ const Block = () => { const fetchData = () => { setLoading(true); - fetch(`http://localhost:3200/${params.superblock}/${params.block}`) + fetch(`${API_LOCATION}/${params.superblock}/${params.block}`) .then(res => res.json() as Promise) .then( superblocks => { diff --git a/tools/challenge-editor/client/src/components/buttons/CreateEmptySteps.tsx b/tools/challenge-editor/client/src/components/buttons/CreateEmptySteps.tsx index df06245abce..e0b9f7d6893 100644 --- a/tools/challenge-editor/client/src/components/buttons/CreateEmptySteps.tsx +++ b/tools/challenge-editor/client/src/components/buttons/CreateEmptySteps.tsx @@ -1,21 +1,18 @@ import React, { useState } from 'react'; import { BlockRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const CreateEmptySteps = ({ superblock, block }: BlockRequiredProps) => { const [num, setNum] = useState(0); const click = handleRequest(() => - fetch( - `http://localhost:3200/${superblock}/${block}/_tools/create-empty-steps`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ num }) - } - ) + fetch(`${API_LOCATION}/${superblock}/${block}/_tools/create-empty-steps`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ num }) + }) ); const changeNum = (e: React.ChangeEvent) => { diff --git a/tools/challenge-editor/client/src/components/buttons/CreateNextStep.tsx b/tools/challenge-editor/client/src/components/buttons/CreateNextStep.tsx index fc40f8276df..6d2384971ea 100644 --- a/tools/challenge-editor/client/src/components/buttons/CreateNextStep.tsx +++ b/tools/challenge-editor/client/src/components/buttons/CreateNextStep.tsx @@ -1,15 +1,12 @@ import React from 'react'; import { BlockRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const CreateNextStep = ({ superblock, block }: BlockRequiredProps) => { const click = handleRequest(() => - fetch( - `http://localhost:3200/${superblock}/${block}/_tools/create-next-step`, - { - method: 'POST' - } - ) + fetch(`${API_LOCATION}/${superblock}/${block}/_tools/create-next-step`, { + method: 'POST' + }) ); return ; diff --git a/tools/challenge-editor/client/src/components/buttons/DeleteStep.tsx b/tools/challenge-editor/client/src/components/buttons/DeleteStep.tsx index 03f85579cb2..f4cff02f227 100644 --- a/tools/challenge-editor/client/src/components/buttons/DeleteStep.tsx +++ b/tools/challenge-editor/client/src/components/buttons/DeleteStep.tsx @@ -1,12 +1,12 @@ import React, { useState } from 'react'; import { BlockRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const DeleteStep = ({ superblock, block }: BlockRequiredProps) => { const [num, setNum] = useState(0); const click = handleRequest(() => - fetch(`http://localhost:3200/${superblock}/${block}/_tools/delete-step`, { + fetch(`${API_LOCATION}/${superblock}/${block}/_tools/delete-step`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/tools/challenge-editor/client/src/components/buttons/InsertStep.tsx b/tools/challenge-editor/client/src/components/buttons/InsertStep.tsx index 24ddd338c0b..d4b6cb433e4 100644 --- a/tools/challenge-editor/client/src/components/buttons/InsertStep.tsx +++ b/tools/challenge-editor/client/src/components/buttons/InsertStep.tsx @@ -1,12 +1,12 @@ import React, { useState } from 'react'; import { BlockRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const InsertStep = ({ superblock, block }: BlockRequiredProps) => { const [num, setNum] = useState(0); const click = handleRequest(() => - fetch(`http://localhost:3200/${superblock}/${block}/_tools/insert-step`, { + fetch(`${API_LOCATION}/${superblock}/${block}/_tools/insert-step`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/tools/challenge-editor/client/src/components/buttons/SaveChallenge.tsx b/tools/challenge-editor/client/src/components/buttons/SaveChallenge.tsx index dc6ad8c0230..ad2f28022ad 100644 --- a/tools/challenge-editor/client/src/components/buttons/SaveChallenge.tsx +++ b/tools/challenge-editor/client/src/components/buttons/SaveChallenge.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ChallengeContentRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const SaveChallenge = ({ superblock, @@ -9,7 +9,7 @@ const SaveChallenge = ({ content }: ChallengeContentRequiredProps) => { const click = handleRequest(() => - fetch(`http://localhost:3200/${superblock}/${block}/${challenge}`, { + fetch(`${API_LOCATION}/${superblock}/${block}/${challenge}`, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/tools/challenge-editor/client/src/components/buttons/UpdateStepTitles.tsx b/tools/challenge-editor/client/src/components/buttons/UpdateStepTitles.tsx index 48eac7ee0c5..cd73010c217 100644 --- a/tools/challenge-editor/client/src/components/buttons/UpdateStepTitles.tsx +++ b/tools/challenge-editor/client/src/components/buttons/UpdateStepTitles.tsx @@ -1,15 +1,12 @@ import React from 'react'; import { BlockRequiredProps } from '../../../interfaces/PropTypes'; -import { handleRequest } from '../../utils/handleRequest'; +import { API_LOCATION, handleRequest } from '../../utils/handleRequest'; const UpdateStepTitles = ({ superblock, block }: BlockRequiredProps) => { const click = handleRequest(() => - fetch( - `http://localhost:3200/${superblock}/${block}/_tools/update-step-titles`, - { - method: 'POST' - } - ) + fetch(`${API_LOCATION}/${superblock}/${block}/_tools/update-step-titles`, { + method: 'POST' + }) ); return ; diff --git a/tools/challenge-editor/client/src/components/editor/Editor.tsx b/tools/challenge-editor/client/src/components/editor/Editor.tsx index 57ff407bbce..8ab19c73424 100644 --- a/tools/challenge-editor/client/src/components/editor/Editor.tsx +++ b/tools/challenge-editor/client/src/components/editor/Editor.tsx @@ -12,6 +12,7 @@ import { Link, useParams } from 'react-router-dom'; import { ChallengeContent } from '../../../interfaces/ChallengeContent'; import SaveChallenge from '../buttons/SaveChallenge'; import './Editor.css'; +import { API_LOCATION } from '../../utils/handleRequest'; const Editor = () => { const [error, setError] = useState(null); @@ -35,7 +36,7 @@ const Editor = () => { const fetchData = () => { setLoading(true); fetch( - `http://localhost:3200/${params.superblock}/${params.block}/${params.challenge}` + `${API_LOCATION}/${params.superblock}/${params.block}/${params.challenge}` ) .then(res => res.json() as Promise) .then( diff --git a/tools/challenge-editor/client/src/components/landing/Landing.tsx b/tools/challenge-editor/client/src/components/landing/Landing.tsx index c3279ed771f..5cfbf25f6c5 100644 --- a/tools/challenge-editor/client/src/components/landing/Landing.tsx +++ b/tools/challenge-editor/client/src/components/landing/Landing.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { SuperBlock } from '../../../interfaces/SuperBlock'; +import { API_LOCATION } from '../../utils/handleRequest'; const Landing = () => { const [error, setError] = useState(null); @@ -13,7 +14,7 @@ const Landing = () => { const fetchData = () => { setLoading(true); - fetch('http://localhost:3200/') + fetch(API_LOCATION) .then(res => res.json() as Promise) .then( superblocks => { diff --git a/tools/challenge-editor/client/src/components/superblock/SuperBlock.tsx b/tools/challenge-editor/client/src/components/superblock/SuperBlock.tsx index 90ebaf0acf7..909190b5316 100644 --- a/tools/challenge-editor/client/src/components/superblock/SuperBlock.tsx +++ b/tools/challenge-editor/client/src/components/superblock/SuperBlock.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import { Link, useParams } from 'react-router-dom'; import { Block } from '../../../interfaces/Block'; +import { API_LOCATION } from '../../utils/handleRequest'; const SuperBlock = () => { const [error, setError] = useState(null); @@ -15,7 +16,7 @@ const SuperBlock = () => { const fetchData = () => { setLoading(true); - fetch(`http://localhost:3200/${params.superblock}`) + fetch(`${API_LOCATION}/${params.superblock}`) .then(res => res.json() as Promise) .then( blocks => { diff --git a/tools/challenge-editor/client/src/utils/handleRequest.ts b/tools/challenge-editor/client/src/utils/handleRequest.ts index 3404c0a5fae..8f4fc759610 100644 --- a/tools/challenge-editor/client/src/utils/handleRequest.ts +++ b/tools/challenge-editor/client/src/utils/handleRequest.ts @@ -4,3 +4,6 @@ export const handleRequest = (makeRequest: () => Promise) => () => { .then(data => alert(JSON.stringify(data))) .catch(err => console.error(err)); }; + +export const API_LOCATION = process.env + .REACT_APP_CHALLENGE_EDITOR_API_LOCATION as string;