feat: add new token page e2e test (#330)
This commit is contained in:
		
							parent
							
								
									4d95cfb800
								
							
						
					
					
						commit
						1699523c97
					
				|  | @ -5,7 +5,7 @@ import user from '../fixtures/api/user.json'; | |||
| import guestUser from '../fixtures/api/guest-user.json'; | ||||
| import seedPeers from '../fixtures/api/clusters/seed-peers.json'; | ||||
| import schedulers from '../fixtures/api/clusters/schedulers.json'; | ||||
| import createClustes from '../fixtures/api/clusters/create-cluster.json'; | ||||
| import createCluster from '../fixtures/api/clusters/create-cluster.json'; | ||||
| import _ from 'lodash'; | ||||
| 
 | ||||
| describe('Create cluster', () => { | ||||
|  | @ -141,7 +141,7 @@ describe('Create cluster', () => { | |||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: createClustes, | ||||
|           body: createCluster, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|  | @ -313,7 +313,7 @@ describe('Create cluster', () => { | |||
|       cy.url().should('include', '/clusters/new'); | ||||
|       cy.get('#name').clear(); | ||||
| 
 | ||||
|       // Enter the correct name。
 | ||||
|       // Enter the correct name.
 | ||||
|       cy.get('#name').type('cluster-12'); | ||||
|       cy.get('#name-helper-text').should('not.exist'); | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,319 @@ | |||
| import root from '../fixtures/api/role-root.json'; | ||||
| import guest from '../fixtures/api/role-guest.json'; | ||||
| import user from '../fixtures/api/user.json'; | ||||
| import guestUser from '../fixtures/api/guest-user.json'; | ||||
| import tokens from '../fixtures/api/tokens/tokens.json'; | ||||
| import createToken from '../fixtures/api/tokens/create-token.json'; | ||||
| import _ from 'lodash'; | ||||
| 
 | ||||
| describe('Create token', () => { | ||||
|   beforeEach(() => { | ||||
|     cy.signin(); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/1', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: user, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/1/roles', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: root, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/personal-access-tokens?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: tokens, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.visit('/developer/personal-access-tokens/new'); | ||||
| 
 | ||||
|     cy.viewport(1440, 1080); | ||||
|   }); | ||||
| 
 | ||||
|   it('can create token', () => { | ||||
|     cy.visit('/developer/personal-access-tokens'); | ||||
| 
 | ||||
|     // Click the `ADD PERSONAL ACCESS TOKENS` button.
 | ||||
|     cy.get('.css-1qdyvok > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the developer/personal-access-tokens/new!
 | ||||
|     cy.url().should('include', '/developer/personal-access-tokens/new'); | ||||
| 
 | ||||
|     cy.get('#name').type('root-12'); | ||||
| 
 | ||||
|     // Choose an expiration time of 60 days.
 | ||||
|     cy.get('#demo-simple-select').click(); | ||||
|     cy.get('[data-value="60"]').click(); | ||||
| 
 | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/personal-access-tokens', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = {}; | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: { | ||||
|             id: 12, | ||||
|             created_at: '2023-12-05T11:26:32Z', | ||||
|             updated_at: '2023-12-05T11:26:32Z', | ||||
|             is_del: 0, | ||||
|             name: 'root-12', | ||||
|             bio: '', | ||||
|             token: 'ZjM1NzM1NGItYjYwYi00OTEyLTlmN2QtNjc5M2JhNzhiOTI3', | ||||
|             scopes: [], | ||||
|             state: 'active', | ||||
|             expired_at: '2033-12-02T11:26:17Z', | ||||
|             user_id: 2, | ||||
|           }, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/personal-access-tokens?page=1&per_page=10000000', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: createToken, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the developer/personal-access-tokens!
 | ||||
|     cy.url().should('include', '/developer/personal-access-tokens'); | ||||
| 
 | ||||
|     // After creation is completed, the copyable token will be displayed.
 | ||||
|     cy.get('.css-1s0a73l').should('exist'); | ||||
| 
 | ||||
|     // Click the Copy icon button.
 | ||||
|     cy.get('.css-1s0a73l > .MuiButtonBase-root').click(); | ||||
| 
 | ||||
|     // The copy icon is no longer displayed.
 | ||||
|     cy.get('#copy').should('not.exist'); | ||||
| 
 | ||||
|     // Shwo done icon.
 | ||||
|     cy.get('#done').should('exist'); | ||||
| 
 | ||||
|     // Show `copied!` text.
 | ||||
|     cy.get('.MuiTooltip-tooltip').should('exist').and('have.text', 'copied!'); | ||||
| 
 | ||||
|     // Let's check the copied text.
 | ||||
|     cy.window() | ||||
|       .its('navigator.clipboard') | ||||
|       .then((clip) => clip.readText()) | ||||
|       .should('equal', 'ZjM1NzM1NGItYjYwYi00OTEyLTlmN2QtNjc5M2JhNzhiOTI3'); | ||||
| 
 | ||||
|     cy.wait(1000); | ||||
| 
 | ||||
|     cy.get('#copy').should('exist'); | ||||
|     cy.get('#done').should('not.exist'); | ||||
|     cy.get('.MuiTooltip-tooltip').should('not.exist'); | ||||
| 
 | ||||
|     // Display successfully created token information.
 | ||||
|     cy.get('#root-12').should('be.visible').and('have.text', 'root-12'); | ||||
| 
 | ||||
|     // Refresh page.
 | ||||
|     cy.reload().then(() => { | ||||
|       cy.wait(2000); | ||||
|     }); | ||||
| 
 | ||||
|     // When you click refresh, the replication token will not be displayed again for your security.
 | ||||
|     cy.get('.css-1s0a73l').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|   it('cannot create token with existing token', () => { | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/personal-access-tokens', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = {}; | ||||
|         req.reply({ | ||||
|           statusCode: 409, | ||||
|           body: { message: 'Conflict' }, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.get('#name').type('root-12{enter}'); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); | ||||
|     cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); | ||||
|     cy.get('.MuiPaper-root').should('not.exist'); | ||||
|   }); | ||||
| 
 | ||||
|   it('click the `CANCEL button', () => { | ||||
|     cy.get('#cancel').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the developer/personal-access-tokens!
 | ||||
|     cy.url().should('include', '/developer/personal-access-tokens'); | ||||
|   }); | ||||
| 
 | ||||
|   it('token cannot be created without required attributes', () => { | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     cy.get('#name-helper-text').should('exist').and('have.text', 'Fill in the characters, the length is 1-100.'); | ||||
|   }); | ||||
| 
 | ||||
|   it('try to create token with guest user', () => { | ||||
|     cy.visit('/signin'); | ||||
| 
 | ||||
|     cy.guestSignin(); | ||||
| 
 | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/2', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: guestUser, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'GET', | ||||
|         url: '/api/v1/users/2/roles', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.reply({ | ||||
|           statusCode: 200, | ||||
|           body: guest, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/personal-access-tokens', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = {}; | ||||
|         req.reply({ | ||||
|           statusCode: 401, | ||||
|           body: { message: 'permission deny' }, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.visit('/developer/personal-access-tokens/new'); | ||||
| 
 | ||||
|     // Users menu does not exist.
 | ||||
|     cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); | ||||
| 
 | ||||
|     cy.get('#name').type('root-12{enter}'); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'permission deny'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should handle API error response', () => { | ||||
|     cy.intercept( | ||||
|       { | ||||
|         method: 'POST', | ||||
|         url: '/api/v1/personal-access-tokens', | ||||
|       }, | ||||
|       (req) => { | ||||
|         req.body = {}; | ||||
|         req.reply({ | ||||
|           forceNetworkError: true, | ||||
|         }); | ||||
|       }, | ||||
|     ); | ||||
| 
 | ||||
|     cy.get('#name').type('root-12{enter}'); | ||||
| 
 | ||||
|     // Show error message.
 | ||||
|     cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch'); | ||||
|   }); | ||||
| 
 | ||||
|   it('cannot create token with invalid attributes', () => { | ||||
|     const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | ||||
|     const name = _.times(101, () => _.sample(characters)).join(''); | ||||
|     const description = _.times(1001, () => _.sample(characters)).join(''); | ||||
| 
 | ||||
|     // Should name message describing the validation error.
 | ||||
|     cy.get('#name').type(name); | ||||
| 
 | ||||
|     // Show verification error message.
 | ||||
|     cy.get('#name-helper-text').should('exist').and('have.text', 'Fill in the characters, the length is 1-100.'); | ||||
| 
 | ||||
|     // Submit form when validation fails.
 | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the developer/personal-access-tokens/new!
 | ||||
|     cy.url().should('include', '/developer/personal-access-tokens/new'); | ||||
|     cy.get('#name').clear(); | ||||
| 
 | ||||
|     // Enter the correct name.
 | ||||
|     cy.get('#name').type('root-12'); | ||||
| 
 | ||||
|     // Should display message describing the validation error.
 | ||||
| 
 | ||||
|     cy.get('#bio').type(description); | ||||
| 
 | ||||
|     // Show verification error message.
 | ||||
|     cy.get('#bio-helper-text').should('exist').and('have.text', 'Fill in the characters, the length is 0-1000.'); | ||||
|     cy.get('#save').click(); | ||||
| 
 | ||||
|     // Then I see that the current page is the developer/personal-access-tokens/new!
 | ||||
|     cy.url().should('include', '/developer/personal-access-tokens/new'); | ||||
| 
 | ||||
|     cy.get( | ||||
|       ':nth-child(1) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input', | ||||
|     ).click(); | ||||
| 
 | ||||
|     // Check if the preheat checkbox is checked.
 | ||||
|     cy.get(':nth-child(1) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input') | ||||
|       .should('be.checked') | ||||
|       .check({ force: true }); | ||||
| 
 | ||||
|     cy.get( | ||||
|       ':nth-child(2) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input', | ||||
|     ).click(); | ||||
| 
 | ||||
|     // Check if the job checkbox is checked.
 | ||||
|     cy.get(':nth-child(2) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input') | ||||
|       .should('be.checked') | ||||
|       .check({ force: true }); | ||||
| 
 | ||||
|     cy.get( | ||||
|       ':nth-child(3) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input', | ||||
|     ).click(); | ||||
| 
 | ||||
|     // Check if the cluster checkbox is checked.
 | ||||
|     cy.get(':nth-child(3) > .MuiBox-root > .MuiFormControlLabel-root > .MuiButtonBase-root > .PrivateSwitchBase-input') | ||||
|       .should('be.checked') | ||||
|       .check({ force: true }); | ||||
|   }); | ||||
| }); | ||||
|  | @ -2,7 +2,7 @@ import root from '../fixtures/api/role-root.json'; | |||
| import user from '../fixtures/api/user.json'; | ||||
| import tokens from '../fixtures/api/tokens/tokens.json'; | ||||
| import deleteToken from '../fixtures/api/tokens/delete-tokens.json'; | ||||
| import deleteTokenAfter from '../fixtures/api/tokens/token-delete-after.json'; | ||||
| import tokenDeleteAfter from '../fixtures/api/tokens/token-delete-after.json'; | ||||
| 
 | ||||
| describe('Tokens', () => { | ||||
|   beforeEach(() => { | ||||
|  | @ -262,7 +262,7 @@ describe('Tokens', () => { | |||
|         (req) => { | ||||
|           req.reply({ | ||||
|             statusCode: 200, | ||||
|             body: deleteTokenAfter, | ||||
|             body: tokenDeleteAfter, | ||||
|           }); | ||||
|         }, | ||||
|       ).as('delete'); | ||||
|  |  | |||
|  | @ -0,0 +1,326 @@ | |||
| [ | ||||
|   { | ||||
|     "id": 1, | ||||
|     "created_at": "2023-12-04T10:27:17Z", | ||||
|     "updated_at": "2023-12-04T10:34:12Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-1", | ||||
|     "bio": "root-1 token,it's used for preheating of harbor.", | ||||
|     "token": "MTk3OTY5NTMtZjlkZi00YWVhLWI5OGEtZTc0YWVhMWZmYmQz", | ||||
|     "scopes": ["preheat"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2033-12-01T10:34:08Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 2, | ||||
|     "created_at": "2023-12-04T10:39:31Z", | ||||
|     "updated_at": "2023-12-04T10:39:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-2", | ||||
|     "bio": "root-2 token, used to open API call warm-up job.", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["job"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-08-11T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 3, | ||||
|     "created_at": "2023-12-04T10:41:31Z", | ||||
|     "updated_at": "2023-12-04T10:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-3", | ||||
|     "bio": "root-3 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2025-02-21T11:37:53Z", | ||||
|     "user_id": 1, | ||||
|     "user": { | ||||
|       "id": 1, | ||||
|       "created_at": "2023-11-06T06:09:04Z", | ||||
|       "updated_at": "2023-11-06T06:09:04Z", | ||||
|       "is_del": 0, | ||||
|       "email": "lucy@example.com", | ||||
|       "name": "lucy", | ||||
|       "avatar": "https://example.com/avatar.png", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Hangzhou", | ||||
|       "bio": "I am lucy", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 4, | ||||
|     "created_at": "2023-12-04T10:42:31Z", | ||||
|     "updated_at": "2023-12-04T10:42:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-4", | ||||
|     "bio": "root-4 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-02-11T10:37:53Z", | ||||
|     "user_id": 1, | ||||
|     "user": { | ||||
|       "id": 1, | ||||
|       "created_at": "2023-11-06T06:09:04Z", | ||||
|       "updated_at": "2023-11-06T06:09:04Z", | ||||
|       "is_del": 0, | ||||
|       "email": "lucy@example.com", | ||||
|       "name": "lucy", | ||||
|       "avatar": "https://example.com/avatar.png", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Hangzhou", | ||||
|       "bio": "I am lucy", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 5, | ||||
|     "created_at": "2023-12-04T10:43:31Z", | ||||
|     "updated_at": "2023-12-04T10:43:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-5", | ||||
|     "bio": "root-5 token, used to open API call warm-up job.", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["job"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2027-09-14T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 6, | ||||
|     "created_at": "2023-12-04T10:45:31Z", | ||||
|     "updated_at": "2023-12-04T10:45:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-6", | ||||
|     "bio": "root-6 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-01-11T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 7, | ||||
|     "created_at": "2023-12-04T11:41:31Z", | ||||
|     "updated_at": "2023-12-04T11:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-7", | ||||
|     "bio": "root-7 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2025-06-11T10:37:53Z", | ||||
|     "user_id": 2, | ||||
|     "user": { | ||||
|       "id": 2, | ||||
|       "created_at": "2023-11-07T06:09:04Z", | ||||
|       "updated_at": "2023-11-07T06:09:04Z", | ||||
|       "is_del": 0, | ||||
|       "email": "jack@example.com", | ||||
|       "name": "jack", | ||||
|       "avatar": "https://example.com/avatar.png", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Shanghai", | ||||
|       "bio": "I am jack", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 8, | ||||
|     "created_at": "2023-12-04T11:49:31Z", | ||||
|     "updated_at": "2023-12-04T11:49:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-8", | ||||
|     "bio": "root-8 token,it's used for preheating of harbor.", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2025-01-11T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 9, | ||||
|     "created_at": "2023-12-05T10:41:31Z", | ||||
|     "updated_at": "2023-12-05T10:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-9", | ||||
|     "bio": "root-9 token,it's used for preheating of harbor.", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["preheat"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2033-12-01T10:34:08Z", | ||||
|     "user_id": 2, | ||||
|     "user": { | ||||
|       "id": 2, | ||||
|       "created_at": "2023-11-07T06:09:04Z", | ||||
|       "updated_at": "2023-11-07T06:09:04Z", | ||||
|       "is_del": 0, | ||||
|       "email": "jack@example.com", | ||||
|       "name": "jack", | ||||
|       "avatar": "https://example.com/avatar.png", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Shanghai", | ||||
|       "bio": "I am jack", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 10, | ||||
|     "created_at": "2023-12-05T18:41:31Z", | ||||
|     "updated_at": "2023-12-05T18:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-10", | ||||
|     "bio": "root-10 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-12-1T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 11, | ||||
|     "created_at": "2023-12-06T10:41:31Z", | ||||
|     "updated_at": "2023-12-06T10:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-11", | ||||
|     "bio": "root-11 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": ["cluster"], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-12-11T10:37:53Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     "id": 12, | ||||
|     "created_at": "2023-12-06T11:41:31Z", | ||||
|     "updated_at": "2023-12-06T11:41:31Z", | ||||
|     "is_del": 0, | ||||
|     "name": "root-12", | ||||
|     "bio": "root-12 token, used to control of cluster", | ||||
|     "token": "YmVmYjA1Y2MtMmFkYy00OTJjLTg4OWUtYzg3MjE0ZWEyOWY4", | ||||
|     "scopes": [], | ||||
|     "state": "active", | ||||
|     "expired_at": "2024-02-03T11:36:05Z", | ||||
|     "user_id": 3, | ||||
|     "user": { | ||||
|       "id": 3, | ||||
|       "created_at": "2023-11-27T07:31:23Z", | ||||
|       "updated_at": "2023-11-27T07:31:23Z", | ||||
|       "is_del": 0, | ||||
|       "email": "root@example.com", | ||||
|       "name": "root", | ||||
|       "avatar": "", | ||||
|       "phone": "1234567890", | ||||
|       "state": "enable", | ||||
|       "location": "Guangzhou", | ||||
|       "bio": "This is root", | ||||
|       "configs": null | ||||
|     } | ||||
|   } | ||||
| ] | ||||
|  | @ -216,19 +216,21 @@ export default function PersonalAccessTokens() { | |||
|                 PopperProps={{ | ||||
|                   disablePortal: true, | ||||
|                 }} | ||||
|                 onClose={() => { | ||||
|                   setShowCopyIcon(false); | ||||
|                 }} | ||||
|                 open={showCopyIcon} | ||||
|                 disableFocusListener | ||||
|                 disableHoverListener | ||||
|                 disableTouchListener | ||||
|                 title="copied!" | ||||
|               > | ||||
|                 <Box component="img" sx={{ width: '1.2rem', height: '1.2rem' }} src="/icons/tokens/done.svg" /> | ||||
|                 <Box | ||||
|                   component="img" | ||||
|                   id="done" | ||||
|                   sx={{ width: '1.2rem', height: '1.2rem' }} | ||||
|                   src="/icons/tokens/done.svg" | ||||
|                 /> | ||||
|               </Tooltip> | ||||
|             ) : ( | ||||
|               <Box component="img" sx={{ width: '1.2rem', height: '1.2rem' }} src="/icons/tokens/copy.svg" /> | ||||
|               <Box component="img" id="copy" sx={{ width: '1.2rem', height: '1.2rem' }} src="/icons/tokens/copy.svg" /> | ||||
|             )} | ||||
|           </IconButton> | ||||
|         </Box> | ||||
|  |  | |||
|  | @ -361,6 +361,7 @@ export default function CreateTokens() { | |||
|                 size="small" | ||||
|                 variant="outlined" | ||||
|                 loadingPosition="end" | ||||
|                 id="cancel" | ||||
|                 sx={{ | ||||
|                   '&.MuiLoadingButton-root': { | ||||
|                     color: 'var(--calcel-size-color)', | ||||
|  | @ -392,6 +393,7 @@ export default function CreateTokens() { | |||
|                 variant="outlined" | ||||
|                 type="submit" | ||||
|                 loadingPosition="end" | ||||
|                 id="save" | ||||
|                 sx={{ | ||||
|                   '&.MuiLoadingButton-root': { | ||||
|                     backgroundColor: 'var(--save-color)', | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue