mirror of
https://github.com/harness/drone.git
synced 2025-05-11 14:40:05 +08:00
feat: [CODE-615]: Show Token after Creation (#233)
This commit is contained in:
parent
c24d2d1795
commit
ef9a0f28d4
@ -216,6 +216,7 @@ export const FormInputWithCopyButton: React.FC<
|
|||||||
return (
|
return (
|
||||||
<FormInput.Text
|
<FormInput.Text
|
||||||
{...props}
|
{...props}
|
||||||
|
className={css.inputWrapper}
|
||||||
inputGroup={{
|
inputGroup={{
|
||||||
...props.inputGroup,
|
...props.inputGroup,
|
||||||
rightElement: (
|
rightElement: (
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
.dialogCtn {
|
.dialogCtn {
|
||||||
overflow: unset !important;
|
overflow: unset !important;
|
||||||
|
|
||||||
button#copyBtn {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-left: 1px solid var(--grey-200) !important;
|
|
||||||
margin-left: var(--spacing-small) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global {
|
:global {
|
||||||
.bp3-form-group,
|
.bp3-form-group,
|
||||||
.TextInput--main {
|
.TextInput--main {
|
||||||
@ -45,3 +39,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputWrapper {
|
||||||
|
button#copyBtn {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-left: 1px solid var(--grey-200) !important;
|
||||||
|
margin-left: var(--spacing-small) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
// this is an auto-generated file
|
// this is an auto-generated file
|
||||||
declare const styles: {
|
declare const styles: {
|
||||||
readonly dialogCtn: string
|
readonly dialogCtn: string
|
||||||
readonly copyBtn: string
|
|
||||||
readonly passwordCtn: string
|
readonly passwordCtn: string
|
||||||
readonly layout: string
|
readonly layout: string
|
||||||
readonly text: string
|
readonly text: string
|
||||||
readonly formikForm: string
|
readonly formikForm: string
|
||||||
|
readonly inputWrapper: string
|
||||||
|
readonly copyBtn: string
|
||||||
}
|
}
|
||||||
export default styles
|
export default styles
|
||||||
|
@ -218,6 +218,7 @@ export interface StringsMap {
|
|||||||
'newToken.generateToken': string
|
'newToken.generateToken': string
|
||||||
'newToken.namePlaceholder': string
|
'newToken.namePlaceholder': string
|
||||||
'newToken.text': string
|
'newToken.text': string
|
||||||
|
'newToken.tokenHelptext': string
|
||||||
'newUserModal.displayNamePlaceholder': string
|
'newUserModal.displayNamePlaceholder': string
|
||||||
'newUserModal.emailPlaceholder': string
|
'newUserModal.emailPlaceholder': string
|
||||||
'newUserModal.passwordHelptext': string
|
'newUserModal.passwordHelptext': string
|
||||||
|
@ -518,6 +518,9 @@ newToken:
|
|||||||
namePlaceholder: Enter the name
|
namePlaceholder: Enter the name
|
||||||
expireOn: Token will expire on {{date}}
|
expireOn: Token will expire on {{date}}
|
||||||
generateToken: Generate Token
|
generateToken: Generate Token
|
||||||
|
tokenHelptext:
|
||||||
|
Your token has been generated. Please make sure to copy and store your token somewhere safe, you wont be
|
||||||
|
able to see it again.
|
||||||
deleteToken: Delete token
|
deleteToken: Delete token
|
||||||
deleteTokenMsg: Token deleted successfully
|
deleteTokenMsg: Token deleted successfully
|
||||||
userProfile:
|
userProfile:
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import React, { useMemo } from 'react'
|
import React, { useMemo, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonVariation,
|
ButtonVariation,
|
||||||
Color,
|
Color,
|
||||||
|
Container,
|
||||||
Dialog,
|
Dialog,
|
||||||
|
FlexExpander,
|
||||||
FontVariation,
|
FontVariation,
|
||||||
FormikForm,
|
FormikForm,
|
||||||
FormInput,
|
FormInput,
|
||||||
@ -15,15 +17,23 @@ import { Formik } from 'formik'
|
|||||||
import { useMutate } from 'restful-react'
|
import { useMutate } from 'restful-react'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
|
import { Else, Match, Render, Truthy } from 'react-jsx-match'
|
||||||
import { REGEX_VALID_REPO_NAME } from 'utils/Utils'
|
|
||||||
|
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { REGEX_VALID_REPO_NAME } from 'utils/Utils'
|
||||||
|
import { CodeIcon } from 'utils/GitUtils'
|
||||||
|
import { CopyButton } from 'components/CopyButton/CopyButton'
|
||||||
|
import { FormInputWithCopyButton } from 'components/UserManagementFlows/AddUserModal'
|
||||||
|
|
||||||
|
import css from 'components/CloneCredentialDialog/CloneCredentialDialog.module.scss'
|
||||||
|
|
||||||
const useNewToken = ({ onClose }: { onClose: () => void }) => {
|
const useNewToken = ({ onClose }: { onClose: () => void }) => {
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const { mutate } = useMutate({ path: '/api/v1/user/tokens', verb: 'POST' })
|
const { mutate } = useMutate({ path: '/api/v1/user/tokens', verb: 'POST' })
|
||||||
|
|
||||||
|
const [generatedToken, setGeneratedToken] = useState<string>()
|
||||||
|
const isTokenGenerated = Boolean(generatedToken)
|
||||||
|
|
||||||
const lifeTimeOptions = useMemo(
|
const lifeTimeOptions = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ label: getString('nDays', { number: 7 }), value: 604800000000000 },
|
{ label: getString('nDays', { number: 7 }), value: 604800000000000 },
|
||||||
@ -34,9 +44,15 @@ const useNewToken = ({ onClose }: { onClose: () => void }) => {
|
|||||||
[getString]
|
[getString]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const onModalClose = () => {
|
||||||
|
hideModal()
|
||||||
|
onClose()
|
||||||
|
setGeneratedToken()
|
||||||
|
}
|
||||||
|
|
||||||
const [openModal, hideModal] = useModalHook(() => {
|
const [openModal, hideModal] = useModalHook(() => {
|
||||||
return (
|
return (
|
||||||
<Dialog isOpen enforceFocus={false} onClose={hideModal} title={getString('createNewToken')}>
|
<Dialog isOpen enforceFocus={false} onClose={onModalClose} title={getString('createNewToken')}>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
uid: '',
|
uid: '',
|
||||||
@ -49,9 +65,8 @@ const useNewToken = ({ onClose }: { onClose: () => void }) => {
|
|||||||
lifeTime: Yup.number().required(getString('validation.expirationDateRequired'))
|
lifeTime: Yup.number().required(getString('validation.expirationDateRequired'))
|
||||||
})}
|
})}
|
||||||
onSubmit={async values => {
|
onSubmit={async values => {
|
||||||
await mutate(values)
|
const res = await mutate(values)
|
||||||
hideModal()
|
setGeneratedToken(res?.access_token)
|
||||||
onClose()
|
|
||||||
}}>
|
}}>
|
||||||
{formikProps => {
|
{formikProps => {
|
||||||
const expiresAtString = moment(Date.now() + formikProps.values.lifeTime / 1000000).format(
|
const expiresAtString = moment(Date.now() + formikProps.values.lifeTime / 1000000).format(
|
||||||
@ -60,32 +75,69 @@ const useNewToken = ({ onClose }: { onClose: () => void }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormikForm>
|
<FormikForm>
|
||||||
<FormInput.Text
|
<FormInputWithCopyButton
|
||||||
name="uid"
|
name="uid"
|
||||||
label={getString('name')}
|
label={getString('name')}
|
||||||
placeholder={getString('newToken.namePlaceholder')}
|
placeholder={getString('newToken.namePlaceholder')}
|
||||||
|
disabled={isTokenGenerated}
|
||||||
|
/>
|
||||||
|
<FormInput.Select
|
||||||
|
name="lifeTime"
|
||||||
|
label={getString('expiration')}
|
||||||
|
items={lifeTimeOptions}
|
||||||
|
usePortal
|
||||||
|
disabled={isTokenGenerated}
|
||||||
/>
|
/>
|
||||||
<FormInput.Select name="lifeTime" label={getString('expiration')} items={lifeTimeOptions} usePortal />
|
|
||||||
{formikProps.values.lifeTime ? (
|
{formikProps.values.lifeTime ? (
|
||||||
<Text font={{ variation: FontVariation.SMALL_SEMI }} color={Color.GREY_400}>
|
<Text
|
||||||
|
font={{ variation: FontVariation.SMALL_SEMI }}
|
||||||
|
color={Color.GREY_400}
|
||||||
|
margin={{ bottom: 'medium' }}>
|
||||||
{getString('newToken.expireOn', { date: expiresAtString })}
|
{getString('newToken.expireOn', { date: expiresAtString })}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Layout.Horizontal margin={{ top: 'xxxlarge' }} spacing="medium">
|
<Render when={isTokenGenerated}>
|
||||||
<Button
|
<Text padding={{ bottom: 'small' }} font={{ variation: FontVariation.FORM_LABEL, size: 'small' }}>
|
||||||
text={getString('newToken.generateToken')}
|
{getString('token')}
|
||||||
type="submit"
|
</Text>
|
||||||
variation={ButtonVariation.PRIMARY}
|
<Container padding={{ bottom: 'medium' }}>
|
||||||
/>
|
<Layout.Horizontal className={css.layout}>
|
||||||
<Button text={getString('cancel')} onClick={hideModal} variation={ButtonVariation.TERTIARY} />
|
<Text className={css.url}>{generatedToken}</Text>
|
||||||
</Layout.Horizontal>
|
<FlexExpander />
|
||||||
|
<CopyButton
|
||||||
|
content={generatedToken || ''}
|
||||||
|
id={css.cloneCopyButton}
|
||||||
|
icon={CodeIcon.Copy}
|
||||||
|
iconProps={{ size: 14 }}
|
||||||
|
/>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Container>
|
||||||
|
<Text padding={{ bottom: 'medium' }} font={{ variation: FontVariation.BODY2_SEMI, size: 'small' }}>
|
||||||
|
{getString('newToken.tokenHelptext')}
|
||||||
|
</Text>
|
||||||
|
</Render>
|
||||||
|
<Match expr={isTokenGenerated}>
|
||||||
|
<Truthy>
|
||||||
|
<Button text={getString('close')} variation={ButtonVariation.TERTIARY} onClick={onModalClose} />
|
||||||
|
</Truthy>
|
||||||
|
<Else>
|
||||||
|
<Layout.Horizontal margin={{ top: 'xxxlarge' }} spacing="medium">
|
||||||
|
<Button
|
||||||
|
text={getString('newToken.generateToken')}
|
||||||
|
type="submit"
|
||||||
|
variation={ButtonVariation.PRIMARY}
|
||||||
|
/>
|
||||||
|
<Button text={getString('cancel')} onClick={hideModal} variation={ButtonVariation.TERTIARY} />
|
||||||
|
</Layout.Horizontal>
|
||||||
|
</Else>
|
||||||
|
</Match>
|
||||||
</FormikForm>
|
</FormikForm>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</Formik>
|
</Formik>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
}, [])
|
}, [generatedToken])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
openModal,
|
openModal,
|
||||||
|
Loading…
Reference in New Issue
Block a user