github.com/minio/console@v1.4.1/web-app/src/screens/Console/IDP/AddIDPConfiguration.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { useEffect, useState } from "react"; 18 import { 19 BackLink, 20 Button, 21 FormLayout, 22 Grid, 23 InputBox, 24 PageLayout, 25 SectionTitle, 26 Switch, 27 } from "mds"; 28 import { useNavigate } from "react-router-dom"; 29 import { useAppDispatch } from "../../../store"; 30 import { modalStyleUtils } from "../Common/FormComponents/common/styleLibrary"; 31 import { 32 setErrorSnackMessage, 33 setHelpName, 34 setServerNeedsRestart, 35 } from "../../../systemSlice"; 36 import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; 37 import HelpMenu from "../HelpMenu"; 38 import { api } from "api"; 39 import { ApiError, HttpResponse, SetIDPResponse } from "api/consoleApi"; 40 import { errorToHandler } from "api/errors"; 41 42 type AddIDPConfigurationProps = { 43 classes?: any; 44 icon: React.ReactNode; 45 helpBox: React.ReactNode; 46 header: string; 47 title: string; 48 backLink: string; 49 formFields: object; 50 }; 51 52 const AddIDPConfiguration = ({ 53 icon, 54 helpBox, 55 header, 56 backLink, 57 title, 58 formFields, 59 }: AddIDPConfigurationProps) => { 60 const extraFormFields = { 61 name: { 62 required: true, 63 hasError: (s: string, editMode: boolean) => { 64 return !s && editMode ? "Config Name is required" : ""; 65 }, 66 label: "Name", 67 tooltip: "Name for identity provider configuration", 68 placeholder: "Name", 69 type: "text", 70 }, 71 ...formFields, 72 }; 73 74 const navigate = useNavigate(); 75 const dispatch = useAppDispatch(); 76 77 const [fields, setFields] = useState<any>({}); 78 const [loadingCreate, setLoadingCreate] = useState<boolean>(false); 79 80 const validSave = () => { 81 for (const [key, value] of Object.entries(extraFormFields)) { 82 if ( 83 value.required && 84 !( 85 fields[key] !== undefined && 86 fields[key] !== null && 87 fields[key] !== "" 88 ) 89 ) { 90 return false; 91 } 92 } 93 return true; 94 }; 95 96 const resetForm = () => { 97 setFields({}); 98 }; 99 100 const addRecord = (event: React.FormEvent) => { 101 setLoadingCreate(true); 102 event.preventDefault(); 103 const name = fields["name"]; 104 let input = ""; 105 for (const key of Object.keys(formFields)) { 106 if (fields[key]) { 107 input += `${key}=${fields[key]} `; 108 } 109 } 110 111 api.idp 112 .createConfiguration("openid", { name, input }) 113 .then((res: HttpResponse<SetIDPResponse, ApiError>) => { 114 navigate(backLink); 115 dispatch(setServerNeedsRestart(res.data.restart === true)); 116 }) 117 .catch((res: HttpResponse<SetIDPResponse, ApiError>) => { 118 dispatch(setErrorSnackMessage(errorToHandler(res.error))); 119 }) 120 .finally(() => setLoadingCreate(false)); 121 }; 122 123 const renderFormField = (key: string, value: any) => { 124 switch (value.type) { 125 case "toggle": 126 return ( 127 <Switch 128 indicatorLabels={["Enabled", "Disabled"]} 129 checked={fields[key] === "on" ? true : false} 130 value={"is-field-enabled"} 131 id={"is-field-enabled"} 132 name={"is-field-enabled"} 133 label={value.label} 134 tooltip={value.tooltip} 135 onChange={(e) => 136 setFields({ ...fields, [key]: e.target.checked ? "on" : "off" }) 137 } 138 description="" 139 /> 140 ); 141 default: 142 return ( 143 <InputBox 144 id={key} 145 required={value.required} 146 name={key} 147 label={value.label} 148 tooltip={value.tooltip} 149 error={value.hasError(fields[key], true)} 150 value={fields[key] ? fields[key] : ""} 151 onChange={(e: React.ChangeEvent<HTMLInputElement>) => 152 setFields({ ...fields, [key]: e.target.value }) 153 } 154 placeholder={value.placeholder} 155 type={value.type} 156 /> 157 ); 158 } 159 }; 160 161 useEffect(() => { 162 dispatch(setHelpName("add_idp_config")); 163 // eslint-disable-next-line react-hooks/exhaustive-deps 164 }, []); 165 166 return ( 167 <Grid item xs={12}> 168 <PageHeaderWrapper 169 label={<BackLink onClick={() => navigate(backLink)} label={header} />} 170 actions={<HelpMenu />} 171 /> 172 <PageLayout> 173 <FormLayout helpBox={helpBox}> 174 <SectionTitle icon={icon}>{title}</SectionTitle> 175 <form 176 noValidate 177 autoComplete="off" 178 onSubmit={(e: React.FormEvent<HTMLFormElement>) => { 179 addRecord(e); 180 }} 181 > 182 <Grid container> 183 <Grid xs={12} item> 184 {Object.entries(extraFormFields).map(([key, value]) => 185 renderFormField(key, value), 186 )} 187 <Grid item xs={12} sx={modalStyleUtils.modalButtonBar}> 188 <Button 189 id={"clear"} 190 type="button" 191 variant="regular" 192 onClick={resetForm} 193 label={"Clear"} 194 /> 195 196 <Button 197 id={"save-key"} 198 type="submit" 199 variant="callAction" 200 color="primary" 201 disabled={loadingCreate || !validSave()} 202 label={"Save"} 203 /> 204 </Grid> 205 </Grid> 206 </Grid> 207 </form> 208 </FormLayout> 209 </PageLayout> 210 </Grid> 211 ); 212 }; 213 214 export default AddIDPConfiguration;