Skip to content

Commit

Permalink
Incorporating variables into the UI (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
CGoodwin90 authored Aug 24, 2023
1 parent 846180e commit 0c27199
Show file tree
Hide file tree
Showing 65 changed files with 3,914 additions and 158 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ README.md
**/build/
**/yarn-error.log
**/.gitignore
node_modules
build

# Envs
**/.env.local
3 changes: 0 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ COPY --from=builder /app/node_modules /app/node_modules
# Copying files from ui service
COPY . /app/

# Making sure we run in production
ENV NODE_ENV=production

ARG KEYCLOAK_API
ENV KEYCLOAK_API=$KEYCLOAK_API

Expand Down
8 changes: 1 addition & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,15 @@ services:
dockerfile: Dockerfile
labels:
lagoon.type: node
command: yarn run start
command: yarn run dev
volumes:
- ./src:/app/src
- ./.env.defaults:/app/.env.defaults
- ./.env.schema:/app/.env.schema
- ./package.json:/app/package.json
ports:
- '8888:3000'
- '3003:3003'
networks:
- amazeeio-network
- default
environment:
<<: *default-environment

networks:
amazeeio-network:
external: true
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"apollo-link-error": "^1.1.1",
"apollo-link-http": "^1.5.5",
"apollo-link-ws": "^1.0.10",
"babel-plugin-styled-components": "^2.1.1",
"bootstrap": "^5.2.3",
"babel-plugin-styled-components": "^2.0.7",
"colors": "^1.4.0",
"core-js": "^3.30.1",
"crypto-js": "^4.1.1",
Expand All @@ -58,6 +59,7 @@
"react": "18.2.0",
"react-apollo": "^2.1.11",
"react-beautiful-dnd": "^13.0.0",
"react-bootstrap": "^2.7.2",
"react-copy-to-clipboard": "^5.0.1",
"react-dom": "18.2.0",
"react-hexgrid": "1.0.4",
Expand Down
15 changes: 15 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ app
app.render(req, res, '/project', { projectName: req.params.projectSlug });
});

server.get('/projects/:projectSlug/project-variables', (req, res) => {
app.render(req, res, '/project-variables', { projectName: req.params.projectSlug });
});

server.get('/projects/:projectSlug/deploy-targets', (req, res) => {
app.render(req, res, '/deploy-targets', { projectName: req.params.projectSlug });
});


server.get('/projects/:projectSlug/:environmentSlug', (req, res) => {
app.render(req, res, '/environment', {
openshiftProjectName: req.params.environmentSlug,
Expand Down Expand Up @@ -108,6 +117,12 @@ app
});
});

server.get('/projects/:projectSlug/:environmentSlug/environment-variables', (req, res) => {
app.render(req, res, '/environment-variables', {
openshiftProjectName: req.params.environmentSlug
});
});

server.get('/alldeployments', (req, res) => {
app.render(req, res, '/alldeployments', {});
});
Expand Down
57 changes: 57 additions & 0 deletions src/components/AddVariable/StyledAddVariable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import styled from "styled-components";
import { color } from "lib/variables";

export const NewVariable = styled.div`
.var-modal {
padding: 10px 0;
}
input {
margin-right: 10px;
width: 100%;
}
.form-input {
display: flex;
align-items: center;
justify-content: space-between;
}
.add-var-btn {
margin-top: 16px;
}
`;

export const NewVariableModal = styled.div`
.var-modal {
padding: 10px 0;
}
.variable-target {
text-align: center;
color: #5f6f7a;
font-family: "source-code-pro", sans-serif;
font-weight: bold;
}
input {
margin-right: 10px;
width: 100%;
}
.form-input {
display: flex;
align-items: center;
justify-content: space-between;
span {
color: ${color.blue};
cursor: pointer;
}
}
.add-var-btn {
margin-top: 16px;
}
a.hover-state {
margin-right: 10px;
color: ${color.blue};
}
.react-select__control, .react-select__menu, .react-select__option, .react-select__single-value {
background:${(props) => props.theme.backgrounds.primary};
color: ${props => props.theme.texts.primary};
}
`;
197 changes: 197 additions & 0 deletions src/components/AddVariable/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import React, {useEffect, useState} from "react";
import Modal from "components/Modal";
import ButtonBootstrap from "react-bootstrap/Button";
import Button from 'components/Button'
import ReactSelect from "react-select";
import { Mutation } from "react-apollo";
import withLogic from "components/AddVariable/logic";
import addOrUpdateEnvVariableMutation from "../../lib/mutation/AddOrUpdateEnvVariableByName";
import { NewVariable, NewVariableModal, custom } from "./StyledAddVariable";

/**
* Adds a Variable.
*/

const scopeOptions = [
{ value: "BUILD", label: "BUILD" },
{ value: "RUNTIME", label: "RUNTIME" },
{ value: "GLOBAL", label: "GLOBAL" },
{ value: "CONTAINER_REGISTRY", label: "CONTAINER_REGISTRY" },
{
value: "INTERNAL_CONTAINER_REGISTRY",
label: "INTERNAL_CONTAINER_REGISTRY",
},
];

export const AddVariable = ({
varProject,
varEnvironment,
varValues,
varTarget,
noVars,
varName,
varValue,
varScope,
refresh,
icon,
inputName,
setInputName,
inputValue,
setInputValue,
inputScope,
setInputScope,
open,
openModal,
closeModal,
setClear,
}) => {
const [updateName, setUpdateName] = useState(varName);
const [updateValue, setUpdateValue] = useState(varValue);
const [updateScope, setUpdateScope] = useState(varScope);
const handleUpdateValue = (event) => {setUpdateValue(event.target.value)};
useEffect(() => {
setUpdateValue(varValue);
setUpdateName(varName);
setUpdateScope(varScope);
}, [varValue]);

return (
<NewVariable>
{
icon ?
<Button variant='white' icon={icon} action={openModal}>
Update
</Button>
:
<ButtonBootstrap onClick={openModal}>
{
noVars || !updateName ? "Add" : "Update"
}
</ButtonBootstrap>
}
<Modal
isOpen={open}
onRequestClose={closeModal}
contentLabel={`Confirm`}
variant={"large"}
>
<NewVariableModal>
<div className="variable-target">
<span className="variable-target">
{
noVars || !updateName ? `Add ${varTarget} Variable` : `Update ${varTarget} Variable`
}
</span>
</div>
<div className="var-modal">
<label htmlFor="varName">Scope</label>
{
<ReactSelect
classNamePrefix="react-select"
aria-label="Scope"
placeholder="Select a variable scope"
name="results"
value={varScope ? scopeOptions.find((o) => o.value === updateScope.toUpperCase()) : scopeOptions.find((o) => o.value === inputScope)}
onChange={varScope ? (selectedOption) => setUpdateScope(selectedOption.value)
: (selectedOption) => setInputScope(selectedOption.value)
}
options={scopeOptions}
required
/>
}
</div>
<div className="var-modal">
<label htmlFor="varName">Name</label>
<input
id="varNameId"
name="varName"
className="addVarnameInput"
type="text"
value={varName ? updateName : inputName}
onChange={!varName ? setInputName : null}
readOnly={!!varName}
/>
</div>
<div className="var-modal">
<label htmlFor="varName">Value</label>
<input
id="varValueId"
name="varValue"
className="addVarValueInput"
type="text"
value={varValue ? updateValue : inputValue}
onChange={varValue ? handleUpdateValue : setInputValue}
/>
</div>
<div className="form-input add-var-btn">
<a href="#" className="hover-state" onClick={closeModal}>
cancel
</a>
<Mutation mutation={addOrUpdateEnvVariableMutation}>
{(addOrUpdateEnvVariableByName, { called, error, data }) => {
let updateVar = varValues.map((varName) => {
return varName.name;
});
updateVar = updateVar.includes(inputName);
if (error) {
console.error(error);
return (
<div>
Unauthorized: You don't have permission to create this
variable.
</div>
);
}

if (data) {
refresh().then(setClear).then(closeModal);
}

if (updateVar && called || updateName && called ) {
return <div>Updating variable</div>;
} else if (called) {
return <div>Adding variable</div>;
}

const addOrUpdateEnvVariableHandler = () => {
addOrUpdateEnvVariableByName({
variables: {
input: {
name: updateName ? updateName : inputName,
value: updateValue ? updateValue : inputValue,
scope: updateScope ? updateScope.toUpperCase() : inputScope,
project: varProject,
environment: varEnvironment,
},
},
});
};

return (
<ButtonBootstrap
disabled={ updateName ?
updateName === "" || updateValue === "" || updateScope === ""
:
inputName === "" || inputValue === "" || inputScope === ""
}
onClick={addOrUpdateEnvVariableHandler}
>
{varTarget == "Environment"
? updateVar || varName
? "Update environment variable"
: "Add environment variable"
: updateVar || varName
? "Update project variable"
: "Add project variable"}
</ButtonBootstrap>
);
}}
</Mutation>
</div>
</NewVariableModal>
</Modal>
</NewVariable>
);
};

export default withLogic(AddVariable);
33 changes: 33 additions & 0 deletions src/components/AddVariable/logic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import compose from "recompose/compose";
import withState from "recompose/withState";
import withHandlers from "recompose/withHandlers";

const withInputValue = withState("inputValue", "setInputValue", "");
const withInputName = withState("inputName", "setInputName", "");
const withInputScope = withState("inputScope", "setInputScope", "");
const withInputClear = withState("clear", "setClear", "");

const withInputHandlers = withHandlers({
setInputValue: ({ setInputValue }) => (event) =>
setInputValue(event.target.value),
setInputName: ({ setInputName }) => (event) =>
setInputName(event.target.value),
setClear: ({ setInputValue, setInputName, setInputScope }) => () =>
[setInputValue(''), setInputName(''), setInputScope('')],
});

const withModalState = withState("open", "setOpen", false);
const withModalHandlers = withHandlers({
openModal: ({ setOpen }) => () => setOpen(true),
closeModal: ({ setOpen }) => () => setOpen(false),
});

export default compose(
withInputValue,
withInputName,
withInputScope,
withInputClear,
withInputHandlers,
withModalState,
withModalHandlers
);
Loading

0 comments on commit 0c27199

Please sign in to comment.