openvsx-webui-test 0.20.0-dev.0 → 0.20.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/lib/components/error-dialog.d.ts.map +1 -1
  2. package/lib/components/error-dialog.js +3 -5
  3. package/lib/components/error-dialog.js.map +1 -1
  4. package/lib/components/generate-token-dialog.d.ts +22 -0
  5. package/lib/components/generate-token-dialog.d.ts.map +1 -0
  6. package/lib/components/generate-token-dialog.js +91 -0
  7. package/lib/components/generate-token-dialog.js.map +1 -0
  8. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.d.ts.map +1 -1
  9. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.js +14 -11
  10. package/lib/components/rate-limiting/usage-stats/usage-stats-chart.js.map +1 -1
  11. package/lib/components/timestamp.d.ts +1 -0
  12. package/lib/components/timestamp.d.ts.map +1 -1
  13. package/lib/components/timestamp.js +2 -1
  14. package/lib/components/timestamp.js.map +1 -1
  15. package/lib/default/menu-content.d.ts +1 -1
  16. package/lib/extension-registry-service.d.ts +7 -1
  17. package/lib/extension-registry-service.d.ts.map +1 -1
  18. package/lib/extension-registry-service.js +41 -0
  19. package/lib/extension-registry-service.js.map +1 -1
  20. package/lib/extension-registry-types.d.ts +6 -0
  21. package/lib/extension-registry-types.d.ts.map +1 -1
  22. package/lib/pages/admin-dashboard/admin-dashboard.d.ts.map +1 -1
  23. package/lib/pages/admin-dashboard/admin-dashboard.js +17 -27
  24. package/lib/pages/admin-dashboard/admin-dashboard.js.map +1 -1
  25. package/lib/pages/admin-dashboard/customers/customer-details.d.ts.map +1 -1
  26. package/lib/pages/admin-dashboard/customers/customer-details.js +2 -1
  27. package/lib/pages/admin-dashboard/customers/customer-details.js.map +1 -1
  28. package/lib/pages/admin-dashboard/customers/customer-token-list.d.ts +19 -0
  29. package/lib/pages/admin-dashboard/customers/customer-token-list.d.ts.map +1 -0
  30. package/lib/pages/admin-dashboard/customers/customer-token-list.js +70 -0
  31. package/lib/pages/admin-dashboard/customers/customer-token-list.js.map +1 -0
  32. package/lib/pages/user/{generate-token-dialog.d.ts → generate-access-token-dialog.d.ts} +2 -2
  33. package/lib/pages/user/generate-access-token-dialog.d.ts.map +1 -0
  34. package/lib/pages/user/generate-access-token-dialog.js +33 -0
  35. package/lib/pages/user/generate-access-token-dialog.js.map +1 -0
  36. package/lib/pages/user/user-settings-tokens.js +3 -3
  37. package/lib/pages/user/user-settings-tokens.js.map +1 -1
  38. package/lib/utils.d.ts +1 -1
  39. package/lib/utils.d.ts.map +1 -1
  40. package/lib/utils.js +10 -5
  41. package/lib/utils.js.map +1 -1
  42. package/package.json +6 -6
  43. package/src/components/error-dialog.tsx +3 -5
  44. package/src/components/generate-token-dialog.tsx +167 -0
  45. package/src/components/rate-limiting/usage-stats/usage-stats-chart.tsx +18 -12
  46. package/src/components/timestamp.tsx +3 -1
  47. package/src/extension-registry-service.ts +49 -1
  48. package/src/extension-registry-types.ts +7 -0
  49. package/src/pages/admin-dashboard/admin-dashboard.tsx +17 -27
  50. package/src/pages/admin-dashboard/customers/customer-details.tsx +4 -0
  51. package/src/pages/admin-dashboard/customers/customer-token-list.tsx +135 -0
  52. package/src/pages/user/generate-access-token-dialog.tsx +49 -0
  53. package/src/pages/user/user-settings-tokens.tsx +3 -3
  54. package/src/utils.ts +9 -5
  55. package/lib/components/copy-to-clipboard.d.ts +0 -21
  56. package/lib/components/copy-to-clipboard.d.ts.map +0 -1
  57. package/lib/components/copy-to-clipboard.js +0 -25
  58. package/lib/components/copy-to-clipboard.js.map +0 -1
  59. package/lib/pages/user/generate-token-dialog.d.ts.map +0 -1
  60. package/lib/pages/user/generate-token-dialog.js +0 -79
  61. package/lib/pages/user/generate-token-dialog.js.map +0 -1
  62. package/src/components/copy-to-clipboard.tsx +0 -50
  63. package/src/pages/user/generate-token-dialog.tsx +0 -157
@@ -0,0 +1,135 @@
1
+ /******************************************************************************
2
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
3
+ *
4
+ * See the NOTICE file(s) distributed with this work for additional
5
+ * information regarding copyright ownership.
6
+ *
7
+ * This program and the accompanying materials are made available under the
8
+ * terms of the Eclipse Public License 2.0 which is available at
9
+ * https://www.eclipse.org/legal/epl-2.0.
10
+ *
11
+ * SPDX-License-Identifier: EPL-2.0
12
+ *****************************************************************************/
13
+
14
+ import { FunctionComponent, useEffect, useState, useContext, useRef } from 'react';
15
+ import {
16
+ Box,
17
+ Typography,
18
+ Divider,
19
+ List,
20
+ ListItem,
21
+ ListItemText,
22
+ IconButton,
23
+ Paper,
24
+ Button,
25
+ type PaperProps
26
+ } from '@mui/material';
27
+ import DeleteIcon from '@mui/icons-material/Delete';
28
+ import AddIcon from '@mui/icons-material/Add';
29
+ import { MainContext } from '../../../context';
30
+ import { Customer, isError, RateLimitToken } from '../../../extension-registry-types';
31
+ import { GenerateTokenDialog } from '../../../components/generate-token-dialog';
32
+ import { Timestamp } from "../../../components/timestamp";
33
+
34
+ const sectionPaperProps: PaperProps = { elevation: 1, sx: { p: 3, mb: 3 } };
35
+
36
+ export const CustomerTokenList: FunctionComponent<CustomerTokenListProps> = props => {
37
+ const { service, handleError } = useContext(MainContext);
38
+ const [tokens, setTokens] = useState<RateLimitToken[]>([]);
39
+ const [dialogOpen, setDialogOpen] = useState(false);
40
+ const abortController = useRef<AbortController>(new AbortController());
41
+
42
+ useEffect(() => {
43
+ fetchTokens();
44
+ }, [props.customer]);
45
+
46
+ useEffect(() => {
47
+ return () => {
48
+ abortController.current.abort();
49
+ };
50
+ }, []);
51
+
52
+ const fetchTokens = async () => {
53
+ try {
54
+ const result = await service.admin.getCustomerRateLimitTokens(abortController.current, props.customer.name);
55
+ setTokens([...result]);
56
+ } catch (err) {
57
+ handleError(err);
58
+ }
59
+ };
60
+
61
+ const handleGenerate = async (description: string): Promise<string> => {
62
+ const token = await service.admin.createCustomerRateLimitToken(abortController.current, props.customer.name, description);
63
+ await fetchTokens();
64
+ return token.value ?? '';
65
+ };
66
+
67
+ const handleDelete = async (tokenId: number) => {
68
+ try {
69
+ const result = await service.admin.deleteCustomerRateLimitToken(abortController.current, props.customer.name, tokenId);
70
+ if (isError(result)) {
71
+ throw result;
72
+ }
73
+ await fetchTokens();
74
+ } catch (err) {
75
+ handleError(err);
76
+ }
77
+ };
78
+
79
+ return <Paper {...sectionPaperProps}>
80
+ <Box
81
+ sx={{
82
+ display: 'flex',
83
+ justifyContent: 'space-between',
84
+ alignItems: 'center',
85
+ mb: 1,
86
+ flexDirection: { xs: 'column', sm: 'column', md: 'row', lg: 'row', xl: 'row' }
87
+ }}
88
+ >
89
+ <Typography variant='h6'>Tokens</Typography>
90
+ <Button size='small' startIcon={<AddIcon />} onClick={() => setDialogOpen(true)}>
91
+ Generate Token
92
+ </Button>
93
+ </Box>
94
+ <Divider sx={{ mb: 1 }} />
95
+ {tokens.length === 0 ? (
96
+ <Typography variant='body2' color='text.secondary' sx={{ py: 1 }}>
97
+ No rate limiting tokens for this customer.
98
+ </Typography>
99
+ ) : (
100
+ <List dense disablePadding>
101
+ {tokens.map(token => (
102
+ <ListItem
103
+ key={token.id}
104
+ secondaryAction={
105
+ <IconButton edge='end' size='small' color='error' onClick={() => handleDelete(token.id)} title='Delete token'>
106
+ <DeleteIcon fontSize='small' />
107
+ </IconButton>
108
+ }
109
+ >
110
+ <ListItemText
111
+ primary={
112
+ <Typography sx={{ fontWeight: 'bold', overflow: 'hidden', textOverflow: 'ellipsis' }}>{token.description || 'N/A'}</Typography>
113
+ }
114
+ secondary={
115
+ <Typography variant='body2'>Created: <Timestamp value={token.createdTimestamp}/></Typography>
116
+ }
117
+ />
118
+ </ListItem>
119
+ ))}
120
+ </List>
121
+ )}
122
+
123
+ <GenerateTokenDialog
124
+ open={dialogOpen}
125
+ onClose={() => setDialogOpen(false)}
126
+ onGenerate={handleGenerate}
127
+ onError={handleError}
128
+ title='Generate token'
129
+ />
130
+ </Paper>;
131
+ };
132
+
133
+ export interface CustomerTokenListProps {
134
+ customer: Customer;
135
+ }
@@ -0,0 +1,49 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2019 TypeFox and others
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * SPDX-License-Identifier: EPL-2.0
9
+ ********************************************************************************/
10
+
11
+ import { FunctionComponent, useContext, useRef, useState } from 'react';
12
+ import { Button } from '@mui/material';
13
+ import { GenerateTokenDialog } from '../../components/generate-token-dialog';
14
+ import { isError } from '../../extension-registry-types';
15
+ import { MainContext } from '../../context';
16
+
17
+ export const GenerateAccessTokenDialog: FunctionComponent<GenerateTokenDialogProps> = props => {
18
+ const context = useContext(MainContext);
19
+ const abortController = useRef<AbortController>(new AbortController());
20
+ const [open, setOpen] = useState(false);
21
+
22
+ const handleGenerate = async (description: string): Promise<string> => {
23
+ if (!context.user) {
24
+ throw new Error('Not logged in');
25
+ }
26
+ const token = await context.service.createAccessToken(abortController.current, context.user, description);
27
+ if (isError(token)) {
28
+ throw token;
29
+ }
30
+
31
+ props.handleTokenGenerated();
32
+
33
+ return token.value!;
34
+ };
35
+
36
+ return <>
37
+ <Button variant='outlined' onClick={() => setOpen(true)}>Generate new token</Button>
38
+ <GenerateTokenDialog
39
+ open={open}
40
+ onClose={() => setOpen(false)}
41
+ onGenerate={handleGenerate}
42
+ onError={context.handleError}
43
+ />
44
+ </>;
45
+ };
46
+
47
+ export interface GenerateTokenDialogProps {
48
+ handleTokenGenerated: () => void;
49
+ }
@@ -15,7 +15,7 @@ import { DelayedLoadIndicator } from '../../components/delayed-load-indicator';
15
15
  import { Timestamp } from '../../components/timestamp';
16
16
  import { PersonalAccessToken } from '../../extension-registry-types';
17
17
  import { MainContext } from '../../context';
18
- import { GenerateTokenDialog } from './generate-token-dialog';
18
+ import { GenerateAccessTokenDialog } from './generate-access-token-dialog';
19
19
  import { UserSettingsRoutes } from './user-settings-routes';
20
20
  import styled from '@mui/material/styles/styled';
21
21
 
@@ -105,7 +105,7 @@ export const UserSettingsTokens: FunctionComponent = () => {
105
105
  <Box alignItems='center' overflow='auto'>
106
106
  <Typography sx={{ fontWeight: 'bold', overflow: 'hidden', textOverflow: 'ellipsis' }}>{token.description}</Typography>
107
107
  <Typography variant='body2'>Created: <Timestamp value={token.createdTimestamp}/></Typography>
108
- <Typography variant='body2'>Expires: {token.expiresTimestamp ? <Timestamp value={token.expiresTimestamp}/> : 'never'}</Typography>
108
+ <Typography variant='body2'>Expires: {token.expiresTimestamp ? <Timestamp value={token.expiresTimestamp} isFutureTime={true} /> : 'never'}</Typography>
109
109
  <Typography variant='body2'>Accessed: {token.accessedTimestamp ? <Timestamp value={token.accessedTimestamp}/> : 'never'}</Typography>
110
110
  </Box>
111
111
  <Box display='flex' alignItems='center'>
@@ -159,7 +159,7 @@ export const UserSettingsTokens: FunctionComponent = () => {
159
159
  }}
160
160
  >
161
161
  <Box mr={1} mb={1}>
162
- <GenerateTokenDialog
162
+ <GenerateAccessTokenDialog
163
163
  handleTokenGenerated={handleTokenGenerated}
164
164
  />
165
165
  </Box>
package/src/utils.ts CHANGED
@@ -52,22 +52,26 @@ export function toLocalTime(timestamp?: string): string | undefined {
52
52
  return new Intl.DateTimeFormat(undefined, options).format(date);
53
53
  }
54
54
 
55
- const msPerMinute = 60 * 1000;
55
+ const msPerSecond = 1000;
56
+ const msPerMinute = msPerSecond * 60;
56
57
  const msPerHour = msPerMinute * 60;
57
58
  const msPerDay = msPerHour * 24;
58
59
  const msPerMonth = msPerDay * 30.4;
59
60
  const msPerYear = msPerDay * 365;
60
- export function toRelativeTime(timestamp?: string): string | undefined {
61
+ export function toRelativeTime(timestamp?: string, isFutureTime: boolean = false): string | undefined {
61
62
  if (!timestamp) {
62
63
  return undefined;
63
64
  }
64
65
  const date = new Date(timestamp);
65
66
  const elapsed = Date.now() - date.getTime();
66
67
 
67
- if (elapsed < 0) {
68
+ if (isFutureTime) {
68
69
  const remaining = -elapsed;
69
- if (remaining < msPerMinute) {
70
- return 'now';
70
+ if (remaining < 0) {
71
+ return "now";
72
+ } else if (remaining < msPerMinute) {
73
+ const value = Math.round(remaining / msPerSecond);
74
+ return `in ${value} second${value !== 1 ? 's' : ''}`;
71
75
  } else if (remaining < msPerHour) {
72
76
  const value = Math.round(remaining / msPerMinute);
73
77
  return `in ${value} minute${value !== 1 ? 's' : ''}`;
@@ -1,21 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2020 TypeFox and others
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * SPDX-License-Identifier: EPL-2.0
9
- ********************************************************************************/
10
- import { FunctionComponent, ReactElement } from 'react';
11
- import { TooltipProps } from '@mui/material';
12
- export declare const CopyToClipboard: FunctionComponent<CopyToClipboardProps>;
13
- interface ChildProps {
14
- copy: (content: any) => void;
15
- }
16
- export interface CopyToClipboardProps {
17
- tooltipProps?: Partial<TooltipProps>;
18
- children: (props: ChildProps) => ReactElement<any>;
19
- }
20
- export {};
21
- //# sourceMappingURL=copy-to-clipboard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"copy-to-clipboard.d.ts","sourceRoot":"","sources":["../../src/components/copy-to-clipboard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;kFAQkF;AAElF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAElE,OAAO,EAAW,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtD,eAAO,MAAM,eAAe,EAAE,iBAAiB,CAAC,oBAAoB,CA0BnE,CAAC;AAEF,UAAU,UAAU;IAChB,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC;CACtD"}
@@ -1,25 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /********************************************************************************
3
- * Copyright (c) 2020 TypeFox and others
4
- *
5
- * This program and the accompanying materials are made available under the
6
- * terms of the Eclipse Public License v. 2.0 which is available at
7
- * http://www.eclipse.org/legal/epl-2.0.
8
- *
9
- * SPDX-License-Identifier: EPL-2.0
10
- ********************************************************************************/
11
- import { useState } from 'react';
12
- import copy from 'clipboard-copy';
13
- import { Tooltip } from '@mui/material';
14
- export const CopyToClipboard = props => {
15
- const [showTooltip, setTooltip] = useState(false);
16
- const handleOnTooltipClose = () => {
17
- setTooltip(false);
18
- };
19
- const onCopy = (content) => {
20
- copy(content);
21
- setTooltip(true);
22
- };
23
- return (_jsx(Tooltip, { open: showTooltip, title: 'Copied to clipboard!', leaveDelay: 1500, onClose: handleOnTooltipClose, disableHoverListener: true, ...props.tooltipProps ?? {}, children: props.children({ copy: onCopy }) }));
24
- };
25
- //# sourceMappingURL=copy-to-clipboard.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"copy-to-clipboard.js","sourceRoot":"","sources":["../../src/components/copy-to-clipboard.tsx"],"names":[],"mappings":";AAAA;;;;;;;;kFAQkF;AAElF,OAAO,EAAmC,QAAQ,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAClC,OAAO,EAAE,OAAO,EAAgB,MAAM,eAAe,CAAC;AAEtD,MAAM,CAAC,MAAM,eAAe,GAA4C,KAAK,CAAC,EAAE;IAC5E,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAE3D,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAC9B,UAAU,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,OAAa,EAAE,EAAE;QAC7B,IAAI,CAAC,OAAO,CAAC,CAAC;QACd,UAAU,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,OAAO,IACJ,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,sBAAsB,EAC7B,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,oBAAoB,EAC7B,oBAAoB,WAChB,KAAK,CAAC,YAAY,IAAI,EAAE,YAGxB,KAAK,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAsB,GAEnD,CACb,CAAC;AACN,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-token-dialog.d.ts","sourceRoot":"","sources":["../../../src/pages/user/generate-token-dialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;kFAQkF;AAElF,OAAO,EAAe,iBAAiB,EAA2C,MAAM,OAAO,CAAC;AAShG,eAAO,MAAM,mBAAmB,EAAE,iBAAiB,CAAC,wBAAwB,CAqI3E,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACrC,oBAAoB,EAAE,MAAM,IAAI,CAAC;CACpC"}
@@ -1,79 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- /********************************************************************************
3
- * Copyright (c) 2019 TypeFox and others
4
- *
5
- * This program and the accompanying materials are made available under the
6
- * terms of the Eclipse Public License v. 2.0 which is available at
7
- * http://www.eclipse.org/legal/epl-2.0.
8
- *
9
- * SPDX-License-Identifier: EPL-2.0
10
- ********************************************************************************/
11
- import { useContext, useEffect, useState, useRef } from 'react';
12
- import { Button, Dialog, DialogTitle, DialogContent, DialogContentText, Box, TextField, DialogActions, Typography } from '@mui/material';
13
- import { ButtonWithProgress } from '../../components/button-with-progress';
14
- import { CopyToClipboard } from '../../components/copy-to-clipboard';
15
- import { isError } from '../../extension-registry-types';
16
- import { MainContext } from '../../context';
17
- const TOKEN_DESCRIPTION_SIZE = 255;
18
- export const GenerateTokenDialog = props => {
19
- const [open, setOpen] = useState(false);
20
- const [posted, setPosted] = useState(false);
21
- const [description, setDescription] = useState('');
22
- const [descriptionError, setDescriptionError] = useState();
23
- const [token, setToken] = useState();
24
- const context = useContext(MainContext);
25
- const abortController = useRef(new AbortController());
26
- useEffect(() => {
27
- document.addEventListener('keydown', handleEnter);
28
- return () => {
29
- abortController.current.abort();
30
- document.removeEventListener('keydown', handleEnter);
31
- };
32
- }, []);
33
- const handleOpenDialog = () => {
34
- setOpen(true);
35
- setPosted(false);
36
- setDescription('');
37
- setToken(undefined);
38
- };
39
- const handleClose = () => setOpen(false);
40
- const handleDescriptionChange = (event) => {
41
- const description = event.target.value;
42
- let descriptionError;
43
- if (description.length > TOKEN_DESCRIPTION_SIZE) {
44
- descriptionError = `The description must not be longer than ${TOKEN_DESCRIPTION_SIZE} characters.`;
45
- }
46
- setDescription(description);
47
- setDescriptionError(descriptionError);
48
- };
49
- const handleGenerate = async () => {
50
- if (!context.user) {
51
- return;
52
- }
53
- setPosted(true);
54
- try {
55
- const token = await context.service.createAccessToken(abortController.current, context.user, description);
56
- if (isError(token)) {
57
- throw token;
58
- }
59
- setToken(token);
60
- props.handleTokenGenerated();
61
- }
62
- catch (err) {
63
- context.handleError(err);
64
- }
65
- };
66
- const handleEnter = (e) => {
67
- if (e.code === 'Enter' && open && !token) {
68
- handleGenerate();
69
- }
70
- };
71
- return _jsxs(_Fragment, { children: [_jsx(Button, { variant: 'outlined', onClick: handleOpenDialog, children: "Generate new token" }), _jsxs(Dialog, { open: open, onClose: handleClose, children: [_jsx(DialogTitle, { children: "Generate new token" }), _jsxs(DialogContent, { children: [_jsx(DialogContentText, { children: "Describe where you will use this token." }), _jsx(Box, { my: 2, children: _jsx(TextField, { disabled: Boolean(token), fullWidth: true, label: 'Token Description', error: Boolean(descriptionError), helperText: descriptionError, onChange: handleDescriptionChange }) }), _jsx(TextField, { disabled: !token, margin: 'dense', label: 'Generated Token...', fullWidth: true, multiline: true, variant: 'outlined', rows: 4, value: token ? token.value : '' }), token ?
72
- _jsx(Box, { children: _jsx(Typography, { sx: { color: 'red', fontWeight: 'bold' }, children: "Copy and paste this token to a safe place. It will not be displayed again." }) }) : null] }), _jsxs(DialogActions, { children: [token ?
73
- _jsx(CopyToClipboard, { tooltipProps: { placement: 'left' }, children: ({ copy }) => (_jsx(Button, { autoFocus: true, variant: 'contained', color: 'secondary', onClick: () => {
74
- copy(token.value);
75
- setTimeout(handleClose, 700);
76
- }, children: "Copy" })) }) : null, _jsx(Button, { onClick: handleClose, color: 'secondary', children: token ? 'Close' : 'Cancel' }), !token ?
77
- _jsx(ButtonWithProgress, { autoFocus: true, sx: { ml: 1 }, error: Boolean(descriptionError), working: posted, onClick: handleGenerate, children: "Generate Token" }) : null] })] })] });
78
- };
79
- //# sourceMappingURL=generate-token-dialog.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-token-dialog.js","sourceRoot":"","sources":["../../../src/pages/user/generate-token-dialog.tsx"],"names":[],"mappings":"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"}
@@ -1,50 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2020 TypeFox and others
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * SPDX-License-Identifier: EPL-2.0
9
- ********************************************************************************/
10
-
11
- import { FunctionComponent, ReactElement, useState } from 'react';
12
- import copy from 'clipboard-copy';
13
- import { Tooltip, TooltipProps } from '@mui/material';
14
-
15
- export const CopyToClipboard: FunctionComponent<CopyToClipboardProps> = props => {
16
- const [showTooltip, setTooltip] = useState<boolean>(false);
17
-
18
- const handleOnTooltipClose = () => {
19
- setTooltip(false);
20
- };
21
-
22
- const onCopy = (content: any) => {
23
- copy(content);
24
- setTooltip(true);
25
- };
26
-
27
- return (
28
- <Tooltip
29
- open={showTooltip}
30
- title={'Copied to clipboard!'}
31
- leaveDelay={1500}
32
- onClose={handleOnTooltipClose}
33
- disableHoverListener
34
- {...props.tooltipProps ?? {}}
35
- >
36
- {
37
- props.children({ copy: onCopy }) as ReactElement<any>
38
- }
39
- </Tooltip>
40
- );
41
- };
42
-
43
- interface ChildProps {
44
- copy: (content: any) => void;
45
- }
46
-
47
- export interface CopyToClipboardProps {
48
- tooltipProps?: Partial<TooltipProps>;
49
- children: (props: ChildProps) => ReactElement<any>;
50
- }
@@ -1,157 +0,0 @@
1
- /********************************************************************************
2
- * Copyright (c) 2019 TypeFox and others
3
- *
4
- * This program and the accompanying materials are made available under the
5
- * terms of the Eclipse Public License v. 2.0 which is available at
6
- * http://www.eclipse.org/legal/epl-2.0.
7
- *
8
- * SPDX-License-Identifier: EPL-2.0
9
- ********************************************************************************/
10
-
11
- import { ChangeEvent, FunctionComponent, useContext, useEffect, useState, useRef } from 'react';
12
- import { Button, Dialog, DialogTitle, DialogContent, DialogContentText, Box, TextField, DialogActions, Typography } from '@mui/material';
13
- import { ButtonWithProgress } from '../../components/button-with-progress';
14
- import { CopyToClipboard } from '../../components/copy-to-clipboard';
15
- import { PersonalAccessToken, isError } from '../../extension-registry-types';
16
- import { MainContext } from '../../context';
17
-
18
- const TOKEN_DESCRIPTION_SIZE = 255;
19
-
20
- export const GenerateTokenDialog: FunctionComponent<GenerateTokenDialogProps> = props => {
21
- const [open, setOpen] = useState<boolean>(false);
22
- const [posted, setPosted] = useState<boolean>(false);
23
- const [description, setDescription] = useState<string>('');
24
- const [descriptionError, setDescriptionError] = useState<string>();
25
- const [token, setToken] = useState<PersonalAccessToken>();
26
-
27
- const context = useContext(MainContext);
28
- const abortController = useRef<AbortController>(new AbortController());
29
-
30
- useEffect(() => {
31
- document.addEventListener('keydown', handleEnter);
32
- return () => {
33
- abortController.current.abort();
34
- document.removeEventListener('keydown', handleEnter);
35
- };
36
- }, []);
37
-
38
- const handleOpenDialog = () => {
39
- setOpen(true);
40
- setPosted(false);
41
- setDescription('');
42
- setToken(undefined);
43
- };
44
-
45
- const handleClose = () => setOpen(false);
46
-
47
- const handleDescriptionChange = (event: ChangeEvent<HTMLInputElement>) => {
48
- const description = event.target.value;
49
- let descriptionError: string | undefined;
50
- if (description.length > TOKEN_DESCRIPTION_SIZE) {
51
- descriptionError = `The description must not be longer than ${TOKEN_DESCRIPTION_SIZE} characters.`;
52
- }
53
-
54
- setDescription(description);
55
- setDescriptionError(descriptionError);
56
- };
57
-
58
- const handleGenerate = async () => {
59
- if (!context.user) {
60
- return;
61
- }
62
- setPosted(true);
63
- try {
64
- const token = await context.service.createAccessToken(abortController.current, context.user, description);
65
- if (isError(token)) {
66
- throw token;
67
- }
68
- setToken(token);
69
- props.handleTokenGenerated();
70
- } catch (err) {
71
- context.handleError(err);
72
- }
73
- };
74
-
75
- const handleEnter = (e: KeyboardEvent) => {
76
- if (e.code === 'Enter' && open && !token) {
77
- handleGenerate();
78
- }
79
- };
80
-
81
- return <>
82
- <Button variant='outlined' onClick={handleOpenDialog}>Generate new token</Button>
83
- <Dialog open={open} onClose={handleClose}>
84
- <DialogTitle>Generate new token</DialogTitle>
85
- <DialogContent>
86
- <DialogContentText>
87
- Describe where you will use this token.
88
- </DialogContentText>
89
- <Box my={2}>
90
- <TextField
91
- disabled={Boolean(token)}
92
- fullWidth
93
- label='Token Description'
94
- error={Boolean(descriptionError)}
95
- helperText={descriptionError}
96
- onChange={handleDescriptionChange} />
97
- </Box>
98
- <TextField
99
- disabled={!token}
100
- margin='dense'
101
- label='Generated Token...'
102
- fullWidth
103
- multiline
104
- variant='outlined'
105
- rows={4}
106
- value={token ? token.value : ''}
107
- />
108
- {
109
- token ?
110
- <Box>
111
- <Typography sx={{ color: 'red', fontWeight: 'bold' }}>
112
- Copy and paste this token to a safe place. It will not be displayed again.
113
- </Typography>
114
- </Box> : null
115
- }
116
- </DialogContent>
117
- <DialogActions>
118
- {
119
- token ?
120
- <CopyToClipboard tooltipProps={{ placement: 'left' }}>
121
- {({ copy }) => (
122
- <Button
123
- autoFocus
124
- variant='contained'
125
- color='secondary'
126
- onClick={() => {
127
- copy(token!.value);
128
- setTimeout(handleClose, 700);
129
- }}
130
- >
131
- Copy
132
- </Button>
133
- )}
134
- </CopyToClipboard> : null
135
- }
136
- <Button onClick={handleClose} color='secondary'>
137
- {token ? 'Close' : 'Cancel'}
138
- </Button>
139
- {
140
- !token ?
141
- <ButtonWithProgress
142
- autoFocus
143
- sx={{ ml: 1 }}
144
- error={Boolean(descriptionError)}
145
- working={posted}
146
- onClick={handleGenerate} >
147
- Generate Token
148
- </ButtonWithProgress> : null
149
- }
150
- </DialogActions>
151
- </Dialog>
152
- </>;
153
- };
154
-
155
- export interface GenerateTokenDialogProps {
156
- handleTokenGenerated: () => void;
157
- }