docs: add tailwindcss for styles, oidc authorize endpoint playground (#4707)

* variable parser

* rm plugin

* set fcn

* env

* EnvCode component

* cleanup env demo

* env

* rm remark plugin

* auth request context

* auth req component

* authorize endpoint construction

* rev react page

* fix endpoint

* styling

* query params with anchor

* desc

* tailwind coexistence

* fix styles

* add login_hint, organizationId scope

* auth request without prompt

* show login_hint

* sync displayed url with actual href

* fix fcn

* coloring

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* Update docs/src/components/authrequest.jsx

Co-authored-by: mffap <[email protected]>

* add plausible, header

* add pkce

* move

* adds pkce code challenge

* replace cboa

* reaname and move to required

* fall back to cboa due to webpack error

* trailing slash

* reorder org_id

* remove resourceowner

* texts

* update references

* buffer, fix some react dom components

* Apply suggestions from code review

Co-authored-by: Florian Forster <[email protected]>

* standard scopes

Co-authored-by: mffap <[email protected]>
Co-authored-by: Florian Forster <[email protected]>
This commit is contained in:
Max Peintner
2022-12-05 18:36:12 +01:00
committed by GitHub
co-authored by mffap Florian Forster
parent add232d1dd
commit 97fe041a86
32 changed files with 1654 additions and 459 deletions
+20 -22
View File
@@ -1,34 +1,32 @@
import React from 'react';
import React from "react";
import styles from '../css/apicard.module.css';
import styles from "../css/apicard.module.css";
export function ApiCard({ title, type, label, children}) {
let style = styles.apiauth;
export function ApiCard({ type, children }) {
let classes = "";
switch (type) {
case 'AUTH':
style = styles.apiauth;
case "AUTH":
classes = "bg-green-500/10 dark:bg-green-500/20";
break;
case 'MGMT':
style = styles.apimgmt;
case "MGMT":
classes = "bg-blue-500/10 dark:bg-blue-500/20";
break;
case 'ADMIN':
style = styles.apiadmin;
case "ADMIN":
classes = "bg-red-500/10 dark:bg-red-500/20";
break;
case 'SYSTEM':
style = styles.apisystem;
case "SYSTEM":
classes = "bg-yellow-500/10 dark:bg-yellow-500/20";
break;
case "ASSET":
classes = "bg-black/10 dark:bg-black/20";
break;
case 'ASSET':
style = styles.apiasset;
break;
}
return (
<div className={`${styles.apicard} ${style} `}>
{/* {title && <h2 className={styles.apicard.title}>{title}</h2>} */}
{/* <p className={styles.apicard.description}>
</p> */}
<div
className={`${styles.apicard} flex mb-4 flex-row p-4 rounded-lg ${classes} `}
>
{children}
</div>
)
);
}
+594
View File
@@ -0,0 +1,594 @@
import React, { Fragment, useContext, useEffect, useState } from "react";
import { AuthRequestContext } from "../utils/authrequest";
import { Listbox } from "@headlessui/react";
import { Transition } from "@headlessui/react";
import { ChevronUpDownIcon, CheckIcon } from "@heroicons/react/24/solid";
import clsx from "clsx";
import { Buffer } from "buffer";
export function SetAuthRequest() {
const {
instance: [instance, setInstance],
clientId: [clientId, setClientId],
redirectUri: [redirectUri, setRedirectUri],
responseType: [responseType, setResponseType],
scope: [scope, setScope],
prompt: [prompt, setPrompt],
authMethod: [authMethod, setAuthMethod],
codeVerifier: [codeVerifier, setCodeVerifier],
codeChallenge: [codeChallenge, setCodeChallenge],
loginHint: [loginHint, setLoginHint],
idTokenHint: [idTokenHint, setIdTokenHint],
organizationId: [organizationId, setOrganizationId],
} = useContext(AuthRequestContext);
const inputClasses = (error) =>
clsx({
"w-full sm:text-sm h-10 mb-2px rounded-md p-2 bg-input-light-background dark:bg-input-dark-background transition-colors duration-300": true,
"border border-solid border-input-light-border dark:border-input-dark-border hover:border-black hover:dark:border-white focus:border-primary-light-500 focus:dark:border-primary-dark-500": true,
"focus:outline-none focus:ring-0 text-base text-black dark:text-white placeholder:italic placeholder-gray-700 dark:placeholder-gray-700": true,
"border border-warn-light-500 dark:border-warn-dark-500 hover:border-warn-light-500 hover:dark:border-warn-dark-500 focus:border-warn-light-500 focus:dark:border-warn-dark-500":
error,
});
const labelClasses = "text-sm";
const hintClasses = "mt-1 text-xs text-black/50 dark:text-white/50";
const allResponseTypes = ["code", "id_token", "id_token token"];
const allPrompts = ["", "login", "select_account", "create"];
const allAuthMethods = ["(none) PKCE", "Client Secret Basic"];
const CodeSnipped = ({ cname, children }) => {
return <span className={cname}>{children}</span>;
};
const allScopes = [
"openid",
"email",
"profile",
"address",
"offline_access",
"urn:zitadel:iam:org:project:id:zitadel:aud",
"urn:zitadel:iam:user:metadata",
`urn:zitadel:iam:org:id:${
organizationId ? organizationId : "[organizationId]"
}`,
];
const [scopeState, setScopeState] = useState(
[true, true, true, false, false, false, false, false]
// new Array(allScopes.length).fill(false)
);
function toggleScope(position, forceChecked = false) {
const updatedCheckedState = scopeState.map((item, index) =>
index === position ? !item : item
);
if (forceChecked) {
updatedCheckedState[position] = true;
}
setScopeState(updatedCheckedState);
setScope(
updatedCheckedState
.map((checked, i) => (checked ? allScopes[i] : ""))
.filter((s) => !!s)
.join(" ")
);
}
// Encoding functions for code_challenge
async function string_to_sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
// return ArrayBuffer
return hashBuffer;
}
async function encodeCodeChallenge(codeChallenge) {
let arrayBuffer = await string_to_sha256(codeChallenge);
let buffer = Buffer.from(arrayBuffer);
let base64 = buffer.toString("base64");
let base54url = base64_to_base64url(base64);
return base54url;
}
var base64_to_base64url = function (input) {
input = input.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
return input;
};
useEffect(async () => {
setCodeChallenge(await encodeCodeChallenge(codeVerifier));
}, [codeVerifier]);
useEffect(() => {
const newScopeState = allScopes.map((s) => scope.includes(s));
if (scopeState !== newScopeState) {
setScopeState(newScopeState);
}
}, [scope]);
return (
<div className="bg-white/5 rounded-md p-6 shadow">
<h5 className="text-lg mt-0 mb-4 font-semibold">Your Domain</h5>
<div className="flex flex-col">
<label className={`${labelClasses} text-yellow-500`}>
Instance Domain
</label>
<input
className={inputClasses(false)}
id="instance"
value={instance}
onChange={(event) => {
const value = event.target.value;
setInstance(value);
}}
/>
<span className={hintClasses}>
The domain of your zitadel instance.
</span>
</div>
<h5 className="text-lg mt-6 mb-2 font-semibold">Required Parameters</h5>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="flex flex-col">
<label className={`${labelClasses} text-green-500`}>Client ID</label>
<input
className={inputClasses(false)}
id="client_id"
value={clientId}
onChange={(event) => {
const value = event.target.value;
setClientId(value);
}}
/>
<span className={hintClasses}>
This is the resource id of an application. It's the application
where you want your users to login.
</span>
</div>
<div className="flex flex-col">
<label className={`${labelClasses} text-blue-500`}>
Redirect URI
</label>
<input
className={inputClasses(false)}
id="redirect_uri"
value={redirectUri}
onChange={(event) => {
const value = event.target.value;
setRedirectUri(value);
}}
/>
<span className={hintClasses}>
Must be one of the pre-configured redirect uris for your
application.
</span>
</div>
<div className="flex flex-col">
<label className={`${labelClasses} text-orange-500`}>
ResponseType
</label>
<Listbox value={responseType} onChange={setResponseType}>
<div className="relative">
<Listbox.Button className="transition-colors duration-300 text-black dark:text-white h-10 relative w-full cursor-default rounded-md bg-white dark:bg-input-dark-background py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm border border-solid border-input-light-border dark:border-input-dark-border hover:border-black hover:dark:border-white focus:border-primary-light-500 focus:dark:border-primary-dark-500">
<span className="block truncate">{responseType}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</span>
</Listbox.Button>
<span className={`${hintClasses} flex`}>
Determines whether a code, id_token token or just id_token will
be returned. Most use cases will need code.
</span>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="pl-0 list-none z-10 top-10 absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-background-dark-300 text-black dark:text-white py-1 text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{allResponseTypes.map((type, typeIdx) => (
<Listbox.Option
key={typeIdx}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-10 pr-4 ${
active ? "bg-black/20 dark:bg-white/20" : ""
}`
}
value={type}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected ? "font-medium" : "font-normal"
}`}
>
{type}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-orange-500 dark:text-orange-400">
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-6">
<div className="flex flex-col">
<label className={`${labelClasses} text-teal-600`}>
Authentication method
</label>
<Listbox value={authMethod} onChange={setAuthMethod}>
<div className="relative">
<Listbox.Button className="transition-colors duration-300 text-black dark:text-white h-10 relative w-full cursor-default rounded-md bg-white dark:bg-input-dark-background py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm border border-solid border-input-light-border dark:border-input-dark-border hover:border-black hover:dark:border-white focus:border-primary-light-500 focus:dark:border-primary-dark-500">
<span className="block truncate">{authMethod}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</span>
</Listbox.Button>
<span className={`${hintClasses} flex`}>
Authentication method
</span>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="pl-0 list-none z-10 absolute top-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-background-dark-300 text-black dark:text-white py-1 text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{allAuthMethods.map((type, typeIdx) => (
<Listbox.Option
key={typeIdx}
className={({ active }) =>
`h-10 relative cursor-default select-none py-2 pl-10 pr-4 ${
active ? "bg-black/20 dark:bg-white/20" : ""
}`
}
value={type}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected ? "font-medium" : "font-normal"
}`}
>
{type}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-500 dark:text-cyan-400">
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
</div>
{authMethod === "(none) PKCE" && (
<div className="flex flex-col">
<label className={`${labelClasses} text-teal-600`}>
Code Verifier
</label>
<input
className={inputClasses(false)}
id="code_verifier"
value={codeVerifier}
onChange={(event) => {
const value = event.target.value;
setCodeVerifier(value);
}}
/>
<span className={hintClasses}>
<span className="text-teal-600">Authentication method</span> PKCE
requires a random string used to generate a{" "}
<code>code_challenge</code>
</span>
</div>
)}
</div>
<h5 className="text-lg mt-6 mb-2 font-semibold">Additional Parameters</h5>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div>
<div className="flex flex-col">
<label className={`${labelClasses} text-cyan-500`}>Prompt</label>
<Listbox value={prompt} onChange={setPrompt}>
<div className="relative">
<Listbox.Button className="transition-colors duration-300 text-black dark:text-white h-10 relative w-full cursor-default rounded-md bg-white dark:bg-input-dark-background py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm border border-solid border-input-light-border dark:border-input-dark-border hover:border-black hover:dark:border-white focus:border-primary-light-500 focus:dark:border-primary-dark-500">
<span className="block truncate">{prompt}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</span>
</Listbox.Button>
<span className={`${hintClasses} flex`}>
Define how the user should be prompted on login and register.
</span>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="pl-0 list-none z-10 absolute top-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white dark:bg-background-dark-300 text-black dark:text-white py-1 text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{allPrompts.map((type, typeIdx) => (
<Listbox.Option
key={typeIdx}
className={({ active }) =>
`h-10 relative cursor-default select-none py-2 pl-10 pr-4 ${
active ? "bg-black/20 dark:bg-white/20" : ""
}`
}
value={type}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected ? "font-medium" : "font-normal"
}`}
>
{type}
</span>
{selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-500 dark:text-cyan-400">
<CheckIcon
className="h-5 w-5"
aria-hidden="true"
/>
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
</div>
</div>
{prompt === "select_account" && (
<div className="flex flex-col">
<label className={`${labelClasses} text-rose-500`}>
Login hint
</label>
<input
className={inputClasses(false)}
id="login_hint"
value={loginHint}
onChange={(event) => {
const value = event.target.value;
setLoginHint(value);
}}
/>
<span className={hintClasses}>
This in combination with a{" "}
<span className="text-black dark:text-white">select_account</span>{" "}
<span className="text-cyan-500">prompt</span> the login will
preselect a user.
</span>
</div>
)}
{/* <div className="flex flex-col">
<label className={`${labelClasses} text-blue-500`}>
ID Token hint
</label>
<input
className={inputClasses(false)}
id="id_token_hint"
value={idTokenHint}
onChange={(event) => {
const value = event.target.value;
setIdTokenHint(value);
}}
/>
<span className={hintClasses}>
This in combination with a{" "}
<span className="text-black dark:text-white">select_account</span>{" "}
<span className="text-emerald-500">prompt</span> the login will
preselect a user.
</span>
</div> */}
</div>
<h5 className="text-lg mt-6 mb-2 font-semibold">Scopes</h5>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-4">
<div className="flex flex-col">
<label className={`${labelClasses} text-purple-500`}>
Organization ID
</label>
<input
className={inputClasses(false)}
id="organization_id"
value={organizationId}
onChange={(event) => {
const value = event.target.value;
setOrganizationId(value);
allScopes[7] = `urn:zitadel:iam:org:id:${
value ? value : "[organizationId]"
}`;
toggleScope(8, true);
setScope(
scopeState
.map((checked, i) => (checked ? allScopes[i] : ""))
.filter((s) => !!s)
.join(" ")
);
}}
/>
<span className={hintClasses}>
Enforce organization policies and user membership by requesting the{" "}
<span className="text-purple-500">scope</span>{" "}
<code>urn:zitadel:iam:org:id:{organizationId}</code>
</span>
</div>
</div>
<div className="py-4">
<p className="text-sm mt-0 mb-0 text-purple-500">Scopes</p>
<span className={`${hintClasses} flex mb-2`}>
Request additional information about the user with scopes. The claims
will be returned on the userinfo_endpoint or in the token (when
configured).
</span>
{allScopes.map((scope, scopeIndex) => {
return (
<div key={`scope-${scope}`} className="flex flex-row items-center">
<input
type="checkbox"
id={`scope_${scope}`}
name="scopes"
value={`${scope}`}
checked={scopeState[scopeIndex]}
onChange={() => {
toggleScope(scopeIndex);
}}
/>
<label className="ml-4" htmlFor={`scope_${scope}`}>
{scope}{" "}
{scopeIndex === 8 && scopeState[8] && !organizationId ? (
<strong className="text-red-500">
Organization ID missing!
</strong>
) : null}
</label>
</div>
);
})}
</div>
{/* <h5>Optional Parameters</h5>
<div className={styles.grid}>
<div className={styles.inputwrapper}>
<label className={styles.label}>Id Token Hint</label>
<input
className={styles.input}
id="id_token_hint"
value={idTokenHint}
onChange={(event) => {
const value = event.target.value;
setIdTokenHint(value);
}}
/>
</div>
</div> */}
<h5 className="text-lg mt-6 mb-2 font-semibold">
Your authorization request
</h5>
<div className="rounded-md bg-gray-700 shadow dark:bg-black/10 p-2 flex flex-col items-center">
<code className="text-sm w-full mb-4 bg-transparent border-none">
<span className="text-yellow-500">
{instance.endsWith("/") ? instance : instance + "/"}
</span>
<span className="text-white">oauth/v2/authorize?</span>
<CodeSnipped cname="text-green-500">{`client_id=${encodeURIComponent(
clientId
)}`}</CodeSnipped>
<CodeSnipped cname="text-blue-500">{`&redirect_uri=${encodeURIComponent(
redirectUri
)}`}</CodeSnipped>
<CodeSnipped cname="text-orange-500">
{`&response_type=${encodeURIComponent(responseType)}`}
</CodeSnipped>
<CodeSnipped cname="text-purple-500">{`&scope=${encodeURIComponent(
scope
)}`}</CodeSnipped>
{prompt && (
<CodeSnipped cname="text-cyan-500">{`&prompt=${encodeURIComponent(
prompt
)}`}</CodeSnipped>
)}
{loginHint && prompt === "select_account" && (
<CodeSnipped cname="text-rose-500">{`&login_hint=${encodeURIComponent(
loginHint
)}`}</CodeSnipped>
)}
{authMethod === "(none) PKCE" && (
<CodeSnipped cname="text-teal-600">{`&code_challenge=${encodeURIComponent(
codeChallenge
)}&code_challenge_method=S256`}</CodeSnipped>
)}
</code>
<a
onClick={() => {
window.plausible("OIDC Playground", {
props: { method: "Try it out", pageloc: "Authorize" },
});
}}
target="_blank"
className="mt-2 flex flex-row items-center py-2 px-4 text-white bg-green-500 dark:bg-green-600 hover:dark:bg-green-500 hover:text-white rounded-md hover:no-underline font-semibold text-sm"
href={`${
instance.endsWith("/") ? instance : instance + "/"
}oauth/v2/authorize?client_id=${encodeURIComponent(
clientId
)}&redirect_uri=${encodeURIComponent(
redirectUri
)}&response_type=${encodeURIComponent(
responseType
)}&scope=${encodeURIComponent(scope)}${
prompt ? `&prompt=${encodeURIComponent(prompt)}` : ""
}${
loginHint && prompt === "select_account"
? `&login_hint=${encodeURIComponent(loginHint)}`
: ""
}${
authMethod === "(none) PKCE"
? `&code_challenge=${encodeURIComponent(
codeChallenge
)}&code_challenge_method=S256`
: ""
}`}
>
<span>Try it out</span>
<i className="text-white text-md ml-2 las la-external-link-alt"></i>
</a>
</div>
</div>
);
}
+6 -10
View File
@@ -1,11 +1,7 @@
import React from 'react';
import React from "react";
import styles from '../css/column.module.css';
export default function Column({children}) {
return (
<div className={styles.column}>
{children}
</div>
)
}
export default function Column({ children }) {
return (
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">{children}</div>
);
}
+133
View File
@@ -0,0 +1,133 @@
import React, { useContext, useEffect } from "react";
import { EnvironmentContext } from "../utils/environment";
import styles from "../css/environment.module.css";
import Interpolate from "@docusaurus/Interpolate";
import CodeBlock from "@theme/CodeBlock";
export function SetEnvironment() {
const {
instance: [instance, setInstance],
clientId: [clientId, setClientId],
} = useContext(EnvironmentContext);
useEffect(() => {
const params = new URLSearchParams(window.location.search); // id=123
const clientId = params.get("clientId");
const instance = params.get("instance");
const localClientId = localStorage.getItem("clientId");
const localInstance = localStorage.getItem("instance");
setClientId(clientId ?? localClientId ?? "");
setInstance(instance ?? localInstance ?? "");
}, []);
function setAndSaveInstance(value) {
if (instance !== value) {
localStorage.setItem("instance", value);
setInstance(value);
}
}
function setAndSaveClientId(value) {
if (clientId !== value) {
localStorage.setItem("clientId", value);
setClientId(value);
}
}
return (
<div>
<div className={styles.inputwrapper}>
<label className={styles.label}>Your instance domain</label>
<input
className={styles.input}
id="instance"
value={instance}
onChange={(event) => {
const value = event.target.value;
if (value) {
setAndSaveInstance(value);
} else {
localStorage.removeItem("instance");
}
}}
/>
</div>
<br />
<div className={styles.inputwrapper}>
<label className={styles.label}>Client ID</label>
<input
className={styles.input}
id="clientid"
value={clientId}
onChange={(event) => {
const value = event.target.value;
if (value) {
setAndSaveClientId(value);
} else {
localStorage.removeItem("clientId");
}
}}
/>
</div>
</div>
);
}
export function Env({ name }) {
const env = useContext(EnvironmentContext);
const variable = env[name];
return <div>{variable}</div>;
}
export function EnvInterpolate({ children }) {
const {
instance: [instance],
clientId: [clientId],
} = useContext(EnvironmentContext);
return (
<Interpolate
values={{
clientId,
instance,
}}
>
{children}
</Interpolate>
);
}
export function EnvCode({
language,
title,
code,
showLineNumbers = false,
children,
}) {
const {
instance: [instance],
clientId: [clientId],
} = useContext(EnvironmentContext);
return (
<CodeBlock
language={language}
title={title}
showLineNumbers={showLineNumbers}
>
<Interpolate
values={{
clientId,
instance,
}}
>
{children}
</Interpolate>
</CodeBlock>
);
}
+156 -88
View File
@@ -1,113 +1,181 @@
import React from 'react';
import React from "react";
import styles from '../css/list.module.css';
import styles from "../css/list.module.css";
export const ICONTYPE = {
START: <div className="rounded rounded-start">
<i className={`las la-play-circle`}></i>
</div>,
TASKS: <div className="rounded rounded-start">
<i className={`las la-tasks`}></i>
</div>,
ARCHITECTURE: <div className="rounded rounded-architecture">
<i className={`las la-sitemap`}></i>
</div>,
INSTANCE: <div className="rounded rounded-instance">
<i className={`las la-industry`}></i>
</div>,
LOGIN: <div className="rounded rounded-login">
<i className={`las la-sign-in-alt`}></i>
</div>,
PRIVATELABELING: <div className="rounded rounded-privatelabel">
<i className={`las la-swatchbook`}></i>
</div>,
TEXTS: <div className="rounded rounded-texts">
<i className={`las la-paragraph`}></i>
</div>,
POLICY: <div className="rounded rounded-policy">
<i className={`las la-file-contract`}></i>
</div>,
SERVICE: <div className="rounded rounded-service">
<i className={`las la-concierge-bell`}></i>
</div>,
STORAGE: <div className="rounded rounded-storage">
<i className={`las la-database`}></i>
</div>,
FOLDER: <div className="rounded rounded-storage">
<i className={`las la-folder`}></i>
</div>,
FILE: <div className="rounded rounded-storage">
<i className={`las la-file-alt`}></i>
</div>,
SYSTEM: <div className="rounded rounded-system">
<i className={`las la-server`}></i>
</div>,
APIS: <div className="rounded rounded-apis">
<i className={`las la-code`}></i>
</div>,
HELP: <div className="rounded rounded-help">
<i className={`las la-question`}></i>
</div>,
HELP_REGISTER: <div className="rounded rounded-login">
<i className={`las la-plus-circle`}></i>
</div>,
HELP_LOGIN: <div className="rounded rounded-login">
<i className={`las la-sign-in-alt`}></i>
</div>,
HELP_PASSWORDLESS: <div className="rounded rounded-login">
<i className={`las la-fingerprint`}></i>
</div>,
HELP_PASSWORD: <div className="rounded rounded-password">
<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%" viewBox="0 0 24 24" fit="" preserveAspectRatio="xMidYMid meet" focusable="false">
<path d="M17,7H22V17H17V19A1,1 0 0,0 18,20H20V22H17.5C16.95,22 16,21.55 16,21C16,21.55 15.05,22 14.5,22H12V20H14A1,1 0 0,0 15,19V5A1,1 0 0,0 14,4H12V2H14.5C15.05,2 16,2.45 16,3C16,2.45 16.95,2 17.5,2H20V4H18A1,1 0 0,0 17,5V7M2,7H13V9H4V15H13V17H2V7M20,15V9H17V15H20M8.5,12A1.5,1.5 0 0,0 7,10.5A1.5,1.5 0 0,0 5.5,12A1.5,1.5 0 0,0 7,13.5A1.5,1.5 0 0,0 8.5,12M13,10.89C12.39,10.33 11.44,10.38 10.88,11C10.32,11.6 10.37,12.55 11,13.11C11.55,13.63 12.43,13.63 13,13.11V10.89Z"></path>
</svg>
</div>,
HELP_FACTORS: <div className="rounded rounded-login">
<i className={`las la-fingerprint`}></i>
</div>,
HELP_PHONE: <div className="rounded rounded-phone">
<i className={`las la-phone`}></i>
</div>,
HELP_EMAIL: <div className="rounded rounded-email">
<i className={`las la-at`}></i>
</div>,
HELP_SOCIAL: <div className="rounded rounded-login">
<i className={`las la-share-alt`}></i>
</div>,
START: (
<div className="custom-rounded custom-rounded-start">
<i className={`las la-play-circle`}></i>
</div>
),
TASKS: (
<div className="custom-rounded custom-rounded-start">
<i className={`las la-tasks`}></i>
</div>
),
ARCHITECTURE: (
<div className="custom-rounded custom-rounded-architecture">
<i className={`las la-sitemap`}></i>
</div>
),
INSTANCE: (
<div className="custom-rounded custom-rounded-instance">
<i className={`las la-industry`}></i>
</div>
),
LOGIN: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-sign-in-alt`}></i>
</div>
),
PRIVATELABELING: (
<div className="custom-rounded custom-rounded-privatelabel">
<i className={`las la-swatchbook`}></i>
</div>
),
TEXTS: (
<div className="custom-rounded custom-rounded-texts">
<i className={`las la-paragraph`}></i>
</div>
),
POLICY: (
<div className="custom-rounded custom-rounded-policy">
<i className={`las la-file-contract`}></i>
</div>
),
SERVICE: (
<div className="custom-rounded custom-rounded-service">
<i className={`las la-concierge-bell`}></i>
</div>
),
STORAGE: (
<div className="custom-rounded custom-rounded-storage">
<i className={`las la-database`}></i>
</div>
),
FOLDER: (
<div className="custom-rounded custom-rounded-storage">
<i className={`las la-folder`}></i>
</div>
),
FILE: (
<div className="custom-rounded custom-rounded-storage">
<i className={`las la-file-alt`}></i>
</div>
),
SYSTEM: (
<div className="custom-rounded custom-rounded-system">
<i className={`las la-server`}></i>
</div>
),
APIS: (
<div className="custom-rounded custom-rounded-apis">
<i className={`las la-code`}></i>
</div>
),
HELP: (
<div className="custom-rounded custom-rounded-help">
<i className={`las la-question`}></i>
</div>
),
HELP_REGISTER: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-plus-circle`}></i>
</div>
),
HELP_LOGIN: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-sign-in-alt`}></i>
</div>
),
HELP_PASSWORDLESS: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-fingerprint`}></i>
</div>
),
HELP_PASSWORD: (
<div className="custom-rounded custom-rounded-password">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
version="1.1"
width="100%"
height="100%"
viewBox="0 0 24 24"
fit=""
preserveAspectRatio="xMidYMid meet"
focusable="false"
>
<path d="M17,7H22V17H17V19A1,1 0 0,0 18,20H20V22H17.5C16.95,22 16,21.55 16,21C16,21.55 15.05,22 14.5,22H12V20H14A1,1 0 0,0 15,19V5A1,1 0 0,0 14,4H12V2H14.5C15.05,2 16,2.45 16,3C16,2.45 16.95,2 17.5,2H20V4H18A1,1 0 0,0 17,5V7M2,7H13V9H4V15H13V17H2V7M20,15V9H17V15H20M8.5,12A1.5,1.5 0 0,0 7,10.5A1.5,1.5 0 0,0 5.5,12A1.5,1.5 0 0,0 7,13.5A1.5,1.5 0 0,0 8.5,12M13,10.89C12.39,10.33 11.44,10.38 10.88,11C10.32,11.6 10.37,12.55 11,13.11C11.55,13.63 12.43,13.63 13,13.11V10.89Z"></path>
</svg>
</div>
),
HELP_FACTORS: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-fingerprint`}></i>
</div>
),
HELP_PHONE: (
<div className="custom-rounded custom-rounded-phone">
<i className={`las la-phone`}></i>
</div>
),
HELP_EMAIL: (
<div className="custom-rounded custom-rounded-email">
<i className={`las la-at`}></i>
</div>
),
HELP_SOCIAL: (
<div className="custom-rounded custom-rounded-login">
<i className={`las la-share-alt`}></i>
</div>
),
};
export function ListElement({ link, iconClasses,roundClasses, label, type, title, description}) {
export function ListElement({
link,
iconClasses,
roundClasses,
label,
type,
title,
description,
}) {
return (
<a className={styles.listelement} href={link}>
{type ? type :
iconClasses && <div className={roundClasses}>
{ label ? <span className={styles.listlabel}>{label}</span>: <i className={`${iconClasses}`}></i> }
</div>
}
{type
? type
: iconClasses && (
<div className={roundClasses}>
{label ? (
<span className={styles.listlabel}>{label}</span>
) : (
<i className={`${iconClasses}`}></i>
)}
</div>
)}
<div>
<h3>{title}</h3>
<p className={styles.listelement.description}>{description}</p>
</div>
</a>
)
);
}
export function ListWrapper({children, title, columns}) {
export function ListWrapper({ children, title, columns }) {
return (
<div className={styles.listWrapper}>
{title && <span className={styles.listWrapperTitle}>{title}</span>}
{children}
</div>
)
);
}
export function HomeListWrapper({children, image}) {
export function HomeListWrapper({ children, image }) {
return (
<div className={styles.homerow}>
{image}
<div className={styles.homecontent}>
{children}
</div>
<div className={styles.homecontent}>{children}</div>
</div>
)
}
);
}