mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 23:12:08 -03:30
Bump react scripts to 5.0
Bump react scripts to 5.0 See: https://github.com/ansible/awx/issues/11543 Bump eslint Bump eslint and related plugins Add @babe/core Add @babe/core remove babel/core. Rename .eslintrc to .eslintrc.json Rename .eslintrc to .eslintrc.json Add extra plugin Move babe-plugin-macro as dev dependencies Move babe-plugin-macro as dev dependencies Add preset-react Add preset-react Fixing lint errors Fixing lint errors Run eslint --fix Run eslint --fix Turn no-restricted-exports off Turn no-restricted-exports off Revert "Run eslint --fix" This reverts commit e760885b6c199f2ca18091088cb79bfa77c1d3ed. Run --fix Run --fix Fix lint errors Also bump specificity of Select CSS border component to avoid bug of missing borders. Also update API tests related to lincenses.
This commit is contained in:
parent
54cbf13219
commit
9703fb06fc
0
awx/ui/.babel.rc
Normal file
0
awx/ui/.babel.rc
Normal file
@ -7,4 +7,5 @@ build
|
||||
node_modules
|
||||
dist
|
||||
images
|
||||
instrumented
|
||||
instrumented
|
||||
*test*.js
|
||||
|
||||
@ -1,14 +1,19 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"parser": "@babel/eslint-parser",
|
||||
"ignorePatterns": ["./node_modules/"],
|
||||
"parserOptions": {
|
||||
"requireConfigFile": false,
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"modules": true
|
||||
}
|
||||
},
|
||||
"babelOptions": {
|
||||
"presets": ["@babel/preset-react"]
|
||||
}
|
||||
},
|
||||
"plugins": ["react-hooks", "jsx-a11y", "i18next"],
|
||||
"plugins": ["react-hooks", "jsx-a11y", "i18next", "@babel"],
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"prettier",
|
||||
@ -17,7 +22,7 @@
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "16.5.2"
|
||||
"version": "detect"
|
||||
},
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
@ -141,6 +146,9 @@
|
||||
"jsx-a11y/label-has-associated-control": "off",
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
"react/jsx-filename-extension": "off"
|
||||
"react/jsx-filename-extension": "off",
|
||||
"no-restricted-exports": "off",
|
||||
"react/function-component-definition": "off",
|
||||
"prefer-regex-literals": "off"
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:14
|
||||
FROM node:14.18.3
|
||||
ARG NPMRC_FILE=.npmrc
|
||||
ENV NPMRC_FILE=${NPMRC_FILE}
|
||||
ARG TARGET='https://awx:8043'
|
||||
@ -6,7 +6,7 @@ ENV TARGET=${TARGET}
|
||||
ENV CI=true
|
||||
WORKDIR /ui
|
||||
ADD .eslintignore .eslintignore
|
||||
ADD .eslintrc .eslintrc
|
||||
ADD .eslintrc.json .eslintrc.json
|
||||
ADD .linguirc .linguirc
|
||||
ADD jsconfig.json jsconfig.json
|
||||
ADD public public
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# AWX-UI
|
||||
|
||||
## Requirements
|
||||
- node 14.x LTS, npm 7.x, make, git
|
||||
- node 14.18.3, npm 7.24.2, make, git
|
||||
|
||||
## Development
|
||||
The API development server will need to be running. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
|
||||
|
||||
39260
awx/ui/package-lock.json
generated
39260
awx/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@
|
||||
"ace-builds": "^1.4.12",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"axios": "0.22.0",
|
||||
"babel-plugin-macros": "^3.0.1",
|
||||
"codemirror": "^5.47.0",
|
||||
"d3": "7.1.1",
|
||||
"dagre": "^0.8.4",
|
||||
@ -34,31 +33,36 @@
|
||||
"styled-components": "5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.10",
|
||||
"@babel/eslint-parser": "^7.16.5",
|
||||
"@babel/eslint-plugin": "^7.16.5",
|
||||
"@babel/plugin-syntax-jsx": "7.16.7",
|
||||
"@babel/polyfill": "^7.8.7",
|
||||
"@babel/preset-react": "7.16.7",
|
||||
"@cypress/instrument-cra": "^1.4.0",
|
||||
"@lingui/cli": "^3.7.1",
|
||||
"@lingui/loader": "^3.8.3",
|
||||
"@lingui/macro": "^3.7.1",
|
||||
"@nteract/mockument": "^1.0.4",
|
||||
"@wojtekmaj/enzyme-adapter-react-17": "0.6.5",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-plugin-macros": "3.1.0",
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-react-16": "^1.14.0",
|
||||
"enzyme-to-json": "^3.3.5",
|
||||
"eslint": "7.30.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint": "^8.7.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-import-resolver-webpack": "0.11.1",
|
||||
"eslint-plugin-i18next": "^5.0.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"eslint-import-resolver-webpack": "0.13.2",
|
||||
"eslint-plugin-i18next": "5.1.2",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-jsx-a11y": "6.5.1",
|
||||
"eslint-plugin-react": "7.28.0",
|
||||
"eslint-plugin-react-hooks": "4.3.0",
|
||||
"http-proxy-middleware": "^1.0.3",
|
||||
"jest-websocket-mock": "^2.0.2",
|
||||
"mock-socket": "^9.0.3",
|
||||
"prettier": "2.3.2",
|
||||
"react-scripts": "^4.0.3"
|
||||
"react-scripts": "5.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prelint": "lingui compile",
|
||||
@ -66,7 +70,7 @@
|
||||
"prestart-instrumented": "lingui compile",
|
||||
"pretest": "lingui compile",
|
||||
"pretest-watch": "lingui compile",
|
||||
"start": "ESLINT_NO_DEV_ERRORS=true PORT=3001 HTTPS=true DANGEROUSLY_DISABLE_HOST_CHECK=true react-scripts start",
|
||||
"start": "GENERATE_SOURCEMAP=false ESLINT_NO_DEV_ERRORS=true PORT=3001 HTTPS=true DANGEROUSLY_DISABLE_HOST_CHECK=true react-scripts start",
|
||||
"start-instrumented": "ESLINT_NO_DEV_ERRORS=true DEBUG=instrument-cra PORT=3001 HTTPS=true DANGEROUSLY_DISABLE_HOST_CHECK=true react-scripts -r @cypress/instrument-cra start",
|
||||
"build": "INLINE_RUNTIME_CHUNK=false react-scripts build",
|
||||
"test": "TZ='UTC' react-scripts test --watchAll=false",
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable default-param-last */
|
||||
import axios from 'axios';
|
||||
import { encodeQueryString } from 'util/qs';
|
||||
import debounce from 'util/debounce';
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
.pf-c-select__toggle:before {
|
||||
border-top: var(--pf-c-select__toggle--before--BorderTopWidth) solid var(--pf-c-select__toggle--before--BorderTopColor);
|
||||
border-right: var(--pf-c-select__toggle--before--BorderRightWidth) solid var(--pf-c-select__toggle--before--BorderRightColor);
|
||||
border-bottom: var(--pf-c-select__toggle--before--BorderBottomWidth) solid var(--pf-c-select__toggle--before--BorderBottomColor);
|
||||
border-left: var(--pf-c-select__toggle--before--BorderLeftWidth) solid var(--pf-c-select__toggle--before--BorderLeftColor);
|
||||
.pf-c-select .pf-c-select__toggle:before {
|
||||
border-top: var(--pf-c-select__toggle--before--BorderTopWidth) solid
|
||||
var(--pf-c-select__toggle--before--BorderTopColor);
|
||||
border-right: var(--pf-c-select__toggle--before--BorderRightWidth) solid
|
||||
var(--pf-c-select__toggle--before--BorderRightColor);
|
||||
border-bottom: var(--pf-c-select__toggle--before--BorderBottomWidth) solid
|
||||
var(--pf-c-select__toggle--before--BorderBottomColor);
|
||||
border-left: var(--pf-c-select__toggle--before--BorderLeftWidth) solid
|
||||
var(--pf-c-select__toggle--before--BorderLeftColor);
|
||||
}
|
||||
/* https://github.com/patternfly/patternfly-react/issues/5650 */
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -91,76 +91,74 @@ function AssociateModal({
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
ouiaId={ouiaId}
|
||||
variant="large"
|
||||
title={title}
|
||||
aria-label={t`Association modal`}
|
||||
isOpen={isModalOpen}
|
||||
onClose={handleClose}
|
||||
actions={[
|
||||
<Button
|
||||
ouiaId="associate-modal-save"
|
||||
aria-label={t`Save`}
|
||||
key="select"
|
||||
variant="primary"
|
||||
onClick={handleSave}
|
||||
isDisabled={selected.length === 0}
|
||||
>
|
||||
{t`Save`}
|
||||
</Button>,
|
||||
<Button
|
||||
ouiaId="associate-modal-cancel"
|
||||
aria-label={t`Cancel`}
|
||||
key="cancel"
|
||||
variant="link"
|
||||
onClick={handleClose}
|
||||
>
|
||||
{t`Cancel`}
|
||||
</Button>,
|
||||
<Modal
|
||||
ouiaId={ouiaId}
|
||||
variant="large"
|
||||
title={title}
|
||||
aria-label={t`Association modal`}
|
||||
isOpen={isModalOpen}
|
||||
onClose={handleClose}
|
||||
actions={[
|
||||
<Button
|
||||
ouiaId="associate-modal-save"
|
||||
aria-label={t`Save`}
|
||||
key="select"
|
||||
variant="primary"
|
||||
onClick={handleSave}
|
||||
isDisabled={selected.length === 0}
|
||||
>
|
||||
{t`Save`}
|
||||
</Button>,
|
||||
<Button
|
||||
ouiaId="associate-modal-cancel"
|
||||
aria-label={t`Cancel`}
|
||||
key="cancel"
|
||||
variant="link"
|
||||
onClick={handleClose}
|
||||
>
|
||||
{t`Cancel`}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<OptionsList
|
||||
displayKey={displayKey}
|
||||
contentError={contentError}
|
||||
columns={columns}
|
||||
deselectItem={handleSelect}
|
||||
header={header}
|
||||
isLoading={isLoading}
|
||||
multiple
|
||||
optionCount={itemCount}
|
||||
options={items}
|
||||
qsConfig={QS_CONFIG(displayKey)}
|
||||
readOnly={false}
|
||||
selectItem={handleSelect}
|
||||
value={selected}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: `${displayKey}__icontains`,
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<OptionsList
|
||||
displayKey={displayKey}
|
||||
contentError={contentError}
|
||||
columns={columns}
|
||||
deselectItem={handleSelect}
|
||||
header={header}
|
||||
isLoading={isLoading}
|
||||
multiple
|
||||
optionCount={itemCount}
|
||||
options={items}
|
||||
qsConfig={QS_CONFIG(displayKey)}
|
||||
readOnly={false}
|
||||
selectItem={handleSelect}
|
||||
value={selected}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: `${displayKey}__icontains`,
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: `${displayKey}`,
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
/>
|
||||
</Modal>
|
||||
</>
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: `${displayKey}`,
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import React, { Fragment } from 'react';
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import { Link, Redirect } from 'react-router-dom';
|
||||
import { bool, instanceOf } from 'prop-types';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
@ -77,6 +77,14 @@ function DataListToolbar({
|
||||
setIsKebabOpen(false);
|
||||
}
|
||||
}, [isKebabModalOpen]);
|
||||
|
||||
const kebabProviderValue = useMemo(
|
||||
() => ({
|
||||
isKebabified: true,
|
||||
onKebabModalChange: setIsKebabModalOpen,
|
||||
}),
|
||||
[setIsKebabModalOpen]
|
||||
);
|
||||
return (
|
||||
<Toolbar
|
||||
id={`${qsConfig.namespace}-list-toolbar`}
|
||||
@ -145,25 +153,18 @@ function DataListToolbar({
|
||||
</ToolbarToggleGroup>
|
||||
{showExpandCollapse && (
|
||||
<ToolbarGroup>
|
||||
<>
|
||||
<ToolbarItem>
|
||||
<ExpandCollapse
|
||||
isCompact={isCompact}
|
||||
onCompact={onCompact}
|
||||
onExpand={onExpand}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</>
|
||||
<ToolbarItem>
|
||||
<ExpandCollapse
|
||||
isCompact={isCompact}
|
||||
onCompact={onCompact}
|
||||
onExpand={onExpand}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
)}
|
||||
{isAdvancedSearchShown && additionalControls.length > 0 && (
|
||||
<ToolbarItem>
|
||||
<KebabifiedProvider
|
||||
value={{
|
||||
isKebabified: true,
|
||||
onKebabModalChange: setIsKebabModalOpen,
|
||||
}}
|
||||
>
|
||||
<KebabifiedProvider value={kebabProviderValue}>
|
||||
<Dropdown
|
||||
toggle={
|
||||
<KebabToggle
|
||||
|
||||
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { TextList, TextListVariants } from '@patternfly/react-core';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const DetailList = ({ children, stacked, compact, ...props }) => (
|
||||
const DetailList = ({ children, stacked, ...props }) => (
|
||||
<TextList component={TextListVariants.dl} {...props}>
|
||||
{children}
|
||||
</TextList>
|
||||
|
||||
@ -22,10 +22,10 @@ function DisassociateButton({
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext);
|
||||
|
||||
function handleDisassociate() {
|
||||
const handleDisassociate = () => {
|
||||
onDisassociate();
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isKebabified) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useField } from 'formik';
|
||||
|
||||
@ -35,9 +35,9 @@ function CredentialsStep({
|
||||
name: 'credentials',
|
||||
validate: (val) =>
|
||||
credentialsValidator(
|
||||
defaultCredentials,
|
||||
allowCredentialsWithPasswords,
|
||||
val
|
||||
val,
|
||||
defaultCredentials
|
||||
),
|
||||
});
|
||||
const [selectedType, setSelectedType] = useState(null);
|
||||
@ -102,9 +102,9 @@ function CredentialsStep({
|
||||
useEffect(() => {
|
||||
helpers.setError(
|
||||
credentialsValidator(
|
||||
defaultCredentials,
|
||||
allowCredentialsWithPasswords,
|
||||
field.value
|
||||
field.value,
|
||||
defaultCredentials
|
||||
)
|
||||
);
|
||||
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { ExclamationCircleIcon as PFExclamationCircleIcon } from '@patternfly/react-icons';
|
||||
import { Tooltip } from '@patternfly/react-core';
|
||||
|
||||
@ -19,18 +19,16 @@ function StepName({ hasErrors, children, id }) {
|
||||
return <div id={id}>{children}</div>;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<AlertText id={id}>
|
||||
{children}
|
||||
<Tooltip
|
||||
position="right"
|
||||
content={t`This step contains errors`}
|
||||
trigger="click mouseenter focus"
|
||||
>
|
||||
<ExclamationCircleIcon css="color: var(--pf-global--danger-color--100)" />
|
||||
</Tooltip>
|
||||
</AlertText>
|
||||
</>
|
||||
<AlertText id={id}>
|
||||
{children}
|
||||
<Tooltip
|
||||
position="right"
|
||||
content={t`This step contains errors`}
|
||||
trigger="click mouseenter focus"
|
||||
>
|
||||
<ExclamationCircleIcon css="color: var(--pf-global--danger-color--100)" />
|
||||
</Tooltip>
|
||||
</AlertText>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -7,9 +7,9 @@ const credentialPromptsForPassword = (credential) =>
|
||||
credential?.inputs?.vault_password === 'ASK';
|
||||
|
||||
export default function credentialsValidator(
|
||||
defaultCredentials = [],
|
||||
allowCredentialsWithPasswords,
|
||||
selectedCredentials
|
||||
selectedCredentials,
|
||||
defaultCredentials = []
|
||||
) {
|
||||
if (defaultCredentials.length > 0 && selectedCredentials) {
|
||||
const missingCredentialTypes = [];
|
||||
|
||||
@ -35,9 +35,9 @@ export default function useCredentialsStep(
|
||||
validate: () => {
|
||||
helpers.setError(
|
||||
credentialsValidator(
|
||||
resourceDefaultCredentials,
|
||||
allowCredentialsWithPasswords,
|
||||
field.value
|
||||
field.value,
|
||||
resourceDefaultCredentials
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
@ -7,7 +7,7 @@ import useOtherPromptsStep from './steps/useOtherPromptsStep';
|
||||
import useSurveyStep from './steps/useSurveyStep';
|
||||
import usePreviewStep from './steps/usePreviewStep';
|
||||
|
||||
function showCredentialPasswordsStep(credentials = [], launchConfig) {
|
||||
function showCredentialPasswordsStep(launchConfig, credentials = []) {
|
||||
if (
|
||||
!launchConfig?.ask_credential_on_launch &&
|
||||
launchConfig?.passwords_needed_to_start
|
||||
@ -53,7 +53,7 @@ export default function useLaunchSteps(launchConfig, surveyConfig, resource) {
|
||||
),
|
||||
useCredentialPasswordsStep(
|
||||
launchConfig,
|
||||
showCredentialPasswordsStep(formikValues.credentials, launchConfig),
|
||||
showCredentialPasswordsStep(launchConfig, formikValues.credentials),
|
||||
visited
|
||||
),
|
||||
useOtherPromptsStep(launchConfig, resource),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
|
||||
@ -150,50 +150,48 @@ function ExecutionEnvironmentLookup({
|
||||
}, [fetchExecutionEnvironments]);
|
||||
|
||||
const renderLookup = () => (
|
||||
<>
|
||||
<Lookup
|
||||
id={id}
|
||||
header={t`Execution Environment`}
|
||||
value={value}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
onDebounce={checkExecutionEnvironmentName}
|
||||
fieldName={fieldName}
|
||||
validate={validate}
|
||||
qsConfig={QS_CONFIG}
|
||||
isLoading={isLoading || isProjectLoading}
|
||||
isDisabled={isDisabled}
|
||||
renderOptionsList={({ state, dispatch, canDelete }) => (
|
||||
<OptionsList
|
||||
value={state.selectedItems}
|
||||
options={executionEnvironments}
|
||||
optionCount={count}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
]}
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
multiple={state.multiple}
|
||||
header={t`Execution Environment`}
|
||||
name="executionEnvironments"
|
||||
qsConfig={QS_CONFIG}
|
||||
readOnly={!canDelete}
|
||||
selectItem={(item) => dispatch({ type: 'SELECT_ITEM', item })}
|
||||
deselectItem={(item) => dispatch({ type: 'DESELECT_ITEM', item })}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
<Lookup
|
||||
id={id}
|
||||
header={t`Execution Environment`}
|
||||
value={value}
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
onDebounce={checkExecutionEnvironmentName}
|
||||
fieldName={fieldName}
|
||||
validate={validate}
|
||||
qsConfig={QS_CONFIG}
|
||||
isLoading={isLoading || isProjectLoading}
|
||||
isDisabled={isDisabled}
|
||||
renderOptionsList={({ state, dispatch, canDelete }) => (
|
||||
<OptionsList
|
||||
value={state.selectedItems}
|
||||
options={executionEnvironments}
|
||||
optionCount={count}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
]}
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
multiple={state.multiple}
|
||||
header={t`Execution Environment`}
|
||||
name="executionEnvironments"
|
||||
qsConfig={QS_CONFIG}
|
||||
readOnly={!canDelete}
|
||||
selectItem={(item) => dispatch({ type: 'SELECT_ITEM', item })}
|
||||
deselectItem={(item) => dispatch({ type: 'DESELECT_ITEM', item })}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
const renderLabel = () => {
|
||||
|
||||
@ -123,71 +123,69 @@ function InventoryLookup({
|
||||
}, [fetchInventories]);
|
||||
|
||||
return isPromptableField ? (
|
||||
<>
|
||||
<FieldWithPrompt
|
||||
fieldId={fieldId}
|
||||
isRequired={required}
|
||||
label={t`Inventory`}
|
||||
promptId={promptId}
|
||||
promptName={promptName}
|
||||
isDisabled={!canEdit || isDisabled}
|
||||
tooltip={t`Select the inventory containing the hosts
|
||||
<FieldWithPrompt
|
||||
fieldId={fieldId}
|
||||
isRequired={required}
|
||||
label={t`Inventory`}
|
||||
promptId={promptId}
|
||||
promptName={promptName}
|
||||
isDisabled={!canEdit || isDisabled}
|
||||
tooltip={t`Select the inventory containing the hosts
|
||||
you want this job to manage.`}
|
||||
>
|
||||
<Lookup
|
||||
id="inventory-lookup"
|
||||
header={t`Inventory`}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
required={required}
|
||||
onDebounce={checkInventoryName}
|
||||
fieldName={fieldName}
|
||||
validate={validate}
|
||||
isLoading={isLoading}
|
||||
isDisabled={!canEdit || isDisabled}
|
||||
qsConfig={QS_CONFIG}
|
||||
renderOptionsList={({ state, dispatch, canDelete }) => (
|
||||
<OptionsList
|
||||
value={state.selectedItems}
|
||||
options={inventories}
|
||||
optionCount={count}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
multiple={state.multiple}
|
||||
header={t`Inventory`}
|
||||
name="inventory"
|
||||
qsConfig={QS_CONFIG}
|
||||
readOnly={!canDelete}
|
||||
selectItem={(item) => dispatch({ type: 'SELECT_ITEM', item })}
|
||||
deselectItem={(item) => dispatch({ type: 'DESELECT_ITEM', item })}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<LookupErrorMessage error={error} />
|
||||
</FieldWithPrompt>
|
||||
</>
|
||||
>
|
||||
<Lookup
|
||||
id="inventory-lookup"
|
||||
header={t`Inventory`}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
required={required}
|
||||
onDebounce={checkInventoryName}
|
||||
fieldName={fieldName}
|
||||
validate={validate}
|
||||
isLoading={isLoading}
|
||||
isDisabled={!canEdit || isDisabled}
|
||||
qsConfig={QS_CONFIG}
|
||||
renderOptionsList={({ state, dispatch, canDelete }) => (
|
||||
<OptionsList
|
||||
value={state.selectedItems}
|
||||
options={inventories}
|
||||
optionCount={count}
|
||||
searchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
sortColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name',
|
||||
},
|
||||
]}
|
||||
searchableKeys={searchableKeys}
|
||||
relatedSearchableKeys={relatedSearchableKeys}
|
||||
multiple={state.multiple}
|
||||
header={t`Inventory`}
|
||||
name="inventory"
|
||||
qsConfig={QS_CONFIG}
|
||||
readOnly={!canDelete}
|
||||
selectItem={(item) => dispatch({ type: 'SELECT_ITEM', item })}
|
||||
deselectItem={(item) => dispatch({ type: 'DESELECT_ITEM', item })}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<LookupErrorMessage error={error} />
|
||||
</FieldWithPrompt>
|
||||
) : (
|
||||
<>
|
||||
<Lookup
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import React, { Fragment } from 'react';
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import { func, string } from 'prop-types';
|
||||
import { Button } from '@patternfly/react-core';
|
||||
|
||||
|
||||
@ -21,12 +21,12 @@ function RoutedTabs({ tabsArray }) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
function handleTabSelect(event, eventKey) {
|
||||
const handleTabSelect = (event, eventKey) => {
|
||||
const match = tabsArray.find((tab) => tab.id === eventKey);
|
||||
if (match) {
|
||||
history.push(match.link);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -164,37 +164,35 @@ function Search({
|
||||
/>
|
||||
)) ||
|
||||
(options && (
|
||||
<>
|
||||
<Select
|
||||
variant={SelectVariant.checkbox}
|
||||
aria-label={name}
|
||||
typeAheadAriaLabel={name}
|
||||
onToggle={setIsFilterDropdownOpen}
|
||||
onSelect={(event, selection) =>
|
||||
handleFilterDropdownSelect(key, event, selection)
|
||||
}
|
||||
selections={chipsByKey[key].chips.map((chip) => {
|
||||
const [, ...value] = chip.key.split(':');
|
||||
return value.join(':');
|
||||
})}
|
||||
isOpen={isFilterDropdownOpen}
|
||||
placeholderText={t`Filter By ${name}`}
|
||||
ouiaId={`filter-by-${key}`}
|
||||
isDisabled={isDisabled}
|
||||
maxHeight={maxSelectHeight}
|
||||
noResultsFoundText={t`No results found`}
|
||||
>
|
||||
{options.map(([optionKey, optionLabel]) => (
|
||||
<SelectOption
|
||||
key={optionKey}
|
||||
value={optionKey}
|
||||
inputId={`select-option-${optionKey}`}
|
||||
>
|
||||
{optionLabel}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
</>
|
||||
<Select
|
||||
variant={SelectVariant.checkbox}
|
||||
aria-label={name}
|
||||
typeAheadAriaLabel={name}
|
||||
onToggle={setIsFilterDropdownOpen}
|
||||
onSelect={(event, selection) =>
|
||||
handleFilterDropdownSelect(key, event, selection)
|
||||
}
|
||||
selections={chipsByKey[key].chips.map((chip) => {
|
||||
const [, ...value] = chip.key.split(':');
|
||||
return value.join(':');
|
||||
})}
|
||||
isOpen={isFilterDropdownOpen}
|
||||
placeholderText={t`Filter By ${name}`}
|
||||
ouiaId={`filter-by-${key}`}
|
||||
isDisabled={isDisabled}
|
||||
maxHeight={maxSelectHeight}
|
||||
noResultsFoundText={t`No results found`}
|
||||
>
|
||||
{options.map(([optionKey, optionLabel]) => (
|
||||
<SelectOption
|
||||
key={optionKey}
|
||||
value={optionKey}
|
||||
inputId={`select-option-${optionKey}`}
|
||||
>
|
||||
{optionLabel}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)) ||
|
||||
(isBoolean && (
|
||||
<Select
|
||||
|
||||
@ -37,7 +37,7 @@ function DraggableSelectedList({ selected, onRemove, onRowDrag }) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function dragItem(item, dest) {
|
||||
const dragItem = (item, dest) => {
|
||||
if (!dest || item.index === dest.index) {
|
||||
return false;
|
||||
}
|
||||
@ -45,7 +45,7 @@ function DraggableSelectedList({ selected, onRemove, onRowDrag }) {
|
||||
const newItems = reorder(selected, item.index, dest.index);
|
||||
onRowDrag(newItems);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (selected.length <= 0) {
|
||||
return null;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import { arrayOf } from 'prop-types';
|
||||
|
||||
import { Link as _Link } from 'react-router-dom';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import 'styled-components/macro';
|
||||
import React from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -133,14 +133,12 @@ function WorkflowNodeHelp({ node }) {
|
||||
return (
|
||||
<>
|
||||
{!unifiedJobTemplate && (!job || job.type !== 'workflow_approval') && (
|
||||
<>
|
||||
<ResourceDeleted job={job}>
|
||||
<StyledExclamationTriangleIcon />
|
||||
<Trans>
|
||||
The resource associated with this node has been deleted.
|
||||
</Trans>
|
||||
</ResourceDeleted>
|
||||
</>
|
||||
<ResourceDeleted job={job}>
|
||||
<StyledExclamationTriangleIcon />
|
||||
<Trans>
|
||||
The resource associated with this node has been deleted.
|
||||
</Trans>
|
||||
</ResourceDeleted>
|
||||
)}
|
||||
{job && (
|
||||
<GridDL>
|
||||
|
||||
@ -4,6 +4,7 @@ import React, {
|
||||
useState,
|
||||
useRef,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { useHistory, Redirect } from 'react-router-dom';
|
||||
import { DateTime } from 'luxon';
|
||||
@ -163,23 +164,35 @@ function SessionProvider({ children }) {
|
||||
clearInterval(sessionIntervalId.current);
|
||||
}, []);
|
||||
|
||||
const sessionValue = useMemo(
|
||||
() => ({
|
||||
isUserBeingLoggedOut,
|
||||
loginRedirectOverride,
|
||||
authRedirectTo,
|
||||
handleSessionContinue,
|
||||
isSessionExpired,
|
||||
logout,
|
||||
sessionCountdown,
|
||||
setAuthRedirectTo,
|
||||
}),
|
||||
[
|
||||
isUserBeingLoggedOut,
|
||||
loginRedirectOverride,
|
||||
authRedirectTo,
|
||||
handleSessionContinue,
|
||||
isSessionExpired,
|
||||
logout,
|
||||
sessionCountdown,
|
||||
setAuthRedirectTo,
|
||||
]
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SessionContext.Provider
|
||||
value={{
|
||||
isUserBeingLoggedOut,
|
||||
loginRedirectOverride,
|
||||
authRedirectTo,
|
||||
handleSessionContinue,
|
||||
isSessionExpired,
|
||||
logout,
|
||||
sessionCountdown,
|
||||
setAuthRedirectTo,
|
||||
}}
|
||||
>
|
||||
<SessionContext.Provider value={sessionValue}>
|
||||
{children}
|
||||
</SessionContext.Provider>
|
||||
);
|
||||
|
||||
@ -73,21 +73,19 @@ function ApplicationAdd({ onSuccessfulAdd }) {
|
||||
return <ContentError error={error} />;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<PageSection>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<ApplicationForm
|
||||
onSubmit={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
authorizationOptions={authorizationOptions}
|
||||
clientTypeOptions={clientTypeOptions}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</PageSection>
|
||||
</>
|
||||
<PageSection>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<ApplicationForm
|
||||
onSubmit={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
authorizationOptions={authorizationOptions}
|
||||
clientTypeOptions={clientTypeOptions}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</PageSection>
|
||||
);
|
||||
}
|
||||
export default ApplicationAdd;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useState } from 'react';
|
||||
import { useField, useFormikContext } from 'formik';
|
||||
import { shape, string } from 'prop-types';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useLocation, useHistory } from 'react-router-dom';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
import { useField, useFormikContext } from 'formik';
|
||||
|
||||
@ -74,59 +74,57 @@ function ExecutionEnvironmentTemplateList({ executionEnvironment }) {
|
||||
}, [fetchTemplates]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading}
|
||||
items={templates}
|
||||
itemCount={templatesCount}
|
||||
pluralizedItemName={t`Templates`}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Type`,
|
||||
key: 'or__type',
|
||||
options: [
|
||||
[`job_template`, t`Job Template`],
|
||||
[`workflow_job_template`, t`Workflow Template`],
|
||||
],
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DatalistToolbar {...props} qsConfig={QS_CONFIG} />
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG} isSelectable={false}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Type`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(template) => (
|
||||
<ExecutionEnvironmentTemplateListItem
|
||||
key={template.id}
|
||||
template={template}
|
||||
detailUrl={`/templates/${template.type}/${template.id}/details`}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
</>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading}
|
||||
items={templates}
|
||||
itemCount={templatesCount}
|
||||
pluralizedItemName={t`Templates`}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Type`,
|
||||
key: 'or__type',
|
||||
options: [
|
||||
[`job_template`, t`Job Template`],
|
||||
[`workflow_job_template`, t`Workflow Template`],
|
||||
],
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DatalistToolbar {...props} qsConfig={QS_CONFIG} />
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG} isSelectable={false}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Type`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(template) => (
|
||||
<ExecutionEnvironmentTemplateListItem
|
||||
key={template.id}
|
||||
template={template}
|
||||
detailUrl={`/templates/${template.type}/${template.id}/details`}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ function ContainerGroup({ setBreadcrumb }) {
|
||||
{contentError.response?.status === 404 && (
|
||||
<span>
|
||||
{t`Container group not found.`}
|
||||
{''}
|
||||
|
||||
<Link to="/instance_groups">{t`View all instance groups`}</Link>
|
||||
</span>
|
||||
)}
|
||||
|
||||
@ -102,7 +102,7 @@ function InstanceGroup({ setBreadcrumb }) {
|
||||
{contentError.response?.status === 404 && (
|
||||
<span>
|
||||
{t`Instance group not found.`}
|
||||
{''}
|
||||
|
||||
<Link to="/instance_groups">{t`View all instance groups`}</Link>
|
||||
</span>
|
||||
)}
|
||||
|
||||
@ -28,9 +28,9 @@ const QS_CONFIG = getQSConfig('instance-group', {
|
||||
});
|
||||
|
||||
function modifyInstanceGroups(
|
||||
items = [],
|
||||
defaultControlPlane,
|
||||
defaultExecution
|
||||
defaultExecution,
|
||||
items = []
|
||||
) {
|
||||
return items.map((item) => {
|
||||
const clonedItem = {
|
||||
@ -128,9 +128,9 @@ function InstanceGroupList({
|
||||
useSelected(instanceGroups);
|
||||
|
||||
const modifiedSelected = modifyInstanceGroups(
|
||||
selected,
|
||||
defaultControlPlane,
|
||||
defaultExecution
|
||||
defaultExecution,
|
||||
selected
|
||||
);
|
||||
|
||||
const {
|
||||
@ -158,13 +158,10 @@ function InstanceGroupList({
|
||||
|
||||
const canAdd = actions && actions.POST;
|
||||
|
||||
function cannotDelete(item) {
|
||||
return (
|
||||
!item.summary_fields.user_capabilities.delete ||
|
||||
item.name === defaultExecution ||
|
||||
item.name === defaultControlPlane
|
||||
);
|
||||
}
|
||||
const cannotDelete = (item) =>
|
||||
!item.summary_fields.user_capabilities.delete ||
|
||||
item.name === defaultExecution ||
|
||||
item.name === defaultControlPlane;
|
||||
|
||||
const pluralizedItemName = t`Instance Groups`;
|
||||
|
||||
|
||||
@ -107,104 +107,102 @@ function InventoryGroupsList() {
|
||||
actions && Object.prototype.hasOwnProperty.call(actions, 'POST');
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading || isAdHocLaunchLoading}
|
||||
items={groups}
|
||||
itemCount={groupCount}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Group type`,
|
||||
key: 'parents__isnull',
|
||||
options: [['true', t`Show only root groups`]],
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(item, index) => (
|
||||
<InventoryGroupItem
|
||||
key={item.id}
|
||||
group={item}
|
||||
inventoryId={inventoryId}
|
||||
isSelected={selected.some((row) => row.id === item.id)}
|
||||
onSelect={() => handleSelect(item)}
|
||||
rowIndex={index}
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading || isAdHocLaunchLoading}
|
||||
items={groups}
|
||||
itemCount={groupCount}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Group type`,
|
||||
key: 'parents__isnull',
|
||||
options: [['true', t`Show only root groups`]],
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(item, index) => (
|
||||
<InventoryGroupItem
|
||||
key={item.id}
|
||||
group={item}
|
||||
inventoryId={inventoryId}
|
||||
isSelected={selected.some((row) => row.id === item.id)}
|
||||
onSelect={() => handleSelect(item)}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
renderToolbar={(props) => (
|
||||
<DataListToolbar
|
||||
{...props}
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
? [
|
||||
<ToolbarAddButton
|
||||
key="add"
|
||||
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
||||
/>,
|
||||
]
|
||||
: []),
|
||||
...(!isAdHocDisabled
|
||||
? [
|
||||
<AdHocCommands
|
||||
adHocItems={selected}
|
||||
hasListItems={groupCount > 0}
|
||||
onLaunchLoading={setIsAdHocLaunchLoading}
|
||||
moduleOptions={moduleOptions}
|
||||
/>,
|
||||
]
|
||||
: []),
|
||||
<Tooltip content={renderTooltip()} position="top" key="delete">
|
||||
<div>
|
||||
<InventoryGroupsDeleteModal
|
||||
groups={selected}
|
||||
isDisabled={
|
||||
selected.length === 0 || selected.some(cannotDelete)
|
||||
}
|
||||
onAfterDelete={() => {
|
||||
fetchData();
|
||||
clearSelected();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
emptyStateControls={
|
||||
canAdd && (
|
||||
<ToolbarAddButton
|
||||
key="add"
|
||||
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
||||
/>
|
||||
)}
|
||||
renderToolbar={(props) => (
|
||||
<DataListToolbar
|
||||
{...props}
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={[
|
||||
...(canAdd
|
||||
? [
|
||||
<ToolbarAddButton
|
||||
key="add"
|
||||
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
||||
/>,
|
||||
]
|
||||
: []),
|
||||
...(!isAdHocDisabled
|
||||
? [
|
||||
<AdHocCommands
|
||||
adHocItems={selected}
|
||||
hasListItems={groupCount > 0}
|
||||
onLaunchLoading={setIsAdHocLaunchLoading}
|
||||
moduleOptions={moduleOptions}
|
||||
/>,
|
||||
]
|
||||
: []),
|
||||
<Tooltip content={renderTooltip()} position="top" key="delete">
|
||||
<div>
|
||||
<InventoryGroupsDeleteModal
|
||||
groups={selected}
|
||||
isDisabled={
|
||||
selected.length === 0 || selected.some(cannotDelete)
|
||||
}
|
||||
onAfterDelete={() => {
|
||||
fetchData();
|
||||
clearSelected();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>,
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
emptyStateControls={
|
||||
canAdd && (
|
||||
<ToolbarAddButton
|
||||
key="add"
|
||||
linkTo={`/inventories/inventory/${inventoryId}/groups/add`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
export default InventoryGroupsList;
|
||||
|
||||
@ -5,22 +5,20 @@ import InventoryRelatedGroupAdd from '../InventoryRelatedGroupAdd';
|
||||
|
||||
function InventoryRelatedGroups() {
|
||||
return (
|
||||
<>
|
||||
<Switch>
|
||||
<Route
|
||||
key="addRelatedGroups"
|
||||
path="/inventories/inventory/:id/groups/:groupId/nested_groups/add"
|
||||
>
|
||||
<InventoryRelatedGroupAdd />
|
||||
</Route>
|
||||
<Route
|
||||
key="relatedGroups"
|
||||
path="/inventories/inventory/:id/groups/:groupId/nested_groups"
|
||||
>
|
||||
<InventoryRelatedGroupList />
|
||||
</Route>
|
||||
</Switch>
|
||||
</>
|
||||
<Switch>
|
||||
<Route
|
||||
key="addRelatedGroups"
|
||||
path="/inventories/inventory/:id/groups/:groupId/nested_groups/add"
|
||||
>
|
||||
<InventoryRelatedGroupAdd />
|
||||
</Route>
|
||||
<Route
|
||||
key="relatedGroups"
|
||||
path="/inventories/inventory/:id/groups/:groupId/nested_groups"
|
||||
>
|
||||
<InventoryRelatedGroupList />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
export default InventoryRelatedGroups;
|
||||
|
||||
@ -57,87 +57,85 @@ function InventorySourceListItem({
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tr id={`source-row-${source.id}`} ouiaId={`source-row-${source.id}`}>
|
||||
<Td
|
||||
data-cy={`check-action-${source.id}`}
|
||||
select={{
|
||||
rowIndex,
|
||||
isSelected,
|
||||
onSelect,
|
||||
}}
|
||||
/>
|
||||
<TdBreakWord dataLabel={t`Name`}>
|
||||
<Link to={`${detailUrl}/details`}>
|
||||
<b>{source.name}</b>
|
||||
</Link>
|
||||
{missingExecutionEnvironment && (
|
||||
<span>
|
||||
<Tooltip
|
||||
className="missing-execution-environment"
|
||||
content={t`Custom virtual environment ${source.custom_virtualenv} must be replaced by an execution environment.`}
|
||||
position="right"
|
||||
>
|
||||
<ExclamationTriangleIcon />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
</TdBreakWord>
|
||||
<Td dataLabel={t`Status`}>
|
||||
{job && (
|
||||
<Tr id={`source-row-${source.id}`} ouiaId={`source-row-${source.id}`}>
|
||||
<Td
|
||||
data-cy={`check-action-${source.id}`}
|
||||
select={{
|
||||
rowIndex,
|
||||
isSelected,
|
||||
onSelect,
|
||||
}}
|
||||
/>
|
||||
<TdBreakWord dataLabel={t`Name`}>
|
||||
<Link to={`${detailUrl}/details`}>
|
||||
<b>{source.name}</b>
|
||||
</Link>
|
||||
{missingExecutionEnvironment && (
|
||||
<span>
|
||||
<Tooltip
|
||||
position="top"
|
||||
content={generateLastJobTooltip(job)}
|
||||
key={job.id}
|
||||
className="missing-execution-environment"
|
||||
content={t`Custom virtual environment ${source.custom_virtualenv} must be replaced by an execution environment.`}
|
||||
position="right"
|
||||
>
|
||||
<Link to={`/jobs/inventory/${job.id}`}>
|
||||
<StatusLabel status={job.status} />
|
||||
</Link>
|
||||
<ExclamationTriangleIcon />
|
||||
</Tooltip>
|
||||
)}
|
||||
</Td>
|
||||
<Td dataLabel={t`Type`}>{label}</Td>
|
||||
<ActionsTd dataLabel={t`Actions`}>
|
||||
{['running', 'pending', 'waiting'].includes(job?.status) ? (
|
||||
<ActionItem visible={source.summary_fields.user_capabilities.start}>
|
||||
{source.summary_fields?.current_job?.id && (
|
||||
<JobCancelButton
|
||||
job={{
|
||||
type: 'inventory_update',
|
||||
id: source?.summary_fields?.current_job?.id,
|
||||
}}
|
||||
errorTitle={t`Inventory Source Sync Error`}
|
||||
errorMessage={t`Failed to cancel Inventory Source Sync`}
|
||||
title={t`Cancel Inventory Source Sync`}
|
||||
showIconButton
|
||||
/>
|
||||
)}
|
||||
</ActionItem>
|
||||
) : (
|
||||
<ActionItem
|
||||
visible={source.summary_fields.user_capabilities.start}
|
||||
tooltip={t`Sync`}
|
||||
>
|
||||
<InventorySourceSyncButton source={source} />
|
||||
</ActionItem>
|
||||
)}
|
||||
<ActionItem
|
||||
visible={source.summary_fields.user_capabilities.edit}
|
||||
tooltip={t`Edit`}
|
||||
</span>
|
||||
)}
|
||||
</TdBreakWord>
|
||||
<Td dataLabel={t`Status`}>
|
||||
{job && (
|
||||
<Tooltip
|
||||
position="top"
|
||||
content={generateLastJobTooltip(job)}
|
||||
key={job.id}
|
||||
>
|
||||
<Button
|
||||
ouiaId={`${source.id}-edit-button`}
|
||||
aria-label={t`Edit Source`}
|
||||
variant="plain"
|
||||
component={Link}
|
||||
to={`${detailUrl}/edit`}
|
||||
>
|
||||
<PencilAltIcon />
|
||||
</Button>
|
||||
<Link to={`/jobs/inventory/${job.id}`}>
|
||||
<StatusLabel status={job.status} />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Td>
|
||||
<Td dataLabel={t`Type`}>{label}</Td>
|
||||
<ActionsTd dataLabel={t`Actions`}>
|
||||
{['running', 'pending', 'waiting'].includes(job?.status) ? (
|
||||
<ActionItem visible={source.summary_fields.user_capabilities.start}>
|
||||
{source.summary_fields?.current_job?.id && (
|
||||
<JobCancelButton
|
||||
job={{
|
||||
type: 'inventory_update',
|
||||
id: source?.summary_fields?.current_job?.id,
|
||||
}}
|
||||
errorTitle={t`Inventory Source Sync Error`}
|
||||
errorMessage={t`Failed to cancel Inventory Source Sync`}
|
||||
title={t`Cancel Inventory Source Sync`}
|
||||
showIconButton
|
||||
/>
|
||||
)}
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
</Tr>
|
||||
</>
|
||||
) : (
|
||||
<ActionItem
|
||||
visible={source.summary_fields.user_capabilities.start}
|
||||
tooltip={t`Sync`}
|
||||
>
|
||||
<InventorySourceSyncButton source={source} />
|
||||
</ActionItem>
|
||||
)}
|
||||
<ActionItem
|
||||
visible={source.summary_fields.user_capabilities.edit}
|
||||
tooltip={t`Edit`}
|
||||
>
|
||||
<Button
|
||||
ouiaId={`${source.id}-edit-button`}
|
||||
aria-label={t`Edit Source`}
|
||||
variant="plain"
|
||||
component={Link}
|
||||
to={`${detailUrl}/edit`}
|
||||
>
|
||||
<PencilAltIcon />
|
||||
</Button>
|
||||
</ActionItem>
|
||||
</ActionsTd>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
export default InventorySourceListItem;
|
||||
|
||||
@ -55,68 +55,66 @@ function SmartInventoryHostList({ inventory }) {
|
||||
}, [fetchHosts]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading || isAdHocLaunchLoading}
|
||||
items={hosts}
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Hosts`}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created by (username)`,
|
||||
key: 'created_by__username',
|
||||
},
|
||||
{
|
||||
name: t`Modified by (username)`,
|
||||
key: 'modified_by__username',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DataListToolbar
|
||||
{...props}
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={
|
||||
inventory?.summary_fields?.user_capabilities?.adhoc
|
||||
? [
|
||||
<AdHocCommands
|
||||
adHocItems={selected}
|
||||
hasListItems={count > 0}
|
||||
onLaunchLoading={setIsAdHocLaunchLoading}
|
||||
/>,
|
||||
]
|
||||
: []
|
||||
}
|
||||
/>
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Recent jobs`}</HeaderCell>
|
||||
<HeaderCell>{t`Inventory`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(host, index) => (
|
||||
<SmartInventoryHostListItem
|
||||
key={host.id}
|
||||
host={host}
|
||||
detailUrl={`/inventories/smart_inventory/${inventory.id}/hosts/${host.id}/details`}
|
||||
isSelected={selected.some((row) => row.id === host.id)}
|
||||
onSelect={() => handleSelect(host)}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading || isAdHocLaunchLoading}
|
||||
items={hosts}
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Hosts`}
|
||||
qsConfig={QS_CONFIG}
|
||||
clearSelected={clearSelected}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Created by (username)`,
|
||||
key: 'created_by__username',
|
||||
},
|
||||
{
|
||||
name: t`Modified by (username)`,
|
||||
key: 'modified_by__username',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DataListToolbar
|
||||
{...props}
|
||||
isAllSelected={isAllSelected}
|
||||
onSelectAll={selectAll}
|
||||
qsConfig={QS_CONFIG}
|
||||
additionalControls={
|
||||
inventory?.summary_fields?.user_capabilities?.adhoc
|
||||
? [
|
||||
<AdHocCommands
|
||||
adHocItems={selected}
|
||||
hasListItems={count > 0}
|
||||
onLaunchLoading={setIsAdHocLaunchLoading}
|
||||
/>,
|
||||
]
|
||||
: []
|
||||
}
|
||||
/>
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Recent jobs`}</HeaderCell>
|
||||
<HeaderCell>{t`Inventory`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(host, index) => (
|
||||
<SmartInventoryHostListItem
|
||||
key={host.id}
|
||||
host={host}
|
||||
detailUrl={`/inventories/smart_inventory/${inventory.id}/hosts/${host.id}/details`}
|
||||
isSelected={selected.some((row) => row.id === host.id)}
|
||||
onSelect={() => handleSelect(host)}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -42,58 +42,56 @@ const PageControls = ({
|
||||
isFlatMode,
|
||||
isTemplateJob,
|
||||
}) => (
|
||||
<>
|
||||
<ControllsWrapper>
|
||||
<ExpandCollapseWrapper>
|
||||
{!isFlatMode && isTemplateJob && (
|
||||
<Button
|
||||
aria-label={
|
||||
isAllCollapsed ? t`Expand job events` : t`Collapse all job events`
|
||||
}
|
||||
variant="plain"
|
||||
type="button"
|
||||
onClick={toggleExpandCollapseAll}
|
||||
>
|
||||
{isAllCollapsed ? <AngleRightIcon /> : <AngleDownIcon />}
|
||||
</Button>
|
||||
)}
|
||||
</ExpandCollapseWrapper>
|
||||
<ScrollWrapper>
|
||||
<ControllsWrapper>
|
||||
<ExpandCollapseWrapper>
|
||||
{!isFlatMode && isTemplateJob && (
|
||||
<Button
|
||||
ouiaId="job-output-scroll-previous-button"
|
||||
aria-label={t`Scroll previous`}
|
||||
onClick={onScrollPrevious}
|
||||
aria-label={
|
||||
isAllCollapsed ? t`Expand job events` : t`Collapse all job events`
|
||||
}
|
||||
variant="plain"
|
||||
type="button"
|
||||
onClick={toggleExpandCollapseAll}
|
||||
>
|
||||
<AngleUpIcon />
|
||||
{isAllCollapsed ? <AngleRightIcon /> : <AngleDownIcon />}
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-next-button"
|
||||
aria-label={t`Scroll next`}
|
||||
onClick={onScrollNext}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDownIcon />
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-first-button"
|
||||
aria-label={t`Scroll first`}
|
||||
onClick={onScrollFirst}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDoubleUpIcon />
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-last-button"
|
||||
aria-label={t`Scroll last`}
|
||||
onClick={onScrollLast}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDoubleDownIcon />
|
||||
</Button>
|
||||
</ScrollWrapper>
|
||||
</ControllsWrapper>
|
||||
</>
|
||||
)}
|
||||
</ExpandCollapseWrapper>
|
||||
<ScrollWrapper>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-previous-button"
|
||||
aria-label={t`Scroll previous`}
|
||||
onClick={onScrollPrevious}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleUpIcon />
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-next-button"
|
||||
aria-label={t`Scroll next`}
|
||||
onClick={onScrollNext}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDownIcon />
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-first-button"
|
||||
aria-label={t`Scroll first`}
|
||||
onClick={onScrollFirst}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDoubleUpIcon />
|
||||
</Button>
|
||||
<Button
|
||||
ouiaId="job-output-scroll-last-button"
|
||||
aria-label={t`Scroll last`}
|
||||
onClick={onScrollLast}
|
||||
variant="plain"
|
||||
>
|
||||
<AngleDoubleDownIcon />
|
||||
</Button>
|
||||
</ScrollWrapper>
|
||||
</ControllsWrapper>
|
||||
);
|
||||
|
||||
export default PageControls;
|
||||
|
||||
@ -68,10 +68,12 @@ const OutputToolbar = ({ job, onDelete, isDeleteDisabled, jobStatus }) => {
|
||||
const taskCount = job?.playbook_counts?.task_count;
|
||||
const darkCount = job?.host_status_counts?.dark;
|
||||
const failureCount = job?.host_status_counts?.failures;
|
||||
const totalHostCount = Object.keys(job?.host_status_counts || {}).reduce(
|
||||
(sum, key) => sum + job?.host_status_counts[key],
|
||||
0
|
||||
);
|
||||
const totalHostCount = job?.host_status_counts
|
||||
? Object.keys(job.host_status_counts || {}).reduce(
|
||||
(sum, key) => sum + job.host_status_counts[key],
|
||||
0
|
||||
)
|
||||
: 0;
|
||||
const { me } = useConfig();
|
||||
|
||||
return (
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/destructuring-assignment */
|
||||
import { useState, useEffect, useReducer } from 'react';
|
||||
|
||||
const initialState = {
|
||||
|
||||
@ -9,6 +9,12 @@ import Job from './Job';
|
||||
import JobTypeRedirect from './JobTypeRedirect';
|
||||
import { JOB_TYPE_URL_SEGMENTS } from '../../constants';
|
||||
|
||||
function TypeRedirect({ view }) {
|
||||
const { id } = useParams();
|
||||
const { path } = useRouteMatch();
|
||||
return <JobTypeRedirect id={id} path={path} view={view} />;
|
||||
}
|
||||
|
||||
function Jobs() {
|
||||
const match = useRouteMatch();
|
||||
const [breadcrumbConfig, setBreadcrumbConfig] = useState({
|
||||
@ -29,12 +35,6 @@ function Jobs() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
function TypeRedirect({ view }) {
|
||||
const { id } = useParams();
|
||||
const { path } = useRouteMatch();
|
||||
return <JobTypeRedirect id={id} path={path} view={view} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ScreenHeader streamType="job" breadcrumbConfig={breadcrumbConfig} />
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { Redirect, withRouter } from 'react-router-dom';
|
||||
|
||||
@ -135,9 +136,9 @@ function AWXLogin({ alt, isAuthenticated }) {
|
||||
/>
|
||||
);
|
||||
|
||||
function setSessionRedirect() {
|
||||
const setSessionRedirect = () => {
|
||||
window.sessionStorage.setItem(SESSION_REDIRECT_URL, authRedirectTo);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Login header={Header} footer={Footer}>
|
||||
|
||||
@ -130,7 +130,7 @@ function ManagementJob({ setBreadcrumb }) {
|
||||
{error?.response?.status === 404 && (
|
||||
<span>
|
||||
{t`Management job not found.`}
|
||||
{''}
|
||||
|
||||
<Link to={basePath}>{t`View all management jobs`}</Link>
|
||||
</span>
|
||||
)}
|
||||
|
||||
@ -75,16 +75,14 @@ function ManagementJobListItem({
|
||||
{isSuperUser ? (
|
||||
<>
|
||||
{isPrompted ? (
|
||||
<>
|
||||
<LaunchManagementPrompt
|
||||
isOpen={isManagementPromptOpen}
|
||||
isLoading={isManagementPromptLoading}
|
||||
onClick={handleManagementPromptClick}
|
||||
onClose={handleManagementPromptClose}
|
||||
onConfirm={handleManagementPromptConfirm}
|
||||
defaultDays={30}
|
||||
/>
|
||||
</>
|
||||
<LaunchManagementPrompt
|
||||
isOpen={isManagementPromptOpen}
|
||||
isLoading={isManagementPromptLoading}
|
||||
onClick={handleManagementPromptClick}
|
||||
onClose={handleManagementPromptClose}
|
||||
onConfirm={handleManagementPromptConfirm}
|
||||
defaultDays={30}
|
||||
/>
|
||||
) : (
|
||||
<Tooltip content={t`Launch management job`} position="top">
|
||||
<Button
|
||||
|
||||
@ -120,7 +120,7 @@ function NotificationTemplateForm({
|
||||
|
||||
const messages = template.messages || { workflow_approval: {} };
|
||||
const defs = defaultMessages[template.notification_type || 'email'];
|
||||
const mergeDefaultMessages = (templ = {}, def) => ({
|
||||
const mergeDefaultMessages = (def, templ = {}) => ({
|
||||
message: templ?.message || def.message || '',
|
||||
body: templ?.body || def.body || '',
|
||||
});
|
||||
@ -140,32 +140,32 @@ function NotificationTemplateForm({
|
||||
},
|
||||
organization: template.summary_fields?.organization,
|
||||
messages: {
|
||||
started: { ...mergeDefaultMessages(messages.started, defs.started) },
|
||||
success: { ...mergeDefaultMessages(messages.success, defs.success) },
|
||||
error: { ...mergeDefaultMessages(messages.error, defs.error) },
|
||||
started: { ...mergeDefaultMessages(defs.started, messages.started) },
|
||||
success: { ...mergeDefaultMessages(defs.success, messages.success) },
|
||||
error: { ...mergeDefaultMessages(defs.error, messages.error) },
|
||||
workflow_approval: {
|
||||
approved: {
|
||||
...mergeDefaultMessages(
|
||||
messages.workflow_approval?.approved,
|
||||
defs.workflow_approval.approved
|
||||
defs.workflow_approval.approved,
|
||||
messages.workflow_approval?.approved
|
||||
),
|
||||
},
|
||||
denied: {
|
||||
...mergeDefaultMessages(
|
||||
messages.workflow_approval?.denied,
|
||||
defs.workflow_approval.denied
|
||||
defs.workflow_approval.denied,
|
||||
messages.workflow_approval?.denied
|
||||
),
|
||||
},
|
||||
running: {
|
||||
...mergeDefaultMessages(
|
||||
messages.workflow_approval?.running,
|
||||
defs.workflow_approval.running
|
||||
defs.workflow_approval.running,
|
||||
messages.workflow_approval?.running
|
||||
),
|
||||
},
|
||||
timed_out: {
|
||||
...mergeDefaultMessages(
|
||||
messages.workflow_approval?.timed_out,
|
||||
defs.workflow_approval.timed_out
|
||||
defs.workflow_approval.timed_out,
|
||||
messages.workflow_approval?.timed_out
|
||||
),
|
||||
},
|
||||
},
|
||||
|
||||
@ -69,57 +69,55 @@ function OrganizationExecEnvList({ organization }) {
|
||||
}, [fetchExecutionEnvironments]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading}
|
||||
items={executionEnvironments}
|
||||
itemCount={executionEnvironmentsCount}
|
||||
pluralizedItemName={t`Execution Environments`}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Image`,
|
||||
key: 'image__icontains',
|
||||
isDefault: false,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DatalistToolbar {...props} qsConfig={QS_CONFIG} />
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG} isSelectable={false}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell sortKey="image">{t`Image`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(executionEnvironment, index) => (
|
||||
<OrganizationExecEnvListItem
|
||||
key={executionEnvironment.id}
|
||||
executionEnvironment={executionEnvironment}
|
||||
detailUrl={`/execution_environments/${executionEnvironment.id}`}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
</>
|
||||
<Card>
|
||||
<PaginatedTable
|
||||
contentError={contentError}
|
||||
hasContentLoading={isLoading}
|
||||
items={executionEnvironments}
|
||||
itemCount={executionEnvironmentsCount}
|
||||
pluralizedItemName={t`Execution Environments`}
|
||||
qsConfig={QS_CONFIG}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
toolbarSearchColumns={[
|
||||
{
|
||||
name: t`Name`,
|
||||
key: 'name__icontains',
|
||||
isDefault: true,
|
||||
},
|
||||
{
|
||||
name: t`Image`,
|
||||
key: 'image__icontains',
|
||||
isDefault: false,
|
||||
},
|
||||
{
|
||||
name: t`Created By (Username)`,
|
||||
key: 'created_by__username__icontains',
|
||||
},
|
||||
{
|
||||
name: t`Modified By (Username)`,
|
||||
key: 'modified_by__username__icontains',
|
||||
},
|
||||
]}
|
||||
renderToolbar={(props) => (
|
||||
<DatalistToolbar {...props} qsConfig={QS_CONFIG} />
|
||||
)}
|
||||
headerRow={
|
||||
<HeaderRow qsConfig={QS_CONFIG} isSelectable={false}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell sortKey="image">{t`Image`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(executionEnvironment, index) => (
|
||||
<OrganizationExecEnvListItem
|
||||
key={executionEnvironment.id}
|
||||
executionEnvironment={executionEnvironment}
|
||||
detailUrl={`/execution_environments/${executionEnvironment.id}`}
|
||||
rowIndex={index}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -54,11 +54,11 @@ function SubscriptionModal({
|
||||
|
||||
const { selected, setSelected } = useSelected(subscriptions);
|
||||
|
||||
function handleConfirm() {
|
||||
const handleConfirm = () => {
|
||||
const [subscription] = selected;
|
||||
onConfirm(subscription);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchSubscriptions();
|
||||
@ -109,29 +109,27 @@ function SubscriptionModal({
|
||||
>
|
||||
{isLoading && <ContentLoading />}
|
||||
{!isLoading && error && (
|
||||
<>
|
||||
<EmptyState variant="full">
|
||||
<EmptyStateIcon icon={ExclamationTriangleIcon} />
|
||||
<Title size="lg" headingLevel="h3">
|
||||
<Trans>No subscriptions found</Trans>
|
||||
</Title>
|
||||
<EmptyStateBody>
|
||||
<Trans>
|
||||
We were unable to locate licenses associated with this account.
|
||||
</Trans>{' '}
|
||||
<Button
|
||||
aria-label={t`Close subscription modal`}
|
||||
onClick={onClose}
|
||||
variant="link"
|
||||
isInline
|
||||
ouiaId="subscription-modal-close"
|
||||
>
|
||||
<Trans>Return to subscription management.</Trans>
|
||||
</Button>
|
||||
</EmptyStateBody>
|
||||
<ErrorDetail error={error} />
|
||||
</EmptyState>
|
||||
</>
|
||||
<EmptyState variant="full">
|
||||
<EmptyStateIcon icon={ExclamationTriangleIcon} />
|
||||
<Title size="lg" headingLevel="h3">
|
||||
<Trans>No subscriptions found</Trans>
|
||||
</Title>
|
||||
<EmptyStateBody>
|
||||
<Trans>
|
||||
We were unable to locate licenses associated with this account.
|
||||
</Trans>{' '}
|
||||
<Button
|
||||
aria-label={t`Close subscription modal`}
|
||||
onClick={onClose}
|
||||
variant="link"
|
||||
isInline
|
||||
ouiaId="subscription-modal-close"
|
||||
>
|
||||
<Trans>Return to subscription management.</Trans>
|
||||
</Button>
|
||||
</EmptyStateBody>
|
||||
<ErrorDetail error={error} />
|
||||
</EmptyState>
|
||||
)}
|
||||
{!isLoading && !error && subscriptions?.length === 0 && (
|
||||
<ContentEmpty
|
||||
|
||||
@ -119,36 +119,34 @@ function SubscriptionStep() {
|
||||
labelIcon={
|
||||
<Popover
|
||||
content={
|
||||
<>
|
||||
<Trans>
|
||||
A subscription manifest is an export of a Red Hat
|
||||
Subscription. To generate a subscription manifest, go to{' '}
|
||||
<Button
|
||||
component="a"
|
||||
href="https://access.redhat.com/management/subscription_allocations"
|
||||
variant="link"
|
||||
target="_blank"
|
||||
isInline
|
||||
ouiaId="subscription-allocations-link"
|
||||
>
|
||||
access.redhat.com
|
||||
</Button>
|
||||
. For more information, see the{' '}
|
||||
<Button
|
||||
component="a"
|
||||
href={`${getDocsBaseUrl(
|
||||
config
|
||||
)}/html/userguide/import_license.html`}
|
||||
variant="link"
|
||||
target="_blank"
|
||||
ouiaId="import-license-link"
|
||||
isInline
|
||||
>
|
||||
User Guide
|
||||
</Button>
|
||||
.
|
||||
</Trans>
|
||||
</>
|
||||
<Trans>
|
||||
A subscription manifest is an export of a Red Hat
|
||||
Subscription. To generate a subscription manifest, go to{' '}
|
||||
<Button
|
||||
component="a"
|
||||
href="https://access.redhat.com/management/subscription_allocations"
|
||||
variant="link"
|
||||
target="_blank"
|
||||
isInline
|
||||
ouiaId="subscription-allocations-link"
|
||||
>
|
||||
access.redhat.com
|
||||
</Button>
|
||||
. For more information, see the{' '}
|
||||
<Button
|
||||
component="a"
|
||||
href={`${getDocsBaseUrl(
|
||||
config
|
||||
)}/html/userguide/import_license.html`}
|
||||
variant="link"
|
||||
target="_blank"
|
||||
ouiaId="import-license-link"
|
||||
isInline
|
||||
>
|
||||
User Guide
|
||||
</Button>
|
||||
.
|
||||
</Trans>
|
||||
}
|
||||
/>
|
||||
}
|
||||
|
||||
@ -33,10 +33,10 @@ function RevertButton({
|
||||
isMatch = true;
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
const handleConfirm = () => {
|
||||
helpers.setValue(isRevertable ? defaultValue : initialValue);
|
||||
onRevertCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const revertTooltipContent = isRevertable
|
||||
? t`Revert to factory default.`
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -9,7 +9,7 @@ function JobTemplateAdd() {
|
||||
const [formSubmitError, setFormSubmitError] = useState(null);
|
||||
const history = useHistory();
|
||||
|
||||
async function handleSubmit(values) {
|
||||
const handleSubmit = async (values) => {
|
||||
const {
|
||||
labels,
|
||||
instanceGroups,
|
||||
@ -35,7 +35,7 @@ function JobTemplateAdd() {
|
||||
execution_environment: values.execution_environment?.id,
|
||||
});
|
||||
await Promise.all([
|
||||
submitLabels(id, labels, values.project.summary_fields.organization.id),
|
||||
submitLabels(id, values.project.summary_fields.organization.id, labels),
|
||||
submitInstanceGroups(id, instanceGroups),
|
||||
submitCredentials(id, credentials),
|
||||
]);
|
||||
@ -43,9 +43,9 @@ function JobTemplateAdd() {
|
||||
} catch (error) {
|
||||
setFormSubmitError(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
async function submitLabels(templateId, labels = [], orgId) {
|
||||
async function submitLabels(templateId, orgId, labels = []) {
|
||||
if (!orgId) {
|
||||
// eslint-disable-next-line no-useless-catch
|
||||
try {
|
||||
@ -80,9 +80,9 @@ function JobTemplateAdd() {
|
||||
return Promise.all(associateCredentials);
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
const handleCancel = () => {
|
||||
history.push(`/templates`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
|
||||
@ -60,7 +60,7 @@ function JobTemplateEdit({ template, reloadTemplate }) {
|
||||
try {
|
||||
await JobTemplatesAPI.update(template.id, remainingValues);
|
||||
await Promise.all([
|
||||
submitLabels(labels, template?.organization),
|
||||
submitLabels(template?.organization, labels),
|
||||
submitCredentials(credentials),
|
||||
JobTemplatesAPI.orderInstanceGroups(
|
||||
template.id,
|
||||
@ -77,7 +77,7 @@ function JobTemplateEdit({ template, reloadTemplate }) {
|
||||
}
|
||||
};
|
||||
|
||||
const submitLabels = async (labels = [], orgId) => {
|
||||
const submitLabels = async (orgId, labels = []) => {
|
||||
const { added, removed } = getAddedAndRemoved(
|
||||
template.summary_fields.labels.results,
|
||||
labels
|
||||
|
||||
@ -36,14 +36,14 @@ function WorkflowJobTemplateAdd() {
|
||||
const {
|
||||
data: { id },
|
||||
} = await WorkflowJobTemplatesAPI.create(templatePayload);
|
||||
await Promise.all(await submitLabels(id, labels, organizationId));
|
||||
await Promise.all(await submitLabels(id, organizationId, labels));
|
||||
history.push(`/templates/workflow_job_template/${id}/visualizer`);
|
||||
} catch (err) {
|
||||
setFormSubmitError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const submitLabels = async (templateId, labels = [], organizationId) => {
|
||||
const submitLabels = async (templateId, organizationId, labels = []) => {
|
||||
if (!organizationId) {
|
||||
// eslint-disable-next-line no-useless-catch
|
||||
try {
|
||||
|
||||
@ -34,7 +34,7 @@ function WorkflowJobTemplateEdit({ template }) {
|
||||
organization?.id || inventory?.summary_fields?.organization.id || null;
|
||||
try {
|
||||
await Promise.all(
|
||||
await submitLabels(labels, formOrgId, template.organization)
|
||||
await submitLabels(formOrgId, template.organization, labels)
|
||||
);
|
||||
await WorkflowJobTemplatesAPI.update(template.id, templatePayload);
|
||||
history.push(`/templates/workflow_job_template/${template.id}/details`);
|
||||
@ -43,7 +43,7 @@ function WorkflowJobTemplateEdit({ template }) {
|
||||
}
|
||||
};
|
||||
|
||||
const submitLabels = async (labels = [], formOrgId, templateOrgId) => {
|
||||
const submitLabels = async (formOrgId, templateOrgId, labels = []) => {
|
||||
const { added, removed } = getAddedAndRemoved(
|
||||
template.summary_fields.labels.results,
|
||||
labels
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import 'styled-components/macro';
|
||||
import React, { useContext, useState, useEffect, useCallback } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
@ -118,11 +119,16 @@ function NodeModalForm({
|
||||
contentError || credentialError
|
||||
);
|
||||
|
||||
const nextButtonText = (activeStep) =>
|
||||
activeStep.id === promptSteps[promptSteps?.length - 1]?.id ||
|
||||
activeStep.name === 'Preview'
|
||||
function nextButtonText(activeStep) {
|
||||
let verifyPromptSteps = false;
|
||||
if (promptSteps.length) {
|
||||
verifyPromptSteps =
|
||||
activeStep.id === promptSteps[promptSteps.length - 1]?.id;
|
||||
}
|
||||
return verifyPromptSteps || activeStep.name === 'Preview'
|
||||
? t`Save`
|
||||
: t`Next`;
|
||||
}
|
||||
|
||||
const CustomFooter = (
|
||||
<WizardFooter>
|
||||
|
||||
@ -72,9 +72,14 @@ function NodeViewModal({ readOnly }) {
|
||||
fullUnifiedJobTemplate?.related?.webhook_receiver &&
|
||||
!fullUnifiedJobTemplate.webhook_key
|
||||
) {
|
||||
const {
|
||||
data: { webhook_key },
|
||||
} = await nodeAPI?.readWebhookKey(fullUnifiedJobTemplate.id);
|
||||
let webhook_key = null;
|
||||
if (nodeAPI) {
|
||||
const { data } = await nodeAPI.readWebhookKey(
|
||||
fullUnifiedJobTemplate.id
|
||||
);
|
||||
webhook_key = data.webhook_key;
|
||||
}
|
||||
|
||||
related.webhook_key = webhook_key;
|
||||
}
|
||||
|
||||
|
||||
@ -617,51 +617,49 @@ function JobTemplateForm({
|
||||
</FormFullWidthLayout>
|
||||
|
||||
{(allowCallbacks || enableWebhooks) && (
|
||||
<>
|
||||
<SubFormLayout>
|
||||
{allowCallbacks && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Provisioning Callback details`}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
{callbackUrl && (
|
||||
<FormGroup
|
||||
label={t`Provisioning Callback URL`}
|
||||
fieldId="template-callback-url"
|
||||
>
|
||||
<TextInput
|
||||
id="template-callback-url"
|
||||
isDisabled
|
||||
value={callbackUrl}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormField
|
||||
id="template-host-config-key"
|
||||
name="host_config_key"
|
||||
label={t`Host Config Key`}
|
||||
validate={allowCallbacks ? required(null) : null}
|
||||
isRequired={allowCallbacks}
|
||||
/>
|
||||
</FormColumnLayout>
|
||||
</>
|
||||
)}
|
||||
<SubFormLayout>
|
||||
{allowCallbacks && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Provisioning Callback details`}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
{callbackUrl && (
|
||||
<FormGroup
|
||||
label={t`Provisioning Callback URL`}
|
||||
fieldId="template-callback-url"
|
||||
>
|
||||
<TextInput
|
||||
id="template-callback-url"
|
||||
isDisabled
|
||||
value={callbackUrl}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
<FormField
|
||||
id="template-host-config-key"
|
||||
name="host_config_key"
|
||||
label={t`Host Config Key`}
|
||||
validate={allowCallbacks ? required(null) : null}
|
||||
isRequired={allowCallbacks}
|
||||
/>
|
||||
</FormColumnLayout>
|
||||
</>
|
||||
)}
|
||||
|
||||
{allowCallbacks && enableWebhooks && <br />}
|
||||
{allowCallbacks && enableWebhooks && <br />}
|
||||
|
||||
{enableWebhooks && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Webhook details`}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
<WebhookSubForm templateType={template.type} />
|
||||
</FormColumnLayout>
|
||||
</>
|
||||
)}
|
||||
</SubFormLayout>
|
||||
</>
|
||||
{enableWebhooks && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Webhook details`}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
<WebhookSubForm templateType={template.type} />
|
||||
</FormColumnLayout>
|
||||
</>
|
||||
)}
|
||||
</SubFormLayout>
|
||||
)}
|
||||
</FormColumnLayout>
|
||||
</FormFullWidthLayout>
|
||||
|
||||
@ -50,12 +50,8 @@ function UserListItem({ user, isSelected, onSelect, detailUrl, rowIndex }) {
|
||||
</span>
|
||||
)}
|
||||
</TdBreakWord>
|
||||
<Td dataLabel={t`First Name`}>
|
||||
{user.first_name && <>{user.first_name}</>}
|
||||
</Td>
|
||||
<Td dataLabel={t`Last Name`}>
|
||||
{user.last_name && <>{user.last_name}</>}
|
||||
</Td>
|
||||
{user.first_name && <Td dataLabel={t`First Name`}>{user.first_name}</Td>}
|
||||
{user.last_name && <Td dataLabel={t`Last Name`}>{user.last_name}</Td>}
|
||||
<Td dataLabel={t`Role`}>{user_type}</Td>
|
||||
<ActionsTd dataLabel={t`Actions`}>
|
||||
<ActionItem
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
22
docs/licenses/ui/babel-helper-environment-visitor.txt
Normal file
22
docs/licenses/ui/babel-helper-environment-visitor.txt
Normal file
@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
22
docs/licenses/ui/babel-helper-hoist-variables.txt
Normal file
22
docs/licenses/ui/babel-helper-hoist-variables.txt
Normal file
@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2020 Kent C. Dodds
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,7 +0,0 @@
|
||||
Copyright © Jorge Bucaran <<https://jorgebucaran.com>>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,22 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 David Clark
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 JD Ballard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@ -1,20 +0,0 @@
|
||||
Copyright (c) 2013 Raynos.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
Copyright (c) 2013 Thiago de Arruda
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 JD Ballard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Dave Justice
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,25 +0,0 @@
|
||||
Copyright 2017 Kat Marchán
|
||||
Copyright npm, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
This library is a fork of 'better-json-errors' by Kat Marchán, extended and
|
||||
distributed under the terms of the MIT license above.
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Brian Donovan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Javier Blanco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
15
docs/licenses/ui/picocolors.txt
Normal file
15
docs/licenses/ui/picocolors.txt
Normal file
@ -0,0 +1,15 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2021 Alexey Raspopov, Kostiantyn Denysov, Anton Verinov
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2012 James Halliday
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
28
docs/licenses/ui/source-map-js.txt
Normal file
28
docs/licenses/ui/source-map-js.txt
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
Copyright (c) 2009-2011, Mozilla Foundation and contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the Mozilla Foundation nor the names of project
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -1,9 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,13 +0,0 @@
|
||||
Copyright 2018 Eemeli Aro <eemeli@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
Loading…
x
Reference in New Issue
Block a user