diff --git a/cypress/e2e/clusters/cluster.cy.ts b/cypress/e2e/clusters/cluster.cy.ts index ffa3715..6b2e1d9 100644 --- a/cypress/e2e/clusters/cluster.cy.ts +++ b/cypress/e2e/clusters/cluster.cy.ts @@ -214,11 +214,11 @@ describe('Cluster', () => { // Click the copy scheduler cluster id icon. cy.get('#copy-scheduler-cluster-id').click(); cy.get('#schedulerClusterIDCopyIcon').should('exist'); - cy.get('#schedulerClusterIDTooltip').should('exist'); + cy.get('#schedulerClusterIDTooltip').should('not.exist'); cy.wait(1000); // Display successful copy icon. - cy.get('#schedulerClusterIDCopyIcon').should('not.exist'); + cy.get('#schedulerClusterIDCopyIcon').should('exist'); cy.get('#schedulerClusterIDTooltip').should('not.exist'); // Let's check the copied text. @@ -230,11 +230,11 @@ describe('Cluster', () => { // Click the copy seed peer cluster id icon. cy.get('#copy-seed-peer-cluster-id').click(); cy.get('#seedPeerClusterIDCopyIcon').should('exist'); - cy.get('#seedPeerClusterIDTooltip').should('exist'); + cy.get('#seedPeerClusterIDTooltip').should('not.exist'); cy.wait(1000); // Display successful copy icon. - cy.get('#seedPeerClusterIDCopyIcon').should('not.exist'); + cy.get('#seedPeerClusterIDCopyIcon').should('exist'); cy.get('#seedPeerClusterIDTooltip').should('not.exist'); // Let's check the copied text. diff --git a/cypress/e2e/clusters/clusters.cy.ts b/cypress/e2e/clusters/clusters.cy.ts index 9be4181..3389e09 100644 --- a/cypress/e2e/clusters/clusters.cy.ts +++ b/cypress/e2e/clusters/clusters.cy.ts @@ -43,7 +43,7 @@ describe('Clusters', () => { ); cy.visit('/clusters'); - cy.viewport(1440, 1080); + cy.viewport(1440, 1480); }); describe('when data is loaded', () => { @@ -86,7 +86,7 @@ describe('Clusters', () => { cy.get('#default-cluster-1') .should('be.visible') .and('contain', 'Default') - .and('have.css', 'background-color', 'rgb(46, 143, 121)'); + .and('have.css', 'background-color', 'rgb(31, 125, 83)'); // Show cluster name. cy.get('#cluster-name-1').should('be.visible').and('contain', 'cluster-1'); @@ -108,7 +108,7 @@ describe('Clusters', () => { cy.get('#default-cluster-2') .should('be.visible') .and('contain', 'Non-Default') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); }); }); @@ -183,8 +183,6 @@ describe('Clusters', () => { describe('pagination', () => { it('pagination updates results and page number', () => { - cy.get('.Mui-selected').invoke('text').should('eq', 'Cluster1'); - // Check number of pagination. cy.get('#clusterPagination > .MuiPagination-ul').children().should('have.length', 7); @@ -193,8 +191,6 @@ describe('Clusters', () => { }); it('when pagination changes, different page results are rendered', () => { - cy.get('.Mui-selected').invoke('text').should('eq', 'Cluster1'); - // Go to last page. cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); @@ -205,7 +201,7 @@ describe('Clusters', () => { cy.get('#default-cluster-8') .should('be.visible') .and('contain', 'Non-Default') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); cy.get('#cluster-name-8').should('be.visible').and('contain', 'cluster-8'); @@ -268,7 +264,7 @@ describe('Clusters', () => { cy.get('#clusterPagination > .MuiPagination-ul .Mui-selected').should('have.text', '5'); - cy.get('#clusters').children().should('have.length', 1); + cy.get('#clustersCard').children().should('have.length', 1); cy.get('#cluster-name-37').should('have.text', 'cluster-37'); @@ -384,7 +380,7 @@ describe('Clusters', () => { cy.get('#free-solo-demo').type('cluster-47'); // No clusters card. - cy.get('#clusters').should('not.exist'); + cy.get('#clustersCard').should('not.exist'); // Pagination has been hidden. cy.get('#clusterPagination > .MuiPagination-ul').should('not.exist'); diff --git a/cypress/e2e/clusters/create-cluster.cy.ts b/cypress/e2e/clusters/create-cluster.cy.ts index 3504202..e8ba95b 100644 --- a/cypress/e2e/clusters/create-cluster.cy.ts +++ b/cypress/e2e/clusters/create-cluster.cy.ts @@ -192,7 +192,7 @@ describe('Create cluster', () => { // 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'); + cy.get('.MuiPaper-message').should('not.exist'); }); it('click the `CANCEL button', () => { diff --git a/cypress/e2e/developer/tokens/create-token.cy.ts b/cypress/e2e/developer/tokens/create-token.cy.ts index 583b259..067503f 100644 --- a/cypress/e2e/developer/tokens/create-token.cy.ts +++ b/cypress/e2e/developer/tokens/create-token.cy.ts @@ -27,7 +27,7 @@ describe('Create token', () => { cy.visit('/developer/personal-access-tokens'); // Click the `ADD PERSONAL ACCESS TOKENS` button. - cy.get('.css-1qdyvok > .MuiButtonBase-root').click(); + cy.get('#new-tokens-button').click(); // Then I see that the current page is the developer/personal-access-tokens/new! cy.url().should('include', '/developer/personal-access-tokens/new'); @@ -140,7 +140,7 @@ describe('Create token', () => { // 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'); + cy.get('.MuiAlert-message').should('not.exist'); }); it('click the `CANCEL button', () => { diff --git a/cypress/e2e/developer/tokens/tokens.cy.ts b/cypress/e2e/developer/tokens/tokens.cy.ts index 1c943a0..fdfab7a 100644 --- a/cypress/e2e/developer/tokens/tokens.cy.ts +++ b/cypress/e2e/developer/tokens/tokens.cy.ts @@ -25,12 +25,7 @@ describe('Tokens', () => { it('when data is loaded', () => { cy.get('[data-testid="isloading"]').should('be.exist'); - cy.get('.css-1qdyvok > .MuiTypography-root').should('have.text', 'Personal access tokens'); - - cy.get('.MuiList-root > :nth-child(2) > .MuiButtonBase-root > .MuiTypography-root').click(); - - // Whether the style selected by menu is Personal access tokens. - cy.get('.MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root').should('have.class', 'Mui-selected'); + cy.get('#token-title').should('have.text', 'Personal access tokens'); // Show token name. cy.get('#root-11').should('be.visible').and('have.text', 'root-11'); @@ -69,7 +64,7 @@ describe('Tokens', () => { }, ); - cy.get('.MuiPaper-root').should('be.visible').and('have.text', `You don't have any tokens.`); + cy.get('#no-tokens').should('be.visible').and('have.text', `You don't have any tokens.`); }); it('should handle API error response', () => { @@ -97,7 +92,7 @@ describe('Tokens', () => { cy.get('#tokens-list').should('not.exist'); // Show You don't have any preheat tokens. - cy.get('.MuiPaper-root').should('be.visible').and('have.text', `You don't have any tokens.`); + cy.get('#no-tokens').should('be.visible').and('have.text', `You don't have any tokens.`); }); describe('pagination', () => { @@ -120,9 +115,9 @@ describe('Tokens', () => { cy.get('#tokens-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '2'); // Show token name. - cy.get('.MuiTypography-inherit').should('be.visible').and('have.text', 'root-1'); + cy.get('#root-1').should('be.visible').and('have.text', 'root-1'); - cy.get('span.css-189ppmh-MuiTypography-root').should('be.visible').and('have.text', 'Thu, Dec 1 2033.'); + cy.get('#expired-at-1').should('be.visible').and('have.text', 'Thu, Dec 1 2033.'); }); it('when you click refresh, the paginated results and page numbers remain unchanged.', () => { diff --git a/cypress/e2e/job/preheats/create-preheat.cy.ts b/cypress/e2e/job/preheats/create-preheat.cy.ts index bdce6b0..7ccd5dc 100644 --- a/cypress/e2e/job/preheats/create-preheat.cy.ts +++ b/cypress/e2e/job/preheats/create-preheat.cy.ts @@ -46,7 +46,7 @@ describe('Create preheat', () => { it('can create preheat', () => { cy.visit('/jobs/preheats'); - cy.get('.css-1g5t85q > .MuiButtonBase-root').click(); + cy.get('#new-preheat').click(); cy.url().should('include', '/jobs/preheats/new'); @@ -321,7 +321,6 @@ describe('Create preheat', () => { it('try to verify header', () => { const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; const key = _.times(101, () => _.sample(characters)).join(''); - const value = _.times(1001, () => _.sample(characters)).join(''); // Select a cluster. cy.get('#select-cluster').click(); @@ -344,13 +343,11 @@ describe('Create preheat', () => { // Show header value verification error message. cy.get('.new_headersValueInput__zn-9E > .MuiFormHelperText-root') .should('be.visible') - .and('have.text', 'Fill in the characters, the length is 1-1000.'); + .and('have.text', 'Fill in the characters, the length is 1-10000.'); // Verification passed. cy.get('.new_headersKeyInput__aZcds > .MuiInputBase-root > .MuiInputBase-input').type('key'); cy.get('.new_headersKeyInput__aZcds > .MuiFormHelperText-root').should('not.exist'); - cy.get('.new_headersValueInput__zn-9E > .MuiInputBase-root').type('value'); - cy.get('.new_headersValueInput__zn-9E > .MuiFormHelperText-root').should('not.exist'); // Incorrect header key entered. cy.get('.new_headersKeyInput__aZcds > .MuiInputBase-root > .MuiInputBase-input').clear(); @@ -371,19 +368,6 @@ describe('Create preheat', () => { cy.get('.new_headersKeyInput__aZcds > .MuiInputBase-root > .MuiInputBase-input').type('key'); cy.get('.new_headersKeyInput__aZcds > .MuiFormHelperText-root').should('not.exist'); - // Incorrect header value entered. - cy.get('.new_headersValueInput__zn-9E > .MuiInputBase-root').type(value); - - // Show header value verification error message. - cy.get('.new_headersValueInput__zn-9E > .MuiFormHelperText-root') - .should('be.visible') - .and('have.text', 'Fill in the characters, the length is 1-1000.'); - - // Show header value verification error message. - cy.get('.new_headersValueInput__zn-9E > .MuiFormHelperText-root') - .should('be.visible') - .and('have.text', 'Fill in the characters, the length is 1-1000.'); - cy.get('#save').click(); // Preheat creation failed, the page is still in preheat/new! diff --git a/cypress/e2e/job/preheats/preheat.cy.ts b/cypress/e2e/job/preheats/preheat.cy.ts index 3b4fa71..2fbcbc6 100644 --- a/cypress/e2e/job/preheats/preheat.cy.ts +++ b/cypress/e2e/job/preheats/preheat.cy.ts @@ -44,14 +44,14 @@ describe('Preheat', () => { it('click the breadcrumb', () => { cy.get('[data-testid="isloading"]').should('be.exist'); - cy.get(':nth-child(6) > .css-1mlhis1 > .css-1ozvesn > .MuiTypography-root > .MuiBox-root').click(); + cy.get('#preheat-6').click(); cy.url().should('include', '/jobs/preheats/6'); // Check for breadcrumb. - cy.get('.MuiBreadcrumbs-ol > :nth-child(3) > .MuiTypography-root').should('exist').and('contain', 'preheats'); + cy.get(':nth-child(3) > .MuiTypography-root').should('exist').and('contain', 'Preheat'); - cy.get('.MuiBreadcrumbs-ol > :nth-child(3) > .MuiTypography-root').click(); + cy.get(':nth-child(3) > .MuiTypography-root').click(); cy.get('[data-testid="isloading"]').should('not.exist'); @@ -244,7 +244,7 @@ describe('Preheat', () => { }); it('unable to display breadcrumb', () => { - cy.get('.MuiBreadcrumbs-ol').should('be.visible').and('contain', 'preheats'); + cy.get('.MuiBreadcrumbs-ol').should('be.visible').and('contain', 'Preheat'); cy.get('.MuiBreadcrumbs-ol > :nth-child(5) > .MuiTypography-root').should('have.text', '-'); }); @@ -303,7 +303,7 @@ describe('Preheat', () => { }); it('unable to display breadcrumb', () => { - cy.get('.MuiBreadcrumbs-ol').should('be.visible').and('contain', 'preheats'); + cy.get('.MuiBreadcrumbs-ol').should('be.visible').and('contain', 'Preheat'); cy.get('.MuiBreadcrumbs-ol > :nth-child(5) > .MuiTypography-root').should('have.text', '-'); }); diff --git a/cypress/e2e/job/preheats/preheats.cy.ts b/cypress/e2e/job/preheats/preheats.cy.ts index e3f9c3f..ba35709 100644 --- a/cypress/e2e/job/preheats/preheats.cy.ts +++ b/cypress/e2e/job/preheats/preheats.cy.ts @@ -67,30 +67,32 @@ describe('Preheats', () => { ).as('preheats'); cy.get('[data-testid="isloading"]').should('be.exist'); cy.wait(120000); + // Executed every 3 seconds, it should be executed 2 times after 6 seconds. cy.get('@preheats').then(() => { expect(interceptCount).to.be.greaterThan(0); expect(interceptCount).to.be.closeTo(2, 1); }); + cy.get('[data-testid="isloading"]').should('not.exist'); cy.get('.MuiList-root > :nth-child(3) > .MuiButtonBase-root').click(); - // Whether the style selected by menu is Preheat. - cy.get( - ':nth-child(3) > .MuiCollapse-root > .MuiCollapse-wrapper > .MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root', - ).should('have.class', 'Mui-selected'); - cy.get('.css-1g5t85q > .MuiTypography-root').should('be.visible').and('have.text', 'Preheats'); + // The preheating status is displayed as PENDING. cy.get('#PENDING-11').should('exist'); cy.get('#id-11').should('have.text', 11); + // cy.get('#created_at-11').should('have.text', '2023-03-23 16:29:18'); cy.get('#description-11').should('have.text', 'This is a preheat task with status pending'); + // The preheating status is displayed as FAILURE. cy.get('#FAILURE-10').should('exist'); cy.get('#description-10').should('have.text', 'This is a preheat task with status failure'); + // The preheating status is displayed as SUCCESS. cy.get('#list-8 > .css-1mlhis1').should('exist').find('#SUCCESS-8').should('exist'); cy.get('#description-8').should('have.text', 'This is a preheat task with status success'); }); + it('should display preheat success list', () => { cy.intercept( { @@ -113,6 +115,7 @@ describe('Preheats', () => { cy.get('#preheats-list').children().should('have.length', 6); cy.get('#preheat-pagination').should('not.exist'); }); + it('should display preheat failure list', () => { cy.intercept( { @@ -134,6 +137,7 @@ describe('Preheats', () => { // Check how many preheat tasks are in success failure. cy.get('#preheats-list').children().should('have.length', 4); }); + it('should display preheat pending list', () => { let interceptCount = 0; cy.intercept( @@ -288,7 +292,7 @@ describe('Preheats', () => { cy.get('#list-1').should('exist').find('#SUCCESS-1').should('exist'); // Go to show preheat page. - cy.get('#preheat-1 > .MuiBox-root').click(); + cy.get('#preheat-1').click(); // Then I see that the current page is the show update personal-access-tokens. cy.url().should('include', '/jobs/preheats/1'); diff --git a/cypress/e2e/job/task/clear.cy.ts b/cypress/e2e/job/task/clear.cy.ts index 5e80fd5..149baae 100644 --- a/cypress/e2e/job/task/clear.cy.ts +++ b/cypress/e2e/job/task/clear.cy.ts @@ -16,6 +16,20 @@ describe('Clear', () => { it('when no data is loaded', () => { cy.get('#no-task').should('not.exist'); + cy.get('#light').should('exist'); + cy.get('#no-task-image').should('exist'); + + cy.get('#dark').click(); + // Dark mode should show a different no-task-image. + + cy.get('.Mui-selected').invoke('text').should('contain', 'Dark'); + + cy.get('.Mui-selected').invoke('text').should('not.contain', 'Light'); + + cy.get('#no-task-image').should('not.exist'); + + cy.get('#dark-no-task-image').should('exist'); + cy.intercept( { method: 'post', @@ -299,6 +313,12 @@ describe('Clear', () => { expect(interceptCount).to.be.closeTo(2, 1); }); + // Executed every 1 minute and once after 1 minute. + cy.get('@cache').then(() => { + expect(interceptCount).to.be.greaterThan(0); + expect(interceptCount).to.be.closeTo(2, 1); + }); + cy.intercept( { method: 'GET', @@ -314,13 +334,6 @@ describe('Clear', () => { // Preheat API error response after three seconds. cy.wait(60000); - - // Show error message. - cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Unauthorized'); - - // Close error message. - cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); - cy.get('.MuiAlert-message').should('not.exist'); }); it('Delete cache API error response', () => { diff --git a/cypress/e2e/job/task/execution.cy.ts b/cypress/e2e/job/task/execution.cy.ts index 4b40d91..03c941e 100644 --- a/cypress/e2e/job/task/execution.cy.ts +++ b/cypress/e2e/job/task/execution.cy.ts @@ -43,12 +43,12 @@ describe('Executions', () => { // Show isloading. cy.get('[data-testid="isloading"]').should('be.exist'); - cy.get('#execution-9 > .MuiBox-root').click(); + cy.get('#execution-9').click(); cy.url().should('include', '/jobs/task/executions/9'); // Check for breadcrumb. - cy.get('.MuiBreadcrumbs-ol').should('exist').and('contain', 'executions').and('contain', '9'); + cy.get('.MuiBreadcrumbs-ol').should('exist').and('contain', 'Executions').and('contain', '9'); cy.get('.MuiBreadcrumbs-ol > :nth-child(5) > .MuiTypography-root').click(); diff --git a/cypress/e2e/job/task/executions.cy.ts b/cypress/e2e/job/task/executions.cy.ts index 998109d..eda6ddb 100644 --- a/cypress/e2e/job/task/executions.cy.ts +++ b/cypress/e2e/job/task/executions.cy.ts @@ -84,13 +84,6 @@ describe('Executions', () => { cy.get('.MuiList-root > :nth-child(3) > .MuiButtonBase-root').click(); - // Whether the style selected by menu is Task. - cy.get( - ':nth-child(3) > .MuiCollapse-root > .MuiCollapse-wrapper > .MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root', - ).should('have.class', 'Mui-selected'); - - cy.get('.MuiList-root > .Mui-selected').should('be.visible').and('have.text', 'Task'); - // The executions status is displayed as PENDING. cy.get('#list-11 > .css-1mlhis1').should('exist').find('#PENDING-11').should('exist'); cy.get('#id-11').should('have.text', 11); @@ -318,7 +311,7 @@ describe('Executions', () => { cy.get('#list-1').should('exist').find('#SUCCESS-1').should('exist'); // Go to show executions page. - cy.get('#execution-1 > .MuiBox-root').click(); + cy.get('#execution-1').click(); // Then I see that the current page is the show update personal-access-tokens. cy.url().should('include', '/jobs/task/executions/1'); diff --git a/cypress/e2e/menu/menu.cy.ts b/cypress/e2e/menu/menu.cy.ts index 2229fe0..a0e8e1d 100644 --- a/cypress/e2e/menu/menu.cy.ts +++ b/cypress/e2e/menu/menu.cy.ts @@ -3,14 +3,39 @@ import seedPeers from '../../fixtures/seed-peers/seed-peers.json'; import schedulers from '../../fixtures/schedulers/schedulers.json'; describe('Menu', () => { + beforeEach(() => { + cy.viewport(1440, 1080); + }); + it('user not signin', () => { // redirect when not signin. cy.visit('/'); // Then I see that the current page is the signin! cy.url().should('include', '/signin'); + }); - cy.viewport(1440, 1080); + it('should switch to dark mode', () => { + cy.guestSignin(); + cy.visit('/'); + + // Click the Toggle Dark button. + cy.get('#dark').click(); + + cy.get('.Mui-selected').invoke('text').should('contain', 'Dark'); + + cy.get('.Mui-selected').invoke('text').should('not.contain', 'Light'); + + cy.get('#main').should('have.css', 'background-color', 'rgb(31, 36, 48)'); + + // Click the Toggle Light button. + cy.get('#light').click(); + + cy.get('.Mui-selected').invoke('text').should('not.contain', 'Dark'); + + cy.get('.Mui-selected').invoke('text').should('contain', 'Light'); + + cy.get('#main').should('have.css', 'background-color', 'rgb(244, 246, 248)'); }); describe('try to signin as guest user', () => { @@ -32,32 +57,36 @@ describe('Menu', () => { }); it('should navigate to the tokens page', () => { - cy.get('.MuiList-root > :nth-child(2) > .MuiButtonBase-root').click(); - cy.get('.MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root').click(); + cy.get('#developer').click(); + cy.get('#personal-access-tokens').click(); // Then I see that the current page is the tokens! cy.url().should('include', '/developer/personal-access-tokens'); // The selected menu is tokens. - cy.get('.MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root').should('have.class', 'Mui-selected'); + cy.get('#personal-access-tokens').should('have.class', 'Mui-selected'); + + cy.get('#dragonfly').click(); + // Then I see that the current page is the clusters! + cy.url().should('include', '/clusters'); }); it('should navigate to the preheats page and task page', () => { - cy.get('.MuiList-root > :nth-child(3) > .MuiButtonBase-root').click(); - cy.get('[href="/jobs/preheats"]').click(); + cy.get('#jobs').click(); + cy.get('#preheats').click(); // Then I see that the current page is the preheats! cy.url().should('include', '/jobs/preheats'); // The selected menu is preheats. - cy.get('[href="/jobs/preheats"]').should('have.class', 'Mui-selected'); + cy.get('#preheats').should('have.class', 'Mui-selected'); - cy.get('[href="/jobs/task/clear"]').click(); + cy.get('#task').click(); // Then I see that the current page is the task! cy.url().should('include', '/jobs/task/clear'); - cy.get('[href="/jobs/task/clear"]').should('have.class', 'Mui-selected'); + cy.get('#task').should('have.class', 'Mui-selected'); }); }); @@ -114,46 +143,42 @@ describe('Menu', () => { }); it('should navigate to the tokens page', () => { - cy.get('.MuiList-root > :nth-child(2) > .MuiButtonBase-root').click(); - cy.get('.MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root').click(); + cy.get('#developer').click(); + cy.get('#personal-access-tokens').click(); // Then I see that the current page is the tokens! cy.url().should('include', '/developer/personal-access-tokens'); // The selected menu is tokens. - cy.get('.MuiCollapse-wrapperInner > .MuiList-root > .MuiButtonBase-root').should('have.class', 'Mui-selected'); + cy.get('#personal-access-tokens').should('have.class', 'Mui-selected'); }); it('should navigate to the preheats page and task page', () => { - cy.get('.MuiList-root > :nth-child(3) > .MuiButtonBase-root').click(); - cy.get('[href="/jobs/preheats"]').click(); - - // Show page loading. - cy.get('#page-loading').should('be.visible'); + cy.get('#jobs').click(); + cy.get('#preheats').click(); // Then I see that the current page is the preheats! cy.url().should('include', '/jobs/preheats'); // The selected menu is preheats. - cy.get('[href="/jobs/preheats"]').should('have.class', 'Mui-selected'); + cy.get('#preheats').should('have.class', 'Mui-selected'); - cy.get('[href="/jobs/task/clear"]').click(); + cy.get('#task').click(); // Then I see that the current page is the task! cy.url().should('include', '/jobs/task/clear'); - // The selected menu is task. - cy.get('[href="/jobs/task/clear"]').should('have.class', 'Mui-selected'); + cy.get('#task').should('have.class', 'Mui-selected'); }); it('should navigate to the users page', () => { - cy.get('[href="/users"]').click(); + cy.get('#users').click(); // Then I see that the current page is the users! cy.url().should('include', '/users'); // The selected menu is users. - cy.get('[href="/users"]').should('have.class', 'Mui-selected'); + cy.get('#users').should('have.class', 'Mui-selected'); }); it('should navigate to the profile page', () => { @@ -167,6 +192,42 @@ describe('Menu', () => { cy.url().should('include', '/profile'); }); + it('The menu should be smaller', () => { + // The menu should be smaller. + cy.get('#closure').should('exist').click(); + cy.get('#expand').should('exist'); + cy.get('#closure').should('not.exist'); + + // Go to tokens page. + cy.get('#developer').click(); + + cy.get('#personal-access-tokens').click(); + + // Then I see that the current page is the tokens! + cy.url().should('include', '/developer/personal-access-tokens'); + + // Go to jobs page. + cy.get('#jobs').click(); + cy.get('#preheats').click(); + + // Then I see that the current page is the preheats! + cy.url().should('include', '/jobs/preheats'); + + // Go to task page. + cy.get('#jobs').click(); + cy.get('#task').click(); + + // Then I see that the current page is the task! + cy.url().should('include', '/jobs/task/clear'); + + // Go to user page. + + cy.get('#users').click(); + + // Then I see that the current page is the users! + cy.url().should('include', '/users'); + }); + it('can logout', () => { cy.intercept( { diff --git a/cypress/e2e/peers/peers.cy.ts b/cypress/e2e/peers/peers.cy.ts index 100ef86..438ec57 100644 --- a/cypress/e2e/peers/peers.cy.ts +++ b/cypress/e2e/peers/peers.cy.ts @@ -250,8 +250,6 @@ describe('Peers', () => { }); describe('refresh', () => { - beforeEach(() => {}); - it('can refresh peers and return new data', () => { cy.get('#total').should('have.text', 10); cy.get('#git-version').should('have.text', 4); @@ -261,7 +259,7 @@ describe('Peers', () => { // Click refresh button. cy.get('#refresh').click(); - cy.get('.css-70qvj9 > .MuiTypography-root').should('be.visible').and('have.text', 'Refresh'); + cy.get('#refresh-title').should('be.visible').and('have.text', 'Refresh'); cy.get('#cancel').click(); cy.get('#refresh').click(); @@ -316,7 +314,7 @@ describe('Peers', () => { // Click refresh button. cy.get('#refresh').click(); - cy.get('.css-70qvj9 > .MuiTypography-root').should('be.visible').and('have.text', 'Refresh'); + cy.get('#refresh-title').should('be.visible').and('have.text', 'Refresh'); cy.intercept( { @@ -355,7 +353,7 @@ describe('Peers', () => { // Click refresh button. cy.get('#refresh').click(); - cy.get('.css-70qvj9 > .MuiTypography-root').should('be.visible').and('have.text', 'Refresh'); + cy.get('#refresh-title').should('be.visible').and('have.text', 'Refresh'); cy.get('#cancel').click(); cy.get('#refresh').click(); diff --git a/cypress/e2e/profile/profile.cy.ts b/cypress/e2e/profile/profile.cy.ts index 58005d3..3c122c7 100644 --- a/cypress/e2e/profile/profile.cy.ts +++ b/cypress/e2e/profile/profile.cy.ts @@ -46,27 +46,9 @@ describe('Profile', () => { cy.viewport(1440, 1080); }); - it('opens user profile page from the home page', () => { - cy.visit('/'); - - cy.get('#unfold-more').click(); - - // Go to profil page. - cy.get('#profile-menu').click(); - - // Then I see that the current page is the profile! - cy.url().should('include', '/profile'); - - cy.get('#my-profile').should('contain', 'My Profile'); - }); - it('when data is loaded', () => { - cy.get('#menu-name').should('be.visible').and('have.text', 'root'); - - cy.get('#menu-email').should('be.visible').and('have.text', 'root@example.com'); - // Show user name. - cy.get('.css-70qvj9 > .MuiBox-root > .MuiTypography-h5').should('be.visible').and('have.text', 'root'); + cy.get('#name-title').should('be.visible').and('have.text', 'root'); // Show user description. cy.get('#description').should('be.visible').and('have.text', 'I am root'); @@ -74,14 +56,14 @@ describe('Profile', () => { cy.get('#name').should('be.visible').and('have.text', 'root'); cy.get('#email').should('be.visible').and('have.text', 'root@example.com'); cy.get('#location').should('be.visible').and('have.text', 'Hangzhou'); - cy.get('#phone').should('be.visible').and('have.text', 1234567890); + cy.get('#phone').should('be.visible').and('have.text', '+86 153 1234 5678'); cy.get('#created_at').should('be.visible').and('have.text', '2023-11-06 06:09:04'); // Check Update Personal Information form. cy.get('.MuiGrid-root > .MuiButtonBase-root').click(); cy.get('#bio').should('have.value', 'I am root'); - cy.get('#phone').should('have.value', 1234567890); + cy.get('#phone').should('have.value', '+86 153 1234 5678'); cy.get('#location').should('have.value', 'Hangzhou'); cy.get('#email').should('have.value', 'root@example.com'); }); @@ -100,11 +82,8 @@ describe('Profile', () => { }, ); - cy.get('#menu-name').should('be.visible').and('have.text', '-'); - cy.get('#menu-email').should('be.visible').and('have.text', '-'); - // Show user name. - cy.get('.MuiTypography-caption').should('be.visible').and('have.text', '-'); + cy.get('#name-title').should('be.visible').and('have.text', '-'); // Show user description. cy.get('#description').should('be.visible').and('have.text', '-'); @@ -119,7 +98,7 @@ describe('Profile', () => { cy.get('.MuiGrid-root > .MuiButtonBase-root').click(); cy.get('#bio').should('have.value', ''); - cy.get('#phone').should('have.value', ''); + cy.get('#phone').should('have.value', '+86'); cy.get('#location').should('have.value', ''); cy.get('#email').should('have.value', ''); }); @@ -144,7 +123,7 @@ describe('Profile', () => { cy.get('.MuiGrid-root > .MuiButtonBase-root').click(); cy.get('#bio').should('have.value', ''); - cy.get('#phone').should('have.value', ''); + cy.get('#phone').should('have.value', '+86'); cy.get('#location').should('have.value', ''); cy.get('#email').should('have.value', ''); }); @@ -193,9 +172,6 @@ describe('Profile', () => { cy.get('#save').click(); - // Check whether the navigation bar email has changed. - cy.get('.MuiTypography-caption').should('have.text', 'root@gmail.com'); - // Check if profile description is updated. cy.get('#description').should('be.visible').and('have.text', 'I am root, I will change the description'); @@ -206,7 +182,7 @@ describe('Profile', () => { cy.get('#location').should('be.visible').and('have.text', 'Shanghai'); // Check if profile phone is updated. - cy.get('#phone').should('be.visible').and('have.text', 15123456789); + cy.get('#phone').should('be.visible').and('have.text', '+86 153 1234 5678'); }); it('click the `CANCEL button', () => { @@ -222,7 +198,6 @@ describe('Profile', () => { cy.get('#description').should('be.visible').and('have.text', 'I am root'); // Check whether the navigation bar email has changed. - cy.get('.MuiTypography-caption').should('have.text', 'root@example.com'); cy.get('#email').should('be.visible').and('have.text', 'root@example.com'); // Click EDIT button. @@ -301,7 +276,7 @@ describe('Profile', () => { // Should display message phone the validation error. cy.get('#phone').clear(); - cy.get('#phone').type('1234567890'); + cy.get('#phone').type('+86 153 1234 123123'); // Show verification error message. cy.get('#phone-helper-text').should('be.visible').and('have.text', 'Invalid phone number.'); @@ -309,7 +284,7 @@ describe('Profile', () => { cy.get('.css-1033rfx > .MuiTypography-root').should('exist').and('have.text', 'Update Personal Information'); cy.get('#phone').clear(); - cy.get('#phone').type('15123456789'); + cy.get('#phone').type('+86 151 2345 6789'); // Verification passed. cy.get('#phone-helper-text').should('not.exist'); @@ -353,8 +328,21 @@ describe('Profile', () => { }); }); - // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + // Click change password tab. + cy.get('#tab-password').click(); + + cy.get('#oldPassword').type('dragonfly1'); + cy.get('#newPassword').type('dragonfly2'); + cy.get('#confirmNewPassword').type('dragonfly2'); + + // Click cancel password button. + cy.get('#cancel-change-password').click(); + + // Input should be cleared. + cy.get('#oldPassword').should('have.value', ''); + cy.get('#newPassword').should('have.value', ''); + cy.get('#confirmNewPassword').should('have.value', ''); + cy.get('#oldPassword').type('dragonfly1'); cy.get('#newPassword').type('dragonfly2'); cy.get('#confirmNewPassword').type('dragonfly2'); @@ -366,24 +354,20 @@ describe('Profile', () => { cy.url().should('include', 'signin'); }); - it('click the `CANCEL button', () => { + it('click the Profile tab', () => { // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); - cy.get('.profile_profileContainer__l5i6P > .MuiGrid-root > .MuiTypography-root') - .should('be.visible') - .and('have.text', 'Change Password'); + cy.get('#tab-password').click(); + cy.get('#change-password-title').should('be.visible').and('have.text', 'Change Password'); cy.get('#oldPassword').type('dragonfly1'); cy.get('#newPassword').type('dragonfly2'); cy.get('#confirmNewPassword').type('dragonfly2'); // Click cancel button. - cy.get('#cancel-change-password').click(); - cy.get('.profile_profileContainer__l5i6P > .MuiGrid-root > .MuiTypography-root').should('not.exist'); + cy.get('#tab-profile').click(); + cy.get('#change-password-title').should('not.exist'); - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); - cy.get('.profile_profileContainer__l5i6P > .MuiGrid-root > .MuiTypography-root') - .should('be.visible') - .and('have.text', 'Change Password'); + cy.get('#tab-password').click(); + cy.get('#change-password-title').should('be.visible').and('have.text', 'Change Password'); // Check if old password is empty. cy.get('#oldPassword').should('have.text', ''); @@ -415,7 +399,7 @@ describe('Profile', () => { cy.visit('/profile'); // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); cy.get('#oldPassword').type('dragonfly1'); cy.get('#newPassword').type('dragonfly2'); cy.get('#confirmNewPassword').type('dragonfly2'); @@ -434,7 +418,7 @@ describe('Profile', () => { }); // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); cy.get('#oldPassword').type('dragonfly1'); cy.get('#newPassword').type('dragonfly2'); cy.get('#confirmNewPassword').type('dragonfly2'); @@ -454,7 +438,7 @@ describe('Profile', () => { }); // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); cy.get('#oldPassword').type('dragonfly1'); cy.get('#newPassword').type('dragonfly2'); cy.get('#confirmNewPassword').type('dragonfly2'); @@ -466,7 +450,7 @@ describe('Profile', () => { it('cannot change password without required attributes', () => { // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); cy.get('#change-password').click(); // Show error message. @@ -490,7 +474,7 @@ describe('Profile', () => { const newPasswordLengthIsInsufficient = _.times(7, () => _.sample(characters)).join(''); // Click change password button. - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); // Should display message old password the validation error. cy.get('#oldPassword').type(oldPassword); @@ -543,7 +527,7 @@ describe('Profile', () => { }); it('click the password hide butto', () => { - cy.get('.css-1a9getn > .MuiButtonBase-root').click(); + cy.get('#tab-password').click(); // Verify the display status of the content of the old password input box. cy.get('#oldPassword').type('dragonfly1'); diff --git a/cypress/e2e/schedulers/scheduler.cy.ts b/cypress/e2e/schedulers/scheduler.cy.ts index 2315b3e..9588501 100644 --- a/cypress/e2e/schedulers/scheduler.cy.ts +++ b/cypress/e2e/schedulers/scheduler.cy.ts @@ -119,7 +119,7 @@ describe('Scheduler', () => { cy.get('#status') .should('be.visible') .and('contain', 'Active') - .and('have.css', 'background-color', 'rgb(46, 143, 121)'); + .and('have.css', 'background-color', 'rgb(31, 125, 83)'); // Show features. cy.get('#features').should('be.visible').and('contain', 'Schedule').and('contain', 'Preheat'); @@ -154,7 +154,7 @@ describe('Scheduler', () => { cy.get('#status') .should('be.visible') .and('contain', 'Inactive') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); }); }); diff --git a/cypress/e2e/schedulers/schedulers.cy.ts b/cypress/e2e/schedulers/schedulers.cy.ts index 0199a82..e54d91f 100644 --- a/cypress/e2e/schedulers/schedulers.cy.ts +++ b/cypress/e2e/schedulers/schedulers.cy.ts @@ -65,17 +65,22 @@ describe('Schedulers', () => { // Show idloading. cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); + // Show hostname. cy.get('#hostname-scheduler-7').should('be.visible').and('contain', 'scheduler-7'); + // Show ip. cy.get('#ip-7').should('be.visible').and('contain', '30.44.98.202'); + // Show state. cy.get('#state-7') .should('be.visible') .and('contain', 'Active') - .and('have.css', 'background-color', 'rgb(46, 143, 121)'); + .and('have.css', 'background-color', 'rgb(31, 125, 83)'); + // Show features. cy.get('#features-7').should('be.visible').and('contain', 'Schedule'); + // Show scheduler-5 information. cy.get('#hostname-scheduler-5').should('be.visible').and('contain', 'scheduler-5'); cy.get('#ip-5').should('be.visible').and('contain', '20.14.28.202'); @@ -83,7 +88,15 @@ describe('Schedulers', () => { cy.get('#state-43') .should('be.visible') .and('contain', 'Inactive') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); + + // Click scheduler-18 operation button. + cy.get('#operation-18').click(); + + cy.get(':nth-child(12) > .MuiPaper-root > .MuiList-root > .schedulers_menu__mxj5m > #view-scheduler-18').click(); + + // Then I see that the current page is the scheduler 18. + cy.url().should('include', 'clusters/1/schedulers/18'); }); it('can display schedulers card', () => { @@ -97,7 +110,7 @@ describe('Schedulers', () => { .should('be.visible') .and('have.text', 'Active') .and('have.css', 'background-color', 'rgba(0, 167, 111, 0.1)'); - cy.get(':nth-child(4) > .MuiButtonBase-root').click(); + cy.get('.MuiPagination-ul > :nth-child(4) > .MuiButtonBase-root').click(); cy.get('#card-hostname-scheduler-41').should('be.visible').and('have.text', 'scheduler-41'); // Show status. cy.get('#card-state-41') @@ -615,7 +628,7 @@ describe('Schedulers', () => { cy.get('[value="inactive"]').click(); - cy.get(':nth-child(4) > .MuiButtonBase-root').click(); + cy.get('.MuiPagination-ul > :nth-child(4) > .MuiButtonBase-root').click(); cy.get('#operation-10').click(); @@ -792,7 +805,7 @@ describe('Schedulers', () => { // Close delete inactive schedulers. cy.get('#close-delete-icon').click(); cy.get('#delete-all-inactive-instances').click(); - cy.get('.css-pbbh6n > .css-70qvj9 > .MuiTypography-root').should('have.text', 'Delete inactive instances'); + cy.get('#delete-inactive-instances-title').should('have.text', 'Delete inactive instances'); cy.get('#schedulerTotal').should('have.text', '0 inactive'); cy.get('#back-button').should('be.disabled'); // Check next button. @@ -869,7 +882,7 @@ describe('Schedulers', () => { } cy.get('#delete-all-inactive-instances').click(); - cy.get('.css-pbbh6n > .css-70qvj9 > .MuiTypography-root').should('have.text', 'Delete inactive instances'); + cy.get('#delete-inactive-instances-title').should('have.text', 'Delete inactive instances'); cy.get('#schedulerTotal').should('have.text', '34 inactive'); cy.get('#back-button').should('be.disabled'); cy.get('#next-button').should('not.be.disabled'); diff --git a/cypress/e2e/seed-peers/seed-peer.cy.ts b/cypress/e2e/seed-peers/seed-peer.cy.ts index cc027c5..a0afdc3 100644 --- a/cypress/e2e/seed-peers/seed-peer.cy.ts +++ b/cypress/e2e/seed-peers/seed-peer.cy.ts @@ -56,7 +56,7 @@ describe('Seed peer', () => { it('click the hostname', () => { cy.visit('/clusters/1/seed-peers'); - cy.get(':nth-child(4) > .MuiButtonBase-root').click(); + cy.get('.MuiPagination-ul > :nth-child(4) > .MuiButtonBase-root').click(); cy.get('#card-hostname-seed-peer-10').should('have.text', 'seed-peer-10'); cy.get('#card-hostname-seed-peer-10').click(); @@ -121,7 +121,7 @@ describe('Seed peer', () => { cy.get('#status') .should('be.visible') .and('contain', 'Active') - .and('have.css', 'background-color', 'rgb(46, 143, 121)'); + .and('have.css', 'background-color', 'rgb(31, 125, 83)'); // Show Created At. cy.get('#created-at').should('have.text', '2023-11-11 20:09:08'); @@ -147,7 +147,7 @@ describe('Seed peer', () => { cy.get('#status') .should('be.visible') .and('contain', 'Inactive') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); }); }); @@ -196,7 +196,7 @@ describe('Seed peer', () => { cy.get('#type').should('contain', '-'); // Show Start. - cy.get(':nth-child(6) > .css-1ltbflq-MuiTypography-root').should('contain', '-'); + cy.get('#status').should('contain', '-'); // Show Created At. cy.get('#created-at').should('contain', '-'); @@ -260,7 +260,7 @@ describe('Seed peer', () => { cy.get('#type').should('contain', '-'); // Show Start. - cy.get(':nth-child(6) > .css-1ltbflq-MuiTypography-root').should('contain', '-'); + cy.get('#status').should('contain', '-'); // Show Created At. cy.get('#created-at').should('contain', '-'); diff --git a/cypress/e2e/seed-peers/seed-peers.cy.ts b/cypress/e2e/seed-peers/seed-peers.cy.ts index 765242b..4393833 100644 --- a/cypress/e2e/seed-peers/seed-peers.cy.ts +++ b/cypress/e2e/seed-peers/seed-peers.cy.ts @@ -74,11 +74,11 @@ describe('Seed peers', () => { cy.get(':nth-child(1) > :nth-child(8) > .MuiChip-root') .should('be.visible') .and('contain', 'Active') - .and('have.css', 'background-color', 'rgb(46, 143, 121)'); + .and('have.css', 'background-color', 'rgb(31, 125, 83)'); }); it('can display seed peers card', () => { - cy.get(':nth-child(4) > .MuiButtonBase-root').click(); + cy.get('.MuiPagination-ul > :nth-child(4) > .MuiButtonBase-root').click(); cy.get('#card-id-7').should('be.visible').and('have.text', '7'); // Show hostname. @@ -329,7 +329,7 @@ describe('Seed peers', () => { cy.get(':nth-child(5) > :nth-child(8) > .MuiChip-root') .should('be.visible') .and('contain', 'Inactive') - .and('have.css', 'background-color', 'rgb(28, 41, 58)'); + .and('have.css', 'background-color', 'rgb(24, 35, 15)'); // Go to last page. cy.get(':nth-child(7) > .MuiButtonBase-root').click(); @@ -554,7 +554,7 @@ describe('Seed peers', () => { cy.get('#card').click(); // Go to last page. - cy.get(':nth-child(4) > .MuiButtonBase-root').click(); + cy.get('.MuiPagination-ul > :nth-child(4) > .MuiButtonBase-root').click(); // Check the current page number. cy.get('#seed-peer-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '3'); @@ -895,7 +895,7 @@ describe('Seed peers', () => { cy.get('#close-delete-icon').click(); cy.get('#delete-all-inactive-instances').click(); - cy.get('.css-pbbh6n > .css-70qvj9 > .MuiTypography-root').should('have.text', 'Delete inactive instances'); + cy.get('#delete-inactive-instances-title').should('have.text', 'Delete inactive instances'); cy.get('#seedPeerTotal').should('have.text', '0 inactive'); cy.get('#back-button').should('be.disabled'); @@ -983,7 +983,7 @@ describe('Seed peers', () => { cy.get('#delete-all-inactive-instances').click(); - cy.get('.css-pbbh6n > .css-70qvj9 > .MuiTypography-root').should('have.text', 'Delete inactive instances'); + cy.get('#delete-inactive-instances-title').should('have.text', 'Delete inactive instances'); cy.get('#seedPeerTotal').should('have.text', '20 inactive'); cy.get('#back-button').should('be.disabled'); cy.get('#next-button').should('not.be.disabled'); diff --git a/cypress/e2e/signin/signin.cy.ts b/cypress/e2e/signin/signin.cy.ts index e278024..8457982 100644 --- a/cypress/e2e/signin/signin.cy.ts +++ b/cypress/e2e/signin/signin.cy.ts @@ -136,12 +136,12 @@ describe('Signin', () => { }); it('click the `Create an account` button', () => { - cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); + cy.get('#create-account').click(); // Then I see that the current page is the signup! cy.url().should('include', '/signup'); - cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); + cy.get('#sign-in').click(); // Then I see that the current page is the signin! cy.url().should('include', '/signin'); diff --git a/cypress/e2e/signup/signup.cy.ts b/cypress/e2e/signup/signup.cy.ts index 988494c..9e3499f 100644 --- a/cypress/e2e/signup/signup.cy.ts +++ b/cypress/e2e/signup/signup.cy.ts @@ -98,12 +98,12 @@ describe('Signup', () => { }); it('click the `Sign in` button', () => { - cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); + cy.get('#sign-in').click(); // Then I see that the current page is the signin! cy.url().should('include', '/signin'); - cy.get('.MuiTypography-inherit > .MuiTypography-root').click(); + cy.get('#create-account').click(); // Then I see that the current page is the signup! cy.url().should('include', '/signup'); diff --git a/cypress/e2e/users/create.user.cy.ts b/cypress/e2e/users/create.user.cy.ts new file mode 100644 index 0000000..8debb46 --- /dev/null +++ b/cypress/e2e/users/create.user.cy.ts @@ -0,0 +1,252 @@ +import _ from 'lodash'; +import createUsers from '../../fixtures/users/create-user.json'; +import users from '../../fixtures/users/users.json'; + +describe('Create user', () => { + beforeEach(() => { + cy.signin(); + + cy.visit('/users/new'); + + cy.viewport(1440, 1080); + }); + + it('can create user', () => { + cy.visit('/users'); + + cy.intercept( + { + method: 'GET', + url: '/api/v1/users?page=1&per_page=10000000', + }, + (req) => { + req.reply({ + statusCode: 200, + body: users, + }); + }, + ); + + // Go to last page. + cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); + + // There is only one piece of data on the last pag. + cy.get('#user-table-body').children().should('have.length', 1); + + cy.get('#create-user').click(); + + // Then I see that the current page is the New user! + cy.url().should('include', '/users/new'); + + cy.get('.MuiBreadcrumbs-ol').should('contain', 'New user'); + + cy.get('#account').type('billy'); + + cy.get('#email').type('billy@example.com'); + + cy.get('#bio').type('I am billy'); + + cy.get('#phone').type('18012341234'); + + cy.get('#location').type('ParisFrance'); + + cy.get('#password').type('Dragonfly1'); + + cy.get('#confirmPassword').type('Dragonfly1'); + + cy.intercept('POST', '/api/v1/users/signup', (req) => { + req.reply({ + statusCode: 200, + body: [], + }); + }); + + cy.intercept( + { + method: 'GET', + url: '/api/v1/users?page=1&per_page=10000000', + }, + (req) => { + req.reply({ + statusCode: 200, + body: createUsers, + }); + }, + ); + + cy.get('#save').click(); + + // Go to last page. + cy.get('.MuiPagination-ul > :nth-child(3) > .MuiButtonBase-root').click(); + + // There is only one piece of data on the last pag. + cy.get('#user-table-body').children().should('have.length', 2); + + cy.get('#user-table-body > :nth-child(2) > :nth-child(2)').should('have.text', 'billy'); + }); + + it('cannot create account with existing email', () => { + cy.intercept('POST', '/api/v1/users/signup', (req) => { + req.reply({ + statusCode: 409, + body: { + message: 'Conflict', + }, + }); + }); + + cy.get('#account').type('root-1'); + cy.get('#email').type('lucy@example.com'); + cy.get('#phone').type('18012341234'); + cy.get('#password').type('dragonfly1'); + cy.get('#confirmPassword').type(`dragonfly1{enter}`); + + // Show error message. + cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); + + // Close error message. + cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); + cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); + }); + + it('cannot create account with existing account', () => { + cy.intercept('POST', '/api/v1/users/signup', (req) => { + req.reply({ + statusCode: 409, + body: { + message: 'Conflict', + }, + }); + }); + + cy.get('#account').type('root'); + cy.get('#email').type('root@console.co'); + cy.get('#phone').type('18012341234'); + cy.get('#password').type('dragonfly1'); + cy.get('#confirmPassword').type(`dragonfly1{enter}`); + + // Show error message. + cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Conflict'); + cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); + cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); + }); + + it('click the password hide butto and confirm password hide butto', () => { + cy.get('#password').type('dragonfly1'); + cy.get('#confirmPassword').type(`dragonfly1{enter}`); + + cy.get('.MuiInputBase-root > .MuiButtonBase-root > [data-testid="VisibilityOffIcon"] > path').click(); + cy.get('#confirmPassword').should('have.value', 'dragonfly1'); + + cy.get('[data-testid="VisibilityOffIcon"]').click(); + cy.get('#confirmPassword').should('have.value', 'dragonfly1'); + }); + + it('should handle API error response', () => { + cy.intercept('POST', '/api/v1/users/signup', (req) => { + req.reply({ + forceNetworkError: true, + }); + }); + + cy.get('#account').type('root-1'); + cy.get('#email').type('root@console.com'); + cy.get('#phone').type('18012341234'); + cy.get('#password').type('dragonfly1'); + cy.get('#confirmPassword').type(`dragonfly1{enter}`); + + // Show error message. + cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch'); + cy.get('.MuiAlert-action > .MuiButtonBase-root').click(); + cy.get('.MuiSnackbar-root > .MuiPaper-root').should('not.exist'); + }); + + it('click the `CANCEL button', () => { + cy.get('#cancel').click(); + + // Then I see that the current page is the users! + cy.url().should('include', '/users'); + }); + + it('cannot signup with invalid attributes', () => { + const nameNotLongEnough = _.times(2, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); + const nameLengthExceeds = _.times(11, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); + const passsword = _.times(8, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); + const location = _.times(101, () => _.sample('abcdefghijklmnopqrstuvwxyz')).join(''); + + // Should display message account the validation error. + cy.get('#account').type(nameNotLongEnough); + cy.get('#account-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 3-10.'); + + cy.get('#account').type(nameLengthExceeds); + cy.get('#account-helper-text').should('be.visible').and('contain', 'Fill in the characters, the length is 3-10.'); + + cy.get('#account').clear(); + + cy.get('#account').type('root'); + + // Verification passed. + cy.get('#account-helper-text').should('not.exist'); + + // Should display message email the validation error. + cy.get('#email').type('root'); + cy.get('#email-helper-text').should('be.visible').and('contain', 'Email is invalid or already taken.'); + + cy.get('#email').clear(); + + cy.get('#email').type('root@console.com'); + + // Verification passed. + cy.get('#email-helper-text').should('not.exist'); + + // Should display message phone the validation error. + cy.get('#phone').type('001'); + cy.get('#phone-helper-text').should('be.visible').and('contain', 'Enter a valid phone number.'); + + cy.get('#phone').clear(); + + cy.get('#phone').type('+86 19101011212'); + + cy.get('#phone-helper-text').should('not.exist'); + + // Should display message location the validation error. + cy.get('#location').clear(); + cy.get('#location').type(location); + + // Show verification error message. + cy.get('#location-helper-text') + .should('be.visible') + .and('have.text', 'Fill in the characters, the length is 0-100.'); + cy.get('#location').clear(); + cy.get('#location').type('Shanghai'); + cy.get('#location-helper-text').should('not.exist'); + + // Should display message password the validation error. + cy.get('#password').type(passsword); + + // Missing number. + cy.get('#password-helper-text') + .should('be.visible') + .and('contain', 'At least 8-16 characters, with at least 1 lowercase letter and 1 number.'); + + cy.get('#password').clear(); + + cy.get('#password').type('dragonfly1'); + + // Verification passed. + cy.get('#password-helper-text').should('not.exist'); + + // Should display message confirm password the validation error. + cy.get('#confirmPassword').type(`dragonfly`); + + // Confirm password verification error when the two passwords are not the same. + cy.get('#confirmPassword-helper-text').should('be.visible').and('contain', 'Please enter the same password.'); + + cy.get('#confirmPassword').clear(); + + cy.get('#confirmPassword').type('dragonfly1'); + + // verification passed. + cy.get('#confirmPassword-helper-text').should('not.exist'); + }); +}); diff --git a/cypress/e2e/users/users.cy.ts b/cypress/e2e/users/users.cy.ts index bfd649b..3c57f04 100644 --- a/cypress/e2e/users/users.cy.ts +++ b/cypress/e2e/users/users.cy.ts @@ -141,13 +141,13 @@ describe('Users', () => { cy.get('#name').should('have.text', 'root'); cy.get('#role').should('have.text', 'root'); cy.get('#email').should('have.text', 'root@example.com'); - cy.get('#phone').should('have.text', '1234567890'); + cy.get('#phone').should('have.text', '+86 153 1234 5678'); cy.get('#location').should('have.text', 'Hangzhou'); cy.get('#created-at').should('contain', '2023-11-06 06:09:04'); cy.get('#updated-at').should('contain', '2023-11-06 06:09:04'); // closure user details. - cy.get('.MuiListSubheader-root > .MuiButtonBase-root').click(); + cy.get('#closure-user-detail').click(); cy.get('#action-jack').click(); @@ -177,7 +177,7 @@ describe('Users', () => { cy.get('#name').should('have.text', 'jack'); cy.get('#role').should('have.text', 'guest'); cy.get('#email').should('have.text', 'jack@example.com'); - cy.get('#phone').should('have.text', '1234567890'); + cy.get('#phone').should('have.text', '+86 153 1234 5678'); cy.get('#location').should('have.text', 'Shanghai'); cy.get('#created-at').should('contain', '2023-11-07 06:09:04'); cy.get('.MuiList-root > :nth-child(17)').should('contain', '2023-11-07 06:09:04'); @@ -375,7 +375,7 @@ describe('Users', () => { // Check the current page number. cy.get('#user-pagination > .MuiPagination-ul .Mui-selected').should('have.text', '2'); - cy.get('[href="/clusters"]').click(); + cy.get('#clusters').click(); // Then I see that the current page is the show update personal-access-tokens. cy.url().should('include', '/clusters'); diff --git a/cypress/fixtures/users/create-user.json b/cypress/fixtures/users/create-user.json new file mode 100644 index 0000000..49a78ff --- /dev/null +++ b/cypress/fixtures/users/create-user.json @@ -0,0 +1,170 @@ +[ + { + "id": 1, + "created_at": "2023-12-07T12:26:52Z", + "updated_at": "2023-12-07T12:26:52Z", + "is_del": 0, + "email": "root@example.com", + "name": "root", + "avatar": "", + "phone": "", + "state": "enable", + "location": "Shanghai", + "bio": "", + "configs": null + }, + { + "id": 2, + "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": "+86 153 1234 5678", + "state": "enable", + "location": "Hangzhou", + "bio": "I am lucy", + "configs": null + }, + { + "id": 3, + "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": "+86 153 1234 5678", + "state": "enable", + "location": "Shanghai", + "bio": "I am jack", + "configs": null + }, + { + "id": 4, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "mary@example.com", + "name": "mary", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "shanghaiHongqiao", + "bio": "I am mary", + "configs": null + }, + { + "id": 5, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "lip@example.com", + "name": "lip", + "avatar": "", + "phone": "+86 153 1234 9876", + "state": "enable", + "location": "Chengdu", + "bio": "I am lip", + "configs": null + }, + { + "id": 6, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "carl@example.com", + "name": "carl", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "shanghaiHuangpu", + "bio": "I am carl", + "configs": null + }, + { + "id": 7, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "david@example.com", + "name": "david", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "Hangzhou", + "bio": "I am david", + "configs": null + }, + { + "id": 8, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "debbie@example.com", + "name": "debbie", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "Tianjing", + "bio": "I am debbie", + "configs": null + }, + { + "id": 9, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "allen@example.com", + "name": "allen", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "Fuzhou", + "bio": "I am allen", + "configs": null + }, + { + "id": 10, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "liam@example.com", + "name": "liam", + "avatar": "", + "phone": "+86 153 1234 9876", + "state": "enable", + "location": "Nanjing", + "bio": "I am liam", + "configs": null + }, + { + "id": 11, + "created_at": "2023-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "noah@example.com", + "name": "noah", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "Shengyang", + "bio": "I am noah", + "configs": null + }, + { + "id": 12, + "created_at": "2024-12-05T07:17:47Z", + "updated_at": "2023-12-12T06:37:49Z", + "is_del": 0, + "email": "billy@example.com", + "name": "billy", + "avatar": "", + "phone": "+86 153 1234 5678", + "state": "enable", + "location": "ParisFrance", + "bio": "I am billy", + "configs": null + } +] diff --git a/cypress/fixtures/users/guest-user.json b/cypress/fixtures/users/guest-user.json index 17dcac5..45a19e3 100644 --- a/cypress/fixtures/users/guest-user.json +++ b/cypress/fixtures/users/guest-user.json @@ -6,7 +6,7 @@ "email": "jack@example.com", "name": "jack", "avatar": "https://example.com/avatar.png", - "phone": "1234567890", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Shanghai", "bio": "I am jack", diff --git a/cypress/fixtures/users/update-user.json b/cypress/fixtures/users/update-user.json index 4eb7399..0c52ae1 100644 --- a/cypress/fixtures/users/update-user.json +++ b/cypress/fixtures/users/update-user.json @@ -6,7 +6,7 @@ "email": "root@gmail.com", "name": "root", "avatar": "https://example.com/avatar.png", - "phone": "15123456789", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Shanghai", "bio": "I am root, I will change the description", diff --git a/cypress/fixtures/users/user.json b/cypress/fixtures/users/user.json index be8a7bf..ad2e8be 100644 --- a/cypress/fixtures/users/user.json +++ b/cypress/fixtures/users/user.json @@ -6,7 +6,7 @@ "email": "root@example.com", "name": "root", "avatar": "https://example.com/avatar.png", - "phone": "1234567890", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Hangzhou", "bio": "I am root", diff --git a/cypress/fixtures/users/users.json b/cypress/fixtures/users/users.json index c73cb65..1afa77a 100644 --- a/cypress/fixtures/users/users.json +++ b/cypress/fixtures/users/users.json @@ -21,7 +21,7 @@ "email": "lucy@example.com", "name": "lucy", "avatar": "https://example.com/avatar.png", - "phone": "1234567890", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Hangzhou", "bio": "I am lucy", @@ -35,7 +35,7 @@ "email": "jack@example.com", "name": "jack", "avatar": "https://example.com/avatar.png", - "phone": "1234567890", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Shanghai", "bio": "I am jack", @@ -49,7 +49,7 @@ "email": "mary@example.com", "name": "mary", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "shanghaiHongqiao", "bio": "I am mary", @@ -63,7 +63,7 @@ "email": "lip@example.com", "name": "lip", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Chengdu", "bio": "I am lip", @@ -77,7 +77,7 @@ "email": "carl@example.com", "name": "carl", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "shanghaiHuangpu", "bio": "I am carl", @@ -91,7 +91,7 @@ "email": "david@example.com", "name": "david", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Hangzhou", "bio": "I am david", @@ -105,7 +105,7 @@ "email": "debbie@example.com", "name": "debbie", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Tianjing", "bio": "I am debbie", @@ -119,7 +119,7 @@ "email": "allen@example.com", "name": "allen", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Fuzhou", "bio": "I am allen", @@ -133,7 +133,7 @@ "email": "liam@example.com", "name": "liam", "avatar": "", - "phone": "18170017449", + "phone": "+86 153 1234 9876", "state": "enable", "location": "Nanjing", "bio": "I am liam", @@ -147,7 +147,7 @@ "email": "noah@example.com", "name": "noah", "avatar": "", - "phone": "15170017449", + "phone": "+86 153 1234 5678", "state": "enable", "location": "Shengyang", "bio": "I am noah", diff --git a/package.json b/package.json index 8b6e8d1..9877411 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "jsonwebtoken": "^9.0.1", "lodash.upperfirst": "^4.3.1", "lottie-react": "^2.4.0", + "mui-tel-input": "^6.0.0", "node-polyfill-webpack-plugin": "^4.0.0", "process": "^0.11.10", "query-string": "^9.0.0", diff --git a/public/fonts/cluster/active.svg b/public/fonts/cluster/active.svg deleted file mode 100644 index 6493c93..0000000 --- a/public/fonts/cluster/active.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/cidrs.svg b/public/fonts/cluster/cidrs.svg deleted file mode 100644 index 6a38f27..0000000 --- a/public/fonts/cluster/cidrs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/cluster-id.svg b/public/fonts/cluster/cluster-id.svg deleted file mode 100644 index a129b17..0000000 --- a/public/fonts/cluster/cluster-id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/cluster.svg b/public/fonts/cluster/cluster.svg deleted file mode 100644 index 17ad213..0000000 --- a/public/fonts/cluster/cluster.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/default.svg b/public/fonts/cluster/default.svg deleted file mode 100644 index e6852bb..0000000 --- a/public/fonts/cluster/default.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/delete-inactive-error.svg b/public/fonts/cluster/delete-inactive-error.svg deleted file mode 100644 index d43ddc7..0000000 --- a/public/fonts/cluster/delete-inactive-error.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/delete-warning.svg b/public/fonts/cluster/delete-warning.svg deleted file mode 100644 index dbe425c..0000000 --- a/public/fonts/cluster/delete-warning.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/delete.svg b/public/fonts/cluster/delete.svg deleted file mode 100644 index 2657438..0000000 --- a/public/fonts/cluster/delete.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/hostname.svg b/public/fonts/cluster/hostname.svg deleted file mode 100644 index c556344..0000000 --- a/public/fonts/cluster/hostname.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/hostnames.svg b/public/fonts/cluster/hostnames.svg deleted file mode 100644 index 44dbe28..0000000 --- a/public/fonts/cluster/hostnames.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/idc.svg b/public/fonts/cluster/idc.svg deleted file mode 100644 index ae27f73..0000000 --- a/public/fonts/cluster/idc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/ip.svg b/public/fonts/cluster/ip.svg deleted file mode 100644 index 269c70d..0000000 --- a/public/fonts/cluster/ip.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/location.svg b/public/fonts/cluster/location.svg deleted file mode 100644 index aaaf98a..0000000 --- a/public/fonts/cluster/location.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/logo.svg b/public/fonts/cluster/logo.svg deleted file mode 100644 index 9f9ef72..0000000 --- a/public/fonts/cluster/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/page-loading.svg b/public/fonts/cluster/page-loading.svg deleted file mode 100644 index f9f48f1..0000000 --- a/public/fonts/cluster/page-loading.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/round.svg b/public/fonts/cluster/round.svg deleted file mode 100644 index a63f6f0..0000000 --- a/public/fonts/cluster/round.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/scheduler-id.svg b/public/fonts/cluster/scheduler-id.svg deleted file mode 100644 index c263955..0000000 --- a/public/fonts/cluster/scheduler-id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/scheduler-ip.svg b/public/fonts/cluster/scheduler-ip.svg deleted file mode 100644 index 6ca262a..0000000 --- a/public/fonts/cluster/scheduler-ip.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/scheduler.svg b/public/fonts/cluster/scheduler.svg deleted file mode 100644 index 9ac40a8..0000000 --- a/public/fonts/cluster/scheduler.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/seed-peer.svg b/public/fonts/cluster/seed-peer.svg deleted file mode 100644 index f31e6dd..0000000 --- a/public/fonts/cluster/seed-peer.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/total.svg b/public/fonts/cluster/total.svg deleted file mode 100644 index 80d5011..0000000 --- a/public/fonts/cluster/total.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/fonts/cluster/user.svg b/public/fonts/cluster/user.svg deleted file mode 100644 index bdf1878..0000000 --- a/public/fonts/cluster/user.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/active.svg b/public/icons/cluster/active.svg deleted file mode 100644 index 6493c93..0000000 --- a/public/icons/cluster/active.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/cluster.svg b/public/icons/cluster/cluster.svg deleted file mode 100644 index 17ad213..0000000 --- a/public/icons/cluster/cluster.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/default.svg b/public/icons/cluster/default.svg deleted file mode 100644 index e6852bb..0000000 --- a/public/icons/cluster/default.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/delete-inactive.svg b/public/icons/cluster/delete-inactive.svg deleted file mode 100644 index 7559f98..0000000 --- a/public/icons/cluster/delete-inactive.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/delete.svg b/public/icons/cluster/delete.svg deleted file mode 100644 index 2657438..0000000 --- a/public/icons/cluster/delete.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/features.svg b/public/icons/cluster/features.svg deleted file mode 100644 index 3345b77..0000000 --- a/public/icons/cluster/features.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/id.svg b/public/icons/cluster/id.svg deleted file mode 100644 index de4dd20..0000000 --- a/public/icons/cluster/id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/inactive-total.svg b/public/icons/cluster/inactive-total.svg deleted file mode 100644 index 620e6cb..0000000 --- a/public/icons/cluster/inactive-total.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/logo.svg b/public/icons/cluster/logo.svg deleted file mode 100644 index 9f9ef72..0000000 --- a/public/icons/cluster/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/peer/export-file.svg b/public/icons/cluster/peer/export-file.svg deleted file mode 100644 index 758a536..0000000 --- a/public/icons/cluster/peer/export-file.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/peer/git-commits.svg b/public/icons/cluster/peer/git-commits.svg deleted file mode 100644 index 4d7477a..0000000 --- a/public/icons/cluster/peer/git-commits.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/public/icons/cluster/peer/refresh-dialog.svg b/public/icons/cluster/peer/refresh-dialog.svg deleted file mode 100644 index c5c951a..0000000 --- a/public/icons/cluster/peer/refresh-dialog.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/peer/total.svg b/public/icons/cluster/peer/total.svg deleted file mode 100644 index a661cba..0000000 --- a/public/icons/cluster/peer/total.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - \ No newline at end of file diff --git a/public/icons/cluster/preheat.svg b/public/icons/cluster/preheat.svg deleted file mode 100644 index e339227..0000000 --- a/public/icons/cluster/preheat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/round.svg b/public/icons/cluster/round.svg deleted file mode 100644 index a63f6f0..0000000 --- a/public/icons/cluster/round.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler.svg b/public/icons/cluster/scheduler.svg deleted file mode 100644 index 9ac40a8..0000000 --- a/public/icons/cluster/scheduler.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/active.svg b/public/icons/cluster/scheduler/active.svg deleted file mode 100644 index 4465845..0000000 --- a/public/icons/cluster/scheduler/active.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/cluster-id.svg b/public/icons/cluster/scheduler/cluster-id.svg deleted file mode 100644 index ac18edb..0000000 --- a/public/icons/cluster/scheduler/cluster-id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/created-at.svg b/public/icons/cluster/scheduler/created-at.svg deleted file mode 100644 index 90a4cce..0000000 --- a/public/icons/cluster/scheduler/created-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/features.svg b/public/icons/cluster/scheduler/features.svg deleted file mode 100644 index 512bf9a..0000000 --- a/public/icons/cluster/scheduler/features.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/hostname.svg b/public/icons/cluster/scheduler/hostname.svg deleted file mode 100644 index b4ba2b5..0000000 --- a/public/icons/cluster/scheduler/hostname.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/port.svg b/public/icons/cluster/scheduler/port.svg deleted file mode 100644 index a4a1545..0000000 --- a/public/icons/cluster/scheduler/port.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/scheduler-id.svg b/public/icons/cluster/scheduler/scheduler-id.svg deleted file mode 100644 index f2f864a..0000000 --- a/public/icons/cluster/scheduler/scheduler-id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/scheduler-ip.svg b/public/icons/cluster/scheduler/scheduler-ip.svg deleted file mode 100644 index 076be07..0000000 --- a/public/icons/cluster/scheduler/scheduler-ip.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/tab-scheduler.svg b/public/icons/cluster/scheduler/tab-scheduler.svg deleted file mode 100644 index 96d1022..0000000 --- a/public/icons/cluster/scheduler/tab-scheduler.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/public/icons/cluster/scheduler/updated-at.svg b/public/icons/cluster/scheduler/updated-at.svg deleted file mode 100644 index 6af943d..0000000 --- a/public/icons/cluster/scheduler/updated-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer.svg b/public/icons/cluster/seed-peer.svg deleted file mode 100644 index f31e6dd..0000000 --- a/public/icons/cluster/seed-peer.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/download-port.svg b/public/icons/cluster/seed-peer/download-port.svg deleted file mode 100644 index 7c425c6..0000000 --- a/public/icons/cluster/seed-peer/download-port.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/object-storage-port.svg b/public/icons/cluster/seed-peer/object-storage-port.svg deleted file mode 100644 index 5ff105b..0000000 --- a/public/icons/cluster/seed-peer/object-storage-port.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/port.svg b/public/icons/cluster/seed-peer/port.svg deleted file mode 100644 index 5257369..0000000 --- a/public/icons/cluster/seed-peer/port.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/seed-peer-download-port.svg b/public/icons/cluster/seed-peer/seed-peer-download-port.svg deleted file mode 100644 index 7317f0c..0000000 --- a/public/icons/cluster/seed-peer/seed-peer-download-port.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/seed-peer-type.svg b/public/icons/cluster/seed-peer/seed-peer-type.svg deleted file mode 100644 index 4678f17..0000000 --- a/public/icons/cluster/seed-peer/seed-peer-type.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/statistics.svg b/public/icons/cluster/statistics.svg deleted file mode 100644 index 89336d6..0000000 --- a/public/icons/cluster/statistics.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/tab-cluster.svg b/public/icons/cluster/tab-cluster.svg deleted file mode 100644 index 3fddc51..0000000 --- a/public/icons/cluster/tab-cluster.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/cluster/unfoldMore.svg b/public/icons/cluster/unfoldMore.svg deleted file mode 100644 index 6717ad9..0000000 --- a/public/icons/cluster/unfoldMore.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/insight/insight.svg b/public/icons/insight/insight.svg deleted file mode 100644 index ad034ff..0000000 --- a/public/icons/insight/insight.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/public/icons/insight/selected-insight.svg b/public/icons/insight/selected-insight.svg deleted file mode 100644 index e1bd7d2..0000000 --- a/public/icons/insight/selected-insight.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - \ No newline at end of file diff --git a/public/icons/job/preheat/created-at.svg b/public/icons/job/preheat/created-at.svg deleted file mode 100644 index 90a4cce..0000000 --- a/public/icons/job/preheat/created-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/preheat/detail.svg b/public/icons/job/preheat/detail.svg deleted file mode 100644 index ae86f2c..0000000 --- a/public/icons/job/preheat/detail.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/preheat/failure.svg b/public/icons/job/preheat/failure.svg deleted file mode 100644 index 977efa8..0000000 --- a/public/icons/job/preheat/failure.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/public/icons/job/preheat/filter.svg b/public/icons/job/preheat/filter.svg deleted file mode 100644 index dc37724..0000000 --- a/public/icons/job/preheat/filter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/preheat/id.svg b/public/icons/job/preheat/id.svg deleted file mode 100644 index f2f864a..0000000 --- a/public/icons/job/preheat/id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/preheat/pending.svg b/public/icons/job/preheat/pending.svg deleted file mode 100644 index 1e68bb8..0000000 --- a/public/icons/job/preheat/pending.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/public/icons/job/preheat/selected-job.svg b/public/icons/job/preheat/selected-job.svg deleted file mode 100644 index b0ae812..0000000 --- a/public/icons/job/preheat/selected-job.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/public/icons/job/task/clear-cache.svg b/public/icons/job/task/clear-cache.svg deleted file mode 100644 index 14e0bf4..0000000 --- a/public/icons/job/task/clear-cache.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/error-log.svg b/public/icons/job/task/error-log.svg deleted file mode 100644 index 77f907e..0000000 --- a/public/icons/job/task/error-log.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/executions.svg b/public/icons/job/task/executions.svg deleted file mode 100644 index a724275..0000000 --- a/public/icons/job/task/executions.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/failure.svg b/public/icons/job/task/failure.svg deleted file mode 100644 index 2839a1e..0000000 --- a/public/icons/job/task/failure.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/hostname.svg b/public/icons/job/task/hostname.svg deleted file mode 100644 index d7eb382..0000000 --- a/public/icons/job/task/hostname.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/no-task.svg b/public/icons/job/task/no-task.svg deleted file mode 100644 index d13c11c..0000000 --- a/public/icons/job/task/no-task.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - No Caching - - - Please enter the task id in your search - box to search for cache. - - - - - - \ No newline at end of file diff --git a/public/icons/job/task/task-id.svg b/public/icons/job/task/task-id.svg deleted file mode 100644 index 4f0fd44..0000000 --- a/public/icons/job/task/task-id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/job/task/type.svg b/public/icons/job/task/type.svg deleted file mode 100644 index d2692fa..0000000 --- a/public/icons/job/task/type.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/created-at.svg b/public/icons/profile/created-at.svg deleted file mode 100644 index 90a4cce..0000000 --- a/public/icons/profile/created-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/email.svg b/public/icons/profile/email.svg deleted file mode 100644 index c8b78d4..0000000 --- a/public/icons/profile/email.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/id.svg b/public/icons/profile/id.svg deleted file mode 100644 index f2f864a..0000000 --- a/public/icons/profile/id.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/location.svg b/public/icons/profile/location.svg deleted file mode 100644 index 678a275..0000000 --- a/public/icons/profile/location.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/name.svg b/public/icons/profile/name.svg deleted file mode 100644 index 4d609a8..0000000 --- a/public/icons/profile/name.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/profile/phone.svg b/public/icons/profile/phone.svg deleted file mode 100644 index ae86d79..0000000 --- a/public/icons/profile/phone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/tokens/developer.svg b/public/icons/tokens/developer.svg deleted file mode 100644 index 3ff7340..0000000 --- a/public/icons/tokens/developer.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/public/icons/tokens/done.svg b/public/icons/tokens/done.svg deleted file mode 100644 index 71606dd..0000000 --- a/public/icons/tokens/done.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/tokens/key.svg b/public/icons/tokens/key.svg deleted file mode 100644 index 106b812..0000000 --- a/public/icons/tokens/key.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/tokens/selected-developer.svg b/public/icons/tokens/selected-developer.svg deleted file mode 100644 index 8d57800..0000000 --- a/public/icons/tokens/selected-developer.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/public/icons/user/bio.svg b/public/icons/user/bio.svg deleted file mode 100644 index 5c150dc..0000000 --- a/public/icons/user/bio.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/created-at.svg b/public/icons/user/created-at.svg deleted file mode 100644 index e600a88..0000000 --- a/public/icons/user/created-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/detail-role.svg b/public/icons/user/detail-role.svg deleted file mode 100644 index dc3ba2d..0000000 --- a/public/icons/user/detail-role.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/edit.svg b/public/icons/user/edit.svg deleted file mode 100644 index 7928eb1..0000000 --- a/public/icons/user/edit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/location.svg b/public/icons/user/location.svg deleted file mode 100644 index 9954cb4..0000000 --- a/public/icons/user/location.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/phone.svg b/public/icons/user/phone.svg deleted file mode 100644 index 9976a99..0000000 --- a/public/icons/user/phone.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/role.svg b/public/icons/user/role.svg deleted file mode 100644 index 4f6f374..0000000 --- a/public/icons/user/role.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/selected-user.svg b/public/icons/user/selected-user.svg deleted file mode 100644 index d6d33d3..0000000 --- a/public/icons/user/selected-user.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/public/icons/user/updated-at.svg b/public/icons/user/updated-at.svg deleted file mode 100644 index fff20bf..0000000 --- a/public/icons/user/updated-at.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/icons/user/user.svg b/public/icons/user/user.svg deleted file mode 100644 index ef82479..0000000 --- a/public/icons/user/user.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/public/images/404/404.svg b/public/images/404/404.svg deleted file mode 100644 index 5fb3fdf..0000000 --- a/public/images/404/404.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - 切片 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/images/login/features.svg b/public/images/login/features.svg deleted file mode 100644 index 9ad6d39..0000000 --- a/public/images/login/features.svg +++ /dev/null @@ -1,654 +0,0 @@ - - - 矩形 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - P2P File Distribution - - - - Ecosystem - - - - Peer Level Control - - - - Consistency - - - - - Isolate Abnormal Peers - - - - Noninvasive - - - - - - Use P2P technology for file - transfer, improve download - efficiency, and save bandwidth - across IDC. - - - Support for host-level limits - speed. - - - Automatically isolate abnormal - peers to improve download - stability. - - - Harbor can distribute and - warm up images based on - Dragonfly. - - - It can ensure that the same - file is consistent in the peer- - to-peer transmission. - - - Supports multiple containers - for distributing images. - - - Features - - - Dragonfly provides a one-stop solution for large-scale file distribution. The basic capabilities - provided by Dragonfly include: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/images/login/login.svg b/public/images/login/login.svg deleted file mode 100644 index 0567f41..0000000 --- a/public/images/login/login.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 12b715e..cf0e0fb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,58 @@ import Main from './layouts/main'; +import { createTheme, ThemeProvider } from '@mui/material'; +import { createContext, useEffect, useMemo, useState } from 'react'; + +export const ColorModeContext = createContext({ toggleColorMode: () => {} }); function App() { - return ; + const [mode, setMode] = useState<'light' | 'dark'>(() => { + const dataTheme = localStorage.getItem('data-theme'); + return (dataTheme as 'light' | 'dark') || 'light'; + }); + + const colorMode = useMemo( + () => ({ + toggleColorMode: () => { + setMode((prevMode) => (prevMode === 'light' ? 'dark' : 'light')); + }, + }), + [], + ); + + useEffect(() => { + document.documentElement.setAttribute('data-theme', mode); + + localStorage.setItem('data-theme', mode); + }, [mode]); + + const theme = useMemo( + () => + createTheme({ + palette: { + mode, + primary: { + main: mode === 'light' ? '#1C293A' : 'rgba(255, 255, 255, 0.8)', + }, + text: { + primary: mode === 'light' ? '#1C293A' : 'rgba(255, 255, 255, 0.8)', + }, + success: { + main: mode === 'light' ? '#1f7d53' : '#008170', + }, + }, + typography: { + fontFamily: 'mabry-light', + }, + }), + [mode], + ); + return ( + + + + + + ); } export default App; diff --git a/src/assets/images/404/404.svg b/src/assets/images/404/404.svg new file mode 100644 index 0000000..831425c --- /dev/null +++ b/src/assets/images/404/404.svg @@ -0,0 +1,132 @@ + + + 切片 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/404/background-image.png b/src/assets/images/404/background-image.png similarity index 100% rename from public/images/404/background-image.png rename to src/assets/images/404/background-image.png diff --git a/public/images/404/logo.svg b/src/assets/images/404/logo.svg similarity index 100% rename from public/images/404/logo.svg rename to src/assets/images/404/logo.svg diff --git a/src/assets/images/cluster/active.svg b/src/assets/images/cluster/active.svg new file mode 100644 index 0000000..0ae7918 --- /dev/null +++ b/src/assets/images/cluster/active.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/arrow-circle-right.svg b/src/assets/images/cluster/arrow-circle-right.svg new file mode 100644 index 0000000..358cac5 --- /dev/null +++ b/src/assets/images/cluster/arrow-circle-right.svg @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/card-features.svg b/src/assets/images/cluster/card-features.svg similarity index 100% rename from public/icons/cluster/card-features.svg rename to src/assets/images/cluster/card-features.svg diff --git a/public/icons/cluster/cidrs.svg b/src/assets/images/cluster/cidrs.svg similarity index 96% rename from public/icons/cluster/cidrs.svg rename to src/assets/images/cluster/cidrs.svg index 9e65dcf..d2c4e21 100644 --- a/public/icons/cluster/cidrs.svg +++ b/src/assets/images/cluster/cidrs.svg @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/public/icons/cluster/selected-cluster.svg b/src/assets/images/cluster/cluster.svg similarity index 88% rename from public/icons/cluster/selected-cluster.svg rename to src/assets/images/cluster/cluster.svg index dc96533..f2d3ee4 100644 --- a/public/icons/cluster/selected-cluster.svg +++ b/src/assets/images/cluster/cluster.svg @@ -1,5 +1,5 @@ - - + \ No newline at end of file diff --git a/src/assets/images/cluster/default.svg b/src/assets/images/cluster/default.svg new file mode 100644 index 0000000..f15be56 --- /dev/null +++ b/src/assets/images/cluster/default.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/delete-inactive-error.svg b/src/assets/images/cluster/delete-inactive-error.svg similarity index 100% rename from public/icons/cluster/delete-inactive-error.svg rename to src/assets/images/cluster/delete-inactive-error.svg diff --git a/public/fonts/cluster/delete-inactive.svg b/src/assets/images/cluster/delete-inactive.svg similarity index 100% rename from public/fonts/cluster/delete-inactive.svg rename to src/assets/images/cluster/delete-inactive.svg diff --git a/public/icons/cluster/delete-warning.svg b/src/assets/images/cluster/delete-warning.svg similarity index 100% rename from public/icons/cluster/delete-warning.svg rename to src/assets/images/cluster/delete-warning.svg diff --git a/src/assets/images/cluster/delete.svg b/src/assets/images/cluster/delete.svg new file mode 100644 index 0000000..547fc77 --- /dev/null +++ b/src/assets/images/cluster/delete.svg @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/features-schedule.svg b/src/assets/images/cluster/features-schedule.svg similarity index 100% rename from public/icons/cluster/features-schedule.svg rename to src/assets/images/cluster/features-schedule.svg diff --git a/src/assets/images/cluster/features.svg b/src/assets/images/cluster/features.svg new file mode 100644 index 0000000..cfa12b6 --- /dev/null +++ b/src/assets/images/cluster/features.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/hostnames.svg b/src/assets/images/cluster/hostnames.svg similarity index 97% rename from public/icons/cluster/hostnames.svg rename to src/assets/images/cluster/hostnames.svg index a0ad10b..656d7aa 100644 --- a/public/icons/cluster/hostnames.svg +++ b/src/assets/images/cluster/hostnames.svg @@ -2,5 +2,5 @@ p-id="18685" width="200" height="200"> + p-id="18686" fill="currentColor"> \ No newline at end of file diff --git a/public/icons/user/id.svg b/src/assets/images/cluster/id.svg similarity index 100% rename from public/icons/user/id.svg rename to src/assets/images/cluster/id.svg diff --git a/public/icons/cluster/idc.svg b/src/assets/images/cluster/idc.svg similarity index 87% rename from public/icons/cluster/idc.svg rename to src/assets/images/cluster/idc.svg index ddbd8e9..6484717 100644 --- a/public/icons/cluster/idc.svg +++ b/src/assets/images/cluster/idc.svg @@ -1,7 +1,7 @@ - + + fill="currentColor" p-id="10979"> \ No newline at end of file diff --git a/public/fonts/cluster/inactive-total.svg b/src/assets/images/cluster/inactive-total.svg similarity index 100% rename from public/fonts/cluster/inactive-total.svg rename to src/assets/images/cluster/inactive-total.svg diff --git a/public/icons/cluster/information-cluster.svg b/src/assets/images/cluster/information-cluster.svg similarity index 88% rename from public/icons/cluster/information-cluster.svg rename to src/assets/images/cluster/information-cluster.svg index 61c5b2e..e09347d 100644 --- a/public/icons/cluster/information-cluster.svg +++ b/src/assets/images/cluster/information-cluster.svg @@ -1,36 +1,36 @@ - + + p-id="20607" fill="currentColor"> + p-id="20608" fill="currentColor"> + p-id="20609" fill="currentColor"> + p-id="20610" fill="currentColor"> + p-id="20611" fill="currentColor"> + p-id="20612" fill="currentColor"> + p-id="20613" fill="currentColor"> + p-id="20614" fill="currentColor"> + p-id="20615" fill="currentColor"> + p-id="20616" fill="currentColor"> + p-id="20617" fill="currentColor"> \ No newline at end of file diff --git a/public/icons/cluster/ip.svg b/src/assets/images/cluster/ip.svg similarity index 100% rename from public/icons/cluster/ip.svg rename to src/assets/images/cluster/ip.svg diff --git a/public/icons/cluster/location.svg b/src/assets/images/cluster/location.svg similarity index 81% rename from public/icons/cluster/location.svg rename to src/assets/images/cluster/location.svg index 33e499f..bea4f39 100644 --- a/public/icons/cluster/location.svg +++ b/src/assets/images/cluster/location.svg @@ -1,5 +1,5 @@ - - + \ No newline at end of file diff --git a/public/icons/cluster/name.svg b/src/assets/images/cluster/name.svg similarity index 100% rename from public/icons/cluster/name.svg rename to src/assets/images/cluster/name.svg diff --git a/public/icons/cluster/no-cluster.svg b/src/assets/images/cluster/no-cluster.svg similarity index 100% rename from public/icons/cluster/no-cluster.svg rename to src/assets/images/cluster/no-cluster.svg diff --git a/public/icons/cluster/peer/active.svg b/src/assets/images/cluster/peer/active.svg similarity index 96% rename from public/icons/cluster/peer/active.svg rename to src/assets/images/cluster/peer/active.svg index 2a7cbd7..fb5acd9 100644 --- a/public/icons/cluster/peer/active.svg +++ b/src/assets/images/cluster/peer/active.svg @@ -2,5 +2,5 @@ p-id="53964" width="64" height="64"> + fill="currentColor" p-id="53965"> \ No newline at end of file diff --git a/src/assets/images/cluster/peer/export-file.svg b/src/assets/images/cluster/peer/export-file.svg new file mode 100644 index 0000000..309c45c --- /dev/null +++ b/src/assets/images/cluster/peer/export-file.svg @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/peer/export.svg b/src/assets/images/cluster/peer/export.svg similarity index 59% rename from public/icons/cluster/peer/export.svg rename to src/assets/images/cluster/peer/export.svg index ac414cf..24559a6 100644 --- a/public/icons/cluster/peer/export.svg +++ b/src/assets/images/cluster/peer/export.svg @@ -1,13 +1,3 @@ - + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/peer/git-versions.svg b/src/assets/images/cluster/peer/git-versions.svg similarity index 100% rename from public/icons/cluster/peer/git-versions.svg rename to src/assets/images/cluster/peer/git-versions.svg diff --git a/src/assets/images/cluster/peer/refresh-dialog.svg b/src/assets/images/cluster/peer/refresh-dialog.svg new file mode 100644 index 0000000..ff9e12b --- /dev/null +++ b/src/assets/images/cluster/peer/refresh-dialog.svg @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/public/icons/cluster/peer/refresh-loading.svg b/src/assets/images/cluster/peer/refresh-loading.svg similarity index 96% rename from public/icons/cluster/peer/refresh-loading.svg rename to src/assets/images/cluster/peer/refresh-loading.svg index eb6b420..42d85fe 100644 --- a/public/icons/cluster/peer/refresh-loading.svg +++ b/src/assets/images/cluster/peer/refresh-loading.svg @@ -4,5 +4,5 @@ repeatCount="indefinite" /> + p-id="26636" fill="currentColor"> \ No newline at end of file diff --git a/public/icons/cluster/peer/refresh.svg b/src/assets/images/cluster/peer/refresh.svg similarity index 96% rename from public/icons/cluster/peer/refresh.svg rename to src/assets/images/cluster/peer/refresh.svg index 041b35a..27c8486 100644 --- a/public/icons/cluster/peer/refresh.svg +++ b/src/assets/images/cluster/peer/refresh.svg @@ -2,5 +2,5 @@ p-id="26635" width="200" height="200"> + p-id="26636" fill="currentColor"> \ No newline at end of file diff --git a/public/icons/cluster/peer/statistics.svg b/src/assets/images/cluster/peer/statistics.svg similarity index 69% rename from public/icons/cluster/peer/statistics.svg rename to src/assets/images/cluster/peer/statistics.svg index cba51a0..347d005 100644 --- a/public/icons/cluster/peer/statistics.svg +++ b/src/assets/images/cluster/peer/statistics.svg @@ -2,18 +2,18 @@ p-id="57208" width="64" height="64"> + fill="currentColor" p-id="57209" data-spm-anchor-id="a313x.search_index.0.i105.5caf3a81aFGzSu" class="selected"> + fill="#dcdcdc" p-id="57210" data-spm-anchor-id="a313x.search_index.0.i100.5caf3a81aFGzSu" class=""> + fill="currentColor" p-id="57211" data-spm-anchor-id="a313x.search_index.0.i104.5caf3a81aFGzSu" class="selected"> - + \ No newline at end of file diff --git a/public/icons/cluster/peer/tab-peer.svg b/src/assets/images/cluster/peer/tab-peer.svg similarity index 98% rename from public/icons/cluster/peer/tab-peer.svg rename to src/assets/images/cluster/peer/tab-peer.svg index 83e808e..6fb9d05 100644 --- a/public/icons/cluster/peer/tab-peer.svg +++ b/src/assets/images/cluster/peer/tab-peer.svg @@ -1,7 +1,7 @@ - + diff --git a/src/assets/images/cluster/peer/total.svg b/src/assets/images/cluster/peer/total.svg new file mode 100644 index 0000000..5fbdfbe --- /dev/null +++ b/src/assets/images/cluster/peer/total.svg @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/preheat.svg b/src/assets/images/cluster/preheat.svg new file mode 100644 index 0000000..1086d07 --- /dev/null +++ b/src/assets/images/cluster/preheat.svg @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/round.svg b/src/assets/images/cluster/round.svg new file mode 100644 index 0000000..d291bdf --- /dev/null +++ b/src/assets/images/cluster/round.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler.svg b/src/assets/images/cluster/scheduler.svg new file mode 100644 index 0000000..4e536fa --- /dev/null +++ b/src/assets/images/cluster/scheduler.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/active.svg b/src/assets/images/cluster/scheduler/active.svg new file mode 100644 index 0000000..5c56099 --- /dev/null +++ b/src/assets/images/cluster/scheduler/active.svg @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/public/icons/cluster/scheduler/card.svg b/src/assets/images/cluster/scheduler/card.svg similarity index 100% rename from public/icons/cluster/scheduler/card.svg rename to src/assets/images/cluster/scheduler/card.svg diff --git a/src/assets/images/cluster/scheduler/cluster-id.svg b/src/assets/images/cluster/scheduler/cluster-id.svg new file mode 100644 index 0000000..655ca79 --- /dev/null +++ b/src/assets/images/cluster/scheduler/cluster-id.svg @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/created-at.svg b/src/assets/images/cluster/scheduler/created-at.svg new file mode 100644 index 0000000..93ed18f --- /dev/null +++ b/src/assets/images/cluster/scheduler/created-at.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/features.svg b/src/assets/images/cluster/scheduler/features.svg new file mode 100644 index 0000000..2070445 --- /dev/null +++ b/src/assets/images/cluster/scheduler/features.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/hostname.svg b/src/assets/images/cluster/scheduler/hostname.svg new file mode 100644 index 0000000..0178589 --- /dev/null +++ b/src/assets/images/cluster/scheduler/hostname.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/cluster/scheduler/ic-content.svg b/src/assets/images/cluster/scheduler/ic-content.svg similarity index 100% rename from public/icons/cluster/scheduler/ic-content.svg rename to src/assets/images/cluster/scheduler/ic-content.svg diff --git a/public/icons/cluster/scheduler/inactive.svg b/src/assets/images/cluster/scheduler/inactive.svg similarity index 91% rename from public/icons/cluster/scheduler/inactive.svg rename to src/assets/images/cluster/scheduler/inactive.svg index da1605b..25956ae 100644 --- a/public/icons/cluster/scheduler/inactive.svg +++ b/src/assets/images/cluster/scheduler/inactive.svg @@ -2,7 +2,7 @@ xmlns:xlink="http://www.w3.org/1999/xlink"> - + diff --git a/src/assets/images/cluster/scheduler/number.svg b/src/assets/images/cluster/scheduler/number.svg new file mode 100644 index 0000000..541d97c --- /dev/null +++ b/src/assets/images/cluster/scheduler/number.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/port.svg b/src/assets/images/cluster/scheduler/port.svg new file mode 100644 index 0000000..25ca984 --- /dev/null +++ b/src/assets/images/cluster/scheduler/port.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/scheduler-id.svg b/src/assets/images/cluster/scheduler/scheduler-id.svg new file mode 100644 index 0000000..bdd8386 --- /dev/null +++ b/src/assets/images/cluster/scheduler/scheduler-id.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/scheduler-ip.svg b/src/assets/images/cluster/scheduler/scheduler-ip.svg new file mode 100644 index 0000000..4f9673c --- /dev/null +++ b/src/assets/images/cluster/scheduler/scheduler-ip.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/public/icons/cluster/scheduler/status.svg b/src/assets/images/cluster/scheduler/status.svg similarity index 87% rename from public/icons/cluster/scheduler/status.svg rename to src/assets/images/cluster/scheduler/status.svg index 63d9f6a..2035be5 100644 --- a/public/icons/cluster/scheduler/status.svg +++ b/src/assets/images/cluster/scheduler/status.svg @@ -2,8 +2,8 @@ width="64" height="64"> + fill="currentColor" p-id="7190"> + fill="currentColor" p-id="7191"> \ No newline at end of file diff --git a/src/assets/images/cluster/scheduler/tab-scheduler.svg b/src/assets/images/cluster/scheduler/tab-scheduler.svg new file mode 100644 index 0000000..c5b9719 --- /dev/null +++ b/src/assets/images/cluster/scheduler/tab-scheduler.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/cluster/scheduler/table.svg b/src/assets/images/cluster/scheduler/table.svg similarity index 100% rename from public/icons/cluster/scheduler/table.svg rename to src/assets/images/cluster/scheduler/table.svg diff --git a/src/assets/images/cluster/scheduler/updated-at.svg b/src/assets/images/cluster/scheduler/updated-at.svg new file mode 100644 index 0000000..d0184b1 --- /dev/null +++ b/src/assets/images/cluster/scheduler/updated-at.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer.svg b/src/assets/images/cluster/seed-peer.svg new file mode 100644 index 0000000..fccfb3f --- /dev/null +++ b/src/assets/images/cluster/seed-peer.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer/download-port.svg b/src/assets/images/cluster/seed-peer/download-port.svg new file mode 100644 index 0000000..908826f --- /dev/null +++ b/src/assets/images/cluster/seed-peer/download-port.svg @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer/object-storage-port.svg b/src/assets/images/cluster/seed-peer/object-storage-port.svg new file mode 100644 index 0000000..86e3b6d --- /dev/null +++ b/src/assets/images/cluster/seed-peer/object-storage-port.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer/port.svg b/src/assets/images/cluster/seed-peer/port.svg new file mode 100644 index 0000000..d15977d --- /dev/null +++ b/src/assets/images/cluster/seed-peer/port.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer/seed-peer-download-port.svg b/src/assets/images/cluster/seed-peer/seed-peer-download-port.svg new file mode 100644 index 0000000..40326cb --- /dev/null +++ b/src/assets/images/cluster/seed-peer/seed-peer-download-port.svg @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/cluster/seed-peer/seed-peer-type.svg b/src/assets/images/cluster/seed-peer/seed-peer-type.svg new file mode 100644 index 0000000..edd47b4 --- /dev/null +++ b/src/assets/images/cluster/seed-peer/seed-peer-type.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/cluster/seed-peer/tab-seed-peer.svg b/src/assets/images/cluster/seed-peer/tab-seed-peer.svg similarity index 98% rename from public/icons/cluster/seed-peer/tab-seed-peer.svg rename to src/assets/images/cluster/seed-peer/tab-seed-peer.svg index aacb812..1604dae 100644 --- a/public/icons/cluster/seed-peer/tab-seed-peer.svg +++ b/src/assets/images/cluster/seed-peer/tab-seed-peer.svg @@ -1,7 +1,7 @@ - + diff --git a/public/icons/cluster/seed-peer/type.svg b/src/assets/images/cluster/seed-peer/type.svg similarity index 100% rename from public/icons/cluster/seed-peer/type.svg rename to src/assets/images/cluster/seed-peer/type.svg diff --git a/public/fonts/cluster/statistics.svg b/src/assets/images/cluster/statistics.svg similarity index 100% rename from public/fonts/cluster/statistics.svg rename to src/assets/images/cluster/statistics.svg diff --git a/public/icons/cluster/status.svg b/src/assets/images/cluster/status.svg similarity index 96% rename from public/icons/cluster/status.svg rename to src/assets/images/cluster/status.svg index e603e64..f45845e 100644 --- a/public/icons/cluster/status.svg +++ b/src/assets/images/cluster/status.svg @@ -2,5 +2,5 @@ p-id="44653" width="200" height="200"> + fill="currentColor" p-id="44654"> \ No newline at end of file diff --git a/src/assets/images/cluster/tab-cluster.svg b/src/assets/images/cluster/tab-cluster.svg new file mode 100644 index 0000000..09d083e --- /dev/null +++ b/src/assets/images/cluster/tab-cluster.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/cluster/total.svg b/src/assets/images/cluster/total.svg similarity index 100% rename from public/icons/cluster/total.svg rename to src/assets/images/cluster/total.svg diff --git a/public/fonts/cluster/unfoldMore.svg b/src/assets/images/cluster/unfoldMore.svg similarity index 100% rename from public/fonts/cluster/unfoldMore.svg rename to src/assets/images/cluster/unfoldMore.svg diff --git a/src/assets/images/job/preheat/created-at.svg b/src/assets/images/job/preheat/created-at.svg new file mode 100644 index 0000000..93ed18f --- /dev/null +++ b/src/assets/images/job/preheat/created-at.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/job/preheat/description.svg b/src/assets/images/job/preheat/description.svg similarity index 88% rename from public/icons/job/preheat/description.svg rename to src/assets/images/job/preheat/description.svg index c1adfe6..4d4c163 100644 --- a/public/icons/job/preheat/description.svg +++ b/src/assets/images/job/preheat/description.svg @@ -2,8 +2,8 @@ p-id="52110" width="64" height="64"> + p-id="52111" fill="currentColor"> + p-id="52112" fill="currentColor"> \ No newline at end of file diff --git a/src/assets/images/job/preheat/detail.svg b/src/assets/images/job/preheat/detail.svg new file mode 100644 index 0000000..1b644f8 --- /dev/null +++ b/src/assets/images/job/preheat/detail.svg @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/job/preheat/error-log.svg b/src/assets/images/job/preheat/error-log.svg similarity index 100% rename from public/icons/job/preheat/error-log.svg rename to src/assets/images/job/preheat/error-log.svg diff --git a/src/assets/images/job/preheat/failure.svg b/src/assets/images/job/preheat/failure.svg new file mode 100644 index 0000000..3f7022a --- /dev/null +++ b/src/assets/images/job/preheat/failure.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/public/icons/job/preheat/headers.svg b/src/assets/images/job/preheat/headers.svg similarity index 93% rename from public/icons/job/preheat/headers.svg rename to src/assets/images/job/preheat/headers.svg index 84a3010..16a73e4 100644 --- a/public/icons/job/preheat/headers.svg +++ b/src/assets/images/job/preheat/headers.svg @@ -2,11 +2,11 @@ p-id="34878" width="64" height="64"> + fill="currentColor" p-id="34879"> + fill="currentColor" p-id="34880"> + fill="currentColor" p-id="34881"> \ No newline at end of file diff --git a/src/assets/images/job/preheat/id.svg b/src/assets/images/job/preheat/id.svg new file mode 100644 index 0000000..bdd8386 --- /dev/null +++ b/src/assets/images/job/preheat/id.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/job/preheat/pending.svg b/src/assets/images/job/preheat/pending.svg new file mode 100644 index 0000000..a213867 --- /dev/null +++ b/src/assets/images/job/preheat/pending.svg @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/public/icons/job/preheat/scope.svg b/src/assets/images/job/preheat/scope.svg similarity index 93% rename from public/icons/job/preheat/scope.svg rename to src/assets/images/job/preheat/scope.svg index 1faa845..cc72b44 100644 --- a/public/icons/job/preheat/scope.svg +++ b/src/assets/images/job/preheat/scope.svg @@ -2,8 +2,8 @@ p-id="11900" width="200" height="200"> + fill="currentColor" p-id="11901"> + fill="currentColor" p-id="11902"> \ No newline at end of file diff --git a/public/icons/job/preheat/status-failure.svg b/src/assets/images/job/preheat/status-failure.svg similarity index 100% rename from public/icons/job/preheat/status-failure.svg rename to src/assets/images/job/preheat/status-failure.svg diff --git a/public/icons/job/preheat/status-pending.svg b/src/assets/images/job/preheat/status-pending.svg similarity index 100% rename from public/icons/job/preheat/status-pending.svg rename to src/assets/images/job/preheat/status-pending.svg diff --git a/public/icons/job/preheat/status-success.svg b/src/assets/images/job/preheat/status-success.svg similarity index 100% rename from public/icons/job/preheat/status-success.svg rename to src/assets/images/job/preheat/status-success.svg diff --git a/public/icons/job/preheat/status.svg b/src/assets/images/job/preheat/status.svg similarity index 87% rename from public/icons/job/preheat/status.svg rename to src/assets/images/job/preheat/status.svg index 63d9f6a..2035be5 100644 --- a/public/icons/job/preheat/status.svg +++ b/src/assets/images/job/preheat/status.svg @@ -2,8 +2,8 @@ width="64" height="64"> + fill="currentColor" p-id="7190"> + fill="currentColor" p-id="7191"> \ No newline at end of file diff --git a/public/icons/job/preheat/success.svg b/src/assets/images/job/preheat/success.svg similarity index 100% rename from public/icons/job/preheat/success.svg rename to src/assets/images/job/preheat/success.svg diff --git a/public/icons/job/preheat/tag-scope.svg b/src/assets/images/job/preheat/tag-scope.svg similarity index 100% rename from public/icons/job/preheat/tag-scope.svg rename to src/assets/images/job/preheat/tag-scope.svg diff --git a/public/icons/job/preheat/tag.svg b/src/assets/images/job/preheat/tag.svg similarity index 90% rename from public/icons/job/preheat/tag.svg rename to src/assets/images/job/preheat/tag.svg index 3d13fdf..c61fa56 100644 --- a/public/icons/job/preheat/tag.svg +++ b/src/assets/images/job/preheat/tag.svg @@ -2,8 +2,8 @@ p-id="37181" width="64" height="64"> + p-id="37182" fill="currentColor"> + p-id="37183" fill="currentColor"> \ No newline at end of file diff --git a/public/icons/job/preheat/url.svg b/src/assets/images/job/preheat/url.svg similarity index 91% rename from public/icons/job/preheat/url.svg rename to src/assets/images/job/preheat/url.svg index 3e03b8a..d181139 100644 --- a/public/icons/job/preheat/url.svg +++ b/src/assets/images/job/preheat/url.svg @@ -2,8 +2,8 @@ p-id="41168" width="64" height="64"> + p-id="41169" fill="currentColor"> + p-id="41170" fill="currentColor"> \ No newline at end of file diff --git a/src/assets/images/job/task/clear-cache.svg b/src/assets/images/job/task/clear-cache.svg new file mode 100644 index 0000000..c8fe2da --- /dev/null +++ b/src/assets/images/job/task/clear-cache.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/job/task/created.svg b/src/assets/images/job/task/created.svg similarity index 100% rename from public/icons/job/task/created.svg rename to src/assets/images/job/task/created.svg diff --git a/src/assets/images/job/task/dark-no-task.svg b/src/assets/images/job/task/dark-no-task.svg new file mode 100644 index 0000000..c780320 --- /dev/null +++ b/src/assets/images/job/task/dark-no-task.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No Caching + + + Please enter the task id in your search + + + box to search for cache. + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/job/task/error-log.svg b/src/assets/images/job/task/error-log.svg new file mode 100644 index 0000000..8d0a83f --- /dev/null +++ b/src/assets/images/job/task/error-log.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/job/task/executions.svg b/src/assets/images/job/task/executions.svg new file mode 100644 index 0000000..93421a9 --- /dev/null +++ b/src/assets/images/job/task/executions.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/job/task/failure.svg b/src/assets/images/job/task/failure.svg new file mode 100644 index 0000000..db8e73d --- /dev/null +++ b/src/assets/images/job/task/failure.svg @@ -0,0 +1,5 @@ + + + +ƒ \ No newline at end of file diff --git a/src/assets/images/job/task/hostname.svg b/src/assets/images/job/task/hostname.svg new file mode 100644 index 0000000..330f90e --- /dev/null +++ b/src/assets/images/job/task/hostname.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/public/icons/job/task/ip.svg b/src/assets/images/job/task/ip.svg similarity index 100% rename from public/icons/job/task/ip.svg rename to src/assets/images/job/task/ip.svg diff --git a/public/icons/job/task/no-search.svg b/src/assets/images/job/task/no-search.svg similarity index 100% rename from public/icons/job/task/no-search.svg rename to src/assets/images/job/task/no-search.svg diff --git a/src/assets/images/job/task/no-task.svg b/src/assets/images/job/task/no-task.svg new file mode 100644 index 0000000..d755a41 --- /dev/null +++ b/src/assets/images/job/task/no-task.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No Caching + + + Please enter the task id in your search + + + box to search for cache. + + + + + + + + \ No newline at end of file diff --git a/public/icons/job/task/scheduler-cluster.svg b/src/assets/images/job/task/scheduler-cluster.svg similarity index 100% rename from public/icons/job/task/scheduler-cluster.svg rename to src/assets/images/job/task/scheduler-cluster.svg diff --git a/public/icons/job/task/search.svg b/src/assets/images/job/task/search.svg similarity index 100% rename from public/icons/job/task/search.svg rename to src/assets/images/job/task/search.svg diff --git a/public/icons/job/task/success.svg b/src/assets/images/job/task/success.svg similarity index 100% rename from public/icons/job/task/success.svg rename to src/assets/images/job/task/success.svg diff --git a/public/icons/job/preheat/job.svg b/src/assets/images/job/task/task-id.svg similarity index 72% rename from public/icons/job/preheat/job.svg rename to src/assets/images/job/task/task-id.svg index ed3405b..6d46fde 100644 --- a/public/icons/job/preheat/job.svg +++ b/src/assets/images/job/task/task-id.svg @@ -1,9 +1,9 @@ - + + fill="currentColor" p-id="9415"> + fill="currentColor" p-id="9416"> \ No newline at end of file diff --git a/src/assets/images/job/task/type.svg b/src/assets/images/job/task/type.svg new file mode 100644 index 0000000..4a9fcd1 --- /dev/null +++ b/src/assets/images/job/task/type.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/login/dark-dragonfly.svg b/src/assets/images/login/dark-dragonfly.svg new file mode 100644 index 0000000..afc10da --- /dev/null +++ b/src/assets/images/login/dark-dragonfly.svg @@ -0,0 +1,160 @@ + + + + + + + + + Provides an efficient, stable, and secure file distribution and image + + + acceleration system based on P2P technology, and is a standard solution and + + + + best practice in the field of image acceleration in the cloud native + + + architecture. + + + + + + + + Dragonfly + + + Welcome To Dragonfly Console ! + + + + + + + + + + + Partners + + + + + + + + + + + + + + + + + + + + Provide + + + CNCF + + + Incubating + + + From 5 companies + + + Efficient,stable, + + + secure file + + + distribution + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/login/dark-milestones.svg b/src/assets/images/login/dark-milestones.svg new file mode 100644 index 0000000..67e5405 --- /dev/null +++ b/src/assets/images/login/dark-milestones.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + In November 2017, + + + Dragonfly 1.x project was + + + open source. + + + In October 2018, became + + + the third project in China to + + + enter the CNCF Sandbox. + + + Officially settled in + + + CNCF Incubating in + + + April 2020. + + + In April 2021, it was + + + updated to Dragonfly 2. + + + Milestones + + + More Application Scenarios + + + : + + + Dragonfly 1.x + + + CNCF SandBox + + + Dragonfly 2 + + + CNCF Incubating + + + + + + + So far, dragonflies have experienced the following stages of development. + + + Dragonfly supports different types of storage sources, such as HDFS, S3, GCS, + Azure Blob, + + + OSS, etc. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/login/dragonfly.svg b/src/assets/images/login/dragonfly.svg similarity index 100% rename from public/images/login/dragonfly.svg rename to src/assets/images/login/dragonfly.svg diff --git a/src/assets/images/login/login.svg b/src/assets/images/login/login.svg new file mode 100644 index 0000000..415523c --- /dev/null +++ b/src/assets/images/login/login.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/public/images/login/milestones.svg b/src/assets/images/login/milestones.svg similarity index 100% rename from public/images/login/milestones.svg rename to src/assets/images/login/milestones.svg diff --git a/src/assets/images/login/page-loading.svg b/src/assets/images/login/page-loading.svg new file mode 100644 index 0000000..356ff54 --- /dev/null +++ b/src/assets/images/login/page-loading.svg @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/closure.svg b/src/assets/images/menu/closure.svg new file mode 100644 index 0000000..599d4e8 --- /dev/null +++ b/src/assets/images/menu/closure.svg @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/cluster.svg b/src/assets/images/menu/cluster.svg new file mode 100644 index 0000000..23072bd --- /dev/null +++ b/src/assets/images/menu/cluster.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/public/images/menu/cyan-blur.png b/src/assets/images/menu/cyan-blur.png similarity index 100% rename from public/images/menu/cyan-blur.png rename to src/assets/images/menu/cyan-blur.png diff --git a/src/assets/images/menu/dark.svg b/src/assets/images/menu/dark.svg new file mode 100644 index 0000000..07a88d8 --- /dev/null +++ b/src/assets/images/menu/dark.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/developer.svg b/src/assets/images/menu/developer.svg new file mode 100644 index 0000000..30e6090 --- /dev/null +++ b/src/assets/images/menu/developer.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/expand.svg b/src/assets/images/menu/expand.svg new file mode 100644 index 0000000..8239599 --- /dev/null +++ b/src/assets/images/menu/expand.svg @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/job.svg b/src/assets/images/menu/job.svg new file mode 100644 index 0000000..26b9b9d --- /dev/null +++ b/src/assets/images/menu/job.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/layout.svg b/src/assets/images/menu/layout.svg new file mode 100644 index 0000000..643fca8 --- /dev/null +++ b/src/assets/images/menu/layout.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/images/menu/light.svg b/src/assets/images/menu/light.svg new file mode 100644 index 0000000..efdcc6b --- /dev/null +++ b/src/assets/images/menu/light.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/menu/logo.svg b/src/assets/images/menu/logo.svg new file mode 100644 index 0000000..5ade25a --- /dev/null +++ b/src/assets/images/menu/logo.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/public/images/menu/red-blur.png b/src/assets/images/menu/red-blur.png similarity index 100% rename from public/images/menu/red-blur.png rename to src/assets/images/menu/red-blur.png diff --git a/src/assets/images/menu/selected-cluster.svg b/src/assets/images/menu/selected-cluster.svg new file mode 100644 index 0000000..23072bd --- /dev/null +++ b/src/assets/images/menu/selected-cluster.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/selected-developer.svg b/src/assets/images/menu/selected-developer.svg new file mode 100644 index 0000000..de3f1e9 --- /dev/null +++ b/src/assets/images/menu/selected-developer.svg @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/selected-job.svg b/src/assets/images/menu/selected-job.svg new file mode 100644 index 0000000..26b9b9d --- /dev/null +++ b/src/assets/images/menu/selected-job.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/selected-user.svg b/src/assets/images/menu/selected-user.svg new file mode 100644 index 0000000..7d457c4 --- /dev/null +++ b/src/assets/images/menu/selected-user.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/sidebar-closure.svg b/src/assets/images/menu/sidebar-closure.svg new file mode 100644 index 0000000..66d05c2 --- /dev/null +++ b/src/assets/images/menu/sidebar-closure.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/sidebar-expand.svg b/src/assets/images/menu/sidebar-expand.svg new file mode 100644 index 0000000..d928b5a --- /dev/null +++ b/src/assets/images/menu/sidebar-expand.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/menu/user.svg b/src/assets/images/menu/user.svg new file mode 100644 index 0000000..a6976d1 --- /dev/null +++ b/src/assets/images/menu/user.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/profile/created-at.svg b/src/assets/images/profile/created-at.svg new file mode 100644 index 0000000..93ed18f --- /dev/null +++ b/src/assets/images/profile/created-at.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/profile/email.svg b/src/assets/images/profile/email.svg new file mode 100644 index 0000000..321f7f9 --- /dev/null +++ b/src/assets/images/profile/email.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/profile/id.svg b/src/assets/images/profile/id.svg new file mode 100644 index 0000000..bdd8386 --- /dev/null +++ b/src/assets/images/profile/id.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/profile/location.svg b/src/assets/images/profile/location.svg new file mode 100644 index 0000000..381126c --- /dev/null +++ b/src/assets/images/profile/location.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/src/assets/images/profile/myj.jpg b/src/assets/images/profile/myj.jpg new file mode 100644 index 0000000..5d8cc89 Binary files /dev/null and b/src/assets/images/profile/myj.jpg differ diff --git a/src/assets/images/profile/name.svg b/src/assets/images/profile/name.svg new file mode 100644 index 0000000..ca0aa8c --- /dev/null +++ b/src/assets/images/profile/name.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/profile/phone.svg b/src/assets/images/profile/phone.svg new file mode 100644 index 0000000..af0cfa2 --- /dev/null +++ b/src/assets/images/profile/phone.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/tokens/copy.svg b/src/assets/images/tokens/copy.svg similarity index 100% rename from public/icons/tokens/copy.svg rename to src/assets/images/tokens/copy.svg diff --git a/src/assets/images/tokens/done.svg b/src/assets/images/tokens/done.svg new file mode 100644 index 0000000..1832098 --- /dev/null +++ b/src/assets/images/tokens/done.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/src/assets/images/tokens/key.svg b/src/assets/images/tokens/key.svg new file mode 100644 index 0000000..653da00 --- /dev/null +++ b/src/assets/images/tokens/key.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/user/bio.svg b/src/assets/images/user/bio.svg new file mode 100644 index 0000000..0d55286 --- /dev/null +++ b/src/assets/images/user/bio.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/public/icons/user/change-password.svg b/src/assets/images/user/change-password.svg similarity index 100% rename from public/icons/user/change-password.svg rename to src/assets/images/user/change-password.svg diff --git a/src/assets/images/user/created-at.svg b/src/assets/images/user/created-at.svg new file mode 100644 index 0000000..0abe79a --- /dev/null +++ b/src/assets/images/user/created-at.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/user/detail-role.svg b/src/assets/images/user/detail-role.svg new file mode 100644 index 0000000..1984011 --- /dev/null +++ b/src/assets/images/user/detail-role.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/public/icons/user/detail.svg b/src/assets/images/user/detail.svg similarity index 100% rename from public/icons/user/detail.svg rename to src/assets/images/user/detail.svg diff --git a/src/assets/images/user/edit.svg b/src/assets/images/user/edit.svg new file mode 100644 index 0000000..3041d96 --- /dev/null +++ b/src/assets/images/user/edit.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/public/icons/user/email.svg b/src/assets/images/user/email.svg similarity index 94% rename from public/icons/user/email.svg rename to src/assets/images/user/email.svg index ea2b5a2..c53181f 100644 --- a/public/icons/user/email.svg +++ b/src/assets/images/user/email.svg @@ -2,5 +2,5 @@ p-id="38521" width="200" height="200"> + p-id="38522" fill="currentColor"> \ No newline at end of file diff --git a/src/assets/images/user/guest.svg b/src/assets/images/user/guest.svg new file mode 100644 index 0000000..db021eb --- /dev/null +++ b/src/assets/images/user/guest.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/src/assets/images/user/id.svg b/src/assets/images/user/id.svg new file mode 100644 index 0000000..e8777e7 --- /dev/null +++ b/src/assets/images/user/id.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/user/location.svg b/src/assets/images/user/location.svg new file mode 100644 index 0000000..5f51556 --- /dev/null +++ b/src/assets/images/user/location.svg @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/public/icons/user/name.svg b/src/assets/images/user/name.svg similarity index 93% rename from public/icons/user/name.svg rename to src/assets/images/user/name.svg index bafbb09..6541deb 100644 --- a/public/icons/user/name.svg +++ b/src/assets/images/user/name.svg @@ -2,5 +2,5 @@ p-id="32166" width="200" height="200"> + fill="currentColor" p-id="32167"> \ No newline at end of file diff --git a/src/assets/images/user/phone.svg b/src/assets/images/user/phone.svg new file mode 100644 index 0000000..d1579d5 --- /dev/null +++ b/src/assets/images/user/phone.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/assets/images/user/role.svg b/src/assets/images/user/role.svg new file mode 100644 index 0000000..b2984ad --- /dev/null +++ b/src/assets/images/user/role.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/user/root.svg b/src/assets/images/user/root.svg new file mode 100644 index 0000000..b018c9a --- /dev/null +++ b/src/assets/images/user/root.svg @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/src/assets/images/user/updated-at.svg b/src/assets/images/user/updated-at.svg new file mode 100644 index 0000000..49edaf4 --- /dev/null +++ b/src/assets/images/user/updated-at.svg @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/public/icons/user/user-edit.svg b/src/assets/images/user/user-edit.svg similarity index 100% rename from public/icons/user/user-edit.svg rename to src/assets/images/user/user-edit.svg diff --git a/src/components/404/index.module.css b/src/components/404/index.module.css index f353ce2..5d2af60 100644 --- a/src/components/404/index.module.css +++ b/src/components/404/index.module.css @@ -1,7 +1,7 @@ .container { height: 100vh; overflow: hidden; - background: url(../../../public/images/404/background-image.png); + background: url(../../assets/images/404/background-image.png); } .content { @@ -18,3 +18,13 @@ display: flex; align-items: center; } + +.logoIcon { + width: 1.8rem; + height: 1.8rem; + margin-right: 0.4rem; +} + +.notFound { + width: 38rem; +} diff --git a/src/components/404/index.tsx b/src/components/404/index.tsx index 1c5822a..46a0e52 100644 --- a/src/components/404/index.tsx +++ b/src/components/404/index.tsx @@ -1,6 +1,8 @@ -import { Box, Typography, Grid, CssBaseline, Button } from '@mui/material'; +import { Box, Typography, Grid, Button } from '@mui/material'; import styles from './index.module.css'; import { useNavigate } from 'react-router-dom'; +import { ReactComponent as Logo } from '../../assets/images/404/logo.svg'; +import { ReactComponent as NotFoundImg } from '../../assets/images/404/404.svg'; export default function NotFound() { const navigate = useNavigate(); @@ -8,18 +10,17 @@ export default function NotFound() { return ( - - + + Dragonfly - - - + + Something gone wrong! - + The page you were looking for doesn't exist. { navigate(`/clusters`); diff --git a/src/components/card.tsx b/src/components/card.tsx index b1182ec..36399f9 100644 --- a/src/components/card.tsx +++ b/src/components/card.tsx @@ -12,10 +12,13 @@ const Card: React.FC = ({ children, className, id }) => { = (props: CircularProgressProp ({ + sx={() => ({ color: '#DAF9F2', - ...theme.applyStyles('dark', { - color: 'var(--description-color)', - }), })} size={20} thickness={4} @@ -25,16 +22,13 @@ const SearchCircularProgress: React.FC = (props: CircularProgressProp variant="indeterminate" disableShrink sx={(theme) => ({ - color: 'var(--description-color)', + color: 'var(--palette-description-color)', animationDuration: '550ms', position: 'absolute', left: 0, [`& .${circularProgressClasses.circle}`]: { strokeLinecap: 'round', }, - ...theme.applyStyles('dark', { - color: '#308fe8', - }), })} size={20} thickness={4} diff --git a/src/components/clusters/edit.module.css b/src/components/clusters/edit.module.css index 451d21b..629ca13 100644 --- a/src/components/clusters/edit.module.css +++ b/src/components/clusters/edit.module.css @@ -62,8 +62,16 @@ .descriptionIcon { width: 0.8rem !important ; height: 0.8rem !important; + color: var(--palette-grey-300Channel); } .descriptionIcon:hover { - color: var(--description-color); + color: var(--palette-description-color); +} + +.informationIcon { + width: 2.6rem; + height: 2.6rem; + margin-right: 1rem; + color: var(--palette-button-color); } diff --git a/src/components/clusters/edit.tsx b/src/components/clusters/edit.tsx index a084511..652b98f 100644 --- a/src/components/clusters/edit.tsx +++ b/src/components/clusters/edit.tsx @@ -12,15 +12,18 @@ import { Tooltip, Typography, Skeleton, + Breadcrumbs, + Link as RouterLink, } from '@mui/material'; import styles from './edit.module.css'; import HelpIcon from '@mui/icons-material/Help'; import { useEffect, useState } from 'react'; import { getCluster, updateCluster, getClusterResponse } from '../../lib/api'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Link, useNavigate, useParams } from 'react-router-dom'; import { CancelLoadingButton, SavelLoadingButton } from '../loading-button'; import Card from '../card'; +import { ReactComponent as Information } from '../../assets/images/cluster/information-cluster.svg'; export default function EditCluster() { const [successMessage, setSuccessMessage] = useState(false); @@ -155,7 +158,7 @@ export default function EditCluster() { } placement="top" > - + ), }, @@ -205,12 +208,12 @@ export default function EditCluster() { placement="top" > @@ -268,12 +271,12 @@ export default function EditCluster() { placement="top" > @@ -332,12 +335,12 @@ export default function EditCluster() { placement="top" > @@ -385,7 +388,7 @@ export default function EditCluster() { title={`If other peers download from the seed peer, the load of the seed peer will increase. When the load limit of the seed peer is reached, the scheduler will no longer schedule other peers to download from the seed peer until the it has the free load.`} placement="top" > - + ), }, @@ -426,7 +429,7 @@ export default function EditCluster() { } placement="top" > - + ), }, @@ -467,7 +470,7 @@ export default function EditCluster() { title={`The maximum number of parents that the scheduler can schedule for download peer.`} placement="top" > - + ), }, @@ -509,7 +512,7 @@ export default function EditCluster() { title={`The scheduler will randomly select the number of parents from all the parents according to the filter parent limit and evaluate the optimal parents in selecting parents for the peer to download task. The number of optimal parent is the scheduling parent limit.`} placement="top" > - + ), }, @@ -550,7 +553,7 @@ export default function EditCluster() { title={`The rate limit(requests per second) for job Open API, default value is 10.`} placement="top" > - + ), }, @@ -702,13 +705,26 @@ export default function EditCluster() { Update Cluster + + } + aria-label="breadcrumb" + sx={{ mb: '2rem', mt: '1rem' }} + > + + Cluster + + + {cluster?.name} + + Edit cluster + - + @@ -743,7 +759,7 @@ export default function EditCluster() { Information - + @@ -754,7 +770,7 @@ export default function EditCluster() { onChange={(event: { target: { checked: any } }) => { setCluster({ ...cluster, is_default: event.target.checked }); }} - sx={{ '&.MuiCheckbox-root': { color: 'var(--button-color)' } }} + sx={{ '&.MuiCheckbox-root': { color: 'var(--palette-button-color)' } }} /> } label="Set cluster as your default cluster" @@ -765,7 +781,7 @@ export default function EditCluster() { title="When peer does not find a matching cluster based on scopes, the default cluster will be used." placement="top" > - + {informationForm.map((item) => ( @@ -786,7 +802,7 @@ export default function EditCluster() { the scope." placement="top" > - + @@ -825,7 +841,7 @@ export default function EditCluster() { Config - + @@ -848,7 +864,7 @@ export default function EditCluster() { loading={loadingButton} onClick={() => { setLoadingButton(true); - navigate(`/clusters/${id}`); + navigate(`/clusters/${params.id}`); }} /> } id="save" text="Save" /> diff --git a/src/components/clusters/index.module.css b/src/components/clusters/index.module.css index f9d5a25..2916bc0 100644 --- a/src/components/clusters/index.module.css +++ b/src/components/clusters/index.module.css @@ -12,49 +12,47 @@ .clusterSmallCircleIcon { width: 0.4rem; height: 0.4rem; + color: var(--palette-grey-400Channel); } .button { - background-color: var(--button-color); + background-color: var(--palette-button-color); border-radius: 0; } .clusterBigCircleIcon { - width: 2rem; - height: 2rem; + width: 1.8rem; + height: 1.8rem; + color: var(--palette-grey-400Channel); } .clusterIcon { - width: 1.8rem; - height: 1.8rem; + width: 1.6rem; + height: 1.6rem; position: absolute; left: 0.8rem; top: 0.3rem; + color: var(--palette-grey-200Channel); } .clusterHeaderContainer { - display: flex; - margin-top: 2rem; + display: grid; + gap: calc(1.5rem); + grid-template-columns: repeat(3, 1fr); + margin-top: 1.5rem; } .clusterContainer { - width: 33.3333%; - margin-right: 1.6rem; + padding: 1rem; } .clusterIconTitle { - margin-left: 1rem !important; - margin-top: 0.2rem !important; + margin-left: 0.7rem !important; font-family: 'mabry-bold' !important; } -.seedPeerContainer { - width: 33%; -} - .seedPseerIconTitle { - margin-left: 1rem !important; - margin-top: 0.2rem !important; + margin-left: 0.7rem !important; font-family: 'mabry-bold' !important; } @@ -62,19 +60,25 @@ display: flex; justify-content: space-between; align-items: flex-end; - margin-top: 0.6rem; + margin-top: 0.8rem; + margin-left: 0.6rem; } .clusterBottomContainer { display: flex; align-items: center; padding-top: 0.4rem; - margin-left: -0.3rem; + margin-left: -0.2rem; } .clusterBottomIcon { - width: 1.2rem; - height: 1.2rem; + width: 1.1rem; + height: 1.1rem; + color: var(--palette-description-color); +} + +.statistics { + color: var(--palette-description-color); } .clusterBottomContentContainer { @@ -83,13 +87,13 @@ } .clusterBottomContent { - margin-left: 0.8rem; + padding-left: 0.7rem; + font-family: 'mabry-bold' !important; } .clusterBottomContentMsg { - font-size: 1rem; - margin-left: 0.4rem; - color: var(--table-title-text-color); + padding-left: 0.4rem; + color: var(--palette-table-title-text-color); } .searchContainer { @@ -101,21 +105,18 @@ width: 23rem; } -/* .clusterListContent { - padding: 1.6rem; -} */ - .nameText { font-family: 'mabry-bold' !important; } .idText { - color: var(--table-title-text-color); + color: var(--palette-table-title-text-color); + padding-left: 0.4rem; } .idIcon { - width: 1.8rem; - padding-right: 0.5rem; + width: 1.4rem; + height: 1.4rem; } .descriptionText { @@ -131,6 +132,12 @@ margin-top: 1rem; } +.arrowCircleRightIcon { + width: 1.9rem; + height: 1.9rem; + color: var(--palette-button-color); +} + .buttonContent { padding: 0; } @@ -206,8 +213,8 @@ align-items: center; justify-content: center; flex-direction: column; - background-color: rgba(var(--no-data-color) / 0.04) !important; - border: dashed 1px rgba(var(--no-data-color) / 0.08); + background-color: rgba(var(--palette-no-data-color) / 0.04) !important; + border: dashed 1px rgba(var(--palette-no-data-color) / 0.08); } .nodataIcon { diff --git a/src/components/clusters/index.tsx b/src/components/clusters/index.tsx index 6c1e8d2..aee6c88 100644 --- a/src/components/clusters/index.tsx +++ b/src/components/clusters/index.tsx @@ -1,7 +1,6 @@ import { Alert, Box, - Breadcrumbs, Button, Chip, Grid, @@ -17,8 +16,6 @@ import { TextField, Divider, } from '@mui/material'; -import SearchIcon from '@mui/icons-material/Search'; -import AddIcon from '@mui/icons-material/Add'; import { getSchedulers, getSeedPeers, @@ -27,46 +24,33 @@ import { getSchedulersResponse, getSeedPeersResponse, } from '../../lib/api'; +import SearchIcon from '@mui/icons-material/Search'; +import AddIcon from '@mui/icons-material/Add'; import styles from './index.module.css'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { fuzzySearch, getDatetime, getPaginatedList, useQuery } from '../../lib/utils'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; import MoreTimeIcon from '@mui/icons-material/MoreTime'; -import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight'; import { useLocation, useNavigate } from 'react-router-dom'; import { MAX_PAGE_SIZE } from '../../lib/constants'; import Card from '../card'; import debounce from 'lodash/debounce'; import SearchCircularProgress from '../circular-progress'; - -const theme = createTheme({ - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 900, - lg: 1135, - xl: 1441, - }, - }, - palette: { - secondary: { - main: '#2E8F79', - }, - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as Round } from '../../assets/images/cluster/round.svg'; +import { ReactComponent as Default } from '../../assets/images/cluster/default.svg'; +import { ReactComponent as Statistics } from '../../assets/images/cluster/peer/statistics.svg'; +import { ReactComponent as Active } from '../../assets/images/cluster/active.svg'; +import { ReactComponent as ClusterID } from '../../assets/images/cluster/id.svg'; +import { ReactComponent as IcContent } from '../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as NoCluster } from '../../assets/images/cluster/no-cluster.svg'; +import { ReactComponent as ArrowCircleRightIcon } from '../../assets/images/cluster/arrow-circle-right.svg'; +import { ReactComponent as Cluster } from '../../assets/images/cluster/cluster.svg'; +import { ReactComponent as Scheduler } from '../../assets/images/cluster/scheduler.svg'; +import { ReactComponent as SeedPeer } from '../../assets/images/cluster/seed-peer.svg'; export default function Clusters() { const [errorMessage, setErrorMessage] = useState(false); const [errorMessageText, setErrorMessageText] = useState(''); const [isLoading, setIsLoading] = useState(true); - const [clusterIsLoading, setClusterIsLoading] = useState(true); const [clusterPage, setClusterPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [pageSize, setPageSize] = useState(9); @@ -87,7 +71,6 @@ export default function Clusters() { (async function () { try { setIsLoading(true); - setClusterIsLoading(true); setClusterPage(page); const [cluster, scheduler, seedPeer] = await Promise.all([ @@ -101,7 +84,6 @@ export default function Clusters() { setSeedPeer(seedPeer); setClusterCount(cluster); setIsLoading(false); - setClusterIsLoading(false); } catch (error) { if (error instanceof Error) { setErrorMessage(true); @@ -209,7 +191,7 @@ export default function Clusters() { }; return ( - + - - } - aria-label="breadcrumb" - > - - Cluster - - + Cluster { navigate(`/clusters/new`); @@ -247,130 +222,120 @@ export default function Clusters() { - - - - - - - - - - - Cluster - - - - - - - {isLoading ? ( - - ) : ( - clusterCount?.length || 0 - )} - - number of clusters - - - - - - {isLoading ? ( - - ) : ( - numberOfDefaultClusters || 0 - )} - - default - - - - - + + + + + + - - - - - - - - - - - - - Scheduler + + Cluster + + + + + + + {isLoading ? : clusterCount?.length || 0} + number of clusters - - - - - {isLoading ? : scheduler?.length || 0} - - number of schedulers - - - - - - {isLoading ? ( - - ) : ( - numberOfActiveSchedulers || 0 - )} - - active - - + + + + + {isLoading ? ( + + ) : ( + numberOfDefaultClusters || 0 + )} + + + default + - - + - - - - - - - - - - - - - Seed Peer + + + + + + + + + + + + Scheduler + + + + + + + {isLoading ? : scheduler?.length || 0} + number of schedulers - - - - - {isLoading ? : seedPeer.length || 0} - - number of seed peers - - - - - - {isLoading ? ( - - ) : ( - numberOfActiveSeedPeers || 0 - )} - - active - - + + + + + {isLoading ? ( + + ) : ( + numberOfActiveSchedulers || 0 + )} + + + active + - - + - - + + + + + + + + + + + + Seed Peer + + + + + + + {isLoading ? : seedPeer.length || 0} + + number of seed peers + + + + + + {isLoading ? ( + + ) : ( + numberOfActiveSeedPeers || 0 + )} + + + active + + + + + + + @@ -426,19 +391,19 @@ export default function Clusters() { {isLoading ? ( - + - - - + + + - + ) : Array.isArray(clusterCount) && clusterCount.length === 0 ? ( - + You have no clusters. ) : Array.isArray(allClusters) && allClusters.length === 0 ? ( - + No results for @@ -483,15 +448,11 @@ export default function Clusters() { - - - {clusterIsLoading ? ( - - ) : ( - - {item.id} - - )} + + + + {item.id} + - {clusterIsLoading ? : item.name} + {item.name} @@ -508,11 +469,7 @@ export default function Clusters() { variant="caption" className={styles.descriptionText} > - {clusterIsLoading ? ( - - ) : ( - item.bio || '-' - )} + {item.bio || '-'} @@ -520,61 +477,44 @@ export default function Clusters() { - {clusterIsLoading ? ( - - ) : ( - - {`${ - item.is_default ? 'Default' : 'Non-Default' - }`} - - )} + + {`${item.is_default ? 'Default' : 'Non-Default'}`} + } - label={ - clusterIsLoading ? ( - - ) : ( - getDatetime(item.created_at) - ) - } + label={getDatetime(item.created_at)} variant="outlined" size="small" /> { navigate(`/clusters/${item.id}`); }} > - + @@ -585,7 +525,7 @@ export default function Clusters() { )} {totalPages > 1 ? ( - + > )} - + ); } diff --git a/src/components/clusters/information.module.css b/src/components/clusters/information.module.css index 5aa556a..ec61691 100644 --- a/src/components/clusters/information.module.css +++ b/src/components/clusters/information.module.css @@ -31,6 +31,12 @@ width: 2.8rem; height: 2.8rem; margin-right: 1rem; + color: var(--palette-button-color); +} + +.copyIcon { + width: 1rem; + height: 1rem; } .updateClusterIcon { @@ -44,7 +50,7 @@ height: 6rem; } -.className { +.name { padding-bottom: 0.4rem; font-family: 'mabry-bold' !important; } @@ -79,20 +85,21 @@ .descriptionIcon { width: 0.9rem !important ; height: 0.9rem !important; + color: var(--palette-grey-300Channel); } .descriptionIcon:hover { - color: var(--description-color); + color: var(--palette-description-color); } .configLable { - color: var(--table-title-text-color); + color: var(--palette-table-title-text-color); margin-right: 0.2rem !important; font-family: 'mabry-bold' !important; } .scopesLable { - color: var(--button-color) !important; + color: var(--palette-button-color) !important; font-family: 'mabry-bold' !important; margin-right: 0.2rem !important; padding-left: 0.4rem; @@ -116,13 +123,14 @@ .scopesIcon { width: 1.6rem; height: 1.6rem; + color: var(--palette-button-color); } .totalContainer { display: flex; align-items: center; padding: 0.3rem; - background-color: var(--menu-background-color) !important; + background-color: var(--palette-grey-background-color) !important; } .totalIcon { @@ -220,7 +228,7 @@ align-items: center; justify-content: center; margin-top: 0.4rem; - padding: 0.5rem; + padding: 0.2rem 0.4rem; } .cidrsText { @@ -266,42 +274,36 @@ } .idcDialogContainer { - display: flex; - flex-wrap: wrap; - justify-content: space-between; + gap: calc(1.5rem); + display: grid; + grid-template-columns: repeat(2, 1fr); } .cidrsDialogContent { - width: 45%; background-color: #f7f7f8 !important; display: flex; align-items: center; justify-content: flex-start; padding: 0.4rem 0.8rem; - margin-bottom: 0.8rem; - margin-right: 0.5rem; - margin-left: 0.5rem; } .cidrsDialogContainer { - display: flex; - flex-wrap: wrap; + gap: calc(1.5rem); + display: grid; + grid-template-columns: repeat(2, 1fr); } .idcDialogContent { - width: 45%; background-color: #f7f7f8 !important; display: flex; align-items: center; justify-content: flex-start; padding: 0.4rem 0.8rem; - margin-bottom: 0.8rem; - margin-right: 0.5rem; - margin-left: 0.5rem; } .cidrsIcon { width: 1.6rem; height: 1.6rem; margin-right: 0.3rem; + color: var(--palette-save-color); } diff --git a/src/components/clusters/information.tsx b/src/components/clusters/information.tsx index 94c3a9b..d47bbc0 100644 --- a/src/components/clusters/information.tsx +++ b/src/components/clusters/information.tsx @@ -15,11 +15,21 @@ import Dialog from '@mui/material/Dialog'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import styles from './information.module.css'; import Card from '../card'; -import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined'; +import HelpIcon from '@mui/icons-material/Help'; import { useContext, useState } from 'react'; import { useCopyToClipboard } from 'react-use'; import { MyContext } from './show'; -import { CancelLoadingButton, DeleteLoadingButton, SavelLoadingButton } from '../loading-button'; +import { ReactComponent as InformationCluster } from '../../assets/images/cluster/information-cluster.svg'; +import { ReactComponent as Done } from '../../assets/images/tokens/done.svg'; +import { ReactComponent as Copy } from '../../assets/images/tokens/copy.svg'; +import { ReactComponent as Edit } from '../../assets/images/user/edit.svg'; +import { ReactComponent as Location } from '../../assets/images/cluster/location.svg'; +import { ReactComponent as IDC } from '../../assets/images/cluster/idc.svg'; +import { ReactComponent as Total } from '../../assets/images/cluster/total.svg'; +import { ReactComponent as CIDRs } from '../../assets/images/cluster/cidrs.svg'; +import { ReactComponent as Hostnames } from '../../assets/images/cluster/hostnames.svg'; +import { ReactComponent as Delete } from '../../assets/images/cluster/delete.svg'; +import { CancelLoadingButton, DeleteLoadingButton } from '../loading-button'; import { Chart as ChartJS, ArcElement, @@ -109,6 +119,7 @@ export default function Information() { } } }; + return ( - + Update @@ -178,12 +187,17 @@ export default function Information() { - + - + {isLoading ? : cluster.name || '-'} - + {isLoading ? : cluster?.bio || '-'} @@ -198,7 +212,7 @@ export default function Information() { title="When peer does not find a matching cluster based on scopes, the default cluster will be used." placement="top" > - + @@ -206,7 +220,9 @@ export default function Information() { sx={{ width: '0.8rem', height: '0.8rem', - backgroundColor: cluster.is_default ? 'var(--description-color)' : 'var(--button-color)', + backgroundColor: cluster.is_default + ? 'var(--palette-description-color)' + : 'var(--palette-dark-300Channel)', borderRadius: '0.2rem', mr: '0.5rem', }} @@ -222,7 +238,6 @@ export default function Information() { - @@ -232,7 +247,7 @@ export default function Information() { title="When the scheduler is deployed, the schedulerClusterID must be filled with this scheduler cluster ID in scheduler configuration. In this way, the scheduler will become the scheduling service of this cluster." placement="top" > - + @@ -257,6 +272,7 @@ export default function Information() { sx={{ width: '1.2rem', height: '1.2rem', + p: 0, }} onClick={() => { copyClusterID('schedulerClusterID', cluster?.scheduler_cluster_id || 0); @@ -276,15 +292,10 @@ export default function Information() { title="copied!" id="schedulerClusterIDTooltip" > - + ) : ( - + )} )} @@ -299,7 +310,7 @@ export default function Information() { title="When the seed peer is deployed, the clusterID must be filled with this seed peer cluster ID in scheduler configuration. In this way, the seed peer will become the seed peer service of this cluster." placement="top" > - + @@ -325,6 +336,7 @@ export default function Information() { sx={{ width: '1.2rem', height: '1.2rem', + p: 0, }} onClick={() => { copyClusterID('seedPeerClusterID', cluster?.seed_peer_cluster_id || 0); @@ -343,15 +355,10 @@ export default function Information() { title="copied!" id="seedPeerClusterIDTooltip" > - + ) : ( - + )} )} @@ -363,7 +370,7 @@ export default function Information() { Create At - + @@ -382,7 +389,7 @@ export default function Information() { peers in the scope." placement="top" > - + @@ -390,7 +397,7 @@ export default function Information() { Config - + @@ -399,7 +406,7 @@ export default function Information() { - + Location @@ -407,7 +414,7 @@ export default function Information() { title={`The cluster needs to serve all peers in the location. When the location in the peer configuration matches the location in the cluster, the peer will preferentially use the scheduler and the seed peer of the cluster. It separated by "|", for example "area|country|province|city".`} placement="top" > - + @@ -432,7 +439,7 @@ export default function Information() { - + IDC @@ -440,12 +447,12 @@ export default function Information() { title={`The cluster needs to serve all peers in the IDC. When the IDC in the peer configuration matches the IDC in the cluster, the peer will preferentially use the scheduler and the seed peer of the cluster. IDC has higher priority than location in the scopes.`} placement="top" > - + - - + + {`Total: ${cluster?.scopes?.idc !== '' ? cluster?.scopes?.idc.split('|').length : 0}`} @@ -503,7 +510,7 @@ export default function Information() { setOpenIDC(true); }} > - + ) : ( <>> @@ -527,7 +534,7 @@ export default function Information() { {cluster?.scopes?.idc.split('|').map((item: any, id: any) => ( - + {item} @@ -541,7 +548,7 @@ export default function Information() { - + CIDRs @@ -549,12 +556,12 @@ export default function Information() { title={`The cluster needs to serve all peers in the CIDRs. The advertise IP will be reported in the peer configuration when the peer is started, and if the advertise IP is empty in the peer configuration, peer will automatically get expose IP as advertise IP. When advertise IP of the peer matches the CIDRs in cluster, the peer will preferentially use the scheduler and the seed peer of the cluster. CIDRs has higher priority than IDC in the scopes. CIDRs has higher priority than IDC in the scopes. CIDRs has priority equal to hostname in the scopes.`} placement="top" > - + - - + + {`Total: ${cluster?.scopes?.cidrs?.length || 0}`} @@ -615,7 +622,7 @@ export default function Information() { setOpenCIDRs(true); }} > - + ) : ( <>> @@ -641,7 +648,7 @@ export default function Information() { {cluster?.scopes?.cidrs?.map((item: any, id: any) => ( - + {item} @@ -654,7 +661,7 @@ export default function Information() { - + Hostnames @@ -664,12 +671,12 @@ export default function Information() { } placement="top" > - + - - + + {`Total: ${cluster?.scopes?.idc !== '' ? cluster?.scopes?.idc.split('|').length : 0}`} @@ -730,7 +737,7 @@ export default function Information() { setOpenHostnames(true); }} > - + ) : ( <>> @@ -756,7 +763,7 @@ export default function Information() { {cluster?.scopes?.hostnames?.map((item: any, id: any) => ( - + {item} @@ -777,7 +784,7 @@ export default function Information() { title="If other peers download from the seed peer, the load of the seed peer will increase. When the load limit of the seed peer is reached, the scheduler will no longer schedule other peers to download from the seed peer until the it has the free load. seed_peer_cluster_config.load_limit" placement="top" > - + {isLoading ? ( @@ -799,7 +806,7 @@ export default function Information() { title={`If other peers download from the peer, the load of the peer will increase. When the load limit of the peer is reached, the scheduler will no longer schedule other peers to download from the peer until the it has the free load.`} placement="top" > - + {isLoading ? ( @@ -821,7 +828,7 @@ export default function Information() { title="The maximum number of parents that the scheduler can schedule for download peer." placement="top" > - + {isLoading ? ( @@ -843,7 +850,7 @@ export default function Information() { title="The scheduler will randomly select the number of parents from all the parents according to the filter parent limit and evaluate the optimal parents in selecting parents for the peer to download task. The number of optimal parent is the scheduling parent limit." placement="top" > - + {isLoading ? ( @@ -865,7 +872,7 @@ export default function Information() { title="The rate limit(requests per second) for job Open API, default value is 10." placement="top" > - + {isLoading ? ( @@ -889,7 +896,7 @@ export default function Information() { > - + Are you sure you want to delet this cluster? diff --git a/src/components/clusters/new.module.css b/src/components/clusters/new.module.css index c8addb4..5713c6d 100644 --- a/src/components/clusters/new.module.css +++ b/src/components/clusters/new.module.css @@ -49,8 +49,20 @@ .descriptionIcon { width: 0.8rem !important ; height: 0.8rem !important; + color: var(--palette-grey-300Channel); } .descriptionIcon:hover { - color: var(--description-color); + color: var(--palette-description-color); +} + +.card { + padding: 2rem; + margin: auto; + width: 60%; +} + +.buttonContainer { + margin: auto; + width: 60%; } diff --git a/src/components/clusters/new.tsx b/src/components/clusters/new.tsx index 65f99db..41939df 100644 --- a/src/components/clusters/new.tsx +++ b/src/components/clusters/new.tsx @@ -2,6 +2,7 @@ import { Alert, Autocomplete, Box, + Breadcrumbs, Checkbox, Chip, Divider, @@ -11,12 +12,13 @@ import { TextField, Tooltip, Typography, + Link as RouterLink, } from '@mui/material'; import styles from './new.module.css'; import { useState } from 'react'; import HelpIcon from '@mui/icons-material/Help'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import { useNavigate } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { createCluster } from '../../lib/api'; import { CancelLoadingButton, SavelLoadingButton } from '../loading-button'; @@ -116,7 +118,7 @@ export default function NewCluster() { title={`The cluster needs to serve all peers in the location. When the location in the peer configuration matches the location in the cluster, the peer will preferentially use the scheduler and the seed peer of the cluster. It separated by "|", for example "area|country|province|city".`} placement="top" > - + ), }, @@ -167,12 +169,12 @@ export default function NewCluster() { placement="top" > @@ -234,12 +236,12 @@ export default function NewCluster() { placement="top" > @@ -299,12 +301,12 @@ export default function NewCluster() { placement="top" > @@ -349,7 +351,7 @@ export default function NewCluster() { title={`If other peers download from the seed peer, the load of the seed peer will increase. When the load limit of the seed peer is reached, the scheduler will no longer schedule other peers to download from the seed peer until the it has the free load.`} placement="top" > - + ), }, @@ -386,7 +388,7 @@ export default function NewCluster() { } placement="top" > - + ), }, @@ -421,7 +423,7 @@ export default function NewCluster() { title={`The maximum number of parents that the scheduler can schedule for download peer.`} placement="top" > - + ), }, @@ -457,7 +459,7 @@ export default function NewCluster() { title={`The scheduler will randomly select the number of parents from all the parents according to the filter parent limit and evaluate the optimal parents in selecting parents for the peer to download task. The number of optimal parent is the scheduling parent limit.`} placement="top" > - + ), }, @@ -490,7 +492,7 @@ export default function NewCluster() { InputProps: { endAdornment: ( - + ), }, @@ -656,7 +658,23 @@ export default function NewCluster() { {errorMessageText} - Create Cluster + + Create Cluster + + + } + aria-label="breadcrumb" + sx={{ mt: '1rem' }} + > + + Cluster + + New cluster + @@ -665,12 +683,12 @@ export default function NewCluster() { Information - + } + control={} label="Set cluster as your default cluster" name="isDefault" sx={{ '&.MuiFormControlLabel-root': { mr: '0.6rem' } }} @@ -679,7 +697,7 @@ export default function NewCluster() { title="When peer does not find a matching cluster based on scopes, the default cluster will be used." placement="top" > - + @@ -712,7 +730,7 @@ export default function NewCluster() { the scope." placement="top" > - + @@ -751,7 +769,7 @@ export default function NewCluster() { Config - + diff --git a/src/components/clusters/peers/inde.module.css b/src/components/clusters/peers/inde.module.css index 9555ca5..0104d41 100644 --- a/src/components/clusters/peers/inde.module.css +++ b/src/components/clusters/peers/inde.module.css @@ -9,7 +9,7 @@ display: flex; align-items: center; justify-content: space-between; - margin-bottom: 2rem; + margin-bottom: 1.5rem; } .headerTitle { @@ -17,6 +17,30 @@ align-items: center; } +.navigationContainer { + display: grid; + gap: calc(1.5rem); + grid-template-columns: repeat(3, 1fr); + margin-bottom: 2rem; +} + +.navigationCount { + display: flex; + align-items: center; +} + +.navigationCountIcon { + background-color: rgba(34 197 94 / 0.18); + color: var(--palette-description-color); + width: 1.5rem; + height: 1.5rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.5rem; +} + .navigationContent { display: flex; justify-content: space-between; @@ -29,24 +53,25 @@ } .navigation { - top: -3rem; + top: -2rem; width: 160px; z-index: -1; height: 160px; - right: -5rem; + right: -6rem; opacity: 0.12; border-radius: 24px; position: absolute; transform: rotate(34deg); - background: linear-gradient(to right, #22c55e 0%, rgba(34 197 94 / 0) 100%); + background: linear-gradient(to right, var(--palette-text-color) 0%, transparent 100%); } .navigationIcon { - width: 2.4rem; - height: 2.4rem; - top: 1.4rem; - right: 1.8rem; + width: 2rem; + height: 2rem; + top: 2.4rem; + right: 1.2rem; position: absolute; + color: var(--palette-text-color); } .dashboard { @@ -91,6 +116,7 @@ width: 1.8rem; height: 1.8rem; margin-right: 0.6rem; + color: var(--palette-text-color); } .activeContent { @@ -101,7 +127,7 @@ .linearProgress { width: 100%; - color: var(--description-color); + color: var(--palette-description-color); } .descriptionIcon { @@ -111,42 +137,24 @@ } .descriptionIcon:hover { - color: var(--description-color); + color: var(--palette-description-color); } .exportIcon { width: 1.8rem; -} - -.featuresIconWrapper { - width: 2.4rem; - height: 2.4rem; - border-radius: 50%; - background-color: #fbfbfb; - display: flex; - align-items: center; - justify-content: center; - margin-right: 0.6rem; -} - -.featuresIconContainer { - width: 1.8rem; height: 1.8rem; - border-radius: 50%; - background-color: #efefef; - display: flex; - align-items: center; - justify-content: center; } -.featuresIcon { - width: 1.2rem; - height: 1.2rem; +.exportFileICon { + width: 2.8rem; + height: 2.8rem; + margin-bottom: 0.8rem; + color: var(--palette-color); } .divider { border-width: 0px 0px thin; - border-color: var(--palette-divider) !important; + border-color: var(--palette-palette-divider) !important; border-style: dashed !important; } @@ -165,3 +173,15 @@ justify-content: center; padding: 1rem 2rem; } + +.refreshIcon { + width: 1.2rem; + height: 1.2rem; + color: var(--palette-button-text-color); +} + +.deleteWarning { + width: 1.4rem; + height: 1.4rem; + padding-right: 0.2rem; +} diff --git a/src/components/clusters/peers/index.tsx b/src/components/clusters/peers/index.tsx index c628c11..5271ef5 100644 --- a/src/components/clusters/peers/index.tsx +++ b/src/components/clusters/peers/index.tsx @@ -1,7 +1,6 @@ import { Box, Button, - Paper, Typography, Divider, FormControl, @@ -11,14 +10,13 @@ import { Dialog, DialogContent, LinearProgress, - createTheme, - ThemeProvider, Skeleton, Snackbar, Alert, Tooltip as MuiTooltip, IconButton, Link, + useTheme, } from '@mui/material'; import { Chart as ChartJS, @@ -45,33 +43,22 @@ import { CancelLoadingButton, SavelLoadingButton } from '../../loading-button'; import { MyContext } from '../../clusters/show'; import _ from 'lodash'; import Card from '../../card'; +import { ReactComponent as RefreshLoading } from '../../../assets/images/cluster/peer/refresh-loading.svg'; +import { ReactComponent as Refresh } from '../../../assets/images/cluster/peer/refresh.svg'; +import { ReactComponent as RefreshDialog } from '../../../assets/images/cluster/peer/refresh-dialog.svg'; +import { ReactComponent as DeleteWarning } from '../../../assets/images/cluster/delete-warning.svg'; +import { ReactComponent as Total } from '../../../assets/images/cluster/peer/total.svg'; +import { ReactComponent as GitVersion } from '../../../assets/images/cluster/peer/git-versions.svg'; +import { ReactComponent as GitCommit } from '../../../assets/images/cluster/peer/git-commits.svg'; +import { ReactComponent as Active } from '../../../assets/images/cluster/peer/active.svg'; +import { ReactComponent as Export } from '../../../assets/images/cluster/peer/export.svg'; +import { ReactComponent as ExportFile } from '../../../assets/images/cluster/peer/export-file.svg'; +import { ReactComponent as Count } from '../../../assets/images/cluster/scheduler/number.svg'; +import { ColorModeContext } from '../../../App'; ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement, Title); Chart.defaults.font.family = 'mabry-light'; -const theme = createTheme({ - breakpoints: { - values: { - xs: 0, - sm: 600, - md: 900, - lg: 1135, - xl: 1441, - }, - }, - palette: { - secondary: { - main: '#2E8F79', - }, - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); - export default function Peer() { const [errorMessage, setErrorMessage] = useState(false); const [errorMessageText, setErrorMessageText] = useState(''); @@ -98,6 +85,9 @@ export default function Peer() { const [disabled, setDisabled] = useState(false); const { cluster } = useContext(MyContext); + const theme = useTheme(); + const colorMode = useContext(ColorModeContext); + useEffect(() => { (async function () { try { @@ -246,29 +236,32 @@ export default function Peer() { datasets: [ { data: gitVersion.map((item) => item.count), - backgroundColor: 'rgb(46,143,121)', - borderColor: 'rgb(46,143,121)', - borderWidth: 1, + backgroundColor: theme.palette.mode === 'dark' ? '#01A76F' : 'rgb(31, 125, 83)', borderRadius: 5, barPercentage: 0.6, }, ], }; + const doughnutBackgroundColor = [ + 'rgb(31, 125, 83)', + 'rgba(31, 125, 83,0.8)', + 'rgba(31, 125, 83,0.6)', + 'rgba(31, 125, 83,0.4)', + 'rgba(31, 125, 83,0.2)', + ]; + + const darkDoughnutBackgroundColor = ['#01A76F', '#5BE49B', '#C8FAD6', '#004B50', '#007868']; + const gitVersionDoughnut = { labels: gitVersion.map((item) => item.name), datasets: [ { label: 'Git Version', data: gitVersion.map((item) => item.count), - backgroundColor: [ - 'rgb(46,143,121)', - 'rgba(46,143,121,0.8)', - 'rgba(46,143,121,0.6)', - 'rgba(46,143,121,0.4)', - 'rgba(46,143,121,0.2)', - ], - borderWidth: 1, + backgroundColor: theme.palette.mode === 'dark' ? darkDoughnutBackgroundColor : doughnutBackgroundColor, + borderWidth: 0, + borderColor: 'rgba(255, 255, 255, 0.6)', }, ], }; @@ -278,9 +271,8 @@ export default function Peer() { datasets: [ { data: gitCommit.map((item) => item.count), - backgroundColor: 'rgb(46,143,121)', - borderColor: 'rgb(46,143,121)', - borderWidth: 1, + backgroundColor: theme.palette.mode === 'dark' ? '#01A76F' : 'rgb(31, 125, 83)', + borderWidth: 0, borderRadius: 5, barPercentage: 0.6, }, @@ -293,14 +285,9 @@ export default function Peer() { { label: 'Git Commit', data: gitCommit.map((item) => item.count), - backgroundColor: [ - 'rgb(46,143,121)', - 'rgba(46,143,121,0.8)', - 'rgba(46,143,121,0.6)', - 'rgba(46,143,121,0.4)', - 'rgba(46,143,121,0.2)', - ], - borderWidth: 1, + backgroundColor: theme.palette.mode === 'dark' ? darkDoughnutBackgroundColor : doughnutBackgroundColor, + borderWidth: 0, + borderColor: 'rgba(255, 255, 255, 0.6)', }, ], }; @@ -441,534 +428,523 @@ export default function Peer() { }; return ( - - - - - {errorMessageText} - - - - - - Peers - - - Peer statistics are only supported in the Rust client, refer to - - dragonflyoss/client - - . + + + + {errorMessageText} + + + + + + Peers + + + Peer statistics are only supported in the Rust client, refer to + + dragonflyoss/client + + . + + } + placement="top" + > + + + + + { + setOpenRefresh(true); + }} + startIcon={ + refresh ? : + } + > + refresh + + { + setOpenExport(true); + }} + startIcon={} + > + Export + + + + + + + + + Total + + {isLoading ? ( + + ) : ( + + {peer.length} - } - placement="top" - > - - + )} + + + + + + number of peers + + + + + - - { - setOpenRefresh(true); - }} - startIcon={ - refresh ? ( - - ) : ( - - ) - } - > - refresh - - { - setOpenExport(true); - }} - startIcon={} - > - Export - + + + + + + Git Version + + {isLoading ? ( + + ) : ( + + {gitVersionCount} + + )} + + + + + + number of git versions + + + + + - - - - - + + + + + + Git Commit + + {isLoading ? ( + + ) : ( + + {gitCommitCount} + + )} + + + + + + number of git commits + + + + + + + + + + + + + - - Total + + Peer Statistics - {isLoading ? ( - - ) : ( - - {peer.length} - - )} - - number of peers + + by Git Version - - + + + + + + - - - - - - - Git Version - - {isLoading ? ( - - ) : ( - - {gitVersionCount} - - )} - - number of git versions - - - - - - - - - - - - - Git Commit - - {isLoading ? ( - - ) : ( - - {gitCommitCount} - - )} - - number of git commits - - - - - - - - - - - - - + + + - + Peer Statistics by Git Version - + - - + + + - - - - - - - Peer Statistics - - - by Git Version - - - - - - - - - + + + + + + + Active + + + {isLoading ? : gitVersionActive ? `${gitVersionActive}%` : '0'} + + - - - - - - Active - - - {isLoading ? : gitVersionActive ? `${gitVersionActive}%` : '0'} - - - - - - + + + + + + + + + Git Version + { + setSelectedGitGitCommitByVersion(e.target.value); + }} + > + + Filter by git version + + + + All + + {selectedGitVersions.map((item) => ( + + {item} + + ))} + + - - - - - Git Version - { - setSelectedGitGitCommitByVersion(e.target.value); - }} - > - - Filter by git version - - - - All - - {selectedGitVersions.map((item) => ( - - {item} - - ))} - - + + + + + + Peer Statistics + + + by Git Commit + + + + + - - - - + + + + + + + - + Peer Statistics by Git Commit - + - - + + + - - - - - - - Peer Statistics - - - by Git Commit - - - - - - - - - + + + + + + + Active + + + {isLoading ? : gitCommitActive ? `${gitCommitActive}%` : '0'} + + - - - - - - Active - - - {isLoading ? : gitCommitActive ? `${gitCommitActive}%` : '0'} - - - - - - - + + - - + + + + + + + Export + + + { + setOpenExport(false); + setExportSelectedVersion('All'); + setExportSelectedCommit('All'); + }} + sx={{ + color: (theme) => theme.palette.grey[500], + p: 0, + }} + > + + + + + + + + + Export Your Data With Fun + + + - - - Export - + + Git Version + setExportSelectedVersion(e.target.value)} + > + + Filter by git version + + + + All + + {exportSelectedGitVersion.map((item) => ( + + {item} + + ))} + + + + Git Commit + setExportSelectedCommit(e.target.value)} + > + + Filter by git commit + + + + All + + {exportSelectedGitCommit.map((item) => ( + + {item} + + ))} + + - + + { setOpenExport(false); setExportSelectedVersion('All'); setExportSelectedCommit('All'); }} - sx={{ - color: (theme) => theme.palette.grey[500], - p: 0, - }} - > - - + /> + } + id="save" + text="Save" + onClick={ExportCSV} + /> - - - - - - Export Your Data With Fun + + + + + + + + Refresh + + + { + setOpenRefresh(false); + }} + sx={{ + color: (theme) => theme.palette.grey[500], + p: 0, + }} + > + + + + + + + + + + WARNING: + + + This action CANNOT be undone. - - - - Git Version - setExportSelectedVersion(e.target.value)} - > - - Filter by git version - - - - All - - {exportSelectedGitVersion.map((item) => ( - - {item} - - ))} - - - - Git Commit - setExportSelectedCommit(e.target.value)} - > - - Filter by git commit - - - - All - - {exportSelectedGitCommit.map((item) => ( - - {item} - - ))} - - - - - - { - setOpenExport(false); - setExportSelectedVersion('All'); - setExportSelectedCommit('All'); - }} - /> - } - id="save" - text="Save" - onClick={ExportCSV} - /> - - - - - - - - - Refresh - - - + The peer data will be forced to refresh. + + { setOpenRefresh(false); }} - sx={{ - color: (theme) => theme.palette.grey[500], - p: 0, - }} - > - - + /> + } + id="save" + text="Save" + onClick={handleRefresh} + /> - - - - - - - - WARNING: - - - This action CANNOT be undone. - - - - The peer data will be forced to refresh. - - { - setOpenRefresh(false); - }} - /> - } - id="save" - text="Save" - onClick={handleRefresh} - /> - - - - - + + + ); } diff --git a/src/components/clusters/schedulers/index.module.css b/src/components/clusters/schedulers/index.module.css index 49fb364..8372f72 100644 --- a/src/components/clusters/schedulers/index.module.css +++ b/src/components/clusters/schedulers/index.module.css @@ -12,7 +12,7 @@ .schedulerInactiveListTitle { display: flex; padding: 0.8rem 1rem; - background-color: var(--table-title-color) !important; + background-color: var(--palette-table-title-color) !important; } .noInactiveScheduler { @@ -26,12 +26,12 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 2rem; + margin-bottom: 1.5rem; } .logHeaderWrapper { display: flex; - margin-bottom: 2rem; + margin-bottom: 1.5rem; } .deleteInactiveWrapper { @@ -70,11 +70,16 @@ justify-content: center; } +.featuresHeaderIcon { + width: 1.6rem; + height: 1.6rem; +} + .featuresIconWrapper { width: 2.4rem; height: 2.4rem; border-radius: 50%; - background-color: #fbfbfb; + background-color: var(--palette-white-500Channel); display: flex; align-items: center; justify-content: center; @@ -85,7 +90,7 @@ width: 1.8rem; height: 1.8rem; border-radius: 50%; - background-color: #efefef; + background-color: var(--palette-white-400Channel); display: flex; align-items: center; justify-content: center; @@ -94,24 +99,28 @@ .featuresIcon { width: 1rem; height: 1rem; + color: var(--palette-save-color); } .menu { - background-image: url(../../../../public/images/menu/cyan-blur.png), url(../../../../public/images/menu/red-blur.png); - background-color: rgba(255, 255, 255, 0.9); + background-color: var(--palette-background-menu); + background-image: url(../../../assets/images/menu/cyan-blur.png), url(../../../assets/images/menu/red-blur.png); background-repeat: no-repeat, no-repeat; padding: 0.2rem; background-size: 50%, 50%; - box-shadow: rgba(145, 158, 171, 0.24) 0px 0px 2px 0px, rgba(145, 158, 171, 0.24) -20px 20px 40px -4px; transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); outline: 0px; background-position: right top, left bottom; - border-radius: 10px; + border-radius: var(--menu-border-radius); overflow: inherit; } +.menuItem { + border-radius: var(--menu-border-radius) !important; +} + .menuItemIcon { - color: var(--button-color); + color: var(--palette-button-color); } .menuText { @@ -135,7 +144,7 @@ display: flex; justify-content: space-between; align-items: center; - padding-bottom: 2rem; + padding-bottom: 1.5rem; } .idIcon { @@ -148,6 +157,7 @@ width: 1rem; height: 1rem; margin-right: 0.4rem; + color: var(--palette-text-color); } .circularProgressWrapper { @@ -195,6 +205,11 @@ align-items: center; } +.schedulerInactiveTable { + font-family: 'mabry-bold'; + color: var(--palette-table-title-text-color); +} + .schedulerInactiveHeaderIP { width: 25%; white-space: nowrap; @@ -232,7 +247,7 @@ display: flex; align-items: center; justify-content: space-between; - padding: 0.5rem; + padding: 0.6rem; } .featuresEdit:nth-last-child(2n) { @@ -308,8 +323,8 @@ align-items: center; justify-content: center; flex-direction: column; - background-color: rgba(var(--no-data-color) / 0.04) !important; - border: dashed 1px rgba(var(--no-data-color) / 0.08); + background-color: rgba(var(--palette-no-data-color) / 0.04) !important; + border: dashed 1px rgba(var(--palette-no-data-color) / 0.08); } .nodataIcon { @@ -322,6 +337,13 @@ font-family: 'mabry-bold'; } +.navigationContainer { + display: grid; + gap: calc(1.5rem); + grid-template-columns: repeat(3, 1fr); + margin-bottom: 1.5rem; +} + .navigationWrapper { padding: 1.2rem; position: relative; @@ -330,33 +352,55 @@ } .navigation { - top: -3rem; + top: -2rem; width: 160px; z-index: -1; height: 160px; - right: -5rem; + right: -6rem; opacity: 0.12; border-radius: 24px; position: absolute; transform: rotate(34deg); - background: linear-gradient(to right, #22c55e 0%, rgba(34 197 94 / 0) 100%); + background: linear-gradient(to right, var(--palette-text-color) 0%, transparent 100%); +} + +.navigationCount { + display: flex; + align-items: center; +} + +.navigationCountIcon { + background-color: rgba(31, 125, 83, 0.2); + color: var(--palette-text-color); + width: 1.5rem; + height: 1.5rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.5rem; } .navigationIcon { - width: 2.4rem; - height: 2.4rem; - top: 1.4rem; - right: 1.8rem; + width: 2rem; + height: 2rem; + top: 2.4rem; + right: 1.2rem; position: absolute; -} - -.tableHeader { - color: var(--table-title-text-color); - font-family: 'mabry-bold' !important; + color: var(--palette-text-color); } .tableRow { - border-bottom: dashed var(--palette-divider); + border-bottom: dashed var(--palette-palette-divider); +} + +.tableHeader { + border-color: var(--palette-palette-divider) !important; +} + +.tableHeaderText { + color: var(--palette-table-title-text-color); + font-family: 'mabry-bold' !important; } .tableRow:last-child { @@ -365,7 +409,43 @@ .divider { border-width: 0px 0px thin; - border-color: var(--palette-divider); + border-color: var(--palette-palette-divider); border-style: dashed; margin: 0; } + +.deleteInactiveInstances { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem; +} + +.deleteInactiveHeader { + display: flex; + align-items: center; + justify-content: space-between; +} + +.deleteIcon { + width: 1.8rem; + height: 1.8rem; + margin-right: 0.4rem; +} + +.inactiveTotalIcon { + width: 0.6rem; + height: 0.6rem; +} + +.deleteWarning { + width: 1.4rem; + height: 1.4rem; + padding-right: 0.2rem; +} + +.failureIcon { + width: 1.2rem; + height: 1.2rem; + margin-right: 0.4rem; +} diff --git a/src/components/clusters/schedulers/index.tsx b/src/components/clusters/schedulers/index.tsx index b15bc2e..72e4728 100644 --- a/src/components/clusters/schedulers/index.tsx +++ b/src/components/clusters/schedulers/index.tsx @@ -1,5 +1,4 @@ import Paper from '@mui/material/Paper'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; import { Alert, Box, @@ -86,20 +85,26 @@ import RemoveRedEyeIcon from '@mui/icons-material/RemoveRedEye'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; import Card from '../../card'; - -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - secondary: { - main: '#2E8F79', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as Total } from '../../../assets/images/cluster/peer/total.svg'; +import { ReactComponent as Active } from '../../../assets/images/cluster/scheduler/active.svg'; +import { ReactComponent as Inactive } from '../../../assets/images/cluster/scheduler/inactive.svg'; +import { ReactComponent as SelectCard } from '../../../assets/images/cluster/scheduler/card.svg'; +import { ReactComponent as SelectTable } from '../../../assets/images/cluster/scheduler/table.svg'; +import { ReactComponent as ID } from '../../../assets/images/cluster/id.svg'; +import { ReactComponent as Status } from '../../../assets/images/cluster/status.svg'; +import { ReactComponent as IP } from '../../../assets/images/cluster/ip.svg'; +import { ReactComponent as CardFeatures } from '../../../assets/images/cluster/card-features.svg'; +import { ReactComponent as Delete } from '../../../assets/images/cluster/delete.svg'; +import { ReactComponent as IcContent } from '../../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as InactiveTotal } from '../../../assets/images/cluster/inactive-total.svg'; +import { ReactComponent as DeleteWarning } from '../../../assets/images/cluster/delete-warning.svg'; +import { ReactComponent as DeleteInactive } from '../../../assets/images/cluster/delete-inactive.svg'; +import { ReactComponent as DeleteInactiveError } from '../../../assets/images/cluster/delete-inactive-error.svg'; +import { ReactComponent as Failure } from '../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Features } from '../../../assets/images/cluster/features.svg'; +import { ReactComponent as Preheat } from '../../../assets/images/cluster/preheat.svg'; +import { ReactComponent as Schedule } from '../../../assets/images/cluster/scheduler.svg'; +import { ReactComponent as Count } from '../../../assets/images/cluster/scheduler/number.svg'; ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement, Title); Chart.defaults.font.family = 'mabry-light'; @@ -123,6 +128,7 @@ function CircularProgressWithLabel(props: LinearProgressProps & { value: number ); } + const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ [`& .${toggleButtonGroupClasses.grouped}`]: { margin: theme.spacing(0.5), @@ -566,7 +572,7 @@ export default function ShowCluster() { }; return ( - + @@ -612,82 +617,89 @@ export default function ShowCluster() { - - - - - - - Total + + + + + Total + + {isLoading ? ( + + + + ) : ( + + {schedulerCount.length} + + )} + + + + + + number of schedulers + + + + + + + + + + + Active + + {isLoading ? ( + + + + ) : ( + + {numberOfActiveSchedulers} - {isLoading ? ( - - - - ) : ( - - {schedulerCount.length} - - )} - - number of schedulers + )} + + + + + + number of active schedulers{' '} - - - - - - - - - - Active + + + + + + + + + Inactive + + {isLoading ? ( + + + + ) : ( + + {numberOfInactiveSchedulers} - {isLoading ? ( - - - - ) : ( - - {numberOfActiveSchedulers} - - )} - - number of active schedulers - - - - - - - - - - - - - Inactive - - {isLoading ? ( - - - - ) : ( - - {numberOfInactiveSchedulers} - - )} - + )} + + + + + number of inactive schedulers - - - - + + + + @@ -740,7 +752,7 @@ export default function ShowCluster() { /> - + {statusList.map((item, index) => ( - handleMenuItemClick(item)}> + handleMenuItemClick(item)} + > {item.lable} ))} @@ -792,6 +813,7 @@ export default function ShowCluster() { border: `1px solid var(--palette-action-hover)`, flexWrap: 'wrap', ml: '1rem', + backgroundColor: 'var(--palette-background-paper)', })} > - + - + @@ -816,9 +838,9 @@ export default function ShowCluster() { {isLoading ? ( - + - + @@ -831,12 +853,11 @@ export default function ShowCluster() { - + @@ -847,7 +868,7 @@ export default function ShowCluster() { {Array.isArray(allSchedulers) && allSchedulers.map((item: any) => ( - + { @@ -861,7 +882,7 @@ export default function ShowCluster() { aria-expanded={Boolean(schedulerAnchorElement) ? 'true' : undefined} className={styles.moreVertIcon} > - + { navigate(`/clusters/${params.id}/schedulers/${schedulerSelectedRow?.id}`); @@ -905,6 +926,7 @@ export default function ShowCluster() { {schedulerFeatures && schedulerFeatures.length > 0 ? ( { setOpenSchedulerEditFeatures(true); @@ -922,6 +944,7 @@ export default function ShowCluster() { '' )} { openHandleScheduler(schedulerSelectedRow); @@ -929,16 +952,20 @@ export default function ShowCluster() { }} > - + - + Delete - + {isLoading ? ( ) : ( @@ -964,7 +991,7 @@ export default function ShowCluster() { - + - + - + - + {Array.isArray(item.features) && item.features.map((features: string, id: any) => ( @@ -1016,7 +1045,7 @@ export default function ShowCluster() { sx={{ borderRadius: '0.2rem', background: 'var(--palette-background-inactive)', - color: 'var(--table-title-text-color)', + color: 'var(--palette-table-title-text-color)', mr: '0.4rem', border: '0', fontFamily: 'mabry-bold', @@ -1032,7 +1061,7 @@ export default function ShowCluster() { ) : ( - + You don't have scheduler cluster. @@ -1041,270 +1070,274 @@ export default function ShowCluster() { ) : ( - - - - + + + + + + ID + + + + + Hostname + + + + + IP + + + + + Port + + + + + Status + + + + + Features + + + + + Operation + + + + + + {isLoading ? ( + - - ID - + - - Hostname - + + + - - IP - + + + - - Port - + + + - - Status - + + + - - Features - + + + - - Operation - + + + - - - {isLoading ? ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ) : allSchedulers.length === 0 ? ( - - You don't have scheduler cluster. - - ) : ( - <> - {Array.isArray(allSchedulers) && - allSchedulers.map((item: any) => { - return ( - - - {item?.id} - - - - {item?.host_name} - - - - {item?.ip} - - - {item?.port} - - - - - - - {Array.isArray(item.features) && - item.features.map((features: string, id: any) => ( - - ))} - - - - { - setSchedulerAnchorElement(event.currentTarget); - setSchedulerSelectedRow(item); - setSchedulerSelectedID(item.id); - }} - size="small" - aria-controls={Boolean(schedulerAnchorElement) ? item?.host_name : undefined} - aria-haspopup="true" - aria-expanded={Boolean(schedulerAnchorElement) ? 'true' : undefined} - > - - - - - { - navigate(`/clusters/${params.id}/schedulers/${schedulerSelectedRow?.id}`); - setSchedulerAnchorElement(null); + ) : allSchedulers.length === 0 ? ( + + You don't have scheduler cluster. + + ) : ( + <> + {Array.isArray(allSchedulers) && + allSchedulers.map((item: any) => { + return ( + + + {item?.id} + + + + {item?.host_name} + + + + {item?.ip} + + + {item?.port} + + + + + + + {Array.isArray(item.features) && + item.features.map((features: string, id: any) => ( + - - - - - View - - - {schedulerFeatures && schedulerFeatures.length > 0 ? ( - { - setOpenSchedulerEditFeatures(true); - setSchedulerAnchorElement(null); - }} - > - - - - - Edit Features - - - ) : ( - '' - )} + /> + ))} + + + + { + setSchedulerAnchorElement(event.currentTarget); + setSchedulerSelectedRow(item); + setSchedulerSelectedID(item.id); + }} + size="small" + aria-controls={Boolean(schedulerAnchorElement) ? item?.host_name : undefined} + aria-haspopup="true" + aria-expanded={Boolean(schedulerAnchorElement) ? 'true' : undefined} + > + + + + + { + navigate(`/clusters/${params.id}/schedulers/${schedulerSelectedRow?.id}`); + setSchedulerAnchorElement(null); + }} + > + + + + + View + + + {schedulerFeatures && schedulerFeatures.length > 0 ? ( { - openHandleScheduler(schedulerSelectedRow); + setOpenSchedulerEditFeatures(true); setSchedulerAnchorElement(null); }} > - + - - Delete + + Edit Features - - - - - ); - })} - > - )} - - - + ) : ( + '' + )} + { + openHandleScheduler(schedulerSelectedRow); + setSchedulerAnchorElement(null); + }} + > + + + + + Delete + + + + + + + ); + })} + > + )} + + )} {schedulerTotalPages > 1 ? ( - + - - - - + + + + Delete inactive instances @@ -1414,15 +1431,15 @@ export default function ShowCluster() { {deleteInactiveSchedulerSuccessful || '0'} - + number of deleted schedulers - + @@ -1438,11 +1455,7 @@ export default function ShowCluster() { number of delete error - + @@ -1478,11 +1491,7 @@ export default function ShowCluster() { id="inactive-header" > - + Error log @@ -1522,10 +1531,9 @@ export default function ShowCluster() { size="small" onClick={handleReset} sx={{ - '&.MuiButton-root': { - backgroundColor: 'var(--button-color)', - color: '#fff', - }, + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }} > Cancel @@ -1553,11 +1561,7 @@ export default function ShowCluster() { alignItems: 'center', }} > - + - + ID - + Hostname - + IP @@ -1696,21 +1685,21 @@ export default function ShowCluster() { ) : activeStep === 1 ? ( - + WARNING: - + This action CANNOT be undone. @@ -1750,8 +1739,9 @@ export default function ShowCluster() { onClick={handleBack} sx={{ '&.MuiButton-root': { - backgroundColor: activeStep === 0 ? '' : 'var(--button-color)', - color: '#fff', + backgroundColor: activeStep === 0 ? '' : 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }, }} > @@ -1767,9 +1757,9 @@ export default function ShowCluster() { id="save-delete" sx={{ '&.MuiLoadingButton-root': { - backgroundColor: 'var(--delete-button-color)', - color: '#fff', - borderColor: 'var(--save-color)', + backgroundColor: 'var(--palette-delete-button-color)', + color: 'var(--palette-button-text-color)', + borderColor: 'var(--palette-save-color)', }, }} > @@ -1788,8 +1778,9 @@ export default function ShowCluster() { backgroundColor: Array.isArray(schedulerInactive) && schedulerInactive.length === 0 ? '' - : 'var(--button-color)', - color: '#fff', + : 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }, }} > @@ -1810,7 +1801,7 @@ export default function ShowCluster() { > - + Are you sure you want to delet this scheduler? @@ -1847,7 +1838,7 @@ export default function ShowCluster() { > - + Featrues @@ -1873,14 +1864,14 @@ export default function ShowCluster() { - + Schedule - + If schedule feature is enabled, the scheduler can schedule download tasks. @@ -1899,14 +1890,14 @@ export default function ShowCluster() { - + Preheat - + If preheat feature is enabled, the scheduler can execute preheating job. @@ -1940,6 +1931,6 @@ export default function ShowCluster() { - + ); } diff --git a/src/components/clusters/schedulers/show.module.css b/src/components/clusters/schedulers/show.module.css index e27b401..a00d833 100644 --- a/src/components/clusters/schedulers/show.module.css +++ b/src/components/clusters/schedulers/show.module.css @@ -23,6 +23,7 @@ .headerIcon { width: 1.4rem; height: 1.4rem; + color: var(var(--palette-detail-lable-color)); } .hostname { @@ -36,9 +37,10 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--button-color); - color: var(--save-size-color); + background-color: var(--palette-text-color); + color: var(--palette-button-text-color); border-radius: 0.3rem; min-width: 1.6rem; padding: 0.2rem 0.4rem; } + diff --git a/src/components/clusters/schedulers/show.tsx b/src/components/clusters/schedulers/show.tsx index 1c100b7..3625485 100644 --- a/src/components/clusters/schedulers/show.tsx +++ b/src/components/clusters/schedulers/show.tsx @@ -17,6 +17,15 @@ import styles from './show.module.css'; import _ from 'lodash'; import { useParams, Link, useLocation } from 'react-router-dom'; import Card from '../../card'; +import { ReactComponent as ID } from '../../../assets/images/cluster/scheduler/scheduler-id.svg'; +import { ReactComponent as Hostname } from '../../../assets/images/cluster/scheduler/hostname.svg'; +import { ReactComponent as ClusterID } from '../../../assets/images/cluster/scheduler/cluster-id.svg'; +import { ReactComponent as IP } from '../../../assets/images/cluster/scheduler/scheduler-ip.svg'; +import { ReactComponent as Status } from '../../../assets/images/cluster/scheduler/status.svg'; +import { ReactComponent as Features } from '../../../assets/images/cluster/scheduler/features.svg'; +import { ReactComponent as Port } from '../../../assets/images/cluster/scheduler/port.svg'; +import { ReactComponent as CreatedAt } from '../../../assets/images/cluster/scheduler/created-at.svg'; +import { ReactComponent as UpdatedAt } from '../../../assets/images/cluster/scheduler/updated-at.svg'; export default function Schedulers() { const [isLoading, setIsLoading] = useState(false); @@ -29,29 +38,6 @@ export default function Schedulers() { const pathSegments = location.pathname.split('/'); const clusterID = pathSegments[pathSegments.length - 3]; - const schedulerLabel = [ - { - label: 'Port', - name: 'port', - }, - { - label: 'State', - name: 'state', - }, - { - label: 'Features', - name: 'features', - }, - { - label: 'Created At', - name: 'created_at', - }, - { - label: 'Updated At', - name: 'updated_at', - }, - ]; - useEffect(() => { (async function () { try { @@ -93,6 +79,7 @@ export default function Schedulers() { {errorMessageText} + Scheduler } aria-label="breadcrumb" - sx={{ mb: '1rem' }} + sx={{ mb: '2rem', mt: '1rem' }} > clusters @@ -113,13 +100,10 @@ export default function Schedulers() { {scheduler?.host_name || '-'} - - Scheduler - - + ID @@ -130,7 +114,7 @@ export default function Schedulers() { - + Hostname @@ -143,13 +127,13 @@ export default function Schedulers() { - + Cluster ID - + {isLoading ? ( ) : ( @@ -160,7 +144,7 @@ export default function Schedulers() { - + IP @@ -171,7 +155,7 @@ export default function Schedulers() { - + Status @@ -187,9 +171,11 @@ export default function Schedulers() { id="status" sx={{ borderRadius: '0.25rem', - backgroundColor: scheduler?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + backgroundColor: + scheduler?.state === 'active' ? 'var(--palette-text-color)' : 'var(--palette-dark-300Channel)', color: scheduler?.state === 'active' ? '#FFFFFF' : '#FFFFFF', - borderColor: scheduler?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + borderColor: + scheduler?.state === 'active' ? 'var(--palette-text-color)' : 'var(--palette-dark-300Channel)', fontWeight: 'bold', }} /> @@ -202,7 +188,7 @@ export default function Schedulers() { - + Features @@ -219,10 +205,10 @@ export default function Schedulers() { variant="outlined" sx={{ borderRadius: '0.25rem', - background: 'var(--button-color)', + background: 'var(--palette-dark-300Channel)', color: '#FFFFFF', mr: '0.4rem', - borderColor: 'var(--button-color)', + borderColor: 'var(--palette-dark-300Channel)', fontWeight: 'bold', }} /> @@ -234,7 +220,7 @@ export default function Schedulers() { - + Port @@ -245,7 +231,7 @@ export default function Schedulers() { - + Created At @@ -267,7 +253,7 @@ export default function Schedulers() { - + Updated At diff --git a/src/components/clusters/seed-peers/index.module.css b/src/components/clusters/seed-peers/index.module.css index ec2a4cf..fda8b03 100644 --- a/src/components/clusters/seed-peers/index.module.css +++ b/src/components/clusters/seed-peers/index.module.css @@ -1,18 +1,18 @@ -.schedulerInactiveCountWrapper { +.seedPeerInactiveCountWrapper { display: flex; align-items: center; padding: 0.8rem 1rem; } -.schedulerInactiveList { +.seedPeerInactiveList { display: flex; padding: 0.8rem 1rem !important; } -.schedulerInactiveListTitle { +.seedPeerInactiveListTitle { display: flex; padding: 0.8rem 1rem; - background-color: var(--table-title-color) !important; + background-color: var(--palette-table-title-color) !important; } .noInactiveScheduler { @@ -26,7 +26,7 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 2rem; + margin-bottom: 1.5rem; } .logHeaderWrapper { @@ -56,6 +56,7 @@ width: 3rem; height: 3rem; margin-right: '0.5rem'; + color: var(var(--palette-detail-lable-color)); } .headerErrorIcon { @@ -69,27 +70,25 @@ margin-bottom: 0.4rem; } -.menuItem:hover { - background-color: var(--button-color) !important; - color: var(--save-size-color); -} - .menu { - background-image: url(../../../../public/images/menu/cyan-blur.png), url(../../../../public/images/menu/red-blur.png); - background-color: rgba(255, 255, 255, 0.9); + background-image: url(../../../assets/images/menu/cyan-blur.png), url(../../../assets/images/menu/red-blur.png); + background-color: var(--palette-background-menu); background-repeat: no-repeat, no-repeat; padding: 0.2rem; background-size: 50%, 50%; - box-shadow: rgba(145, 158, 171, 0.24) 0px 0px 2px 0px, rgba(145, 158, 171, 0.24) -20px 20px 40px -4px; transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); outline: 0px; background-position: right top, left bottom; - border-radius: 10px; + border-radius: var(--menu-border-radius); overflow: inherit; } +.menuItem { + border-radius: var(--menu-border-radius) !important; +} + .menuItemIcon { - color: var(--button-color); + color: var(--palette-button-color); } .menuText { @@ -105,7 +104,7 @@ display: flex; justify-content: space-between; align-items: center; - padding-bottom: 2rem; + padding-bottom: 1.5rem; } .idIcon { @@ -128,7 +127,7 @@ margin-bottom: 2rem; } -.schedulerInactiveHeaderID { +.seedPeerInactiveHeaderID { width: 20%; white-space: nowrap; overflow: hidden; @@ -137,7 +136,7 @@ align-items: center; } -.schedulerInactiveHeaderHostname { +.seedPeerInactiveHeaderHostname { width: 50%; white-space: nowrap; overflow: hidden; @@ -146,7 +145,12 @@ align-items: center; } -.schedulerInactiveHeaderIP { +.seedPeerInactiveTableHeaderText { + font-family: 'mabry-bold'; + color: var(var(--palette-table-title-text-color)); +} + +.seedPeerInactiveHeaderIP { width: 25%; white-space: nowrap; overflow: hidden; @@ -155,7 +159,7 @@ align-items: center; } -.schedulerInactiveID { +.seedPeerInactiveID { display: flex; align-items: center; width: 20%; @@ -164,7 +168,7 @@ text-overflow: ellipsis; } -.schedulerInactiveHostname { +.seedPeerInactiveHostname { width: 50%; white-space: nowrap; overflow: hidden; @@ -172,29 +176,17 @@ padding-right: 1rem; } -.schedulerInactiveIP { +.seedPeerInactiveIP { width: 25%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.seedPeerHeader { - width: 33.3333%; - padding: 1.2rem; - display: flex; - justify-content: space-between; - position: relative; - z-index: 0; - overflow: hidden; -} - .activeHeader { - width: 33.3333%; padding: 1.2rem; display: flex; justify-content: space-between; - margin-left: 1.6rem; position: relative; z-index: 0; overflow: hidden; @@ -204,6 +196,7 @@ width: 1rem; height: 1rem; margin-right: 0.4rem; + color: var(--palette-text-color); } .hostnameCardText { @@ -292,8 +285,8 @@ align-items: center; justify-content: center; flex-direction: column; - background-color: rgba(var(--no-data-color) / 0.04) !important; - border: dashed 1px rgba(var(--no-data-color) / 0.08); + background-color: rgba(var(--palette-no-data-color) / 0.04) !important; + border: dashed 1px rgba(var(--palette-no-data-color) / 0.08); } .nodataIcon { @@ -306,34 +299,63 @@ font-family: 'mabry-bold'; } +.navigationContainer { + display: grid; + gap: calc(1.5rem); + grid-template-columns: repeat(3, 1fr); + margin-bottom: 1.5rem; +} + +.navigationCount { + display: flex; + align-items: center; +} + +.navigationCountIcon { + background-color: rgba(34 197 94 / 0.18); + color: var(--palette-description-color); + width: 1.5rem; + height: 1.5rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 0.5rem; +} + .navigation { - top: -3rem; + top: -2rem; width: 160px; z-index: -1; height: 160px; - right: -5rem; + right: -6rem; opacity: 0.12; border-radius: 24px; position: absolute; transform: rotate(34deg); - background: linear-gradient(to right, #22c55e 0%, rgba(34 197 94 / 0) 100%); + background: linear-gradient(to right, var(--palette-text-color) 0%, transparent 100%); } .navigationIcon { - width: 2.4rem; - height: 2.4rem; - top: 1.4rem; - right: 1.8rem; + width: 2rem; + height: 2rem; + top: 2.4rem; + right: 1.2rem; position: absolute; + color: var(--palette-text-color); } .tableHeader { - color: var(--table-title-text-color); + border-color: var(--palette-palette-divider) !important; +} + +.tableHeaderText { + color: var(--palette-table-title-text-color); font-family: 'mabry-bold' !important; } .tableRow { - border-bottom: dashed var(--palette-divider); + border-bottom: dashed var(--palette-palette-divider); } .tableRow:last-child { @@ -342,7 +364,43 @@ .divider { border-width: 0px 0px thin; - border-color: var(--palette-divider); + border-color: var(--palette-palette-divider); border-style: dashed; margin: 0; } + +.deleteInactiveInstances { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem; +} + +.deleteInactiveHeader { + display: flex; + align-items: center; + justify-content: space-between; +} + +.deleteIcon { + width: 1.8rem; + height: 1.8rem; + margin-right: 0.4rem; +} + +.inactiveTotalIcon { + width: 0.6rem; + height: 0.6rem; +} + +.deleteWarning { + width: 1.4rem; + height: 1.4rem; + padding-right: 0.2rem; +} + +.failureIcon { + width: 1.2rem; + height: 1.2rem; + margin-right: 0.4rem; +} diff --git a/src/components/clusters/seed-peers/index.tsx b/src/components/clusters/seed-peers/index.tsx index f8d43d3..a5d6c40 100644 --- a/src/components/clusters/seed-peers/index.tsx +++ b/src/components/clusters/seed-peers/index.tsx @@ -1,5 +1,4 @@ import Paper from '@mui/material/Paper'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; import { Alert, Box, @@ -66,20 +65,25 @@ import Card from '../../card'; import RemoveRedEyeIcon from '@mui/icons-material/RemoveRedEye'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ExpandLessIcon from '@mui/icons-material/ExpandLess'; - -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - secondary: { - main: '#2E8F79', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as Total } from '../../../assets/images/cluster/peer/total.svg'; +import { ReactComponent as Active } from '../../../assets/images/cluster/scheduler/active.svg'; +import { ReactComponent as Inactive } from '../../../assets/images/cluster/scheduler/inactive.svg'; +import { ReactComponent as SelectCard } from '../../../assets/images/cluster/scheduler/card.svg'; +import { ReactComponent as SelectTable } from '../../../assets/images/cluster/scheduler/table.svg'; +import { ReactComponent as ID } from '../../../assets/images/cluster/id.svg'; +import { ReactComponent as Status } from '../../../assets/images/cluster/status.svg'; +import { ReactComponent as IP } from '../../../assets/images/cluster/ip.svg'; +import { ReactComponent as Type } from '../../../assets/images/cluster/seed-peer/type.svg'; +import { ReactComponent as Port } from '../../../assets/images/cluster/seed-peer/port.svg'; +import { ReactComponent as DownloadPort } from '../../../assets/images/cluster/seed-peer/download-port.svg'; +import { ReactComponent as Delete } from '../../../assets/images/cluster/delete.svg'; +import { ReactComponent as IcContent } from '../../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as InactiveTotal } from '../../../assets/images/cluster/inactive-total.svg'; +import { ReactComponent as DeleteWarning } from '../../../assets/images/cluster/delete-warning.svg'; +import { ReactComponent as DeleteInactive } from '../../../assets/images/cluster/delete-inactive.svg'; +import { ReactComponent as DeleteInactiveError } from '../../../assets/images/cluster/delete-inactive-error.svg'; +import { ReactComponent as Failure } from '../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Count } from '../../../assets/images/cluster/scheduler/number.svg'; function CircularProgressWithLabel(props: LinearProgressProps & { value: number }) { return ( @@ -505,7 +509,7 @@ export default function ShowCluster() { }; return ( - + @@ -563,26 +566,10 @@ export default function ShowCluster() { position: 'absolute', }} > - - - - + + + + Delete inactive instances @@ -634,11 +621,7 @@ export default function ShowCluster() { number of deleted seed peers - + @@ -654,11 +637,7 @@ export default function ShowCluster() { number of delete error - + @@ -694,11 +673,7 @@ export default function ShowCluster() { id="inactive-header" > - + Error log @@ -738,10 +713,9 @@ export default function ShowCluster() { size="small" onClick={handleReset} sx={{ - '&.MuiButton-root': { - backgroundColor: 'var(--button-color)', - color: '#fff', - }, + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }} > Cancel @@ -755,7 +729,7 @@ export default function ShowCluster() { {activeStep === 0 ? ( - + Seed peers @@ -769,11 +743,7 @@ export default function ShowCluster() { alignItems: 'center', }} > - + - - - + + + ID - - + + Hostname - - + + IP @@ -810,7 +780,7 @@ export default function ShowCluster() { { return index !== seedPeerInactive.length - 1 ? ( - + - + {item.id} @@ -835,17 +801,13 @@ export default function ShowCluster() { {item.host_name} - + {item.ip} @@ -854,13 +816,9 @@ export default function ShowCluster() { ) : ( - + - + {item.id} @@ -868,17 +826,13 @@ export default function ShowCluster() { {item.host_name} - + {item.ip} @@ -897,21 +851,21 @@ export default function ShowCluster() { ) : activeStep === 1 ? ( - + WARNING: - + This action CANNOT be undone. @@ -951,8 +905,9 @@ export default function ShowCluster() { onClick={handleBack} sx={{ '&.MuiButton-root': { - backgroundColor: activeStep === 0 ? '' : 'var(--button-color)', - color: '#fff', + backgroundColor: activeStep === 0 ? '' : 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }, }} > @@ -968,9 +923,9 @@ export default function ShowCluster() { id="save-delete" sx={{ '&.MuiLoadingButton-root': { - backgroundColor: 'var(--delete-button-color)', + backgroundColor: 'var(--palette-delete-button-color)', color: '#fff', - borderColor: 'var(--save-color)', + borderColor: 'var(--palette-save-color)', }, }} > @@ -989,8 +944,9 @@ export default function ShowCluster() { backgroundColor: Array.isArray(seedPeerInactive) && seedPeerInactive.length === 0 ? '' - : 'var(--button-color)', - color: '#fff', + : 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }, }} > @@ -1003,11 +959,11 @@ export default function ShowCluster() { - - + + - + Total @@ -1020,20 +976,24 @@ export default function ShowCluster() { {seedPeerCount?.length || 0} )} - - - number of seed peers - + + + + + + number of seed peers + + - + - + Active @@ -1046,19 +1006,24 @@ export default function ShowCluster() { {numberOfActiveSeedPeers} )} - - number of active seed peers - + + + + + + number of active seed peers + + - + - + Inactive @@ -1071,14 +1036,20 @@ export default function ShowCluster() { {numberOfInactiveSeedPeers} )} - - number of inactive seed peers - + + + + + + + number of inactive seed peers + + - + @@ -1132,7 +1103,7 @@ export default function ShowCluster() { /> - + {statusList.map((item, index) => ( - handleMenuItemClick(item)}> + handleMenuItemClick(item)} + > {item.lable} ))} @@ -1184,6 +1164,7 @@ export default function ShowCluster() { border: `1px solid var(--palette-action-hover)`, flexWrap: 'wrap', ml: '1rem', + backgroundColor: 'var(--palette-background-paper)', })} > - + - + @@ -1208,9 +1189,9 @@ export default function ShowCluster() { {isLoading ? ( - + - + @@ -1223,12 +1204,11 @@ export default function ShowCluster() { - + @@ -1239,7 +1219,7 @@ export default function ShowCluster() { {Array.isArray(allseedPeers) && allseedPeers.map((item: any) => ( - + { setSeedPeerAnchorElement(event.currentTarget); @@ -1253,7 +1233,7 @@ export default function ShowCluster() { aria-expanded={Boolean(seedPeerAnchorElement) ? 'true' : undefined} className={styles.moreVertIcon} > - + { navigate(`/clusters/${params.id}/seed-peers/${seedPeerSelectedRow?.id}`); @@ -1295,6 +1276,7 @@ export default function ShowCluster() { { openHandleSeedPeer(seedPeerSelectedRow); @@ -1302,12 +1284,12 @@ export default function ShowCluster() { }} > - + Delete @@ -1315,7 +1297,7 @@ export default function ShowCluster() { - + {' '} {isLoading ? ( ) : ( @@ -1341,7 +1323,7 @@ export default function ShowCluster() { - + - + - + {item.ip} - + {_.upperFirst(item?.type) || ''} - + {_.upperFirst(item?.port) || ''} - + {_.upperFirst(item?.download_port) || ''} @@ -1405,7 +1385,7 @@ export default function ShowCluster() { ) : ( - + You don't have seed peer cluster. @@ -1416,50 +1396,50 @@ export default function ShowCluster() { - + - - + + ID - - + + Hostname - - + + IP - - + + Port - - + + Download Port - - + + Object Storage Port - - + + Type - - + + Status - - + + Operation @@ -1540,7 +1520,7 @@ export default function ShowCluster() { component={Link} to={`/clusters/${params.id}/seed-peers/${item?.id}`} underline="hover" - sx={{ color: 'var(--description-color)' }} + color="var(--palette-description-color)" > {item?.host_name} @@ -1568,51 +1548,60 @@ export default function ShowCluster() { sx={{ borderRadius: '0.2rem', backgroundColor: - item?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + item?.state === 'active' + ? 'var(--palette-description-color)' + : 'var(--palette-dark-300Channel)', color: item?.state === 'active' ? '#FFFFFF' : '#FFFFFF', borderColor: - item?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + item?.state === 'active' + ? 'var(--palette-description-color)' + : 'var(--palette-dark-300Channel)', fontWeight: 'bold', }} /> { setSeedPeerAnchorElement(event.currentTarget); setSeedPeerSelectedRow(item); setSeedPeerSelectedID(item.id); }} size="small" - id={`operation-${item?.id}`} aria-controls={Boolean(seedPeerAnchorElement) ? item?.host_name : undefined} aria-haspopup="true" aria-expanded={Boolean(seedPeerAnchorElement) ? 'true' : undefined} - sx={{ position: 'relative' }} > - + { navigate(`/clusters/${params.id}/seed-peers/${seedPeerSelectedRow?.id}`); @@ -1627,6 +1616,7 @@ export default function ShowCluster() { { openHandleSeedPeer(seedPeerSelectedRow); @@ -1634,12 +1624,15 @@ export default function ShowCluster() { }} > - + Delete @@ -1665,7 +1658,7 @@ export default function ShowCluster() { > - + Are you sure you want to delet this seed peer? @@ -1690,7 +1683,7 @@ export default function ShowCluster() { {seedPeerTotalPages > 1 ? ( - + > )} - + ); } diff --git a/src/components/clusters/seed-peers/show.module.css b/src/components/clusters/seed-peers/show.module.css index 96dfcc1..7ed79de 100644 --- a/src/components/clusters/seed-peers/show.module.css +++ b/src/components/clusters/seed-peers/show.module.css @@ -35,8 +35,8 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--button-color); - color: var(--save-size-color); + background-color: var(--palette-button-color); + color: var(--palette-button-text-color); border-radius: 0.3rem; min-width: 1.6rem; padding: 0.2rem 0.4rem; diff --git a/src/components/clusters/seed-peers/show.tsx b/src/components/clusters/seed-peers/show.tsx index 099d15a..4caad62 100644 --- a/src/components/clusters/seed-peers/show.tsx +++ b/src/components/clusters/seed-peers/show.tsx @@ -1,4 +1,3 @@ -import Paper from '@mui/material/Paper'; import { Alert, Box, Breadcrumbs, Chip, Link as RouterLink, Skeleton, Snackbar, Typography } from '@mui/material'; import { useEffect, useState } from 'react'; import { getSeedPeer, getSeedPeerResponse } from '../../../lib/api'; @@ -8,6 +7,17 @@ import styles from './show.module.css'; import _ from 'lodash'; import { useParams, Link, useLocation } from 'react-router-dom'; import Card from '../../card'; +import { ReactComponent as ID } from '../../../assets/images/cluster/scheduler/scheduler-id.svg'; +import { ReactComponent as Hostname } from '../../../assets/images/cluster/scheduler/hostname.svg'; +import { ReactComponent as IP } from '../../../assets/images/cluster/scheduler/scheduler-ip.svg'; +import { ReactComponent as ClusterID } from '../../../assets/images/cluster/scheduler/cluster-id.svg'; +import { ReactComponent as Type } from '../../../assets/images/cluster/seed-peer/seed-peer-type.svg'; +import { ReactComponent as Status } from '../../../assets/images/cluster/scheduler/status.svg'; +import { ReactComponent as Port } from '../../../assets/images/cluster/scheduler/port.svg'; +import { ReactComponent as DownloadPort } from '../../../assets/images/cluster/seed-peer/seed-peer-download-port.svg'; +import { ReactComponent as ObjectStoragePort } from '../../../assets/images/cluster/seed-peer/object-storage-port.svg'; +import { ReactComponent as CreatedAt } from '../../../assets/images/cluster/scheduler/created-at.svg'; +import { ReactComponent as UpdatedAt } from '../../../assets/images/cluster/scheduler/updated-at.svg'; export default function SeedPeer() { const [isLoading, setIsLoading] = useState(false); @@ -61,6 +71,7 @@ export default function SeedPeer() { {errorMessageText} + Seed-Peer } aria-label="breadcrumb" - sx={{ mb: '1rem' }} + sx={{ mb: '2rem', mt: '1rem' }} > clusters @@ -81,13 +92,10 @@ export default function SeedPeer() { {seedPeer?.host_name || '-'} - - Seed-Peer - - + ID @@ -98,7 +106,7 @@ export default function SeedPeer() { - + Hostname @@ -109,7 +117,7 @@ export default function SeedPeer() { - + IP @@ -120,7 +128,7 @@ export default function SeedPeer() { - + Cluster ID @@ -137,7 +145,7 @@ export default function SeedPeer() { - + Type @@ -152,7 +160,7 @@ export default function SeedPeer() { - + Status @@ -168,20 +176,38 @@ export default function SeedPeer() { variant="outlined" sx={{ borderRadius: '0.25rem', - backgroundColor: seedPeer?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + backgroundColor: + seedPeer?.state === 'active' + ? 'var(--palette-description-color)' + : 'var(--palette-dark-300Channel)', color: seedPeer?.state === 'active' ? '#FFFFFF' : '#FFFFFF', - borderColor: seedPeer?.state === 'active' ? 'var(--description-color)' : 'var(--button-color)', + borderColor: + seedPeer?.state === 'active' + ? 'var(--palette-description-color)' + : 'var(--palette-dark-300Channel)', fontWeight: 'bold', }} /> ) : ( - '-' + )} - + Port @@ -192,11 +218,7 @@ export default function SeedPeer() { - + Download Port @@ -207,7 +229,7 @@ export default function SeedPeer() { - + Object Storage Port @@ -222,7 +244,7 @@ export default function SeedPeer() { - + Created At @@ -244,7 +266,7 @@ export default function SeedPeer() { - + Updated At diff --git a/src/components/clusters/show.module.css b/src/components/clusters/show.module.css index dfb3879..4b6aa3f 100644 --- a/src/components/clusters/show.module.css +++ b/src/components/clusters/show.module.css @@ -5,231 +5,7 @@ align-items: center; } -.updateClusterIcon { +.tableIcon { width: 1.4rem; height: 1.4rem; - margin-right: 0.4rem; -} - -.deleteClusterIcon { - width: 6rem; - height: 6rem; -} - -.ipContainer { - display: flex; - justify-content: center; - align-items: flex-end; -} - -.ipIcon { - width: 1.4rem; - height: 1.4rem; - margin-right: 0.4rem; -} - -.searchContainer { - display: flex; - justify-content: flex-start; - margin-right: 1rem; - margin-top: 0.6rem; - margin-bottom: 0.6rem; -} - -.openDeleteInactiveDialog { - display: flex; - justify-content: space-between; - align-items: center; - margin: 1rem 0; -} - -.successfulLog { - padding: 0rem !important; -} - -.deleteInactiveWrapper { - padding: 1rem; -} - -.schedulerInactiveCountWrapper { - display: flex; - align-items: center; - padding: 0.8rem 1rem; -} - -.schedulerInactiveList { - display: flex; - padding: 0.8rem 1rem !important; -} - -.schedulerInactiveListTitle { - display: flex; - padding: 0.6rem 1rem; - background-color: #f7f7f7 !important; -} - -.noInactiveScheduler { - padding: 1rem 0; - display: flex; - justify-content: center; - margin: auto; -} - -.schedulerInactiveHeaderID { - width: 20%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: flex; - align-items: center; -} - -.schedulerInactiveHeaderHostname { - width: 50%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: flex; - align-items: center; -} - -.schedulerInactiveHeaderIP { - width: 25%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: flex; - align-items: center; -} - -.schedulerInactiveID { - display: flex; - align-items: center; - width: 20%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.schedulerInactiveHostname { - width: 50%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding-right: 1rem; -} - -.schedulerInactiveIP { - width: 25%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.circularProgressWrapper { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - margin: 1rem auto; -} - -.logHeaderWrapper { - display: flex; - margin-bottom: 2rem; -} - -.headerContainer { - width: 33.333%; - margin-right: 0.6rem; - padding: 0.8rem; - display: flex; - align-items: flex-end; - justify-content: space-between; -} - -.headerContainer:last-child { - margin-right: 0; - position: relative; -} - -.successHeaderContainer { - width: 50%; - margin-right: 1rem; - padding: 1rem; - display: flex; - align-items: flex-end; - justify-content: space-between; -} - -.successHeaderContainer:last-child { - margin-right: 0; -} - -.headerIcon { - width: 3rem; - height: 3rem; - margin-right: '0.5rem'; -} - -.headerErrorIcon { - width: 2.2rem; - height: 2.2rem; -} - -.headerContent { - display: flex; - align-items: center; - margin-bottom: 0.4rem; -} - -.doughnut { - width: 6rem; - height: 6rem; -} - -.hostnameText { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.featuresIconWrapper { - width: 2.4rem; - height: 2.4rem; - border-radius: 50%; - background-color: #fbfbfb; - display: flex; - align-items: center; - justify-content: center; - margin-right: 0.6rem; -} - -.featuresIconContainer { - width: 1.8rem; - height: 1.8rem; - border-radius: 50%; - background-color: #efefef; - display: flex; - align-items: center; - justify-content: center; -} - -.featuresIcon { - width: 1.2rem; - height: 1.2rem; -} - -.menuItem:hover { - background-color: var(--button-color) !important; - color: var(--save-size-color); -} - -.menuItemIcon { - color: var(--button-color); -} - -.menuItem:hover .menuItemIcon { - color: var(--save-size-color); } diff --git a/src/components/clusters/show.tsx b/src/components/clusters/show.tsx index 3909876..47952cf 100644 --- a/src/components/clusters/show.tsx +++ b/src/components/clusters/show.tsx @@ -1,13 +1,4 @@ -import { - Breadcrumbs, - createTheme, - styled, - ThemeProvider, - Typography, - Link as RouterLink, - Snackbar, - Alert, -} from '@mui/material'; +import { Breadcrumbs, styled, Typography, Link as RouterLink, Snackbar, Alert } from '@mui/material'; import { Link, Outlet, useLocation, useParams } from 'react-router-dom'; import * as React from 'react'; import Box from '@mui/material/Box'; @@ -15,17 +6,11 @@ import Tabs from '@mui/material/Tabs'; import Tab, { TabProps } from '@mui/material/Tab'; import { createContext, useEffect, useState } from 'react'; import { getCluster, getClusterResponse } from '../../lib/api'; - -const theme = createTheme({ - palette: { - primary: { - main: '#2e8f79', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as TabCluster } from '../../assets/images/cluster/tab-cluster.svg'; +import { ReactComponent as TabScheduler } from '../../assets/images/cluster/scheduler/tab-scheduler.svg'; +import { ReactComponent as TabSeedPeer } from '../../assets/images/cluster/seed-peer/tab-seed-peer.svg'; +import { ReactComponent as TabPeer } from '../../assets/images/cluster/peer/tab-peer.svg'; +import styles from './show.module.css'; interface MyContextType { cluster: getClusterResponse; @@ -139,60 +124,62 @@ export default function NavTabs() { setValue(newValue); }; - const AntTab = styled((props: StyledTabProps) => )( - ({ theme }) => ({ - textTransform: 'none', + const AntTab = styled((props: StyledTabProps) => )(({ theme }) => ({ + textTransform: 'none', + minWidth: 0, + [theme.breakpoints.up('sm')]: { minWidth: 0, - [theme.breakpoints.up('sm')]: { - minWidth: 0, - }, - fontWeight: theme.typography.fontWeightRegular, - marginRight: theme.spacing(1), - color: 'rgba(0, 0, 0, 0.85)', - fontSize: '0.9rem', - '&:hover': { - color: 'primary', - opacity: 1, - }, - '&.Mui-selected': { - color: '#000', - fontFamily: 'mabry-bold', - }, - }), - ); + }, + minHeight: '3rem', + fontWeight: theme.typography.fontWeightRegular, + color: 'var(--palette-grey-tab)', + padding: '0', + marginRight: '2rem', + fontFamily: 'mabry-bold', + fontSize: '0.9rem', + '&:hover': { + color: 'primary', + opacity: 1, + }, + '&.Mui-selected': { + color: 'var(--palette-text-color)', + fontFamily: 'mabry-bold', + }, + })); const AntTabs = styled(Tabs)({ - borderBottom: '1px solid #e8e8e8', + borderBottom: '1px solid var(--palette-tab-border-color)', '& .MuiTabs-indicator': { - backgroundColor: 'primary', + backgroundColor: 'var(--palette-text-color)', + borderRadius: '1rem', }, }); const tabList = [ { id: 'tab-cluster', - icon: , + icon: , label: 'Cluster', component: Link, to: `/clusters/${params.id}`, }, { id: 'tab-cluster', - icon: , + icon: , label: 'Schedulers', component: Link, to: `/clusters/${params.id}/schedulers`, }, { id: 'tab-cluster', - icon: , + icon: , label: 'Seed Peers', component: Link, to: `/clusters/${params.id}/seed-peers`, }, { id: 'tab-cluster', - icon: , + icon: , label: 'Peers', component: Link, to: `/clusters/${params.id}/peers`, @@ -209,49 +196,65 @@ export default function NavTabs() { return ( - - - - {errorMessageText} - - - - } - aria-label="breadcrumb" - sx={{ mb: '1rem' }} - > - - clusters - - + + + {errorMessageText} + + + + } + aria-label="breadcrumb" + sx={{ mb: '1rem' }} + > + + Cluster + + {location.pathname.split('/')[3] ? ( + {cluster?.name || '-'} - {location.pathname.split('/')[3] && ( - {location.pathname.split('/')[3]} - )} - - - {tabList.map((item) => { - return ; - })} - - - + ) : ( + + {cluster?.name || '-'} + + )} + {location.pathname.split('/')[3] && ( + + {location.pathname.split('/')[3] === 'schedulers' + ? 'Schedulers' + : location.pathname.split('/')[3] === 'seed-peers' + ? 'Seed Peers' + : 'Peers'} + + )} + + + {tabList.map((item) => { + return ; + })} + + ); } diff --git a/src/components/dark-layout.module.css b/src/components/dark-layout.module.css new file mode 100644 index 0000000..1baef12 --- /dev/null +++ b/src/components/dark-layout.module.css @@ -0,0 +1,15 @@ +.github { + width: 2rem; + height: 2rem; + color: var(--palette-secondary-dark); +} + +.icon { + width: 1.2rem; + height: 1.2rem; +} + +.darkModeIcon { + width: 1.2rem; + height: 1.2rem; +} diff --git a/src/components/dark-layout.tsx b/src/components/dark-layout.tsx new file mode 100644 index 0000000..52e6adb --- /dev/null +++ b/src/components/dark-layout.tsx @@ -0,0 +1,191 @@ +import { + Box, + FormControl, + FormControlLabel, + IconButton, + Link, + Paper, + styled, + Switch, + ToggleButton, + ToggleButtonGroup, + toggleButtonGroupClasses, + Typography, + useTheme, +} from '@mui/material'; +import { ReactComponent as Dark } from '../assets/images/menu/dark.svg'; +import { ReactComponent as Light } from '../assets/images/menu/light.svg'; +import { useContext, useState } from 'react'; +import { ColorModeContext } from '../App'; +import styles from './dark-layout.module.css'; + +interface layoutProps { + className?: string; +} + +const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ + [`& .${toggleButtonGroupClasses.grouped}`]: { + margin: theme.spacing(0.5), + border: 0, + borderRadius: theme.shape.borderRadius, + [`&.${toggleButtonGroupClasses.disabled}`]: { + border: 0, + }, + }, + [`& .${toggleButtonGroupClasses.middleButton},& .${toggleButtonGroupClasses.lastButton}`]: { + marginLeft: -1, + }, + width: '100%', +})); + +const VerticalToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ + [`& .${toggleButtonGroupClasses.grouped}`]: { + margin: theme.spacing(0.5), + border: 0, + borderRadius: theme.shape.borderRadius, + [`&.${toggleButtonGroupClasses.disabled}`]: { + border: 0, + }, + }, + [`& .${toggleButtonGroupClasses.middleButton},& .${toggleButtonGroupClasses.lastButton}`]: { + marginTop: -1, + }, +})); + +export const HeaderLayout: React.FC = ({ className }) => { + const theme = useTheme(); + const colorMode = useContext(ColorModeContext); + + return ( + + ({ + display: 'inline-flex', + flexWrap: 'wrap', + bgcolor: 'var(--palette-grey-600Channel)', + borderRadius: '1.2rem', + width: '100%', + })} + > + + + + + Light + + + + + + Dark + + + + + + ); +}; + +export const ShrinkDarkMode: React.FC = ({ className }) => { + const theme = useTheme(); + const colorMode = useContext(ColorModeContext); + + return ( + + ({ + display: 'inline-flex', + flexWrap: 'wrap', + backgroundColor: 'var(--palette-grey-600Channel)', + borderRadius: '1.2rem', + })} + > + + + + + + + + + + + ); +}; diff --git a/src/components/developer/tokens/edit.module.css b/src/components/developer/tokens/edit.module.css index c669bb1..9b1c3af 100644 --- a/src/components/developer/tokens/edit.module.css +++ b/src/components/developer/tokens/edit.module.css @@ -1,6 +1,13 @@ .header { - display: inline-flex; - align-items: center; - padding: 1rem; - margin-bottom: 1rem; - } \ No newline at end of file + display: inline-flex; + align-items: center; + padding: 1rem; + margin-bottom: 1rem; +} + +.tokenIcon { + width: 2.6rem; + height: 2.6rem; + margin-right: 1rem; + color: var(--palette-button-color); +} diff --git a/src/components/developer/tokens/edit.tsx b/src/components/developer/tokens/edit.tsx index 9d7bea0..517b783 100644 --- a/src/components/developer/tokens/edit.tsx +++ b/src/components/developer/tokens/edit.tsx @@ -9,37 +9,26 @@ import { SelectChangeEvent, FormControlLabel, Checkbox, - createTheme, - ThemeProvider, Snackbar, Alert, Tooltip, InputLabel, FormGroup, FormHelperText, - Paper, Skeleton, + Breadcrumbs, + Link as RouterLink, } from '@mui/material'; import { useEffect, useState } from 'react'; import { formatDate, getExpiredTime } from '../../../lib/utils'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Link, useNavigate, useParams } from 'react-router-dom'; import { getToken, updateTokens } from '../../../lib/api'; import HelpIcon from '@mui/icons-material/Help'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { CancelLoadingButton, SavelLoadingButton } from '../../loading-button'; import Card from '../../card'; import styles from './edit.module.css'; - -const theme = createTheme({ - palette: { - secondary: { - main: '#1c293a', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as Token } from '../../../assets/images/tokens/key.svg'; export default function UpdateTokens() { const [successMessage, setSuccessMessage] = useState(false); @@ -74,8 +63,12 @@ export default function UpdateTokens() { endAdornment: ( ), @@ -214,187 +207,211 @@ export default function UpdateTokens() { {errorMessageText} - - Update personal access token - - - - - - - ID: + Update personal access token + + } + aria-label="breadcrumb" + sx={{ m: '1rem 0' }} + > + Developer + + Personal access tokens + + {tokens.name || ''} + + + + + + + + ID: + + {isLoading ? ( + + ) : ( + + {tokens.id} - {isLoading ? ( - - ) : ( - - {tokens.id} - - )} - - - - Name: - - {isLoading ? ( - - ) : ( - - {tokens.name} - - )} - + )} - - - - - - Information + + + Name: + + {isLoading ? ( + + ) : ( + + {tokens.name} - - - - - {formList.map((item) => ( - - ))} - - - Expiration - - - - - - - - Expiration - - - - - 7 days - 30 days - 60 days - 90 days - 10 years - - {expiredTimeError && Please select an option.} - - - The token expires on {formatDate(expiredTime) || ''}. - - - - - - Select scopes - - - - - - - - - - { - setPreheat(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of preheating, it's used for preheating of harbor. - - - - - { - setJob(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of job. If you need to call preheat job through open API, it is recommended to use - preheat job. - - - - - { - setCluster(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of cluster. - - - - - - - { - navigate('/developer/personal-access-tokens'); + )} + + + + + + + + Information + + + - } id="save" text="Save" /> + + + {formList.map((item) => ( + + ))} + + + Expiration + + + + + + + + Expiration + + + + + 7 days + 30 days + 60 days + 90 days + 10 years + + {expiredTimeError && Please select an option.} + + + The token expires on {formatDate(expiredTime) || ''}. + - - + + + Select scopes + + + + + + + + + + { + setPreheat(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of preheating, it's used for preheating of harbor. + + + + + { + setJob(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of job. If you need to call preheat job through open API, it is recommended to use + preheat job. + + + + + { + setCluster(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of cluster. + + + + + + + { + navigate('/developer/personal-access-tokens'); + }} + /> + } id="save" text="Save" /> + + + ); } diff --git a/src/components/developer/tokens/index.module.css b/src/components/developer/tokens/index.module.css index 56f9234..b2c39a2 100644 --- a/src/components/developer/tokens/index.module.css +++ b/src/components/developer/tokens/index.module.css @@ -5,8 +5,8 @@ align-items: center; justify-content: center; flex-direction: column; - background-color: rgba(var(--no-data-color) / 0.04) !important; - border: dashed 1px rgba(var(--no-data-color) / 0.08); + background-color: rgba(var(--palette-no-data-color) / 0.04) !important; + border: dashed 1px rgba(var(--palette-no-data-color) / 0.08); } .nodataIcon { @@ -23,6 +23,16 @@ display: flex; align-items: center; padding: 0.8rem; - background-color: var(--menu-background-color) !important; + background-color: var(--palette-grey-background-color) !important; margin-bottom: 1rem; } + +.copyIcon { + width: 1.4rem; + height: 1.4rem; +} + +.deleteIcon { + width: 6rem; + height: 6rem; +} diff --git a/src/components/developer/tokens/index.tsx b/src/components/developer/tokens/index.tsx index d384a50..0f7335c 100644 --- a/src/components/developer/tokens/index.tsx +++ b/src/components/developer/tokens/index.tsx @@ -25,6 +25,10 @@ import { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../../lib/constants'; import { CancelLoadingButton, DeleteLoadingButton } from '../../loading-button'; import Card from '../../card'; import styles from './index.module.css'; +import { ReactComponent as Done } from '../../../assets/images/tokens/done.svg'; +import { ReactComponent as Copy } from '../../../assets/images/tokens/copy.svg'; +import { ReactComponent as IcContent } from '../../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as Delete } from '../../../assets/images/cluster/delete.svg'; export default function PersonalAccessTokens() { const [successMessage, setSuccessMessage] = useState(false); @@ -165,27 +169,17 @@ export default function PersonalAccessTokens() { {errorMessageText} - - } - aria-label="breadcrumb" - sx={{ mb: '1rem' }} - > - developer - personal access tokens - - - Personal access tokens + + + Personal access tokens + { @@ -196,7 +190,19 @@ export default function PersonalAccessTokens() { Add Personal access tokens - + + } + aria-label="breadcrumb" + sx={{ mb: '1rem' }} + > + Developer + Personal access tokens + + Tokens you have generated that can be used to access the Dragonfly API. {showCopyColumn ? ( @@ -226,15 +232,10 @@ export default function PersonalAccessTokens() { disableTouchListener title="copied!" > - + ) : ( - + )} @@ -261,8 +262,8 @@ export default function PersonalAccessTokens() { ) : allTokens.length === 0 ? ( - - + + You don't have any tokens. @@ -282,7 +283,7 @@ export default function PersonalAccessTokens() { component={Link} to={`/developer/personal-access-tokens/${item?.id}`} underline="hover" - sx={{ color: 'var(--description-color)' }} + sx={{ color: 'var(--palette-description-color)' }} > {item.name} @@ -304,10 +305,9 @@ export default function PersonalAccessTokens() { size="small" id={`delete-token-${item?.id}`} sx={{ - '&.MuiButton-root': { - backgroundColor: 'var(--button-color)', - color: '#fff', - }, + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }} variant="contained" onClick={() => { @@ -321,7 +321,7 @@ export default function PersonalAccessTokens() { @@ -338,7 +338,7 @@ export default function PersonalAccessTokens() { component={Link} to={`/developer/personal-access-tokens/${item?.id}`} underline="hover" - sx={{ color: 'var(--description-color)' }} + sx={{ color: 'var(--palette-description-color)' }} > {item.name} @@ -360,10 +360,9 @@ export default function PersonalAccessTokens() { size="small" id={`delete-token-${item?.id}`} sx={{ - '&.MuiButton-root': { - backgroundColor: 'var(--button-color)', - color: '#fff', - }, + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, }} variant="contained" onClick={() => { @@ -389,12 +388,7 @@ export default function PersonalAccessTokens() { setTokensPage(newPage); navigate(`/developer/personal-access-tokens${newPage > 1 ? `?page=${newPage}` : ''}`); }} - sx={{ - '& .Mui-selected': { - backgroundColor: 'var(--button-color)!important', - color: '#FFF', - }, - }} + color="primary" size="small" /> @@ -411,7 +405,7 @@ export default function PersonalAccessTokens() { > - + Are you sure you want to delete this token? diff --git a/src/components/developer/tokens/new.tsx b/src/components/developer/tokens/new.tsx index 7a91389..38746d0 100644 --- a/src/components/developer/tokens/new.tsx +++ b/src/components/developer/tokens/new.tsx @@ -16,28 +16,18 @@ import { Tooltip, FormGroup, InputLabel, + Breadcrumbs, + Link as RouterLink, } from '@mui/material'; import { useContext, useEffect, useState } from 'react'; import { formatDate, getExpiredTime } from '../../../lib/utils'; -import { useNavigate } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { createTokens } from '../../../lib/api'; import HelpIcon from '@mui/icons-material/Help'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { MyContext } from '../../menu'; import { CancelLoadingButton, SavelLoadingButton } from '../../loading-button'; -const theme = createTheme({ - palette: { - secondary: { - contrastText: '#fff', - main: '#1c293a', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); - export default function CreateTokens() { const [successMessage, setSuccessMessage] = useState(false); const [errorMessage, setErrorMessage] = useState(false); @@ -68,8 +58,12 @@ export default function CreateTokens() { endAdornment: ( ), @@ -102,8 +96,12 @@ export default function CreateTokens() { endAdornment: ( ), @@ -220,166 +218,192 @@ export default function CreateTokens() { {errorMessageText} - - Create personal access token - - - - - - Information - - - - - - {formList.map((item) => { - return item?.formProps?.name === 'bio' ? ( - - ) : ( - - ); - })} - - - Expiration - - - - - - - - Expiration - - - - 7 days - 30 days - 60 days - 90 days - 10 years - - - The token expires on {formatDate(expiredTime) || ''}. - - - - - - Select scopes - - - - - - - - - - { - setPreheat(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of preheating, it's used for preheating of harbor. - - - - - { - setJob(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of job. If you need to call preheat job through open API, it is recommended to use - preheat job. - - - - - { - setCluster(event.target.checked); - }} - sx={{ color: 'var(--button-color)!important' }} - /> - } - /> - - - Full control of cluster. - - - - - - - { - navigate('/developer/personal-access-tokens'); + Create personal access token + + } + aria-label="breadcrumb" + sx={{ m: '1rem 0' }} + > + Developer + + Personal access tokens + + New token + + + + + + + Information + + + - } id="save" text="Save" /> + + + {formList.map((item) => { + return item?.formProps?.name === 'bio' ? ( + + ) : ( + + ); + })} + + + Expiration + + + + + + + + Expiration + + + + 7 days + 30 days + 60 days + 90 days + 10 years + + + The token expires on {formatDate(expiredTime) || ''}. + - - + + + Select scopes + + + + + + + + + + { + setPreheat(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of preheating, it's used for preheating of harbor. + + + + + { + setJob(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of job. If you need to call preheat job through open API, it is recommended to use + preheat job. + + + + + { + setCluster(event.target.checked); + }} + sx={{ color: 'var(--palette-button-color)!important' }} + /> + } + /> + + + Full control of cluster. + + + + + + + { + navigate('/developer/personal-access-tokens'); + }} + /> + } id="save" text="Save" /> + + + ); } diff --git a/src/components/job/preheats/index.module.css b/src/components/job/preheats/index.module.css index 40e76fb..2ea682c 100644 --- a/src/components/job/preheats/index.module.css +++ b/src/components/job/preheats/index.module.css @@ -16,6 +16,18 @@ font-family: 'mabry-bold'; } +.statusIcon { + width: 1.3rem; + height: 1.3rem; + margin: 0.1rem; +} + +.pendingIcon { + width: 1.3rem; + height: 1.3rem; + color: #dbab0a; +} + .description { width: 90%; overflow: hidden; @@ -37,3 +49,22 @@ justify-content: space-between; margin-left: 0.6rem; } + +.detailIcon { + width: 2rem; + height: 2rem; + color: var(--palette-button-color); +} + +.menu { + background-color: var(--palette-background-menu); + background-image: url(../../../assets/images/menu/cyan-blur.png), url(../../../assets/images/menu/red-blur.png); + background-repeat: no-repeat, no-repeat; + padding: 0.2rem; + background-size: 50%, 50%; + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); + outline: 0px; + background-position: right top, left bottom; + border-radius: var(--menu-border-radius); + overflow: inherit; +} diff --git a/src/components/job/preheats/index.tsx b/src/components/job/preheats/index.tsx index 44e6e82..04762c4 100644 --- a/src/components/job/preheats/index.tsx +++ b/src/components/job/preheats/index.tsx @@ -27,6 +27,11 @@ import { DEFAULT_PAGE_SIZE } from '../../../lib/constants'; import { getBJTDatetime, useQuery } from '../../../lib/utils'; import styles from './index.module.css'; import Card from '../../card'; +import { ReactComponent as IcContent } from '../../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as Success } from '../../../assets/images/job/preheat/success.svg'; +import { ReactComponent as Failure } from '../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Pending } from '../../../assets/images/job/preheat/pending.svg'; +import { ReactComponent as Detail } from '../../../assets/images/job/preheat/detail.svg'; export default function Preheats() { const [errorMessage, setErrorMessage] = useState(false); @@ -43,17 +48,6 @@ export default function Preheats() { const query = useQuery(); const page = query.get('page') ? parseInt(query.get('page') as string, 10) || 1 : 1; - const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, - }); - useEffect(() => { (async function () { try { @@ -70,7 +64,7 @@ export default function Preheats() { setPreheatTotalPages(jobs.total_page || 1); const states = jobs.data.filter( - (obj) => obj.result.state !== 'SUCCESS' && obj.result.state !== 'FAILURE', + (obj) => obj?.result?.state !== 'SUCCESS' && obj?.result?.state !== 'FAILURE', ).length; states === 0 ? setShouldPoll(false) : setShouldPoll(true); @@ -101,7 +95,7 @@ export default function Preheats() { setPreheatTotalPages(jobs.total_page || 1); const states = jobs.data.filter( - (obj) => obj.result.state !== 'SUCCESS' && obj.result.state !== 'FAILURE', + (obj) => obj?.result?.state !== 'SUCCESS' && obj?.result?.state !== 'FAILURE', ).length; states === 0 ? setShouldPoll(false) : setShouldPoll(true); @@ -144,7 +138,7 @@ export default function Preheats() { }; return ( - + - - } - aria-label="breadcrumb" - sx={{ mb: '1rem' }} - > - jobs - preheats - - + Preheats } variant="contained" @@ -186,11 +168,23 @@ export default function Preheats() { add preheat + + } + aria-label="breadcrumb" + sx={{ mb: '1.5rem' }} + > + Job + Preheat + ) : allPreheats.length === 0 ? ( - + You don't have any preheat tasks. @@ -261,27 +255,12 @@ export default function Preheats() { - {item.result.state === 'SUCCESS' ? ( - - ) : item.result.state === 'FAILURE' ? ( - + {item?.result?.state === 'SUCCESS' ? ( + + ) : item?.result?.state === 'FAILURE' ? ( + ) : ( - + )} @@ -313,20 +292,16 @@ export default function Preheats() { id={`preheat-${item?.id}`} to={`/jobs/preheats/${item?.id}`} underline="hover" - sx={{ color: 'var(--description-color)' }} + sx={{ color: 'var(--palette-description-color)' }} > - + @@ -334,27 +309,12 @@ export default function Preheats() { ) : ( - {item.result.state === 'SUCCESS' ? ( - - ) : item.result.state === 'FAILURE' ? ( - + {item?.result?.state === 'SUCCESS' ? ( + + ) : item?.result?.state === 'FAILURE' ? ( + ) : ( - + )} @@ -386,13 +346,9 @@ export default function Preheats() { id={`preheat-${item?.id}`} to={`/jobs/preheats/${item?.id}`} underline="hover" - sx={{ color: 'var(--description-color)' }} + sx={{ color: 'var(--palette-description-color)' }} > - + @@ -402,7 +358,7 @@ export default function Preheats() { )} {preheatTotalPages > 1 ? ( - + > )} - + ); } diff --git a/src/components/job/preheats/new.module.css b/src/components/job/preheats/new.module.css index 7abfe5a..11fb65c 100644 --- a/src/components/job/preheats/new.module.css +++ b/src/components/job/preheats/new.module.css @@ -27,3 +27,18 @@ .argsWrapper:nth-child(n + 3) { width: 100%; } + +.argsWrapper { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: calc(1.5rem); + padding: 1.5rem; +} + +.headersWrapper { + padding: 1rem; + width: 37rem; + margin-top: 1rem; + border-radius: 0.25rem !important; + background-color: var(--palette-background-paper) !important; +} diff --git a/src/components/job/preheats/new.tsx b/src/components/job/preheats/new.tsx index e8ad85b..6c1b85f 100644 --- a/src/components/job/preheats/new.tsx +++ b/src/components/job/preheats/new.tsx @@ -13,8 +13,7 @@ import { MenuItem, Checkbox, ListItemText, - createTheme, - ThemeProvider, + Link as RouterLink, FormHelperText, Grid, Chip, @@ -23,17 +22,19 @@ import { Alert, Paper, SelectChangeEvent, + Breadcrumbs, } from '@mui/material'; import { useEffect, useState } from 'react'; import HelpIcon from '@mui/icons-material/Help'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import ClearIcon from '@mui/icons-material/Clear'; -import { useNavigate } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; import { createJob, getClusters } from '../../../lib/api'; import { MAX_PAGE_SIZE } from '../../../lib/constants'; import styles from './new.module.css'; import AddIcon from '@mui/icons-material/Add'; import { CancelLoadingButton, SavelLoadingButton } from '../../loading-button'; +import Card from '../../card'; export default function NewPreheat() { const [successMessage, setSuccessMessage] = useState(false); @@ -55,17 +56,6 @@ export default function NewPreheat() { const navigate = useNavigate(); - const theme = createTheme({ - palette: { - secondary: { - main: '#1c293a', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, - }); - useEffect(() => { (async function () { try { @@ -96,8 +86,12 @@ export default function NewPreheat() { endAdornment: ( ), @@ -137,8 +131,12 @@ export default function NewPreheat() { placement="top" > ), @@ -169,8 +167,12 @@ export default function NewPreheat() { endAdornment: ( ), @@ -261,7 +263,7 @@ export default function NewPreheat() { }; const headersValueValidate = (value: any) => { - const regex = /^.{1,1000}$/; + const regex = /^.{1,10000}$/; return regex.test(value); }; @@ -374,7 +376,7 @@ export default function NewPreheat() { }; return ( - + Create Preheat + + } + aria-label="breadcrumb" + sx={{ mt: '1rem' }} + > + Job + + Preheat + + + New preheat + + @@ -408,8 +427,12 @@ export default function NewPreheat() { @@ -431,19 +454,16 @@ export default function NewPreheat() { - + Clusters -1} /> @@ -485,13 +505,17 @@ export default function NewPreheat() { - + Scope {argsForm.map((item) => { - return ( - <> - {item.id === 'filteredQueryParams' ? ( - ( - - {params.InputProps.endAdornment} - - - - > - ), - }} - color="success" - {...item.formProps} - /> - )} - /> - ) : item.formProps.id === 'tag' ? ( - - ) : ( - - )} - > + return item.id === 'filteredQueryParams' ? ( + + ( + + {params.InputProps.endAdornment} + + + + > + ), + }} + color="success" + {...item.formProps} + /> + )} + /> + + ) : item.formProps.id === 'tag' ? ( + + ) : ( + + + ); })} {headers.length > 0 ? ( - + Headers @@ -618,7 +647,7 @@ export default function NewPreheat() { multiline maxRows={3} error={!headersValueValidate(item.value)} - helperText={!headersValueValidate(item.value) && 'Fill in the characters, the length is 1-1000.'} + helperText={!headersValueValidate(item.value) && 'Fill in the characters, the length is 1-10000.'} className={styles.headersValueInput} value={item.value} onChange={(event) => { @@ -639,15 +668,15 @@ export default function NewPreheat() { setheaders(newheaders); }} > - + ))} - + ); } diff --git a/src/components/job/preheats/show.module.css b/src/components/job/preheats/show.module.css index 97d5b44..cab8ef7 100644 --- a/src/components/job/preheats/show.module.css +++ b/src/components/job/preheats/show.module.css @@ -3,9 +3,16 @@ } .statusIcon { - width: 1.3rem !important; - height: 1.3rem !important; + margin-right: 0.5rem; + width: 1rem !important; + height: 1rem !important; +} + +.pendingIcon { + width: 1.3rem; + height: 1.3rem; margin-right: 0.4rem; + color: var(--palette-button-text-color); } .informationContainer { @@ -23,11 +30,12 @@ .informationTitleIcon { width: 1.4rem !important; height: 1.4rem !important; + color: var(--palette-detail-lable-color); } .informationTitleText { margin-left: 1rem !important; - color: #515151; + color: var(--palette-detail-lable-color); font-family: 'mabry-bold' !important; } @@ -84,8 +92,8 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--button-color); - color: var(--save-size-color); + background-color: var(--palette-button-color); + color: var(--palette-button-text-color); border-radius: 0.3rem; min-width: 1.6rem; margin-right: 0.5rem; @@ -95,8 +103,8 @@ .scopeContent { display: inline-flex; align-items: center; - background-color: var(--button-color); - color: var(--save-size-color); + background-color: var(--palette-button-color); + color: var(--palette-scopes-icon-color); border-radius: 0.3rem; min-width: 1.6rem; margin-right: 0.5rem; @@ -105,8 +113,8 @@ .tagContent { display: inline-flex; - background-color: var(--description-color); - color: var(--save-size-color); + background-color: var(--palette-description-color); + color: var(--palette-scopes-icon-color); border-radius: 0.3rem; min-width: 1.6rem; padding: 0.2rem 0.4rem; @@ -119,3 +127,8 @@ white-space: nowrap; font-style: italic; } + +.errorIcon { + width: 1.3rem; + height: 1.3rem; +} diff --git a/src/components/job/preheats/show.tsx b/src/components/job/preheats/show.tsx index ada9098..ac03223 100644 --- a/src/components/job/preheats/show.tsx +++ b/src/components/job/preheats/show.tsx @@ -2,7 +2,6 @@ import { Box, Chip, Divider, - Paper, Typography, Breadcrumbs, Link as RouterLink, @@ -15,8 +14,6 @@ import { AccordionDetails, AccordionSummary, Accordion, - ThemeProvider, - createTheme, styled, tooltipClasses, TooltipProps, @@ -29,17 +26,19 @@ import { getBJTDatetime } from '../../../lib/utils'; import styles from './show.module.css'; import ArrowForwardIosSharpIcon from '@mui/icons-material/ArrowForwardIosSharp'; import Card from '../../card'; - -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as PreheatID } from '../../../assets/images/job/preheat/id.svg'; +import { ReactComponent as Description } from '../../../assets/images/job/preheat/description.svg'; +import { ReactComponent as Status } from '../../../assets/images/job/preheat/status.svg'; +import { ReactComponent as URL } from '../../../assets/images/job/preheat/url.svg'; +import { ReactComponent as Scope } from '../../../assets/images/job/preheat/scope.svg'; +import { ReactComponent as Tag } from '../../../assets/images/job/preheat/tag.svg'; +import { ReactComponent as Headers } from '../../../assets/images/job/preheat/headers.svg'; +import { ReactComponent as SchedulerClustersID } from '../../../assets/images/job/preheat/id.svg'; +import { ReactComponent as CreatedAt } from '../../../assets/images/job/preheat/created-at.svg'; +import { ReactComponent as Failure } from '../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Pending } from '../../../assets/images/job/preheat/pending.svg'; +import { ReactComponent as ErrorLog } from '../../../assets/images/job/preheat/error-log.svg'; +import { ReactComponent as TagScope } from '../../../assets/images/job/preheat/tag-scope.svg'; const CustomWidthTooltip = styled(({ className, ...props }: TooltipProps) => ( @@ -132,7 +131,7 @@ export default function ShowPreheat() { const scope = preheat?.args?.scope && scopeList.find((item) => item.name === preheat?.args?.scope); return ( - + + + Preheat + } aria-label="breadcrumb" - sx={{ mb: '1rem' }} + sx={{ mb: '1.5rem', mt: '1rem' }} > - jobs - - preheats + Job + + Preheat - {preheat?.id || '-'} + {preheat?.id || '-'} - - Preheat - - + - + - + > ) : ( - + )} - + > @@ -290,7 +279,7 @@ export default function ShowPreheat() { - + - + ) : scope ? ( - + {scope.label || '-'} @@ -341,7 +330,7 @@ export default function ShowPreheat() { - + - + - + - + - - + + Preheat @@ -531,6 +516,6 @@ export default function ShowPreheat() { - + ); } diff --git a/src/components/job/task/clear/index.module.css b/src/components/job/task/clear/index.module.css index ba05b97..397aa9a 100644 --- a/src/components/job/task/clear/index.module.css +++ b/src/components/job/task/clear/index.module.css @@ -23,7 +23,7 @@ } .hostnameTitle { - color: #515155; + color: var(--palette-table-title-text-color); } .filterInput { @@ -54,5 +54,37 @@ } .circularProgress { + width: 2.2rem; + height: 2.2rem; + display: flex; + align-items: center; + justify-content: flex-start; +} + +.schedulerClusterIcon { + width: 0.6rem; + height: 0.6rem; +} + +.noSearch { + width: 4rem; + height: 4rem; + margin-bottom: 3rem; +} + +.noTask { + width: 30rem; + height: 30rem; +} + +.deleteIcon { + width: 1.8rem; + height: 1.8rem; margin-right: 0.4rem; } + +.deleteWarningIcon { + width: 1.4rem; + height: 1.4rem; + padding-right: 0.2rem; +} diff --git a/src/components/job/task/clear/index.tsx b/src/components/job/task/clear/index.tsx index 83fbc58..7a5179a 100644 --- a/src/components/job/task/clear/index.tsx +++ b/src/components/job/task/clear/index.tsx @@ -11,8 +11,6 @@ import { Alert, Tooltip, Divider, - createTheme, - ThemeProvider, TextField, styled, Autocomplete, @@ -20,6 +18,7 @@ import { ToggleButton, toggleButtonGroupClasses, Pagination, + useTheme, } from '@mui/material'; import styles from './index.module.css'; import { useEffect, useState } from 'react'; @@ -39,10 +38,16 @@ import SearchCircularProgress from '../../../circular-progress'; import AssignmentOutlinedIcon from '@mui/icons-material/AssignmentOutlined'; import LinkOutlinedIcon from '@mui/icons-material/LinkOutlined'; import Card from '../../../card'; +import { ReactComponent as SchedulerCluster } from '../../../../assets/images/job/task/scheduler-cluster.svg'; +import { ReactComponent as NoSearch } from '../../../../assets/images/job/task/no-search.svg'; +import { ReactComponent as NoTask } from '../../../../assets/images/job/task/no-task.svg'; +import { ReactComponent as DarkNoTask } from '../../../../assets/images/job/task/dark-no-task.svg'; +import { ReactComponent as Delete } from '../../../../assets/images/cluster/delete.svg'; +import { ReactComponent as DeleteWarning } from '../../../../assets/images/cluster/delete-warning.svg'; const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ [`& .${toggleButtonGroupClasses.grouped}`]: { - margin: theme.spacing(0.5), + margin: theme.spacing(0.7), border: 0, borderRadius: theme.shape.borderRadius, [`&.${toggleButtonGroupClasses.disabled}`]: { @@ -51,28 +56,16 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ }, [`& .${toggleButtonGroupClasses.middleButton},& .${toggleButtonGroupClasses.lastButton}`]: { marginLeft: -1, - borderLeft: '1px solid transparent', + border: 0, }, })); -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - success: { - main: '#2e8f79', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); - export default function Clear() { const [errorMessage, setErrorMessage] = useState(false); const [errorMessageText, setErrorMessageText] = useState(''); const [isLoading, setIsLoading] = useState(false); + const [searchTaskISLodaing, setSearchTaskISLodaing] = useState(false); + const [searchIconISLodaing, setSearchIconISLodaing] = useState(false); const [openDeleteTask, setOpenDeleteTask] = useState(false); const [deleteLoadingButton, setDeleteLoadingButton] = useState(false); const [searchTask, setSearchTask] = useState(''); @@ -95,6 +88,7 @@ export default function Clear() { const { url, tag, application, filtered_query_params } = searchData; const navigate = useNavigate(); + const theme = useTheme(); useEffect(() => { const fetchJob = async () => { @@ -102,9 +96,12 @@ export default function Clear() { if (searchID) { const job = await getTaskJob(searchID); - if (job.type === 'get_task') { + if (job?.type === 'get_task') { if ((job?.result?.state && job?.result?.state === 'SUCCESS') || job?.result?.state === 'FAILURE') { setIsLoading(false); + setSearchIconISLodaing(false); + setSearchTaskISLodaing(false); + setTask(job); } else { setShouldPoll(true); @@ -116,6 +113,8 @@ export default function Clear() { setErrorMessage(true); setErrorMessageText(error.message); setIsLoading(false); + setSearchIconISLodaing(false); + setSearchTaskISLodaing(false); } } }; @@ -133,6 +132,8 @@ export default function Clear() { setTask(job); setShouldPoll(false); setIsLoading(false); + setSearchIconISLodaing(false); + setSearchTaskISLodaing(false); } } catch (error) { if (error instanceof Error) { @@ -140,6 +141,8 @@ export default function Clear() { setErrorMessageText(error.message); setShouldPoll(false); setIsLoading(false); + setSearchIconISLodaing(false); + setSearchTaskISLodaing(false); } } }; @@ -165,7 +168,15 @@ export default function Clear() { helperText: urlError ? 'Fill in the characters, the length is 0-1000.' : '', error: urlError, InputProps: { - startAdornment: , + startAdornment: searchIconISLodaing ? ( + + + + ) : ( + + + + ), endAdornment: searchTask ? ( @@ -208,8 +219,12 @@ export default function Clear() { placement="top" > ), @@ -240,8 +255,12 @@ export default function Clear() { InputProps: ( ), @@ -321,10 +340,14 @@ export default function Clear() { helperText: taskIDError ? 'Fill in the characters, the length is 0-1000.' : '', error: taskIDError, InputProps: { - startAdornment: isLoading ? ( - + startAdornment: searchTaskISLodaing ? ( + + + ) : ( - + + + ), endAdornment: searchTask ? ( { + setIsLoading(true); + setSearchTaskISLodaing(true); + setSearchIconISLodaing(false); try { event.preventDefault(); const data = new FormData(event.currentTarget); @@ -443,7 +469,6 @@ export default function Clear() { taskIDList.syncError = !taskIDList.validate(taskIDValue as string); if (searchTask !== '' && !taskIDList.syncError) { - setIsLoading(true); const data = { args: { task_id: searchTask, @@ -457,19 +482,23 @@ export default function Clear() { navigate('/jobs/task/clear'); setTask(null); setIsLoading(false); + setSearchTaskISLodaing(false); } } catch (error) { if (error instanceof Error) { setErrorMessage(true); setErrorMessageText(error.message); setIsLoading(false); + setSearchTaskISLodaing(false); } } }; const handleSearchByURL = async (event: any) => { + setSearchTaskISLodaing(false); setLoadingButton(true); setIsLoading(true); + setSearchIconISLodaing(true); event.preventDefault(); const data = new FormData(event.currentTarget); @@ -525,6 +554,7 @@ export default function Clear() { } catch (error) { if (error instanceof Error) { setIsLoading(false); + setSearchIconISLodaing(false); setLoadingButton(false); setErrorMessage(true); setErrorMessageText(error.message); @@ -532,6 +562,7 @@ export default function Clear() { } } else { setIsLoading(false); + setSearchIconISLodaing(false); setLoadingButton(false); } }; @@ -569,7 +600,7 @@ export default function Clear() { }; return ( - + ({ + elevation={0} + sx={{ display: 'inline-flex', flexWrap: 'wrap', mb: '2rem', - backgroundColor: '#EEEEEE', - })} + backgroundColor: 'var(--palette-grey-600Channel)', + borderRadius: '0.4rem', + }} > @@ -625,18 +659,20 @@ export default function Clear() { size="small" sx={{ '&.Mui-selected': { - backgroundColor: 'var(--button-color)', - color: 'var(--table-title-color)', + backgroundColor: 'var(--palette-save-color)', + color: '#FFFFFF', boxShadow: 'rgba(145, 158, 171, 0.2) 0px 0px 2px 0px, rgba(145, 158, 171, 0.12) 0px 12px 24px -4px', '&:hover': { - backgroundColor: 'var(--button-color)', + backgroundColor: 'var(--palette-save-color)', }, }, '&:hover': { backgroundColor: 'transparent', }, - p: '0.3rem 0.6rem', - width: '11.5rem', + // textTransform: 'none', + p: '0.3rem 0.5rem', + // width: '11.5rem', + color: 'var(--palette-dark-400Channel)', }} > @@ -646,7 +682,7 @@ export default function Clear() { {search === 'task-id' ? ( - + ) : ( <> @@ -660,6 +696,7 @@ export default function Clear() { borderRadius: '0.2rem', width: optional ? '45rem' : '36rem', position: 'absolute', + backgroundColor: 'var(--palette-background-menu-paper)', }} > Optional - + {formList.map((item) => { return ( @@ -694,12 +731,12 @@ export default function Clear() { placement="top" > @@ -739,7 +776,7 @@ export default function Clear() { text="search" /> - + > ) : ( '' @@ -754,14 +791,14 @@ export default function Clear() { ) : task && task?.type === 'get_task' ? ( - {peers && peers?.length > 0 ? ( + {Array.isArray(peers) && peers?.length > 0 ? ( <> Cache {peers.map((peer: any, index: any) => { - const peerId = peer.scheduler_cluster_id; + const peerId = peer?.scheduler_cluster_id; const totalPage = Math.ceil(peer?.peers.length / 5); const taskPage = taskPages[peerId] || 1; const currentPageData = getPaginatedList(peer?.peers, taskPage, 5); @@ -789,11 +826,7 @@ export default function Clear() { alignItems: 'center', }} > - + { event.stopPropagation(); @@ -826,7 +863,7 @@ export default function Clear() { p: '1rem 0.8rem', display: 'flex', alignItems: 'center', - backgroundColor: 'var(--table-title-color)', + backgroundColor: 'var(--palette-table-title-color)', }} > @@ -891,13 +928,13 @@ export default function Clear() { borderRadius: '0.2rem', backgroundColor: item?.host_type === 'super' - ? 'var( --description-color)' - : 'var(--button-color)', + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', color: item?.host_type === 'super' ? '#FFFFFF' : '#FFFFFF', borderColor: item?.host_type === 'super' - ? 'var( --description-color)' - : 'var(--button-color)', + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', fontWeight: 'bold', }} /> @@ -947,13 +984,13 @@ export default function Clear() { borderRadius: '0.2rem', backgroundColor: item?.host_type === 'super' - ? 'var( --description-color)' - : 'var(--button-color)', + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', color: item?.host_type === 'super' ? '#FFFFFF' : '#FFFFFF', borderColor: item?.host_type === 'super' - ? 'var( --description-color)' - : 'var(--button-color)', + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', fontWeight: 'bold', }} /> @@ -972,7 +1009,7 @@ export default function Clear() { {totalPage > 1 ? ( - + ) : ( - + You don't find any results! @@ -1010,7 +1047,11 @@ export default function Clear() { p: '3rem 2rem 2rem 2rem', }} > - + {theme.palette.mode === 'light' ? ( + + ) : ( + + )} )} - + Delete @@ -1063,21 +1100,17 @@ export default function Clear() { - + WARNING: - + This action CANNOT be undone. @@ -1115,6 +1148,6 @@ export default function Clear() { - + ); } diff --git a/src/components/job/task/executions/index.module.css b/src/components/job/task/executions/index.module.css index 8e01cc3..d0600ac 100644 --- a/src/components/job/task/executions/index.module.css +++ b/src/components/job/task/executions/index.module.css @@ -3,7 +3,7 @@ display: flex; align-items: center; justify-content: space-between; - background-color: var(--table-title-color); + background-color: var(--palette-table-title-color); } .listWrapper { @@ -51,3 +51,20 @@ color: var(--palette-text-disabled); font-family: 'mabry-bold'; } + +.stateIcon { + width: 1.3rem; + height: 1.3rem; +} + +.pendingIcon { + width: 1.3rem; + height: 1.3rem; + color: #dbab0a; +} + +.detailIcon { + width: 2rem; + height: 2rem; + color: var(--palette-button-color); +} diff --git a/src/components/job/task/executions/index.tsx b/src/components/job/task/executions/index.tsx index 36e3913..378bdd2 100644 --- a/src/components/job/task/executions/index.tsx +++ b/src/components/job/task/executions/index.tsx @@ -23,6 +23,11 @@ import { } from '@mui/material'; import MoreTimeIcon from '@mui/icons-material/MoreTime'; import Card from '../../../card'; +import { ReactComponent as IcContent } from '../../../../assets/images/cluster/scheduler/ic-content.svg'; +import { ReactComponent as Success } from '../../../../assets/images/job/preheat/success.svg'; +import { ReactComponent as Failure } from '../../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Pending } from '../../../../assets/images/job/preheat/pending.svg'; +import { ReactComponent as Detail } from '../../../../assets/images/job/preheat/detail.svg'; export default function Executions() { const [errorMessage, setErrorMessage] = useState(false); @@ -119,17 +124,6 @@ export default function Executions() { setStatus(event.target.value); }; - const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, - }); - const handleClose = (_event: any, reason?: string) => { if (reason === 'clickaway') { return; @@ -139,7 +133,7 @@ export default function Executions() { }; return ( - + ) : executions && executions.length === 0 ? ( - + You don't have any executions. @@ -217,26 +211,11 @@ export default function Executions() { {item.result.state === 'SUCCESS' ? ( - + ) : item.result.state === 'FAILURE' ? ( - + ) : ( - + )} - + @@ -286,26 +261,11 @@ export default function Executions() { {item.result.state === 'SUCCESS' ? ( - + ) : item.result.state === 'FAILURE' ? ( - + ) : ( - + )} - + @@ -347,7 +303,7 @@ export default function Executions() { )} {totalPages > 1 ? ( - + > )} - + ); } diff --git a/src/components/job/task/executions/show.module.css b/src/components/job/task/executions/show.module.css index 64b5e81..7c0a99a 100644 --- a/src/components/job/task/executions/show.module.css +++ b/src/components/job/task/executions/show.module.css @@ -32,18 +32,15 @@ .informationTitleIcon { width: 1.4rem !important; height: 1.4rem !important; + color: var(--palette-detail-lable-color); } .informationTitleText { margin-left: 1rem !important; - color: #515151; + color: var(--palette-detail-lable-color); font-family: 'mabry-bold' !important; } -.statusIcon { - margin-right: 0.2rem; -} - .schedulerClustersID { width: 70%; display: flex; @@ -54,10 +51,11 @@ display: flex; align-items: center; justify-content: center; - background-color: var(--button-color); - color: var(--save-size-color); - border-radius: 0.3rem; + background-color: var(--palette-button-color); + color: var(--palette-button-text-color); + border-radius: 0.4rem; min-width: 1.6rem; + height: 1.6rem; margin-right: 0.5rem; padding: 0.2rem 0.4rem; } @@ -78,9 +76,39 @@ } .tableRow { - border-bottom: dashed var(--palette-divider); + border-bottom: dashed var(--palette-palette-divider); } .tableRow:last-child { border-bottom: none; } + +.statusIcon { + margin-right: 0.5rem; + width: 1rem !important; + height: 1rem !important; +} + +.pendingIcon { + width: 1.3rem; + height: 1.3rem; + margin-right: 0.4rem; + color: var(--palette-button-text-color); +} + +.errorIcon { + width: 1.3rem; + height: 1.3rem; +} + +.errorLogIcon { + width: 1.8rem; + height: 1.8rem; + color: var(--palette-button-color); +} + +.IPIcon { + width: 1.5rem; + height: 1.5rem; + padding-right: 0.4rem; +} diff --git a/src/components/job/task/executions/show.tsx b/src/components/job/task/executions/show.tsx index efa911a..36c02cb 100644 --- a/src/components/job/task/executions/show.tsx +++ b/src/components/job/task/executions/show.tsx @@ -34,17 +34,18 @@ import { getBJTDatetime, getPaginatedList, useQuery } from '../../../../lib/util import _ from 'lodash'; import { DEFAULT_SCHEDULER_TABLE_PAGE_SIZE } from '../../../../lib/constants'; import Card from '../../../card'; - -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as PreheatID } from '../../../../assets/images/job/preheat/id.svg'; +import { ReactComponent as Status } from '../../../../assets/images/job/preheat/status.svg'; +import { ReactComponent as URL } from '../../../../assets/images/job/preheat/url.svg'; +import { ReactComponent as Tag } from '../../../../assets/images/job/preheat/tag.svg'; +import { ReactComponent as CreatedAt } from '../../../../assets/images/job/preheat/created-at.svg'; +import { ReactComponent as Failure } from '../../../../assets/images/job/preheat/failure.svg'; +import { ReactComponent as Pending } from '../../../../assets/images/job/preheat/pending.svg'; +import { ReactComponent as ErrorLog } from '../../../../assets/images/job/preheat/error-log.svg'; +import { ReactComponent as TaskID } from '../../../../assets/images/job/task/task-id.svg'; +import { ReactComponent as Application } from '../../../../assets/images/job/task/type.svg'; +import { ReactComponent as IP } from '../../../../assets/images/job/task/ip.svg'; +import { ReactComponent as CheckLog } from '../../../../assets/images/job/task/error-log.svg'; const CustomWidthTooltip = styled(({ className, ...props }: TooltipProps) => ( @@ -173,7 +174,7 @@ export default function ShowExecutions() { const errorlog = Array.from(new Set(jobStates.filter((items: string) => items !== ''))); return ( - + - - + + Error log @@ -255,7 +252,7 @@ export default function ShowExecutions() { - + ID @@ -266,7 +263,7 @@ export default function ShowExecutions() { - + Status @@ -287,6 +284,7 @@ export default function ShowExecutions() { : executions?.result.state === 'FAILURE' ? '#D42536' : '#DBAB0A', + color: 'var(var(--palette-button-text-color)', }} id="status" > @@ -295,12 +293,7 @@ export default function ShowExecutions() { ) : executions?.result?.state === 'FAILURE' ? ( <>> ) : ( - + )} - + > @@ -357,7 +345,7 @@ export default function ShowExecutions() { - + Task ID @@ -372,7 +360,7 @@ export default function ShowExecutions() { - + URL @@ -389,7 +377,7 @@ export default function ShowExecutions() { - + Tag @@ -404,10 +392,10 @@ export default function ShowExecutions() { variant="outlined" sx={{ borderRadius: '0.3rem', - background: 'var(--button-color)', + background: 'var(--palette-button-color)', color: '#FFFFFF', mr: '0.4rem', - borderColor: 'var(--button-color)', + borderColor: 'var(--palette-button-color)', fontWeight: 'bold', }} /> @@ -420,7 +408,7 @@ export default function ShowExecutions() { - + Application @@ -437,7 +425,7 @@ export default function ShowExecutions() { - + Scheduler Clusters ID @@ -460,7 +448,7 @@ export default function ShowExecutions() { - + Created At @@ -502,7 +490,7 @@ export default function ShowExecutions() { - + @@ -539,7 +527,7 @@ export default function ShowExecutions() { - + @@ -585,11 +573,7 @@ export default function ShowExecutions() { - + {item?.ip} @@ -603,10 +587,14 @@ export default function ShowExecutions() { sx={{ borderRadius: '0.2rem', backgroundColor: - item?.host_type === 'super' ? 'var( --description-color)' : 'var(--button-color)', + item?.host_type === 'super' + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', color: item?.host_type === 'super' ? '#FFFFFF' : '#FFFFFF', borderColor: - item?.host_type === 'super' ? 'var( --description-color)' : 'var(--button-color)', + item?.host_type === 'super' + ? 'var( --palette-description-color)' + : 'var(--palette-button-color)', fontWeight: 'bold', }} /> @@ -618,12 +606,7 @@ export default function ShowExecutions() { setErrorLog(true); }} > - + @@ -635,7 +618,7 @@ export default function ShowExecutions() { {totalPages > 1 ? ( - + > )} - + ); } diff --git a/src/components/job/task/index.module.css b/src/components/job/task/index.module.css new file mode 100644 index 0000000..6af2499 --- /dev/null +++ b/src/components/job/task/index.module.css @@ -0,0 +1,4 @@ +.tabIcon { + width: 1.5rem; + height: 1.5rem; +} diff --git a/src/components/job/task/index.tsx b/src/components/job/task/index.tsx index 7a98ad6..fa7b4d7 100644 --- a/src/components/job/task/index.tsx +++ b/src/components/job/task/index.tsx @@ -1,21 +1,13 @@ -import { Breadcrumbs, createTheme, styled, ThemeProvider, Typography, Link as RouterLink } from '@mui/material'; +import { Breadcrumbs, styled, Typography, Link as RouterLink } from '@mui/material'; import { Link, Outlet, useLocation, useParams } from 'react-router-dom'; import * as React from 'react'; import Box from '@mui/material/Box'; import Tabs from '@mui/material/Tabs'; import Tab, { TabProps } from '@mui/material/Tab'; import { useEffect } from 'react'; - -const theme = createTheme({ - palette: { - primary: { - main: '#2e8f79', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import styles from './index.module.css'; +import { ReactComponent as Clear } from '../../../assets/images/job/task/clear-cache.svg'; +import { ReactComponent as Executions } from '../../../assets/images/job/task/executions.svg'; export default function NavTabs() { const [value, setValue] = React.useState(1); @@ -47,29 +39,33 @@ export default function NavTabs() { [theme.breakpoints.up('sm')]: { minWidth: 0, }, + minHeight: '3rem', fontWeight: theme.typography.fontWeightRegular, - marginRight: theme.spacing(1), - color: 'rgba(0, 0, 0, 0.85)', + color: 'var(--palette-grey-tab)', + padding: '0', + marginRight: '2rem', fontSize: '0.9rem', + fontFamily: 'mabry-bold', '&:hover': { color: 'primary', opacity: 1, }, '&.Mui-selected': { - color: '#000', + color: 'var(--palette-description-color)', fontFamily: 'mabry-bold', }, })); const AntTabs = styled(Tabs)({ - borderBottom: '1px solid #e8e8e8', + borderBottom: '1px solid var(--palette-tab-border-color)', '& .MuiTabs-indicator': { - backgroundColor: 'primary', + backgroundColor: 'var(--palette-description-color)', + borderRadius: '1rem', }, }); return ( - + - jobs - task + Job + Task {location.pathname.split('/')[3] === 'executions' ? ( - executions + Executions ) : ( - {location.pathname.split('/')[3]} + Clear )} - {params?.id ? {params?.id} : ''} + {params?.id ? {params?.id || '-'} : ''} } + icon={} iconPosition="start" label="Clear" component={Link} @@ -112,7 +108,7 @@ export default function NavTabs() { id="tab-clear" /> } + icon={} iconPosition="start" label="Executions" component={Link} @@ -121,6 +117,6 @@ export default function NavTabs() { /> - + ); } diff --git a/src/components/loading-backdrop.tsx b/src/components/loading-backdrop.tsx deleted file mode 100644 index 80a43ad..0000000 --- a/src/components/loading-backdrop.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Backdrop, Box } from '@mui/material'; - -interface LoadingBackdropProps { - open: boolean; -} - -const LoadingBackdrop: React.FC = ({ open }) => { - return ( - theme.zIndex.drawer + 1, - backgroundColor: 'rgba(0,0,0,0.3)', - }} - > - - - ); -}; - -export default LoadingBackdrop; diff --git a/src/components/loading-button.tsx b/src/components/loading-button.tsx index 559ff89..9f4477b 100644 --- a/src/components/loading-button.tsx +++ b/src/components/loading-button.tsx @@ -12,7 +12,7 @@ interface cancelLoadingButtonProps extends ButtonProps { export const CancelLoadingButton: React.FC = ({ loading, onClick, id, ...rest }) => ( } + endIcon={} size="small" variant="outlined" type="reset" @@ -20,17 +20,17 @@ export const CancelLoadingButton: React.FC = ({ loadin id={id} sx={{ '&.MuiLoadingButton-root': { - color: 'var(--calcel-size-color)', - borderColor: 'var(--calcel-color)', + color: 'var(--palette-secondary-dark)', + borderColor: 'var(--palette-secondary-dark)', + backgroundColor: 'var(--palette-calcel-background-color)', }, ':hover': { - backgroundColor: 'var(--calcel-hover-corlor)', - borderColor: 'var(--calcel-hover-corlor)', + backgroundColor: 'var(--palette-calcel-hover-corlor)', + borderColor: 'var(--palette-secondary-dark)', }, '&.MuiLoadingButton-loading': { - backgroundColor: 'var(--button-loading-color)', - color: 'var(--button-loading-size-color)', - borderColor: 'var(--button-loading-color)', + backgroundColor: 'var(--palette-button-loading-color)', + color: 'var(--palette-button-loading-size-color)', }, mr: '1rem', width: '7rem', @@ -75,18 +75,18 @@ export const SavelLoadingButton: React.FC = ({ id={id} sx={{ '&.MuiLoadingButton-root': { - backgroundColor: 'var(--save-color)', - color: 'var(--save-size-color)', - borderColor: 'var(--save-color)', + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + borderColor: 'var(--palette-button-color)', }, ':hover': { - backgroundColor: 'var(--save-hover-corlor)', - borderColor: 'var(--save-hover-corlor)', + backgroundColor: 'var(--palette-hover-button-text-color)', + borderColor: 'var(--palette-hover-button-text-color)', }, '&.MuiLoadingButton-loading': { - backgroundColor: 'var(--button-loading-color)', - color: 'var(--button-loading-size-color)', - borderColor: 'var(--button-loading-color)', + backgroundColor: 'var(--palette-button-loading-color)', + color: 'var(--palette-button-loading-size-color)', + borderColor: 'var(--palette-button-loading-color)', }, width: '7rem', }} @@ -123,18 +123,18 @@ export const DeleteLoadingButton: React.FC = ({ id={id} sx={{ '&.MuiLoadingButton-root': { - backgroundColor: 'var(--delete-button-color)', - color: 'var(--save-size-color)', - borderColor: 'var(--delete-button-color)', + backgroundColor: 'var(--palette-delete-button-color)', + color: 'var(--palette-common-white)', + borderColor: 'var(--palette-delete-button-color)', }, ':hover': { - backgroundColor: 'var(--delete-button-hover-color)', - borderColor: 'var(--delete-button-hover-color)', + backgroundColor: 'var(--palette-delete-button-hover-color)', + borderColor: 'var(--palette-delete-button-hover-color)', }, '&.MuiLoadingButton-loading': { - backgroundColor: 'var(--delete-button-color)', + backgroundColor: 'var(--palette-delete-button-color)', - borderColor: 'var(--delete-button-color)', + borderColor: 'var(--palette-delete-button-color)', }, width: '7rem', }} diff --git a/src/components/menu/index.module.css b/src/components/menu/index.module.css index de958c3..4f9d356 100644 --- a/src/components/menu/index.module.css +++ b/src/components/menu/index.module.css @@ -1,85 +1,261 @@ .container { display: flex; - flex-direction: row; + flex: 1 1 auto; + flex-direction: column; + background-color: var(--palette-sidebar-background-color); + height: 100vh; +} + +.layout { + display: flex; + flex: 1 1 auto; + flex-direction: column; + background-color: var(--palette-sidebar-background-color); +} + +.main { + display: flex; + flex: 1 1 auto; + flex-direction: column; + padding: 1.5rem 2rem; + margin: 0.8rem 0.8rem 0.8rem 1.2rem; + overflow-y: auto !important; + background-color: var(--palette-main-background-paper); + box-shadow: var(--palette-card-box-shadow); + border-radius: 0.6rem; } .navigationBarContainer { background-size: cover; background-position: center; - height: 100vh; - max-width: 16rem; + height: 100%; + position: fixed; display: flex; flex-direction: column; + z-index: 1101; + background-color: var(--palette-sidebar-background-color); +} + +.sidebarTitle { + padding: 1.5rem 0 1rem 0.3rem; + display: flex; + align-items: center; justify-content: space-between; } -.title { +.expandIcon { + width: 1rem; + height: 1rem; + color: var(--palette-sidebar-menu-color); +} + +.liMenu { display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.shrinkLiMenu { + display: flex; + flex-direction: column; + gap: 0.6rem; + align-items: center; +} + +.sidebarExpand { + width: 0.6rem; + height: 0.6rem; +} + +.list { + margin-left: 1.25rem !important; + padding-left: 0.75rem !important; + padding-top: 0.8rem !important; + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.list:before { + top: 0px; + left: 0px; + width: 2px; + content: ''; + position: absolute; + background-color: var(--paletteexpandable-sidebar-navigation); + bottom: 1rem; + bottom: calc(36px - 2px - 12px / 2); +} + +.expandable:before { + left: 0px; + content: ''; + position: absolute; + width: 12px; + height: 12px; + background-color: var(--paletteexpandable-sidebar-navigation); + mask: url(../../assets/images/menu/layout.svg) 50% 50% / 100% no-repeat; + transform: translate(calc(12px * -1), calc(12px * -0.4)); +} + +.shrinkMenu { + background-color: var(--palette-background-menu); + background-image: url(../../assets/images/menu/cyan-blur.png), url(../../assets/images/menu/red-blur.png); + background-repeat: no-repeat, no-repeat; + padding: 0.2rem; + background-size: 50%, 50%; + box-shadow: var(--custom-sidebar-shadows-dropdown); + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); + outline: 0px; + background-position: right top, left bottom; + border-radius: var(--menu-border-radius); + overflow: inherit; + min-width: 10rem; +} + +.title { + display: inline-flex; align-items: center; - margin-left: 0.4rem; - margin-top: 2rem; } .logo { width: 1.8rem; height: 1.8rem; - margin-right: 0.8rem; + color: var(--palette-description-color); } .menuIcon { - width: 1.6rem; - height: 1.6rem; -} - -.avatar { - width: 2.6rem !important; - height: 2.6rem !important; - margin-right: 0.6rem; - background: var(--button-color) !important; -} - -.menu { - padding-top: 0.4rem; - padding-bottom: 0.4rem; - width: 14rem; -} - -.expandMenu { - padding-top: 0.4rem; - padding-bottom: 0.4rem; - width: 14rem; - float: right; + width: 1rem; + height: 1rem; } .menuText { font-family: 'mabry-bold' !important; + margin-left: 0.5rem !important; +} + +.avatarMenu { + font-family: 'mabry-bold' !important; + color: var(--palette-color); +} + +.avatarButton { + position: relative; + transition: transform 0.6s easel; + margin-left: 0.3rem; + padding: 0.3rem; +} + +.avatarButton:hover { + transform: scale(1.06); +} + +.avatarWrapper { + background: conic-gradient(#73bafb, #ffd666, #73bafb); + width: 2.7rem; + height: 2.7rem; + animation: rotate 4s linear infinite; + position: absolute; + border-radius: 50%; +} + +@keyframes rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.avatar { + width: 2.35rem !important; + height: 2.35rem !important; + background: var(--palette-secondary-dark) !important; } .profileMenu { - background-image: url(../../../public/images/menu/cyan-blur.png), url(../../../public/images/menu/red-blur.png); - background-color: rgba(255, 255, 255, 0.9); + background-color: var(--palette-background-menu); + background-image: url(../../assets/images/menu/cyan-blur.png), url(../../assets/images/menu/red-blur.png); background-repeat: no-repeat, no-repeat; padding: 0.2rem; background-size: 50%, 50%; - box-shadow: rgba(145, 158, 171, 0.24) 0px 0px 2px 0px, rgba(145, 158, 171, 0.24) -20px 20px 40px -4px; transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); outline: 0px; background-position: right top, left bottom; - border-radius: 10px; + border-radius: var(--menu-border-radius); overflow: inherit; + min-width: 10rem; +} + +.avatarContainer { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0.8rem; +} + +.menuAvatar { + width: 3rem !important; + height: 3rem !important; + background: var(--palette-secondary-dark) !important; +} + +.menuUserName { + font-family: 'mabry-bold' !important; + padding-top: 0.6rem; + color: var(--palette-color); +} + +.menuUserEmail { + width: 100%; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-top: 0.6rem; + color: var(--palette-text-palette-text-secondary); } .menuItemIcon { - color: var(--button-color); + color: var(--palette-button-color); } .pageContainer { - position: relative; - width: 100%; + overflow-y: auto; + height: 100vh; } .pageloading { width: 100%; position: absolute; top: 0; + z-index: 1200; +} + +.sidebarUser { + padding: 0.4rem 0.6rem 0.4rem 0.7rem; + margin-bottom: 0.8rem; + display: flex; + align-items: center; + position: relative; + background-color: var(--palette-sidebar-user-background-paper) !important; +} + +.shrinkSidebarUser { + padding-bottom: 0.8rem; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +} + +.shrinkDarkMode { + margin-bottom: 1rem; +} + +.darkMode { + margin-bottom: 1rem; + width: 100%; } diff --git a/src/components/menu/index.tsx b/src/components/menu/index.tsx index fcda29e..9bf2df1 100644 --- a/src/components/menu/index.tsx +++ b/src/components/menu/index.tsx @@ -2,7 +2,6 @@ import styles from './index.module.css'; import { Alert, Avatar, - Backdrop, Collapse, Divider, Grid, @@ -12,8 +11,9 @@ import { Menu, MenuItem, Snackbar, - Tooltip, Typography, + Link as RouterLink, + Tooltip, } from '@mui/material'; import { styled } from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; @@ -21,14 +21,23 @@ import Box from '@mui/material/Box'; import List from '@mui/material/List'; import { ListItemButton, ListItemIcon } from '@mui/material'; import { createContext, useEffect, useState } from 'react'; -import { ExpandLess, ExpandMore, Logout, PersonAdd } from '@mui/icons-material'; -import ChevronRightOutlinedIcon from '@mui/icons-material/ChevronRightOutlined'; +import { Logout, PersonAdd } from '@mui/icons-material'; import { getUserRoles, getUser, signOut, getUserResponse } from '../../lib/api'; -import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore'; import { getJwtPayload, setPageTitle } from '../../lib/utils'; import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom'; import { ROLE_ROOT, ROLE_GUEST } from '../../lib/constants'; -import LoadingBackdrop from '../loading-backdrop'; +import { ReactComponent as Cluster } from '../../assets/images/menu/cluster.svg'; +import { ReactComponent as Developer } from '../../assets/images/menu/developer.svg'; +import { ReactComponent as Job } from '../../assets/images/menu/job.svg'; +import { ReactComponent as User } from '../../assets/images/menu/user.svg'; +import { ReactComponent as Logo } from '../../assets/images/menu/logo.svg'; +import { ReactComponent as Expand } from '../../assets/images/menu/expand.svg'; +import { ReactComponent as Closure } from '../../assets/images/menu/closure.svg'; +import { ReactComponent as SidebarExpand } from '../../assets/images/menu/sidebar-expand.svg'; +import { ReactComponent as SidebarClosure } from '../../assets/images/menu/sidebar-closure.svg'; +import { HeaderLayout, ShrinkDarkMode } from '../dark-layout'; +import Card from '../card'; +import _ from 'lodash'; interface MyContextType { user: getUserResponse; @@ -56,28 +65,15 @@ export const MyContext = createContext({ }, }); -const Main = styled('div')(({ theme }) => ({ - flexGrow: 1, - overflow: 'auto', - minHeight: '100%', - height: '100vh', - paddingBottom: theme.spacing(8), - [theme.breakpoints.up('lg')]: { - paddingTop: '1.5rem', - paddingLeft: theme.spacing(4), - paddingRight: theme.spacing(4), - }, - fontFamily: 'mabry-light,sans-serif', -})); - const BorderLinearProgress = styled(LinearProgress)(({ theme }) => ({ borderRadius: 5, + height: '3px', [`&.${linearProgressClasses.colorPrimary}`]: { backgroundColor: 'rgba(0, 167, 111, 0.4)', }, [`& .${linearProgressClasses.bar}`]: { borderRadius: 3, - backgroundColor: 'var(--description-color)', + backgroundColor: 'var(--palette-description-color)', }, })); @@ -104,6 +100,11 @@ export default function Layout(props: any) { const [expandDeveloper, setExpandDeveloper] = useState(false); const [expandJob, setExpandJob] = useState(false); const [progress, setProgress] = useState(0); + const [expandedMenu, setExpandedMenu] = useState(null); + const [compactLayout, setCompactLayout] = useState(() => { + const storedValue = localStorage.getItem('compactLayout'); + return storedValue === 'true'; + }); const openProfile = Boolean(anchorElement); const location = useLocation(); @@ -164,6 +165,14 @@ export default function Layout(props: any) { } }, [location.pathname, navigate, location.state?.firstLogin]); + const handleMouseLeave = () => { + setExpandedMenu(null); + }; + + useEffect(() => { + localStorage.setItem('compactLayout', compactLayout ? 'true' : 'false'); + }, [compactLayout]); + const handleUserUpdate = (newUser: getUserResponse) => { setUser(newUser); }; @@ -173,15 +182,13 @@ export default function Layout(props: any) { label: 'clusters', href: '/clusters', text: 'Cluster', - icon: , - selectedIcon: , + icon: , }, { label: 'developer', href: '/tokens', text: 'Developer', - icon: , - selectedIcon: , + icon: , expand: expandDeveloper, setExpand: setExpandDeveloper, menuProps: [ @@ -196,8 +203,7 @@ export default function Layout(props: any) { label: 'jobs', href: '/jobs', text: 'Job', - icon: , - selectedIcon: , + icon: , expand: expandJob, setExpand: setExpandJob, menuProps: [ @@ -220,8 +226,7 @@ export default function Layout(props: any) { label: 'users', href: '/users', text: 'User', - icon: , - selectedIcon: , + icon: , }); } @@ -244,6 +249,7 @@ export default function Layout(props: any) { if (reason === 'clickaway') { return; } + setFirstLogin(false); setErrorMessage(false); }; @@ -282,216 +288,472 @@ export default function Layout(props: any) { {location.pathname === '/signin' || location.pathname === '/signup' ? ( {props.children} ) : ( - + - - - - - - - - Dragonfly - - - - {menu.map((items) => - items?.menuProps ? ( - - + + {compactLayout ? ( + + + + { - items?.setExpand(!items?.expand); - }} - sx={{ - '&.Mui-selected': { - backgroundColor: 'var(--menu-background-color)', - color: 'var(--description-color)', - }, - '&.Mui-selected:hover': { - backgroundColor: 'var(--hover-menu-background-color)', - color: 'var(--description-color)', - }, - height: '2.6rem', - borderRadius: '0.2rem', + setCompactLayout((e: any) => !e); }} > - {(location.pathname.split('/')[1] || '') === items.label ? items.selectedIcon : items.icon} - - {items.text} - - {items.expand ? : } - - - - {items.menuProps?.map((item) => { - return ( - - - {item.text} - - - ); - })} - - + + - ) : ( - + {menu.map((items, index) => { + return items?.menuProps ? ( + { + setExpandedMenu(items.label); + }} + sx={{ + '&.Mui-selected': { + backgroundColor: 'var(--palette-menu-background-color)', + color: 'var(--palette-secondary-dark)', + }, + '&.Mui-selected:hover': { + backgroundColor: 'var(--palette-hover-menu-background-color)', + color: 'var(--palette-secondary-dark)', + }, + borderRadius: '0.6rem', + color: 'var(--palette-sidebar-menu-color)', + p: '0.5rem', + justifyContent: 'center', + position: 'relative !important', + width: '2.4rem', + height: '2.4rem', + }} + > + {items.icon} + {items?.menuProps && expandedMenu === items.label && ( + + {items.menuProps.map((subItem) => ( + { + setExpandedMenu(null); + }} + component={Link} + to={subItem.href} + > + + {subItem.text} + + + ))} + + )} + + ) : ( + + {items.icon} + + ); + })} + + + + + { + setAnchorElement(event.currentTarget); + }} + sx={{ p: '0.3rem' }} + > + + + + { + setAnchorElement(null); + }} + anchorOrigin={{ + vertical: 'top', + horizontal: 'left', + }} + transformOrigin={{ + vertical: 'bottom', + horizontal: 'left', + }} sx={{ - '&.Mui-selected': { - backgroundColor: 'var(--menu-background-color)', - color: 'var(--description-color)', + '& .MuiMenu-paper': { + boxShadow: 'var(--custom-shadows-dropdown)', + borderRadius: 'var(--menu-border-radius)', }, - '&.Mui-selected:hover': { - backgroundColor: 'var(--hover-menu-background-color)', - color: 'var(--description-color)', + '& .MuiMenu-list': { + width: '14rem', + p: '0', }, - height: '2.6rem', - borderRadius: '0.2rem', - mb: '0.4rem', - mt: '0.4rem', }} > - {(location.pathname.split('/')[1] || '') === items.label ? items.selectedIcon : items.icon} - - {items.text} - - - ), - )} - - - - - - - - - {user?.name || '-'} - - - + + + + {user?.name} + + + + {user?.email || '-'} + + + + + { + setAnchorElement(null); + navigate('/profile'); + }} + sx={{ borderRadius: 'var(--menu-border-radius)' }} + > + + + + + Profile + + + + + + + + Logout + + + + + + + ) : ( + + + + + + + Dragonfly + + + { + setCompactLayout((e: any) => !e); }} > - {user?.email || '-'} - - + + + + + {menu.map((items) => + items?.menuProps ? ( + + { + items?.setExpand(!items?.expand); + }} + className={ + (location.pathname.split('/')[1] || '') === items.label ? styles.listButton : '' + } + sx={{ + '&.Mui-selected': { + backgroundColor: 'var(--palette-menu-background-color)', + color: 'var(--palette-secondary-dark)', + }, + '&.Mui-selected:hover': { + color: 'var(--palette-secondary-dark)', + }, + borderRadius: '0.6rem', + color: 'var(--palette-sidebar-menu-color)', + p: '0.5rem 0.7rem', + justifyContent: 'space-between', + }} + > + + {items.icon} + + {items.text} + + + {items.expand ? ( + + ) : ( + + )} + + + + {items.menuProps?.map((item) => { + return ( + + + {item.text} + + + ); + })} + + + + ) : ( + + {items.icon} + + {items.text} + + + ), + )} + - - { - setAnchorElement(event.currentTarget); - }} - size="small" - id="unfold-more" - aria-controls={openProfile ? 'account-menu' : undefined} - aria-haspopup="true" - aria-expanded={openProfile ? 'true' : undefined} - sx={{ position: 'relative', padding: '0' }} - > - - - - { - setAnchorElement(null); - }} - sx={{ - position: 'absolute', - top: '-6rem', - left: '-5.2rem', - '& .MuiMenu-paper': { - boxShadow: '0 0.075rem 0.2rem -0.0625rem #32325d40, 0 0.0625rem 0.0145rem -0.0625rem #0000004d;', - }, - '& .MuiMenu-list': { - p: 0, - }, - }} - > - - { - setAnchorElement(null); - - navigate('/profile'); - }} - > - - - - - Profile - - - - - - - - Logout - - - - - + + + + { + setAnchorElement(event.currentTarget); + }} + id="unfold-more" + className={styles.avatarButton} + sx={{ p: '0.3rem' }} + > + + + + + + {user?.name || '-'} + + + + {user?.email || '-'} + + + + { + setAnchorElement(null); + }} + anchorOrigin={{ + vertical: 'top', + horizontal: 'left', + }} + transformOrigin={{ + vertical: 'bottom', + horizontal: 'left', + }} + sx={{ + '& .MuiMenu-paper': { + boxShadow: 'var(--custom-shadows-dropdown)', + borderRadius: 'var(--menu-border-radius);', + }, + '& .MuiMenu-list': { + width: '14rem', + p: '0', + }, + }} + > + + + + + {user?.name} + + + + {user?.email || '-'} + + + + + { + setAnchorElement(null); + navigate('/profile'); + }} + sx={{ borderRadius: 'var(--menu-border-radius)' }} + > + + + + + Profile + + + + + + + + Logout + + + + + + + + )} + + + + + + - - - - )} diff --git a/src/components/profile/index.module.css b/src/components/profile/index.module.css index 85827b9..b05a642 100644 --- a/src/components/profile/index.module.css +++ b/src/components/profile/index.module.css @@ -1,30 +1,78 @@ .userIcon { - width: 1.6rem; - height: 1.6rem; + width: 1.4rem; + height: 1.4rem; + color: var(--palette-detail-lable-color); } .profileContainer { margin-bottom: 2rem; - padding: 2rem; + position: relative; + height: 14rem; + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); + overflow: hidden; + border-radius: 16px; + z-index: 0; +} + +.profileImage { + background-color: #155939; + background-size: cover; + background-repeat: no-repeat; + background-position: center center; + height: 100%; +} + +.profileContent { + left: 24px; + bottom: 24px; + z-index: 10; + position: absolute; + display: inline-flex; +} + +.tabs { + position: absolute; + width: 100%; + bottom: 0px; + z-index: 9; + background-color: var(--palette-profile-background-paper); + display: flex; + justify-content: flex-end; } .textField { - width: 22rem; + width: 24rem; max-width: 28rem; margin-top: 0.8rem !important; margin-bottom: 0.8rem !important; } .avatarContainer { - display: flex; - justify-content: space-between; - align-items: flex-start; + position: relative; + transition: transform 0.6s easel; + margin-left: 0.3rem; + padding: 0.3rem; + display: inline-flex; + justify-content: center; + align-items: center; + border-radius: 50%; + color: #000; +} + +.avatarWrapper { + background-color: #fff; + width: 7.25rem; + height: 7.25rem; + animation: rotate 4s linear infinite; + position: absolute; + border-radius: 50%; } .avatarContent { - width: 5rem !important; - height: 5rem !important; - background-color: var(--button-color) !important; + box-shadow: var(--palette-main-box-shadow) !important; + width: 7rem !important; + height: 7rem !important; + background: var(--palette-secondary-dark) !important; } .informationHeader { @@ -44,10 +92,6 @@ padding-bottom: 1rem; } -.editIcon { - color: var(--palette-text-disabled); -} - .informationLable { width: 30%; display: flex; @@ -59,3 +103,38 @@ color: var(--palette-detail-lable-color); font-family: 'mabry-bold' !important; } + +.textFieldIcon { + width: 1.4rem; + height: 1.4rem; + margin-right: 0.4rem; + color: var(--palette-grey-tab); +} + +.editIcon { + width: 1.4rem; + height: 1.4rem; + margin-right: 0.4rem; + color: var(--palette-scopes-icon-color); +} + +.passwordWrapper { + padding: 2rem; +} + +.passwordTextField { + width: 50rem; + max-width: 28rem; + margin-top: 0.8rem !important; + margin-bottom: 0.8rem !important; +} + +.tabIcon { + width: 1.5rem; + height: 1.5rem; +} + +.profileForm { + display: flex; + flex-direction: column; +} diff --git a/src/components/profile/index.tsx b/src/components/profile/index.tsx index c6b3cc4..9897bcb 100644 --- a/src/components/profile/index.tsx +++ b/src/components/profile/index.tsx @@ -1,6 +1,7 @@ import { Alert, Box, + Breadcrumbs, Button, Chip, Divider, @@ -9,6 +10,10 @@ import { InputAdornment, Paper, Snackbar, + styled, + Tab, + TabProps, + Tabs, TextField, Typography, } from '@mui/material'; @@ -16,7 +21,6 @@ import Avatar from '@mui/material/Avatar'; import Stack from '@mui/material/Stack'; import { useState, useEffect, useContext } from 'react'; import { updateUser, getUser, updatePassword, signOut, getUserResponse } from '../../lib/api'; -import LocalPhoneIcon from '@mui/icons-material/LocalPhone'; import EmailIcon from '@mui/icons-material/Email'; import LocationOnIcon from '@mui/icons-material/LocationOn'; import DescriptionIcon from '@mui/icons-material/Description'; @@ -31,6 +35,51 @@ import { MyContext } from '../menu/index'; import { CancelLoadingButton, SavelLoadingButton } from '../loading-button'; import Card from '../card'; import MoreTimeIcon from '@mui/icons-material/MoreTime'; +import { ReactComponent as Name } from '../../assets/images/profile/name.svg'; +import { ReactComponent as ID } from '../../assets/images/profile/id.svg'; +import { ReactComponent as Email } from '../../assets/images/profile/email.svg'; +import { ReactComponent as Location } from '../../assets/images/profile/location.svg'; +import { ReactComponent as Phone } from '../../assets/images/profile/phone.svg'; +import { ReactComponent as CreatedAt } from '../../assets/images/profile/created-at.svg'; +import { ReactComponent as Edit } from '../../assets/images/user/edit.svg'; +import { ReactComponent as UserID } from '../../assets/images/user/id.svg'; +import { ReactComponent as DetailRole } from '../../assets/images/user/detail-role.svg'; +import TabPanel from '@mui/lab/TabPanel'; +import { TabContext } from '@mui/lab'; +import _ from 'lodash'; +import { matchIsValidTel, MuiTelInput } from 'mui-tel-input'; + +type StyledTabProps = Omit & {}; + +const AntTab = styled((props: StyledTabProps) => )(({ theme }) => ({ + textTransform: 'none', + minWidth: 0, + [theme.breakpoints.up('sm')]: { + minWidth: 0, + }, + minHeight: '3rem', + fontWeight: theme.typography.fontWeightRegular, + color: 'var(--palette-grey-tab)', + padding: '0', + marginRight: '2rem', + fontSize: '0.9rem', + fontFamily: 'mabry-bold', + '&:hover': { + color: 'primary', + opacity: 1, + }, + '&.Mui-selected': { + color: 'var(--palette-description-color)', + fontFamily: 'mabry-bold', + }, +})); + +const AntTabs = styled(Tabs)({ + '& .MuiTabs-indicator': { + backgroundColor: 'var(--palette-description-color)', + borderRadius: '1rem', + }, +}); export default function Profile() { const [successMessage, setSuccessMessage] = useState(false); @@ -49,9 +98,9 @@ export default function Profile() { const [showNewPassword, setShowNewPassword] = useState(false); const [passwordLoadingButton, setPasswordLoadingButton] = useState(false); const [personalLoadingButton, setPersonalLoadingButton] = useState(false); - const [showMyProfile, setShowMyProfile] = useState(true); const [showPersonalInformation, setShowPersonalInformation] = useState(true); - const [location, setLocation] = useState(''); + const [phone, setPhone] = useState(''); + const [value, setValue] = useState('1'); const [users, setUsers] = useState({ id: 0, @@ -71,47 +120,59 @@ export default function Profile() { new_password: '', }); - const { user, handleUserUpdate } = useContext(MyContext); + const { user, handleUserUpdate, role } = useContext(MyContext); const navigate = useNavigate(); useEffect(() => { setUsers(user); - setLocation(user?.location); + setPhone(user.phone); }, [user]); const { old_password, new_password } = password; + const handleChangePhone = (newValue: string, data: any, cb?: () => void) => { + setPhone(newValue); + const { setError } = data; + setError( + !matchIsValidTel(newValue, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }), + ); + + cb && cb(); + }; + const userLable = [ { name: 'id', label: 'ID', - icon: , + icon: , }, { name: 'name', label: 'Name', - icon: , + icon: , }, { name: 'email', label: 'Email', - icon: , + icon: , }, { name: 'location', label: 'Location', - icon: , + icon: , }, { name: 'phone', label: 'Phone', - icon: , + icon: , }, { name: 'created_at', label: 'Created At', - icon: , + icon: , }, ]; @@ -137,7 +198,7 @@ export default function Profile() { InputProps: { startAdornment: ( - : + : ), }, @@ -157,31 +218,17 @@ export default function Profile() { label: 'Phone', name: 'phone', autoComplete: 'family-name', - value: users.phone, + value: phone, placeholder: 'Enter your Phone', helperText: phoneError ? 'Invalid phone number.' : '', error: phoneError, onChange: (e: any) => { - setUsers({ ...users, phone: e.target.value }); - changeValidate(e.target.value, profileForm[1]); - }, - - InputProps: { - startAdornment: ( - - : - - ), + handleChangePhone(e, profileForm[1]); }, }, syncError: false, setError: setPhoneError, - - validate: (value: string) => { - const reg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$|^$/; - return reg.test(value); - }, }, { formProps: { @@ -202,7 +249,7 @@ export default function Profile() { InputProps: { startAdornment: ( - : + : ), }, @@ -235,7 +282,7 @@ export default function Profile() { InputProps: { startAdornment: ( - : + : ), }, @@ -271,7 +318,7 @@ export default function Profile() { InputProps: { startAdornment: ( - + ), @@ -284,9 +331,9 @@ export default function Profile() { edge="end" > {showOldPassword ? ( - + ) : ( - + )} ), @@ -322,7 +369,7 @@ export default function Profile() { InputProps: { startAdornment: ( - + ), endAdornment: ( @@ -334,9 +381,9 @@ export default function Profile() { edge="end" > {showNewPassword ? ( - + ) : ( - + )} ), @@ -367,7 +414,7 @@ export default function Profile() { InputProps: { startAdornment: ( - + ), @@ -380,9 +427,9 @@ export default function Profile() { edge="end" > {showConfirmPassword ? ( - + ) : ( - + )} ), @@ -422,8 +469,20 @@ export default function Profile() { profileForm.forEach((item) => { const value = data.get(item.formProps.name); - item.setError(!item.validate(value as string)); - item.syncError = !item.validate(value as string); + if (item.validate) { + item.setError(!item.validate(value as string)); + item.syncError = !item.validate(value as string); + } else { + item.setError( + !matchIsValidTel(phone, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }), + ); + + item.syncError = !matchIsValidTel(phone, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }); + } }); const canSubmit = Boolean(!profileForm.filter((item) => item.syncError).length); @@ -432,7 +491,7 @@ export default function Profile() { bio: users.bio, email: users.email, location: users.location, - phone: users.phone, + phone: phone, }; if (canSubmit) { @@ -461,7 +520,6 @@ export default function Profile() { const cancelHandlePersonalInformation = async () => { setUsers(user); - setLocation(user?.location); setShowPersonalInformation(true); }; @@ -507,7 +565,6 @@ export default function Profile() { }; const cancelChangePassword = () => { - setShowMyProfile(true); setPassword({ ...password, old_password: '', new_password: '' }); }; @@ -520,6 +577,10 @@ export default function Profile() { setErrorMessage(false); }; + const handleChange = (event: React.SyntheticEvent, newValue: string) => { + setValue(newValue); + }; + return ( - + My Profile - - {showMyProfile ? ( - - - - - - - + + + + + + + + + + {users?.name || '-'} - - - - {location || '-'} - - + + {_.upperFirst(user?.state) || ''} + + {/* + {_.upperFirst(user?.state) || ''} + */} - - { - setShowMyProfile(false); - }} - > - - Change Password - - - ) : ( - - - Change Password - - {passwordForm.map((item) => ( - - - - ))} - - + + } + key="1" + iconPosition="start" + label="Profile" + sx={{ textTransform: 'none' }} + id="tab-profile" + value="1" onClick={cancelChangePassword} /> - } - id="change-password" - text="Save" + } + key="2" + iconPosition="start" + label="Security" + id="tab-password" + value="2" /> - - - )} - - - {showPersonalInformation ? ( - - - - About me - - { - setShowPersonalInformation(false); - }} - > - - Edit - - - - - - {user?.bio || '-'} - - - Personal Details - - - - {userLable.map((item) => { - return ( - - - - {item.icon} - - {item.label} - - - - {item.name === 'created_at' ? ( - users?.[item.name] ? ( - } - label={getDatetime(users?.[item.name]) || '-'} - variant="outlined" - size="small" - /> - ) : ( - - - - - ) - ) : ( - - {users?.[item?.name as keyof typeof users] || '-'} - - )} - - - - ); - })} - + - ) : ( - - - Update Personal Information - - - {profileForm.map((item) => ( - - + + + {showPersonalInformation ? ( + + + + About me + + + variant="contained" + sx={{ + background: 'var(--palette-button-color)', + color: 'var(--palette-button-text-color)', + ':hover': { backgroundColor: 'var(--palette-hover-button-text-color)' }, + }} + onClick={() => { + setShowPersonalInformation(false); + }} + > + + Edit + + + + + + {user?.bio || '-'} + + + + {userLable.map((item) => { + return ( + + + + {item.icon} + + {item.label} + + + + {item.name === 'created_at' ? ( + users?.[item.name] ? ( + } + label={getDatetime(users?.[item.name]) || '-'} + variant="outlined" + size="small" + /> + ) : ( + + - + + ) + ) : item.label === 'Name' || item?.label === 'ID' ? ( + + {users?.[item?.name as keyof typeof users] || '-'} + + ) : ( + + {users?.[item?.name as keyof typeof users] || '-'} + + )} + + + + ); + })} + + + ) : ( + + + Update Personal Information + + + {profileForm.map((item) => + item.formProps.id === 'phone' ? ( + + ) : ( + + ), + )} + + + } + id="save" + text="Save" + /> + + + + )} + + + + + + + Change Password + + {passwordForm.map((item) => ( + + ))} } - id="save" + id="change-password" text="Save" /> - - - )} - + + + + ); } diff --git a/src/components/rotation.tsx b/src/components/rotation.tsx index 40d61d0..0a43e51 100644 --- a/src/components/rotation.tsx +++ b/src/components/rotation.tsx @@ -1,90 +1,80 @@ -import { Box, Grid, MobileStepper, ThemeProvider, createTheme } from '@mui/material'; +import { Grid, MobileStepper, useTheme } from '@mui/material'; import { useState } from 'react'; import { autoPlay } from 'react-swipeable-views-utils'; import SwipeableViews from 'react-swipeable-views'; +import { ReactComponent as Dragonfly } from '../assets/images/login/dragonfly.svg'; +import { ReactComponent as DarkDragonfly } from '../assets/images/login/dark-dragonfly.svg'; +import { ReactComponent as Features } from '../assets/images/login/features.svg'; +import { ReactComponent as DarkFeatures } from '../assets/images/login/dark-features.svg'; +import { ReactComponent as Milestones } from '../assets/images/login/milestones.svg'; +import { ReactComponent as DarkMilestones } from '../assets/images/login/dark-milestones.svg'; const AutoPlaySwipeableViews = autoPlay(SwipeableViews); -const rotationChart = [ - { - label: 'Dragonfly', - imageURL: '/images/login/dragonfly.svg', - }, - { - label: 'Features', - imageURL: '/images/login/features.svg', - }, - { - label: 'Milestones', - imageURL: '/images/login/milestones.svg', - }, -]; - -const theme = createTheme({ - components: { - MuiMobileStepper: { - styleOverrides: { - dotActive: { - backgroundColor: 'var(--description-color)', - }, - }, - }, - }, -}); - export default function Rotation() { - const [imageList] = useState(rotationChart); const [imageIndex, setImageIndex] = useState(0); + const theme = useTheme(); + + const rotationChart = [ + { + label: 'Dragonfly', + imageURL: , + }, + { + label: 'Milestones', + imageURL: , + }, + ]; + + const darkRotationChart = [ + { + label: 'Dragonfly', + imageURL: , + }, + { + label: 'Milestones', + imageURL: , + }, + ]; const handleStepChange = (step: number) => { setImageIndex(step); }; return ( - - - - {imageList.map((step, index) => { - return ( - - - {Math.abs(imageIndex - index) <= 2 ? ( - - ) : null} - - - ); - })} - - { - - } - - + + + {theme.palette.mode === 'light' + ? rotationChart.map((step, index) => { + return ( + + {Math.abs(imageIndex - index) <= 2 ? step.imageURL : null} + + ); + }) + : darkRotationChart.map((step, index) => { + return ( + + {Math.abs(imageIndex - index) <= 2 ? step.imageURL : null} + + ); + })} + + + ); } diff --git a/src/components/signin/index.module.css b/src/components/signin/index.module.css index bb8f9f1..15bbd87 100644 --- a/src/components/signin/index.module.css +++ b/src/components/signin/index.module.css @@ -1,6 +1,12 @@ .page { height: 100vh; overflow: hidden; + position: relative; +} + +.pageLoading { + width: 4rem; + height: 4rem; } .container { @@ -8,17 +14,35 @@ align-items: center; justify-content: center; margin-bottom: 7rem; + position: relative; +} + +.header { + position: absolute; + top: 1rem; + right: 1rem; + width: 11rem; +} + +.githubContainer { + z-index: 9; + right: 1.6rem; + bottom: 1.6rem; + width: 2rem; + height: 2rem; + position: absolute; } .logo { width: 3rem; height: 3rem; margin-bottom: 1rem; + color: var(--palette-description-color); } .separationLineContainer { - margin-top: 1.2rem; - margin-bottom: 0.8rem; + margin-top: 1rem; + margin-bottom: 0.6rem; height: 2rem; display: flex; justify-content: space-evenly; @@ -35,3 +59,9 @@ margin: 0, 15; vertical-align: middle; } + +.github { + width: 2rem; + height: 2rem; + color: var(--palette-secondary-dark); +} diff --git a/src/components/signin/index.tsx b/src/components/signin/index.tsx index 39aa4fa..37ee3ac 100644 --- a/src/components/signin/index.tsx +++ b/src/components/signin/index.tsx @@ -1,10 +1,8 @@ -import CssBaseline from '@mui/material/CssBaseline'; import TextField from '@mui/material/TextField'; import Grid from '@mui/material/Grid'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import Container from '@mui/material/Container'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; import IconButton from '@mui/material/IconButton'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; import Visibility from '@mui/icons-material/Visibility'; @@ -15,6 +13,9 @@ import styles from './index.module.css'; import { Alert, Backdrop, Snackbar, Link as RouterLink, Button } from '@mui/material'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import { setPageTitle } from '../../lib/utils'; +import { ReactComponent as Login } from '../../assets/images/login/login.svg'; +import { ReactComponent as PageLoading } from '../../assets/images/login/page-loading.svg'; +import { HeaderLayout } from '../dark-layout'; export default function SignIn() { const [errorMessage, setErrorMessage] = useState(false); @@ -93,15 +94,6 @@ export default function SignIn() { setPageTitle(location.pathname); }, [location]); - const theme = createTheme({ - palette: { - secondary: { - contrastText: '#fff', - main: '#2E8F79', - }, - }, - }); - const changeValidate = (value: string, data: any) => { const { setError, validate } = data; setError(!validate(value)); @@ -175,87 +167,96 @@ export default function SignIn() { backgroundColor: 'rgba(0,0,0,0.3)', }} > - + - - - - - - - Welcome back! - - - Through which you can easily configure clusters and view cluster information. - - - - - {formList.map((item) => ( - - ))} - - Sign In - - - - - or + + + + + + Welcome back! + + + Through which you can easily configure clusters and view cluster information. + + + + + {formList.map((item) => ( + + ))} + + Sign In + + + + + or + + + + + + + New to Dragnfly? - - - - - - New to Dragnfly? - - { - setPageLoding(true); - }} - sx={{ color: '#2E8F79', ml: '0.4rem' }} - > - Create an account. - - - + { + setPageLoding(true); + }} + sx={{ color: '#2E8F79', ml: '0.4rem' }} + > + Create an account. + + - - + + ); diff --git a/src/components/signup/index.module.css b/src/components/signup/index.module.css index bb8f9f1..532fb7e 100644 --- a/src/components/signup/index.module.css +++ b/src/components/signup/index.module.css @@ -1,6 +1,12 @@ .page { height: 100vh; overflow: hidden; + position: relative; +} + +.pageLoading { + width: 4rem; + height: 4rem; } .container { @@ -8,12 +14,36 @@ align-items: center; justify-content: center; margin-bottom: 7rem; + position: relative; +} + +.header { + position: absolute; + top: 1rem; + right: 1rem; + width: 11rem; +} + +.githubContainer { + z-index: 9; + right: 1.6rem; + bottom: 1.6rem; + width: 2rem; + height: 2rem; + position: absolute; +} + +.headerContent { + width: 2rem; + height: 2rem; + color: var(--palette-secondary-dark); } .logo { width: 3rem; height: 3rem; margin-bottom: 1rem; + color: var(--palette-description-color); } .separationLineContainer { diff --git a/src/components/signup/index.tsx b/src/components/signup/index.tsx index 870ba88..e3d3a6d 100644 --- a/src/components/signup/index.tsx +++ b/src/components/signup/index.tsx @@ -1,11 +1,8 @@ -import * as React from 'react'; import Button from '@mui/material/Button'; -import CssBaseline from '@mui/material/CssBaseline'; import TextField from '@mui/material/TextField'; import { useEffect, useState } from 'react'; import Typography from '@mui/material/Typography'; import Container from '@mui/material/Container'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; import IconButton from '@mui/material/IconButton'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; import Visibility from '@mui/icons-material/Visibility'; @@ -15,6 +12,9 @@ import { signUp } from '../../lib/api'; import styles from './index.module.css'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import { setPageTitle } from '../../lib/utils'; +import { ReactComponent as Login } from '../../assets/images/login/login.svg'; +import { ReactComponent as PageLoading } from '../../assets/images/login/page-loading.svg'; +import { HeaderLayout } from '../dark-layout'; export default function SignUp() { const [errorMessage, setErrorMessage] = useState(false); @@ -160,15 +160,6 @@ export default function SignUp() { setPageTitle(location.pathname); }, [location]); - const theme = createTheme({ - palette: { - secondary: { - contrastText: '#fff', - main: '#2E8F79', - }, - }, - }); - const handlePassword = (type: 'password' | 'confirmPassword') => { if (type === 'password') { setShowPassword((show) => !show); @@ -244,78 +235,87 @@ export default function SignUp() { backgroundColor: 'rgba(0,0,0,0.3)', }} > - + - - - - - - - Registered Account - - - - - - {formList.map((item) => ( - - - - ))} - - - Sign Up - - - - - or - - - - - - Already have an account? - { - setPageLoding(true); - }} - sx={{ color: '#2E8F79', ml: '0.4rem' }} - > - Sign in - + + + + + + Registered Account + + + + + + {formList.map((item) => ( + + - + ))} + + + Sign Up + + + + + or + + + + + + Already have an account? + { + setPageLoding(true); + }} + sx={{ color: '#2E8F79', ml: '0.4rem' }} + > + Sign in + + - - + + ); diff --git a/src/components/users/index.module.css b/src/components/users/index.module.css index 636a269..45d4e44 100644 --- a/src/components/users/index.module.css +++ b/src/components/users/index.module.css @@ -1,7 +1,6 @@ .changeRoleContainer { display: flex; flex-direction: column; - align-items: center; } .roleIcon { @@ -19,6 +18,7 @@ display: flex; align-items: center; justify-content: space-between; + padding: 0.2rem 0rem 0.7rem 1rem; } .detailContentWrap { @@ -41,10 +41,11 @@ .detailIcon { width: 1.4rem; height: 1.4rem; + color: var(--palette-table-title-text-color); } .menuItemIcon { - color: var(--button-color); + color: var(--palette-button-color); width: 2rem; } @@ -53,22 +54,21 @@ } .menu { - background-image: url(../../../public/images/menu/cyan-blur.png), url(../../../public/images/menu/red-blur.png); - background-color: rgba(255, 255, 255, 0.9); + background-image: url(../../assets/images/menu/cyan-blur.png), url(../../assets/images/menu/red-blur.png); + background-color: var(--palette-background-menu); background-repeat: no-repeat, no-repeat; padding: 0.2rem; background-size: 50%, 50%; - box-shadow: rgba(145, 158, 171, 0.24) 0px 0px 2px 0px, rgba(145, 158, 171, 0.24) -20px 20px 40px -4px; transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); outline: 0px; background-position: right top, left bottom; - border-radius: 10px; + border-radius: var(--menu-border-radius); overflow: inherit; } .detailTitle { padding-left: 0.8rem; - color: var(--text---palette-text-secondary); + color: var(--palette-table-title-text-color); } .detailContent { @@ -76,14 +76,72 @@ } .tableHeader { - color: var(--table-title-text-color); + color: var(--palette-table-title-text-color); font-family: 'mabry-bold' !important; } .tableRow { - border-bottom: dashed var(--palette-divider); + border-bottom: dashed var(--palette-palette-divider); } .tableRow:last-child { border-bottom: none; } + +.tableHeaderText { + border-color: var(--palette-palette-divider) !important; +} + +.searchWrapper { + display: flex; + margin-bottom: 2rem; +} + +.roleContainer { + display: flex; + align-items: center; +} + +.editRoleHeader { + display: flex; + justify-content: space-between; + padding: 0.8rem 1rem; +} + +.editRoleHeaderIcon { + width: 2rem; + height: 2rem; + color: var(--palette-button-color); +} + +.roleEdit { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.6rem; + background-color: var(--palette-background-paper); + box-shadow: var(--palette-card-box-shadow); + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1); + border-radius: 0.6rem; + border: solid; + color: var(--palette-color); + overflow: hidden; + border-width: 1px; +} + +.roleEdit:nth-last-child(2n) { + margin-bottom: 1rem; +} + +.roleIcon { + width: 1.5rem; + height: 1.5rem; + color: var(--palette-secondary-dark); +} + +.roleText { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--palette-text-palette-text-secondary); +} diff --git a/src/components/users/index.tsx b/src/components/users/index.tsx index 92bb61c..14252e3 100644 --- a/src/components/users/index.tsx +++ b/src/components/users/index.tsx @@ -4,19 +4,15 @@ import { Box, Alert, Avatar, - Breadcrumbs, Chip, Dialog, DialogContent, Drawer, FormControl, - FormControlLabel, FormLabel, IconButton, ListItemAvatar, - ListSubheader, Radio, - RadioGroup, Skeleton, Snackbar, Tooltip, @@ -29,64 +25,42 @@ import { ListItem, List, Pagination, - ThemeProvider, - createTheme, MenuItem, Menu, ListItemIcon, + Button, + Stack, + Autocomplete, + TextField, } from '@mui/material'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import CloseIcon from '@mui/icons-material/Close'; +import SearchIcon from '@mui/icons-material/Search'; import { getUserRoles, getUsers, getUser, deleteUserRole, putUserRole, getUsersResponse } from '../../lib/api'; -import { makeStyles } from '@mui/styles'; -import { getDatetime, getPaginatedList, useQuery } from '../../lib/utils'; +import { fuzzySearch, getDatetime, getPaginatedList, useQuery } from '../../lib/utils'; +import AddIcon from '@mui/icons-material/Add'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import styles from './index.module.css'; -import _ from 'lodash'; +import _, { debounce } from 'lodash'; import { ROLE_ROOT, ROLE_GUEST, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../lib/constants'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { CancelLoadingButton, SavelLoadingButton } from '../loading-button'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import ModeEditIcon from '@mui/icons-material/ModeEdit'; import PersonIcon from '@mui/icons-material/Person'; import Card from '../card'; - -const useStyles = makeStyles((theme: any) => ({ - tableRow: { - '&$selected': { - backgroundColor: 'var(--button-color)', - }, - }, - hover: { - backgroundColor: theme.palette.action.hover, - }, - selected: {}, - tableCell: { - color: theme.palette.text.primary, - }, - - selectedTableCell: { - color: '#fff', - }, - selectedTableAvatar: { - color: 'var(--button-color)!important', - backgroundColor: '#fff!important', - }, - selectedButton: { - color: 'var(--button-color)!important', - backgroundColor: '#fff!important', - }, -})); - -const theme = createTheme({ - palette: { - primary: { - main: '#1C293A', - }, - }, - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); +import { ReactComponent as Role } from '../../assets/images/user/role.svg'; +import { ReactComponent as UserID } from '../../assets/images/user/id.svg'; +import { ReactComponent as Name } from '../../assets/images/user/name.svg'; +import { ReactComponent as DetailRole } from '../../assets/images/user/detail-role.svg'; +import { ReactComponent as Email } from '../../assets/images/user/email.svg'; +import { ReactComponent as Phone } from '../../assets/images/user/phone.svg'; +import { ReactComponent as Location } from '../../assets/images/user/location.svg'; +import { ReactComponent as CreatedAt } from '../../assets/images/user/created-at.svg'; +import { ReactComponent as UpdatedAt } from '../../assets/images/user/updated-at.svg'; +import { ReactComponent as Root } from '../../assets/images/user/root.svg'; +import { ReactComponent as Guest } from '../../assets/images/user/guest.svg'; +import SearchCircularProgress from '../circular-progress'; export default function Users() { const [isLoading, setIsLoading] = useState(true); @@ -103,6 +77,7 @@ export default function Users() { const [userTotalPages, setUserTotalPages] = useState(1); const [users, setUsers] = useState([]); const [allUsers, setAllUsers] = useState([]); + const [userCount, setUserCount] = useState([]); const [user, setUser] = useState({ id: 0, email: '', @@ -116,11 +91,14 @@ export default function Users() { const [detailRole, setDetailRole] = useState(''); const [updateRole, setUpdatelRole] = useState(''); const [anchorElement, setAnchorElement] = useState(null); + const [searchUser, setSearchUser] = useState(''); + const [searchIconISLodaing, setSearchIconISLodaing] = useState(false); - const classes = useStyles(); const navigate = useNavigate(); const query = useQuery(); const page = query.get('page') ? parseInt(query.get('page') as string, 10) || 1 : 1; + const search = query.get('search') ? (query.get('search') as string) : ''; + const location = useLocation(); useEffect(() => { (async function () { @@ -131,6 +109,7 @@ export default function Users() { const user = await getUsers({ page: 1, per_page: MAX_PAGE_SIZE }); setUsers(user); + setUserCount(user); setIsLoading(false); } catch (error) { if (error instanceof Error) { @@ -143,11 +122,16 @@ export default function Users() { }, [userPage, page]); useEffect(() => { - const totalPage = Math.ceil(users.length / DEFAULT_PAGE_SIZE); - const currentPageData = getPaginatedList(users, userPage, DEFAULT_PAGE_SIZE); + if (Array.isArray(users) && users.length > 0) { + const totalPage = Math.ceil(users.length / DEFAULT_PAGE_SIZE); + const currentPageData = getPaginatedList(users, userPage, DEFAULT_PAGE_SIZE); - setUserTotalPages(totalPage || 1); - setAllUsers(currentPageData); + setUserTotalPages(totalPage || 1); + setAllUsers(currentPageData); + } else if (users === null || users) { + setUserTotalPages(1); + setAllUsers([]); + } }, [users, userPage]); const handleChange = async (row: any) => { @@ -248,8 +232,43 @@ export default function Users() { setErrorMessage(false); }; + const debounced = useMemo( + () => + debounce(async (currentSearch) => { + if (currentSearch && userCount.length > 0) { + const user = fuzzySearch(currentSearch, userCount); + + setUsers(user); + setSearchIconISLodaing(false); + } else if (currentSearch === '' && userCount.length > 0) { + setUsers(userCount); + setSearchIconISLodaing(false); + } + }, 500), + [userCount], + ); + + const handleInputChange = useCallback( + (newSearch: any) => { + setSearchUser(newSearch); + setSearchIconISLodaing(true); + debounced(newSearch); + + const queryString = newSearch ? `?search=${newSearch}` : ''; + navigate(`${location.pathname}${queryString}`); + }, + [debounced, location.pathname, navigate], + ); + + useEffect(() => { + if (search) { + setSearchUser(search); + debounced(search); + } + }, [search, debounced]); + return ( - + - - } - sx={{ mb: '2rem' }} - > - + + User - + { + navigate(`/users/new`); + }} + > + + Add User + + + + + { + handleInputChange(newInputValue); + }} + options={(Array.isArray(allUsers) && allUsers.map((option) => option?.name)) || ['']} + renderInput={(params) => ( + + + + ) : ( + + + + ), + }} + /> + )} + /> + + - + - - + + Name - + Email - + Location - + State - + Operation @@ -367,8 +447,7 @@ export default function Users() { alt="Remy Sharp" sx={{ '&.MuiAvatar-root': { - background: 'var(--button-color)', - color: '#fff', + background: 'var(--palette-secondary-dark)', }, }} src={item?.avatar} @@ -376,7 +455,7 @@ export default function Users() { - + {item?.name || '-'} @@ -389,9 +468,15 @@ export default function Users() { variant="outlined" sx={{ borderRadius: '0.2rem', - backgroundColor: item?.state === 'enable' ? 'var( --description-color)' : 'var(--button-color)', + backgroundColor: + item?.state === 'enable' + ? 'var( --palette-description-color)' + : 'var(--palette-dark-300Channel)', color: item?.state === 'enable' ? '#FFFFFF' : '#FFFFFF', - borderColor: item?.state === 'enable' ? 'var( --description-color)' : 'var(--button-color)', + borderColor: + item?.state === 'enable' + ? 'var( --palette-description-color)' + : 'var(--palette-dark-300Channel)', fontWeight: 'bold', }} /> @@ -404,21 +489,26 @@ export default function Users() { }} id={`action-${item?.name}`} aria-haspopup="true" - sx={{ position: 'relative' }} > - + { handleChange(selectedRow); @@ -444,6 +535,7 @@ export default function Users() { <>> ) : ( { openSwitchUser(selectedRow); @@ -487,54 +579,115 @@ export default function Users() { + + + + + Role + + + theme.palette.grey[500], + p: '0.2rem', + }} + > + + + + - - - { - setUpdatelRole(e.target.value); + - + + + + Root + + + + The root user is the super user of the system and has the highest authority. + + + + + - } - label="root" + id="role-root" + name="radio-buttons" + checked={updateRole === 'root'} + sx={{ + '&.Mui-checked': { + color: 'var(--palette-description-color)', + }, + }} + onChange={(e: any) => { + setUpdatelRole(e.target.value); + }} /> - + + + + + + Guest + + + + The guest user has limited permissions and is intended for general user access. + + + + + - } - label="guest" + id="role-guest" + name="radio-buttons" + checked={updateRole === 'guest'} + sx={{ + '&.Mui-checked': { + color: 'var(--palette-description-color)', + }, + }} + onChange={(e: any) => { + setUpdatelRole(e.target.value); + }} /> - + @@ -552,11 +705,12 @@ export default function Users() { - + User Detail { setUserDetail(false); setSwitchUser(false); @@ -564,19 +718,19 @@ export default function Users() { setDetailIsLoading(true); }} > - + - + - + ID @@ -588,13 +742,13 @@ export default function Users() { - + Name @@ -610,13 +764,13 @@ export default function Users() { - + Role @@ -631,10 +785,10 @@ export default function Users() { variant="outlined" sx={{ borderRadius: '0.2rem', - background: 'var(--button-color)', + background: 'var(--palette-button-color)', color: '#FFFFFF', mr: '0.4rem', - borderColor: 'var(--button-color)', + borderColor: 'var(--palette-button-color)', fontWeight: 'bold', }} /> @@ -648,13 +802,13 @@ export default function Users() { - + Email @@ -672,13 +826,13 @@ export default function Users() { - + Phone @@ -694,13 +848,13 @@ export default function Users() { - + Location @@ -720,13 +874,13 @@ export default function Users() { - + Created At @@ -750,13 +904,13 @@ export default function Users() { - + Updated At @@ -780,6 +934,6 @@ export default function Users() { - + ); } diff --git a/src/components/users/new.module.css b/src/components/users/new.module.css new file mode 100644 index 0000000..4b7fbc6 --- /dev/null +++ b/src/components/users/new.module.css @@ -0,0 +1,57 @@ +.container { + display: flex; + gap: calc(3 * 0.5rem) calc(3 * 0.5rem); + align-items: flex-start; +} + +.textField:nth-child(3) { + grid-column: span 2; +} + +.formData { + width: 65%; + padding: 2rem 1.5rem; +} + +.textFieldContainer { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: calc(1.5rem); +} + +.uploadWrapper { + width: 35%; + display: flex; + justify-content: center; + align-items: center; + padding: 4rem 2rem; + flex-direction: column; +} + +.uploadText { + text-align: center; + padding-top: 2rem; +} + +.submitWrapper { + padding-top: 2rem; + display: flex; + justify-content: flex-end; +} + +.form { + display: flex; + flex-wrap: wrap; + width: 70%; +} + +.input { + width: 20rem !important; + margin-top: 1rem !important; + margin-bottom: 1rem !important; + margin-right: 1rem !important; +} + +.input:nth-child(3) { + width: 41rem !important; +} diff --git a/src/components/users/new.tsx b/src/components/users/new.tsx new file mode 100644 index 0000000..9586742 --- /dev/null +++ b/src/components/users/new.tsx @@ -0,0 +1,406 @@ +import TextField from '@mui/material/TextField'; +import { useState } from 'react'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import Visibility from '@mui/icons-material/Visibility'; +import { + Alert, + Backdrop, + Box, + Grid, + InputAdornment, + Snackbar, + Link as RouterLink, + Divider, + styled, + Breadcrumbs, +} from '@mui/material'; +import { Link, useLocation, useNavigate } from 'react-router-dom'; +import { matchIsValidTel, MuiTelInput } from 'mui-tel-input'; +import styles from './new.module.css'; +import { CancelLoadingButton, SavelLoadingButton } from '../loading-button'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import { signUp } from '../../lib/api'; + +export default function NewUser() { + const [errorMessage, setErrorMessage] = useState(false); + const [errorMessageText, setErrorMessageText] = useState(''); + const [accountError, setAccountError] = useState(false); + const [emailError, setEmailError] = useState(false); + const [phoneError, setPhoneError] = useState(false); + const [locationError, setLocationError] = useState(false); + const [bioError, setBioError] = useState(false); + const [passwordError, setPasswordError] = useState(false); + const [confirmPassworError, setConfirmPassworError] = useState(false); + const [password, setPassword] = useState(''); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [loadingButton, setLoadingButton] = useState(false); + const [successMessage, setSuccessMessage] = useState(false); + const [phone, setPhone] = useState(''); + + const navigate = useNavigate(); + + const changeValidate = (value: string, data: any, cb?: () => void) => { + const { setError, validate } = data; + setError(!validate(value)); + cb && cb(); + }; + + const handlePassword = (type: 'password' | 'confirmPassword') => { + if (type === 'password') { + setShowPassword((show) => !show); + } else { + setShowConfirmPassword((show) => !show); + } + }; + + const handleChange = (newValue: string, data: any, cb?: () => void) => { + setPhone(newValue); + const { setError } = data; + setError( + !matchIsValidTel(newValue, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }), + ); + + cb && cb(); + }; + + const formList = [ + { + formProps: { + name: 'username', + label: 'Account', + autoComplete: 'family-name', + id: 'account', + required: true, + placeholder: 'Enter your account', + error: accountError, + helperText: accountError ? 'Fill in the characters, the length is 3-10.' : '', + + onChange: (e: any) => { + changeValidate(e.target.value, formList[0]); + }, + }, + syncError: false, + setError: setAccountError, + + validate: (value: string) => { + const reg = /^(?=.*[A-Za-z0-9@$!%*?&._-])[A-Za-z0-9@$!%*?&._-]{3,10}$/; + return reg.test(value); + }, + }, + { + formProps: { + name: 'email', + label: 'Email', + autoComplete: 'email', + id: 'email', + required: true, + placeholder: 'Enter your email', + error: emailError, + helperText: emailError ? 'Email is invalid or already taken.' : '', + + onChange: (e: any) => { + changeValidate(e.target.value, formList[1]); + }, + }, + syncError: false, + setError: setEmailError, + + validate: (value: string) => { + const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; + return reg.test(value); + }, + }, + { + formProps: { + name: 'bio', + label: 'Description', + autoComplete: 'bio', + id: 'bio', + placeholder: 'Enter your description', + error: bioError, + helperText: bioError ? 'Fill in the characters, the length is 0-1000.' : '', + + onChange: (e: any) => { + changeValidate(e.target.value, formList[2]); + }, + }, + syncError: false, + setError: setBioError, + + validate: (value: string) => { + const reg = /^.{0,1000}$/; + return reg.test(value); + }, + }, + { + formProps: { + name: 'phone', + label: 'Phone', + autoComplete: 'phone', + id: 'phone', + placeholder: 'Enter your phone', + error: phoneError, + helperText: phoneError ? 'Enter a valid phone number.' : '', + value: phone, + onChange: (newValue: any) => { + handleChange(newValue, formList[3]); + }, + }, + syncError: false, + setError: setPhoneError, + }, + { + formProps: { + name: 'location', + label: 'Location', + autoComplete: 'location', + id: 'location', + placeholder: 'Enter your location', + error: locationError, + helperText: locationError ? 'Fill in the characters, the length is 0-100.' : '', + + onChange: (e: any) => { + changeValidate(e.target.value, formList[4]); + }, + }, + syncError: false, + setError: setLocationError, + + validate: (value: string) => { + const reg = /^[A-Za-z0-9]{0,100}$/; + return reg.test(value); + }, + }, + { + formProps: { + name: 'password', + label: 'Password', + id: 'password', + required: true, + placeholder: 'Enter your password', + autoComplete: 'new-password', + helperText: passwordError ? `At least 8-16 characters, with at least 1 lowercase letter and 1 number.` : '', + type: showPassword ? 'text' : 'password', + error: passwordError, + InputProps: { + endAdornment: ( + { + handlePassword('password'); + }} + edge="end" + > + {showPassword ? : } + + ), + }, + + onChange: (e: any) => { + changeValidate(e.target.value, formList[5], () => { + setPassword(e.target.value); + }); + }, + }, + syncError: false, + setError: setPasswordError, + + validate: (value: string) => { + const reg = /^(?=.*[a-z])(?=.*\d)[^]{8,16}$/; + return reg.test(value); + }, + }, + { + formProps: { + name: 'confirmPassword', + label: 'ConfirmPassword', + id: 'confirmPassword', + required: true, + type: showConfirmPassword ? 'text' : 'password', + autoComplete: 'new-password', + placeholder: 'Repeat your new password', + error: confirmPassworError, + helperText: confirmPassworError ? 'Please enter the same password.' : '', + + InputProps: { + endAdornment: ( + + { + handlePassword('confirmPassword'); + }} + edge="end" + > + {showConfirmPassword ? : } + + + ), + }, + + onChange: (e: any) => { + changeValidate(e.target.value, formList[6]); + }, + }, + + syncError: false, + setError: setConfirmPassworError, + + validate: (value: string) => { + const reg = /^(?=.*[a-z])(?=.*\d)[^]{8,16}$/; + return value === password && reg.test(value); + }, + }, + ]; + + const handleClose = (_event: any, reason?: string) => { + if (reason === 'clickaway') { + return; + } + + setSuccessMessage(false); + setErrorMessage(false); + }; + + const handleSubmit = async (event: any) => { + setLoadingButton(true); + event.preventDefault(); + const account = event.currentTarget.elements.account.value; + const password = event.currentTarget.elements.password.value; + const email = event.currentTarget.elements.email.value; + const phone = event.currentTarget.elements.phone.value; + const location = event.currentTarget.elements.location.value; + const bio = event.currentTarget.elements.bio.value; + + const data = new FormData(event.currentTarget); + + formList.forEach((item) => { + const value = data.get(item.formProps.name); + + if (item.validate) { + item.setError(!item.validate(value as string)); + item.syncError = !item.validate(value as string); + } else { + item.setError( + !matchIsValidTel(phone, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }), + ); + + item.syncError = !matchIsValidTel(phone, { + onlyCountries: ['FR', 'BE', 'CN', 'US', 'CA', 'JP', 'KR', 'TW', 'HK', 'MO', 'SG', 'MY', 'TH', 'VN'], + }); + } + }); + + const canSubmit = Boolean(!formList.filter((item) => item.syncError).length); + + if (canSubmit) { + try { + await signUp({ + name: account, + password: password, + email: email, + bio: bio, + phone: phone, + location: location, + }); + setLoadingButton(false); + navigate(`/users`); + } catch (error) { + if (error instanceof Error) { + setLoadingButton(false); + setErrorMessage(true); + setErrorMessageText(error.message); + } + } + } else { + setLoadingButton(false); + } + }; + + return ( + + + + Submission successful! + + + + + {errorMessageText} + + + Create a new user + + } + aria-label="breadcrumb" + > + + User + + + New user + + + + + + {formList.map((item) => + item.formProps.id === 'phone' ? ( + + ) : ( + + ), + )} + + + + { + navigate(`/users`); + }} + /> + } id="save" text="Save" /> + + + + ); +} diff --git a/src/index.css b/src/index.css index 70a79c4..4bcc102 100644 --- a/src/index.css +++ b/src/index.css @@ -8,40 +8,145 @@ src: url('../public/fonts/MabryPro-Bold.ttf') format('woff'); } -:root { - --button-color: #1c293a; - --description-color: #2e8f79; - --save-color: #1c293a; - --save-size-color: #ffffff; - --save-hover-corlor: #555555; - --calcel-color: #979797; - --calcel-size-color: #000000; - --calcel-hover-corlor: #f4f3f6; - --button-loading-color: #dedede; - --button-loading-size-color: #000000; - --scopes-icon-color: #edeff2; - --table-title-color: #f4f6f8; - --title-light-color: #7a7a7a; - --menu-background-color: rgba(0, 167, 111, 0.1); - --hover-menu-background-color: rgba(0, 167, 111, 0.2); - --menu-color: #00a76f; - --table-title-text-color: #637381; - --palette-background-paper: #ffffff; - --no-data-color: 145 158 171; +body { + color: #18230f !important; + background-color: rgba(255, 255, 255, 0.9) !important; + --palette-description-color: #1f7d53; + --palette-text-color: #1f7d53; + --palette-color: #18230f; + --palette-button-text-color: #fff; + --palette-button-color: #18230f; + --palette-secondary-dark: #18230f; + --palette-sign-hover-button-text-color: rgb(32, 100, 84); + --palette-hover-button-text-color: #1d3048; + --palette-delete-button-color: #d42536; + --palette-delete-button-hover-color: #d42537b8; + --palette-button-loading-color: #dedede; + --palette-button-loading-size-color: #000000; + --palette-save-color: #18230f; + --palette-calcel-hover-corlor: #f7f7f7; + --palette-calcel-background-color: rgb(255, 255, 255); + --palette-scopes-icon-color: #edeff2; + --palette-table-title-color: #f4f6f8; + --palette-table-title-text-color: #637381; + --palette-main-background-paper: rgba(255, 255, 255, 0.9); + --palette-menu-color: #00a76f; + --palette-sidebar-menu-background-color: #18230f; + --palette-menu-background-color: rgba(145 158 171 / 0.16); + --palette-grey-background-color: #00a76f1a; + --palette-sidebar-expand-background-color: rgba(255, 255, 255, 0.9); + --palette-hover-menu-background-color: #00a76f26; + --palette-background-menu-paper: #fff; + --palette-header-background-color: #f9fafb; + --palette-sidebar-background-color: #f4f6f8; + --palette-sidebar-menu-color: #637381; + --paletteexpandable-sidebar-navigation: #e2e5e9; + --menu-border-radius: 0.4rem; + --palette-background-menu: rgba(255, 255, 255); + --palette-common-white: #fff; + --palette-background-paper: rgba(255, 255, 255, 0.9); + --palette-profile-background-paper: rgba(255, 255, 255, 1); + --palette-sidebar-user-background-paper: #fff; + --palette-no-data-color: 145 158 171; --palette-text-disabled: #919eab; - --text---palette-text-secondary: #637381; - --palette-divider: rgba(145 158 171 / 0.4); - --palette-background-neutral: #f4f6f8; + --palette-text-palette-text-secondary: #637381; + --palette-palette-divider: rgba(145 158 171 / 0.4); --palette-background-inactive: rgb(145 158 171 / 0.16); --palette-card-hover-background-color: #f4f6f8; --palette-detail-lable-color: #515151; --palette-action-hover: rgba(145 158 171 / 0.08); - --delete-button-color: #d42536; - --delete-button-hover-color: #d42537b8; + --palette-background-rotation: #f6f7f9; + --palette-background--hover-rotation: #e7e8ea; + --palette-tab-border-color: #e8e8e8; + --palette-text-secondary: #18230f; + --palette-grey-600Channel: rgba(145 158 171 / 0.16); + --palette-grey-500Channel: 145 158 171; + --palette-grey-400Channel: #e4e5e5; + --palette-grey-300Channel: rgba(0, 0, 0, 0.198); + --palette-grey-200Channel: #18230f; + --palette-grey-100Channel: rgb(232, 232, 232); + --palette-grey-tab: #919eab; + --palette-white-500Channel: #f7f7f7; + --palette-white-400Channel: #efefef; + --palette-dark-500Channel: 134 134 134; + --palette-dark-400Channel: rgba(0, 0, 0, 0.7); + --palette-dark-300Channel: #18230f; + --palette-dark-200Channel: #e9e9e9; + --palette-green-500Channel: rgb(237, 247, 237); + --palette-color-neutral-200: #e8e8e8; + --palette-main-box-shadow: 0 0.125rem 0.2rem -0.0625rem #32325d40, 0 0.0625rem 0.245rem -1.0625rem #0000004d; + --palette-card-box-shadow: 0 0 2px 0 rgba(145 158 171 / 0.2), 0 12px 24px -4px rgba(145 158 171 / 0.12); + --palette-menu-shadow: 0 0.02rem 0.08rem 0.004rem #32325d6b, 0 0.0625rem 0.0145rem -0.0625rem #0000004d; + --custom-shadows-dropdown: 0 0 2px 0 rgba(145 158 171 / 0.24), 2px 5px 0px -5px rgba(145 158 171 / 0.24); + --custom-sidebar-shadows-dropdown: 0 0 2px 0 rgba(0 0 0 / 0.24), 2px 5px 0px -5px rgba(145 158 171 / 0.24); +} + +[data-theme='dark'] body { + color: rgba(255, 255, 255, 0.8) !important; + background-color: #0d121e !important; + --palette-main-background-paper: #0d121e; + --palette-color: rgba(255, 255, 255, 0.7); + --palette-secondary-dark: #ececec; + --palette-description-color: #008170; + --palette-text-color: #008170; + --palette-background-paper: #1f2430; + --palette-profile-background-paper: #1f2430; + --palette-sidebar-user-background-paper: #161b23; + --palette-background-menu-paper: #161b23; + --palette-menu-shadow: none; + --palette-menu-background-color: rgba(145 158 171 / 0.16); + --palette-grey-background-color: rgba(0, 129, 112, 0.2); + --palette-sidebar-expand-background-color: #2a2f3b; + --palette-hover-menu-background-color: #2d323d; + --palette-background-menu: rgba(28, 37, 46); + --palette-text-secondary: #919eab; + --palette-header-background-color: #161b23; + --palette-sidebar-menu-background-color: rgba(255, 255, 255, 0.9); + --palette-sidebar-background-color: #1f2430; + --palette-sidebar-menu-color: rgba(255, 255, 255, 0.8); + --paletteexpandable-sidebar-navigation: #303540; + --palette-grey-tab: #6b7681; + --palette-button-text-color: rgba(255, 255, 255, 0.8); + --palette-button-color: #008170; + --palette-sign-hover-button-text-color: #039b87; + --palette-hover-button-text-color: #039b87; + --palette-save-color: #161b23; + --palette-calcel-hover-corlor: rgba(145 158 171 / 0.3); + --palette-calcel-background-color: rgba(145 158 171 / 0.2); + --palette-card-hover-background-color: #1a202d; + --palette-table-title-color: rgba(255, 255, 255, 0.1); + --palette-table-title-text-color: #919eab; + --palette-detail-lable-color: #a1a0a2; + --palette-background-rotation: #1f2430; + --palette-background--hover-rotation: #25303c; + --palette-tab-border-color: #343536; + --palette-grey-600Channel: #2a2f3b; + --palette-grey-400Channel: #474747; + --palette-grey-300Channel: #c6c6c6; + --palette-grey-200Channel: rgba(255, 255, 255, 0.7); + --palette-grey-100Channel: #4b4e51; + --palette-white-500Channel: #e8e8e8; + --palette-white-400Channel: #d1d1d1; + --palette-dark-500Channel: 145 158 171; + --palette-dark-400Channel: #7d8893; + --palette-dark-300Channel: #5d5f61; + --palette-dark-200Channel: #28323d; + --palette-green-500Channel: rgb(12, 19, 13); + --palette-color-neutral-200: #1f2430; + --palette-main-box-shadow: rgb(255 255 255 / 23%) 0px 0px 0px 0px, rgb(202 204 206 / 32%) 0px 1px 1px -3px; + --custom-shadows-dropdown: 0 0 1px 0 rgb(93 94 95 / 20%), 1px 2px 0px -2px rgb(103 108 112 / 24%); + --custom-sidebar-shadows-dropdown: 0 0 2px 0 rgba(0 0 0 / 0.34), -20px 20px 40px -4px rgba(0 0 0 / 0.24); + --palette-card-box-shadow: 0 0 2px 0 rgba(0 0 0 / 0.2), 0 12px 24px -4px rgba(0 0 0 / 0.12); } body { font-family: 'mabry-light' !important; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + min-height: 100vh; + overflow-y: hidden; } h2 { diff --git a/src/index.tsx b/src/index.tsx index 89022ac..a76b0cc 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,22 +3,13 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { BrowserRouter as Routers } from 'react-router-dom'; -import { ThemeProvider, createTheme } from '@mui/material/styles'; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); -const theme = createTheme({ - typography: { - fontFamily: 'mabry-light,sans-serif', - }, -}); - root.render( - - - - - + + + , ); diff --git a/src/layouts/main.tsx b/src/layouts/main.tsx index 6555a9d..5da592d 100644 --- a/src/layouts/main.tsx +++ b/src/layouts/main.tsx @@ -15,6 +15,7 @@ import ShowSeedPeer from '../components/clusters/seed-peers/show'; import Peers from '../components/clusters/peers'; import Profile from '../components/profile'; import Users from '../components/users'; +import NewUser from '../components/users/new'; import Tokens from '../components/developer/tokens'; import NewTokens from '../components/developer/tokens/new'; import EditTokens from '../components/developer/tokens/edit'; @@ -53,7 +54,7 @@ function Main() { return ( } /> - } /> + } /> } /> } /> }> @@ -81,6 +82,7 @@ function Main() { } /> {isRoot && } />} + } /> ); diff --git a/src/lib/api.ts b/src/lib/api.ts index 2a223f3..aa3752f 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -178,6 +178,9 @@ interface signUpRequset { name: string; password: string; email: string; + bio?: string; + location?: string; + phone?: string; } interface signUpResponse { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 3520206..093db18 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -125,7 +125,7 @@ export const exportCSVFile = (headers: Header[], items: getPeersResponse[], file } }; -export const fuzzySearch = (keyword: string, data: getClustersResponse[]) => { +export const fuzzySearch = (keyword: string, data: any[]) => { if (!data || !Array.isArray(data)) return []; return data.filter((item) => item.name && typeof item.name === 'string' && item.name.includes(keyword));