github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/lib/components/repositoryCreateForm.jsx (about)

     1  import React, {useEffect, useRef, useState} from 'react';
     2  import Form from "react-bootstrap/Form";
     3  import Alert from "react-bootstrap/Alert";
     4  import {Warnings} from "./controls";
     5  import {FloatingLabel} from "react-bootstrap";
     6  import Accordion from "react-bootstrap/Accordion";
     7  
     8  const DEFAULT_BLOCKSTORE_EXAMPLE = "e.g. s3://example-bucket/";
     9  const DEFAULT_BLOCKSTORE_VALIDITY_REGEX = new RegExp(`^s3://`);
    10  
    11  export const RepositoryCreateForm = ({ id, config, onSubmit, formValid, setFormValid, error = null, sampleRepoChecked = false }) => {
    12      const repoValidityRegex = /^[a-z0-9][a-z0-9-]{2,62}$/;
    13  
    14      const [repoValid, setRepoValid] = useState(null);
    15      const defaultNamespacePrefix = config.default_namespace_prefix
    16  
    17      const [storageNamespaceValid, setStorageNamespaceValid] = useState(defaultNamespacePrefix ? true : null);
    18      const [defaultBranchValid, setDefaultBranchValid] = useState(true);
    19      
    20      const storageNamespaceField = useRef(null);
    21      const defaultBranchField = useRef(null);
    22      const repoNameField = useRef(null);
    23      const sampleDataCheckbox = useRef(null);
    24  
    25      useEffect(() => {
    26          if (sampleDataCheckbox.current) {
    27              sampleDataCheckbox.current.checked = sampleRepoChecked;
    28          }
    29      }, [sampleRepoChecked, sampleDataCheckbox.current]);
    30  
    31  
    32      const onRepoNameChange = () => {
    33          const isRepoValid = repoValidityRegex.test(repoNameField.current.value);
    34          setRepoValid(isRepoValid);
    35          setFormValid(isRepoValid && storageNamespaceValid && defaultBranchValid);
    36          if (defaultNamespacePrefix) {
    37              storageNamespaceField.current.value = defaultNamespacePrefix + repoNameField.current.value
    38              checkStorageNamespaceValidity()
    39          }
    40      };
    41  
    42      const checkStorageNamespaceValidity = () => {
    43          const isStorageNamespaceValid = storageNamespaceValidityRegex.test(storageNamespaceField.current.value);
    44          setStorageNamespaceValid(isStorageNamespaceValid);
    45          setFormValid(isStorageNamespaceValid && defaultBranchValid && repoValidityRegex.test(repoNameField.current.value));
    46      };
    47  
    48      const checkDefaultBranchValidity = () => {
    49          const isBranchValid = defaultBranchField.current.value.length;
    50          setDefaultBranchValid(isBranchValid);
    51          setFormValid(isBranchValid && storageNamespaceValid && repoValid);
    52      };
    53  
    54      const storageType = config.blockstore_type
    55      const storageNamespaceValidityRegexStr = config ? config.blockstore_namespace_ValidityRegex : DEFAULT_BLOCKSTORE_VALIDITY_REGEX;
    56      const storageNamespaceValidityRegex = RegExp(storageNamespaceValidityRegexStr);
    57      const storageNamespaceExample = config ? config.blockstore_namespace_example : DEFAULT_BLOCKSTORE_EXAMPLE;
    58  
    59      useEffect(() => {
    60          if (repoNameField.current) {
    61              repoNameField.current.focus();
    62          }
    63      }, []);
    64  
    65      const sampleCheckbox = (
    66        <Form.Group controlId="sampleData" className="mt-3">
    67            <Form.Check ref={sampleDataCheckbox} type="checkbox" label="Add sample data, hooks, and configuration" />
    68        </Form.Group>
    69      );
    70  
    71      const flattenForm = !defaultNamespacePrefix;
    72  
    73      const basicSettings = (
    74        <>
    75            <Form.Group className="mb-3">
    76                <Form.Text>
    77                    A repository contains all of your objects, including the revision history. <a href="https://docs.lakefs.io/understand/model.html#repository" target="_blank" rel="noopener noreferrer">Learn more.</a>
    78                </Form.Text>
    79            </Form.Group>
    80            <Form.Group controlId="id">
    81                <FloatingLabel label="Repository ID" controlId="repositryIdControl">
    82                    <Form.Control type="text" ref={repoNameField} onChange={onRepoNameChange} placeholder="my-data-lake"/>
    83                </FloatingLabel>
    84                {repoValid === false &&
    85                  <Form.Text className="text-danger">
    86                      Min 3 characters. Only lowercase alphanumeric characters and {'\'-\''} allowed.
    87                  </Form.Text>
    88                }
    89            </Form.Group>
    90  
    91            {!flattenForm && sampleCheckbox}
    92        </>
    93      )
    94  
    95      const advancedSettings = (
    96        <>
    97            <Form.Group controlId="defaultBranch" className="mt-3">
    98                <FloatingLabel label="Default Branch Name" controlId="defaultBranchNameCtrl">
    99                    <Form.Control type="text" ref={defaultBranchField} defaultValue={"main"}  placeholder="main" onChange={checkDefaultBranchValidity}/>
   100                </FloatingLabel>
   101                {defaultBranchValid === false &&
   102                  <Form.Text className="text-danger">
   103                      Invalid Branch.
   104                  </Form.Text>
   105                }
   106            </Form.Group>
   107            <Form.Group className="mt-3">
   108                <FloatingLabel label="Storage Namespace" controlId="storageNamespaceCtrl">
   109                    <Form.Control type="text" ref={storageNamespaceField} placeholder={storageNamespaceExample} onChange={checkStorageNamespaceValidity} aria-describedby="namespaceHelpText"/>
   110                </FloatingLabel>
   111                <Form.Text muted id="namespaceHelpText">
   112                    Where should data be stored? (e.g. <code>{storageNamespaceExample}</code>)
   113                </Form.Text>
   114                {storageNamespaceValid === false &&
   115                  <p>
   116                      <Form.Text className="text-danger">
   117                          {"Can only create repository with storage type: " + storageType}
   118                      </Form.Text>
   119                  </p>
   120                }
   121            </Form.Group>
   122            {flattenForm && sampleCheckbox}
   123        </>
   124      );
   125  
   126      const creationForm = (defaultNamespacePrefix) ? (
   127        <>
   128          <section className="repository-creation-expanded">
   129            {basicSettings}
   130          </section>
   131          <Accordion className="repository-creation-accordion">
   132              <Accordion.Item eventKey={"1"}>
   133                  <Accordion.Header>Advanced Settings</Accordion.Header>
   134                  <Accordion.Body>
   135                      {advancedSettings}
   136                  </Accordion.Body>
   137              </Accordion.Item>
   138          </Accordion>
   139        </>
   140      ) : (
   141        <section className="repository-creation-expanded">
   142            {basicSettings}
   143            {advancedSettings}
   144        </section>
   145      )
   146  
   147      return (
   148          <Form id={id} onSubmit={(e) => {
   149              e.preventDefault();
   150              if (!formValid) {
   151                  return;
   152              }
   153              onSubmit({
   154                  name: repoNameField.current.value,
   155                  storage_namespace: storageNamespaceField.current.value,
   156                  default_branch: defaultBranchField.current.value,
   157                  sample_data: sampleDataCheckbox.current.checked,
   158              });
   159          }}>
   160              <h4 className="mb-3">Create A New Repository</h4>
   161  
   162              {creationForm}
   163  
   164              {config?.warnings &&
   165                <Warnings warnings={config.warnings}/>
   166              }
   167  
   168              {error &&
   169                  <div className="mb-3">
   170                      <Alert variant={"danger"}>{error.message}</Alert>
   171                  </div>
   172              }
   173          </Form>
   174      );
   175  }