1
0
mirror of synced 2025-12-19 18:14:56 -05:00

📚 docs: Allow visitors to request ERDs (#45694)

This commit is contained in:
letiescanciano
2024-10-10 07:51:39 +02:00
committed by GitHub
parent b051802f69
commit 13b158ef95
13 changed files with 619 additions and 37 deletions

1
docusaurus/.env.example Normal file
View File

@@ -0,0 +1 @@
REQUEST_ERD_API_URL=

View File

@@ -10,7 +10,9 @@
# Misc
.DS_Store
.env
.env.local
.env
.env.development.local
.env.test.local
.env.production.local

View File

@@ -1,6 +1,6 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
import "dotenv/config.js";
const yaml = require("js-yaml");
const fs = require("node:fs");
const path = require("node:path");
@@ -78,7 +78,9 @@ const config = {
},
}),
],
customFields: {
requestErdApiUrl: process.env.REQUEST_ERD_API_URL,
},
clientModules: [
require.resolve("./src/scripts/cloudStatus.js"),
require.resolve("./src/scripts/download-abctl-buttons.js"),

View File

@@ -90,7 +90,7 @@
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.18",
"@headlessui/react": "^2.1.9",
"@mdx-js/react": "^3.0.0",
"async": "2.6.4",
"autoprefixer": "10.4.16",
@@ -106,6 +106,7 @@
"del": "6.1.1",
"docusaurus-plugin-hubspot": "^1.0.0",
"docusaurus-plugin-segment": "^1.0.3",
"dotenv": "^16.4.5",
"html-loader": "^4.2.0",
"js-yaml": "^4.1.0",
"json-schema-faker": "^0.5.4",

View File

@@ -237,8 +237,8 @@ importers:
specifier: ^0.2.0
version: 0.2.0(@fortawesome/fontawesome-svg-core@6.5.1)(react@18.2.0)
'@headlessui/react':
specifier: ^1.7.18
version: 1.7.18(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
specifier: ^2.1.9
version: 2.1.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@mdx-js/react':
specifier: ^3.0.0
version: 3.0.0(@types/react@18.2.46)(react@18.2.0)
@@ -284,6 +284,9 @@ importers:
docusaurus-plugin-segment:
specifier: ^1.0.3
version: 1.0.3
dotenv:
specifier: ^16.4.5
version: 16.4.5
html-loader:
specifier: ^4.2.0
version: 4.2.0(webpack@5.89.0)
@@ -1424,6 +1427,27 @@ packages:
'@docusaurus/types':
optional: true
'@floating-ui/core@1.6.8':
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
'@floating-ui/dom@1.6.11':
resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==}
'@floating-ui/react-dom@2.1.2':
resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/react@0.26.24':
resolution: {integrity: sha512-2ly0pCkZIGEQUq5H8bBK0XJmc1xIK/RM3tvVzY3GBER7IOD1UgmC2Y2tjj4AuS+TC+vTE1KJv2053290jua0Sw==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
'@floating-ui/utils@0.2.8':
resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==}
'@fortawesome/fontawesome-common-types@6.5.1':
resolution: {integrity: sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==}
engines: {node: '>=6'}
@@ -1452,12 +1476,12 @@ packages:
'@hapi/topo@5.1.0':
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
'@headlessui/react@1.7.18':
resolution: {integrity: sha512-4i5DOrzwN4qSgNsL4Si61VMkUcWbcSKueUV7sFhpHzQcSShdlHENE5+QBntMSRvHt8NyoFO2AGG8si9lq+w4zQ==}
'@headlessui/react@2.1.9':
resolution: {integrity: sha512-ckWw7vlKtnoa1fL2X0fx1a3t/Li9MIKDVXn3SgG65YlxvDAsNrY39PPCxVM7sQRA7go2fJsuHSSauKFNaJHH7A==}
engines: {node: '>=10'}
peerDependencies:
react: ^16 || ^17 || ^18
react-dom: ^16 || ^17 || ^18
react: ^18
react-dom: ^18
'@jest/schemas@29.6.3':
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
@@ -1536,6 +1560,37 @@ packages:
'@polka/url@1.0.0-next.24':
resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==}
'@react-aria/focus@3.18.3':
resolution: {integrity: sha512-WKUElg+5zS0D3xlVn8MntNnkzJql2J6MuzAMP8Sv5WTgFDse/XGR842dsxPTIyKKdrWVCRegCuwa4m3n/GzgJw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/interactions@3.22.3':
resolution: {integrity: sha512-RRUb/aG+P0IKTIWikY/SylB6bIbLZeztnZY2vbe7RAG5MgVaCgn5HQ45SI15GlTmhsFG8CnF6slJsUFJiNHpbQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/ssr@3.9.6':
resolution: {integrity: sha512-iLo82l82ilMiVGy342SELjshuWottlb5+VefO3jOQqQRNYnJBFpUSadswDPbRimSgJUZuFwIEYs6AabkP038fA==}
engines: {node: '>= 12'}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-aria/utils@3.25.3':
resolution: {integrity: sha512-PR5H/2vaD8fSq0H/UB9inNbc8KDcVmW6fYAfSWkkn+OAdhTTMVKqXXrZuZBWyFfSD5Ze7VN6acr4hrOQm2bmrA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-stately/utils@3.10.4':
resolution: {integrity: sha512-gBEQEIMRh5f60KCm7QKQ2WfvhB2gLUr9b72sqUdIZ2EG+xuPgaIlCBeSicvjmjBvYZwOjoOEnmIkcx2GHp/HWw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@react-types/shared@3.25.0':
resolution: {integrity: sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0
'@segment/snippet@4.16.2':
resolution: {integrity: sha512-2fgsrt4U+vKv14ohOAsViCEzeZotaawF2Il7YUbmYVrhPn8Hq7xuGznHKRdZeoxScQ87X36xDX2Fzh5bAYRN7g==}
@@ -1644,18 +1699,21 @@ packages:
resolution: {integrity: sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==}
engines: {node: '>=10'}
'@swc/helpers@0.5.13':
resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==}
'@szmarczak/http-timer@5.0.1':
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
engines: {node: '>=14.16'}
'@tanstack/react-virtual@3.0.1':
resolution: {integrity: sha512-IFOFuRUTaiM/yibty9qQ9BfycQnYXIDHGP2+cU+0LrFFGNhVxCXSQnaY6wkX8uJVteFEBjUondX0Hmpp7TNcag==}
'@tanstack/react-virtual@3.10.8':
resolution: {integrity: sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
'@tanstack/virtual-core@3.0.0':
resolution: {integrity: sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==}
'@tanstack/virtual-core@3.10.8':
resolution: {integrity: sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==}
'@trysound/sax@0.2.0':
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
@@ -2205,9 +2263,6 @@ packages:
resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==}
engines: {node: 10.* || >= 12.*}
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
clone-deep@4.0.1:
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
engines: {node: '>=6'}
@@ -2847,6 +2902,10 @@ packages:
resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
engines: {node: '>=10'}
dotenv@16.4.5:
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
engines: {node: '>=12'}
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
@@ -5468,6 +5527,9 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
tabbable@6.2.0:
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
tapable@1.1.3:
resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==}
engines: {node: '>=6'}
@@ -7672,6 +7734,31 @@ snapshots:
- uglify-js
- webpack-cli
'@floating-ui/core@1.6.8':
dependencies:
'@floating-ui/utils': 0.2.8
'@floating-ui/dom@1.6.11':
dependencies:
'@floating-ui/core': 1.6.8
'@floating-ui/utils': 0.2.8
'@floating-ui/react-dom@2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@floating-ui/dom': 1.6.11
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
'@floating-ui/react@0.26.24(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@floating-ui/react-dom': 2.1.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@floating-ui/utils': 0.2.8
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
tabbable: 6.2.0
'@floating-ui/utils@0.2.8': {}
'@fortawesome/fontawesome-common-types@6.5.1': {}
'@fortawesome/fontawesome-svg-core@6.5.1':
@@ -7698,10 +7785,12 @@ snapshots:
dependencies:
'@hapi/hoek': 9.3.0
'@headlessui/react@1.7.18(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
'@headlessui/react@2.1.9(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@tanstack/react-virtual': 3.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
client-only: 0.0.1
'@floating-ui/react': 0.26.24(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@react-aria/focus': 3.18.3(react@18.2.0)
'@react-aria/interactions': 3.22.3(react@18.2.0)
'@tanstack/react-virtual': 3.10.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
@@ -7812,6 +7901,46 @@ snapshots:
'@polka/url@1.0.0-next.24': {}
'@react-aria/focus@3.18.3(react@18.2.0)':
dependencies:
'@react-aria/interactions': 3.22.3(react@18.2.0)
'@react-aria/utils': 3.25.3(react@18.2.0)
'@react-types/shared': 3.25.0(react@18.2.0)
'@swc/helpers': 0.5.13
clsx: 2.1.0
react: 18.2.0
'@react-aria/interactions@3.22.3(react@18.2.0)':
dependencies:
'@react-aria/ssr': 3.9.6(react@18.2.0)
'@react-aria/utils': 3.25.3(react@18.2.0)
'@react-types/shared': 3.25.0(react@18.2.0)
'@swc/helpers': 0.5.13
react: 18.2.0
'@react-aria/ssr@3.9.6(react@18.2.0)':
dependencies:
'@swc/helpers': 0.5.13
react: 18.2.0
'@react-aria/utils@3.25.3(react@18.2.0)':
dependencies:
'@react-aria/ssr': 3.9.6(react@18.2.0)
'@react-stately/utils': 3.10.4(react@18.2.0)
'@react-types/shared': 3.25.0(react@18.2.0)
'@swc/helpers': 0.5.13
clsx: 2.1.0
react: 18.2.0
'@react-stately/utils@3.10.4(react@18.2.0)':
dependencies:
'@swc/helpers': 0.5.13
react: 18.2.0
'@react-types/shared@3.25.0(react@18.2.0)':
dependencies:
react: 18.2.0
'@segment/snippet@4.16.2':
dependencies:
'@ndhoule/map': 2.0.1
@@ -7931,17 +8060,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@swc/helpers@0.5.13':
dependencies:
tslib: 2.6.2
'@szmarczak/http-timer@5.0.1':
dependencies:
defer-to-connect: 2.0.1
'@tanstack/react-virtual@3.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
'@tanstack/react-virtual@3.10.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
'@tanstack/virtual-core': 3.0.0
'@tanstack/virtual-core': 3.10.8
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
'@tanstack/virtual-core@3.0.0': {}
'@tanstack/virtual-core@3.10.8': {}
'@trysound/sax@0.2.0': {}
@@ -8590,8 +8723,6 @@ snapshots:
optionalDependencies:
'@colors/colors': 1.5.0
client-only@0.0.1: {}
clone-deep@4.0.1:
dependencies:
is-plain-object: 2.0.4
@@ -9299,6 +9430,8 @@ snapshots:
dependencies:
is-obj: 2.0.0
dotenv@16.4.5: {}
duplexer@0.1.2: {}
eastasianwidth@0.2.0: {}
@@ -12465,6 +12598,8 @@ snapshots:
csso: 5.0.5
picocolors: 1.0.0
tabbable@6.2.0: {}
tapable@1.1.3: {}
tapable@2.2.1: {}

View File

@@ -0,0 +1,47 @@
import { faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
Description,
Dialog,
DialogPanel,
DialogTitle,
} from "@headlessui/react";
import React from "react";
import styles from "./Modal.module.css";
export const Overlay = () => (
<div className={styles.modalOverlay} aria-hidden="true" />
);
const CloseButton = ({ onClose }) => {
return (
<button onClick={onClose} className={styles.modalCloseButton}>
<FontAwesomeIcon icon={faXmark} />
</button>
);
};
export const Modal = ({ title, isOpen, description, onClose, children }) => {
return (
<Dialog
open={isOpen}
onClose={onClose}
className={styles.modalPageContainer}
>
<Overlay />
<div className={styles.modalContainer}>
<DialogPanel className={styles.modalPanel}>
<div className={styles.modalHeader}>
<DialogTitle className={styles.modalTitle}>{title}
</DialogTitle>
<CloseButton onClose={onClose} />
</div>
<Description>{description}</Description>
{children}
</DialogPanel>
</div>
</Dialog>
);
};

View File

@@ -0,0 +1,59 @@
@keyframes fade-in-container {
from {
opacity: 0;
}
}
.modalPageContainer{
position:absolute;
z-index:1000;
}
.modalOverlay{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
background: var(--modal-overlay-background);
}
.modalHeader {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.modalCloseButton {
background: none;
border: none;
cursor: pointer;
margin-left: auto;
margin-right: 0;
}
.modalContainer {
z-index:1000;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
animation: fade-in-container 0.2s ease-out;
display: flex;
justify-content: center;
align-items: center;
}
.modalPanel {
max-height: 100%;
display: flex;
flex-direction: column;
background: var(--color-white);
padding: 20px;
border-radius: 5px;
font-size: 0.8em;
}
.modalTitle {
font-size: 16px;
line-height: 1.2em;
}

View File

@@ -0,0 +1,143 @@
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import cn from "classnames";
import React, { useState } from "react";
import styles from "./EmailModal.module.css";
import { Modal } from "../Modal/Modal";
const Form = ({ status, onSubmit }) => {
const [email, setEmail] = useState("");
const [emailError, setEmailError] = useState("");
const [showEmailError, setShowEmailError] = useState(false);
const emailValidation = (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (emailRegex.test(value)) {
setEmailError("");
} else {
setEmailError("Please enter a valid email address");
}
};
const handleOnChange = (e) => {
const emailValue = e.target.value;
setEmail(emailValue);
emailValidation(emailValue);
};
const handleBlur = () => {
if (email && emailError) {
setShowEmailError(true);
}
};
const handleFocus = () => {
setShowEmailError(false);
};
if (status === "success") {
return (
<div className={cn(styles.form__status, styles["form__status--success"])}>
<p> Request submitted successfully!</p>
<p> We will notify you when the ERD is ready</p>
</div>
);
}
if (status === "error") {
return (
<div className={cn(styles.form__status, styles["form__status--error"])}>
<p> Error submitting your request. Please try again later.</p>
</div>
);
}
return (
<form
className={styles.form}
onSubmit={(e) => {
e.preventDefault();
onSubmit(email);
}}
>
<div className={styles.form__inputContainer}>
<input
className={cn(styles.form__input, {
[styles["form__input--error"]]: showEmailError && emailError,
})}
type="email"
value={email}
autoComplete="email"
onChange={handleOnChange}
onBlur={handleBlur}
onFocus={handleFocus}
placeholder="Enter your email"
required
disabled={status === "loading"}
/>
{showEmailError && emailError && (
<p className={styles.form__input__errorMessage}>{emailError}</p>
)}
</div>
<button
type="submit"
className={styles.form__submitButton}
disabled={status === "loading" || Boolean(emailError) || !email}
>
{status === "loading" ? "Submitting..." : "Submit"}
</button>
</form>
);
};
export const EmailModal = ({ isOpen, onClose, sourceInfo }) => {
const [status, setStatus] = useState("");
const {
siteConfig: {
customFields: { requestErdApiUrl },
},
} = useDocusaurusContext();
if (!isOpen) return null;
const handleSubmit = async (email) => {
setStatus("loading");
try {
const response = await fetch(`${requestErdApiUrl}/api/request-erd`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
requester_email: email,
url: sourceInfo.url,
source_name: sourceInfo.name,
source_definition_id: sourceInfo.definitionId,
}),
});
if (!response.ok) {
const error = await response.text();
console.error("Error requesting ERD:", JSON.parse(error));
setStatus("error");
} else {
setStatus("success");
}
} catch (error) {
console.error("Error requesting ERD:", error);
setStatus("error");
}
};
return (
<Modal
isOpen={isOpen}
title="Request ERD"
description="We ask for your email so we can notify you when the ERD is ready."
onClose={() => {
setStatus("");
onClose();
}}
>
<Form onSubmit={handleSubmit} status={status} />
</Modal>
);
};

View File

@@ -0,0 +1,53 @@
.form {
display: flex;
width: 100%;
gap: 8px;
}
.form__inputContainer {
flex-grow: 1;
}
.form__input {
border: 1px solid var(--color-grey-400);
border-radius: 6px;
padding: 10px;
width: 100%;
}
.form__input--error {
border: 1px solid var(--color-red-400);
}
.form__input__errorMessage {
color: var(--color-red-400);
font-size: 0.8em;
margin-bottom: 0;
}
.form__submitButton {
background-color: var(--ifm-color-primary);
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
max-height: 38px;
}
.form__submitButton:disabled {
background-color: var(--ifm-color-primary-lightest);
cursor: not-allowed;
}
.form__status p {
margin: 0;
}
.form__status--success {
font-weight: 600;
}
.form__status--error {
color: var(--color-red-400);
}

View File

@@ -0,0 +1,63 @@
import { useLocation } from "@docusaurus/router";
import React, { useEffect, useState } from "react";
import { EmailModal } from "./EmailModal";
import styles from "./RequestERD.module.css";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const { getRegistryEntry } = require("../../remark/utils");
const { getFromPaths } = require("../../helpers/objects");
export const RequestERD = () => {
const location = useLocation();
const [hasERD, setHasERD] = useState(false);
const [source, setSource] = useState(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const isSourcePage = /\/sources\/[^/]+/.test(location.pathname);
useEffect(() => {
async function checkExistingERD() {
const entry = await getRegistryEntry({ path: location.pathname });
const erdUrl = getFromPaths(entry, "erdUrl_[oss|cloud]");
setHasERD(Boolean(erdUrl));
const name = getFromPaths(entry, "name_[oss|cloud]");
setSource({
name,
definitionId: entry.definitionId,
});
}
if (isSourcePage) {
checkExistingERD();
}
}, [location.pathname]);
const handleRequestERD = () => {
setIsModalOpen(true);
};
if (!isSourcePage || hasERD) {
return null;
}
return (
<>
<div className={styles.requestERD}>
<button className={styles.requestERDButton} onClick={handleRequestERD}>
<FontAwesomeIcon icon={faPlus} />
Request Entity-Relationship Diagram
</button>
</div>
<EmailModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
sourceInfo={{
url: location.pathname,
name: source?.name,
definitionId: source?.definitionId,
}}
/>
</>
);
};

View File

@@ -0,0 +1,26 @@
.requestERD {
margin-top: 1em;
font-size: 0.8em;
color: var(--ifm-toc-link-color);
}
.requestERDButton {
border-radius: 6px;
padding: 6px 12px;
font-size: 12px;
display: flex;
align-items: center;
gap: 8px;
width: fit-content;
color: var(--ifm-toc-link-color);
border: 1px solid var(--ifm-toc-link-color);
text-align: left;
background-color: transparent;
cursor: pointer;
}
.requestERDButton:hover {
color: var(--ifm-color-primary);
border: 1px solid var(--ifm-color-primary);
}

View File

@@ -35,6 +35,9 @@
--color-green-50: hsl(184, 67%, 92%);
--color-blue-30: hsl(240, 100%, 98%);
--color-dark-blue-700: hsl(236, 43%, 31%);
--color-red-400: hsl(0, 73%, 50%);
--modal-overlay-background: hsla(241, 51%, 20%, 50%);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
@@ -59,6 +62,9 @@ html[data-theme="dark"] {
--color-blue-30: hsl(252, 25%, 18%);
--color-dark-blue-700: hsl(240, 100%, 98%);
--color-white: hsl(0, 0%, 16%);
--color-red-400: hsl(0, 81%, 71%);
--modal-overlay-background: hsla(236, 11%, 42%, 70%);
}
.docusaurus-highlight-code-line {

View File

@@ -1,22 +1,54 @@
import React, { useState } from 'react';
import TOCItems from '@theme-original/TOCItems';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faThumbsDown, faThumbsUp } from '@fortawesome/free-regular-svg-icons';
import { faThumbsDown, faThumbsUp } from "@fortawesome/free-regular-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import TOCItems from "@theme-original/TOCItems";
import React, { useState } from "react";
import { RequestERD } from "../../components/RequestERD/RequestERD";
import styles from "./TOCItemsWrapper.module.css";
function showDocSurvey() {
const showSurvey = () => {
chmln.show("6525a7ef3f4f150011627c9f");
}
};
if (!window.chmln) {
// Initialize Chameleon if it's not loaded already
!function(d,w){var t="SaG54hxuMI4CDIZa2yBv4lX1NHVB0jQBNTORqyAN2p2tE4-1OtIxC-DS9ywbXXIr2TPyYr",c="chmln",i=d.createElement("script");if(w[c]||(w[c]={}),!w[c].root){w[c].accountToken=t,w[c].location=w.location.href.toString(),w[c].now=new Date,w[c].fastUrl='https://fast.chameleon.io/';var m="identify alias track clear set show on off custom help _data".split(" ");for(var s=0;s<m.length;s++){!function(){var t=w[c][m[s]+"_a"]=[];w[c][m[s]]=function(){t.push(arguments);};}();}i.src=w[c].fastUrl+"messo/"+t+"/messo.min.js",i.async=!0,d.head.appendChild(i);}}(document,window);
!(function (d, w) {
var t =
"SaG54hxuMI4CDIZa2yBv4lX1NHVB0jQBNTORqyAN2p2tE4-1OtIxC-DS9ywbXXIr2TPyYr",
c = "chmln",
i = d.createElement("script");
if ((w[c] || (w[c] = {}), !w[c].root)) {
(w[c].accountToken = t),
(w[c].location = w.location.href.toString()),
(w[c].now = new Date()),
(w[c].fastUrl = "https://fast.chameleon.io/");
var m =
"identify alias track clear set show on off custom help _data".split(
" "
);
for (var s = 0; s < m.length; s++) {
!(function () {
var t = (w[c][m[s] + "_a"] = []);
w[c][m[s]] = function () {
t.push(arguments);
};
})();
}
(i.src = w[c].fastUrl + "messo/" + t + "/messo.min.js"),
(i.async = !0),
d.head.appendChild(i);
}
})(document, window);
// As soon as it's loaded show the survey
window.chmln.on("load:chmln", showSurvey);
// Identify the user reusing the segment id if possible
window.chmln.identify(window.analytics?.user().id() ?? window.analytics?.user().anonymousId() ?? "chmln-no-segment-user", {});
window.chmln.identify(
window.analytics?.user().id() ??
window.analytics?.user().anonymousId() ??
"chmln-no-segment-user",
{}
);
} else {
showSurvey();
}
@@ -39,22 +71,34 @@ export default function TOCItemsWrapper(props) {
return (
<>
<TOCItems {...props} />
<RequestERD />
<div className={styles.pageRate}>
<div>Was this page helpful?</div>
{!voted ?
{!voted ? (
<div className={styles.buttonWrapper}>
<button className={styles.rateButton} onClick={() => onVote("up")}>
<FontAwesomeIcon icon={faThumbsUp} size="lg" className={styles.rateButton} />
<FontAwesomeIcon
icon={faThumbsUp}
size="lg"
className={styles.rateButton}
/>
Yes
</button>
<button className={styles.rateButton} onClick={() => onVote("down")}>
<FontAwesomeIcon icon={faThumbsDown} size="lg" className={styles.rateButton} />
<button
className={styles.rateButton}
onClick={() => onVote("down")}
>
<FontAwesomeIcon
icon={faThumbsDown}
size="lg"
className={styles.rateButton}
/>
No
</button>
</div>
:
) : (
<div className={styles.thanks}>Thank you!</div>
}
)}
</div>
</>
);