|
|
@@ -1,4 +1,4 @@
|
|
|
-import React, { useState } from "react"
|
|
|
+import React, { useState } from "react";
|
|
|
import ServiceContainer from "./ServiceContainer";
|
|
|
import styled from "styled-components";
|
|
|
import Spacer from "components/porter/Spacer";
|
|
|
@@ -19,32 +19,41 @@ interface ServicesProps {
|
|
|
setServices: (services: Service[]) => void;
|
|
|
}
|
|
|
|
|
|
-const Services: React.FC<ServicesProps> = ({
|
|
|
- services,
|
|
|
- setServices,
|
|
|
-}) => {
|
|
|
- const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(false);
|
|
|
- const [serviceName, setServiceName] = useState<string>('');
|
|
|
- const [serviceType, setServiceType] = useState<ServiceType>('web');
|
|
|
+const Services: React.FC<ServicesProps> = ({ services, setServices }) => {
|
|
|
+ const [showAddServiceModal, setShowAddServiceModal] = useState<boolean>(
|
|
|
+ false
|
|
|
+ );
|
|
|
+ const [serviceName, setServiceName] = useState<string>("");
|
|
|
+ const [serviceType, setServiceType] = useState<ServiceType>("web");
|
|
|
+ const isServiceNameValid = (name: string) => {
|
|
|
+ const regex = /^[a-z0-9-]+$/;
|
|
|
+ return regex.test(name);
|
|
|
+ };
|
|
|
|
|
|
return (
|
|
|
<>
|
|
|
- {services.length > 0 &&
|
|
|
+ {services.length > 0 && (
|
|
|
<>
|
|
|
<ServicesContainer>
|
|
|
{services.map((service, index) => {
|
|
|
return (
|
|
|
<ServiceContainer
|
|
|
service={service}
|
|
|
- editService={(newService: Service) => setServices(services.map((s, i) => i === index ? newService : s))}
|
|
|
- deleteService={() => setServices(services.filter((_, i) => i !== index))}
|
|
|
+ editService={(newService: Service) =>
|
|
|
+ setServices(
|
|
|
+ services.map((s, i) => (i === index ? newService : s))
|
|
|
+ )
|
|
|
+ }
|
|
|
+ deleteService={() =>
|
|
|
+ setServices(services.filter((_, i) => i !== index))
|
|
|
+ }
|
|
|
/>
|
|
|
- )
|
|
|
+ );
|
|
|
})}
|
|
|
</ServicesContainer>
|
|
|
<Spacer y={0.5} />
|
|
|
</>
|
|
|
- }
|
|
|
+ )}
|
|
|
<AddServiceButton onClick={() => setShowAddServiceModal(true)}>
|
|
|
<i className="material-icons add-icon">add_icon</i>
|
|
|
Add a new service
|
|
|
@@ -57,18 +66,18 @@ const Services: React.FC<ServicesProps> = ({
|
|
|
<Spacer y={0.5} />
|
|
|
<Container row>
|
|
|
<ServiceIcon>
|
|
|
- {serviceType === 'web' && <img src={web} />}
|
|
|
- {serviceType === 'worker' && <img src={worker} />}
|
|
|
- {serviceType === 'job' && <img src={job} />}
|
|
|
+ {serviceType === "web" && <img src={web} />}
|
|
|
+ {serviceType === "worker" && <img src={worker} />}
|
|
|
+ {serviceType === "job" && <img src={job} />}
|
|
|
</ServiceIcon>
|
|
|
<Select
|
|
|
value={serviceType}
|
|
|
// this is ugly
|
|
|
setValue={(value: string) => setServiceType(value as ServiceType)}
|
|
|
options={[
|
|
|
- { label: 'Web', value: 'web' },
|
|
|
- { label: 'Worker', value: 'worker' },
|
|
|
- { label: 'Job', value: 'job' }
|
|
|
+ { label: "Web", value: "web" },
|
|
|
+ { label: "Worker", value: "worker" },
|
|
|
+ { label: "Job", value: "job" },
|
|
|
]}
|
|
|
/>
|
|
|
</Container>
|
|
|
@@ -79,24 +88,34 @@ const Services: React.FC<ServicesProps> = ({
|
|
|
placeholder="ex: my-service"
|
|
|
width="300px"
|
|
|
value={serviceName}
|
|
|
+ error={
|
|
|
+ !isServiceNameValid(serviceName) &&
|
|
|
+ 'Lowercase letters, numbers, and "-" only.'
|
|
|
+ }
|
|
|
setValue={setServiceName}
|
|
|
/>
|
|
|
<Spacer y={1} />
|
|
|
- <Button onClick={() => {
|
|
|
- setServices([...services, createDefaultService(serviceName, serviceType)]);
|
|
|
- setShowAddServiceModal(false);
|
|
|
- setServiceName('');
|
|
|
- setServiceType('web');
|
|
|
- }}>
|
|
|
+ <Button
|
|
|
+ onClick={() => {
|
|
|
+ setServices([
|
|
|
+ ...services,
|
|
|
+ createDefaultService(serviceName, serviceType),
|
|
|
+ ]);
|
|
|
+ setShowAddServiceModal(false);
|
|
|
+ setServiceName("");
|
|
|
+ setServiceType("web");
|
|
|
+ }}
|
|
|
+ disabled={!isServiceNameValid(serviceName)}
|
|
|
+ >
|
|
|
<I className="material-icons">add</I> Add service
|
|
|
</Button>
|
|
|
</Modal>
|
|
|
)}
|
|
|
</>
|
|
|
- )
|
|
|
-}
|
|
|
+ );
|
|
|
+};
|
|
|
|
|
|
-export default Services
|
|
|
+export default Services;
|
|
|
|
|
|
const ServiceIcon = styled.div`
|
|
|
border: 1px solid #494b4f;
|
|
|
@@ -133,11 +152,10 @@ const I = styled.i`
|
|
|
justify-content: center;
|
|
|
`;
|
|
|
|
|
|
-const ServicesContainer = styled.div`
|
|
|
-`;
|
|
|
+const ServicesContainer = styled.div``;
|
|
|
|
|
|
const AddServiceButton = styled.div`
|
|
|
- color: #aaaabb;
|
|
|
+ color: #aaaabb;
|
|
|
background: #26292e;
|
|
|
border: 1px solid #494b4f;
|
|
|
:hover {
|
|
|
@@ -156,4 +174,4 @@ const AddServiceButton = styled.div`
|
|
|
width: 30px;
|
|
|
font-size: 20px;
|
|
|
}
|
|
|
-`;
|
|
|
+`;
|