feat: add Icons plugin

* Change existing icons to React wrapper components

* Add `icons` plugin to expose Icon components to plugin system

* Create components that re-export Lock and Unlock components so they can be changed separately in Authorise top button and Authorise operation summary button

* Add new Lock and Unlock icons to `auth` plugin

---------

Co-authored-by: Vladimír Gorej <vladimir.gorej@smartbear.com>
This commit is contained in:
Damian Polewski
2023-07-20 14:51:17 +02:00
committed by GitHub
parent be9f94490b
commit f3ea2a251d
24 changed files with 386 additions and 36 deletions

View File

@@ -0,0 +1,17 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const LockAuthOperation = ({ getComponent, ...props }) => {
const LockIcon = getComponent("LockIcon")
return <LockIcon {...props} />
}
LockAuthOperation.propTypes = {
getComponent: PropTypes.func.isRequired
}
export default LockAuthOperation

View File

@@ -0,0 +1,17 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const LockAuth = ({ getComponent, ...props }) => {
const LockIcon = getComponent("LockIcon")
return <LockIcon {...props} />
}
LockAuth.propTypes = {
getComponent: PropTypes.func.isRequired
}
export default LockAuth

View File

@@ -0,0 +1,17 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const UnlockAuthOperation = ({ getComponent, ...props }) => {
const UnlockIcon = getComponent("UnlockIcon")
return <UnlockIcon {...props} />
}
UnlockAuthOperation.propTypes = {
getComponent: PropTypes.func.isRequired
}
export default UnlockAuthOperation

View File

@@ -0,0 +1,17 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const UnlockAuth = ({ getComponent, ...props }) => {
const UnlockIcon = getComponent("UnlockIcon")
return <UnlockIcon {...props} />
}
UnlockAuth.propTypes = {
getComponent: PropTypes.func.isRequired
}
export default UnlockAuth

View File

@@ -5,6 +5,11 @@ import { execute as wrappedExecuteAction } from "./spec-extensions/wrap-actions"
import { loaded as wrappedLoadedAction } from "./configs-extensions/wrap-actions"
import { authorize as wrappedAuthorizeAction, logout as wrappedLogoutAction } from "./wrap-actions"
import LockAuthIcon from "./components/lock-auth"
import UnlockAuthIcon from "./components/unlock-auth"
import LockAuthOperationIcon from "./components/lock-auth-operation"
import UnlockAuthOperationIcon from "./components/unlock-auth-operation"
export default function() {
return {
afterLoad(system) {
@@ -13,6 +18,12 @@ export default function() {
this.rootInjects.preauthorizeApiKey = preauthorizeApiKey.bind(null, system)
this.rootInjects.preauthorizeBasic = preauthorizeBasic.bind(null, system)
},
components: {
LockAuthIcon: LockAuthIcon,
UnlockAuthIcon: UnlockAuthIcon,
LockAuthOperationIcon: LockAuthOperationIcon,
UnlockAuthOperationIcon: UnlockAuthOperationIcon,
},
statePlugins: {
auth: {
reducers,

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const ArrowDown = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
</svg>
)
ArrowDown.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
ArrowDown.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default ArrowDown

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const ArrowUp = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M 17.418 14.908 C 17.69 15.176 18.127 15.176 18.397 14.908 C 18.667 14.64 18.668 14.207 18.397 13.939 L 10.489 6.109 C 10.219 5.841 9.782 5.841 9.51 6.109 L 1.602 13.939 C 1.332 14.207 1.332 14.64 1.602 14.908 C 1.873 15.176 2.311 15.176 2.581 14.908 L 10 7.767 L 17.418 14.908 Z"/>
</svg>
)
ArrowUp.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
ArrowUp.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default ArrowUp

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const Arrow = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
</svg>
)
Arrow.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
Arrow.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default Arrow

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const Close = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" />
</svg>
)
Close.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
Close.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default Close

View File

@@ -0,0 +1,38 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const Copy = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 15 16"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<g transform='translate(2, -1)'>
<path
fill='#ffffff'
fillRule='evenodd'
d='M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z'></path>
</g>
</svg>
)
Copy.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
Copy.defaultProps = {
className: null,
width: 15,
height: 16,
}
export default Copy

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const Lock = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" />
</svg>
)
Lock.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
Lock.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default Lock

View File

@@ -0,0 +1,33 @@
/**
* @prettier
*/
import React from "react"
import PropTypes from "prop-types"
const Unlock = ({ className, width, height }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
className={className}
width={width}
height={height}
aria-hidden="true"
focusable="false"
>
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</svg>
)
Unlock.propTypes = {
className: PropTypes.string,
width: PropTypes.string,
height: PropTypes.string,
}
Unlock.defaultProps = {
className: null,
width: 20,
height: 20,
}
export default Unlock

View File

@@ -0,0 +1,24 @@
/**
* @prettier
*/
import ArrowUpIcon from "./components/arrow-up"
import ArrowDownIcon from "./components/arrow-down"
import ArrowIcon from "./components/arrow"
import CloseIcon from "./components/close"
import CopyIcon from "./components/copy"
import LockIcon from "./components/lock"
import UnlockIcon from "./components/unlock"
const IconsPlugin = () => ({
components: {
ArrowUpIcon,
ArrowDownIcon,
ArrowIcon,
CloseIcon,
CopyIcon,
LockIcon,
UnlockIcon,
}
})
export default IconsPlugin

View File

@@ -21,6 +21,8 @@ const Models = ({
const isOpen = layoutSelectors.isShown(schemasPath, isOpenDefault)
const Collapse = getComponent("Collapse")
const JSONSchema202012 = getComponent("JSONSchema202012")
const ArrowUpIcon = getComponent("ArrowUpIcon")
const ArrowDownIcon = getComponent("ArrowDownIcon")
/**
* Effects.
@@ -80,9 +82,7 @@ const Models = ({
onClick={handleModelsExpand}
>
<span>Schemas</span>
<svg width="20" height="20" aria-hidden="true" focusable="false">
<use xlinkHref={isOpen ? "#large-arrow-up" : "#large-arrow-down"} />
</svg>
{isOpen ? <ArrowUpIcon /> : <ArrowDownIcon />}
</button>
</h4>
<Collapse isOpened={isOpen}>

View File

@@ -35,11 +35,14 @@ const activeStyle = {
borderBottom: "none"
}
const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs }) => {
const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs, getComponent }) => {
const config = isFunction(getConfigs) ? getConfigs() : null
const canSyntaxHighlight = get(config, "syntaxHighlight") !== false && get(config, "syntaxHighlight.activated", true)
const rootRef = useRef(null)
const ArrowIcon = getComponent("ArrowUpIcon")
const ArrowDownIcon = getComponent("ArrowDownIcon")
const [activeLanguage, setActiveLanguage] = useState(requestSnippetsSelectors.getSnippetGenerators()?.keySeq().first())
const [isExpanded, setIsExpanded] = useState(requestSnippetsSelectors?.getDefaultExpanded())
useEffect(() => {
@@ -119,9 +122,7 @@ const RequestSnippets = ({ request, requestSnippetsSelectors, getConfigs }) => {
style={{ border: "none", background: "none" }}
title={isExpanded ? "Collapse operation" : "Expand operation"}
>
<svg className="arrow" width="10" height="10">
<use href={isExpanded ? "#large-arrow-down" : "#large-arrow"} xlinkHref={isExpanded ? "#large-arrow-down" : "#large-arrow"} />
</svg>
{isExpanded ? <ArrowDownIcon className="arrow" width="10" height="10" /> : <ArrowIcon className="arrow" width="10" height="10" />}
</button>
</div>
{
@@ -153,6 +154,7 @@ RequestSnippets.propTypes = {
request: PropTypes.object.isRequired,
requestSnippetsSelectors: PropTypes.object.isRequired,
getConfigs: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
requestSnippetsActions: PropTypes.object,
}