Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"homepage": "/dashboard",
"dependencies": {
"@devtron-labs/devtron-fe-common-lib": "1.20.6-pre-51",
"@devtron-labs/devtron-fe-common-lib": "1.20.6-pre-53",
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rjsf/core": "^5.13.3",
"@rjsf/utils": "^5.13.3",
Expand All @@ -23,7 +23,6 @@
"moment": "^2.29.4",
"query-string": "^7.1.1",
"react": "^17.0.2",
"react-dates": "^21.8.0",
"react-dom": "^17.0.2",
"react-ga4": "^1.4.1",
"react-gtm-module": "^2.0.11",
Expand Down Expand Up @@ -74,7 +73,6 @@
"@types/jest": "^27.4.1",
"@types/node": "20.11.0",
"@types/react": "17.0.39",
"@types/react-dates": "^21.8.6",
"@types/react-dom": "17.0.13",
"@types/react-router-dom": "^5.3.3",
"@types/react-transition-group": "^4.4.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ import {
ButtonStyleType,
ButtonVariantType,
ComponentSizeType,
DATE_TIME_FORMATS,
FeatureTitleWithInfo,
GenericFilterEmptyState,
} from '@devtron-labs/devtron-fe-common-lib'

import { ReactComponent as Trash } from '../../../../assets/icons/ic-delete-interactive.svg'
import { ReactComponent as Key } from '../../../../assets/icons/ic-key-bulb.svg'
import { ReactComponent as Edit } from '../../../../assets/icons/ic-pencil.svg'
import { HEADER_TEXT, MomentDateFormat } from '../../../../config'
import { HEADER_TEXT } from '../../../../config'
import { APITokenListType, TokenListType } from './apiToken.type'
import { isTokenExpired } from './apiToken.utils'
import DeleteAPITokenModal from './DeleteAPITokenModal'
Expand Down Expand Up @@ -126,7 +127,9 @@ const APITokenList = ({ tokenList, renderSearchToken, reload }: APITokenListType
</div>
<div className="dc__ellipsis-right">
{list.lastUsedAt
? moment(list.lastUsedAt).format(MomentDateFormat)
? moment(list.lastUsedAt).format(
DATE_TIME_FORMATS.WEEKDAY_WITH_DATE_MONTH_AND_YEAR,
)
: 'Never used'}
</div>
<div>{list.lastUsedByIp ? list.lastUsedByIp : '-'}</div>
Expand All @@ -136,7 +139,7 @@ const APITokenList = ({ tokenList, renderSearchToken, reload }: APITokenListType
) : (
<>
{isTokenExpired(list.expireAtInMs) ? 'Expired on ' : ''}
{moment(list.expireAtInMs).format(MomentDateFormat)}
{moment(list.expireAtInMs).format(DATE_TIME_FORMATS.TWELVE_HOURS_FORMAT)}
</>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import APITokenList from './APITokenList'
import CreateAPIToken from './CreateAPIToken'
import EditAPIToken from './EditAPIToken'
import { getGeneratedAPITokenList } from './service'
import { ExpirationDateSelectOptionType } from './types'

import './apiToken.scss'

Expand All @@ -48,7 +49,7 @@ const ApiTokens = () => {
const [errorStatusCode, setErrorStatusCode] = useState(0)
const [showGenerateModal, setShowGenerateModal] = useState(false)
const [showRegenerateTokenModal, setShowRegenerateTokenModal] = useState(false)
const [selectedExpirationDate, setSelectedExpirationDate] = useState<{ label: string; value: number }>({
const [selectedExpirationDate, setSelectedExpirationDate] = useState<ExpirationDateSelectOptionType>({
label: '30 days',
value: 30,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import { useEffect, useState } from 'react'
import { useHistory, useRouteMatch } from 'react-router-dom'
import { Moment } from 'moment'
import dayjs from 'dayjs'

import {
CustomInput,
Expand Down Expand Up @@ -49,6 +49,7 @@ import ExpirationDate from './ExpirationDate'
import GenerateActionButton from './GenerateActionButton'
import GenerateModal from './GenerateModal'
import { createGeneratedAPIToken } from './service'
import { ExpirationDateSelectOptionType } from './types'
import { ValidationRules } from './validationRules'

const showStatus = !!importComponentFromFELibrary('StatusHeaderCell', null, 'function')
Expand Down Expand Up @@ -103,7 +104,7 @@ const CreateAPIToken = ({
isSaveDisabled,
allowManageAllAccess,
} = usePermissionConfiguration()
const [customDate, setCustomDate] = useState<Moment>(null)
const [customDate, setCustomDate] = useState<Date>(dayjs().add(1, 'day').toDate())
const [tokenResponse, setTokenResponse] = useState<TokenResponseType>({
success: false,
token: '',
Expand Down Expand Up @@ -147,11 +148,11 @@ const CreateAPIToken = ({
}
}

const onCustomDateChange = (event) => {
setCustomDate(event)
const onCustomDateChange = (date: Date) => {
setCustomDate(date)
setFormData({
...formData,
expireAtInMs: event.valueOf(),
expireAtInMs: date.valueOf(),
dateType: 'Custom',
})

Expand All @@ -167,12 +168,15 @@ const CreateAPIToken = ({
history.push(`${match.path.split('create')[0]}list`)
}

const onChangeSelectFormData = (selectedOption: { label: string; value: number }) => {
const onChangeSelectFormData = (selectedOption: ExpirationDateSelectOptionType) => {
setSelectedExpirationDate(selectedOption)
const parsedMilliseconds = selectedOption.value === 0 ? 0 : getDateInMilliseconds(selectedOption.value)

setFormData({
...formData,
expireAtInMs: selectedOption.value === 0 ? 0 : getDateInMilliseconds(selectedOption.value),
dateType: selectedOption.label,
expireAtInMs:
typeof selectedOption.value === 'number' ? parsedMilliseconds : selectedOption.value.valueOf(),
dateType: selectedOption.label as string,
})
}

Expand Down Expand Up @@ -283,7 +287,7 @@ const CreateAPIToken = ({
placeholder="Enter a description to remember where you have used this token"
error={formDataErrorObj.invalidDescription && formDataErrorObj.invalidDescriptionMessage}
/>
<label className="form__row">
<div className="form__row">
<div className="flex left">
<ExpirationDate
selectedExpirationDate={selectedExpirationDate}
Expand All @@ -299,7 +303,7 @@ const CreateAPIToken = ({
Custom expiration can't be blank. Please select a date.
</span>
)}
</label>
</div>
<div className="dc__border-top" />
<PermissionConfigurationForm showUserPermissionGroupSelector isAddMode />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import React, { useEffect, useMemo, useState } from 'react'
import { useHistory, useParams, useRouteMatch } from 'react-router-dom'
import dayjs from 'dayjs'
import moment from 'moment'

import {
Expand All @@ -26,6 +27,7 @@ import {
ButtonVariantType,
ClipboardButton,
CustomInput,
DATE_TIME_FORMATS,
ErrorScreenManager,
Icon,
InfoBlock,
Expand All @@ -39,7 +41,6 @@ import {
} from '@devtron-labs/devtron-fe-common-lib'

import { importComponentFromFELibrary } from '../../../../components/common'
import { MomentDateFormat } from '../../../../config'
import { API_COMPONENTS } from '../../../../config/constantMessaging'
import { createOrUpdateUser, getUserById } from '../authorization.service'
import { getDefaultUserStatusAndTimeout } from '../libUtils'
Expand Down Expand Up @@ -89,7 +90,7 @@ const EditAPIToken = ({
const { serverMode } = useMainContext()
const [loader, setLoader] = useState(false)

const [customDate, setCustomDate] = useState<number>(undefined)
const [customDate, setCustomDate] = useState<Date>(dayjs().add(1, 'day').toDate())
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false)
const [invalidDescription, setInvalidDescription] = useState(false)

Expand Down Expand Up @@ -177,7 +178,7 @@ const EditAPIToken = ({
return (
<span className="fw-6 cn-9">
This token {isTokenExpired(editData.expireAtInMs) ? 'expired' : 'expires'} on&nbsp;
{moment(editData.expireAtInMs).format(MomentDateFormat)}.
{moment(editData.expireAtInMs).format(DATE_TIME_FORMATS.TWELVE_HOURS_FORMAT)}.
</span>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,56 @@
/* eslint-disable react/prop-types */
import moment from 'moment'

import { InfoBlock, SelectPicker } from '@devtron-labs/devtron-fe-common-lib'
import {
ComponentSizeType,
DATE_TIME_FORMATS,
DateTimePicker,
InfoBlock,
SelectPicker,
} from '@devtron-labs/devtron-fe-common-lib'

import { SingleDatePickerComponent } from '../../../../components/common'
import { MomentDateFormat } from '../../../../config'
import { getDateInMilliseconds, getOptions } from './apiToken.utils'
import { ExpirationDateProps } from './types'

const ExpirationDate = ({ selectedExpirationDate, onChangeSelectFormData, handleDatesChange, customDate }) => (
const ExpirationDate = ({
selectedExpirationDate,
onChangeSelectFormData,
handleDatesChange,
customDate,
}: ExpirationDateProps) => (
<div className="w-100">
<div className="flex left bottom dc__gap-16">
<div className="w-200">
<SelectPicker
<SelectPicker<number | Date, false>
label="Expiration"
required
inputId="token-expiry-duration"
value={selectedExpirationDate}
options={getOptions(customDate)}
classNamePrefix="select-token-expiry-duration"
onChange={onChangeSelectFormData}
size={ComponentSizeType.large}
/>
</div>

{selectedExpirationDate.label !== 'Custom' && selectedExpirationDate.label !== 'No expiration' && (
<span className="fs-13 fw-4 cn-9">
<span>This token will expire on</span>&nbsp;
{moment(getDateInMilliseconds(selectedExpirationDate.value)).format(MomentDateFormat)}
{moment(getDateInMilliseconds(selectedExpirationDate.value)).format(
DATE_TIME_FORMATS.DD_MMM_YYYY_HH_MM,
)}
</span>
)}
{selectedExpirationDate.label === 'No expiration' && (
<span className="ml-16 fs-13 fw-4 cn-9">The token will never expire!</span>
)}
{selectedExpirationDate.label === 'Custom' && (
<div className="w-200 ml-16">
<SingleDatePickerComponent
date={customDate}
handleDatesChange={handleDatesChange}
readOnly
isTodayBlocked
/>
</div>
<DateTimePicker
id="expiration-date-picker"
date={customDate}
onChange={handleDatesChange}
isTodayBlocked
/>
)}
</div>
{selectedExpirationDate.label === 'No expiration' && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ExpirationDate from './ExpirationDate'
import GenerateActionButton from './GenerateActionButton'
import GenerateModal from './GenerateModal'
import { updateGeneratedAPIToken } from './service'
import { ExpirationDateProps, ExpirationDateSelectOptionType } from './types'

const RegeneratedModal = ({
close,
Expand All @@ -38,7 +39,7 @@ const RegeneratedModal = ({
}: RegenerateModalType) => {
const [loader, setLoader] = useState(false)
const [showGenerateModal, setShowGenerateModal] = useState(false)
const [selectedExpirationDate, setSelectedExpirationDate] = useState<{ label: string; value: number }>({
const [selectedExpirationDate, setSelectedExpirationDate] = useState<ExpirationDateSelectOptionType>({
label: '30 days',
value: 30,
})
Expand All @@ -48,18 +49,22 @@ const RegeneratedModal = ({
)
const [invalidCustomDate, setInvalidCustomDate] = useState(false)

const onChangeSelectFormData = (selectedOption: { label: string; value: number }) => {
setRegeneratedExpireAtInMs(selectedOption.value === 0 ? 0 : getDateInMilliseconds(selectedOption.value))
const onChangeSelectFormData: ExpirationDateProps['onChangeSelectFormData'] = (selectedOption) => {
const parsedMilliseconds = selectedOption.value === 0 ? 0 : getDateInMilliseconds(selectedOption.value)

setRegeneratedExpireAtInMs(
typeof selectedOption.value === 'number' ? parsedMilliseconds : selectedOption.value.valueOf(),
)
setSelectedExpirationDate(selectedOption)

if (selectedOption.label === 'Custom' && invalidCustomDate) {
setInvalidCustomDate(false)
}
}

const handleDatesChange = (event): void => {
setCustomDate(event)
setRegeneratedExpireAtInMs(event.valueOf())
const handleDatesChange = (date: Date): void => {
setCustomDate(date)
setRegeneratedExpireAtInMs(date.valueOf())

if (invalidCustomDate) {
setInvalidCustomDate(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import React from 'react'

import { GenericModalProps } from '@devtron-labs/devtron-fe-common-lib'

import { ExpirationDateSelectOptionType } from './types'

export interface FormType {
name: string
description: string
Expand All @@ -36,8 +38,8 @@ export interface GenerateTokenType {
showGenerateModal: boolean
setShowGenerateModal: React.Dispatch<React.SetStateAction<boolean>>
handleGenerateTokenActionButton: () => void
setSelectedExpirationDate
selectedExpirationDate
setSelectedExpirationDate: React.Dispatch<React.SetStateAction<ExpirationDateSelectOptionType>>
selectedExpirationDate: ExpirationDateSelectOptionType
reload: () => void
}

Expand Down Expand Up @@ -95,8 +97,8 @@ export interface RegenerateModalType {
close: () => void
setShowRegeneratedModal: React.Dispatch<React.SetStateAction<boolean>>
editData: EditDataType
customDate: number
setCustomDate: React.Dispatch<React.SetStateAction<number>>
customDate: Date
setCustomDate: React.Dispatch<React.SetStateAction<Date>>
reload: () => void
redirectToTokenList: () => void
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
* limitations under the License.
*/

import { SelectPickerOptionType } from '@devtron-labs/devtron-fe-common-lib'

import { TokenListType } from './apiToken.type'

export function getOptions(customDate) {
return [
{ value: 7, label: '7 days' },
{ value: 30, label: '30 days' },
{ value: 60, label: '60 days' },
{ value: 90, label: '90 days' },
{ value: customDate, label: 'Custom' },
{ value: 0, label: 'No expiration' },
]
}
export const getOptions = (customDate: Date): SelectPickerOptionType<number | Date>[] => [
{ value: 7, label: '7 days' },
{ value: 30, label: '30 days' },
{ value: 60, label: '60 days' },
{ value: 90, label: '90 days' },
{ value: customDate, label: 'Custom' },
{ value: 0, label: 'No expiration' },
]

const millisecondsInDay = 86400000

Expand Down
10 changes: 10 additions & 0 deletions src/Pages/GlobalConfigurations/Authorization/APITokens/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SelectPickerOptionType } from '@devtron-labs/devtron-fe-common-lib'

export type ExpirationDateSelectOptionType = SelectPickerOptionType<number | Date>

export interface ExpirationDateProps {
selectedExpirationDate: ExpirationDateSelectOptionType
onChangeSelectFormData: (value: ExpirationDateSelectOptionType) => void
handleDatesChange: (date: Date) => void
customDate: Date
}
Loading