feat: resource task add Image Manifest Url (#551)
Signed-off-by: zhaoxinxin <1186037180@qq.com>
This commit is contained in:
parent
5d943d8aea
commit
36678fbf10
|
|
@ -1,8 +1,9 @@
|
|||
import createTaskJob from '../../../fixtures/job/task/create-task-job.json';
|
||||
import task from '../../../fixtures/job/task/task.json';
|
||||
import pendingTask from '../../../fixtures/job/task/pending-task.json';
|
||||
import taskIDByTask from '../../../fixtures/job/task/task-id-by-task.json';
|
||||
import noTask from '../../../fixtures/job/task/no-task.json';
|
||||
import createTaskJob from '../../../fixtures/resource/task/create-task-job.json';
|
||||
import task from '../../../fixtures/resource/task/task.json';
|
||||
import pendingTask from '../../../fixtures/resource/task/pending-task.json';
|
||||
import taskIDByTask from '../../../fixtures/resource/task/task-id-by-task.json';
|
||||
import noTask from '../../../fixtures/resource/task/no-task.json';
|
||||
import ImageManifest from '../../../fixtures/resource/task/image-manifest-url-task.json';
|
||||
import _ from 'lodash';
|
||||
|
||||
describe('Clear', () => {
|
||||
|
|
@ -13,56 +14,95 @@ describe('Clear', () => {
|
|||
cy.viewport(1440, 1080);
|
||||
});
|
||||
|
||||
it('when no data is loaded', () => {
|
||||
cy.get('#no-task').should('not.exist');
|
||||
describe('when no data is loaded', () => {
|
||||
it('when search by url has no data to load', () => {
|
||||
cy.get('#no-task').should('not.exist');
|
||||
|
||||
cy.get('#light').should('exist');
|
||||
cy.get('#no-task-image').should('not.exist');
|
||||
cy.get('#light').should('exist');
|
||||
cy.get('#no-task-image').should('not.exist');
|
||||
|
||||
// Click the Toggle Light button.
|
||||
cy.get('#light').click();
|
||||
cy.get('#light').should('have.class', 'Mui-selected');
|
||||
// Click the Toggle Light button.
|
||||
cy.get('#light').click();
|
||||
cy.get('#light').should('have.class', 'Mui-selected');
|
||||
|
||||
// Check if it is switched to light mode.
|
||||
cy.get('#main').should('have.css', 'background-color', 'rgb(244, 246, 248)');
|
||||
// Check if it is switched to light mode.
|
||||
cy.get('#main').should('have.css', 'background-color', 'rgb(244, 246, 248)');
|
||||
|
||||
cy.get('#no-task-image').should('exist');
|
||||
cy.get('#no-task-image').should('exist');
|
||||
|
||||
cy.get('#dark-no-task-image').should('not.exist');
|
||||
cy.get('#dark-no-task-image').should('not.exist');
|
||||
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'post',
|
||||
url: '/api/v1/jobs',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: createTaskJob,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/v1/jobs/1',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: noTask,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'post',
|
||||
url: '/api/v1/jobs',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: createTaskJob,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/v1/jobs/1',
|
||||
},
|
||||
(req) => {
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: noTask,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
cy.get('#url').click();
|
||||
cy.get('#url').click();
|
||||
|
||||
// Add url.
|
||||
cy.get('#url').type('https://example.com/path/to/file');
|
||||
// Add url.
|
||||
cy.get('#url').type('https://example.com/path/to/file');
|
||||
|
||||
cy.get('#searchByURL').click();
|
||||
cy.get('#searchByURL').click();
|
||||
|
||||
cy.get('#no-task').should('exist');
|
||||
cy.get('#no-task').should('exist');
|
||||
});
|
||||
|
||||
it('when search by image manifest url has no data to load', () => {
|
||||
cy.get('#no-task').should('not.exist');
|
||||
|
||||
cy.get('#serach-image-manifest-url').click();
|
||||
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'post',
|
||||
url: '/api/v1/jobs',
|
||||
},
|
||||
async (req) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: {
|
||||
image: {
|
||||
layers: [
|
||||
{
|
||||
url: 'https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c7c72808bf776cd122bdaf4630a4a35ea319603d6a3b6cbffddd4c7fd6d2d269',
|
||||
},
|
||||
{
|
||||
url: 'https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:9986a736f7d3d24bb01b0a560fa0f19c4b57e56c646e1f998941529d28710e6b',
|
||||
},
|
||||
],
|
||||
},
|
||||
peers: [],
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
cy.get('#image-manifest-url').type('https://example.com/path/to/file{enter}');
|
||||
|
||||
// Shou You don't find any results!
|
||||
cy.get('#no-image-manifest-URL-task').should('exist').and('contain', `You don't find any results!`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when data is loaded', () => {
|
||||
|
|
@ -283,6 +323,42 @@ describe('Clear', () => {
|
|||
// Pagination should not be displayed.
|
||||
cy.get('#pagination-1').should('exist');
|
||||
});
|
||||
|
||||
it('can search by image manifest url', () => {
|
||||
cy.get('#no-task').should('not.exist');
|
||||
|
||||
cy.get('#serach-image-manifest-url').click();
|
||||
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'post',
|
||||
url: '/api/v1/jobs',
|
||||
},
|
||||
async (req) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
req.reply({
|
||||
statusCode: 200,
|
||||
body: ImageManifest,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
cy.get('#image-manifest-url').type('https://example.com/path/to/file{enter}');
|
||||
|
||||
// Show is loading.
|
||||
cy.get('#isLoading').should('exist');
|
||||
|
||||
// Display cache information.
|
||||
cy.get('#blobs').should('have.text', 'Total: 5');
|
||||
cy.get('#scheduler-id-0').should('exist', 'ID : 1');
|
||||
cy.get('#isLoading').should('not.exist');
|
||||
cy.get('#scheduler-1-hostname-0').should('have.text', 'kind-worker1');
|
||||
cy.get('#scheduler-1-ip-0').should('have.text', '172.18.0.4');
|
||||
cy.get('#scheduler-1-proportion-0').should('contain', '60.00%');
|
||||
|
||||
// Should display URL.
|
||||
cy.get('#scheduler-1-url-0').click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should handle API error response', () => {
|
||||
|
|
@ -395,7 +471,7 @@ describe('Clear', () => {
|
|||
cy.wait(60000);
|
||||
});
|
||||
|
||||
it('Delete cache API error response', () => {
|
||||
it('delete cache API error response', () => {
|
||||
// Search by task id.
|
||||
cy.get('#serach-task-id').click();
|
||||
cy.intercept(
|
||||
|
|
@ -434,6 +510,27 @@ describe('Clear', () => {
|
|||
cy.get('.MuiAlert-action > .MuiButtonBase-root').click();
|
||||
cy.get('.MuiAlert-message').should('not.exist');
|
||||
});
|
||||
|
||||
it('search by image manifest url API error response', () => {
|
||||
cy.get('#no-task').should('not.exist');
|
||||
cy.get('#serach-image-manifest-url').click();
|
||||
cy.intercept(
|
||||
{
|
||||
method: 'post',
|
||||
url: '/api/v1/jobs',
|
||||
},
|
||||
async (req) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
req.reply({
|
||||
forceNetworkError: true,
|
||||
});
|
||||
},
|
||||
);
|
||||
cy.get('#image-manifest-url').type('https://example.com/path/to/file{enter}');
|
||||
|
||||
// Show error message.
|
||||
cy.get('.MuiAlert-message').should('be.visible').and('contain', 'Failed to fetch');
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
|
|
@ -625,10 +722,7 @@ describe('Clear', () => {
|
|||
|
||||
cy.get('#searchByURL').click();
|
||||
|
||||
cy.get(':nth-child(2) > .MuiPaper-root > .css-whqzh4 > .css-70qvj9 > .css-1y3f2j > #schedulerTotal').should(
|
||||
'contain',
|
||||
'2',
|
||||
);
|
||||
cy.get('#scheduler-id-1').should('contain', '2');
|
||||
|
||||
cy.get(':nth-child(2) > .MuiPaper-root > .css-whqzh4 > .MuiButtonBase-root').click();
|
||||
|
||||
|
|
@ -698,10 +792,7 @@ describe('Clear', () => {
|
|||
'fe0c4a611d35e338efd342c346a2c671c358c5187c483a5fc7cd66c6685ce916{enter}',
|
||||
);
|
||||
|
||||
cy.get(':nth-child(2) > .MuiPaper-root > .css-whqzh4 > .css-70qvj9 > .css-1y3f2j > #schedulerTotal').should(
|
||||
'contain',
|
||||
'2',
|
||||
);
|
||||
cy.get('#scheduler-id-1').should('contain', '2');
|
||||
|
||||
cy.get(':nth-child(2) > .MuiPaper-root > .css-whqzh4 > .MuiButtonBase-root').click();
|
||||
|
||||
|
|
@ -819,7 +910,7 @@ describe('Clear', () => {
|
|||
.and('have.text', 'Fill in the characters, the length is 0-1000.');
|
||||
});
|
||||
|
||||
it('try to verify url', () => {
|
||||
it('try to verify content for calculating task id', () => {
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
const contentForCalculatingTaskID = _.times(1001, () => _.sample(characters)).join('');
|
||||
|
||||
|
|
@ -831,5 +922,26 @@ describe('Clear', () => {
|
|||
.should('be.visible')
|
||||
.and('have.text', 'Fill in the characters, the length is 0-1000.');
|
||||
});
|
||||
|
||||
it('try to verify image manifest url', () => {
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
const url = _.times(1001, () => _.sample(characters)).join('');
|
||||
|
||||
cy.get('#serach-image-manifest-url').click();
|
||||
|
||||
cy.get('#image-manifest-url').click();
|
||||
|
||||
// Should display message url the validation error.
|
||||
cy.get('#image-manifest-url').type(`https://docs${url}`);
|
||||
|
||||
cy.get('#image-manifest-url-helper-text')
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Fill in the characters, the length is 1-1000.');
|
||||
|
||||
cy.get('#image-manifest-url').clear();
|
||||
cy.get('#image-manifest-url').type('https://docs');
|
||||
|
||||
cy.get('#image-manifest-url-helper-text').should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import executions from '../../../fixtures/job/task/executions.json';
|
||||
import execution from '../../../fixtures/job/task/execution.json';
|
||||
import pendingExecution from '../../../fixtures/job/task/pending-execution.json';
|
||||
import failureExecution from '../../../fixtures/job/task/failure-execution.json';
|
||||
import executions from '../../../fixtures/resource/task/executions.json';
|
||||
import execution from '../../../fixtures/resource/task/execution.json';
|
||||
import pendingExecution from '../../../fixtures/resource/task/pending-execution.json';
|
||||
import failureExecution from '../../../fixtures/resource/task/failure-execution.json';
|
||||
|
||||
describe('Executions', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import executions from '../../../fixtures/job/task/executions.json';
|
||||
import paginationExecutions from '../../../fixtures/job/task/pagination-executions.json';
|
||||
import successExecutions from '../../../fixtures/job/task/success-executions.json';
|
||||
import failureExecutions from '../../../fixtures/job/task/failure-executions.json';
|
||||
import pendingExecutions from '../../../fixtures/job/task/pending-executions.json';
|
||||
import executions from '../../../fixtures/resource/task/executions.json';
|
||||
import paginationExecutions from '../../../fixtures/resource/task/pagination-executions.json';
|
||||
import successExecutions from '../../../fixtures/resource/task/success-executions.json';
|
||||
import failureExecutions from '../../../fixtures/resource/task/failure-executions.json';
|
||||
import pendingExecutions from '../../../fixtures/resource/task/pending-executions.json';
|
||||
|
||||
describe('Executions', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
{
|
||||
"image": {
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c1d6d1b2d5a367259e6e51a7f4d1ccd66a28cc9940d6599d8a8ea9544dd4b4a8"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1a1d290795d904815786e41d39a41dc1af5de68a9e9020baba8bd83b32d8f95"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1ffc4b5459e82dc8e7ddd1d1a2ec469e85a1f076090c22851a1f2ce6f71e1a6"
|
||||
}
|
||||
]
|
||||
},
|
||||
"peers": [
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker1",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1ffc4b5459e82dc8e7ddd1d1a2ec469e85a1f076090c22851a1f2ce6f71e1a6?format=json"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c1d6d1b2d5a367259e6e51a7f4d1ccd66a28cc9940d6599d8a8ea9544dd4b4a8"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c1d6d1b2d5a367259e6e51a7f4d1ccd66a28cc9940d6599d8a8ea9544dd4b4a7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker2",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker3",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1ffc4b5459e82dc8e7ddd1d1a2ec469e85a1f076090c22851a1f2ce6f71e1a6"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c1d6d1b2d5a367259e6e51a7f4d1ccd66a28cc9940d6599d8a8ea9544dd4b4a8"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker4",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker5",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1ffc4b5459e82dc8e7ddd1d1a2ec469e85a1f076090c22851a1f2ce6f71e1a6"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:c1d6d1b2d5a367259e6e51a7f4d1ccd66a28cc9940d6599d8a8ea9544dd4b4a8"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.4",
|
||||
"hostname": "kind-worker6",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 1
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.3",
|
||||
"hostname": "kind-worker7",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 2
|
||||
},
|
||||
{
|
||||
"ip": "172.18.0.3",
|
||||
"hostname": "kind-worker8",
|
||||
"layers": [
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:f1f1039835051ecc04909f939530e86a20f02d2ce5ad7a81c0fa3616f7303944"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:871ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
},
|
||||
{
|
||||
"url": "https://ghcr.io/v2/dragonflyoss/scheduler/blobs/sha256:771ab018db94b4ae7b137764837bc4504393a60656ba187189e985cd809064f7"
|
||||
}
|
||||
],
|
||||
"scheduler_cluster_id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<svg t="1751289209561" class="icon" viewBox="0 0 1191 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="48455" width="200" height="200">
|
||||
<path
|
||||
d="M1081.527579 542.078644A108.415332 108.415332 0 0 1 1189.942911 651.155045v264.42764a107.754263 107.754263 0 0 1-108.415332 108.415332H108.433866A107.754263 107.754263 0 0 1 0.018534 914.260546v-264.427639A108.415332 108.415332 0 0 1 108.433866 542.078644z m0 80.65043H108.433866a28.425971 28.425971 0 0 0-27.764902 27.103833v264.427639a27.103833 27.103833 0 0 0 27.103833 27.764903h973.754782a27.764902 27.764902 0 0 0 27.764902-27.103833v-264.42764a28.425971 28.425971 0 0 0-27.103833-28.425971zM207.594231 727.177992a33.714524 33.714524 0 0 1 34.375593 33.714524v37.680938a34.375593 34.375593 0 0 1-66.10691 0v-37.680938a33.714524 33.714524 0 0 1 31.731317-33.714524z m154.690169 0a33.714524 33.714524 0 0 1 34.375593 33.714524v37.680938a34.375593 34.375593 0 0 1-66.10691 0v-37.680938a33.714524 33.714524 0 0 1 31.731317-33.714524zM925.515272 727.177992a52.885528 52.885528 0 1 1 0 105.109986h-27.764902a52.885528 52.885528 0 1 1 0-105.109986z m156.012307-727.176009A107.754263 107.754263 0 0 1 1189.942911 108.417315v264.42764a108.415332 108.415332 0 0 1-108.415332 108.415332H108.433866A108.415332 108.415332 0 0 1 0.018534 372.183886v-264.42764A107.754263 107.754263 0 0 1 108.433866 0.001983z m0 80.65043H108.433866a27.764902 27.764902 0 0 0-27.764902 27.103833v264.42764a27.764902 27.764902 0 0 0 27.103833 27.764902h973.754782a27.764902 27.764902 0 0 0 27.764902-27.103833v-264.42764a27.764902 27.764902 0 0 0-27.103833-27.764902zM207.594231 185.7624a34.375593 34.375593 0 0 1 34.375593 34.375593v37.01987a34.375593 34.375593 0 1 1-66.10691 0v-37.01987a33.714524 33.714524 0 0 1 31.731317-34.375593z m154.690169 0a34.375593 34.375593 0 0 1 34.375593 34.375593v37.01987a34.375593 34.375593 0 1 1-66.10691 0v-37.01987a33.714524 33.714524 0 0 1 31.731317-34.375593z m561.247665 0a52.885528 52.885528 0 0 1 0 105.771056h-27.764903a52.885528 52.885528 0 1 1 0-105.771056z"
|
||||
fill="currentColor" p-id="48456"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<svg t="1734589694524" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="53329" width="200" height="200">
|
||||
<path
|
||||
d="M537.362229 1024c-9.510836 0-15.851393-3.170279-22.19195-9.510836l-282.154799-278.98452c-120.470588-123.640867-158.513932-307.517028-91.938081-466.03096S362.996904 6.340557 534.19195 6.340557s329.708978 104.619195 393.114552 263.133127c66.575851 158.513932 28.532508 342.390093-91.938081 466.03096L559.55418 1014.489164c-6.340557 6.340557-12.681115 9.510836-22.191951 9.510836z m0-957.424149C391.529412 66.575851 258.377709 155.343653 201.312693 291.665635c-57.065015 136.321981-25.362229 291.665635 79.256966 396.284829l259.962849 256.79257 259.962848-259.962848c104.619195-104.619195 136.321981-259.962848 79.256966-396.28483-60.235294-133.151703-193.386997-221.919505-342.390093-221.919505z m0 0"
|
||||
fill="currentColor" p-id="53330"></path>
|
||||
<path
|
||||
d="M382.018576 285.325077h63.405573v342.390093h-63.405573V285.325077z m244.111455 342.390093h-63.405573V317.027864c0-15.851393 12.681115-31.702786 31.702787-31.702787h66.575851c60.235294 0 107.789474 47.55418 107.789474 107.789474s-47.55418 107.789474-107.789474 107.789474h-34.873065v126.811145z m0-187.046439h34.873065c25.362229 0 47.55418-22.19195 47.55418-47.55418s-22.19195-47.55418-47.55418-47.554179h-34.873065v95.108359z m0 0"
|
||||
fill="currentColor" p-id="53331"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<svg t="1751448383394" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="56778" width="200" height="200">
|
||||
<path
|
||||
d="M118.979048 637.074286l137.99619 66.243047 255.171048 123.587048 246.076952-119.222857 147.163429-70.485334a73.142857 73.142857 0 0 1-34.230857 97.109334l-327.119239 158.427428a73.142857 73.142857 0 0 1-63.780571 0L153.136762 734.305524A73.142857 73.142857 0 0 1 118.979048 637.074286z m786.090666-153.063619a73.142857 73.142857 0 0 1-33.913904 97.767619L544.01219 740.205714a73.142857 73.142857 0 0 1-63.780571 0L153.136762 581.778286A73.142857 73.142857 0 0 1 117.51619 487.862857l362.300953 170.886095 32.329143 15.652572 327.119238-158.427429 65.80419-31.939047zM544.036571 139.190857l327.094858 158.403048a73.142857 73.142857 0 0 1 0 131.657143l-327.094858 158.427428a73.142857 73.142857 0 0 1-63.780571 0L153.136762 429.251048a73.142857 73.142857 0 0 1 0-131.657143L480.256 139.215238a73.142857 73.142857 0 0 1 63.780571 0z m-31.890285 65.828572L185.027048 363.422476l327.119238 158.427429 327.119238-158.427429L512.146286 205.04381z"
|
||||
p-id="56779" fill="currentColor"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,23 @@
|
|||
<svg t="1751461120062" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="62198" width="200" height="200">
|
||||
<path
|
||||
d="M486.105058 51.989846C217.657489 51.989846 0.09998 269.547354 0.09998 537.994923c0 268.347588 217.557508 486.005077 486.005078 486.005077 268.347588 0 486.005077-217.557508 486.005077-486.005077H486.105058V51.989846z"
|
||||
fill="currentColor" p-id="62199" data-spm-anchor-id="a313x.search_index.0.i52.46c83a815s2V0n" class="selected">
|
||||
</path>
|
||||
<path d="M537.894942 0.09998v486.005078h486.005078C1023.90002 217.657489 806.342511 0.09998 537.894942 0.09998z"
|
||||
fill="rgb(178, 228, 193)" p-id="62200" data-spm-anchor-id="a313x.search_index.0.i54.46c83a815s2V0n" class="">
|
||||
</path>
|
||||
</svg>
|
||||
|
||||
<!-- <svg t="1751448525528" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="61090" width="200" height="200">
|
||||
<path
|
||||
d="M539.450983 15.110813h-0.503689v467.927137h468.934515C1007.579596 224.544724 798.044947 15.110813 539.450983 15.110813z"
|
||||
fill="currentColor" p-id="61091"></path>
|
||||
<path
|
||||
d="M486.563632 82.101458h-15.110672c-62.961132 0-125.2171 12.592226-183.141342 37.172252C114.337417 193.013789 1.309592 363.663642 1.208854 552.647778c-0.201476 260.105031 210.542027 471.150747 470.747795 471.352222h0.705165c259.903555-0.201476 470.445582-211.045716 470.244106-470.949271v-15.614361H486.563632v-455.33491z m425.919469 485.556254c-1.712543 54.196943-13.498867 107.487245-34.553069 157.4532-94.794281 224.141632-353.388244 328.908956-577.429139 234.114675C142.644742 892.33568 37.877417 740.221584 31.631673 569.068041c-8.76419-243.281816 181.328062-447.678837 424.710615-456.443026v455.032697h456.140813z"
|
||||
fill="currentColor" p-id="61092"></path>
|
||||
<path
|
||||
d="M1022.992481 482.836474C1022.791005 215.98201 806.305447-0.201335 539.450983 0.000141H523.836623v498.14848h499.155858v-15.110671-0.201476zM554.057966 467.927278V30.42296c238.647877 7.454598 430.452671 198.856441 438.511696 437.504318H554.057966z"
|
||||
fill="currentColor" p-id="61093"></path>
|
||||
</svg> -->
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -62,6 +62,14 @@
|
|||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.schedulerClusterWrapper {
|
||||
border: 1px solid #d5d2d2;
|
||||
padding: 0.1rem 0.3rem;
|
||||
border-radius: 0.3rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.schedulerClusterIcon {
|
||||
width: 0.6rem;
|
||||
height: 0.6rem;
|
||||
|
|
@ -95,3 +103,129 @@
|
|||
height: 1.25rem;
|
||||
margin-right: 0.4rem;
|
||||
}
|
||||
|
||||
.imageManifestCard {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.imageManifestHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cacheHeader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 1.5rem 0 1rem 0;
|
||||
}
|
||||
|
||||
.bolbWrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--palette-table-title-text-color);
|
||||
}
|
||||
|
||||
.bolbText {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 0.3rem;
|
||||
background-color: var(--palette-background-inactive);
|
||||
padding: 0.2rem 0.4rem;
|
||||
}
|
||||
|
||||
.hostnameContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.4rem 0;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.hostnameWrapper {
|
||||
border-radius: 0.3rem;
|
||||
background-color: var(--palette-background-inactive);
|
||||
border: 0;
|
||||
font-family: 'mabry-bold';
|
||||
display: inline-flex;
|
||||
padding: 0.3rem 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hostnameIcon {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
.urlsWrapper {
|
||||
border-color: var(--palette-palette-divider) !important;
|
||||
background-color: var(--palette-background-inactive) !important;
|
||||
border-radius: var(--menu-border-radius) !important;
|
||||
padding: 0.5rem 0.6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.url {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.urlIcon {
|
||||
width: 8%;
|
||||
height: 1.4rem !important;
|
||||
color: var(--palette-detail-lable-color);
|
||||
}
|
||||
|
||||
.layerWrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.layerIcon {
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
|
||||
.bolbIconWrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 0.6rem !important;
|
||||
transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
z-index: 0;
|
||||
color: var(--palette-color) !important;
|
||||
background-image: none;
|
||||
padding: 0.4rem;
|
||||
background-color: var(--palette-background-paper) !important;
|
||||
box-shadow: var(--palette-card-box-shadow) !important;
|
||||
}
|
||||
|
||||
.cardCantainer {
|
||||
gap: calc(1.2rem);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.bolbProportionContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.3rem 0.4rem;
|
||||
background-color: var(--palette-button-color) !important;
|
||||
border-radius: var(--menu-border-radius) !important;
|
||||
margin-right: 0.4rem;
|
||||
color: var(--palette-scopes-icon-color);
|
||||
}
|
||||
|
||||
.bolbIcon {
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
.bolbProportionText {
|
||||
padding-left: 0.4rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ import {
|
|||
Pagination,
|
||||
useTheme,
|
||||
InputAdornment,
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
} from '@mui/material';
|
||||
import styles from './index.module.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
|
@ -27,8 +30,15 @@ import ClearIcon from '@mui/icons-material/Clear';
|
|||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import MoreTimeIcon from '@mui/icons-material/MoreTime';
|
||||
import { getTaskJobResponse, createTaskJob, getTaskJob } from '../../../../lib/api';
|
||||
import { getDatetime, getPaginatedList } from '../../../../lib/utils';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import {
|
||||
getTaskJobResponse,
|
||||
createTaskJob,
|
||||
getTaskJob,
|
||||
createGetImageDistributionJob,
|
||||
createGetImageDistributionJobResponse,
|
||||
} from '../../../../lib/api';
|
||||
import { extractSHA256Regex, getDatetime, getPaginatedList } from '../../../../lib/utils';
|
||||
import _ from 'lodash';
|
||||
import SearchTaskAnimation from '../../../search-task-animation';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
|
@ -46,6 +56,12 @@ import { ReactComponent as DarkNoTask } from '../../../../assets/images/resource
|
|||
import { ReactComponent as Delete } from '../../../../assets/images/cluster/delete.svg';
|
||||
import { ReactComponent as DeleteWarning } from '../../../../assets/images/cluster/delete-warning.svg';
|
||||
import { ReactComponent as ContentForCalculatingTaskID } from '../../../../assets/images/resource/task/content-for-calculating-task-id.svg';
|
||||
import { ReactComponent as ImageManifest } from '../../../../assets/images/resource/task/image-manifest.svg';
|
||||
import { ReactComponent as IP } from '../../../../assets/images/resource/task/clear-ip.svg';
|
||||
import { ReactComponent as Hostnames } from '../../../../assets/images/resource/task/clear-hostname.svg';
|
||||
import { ReactComponent as Proportion } from '../../../../assets/images/resource/task/proportion.svg';
|
||||
|
||||
import { ReactComponent as Layer } from '../../../../assets/images/resource/task/layer.svg';
|
||||
|
||||
const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({
|
||||
[`& .${toggleButtonGroupClasses.grouped}`]: {
|
||||
|
|
@ -62,17 +78,71 @@ const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
type Layers = {
|
||||
url: string;
|
||||
};
|
||||
|
||||
type Image = {
|
||||
layers: Layers[];
|
||||
};
|
||||
|
||||
type OriginalPeer = {
|
||||
ip: string;
|
||||
hostname: string;
|
||||
layers: Layers[];
|
||||
scheduler_cluster_id?: number;
|
||||
};
|
||||
|
||||
type ClusteredPeer = {
|
||||
peer: Omit<OriginalPeer, 'scheduler_cluster_id'>[];
|
||||
scheduler_cluster_id: number;
|
||||
};
|
||||
|
||||
type TransformedImage = {
|
||||
peers: ClusteredPeer[];
|
||||
image: Image;
|
||||
};
|
||||
|
||||
const transformImages = (images: createGetImageDistributionJobResponse): TransformedImage => {
|
||||
const clusters = new Map<number, Omit<OriginalPeer, 'scheduler_cluster_id'>[]>();
|
||||
|
||||
for (const peer of images.peers || []) {
|
||||
const clusterId = peer.scheduler_cluster_id ?? 1;
|
||||
|
||||
if (!clusters.has(clusterId)) {
|
||||
clusters.set(clusterId, []);
|
||||
}
|
||||
|
||||
const cleanedPeer = {
|
||||
ip: peer.ip,
|
||||
hostname: peer.hostname,
|
||||
layers: peer.layers,
|
||||
};
|
||||
|
||||
clusters.get(clusterId)!.push(cleanedPeer);
|
||||
}
|
||||
|
||||
const resultPeers: ClusteredPeer[] = Array.from(clusters.entries()).map(([id, peers]) => ({
|
||||
peer: peers,
|
||||
scheduler_cluster_id: id,
|
||||
}));
|
||||
|
||||
return { peers: resultPeers, image: images.image };
|
||||
};
|
||||
|
||||
export default function Clear() {
|
||||
const [errorMessage, setErrorMessage] = useState(false);
|
||||
const [errorMessageText, setErrorMessageText] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [searchTaskISLodaing, setSearchTaskISLodaing] = useState(false);
|
||||
const [searchContentForCalculatingTaskIDISLodaing, setSearchContentForCalculatingTaskIDISLodaing] = useState(false);
|
||||
const [searchImageManifestISLodaing, setSearchImageManifestISLodaing] = useState(false);
|
||||
const [searchIconISLodaing, setSearchIconISLodaing] = useState(false);
|
||||
const [openDeleteTask, setOpenDeleteTask] = useState(false);
|
||||
const [deleteLoadingButton, setDeleteLoadingButton] = useState(false);
|
||||
const [searchTask, setSearchTask] = useState('');
|
||||
const [searchContentForCalculatingTaskID, setSearchContentForCalculatingTaskID] = useState('');
|
||||
const [searchImageManifest, setSearchImageManifest] = useState('');
|
||||
const [task, setTask] = useState<getTaskJobResponse | any>();
|
||||
const [optional, setOptional] = useState(false);
|
||||
const [deleteError, setDeleteError] = useState(false);
|
||||
|
|
@ -97,6 +167,9 @@ export default function Clear() {
|
|||
filtered_query_params: '',
|
||||
piece_length: 0,
|
||||
});
|
||||
const [imageManifestURL, setImageManifestURL] = useState<TransformedImage>();
|
||||
const [layer, setLayer] = useState(0);
|
||||
const [pageStates, setPageStates] = useState<any>({});
|
||||
|
||||
const { url, tag, application, filtered_query_params } = searchData;
|
||||
const navigate = useNavigate();
|
||||
|
|
@ -493,6 +566,61 @@ export default function Clear() {
|
|||
},
|
||||
};
|
||||
|
||||
const imageManifestForm = {
|
||||
formProps: {
|
||||
id: 'image-manifest-url',
|
||||
label: 'Image Manifest URL',
|
||||
name: 'image-manifest-url',
|
||||
required: true,
|
||||
value: searchImageManifest,
|
||||
autoComplete: 'family-name',
|
||||
placeholder: 'Enter your image manifest URL',
|
||||
helperText: contentForCalculatingTaskIDError ? 'Fill in the characters, the length is 1-1000.' : '',
|
||||
error: contentForCalculatingTaskIDError,
|
||||
InputProps: {
|
||||
startAdornment: searchImageManifestISLodaing ? (
|
||||
<Box className={styles.circularProgress}>
|
||||
<SearchCircularProgress />
|
||||
</Box>
|
||||
) : (
|
||||
<Box className={styles.circularProgress}>
|
||||
<SearchIcon sx={{ color: '#9BA0A6' }} />
|
||||
</Box>
|
||||
),
|
||||
endAdornment: searchImageManifest ? (
|
||||
<IconButton
|
||||
type="button"
|
||||
aria-label="search"
|
||||
onClick={() => {
|
||||
setSearchImageManifest('');
|
||||
setSearchImageManifestISLodaing(false);
|
||||
}}
|
||||
>
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
},
|
||||
|
||||
onChange: (e: any) => {
|
||||
changeValidate(e.target.value, imageManifestForm);
|
||||
setSearchImageManifest(e.target.value);
|
||||
|
||||
if (e.target.value === '') {
|
||||
setSearchImageManifestISLodaing(false);
|
||||
}
|
||||
},
|
||||
},
|
||||
syncError: false,
|
||||
setError: setContentForCalculatingTaskIDError,
|
||||
|
||||
validate: (value: string) => {
|
||||
const reg = /^(?:https?|ftp):\/\/[^\s/$.?#].[^\s].{1,1000}$/;
|
||||
return reg.test(value);
|
||||
},
|
||||
};
|
||||
|
||||
const result =
|
||||
task?.result?.job_states?.map((item: any) => {
|
||||
return item.results ? item.results.map((resultItem: any) => resultItem) : [];
|
||||
|
|
@ -740,6 +868,37 @@ export default function Clear() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleSearchByImageManifestURL = async (event: any) => {
|
||||
setIsLoading(true);
|
||||
setSearchImageManifestISLodaing(true);
|
||||
|
||||
try {
|
||||
event.preventDefault();
|
||||
|
||||
const form = {
|
||||
args: {
|
||||
url: searchImageManifest,
|
||||
},
|
||||
type: 'get_image_distribution',
|
||||
};
|
||||
|
||||
const imageManifest = await createGetImageDistributionJob(form);
|
||||
const imageManifestTask = transformImages(imageManifest);
|
||||
|
||||
setImageManifestURL(imageManifestTask);
|
||||
setLayer(imageManifestTask?.image?.layers?.length || 0);
|
||||
setSearchImageManifestISLodaing(false);
|
||||
setIsLoading(false);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
setErrorMessage(true);
|
||||
setErrorMessageText(error.message);
|
||||
setIsLoading(false);
|
||||
setSearchImageManifestISLodaing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = (_event: any, reason?: string) => {
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
|
|
@ -765,6 +924,8 @@ export default function Clear() {
|
|||
setOptional(false);
|
||||
setSearchTask('');
|
||||
setSearchDada({ url: '', tag: '', application: '', filtered_query_params: '', piece_length: 0 });
|
||||
setSearchContentForCalculatingTaskID('');
|
||||
setSearchImageManifest('');
|
||||
};
|
||||
|
||||
const handlePageChange = (peerId: any, newPage: any) => {
|
||||
|
|
@ -774,6 +935,13 @@ export default function Clear() {
|
|||
}));
|
||||
};
|
||||
|
||||
const handleImagePageChange = (schedulerClusterId: any, page: any) => {
|
||||
setPageStates((prev: any) => ({
|
||||
...prev,
|
||||
[schedulerClusterId]: page,
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Snackbar
|
||||
|
|
@ -827,6 +995,30 @@ export default function Clear() {
|
|||
<LinkOutlinedIcon sx={{ mr: '0.4rem' }} />
|
||||
Search by URL
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
id="serach-image-manifest-url"
|
||||
value="image-manifest-url"
|
||||
size="small"
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
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(--palette-save-color)',
|
||||
},
|
||||
},
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
p: '0.3rem 0.5rem',
|
||||
color: 'var(--palette-dark-400Channel)',
|
||||
textTransform: 'none',
|
||||
}}
|
||||
>
|
||||
<ImageManifest className={styles.contentForCalculatingTaskIDIcon} />
|
||||
Search by Image Manifest URL
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
id="serach-task-id"
|
||||
value="task-id"
|
||||
|
|
@ -890,6 +1082,15 @@ export default function Clear() {
|
|||
>
|
||||
<TextField fullWidth variant="outlined" size="small" {...calculatingTaskIDForm.formProps} sx={{ p: 0 }} />
|
||||
</Box>
|
||||
) : search === 'image-manifest-url' ? (
|
||||
<Box
|
||||
key="image-manifest-url"
|
||||
component="form"
|
||||
onSubmit={handleSearchByImageManifestURL}
|
||||
sx={{ width: '38rem', height: '3rem' }}
|
||||
>
|
||||
<TextField fullWidth variant="outlined" size="small" {...imageManifestForm.formProps} sx={{ p: 0 }} />
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ position: 'relative', height: '3rem' }}>
|
||||
<Paper
|
||||
|
|
@ -902,6 +1103,7 @@ export default function Clear() {
|
|||
width: optional ? '45rem' : '36rem',
|
||||
position: 'absolute',
|
||||
backgroundColor: 'var(--palette-background-menu-paper)',
|
||||
zIndex: '100001',
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
|
|
@ -1023,19 +1225,11 @@ export default function Clear() {
|
|||
<Typography variant="subtitle1" mr="0.6rem" fontFamily="mabry-bold">
|
||||
Scheduler Cluster
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
border: '1px solid #d5d2d2',
|
||||
p: '0.2rem 0.3rem',
|
||||
borderRadius: '0.2rem',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Box className={styles.schedulerClusterWrapper} id={`scheduler-id-${index}`}>
|
||||
<SchedulerCluster className={styles.schedulerClusterIcon} />
|
||||
<Typography
|
||||
id="schedulerTotal"
|
||||
variant="subtitle2"
|
||||
variant="caption"
|
||||
fontFamily="mabry-bold"
|
||||
component="div"
|
||||
pl="0.3rem"
|
||||
|
|
@ -1242,6 +1436,184 @@ export default function Clear() {
|
|||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
) : Array.isArray(imageManifestURL?.peers) ? (
|
||||
imageManifestURL?.peers.length > 0 ? (
|
||||
<Box>
|
||||
<Box className={styles.cacheHeader}>
|
||||
<Typography variant="h6" fontFamily="mabry-bold">
|
||||
Cache
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box className={styles.bolbWrapper}>
|
||||
<Typography variant="body2" fontFamily="mabry-bold" component="div" pr="0.4rem">
|
||||
Blobs
|
||||
</Typography>
|
||||
<Typography
|
||||
id="blobs"
|
||||
variant="caption"
|
||||
fontFamily="mabry-bold"
|
||||
component="div"
|
||||
className={styles.bolbText}
|
||||
>
|
||||
{`Total: ${layer || 0}`}
|
||||
</Typography>
|
||||
</Box>
|
||||
{imageManifestURL?.peers.map((item, index) => {
|
||||
const schedulerClusterId = item.scheduler_cluster_id;
|
||||
const totalPage = Math.ceil(item.peer.length / 5);
|
||||
const currentPage = pageStates[schedulerClusterId] || 1;
|
||||
const paginatedPeers = getPaginatedList(item.peer, currentPage, 5);
|
||||
return (
|
||||
<Box mb="2rem" key={index}>
|
||||
<Card key={index} className={styles.imageManifestCard}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', p: '1rem' }}>
|
||||
<Typography variant="subtitle1" mr="0.6rem" fontFamily="mabry-bold">
|
||||
Scheduler Cluster
|
||||
</Typography>
|
||||
<Box className={styles.schedulerClusterWrapper} id={`scheduler-id-${index}`}>
|
||||
<SchedulerCluster className={styles.schedulerClusterIcon} />
|
||||
<Typography
|
||||
variant="caption"
|
||||
fontFamily="mabry-bold"
|
||||
component="div"
|
||||
pl="0.3rem"
|
||||
lineHeight="1rem"
|
||||
>
|
||||
ID : {item?.scheduler_cluster_id || '0'}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Divider />
|
||||
{paginatedPeers?.map((items, peerIndex) => {
|
||||
return (
|
||||
<Box key={peerIndex}>
|
||||
<Accordion
|
||||
disableGutters
|
||||
elevation={0}
|
||||
square
|
||||
sx={{
|
||||
'&:not(:last-child)': {
|
||||
borderBottom: 0,
|
||||
},
|
||||
'&:before': {
|
||||
display: 'none',
|
||||
},
|
||||
backgroundColor: 'var(--palette-background-paper)',
|
||||
}}
|
||||
>
|
||||
<AccordionSummary
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
aria-controls="panel1-content"
|
||||
id={`scheduler-${item?.scheduler_cluster_id}-url-${peerIndex}`}
|
||||
>
|
||||
<Box className={styles.imageManifestHeader}>
|
||||
<Box className={styles.hostnameContainer}>
|
||||
<Box width="18%">
|
||||
<Box
|
||||
className={styles.hostnameWrapper}
|
||||
id={`scheduler-${item?.scheduler_cluster_id}-hostname-${peerIndex}`}
|
||||
>
|
||||
<Hostnames className={styles.hostnameIcon} />
|
||||
<Typography variant="subtitle2" ml="0.4rem" fontFamily="mabry-bold">
|
||||
{items?.hostname}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
className={styles.hostnameWrapper}
|
||||
id={`scheduler-${item?.scheduler_cluster_id}-ip-${peerIndex}`}
|
||||
>
|
||||
<IP className={styles.hostnameIcon} />
|
||||
<Typography variant="subtitle2" ml="0.4rem" fontFamily="mabry-bold">
|
||||
{items?.ip}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
className={styles.bolbProportionContainer}
|
||||
id={`scheduler-${item?.scheduler_cluster_id}-proportion-${peerIndex}`}
|
||||
>
|
||||
<Proportion className={styles.bolbIcon} />
|
||||
<Typography
|
||||
component="div"
|
||||
variant="body2"
|
||||
fontFamily="mabry-bold"
|
||||
className={styles.bolbProportionText}
|
||||
>
|
||||
{`${((items?.layers?.length / layer) * 100).toFixed(2) || 0}%`}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails
|
||||
key={peerIndex}
|
||||
sx={{
|
||||
padding: '1rem',
|
||||
backgroundColor: 'var(--palette-background-paper)',
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Box className={styles.layerWrapper}>
|
||||
<Paper variant="outlined" className={styles.bolbIconWrapper}>
|
||||
<Layer className={styles.layerIcon} />
|
||||
</Paper>
|
||||
<Typography component="div" variant="body2" fontFamily="mabry-bold" ml="0.5rem">
|
||||
Blobs
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box className={styles.cardCantainer}>
|
||||
{items?.layers.map((item: any, bolbIndex: any) => (
|
||||
<Box key={bolbIndex} className={styles.urlsWrapper}>
|
||||
<Tooltip title={extractSHA256Regex(item?.url || '-') || '-'} placement="top">
|
||||
<Typography
|
||||
id={`url-${bolbIndex}`}
|
||||
className={styles.url}
|
||||
fontFamily="mabry-bold"
|
||||
variant="body2"
|
||||
>
|
||||
{extractSHA256Regex(item?.url || '-') || '-'}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
{peerIndex !== paginatedPeers.length - 1 && <Divider />}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Card>
|
||||
{totalPage > 1 && (
|
||||
<Box display="flex" justifyContent="flex-end" sx={{ marginTop: '2rem' }}>
|
||||
<Pagination
|
||||
id={`pagination-${index}`}
|
||||
count={Math.ceil(item.peer.length / 5)}
|
||||
page={currentPage}
|
||||
onChange={(e, page) => handleImagePageChange(schedulerClusterId, page)}
|
||||
color="primary"
|
||||
size="small"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
) : (
|
||||
<Box
|
||||
id="no-image-manifest-URL-task"
|
||||
sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: '6rem' }}
|
||||
>
|
||||
<NoSearch className={styles.noSearch} />
|
||||
<Box>
|
||||
<Typography variant="h5" component="span">
|
||||
You don't find any results!
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
|
|
|
|||
|
|
@ -982,12 +982,36 @@ export interface createTaskJobResponse {
|
|||
scheduler_clusters: Array<scheduler_clusters>;
|
||||
}
|
||||
|
||||
interface layers {
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface ImageDistributionpeers {
|
||||
ip: string;
|
||||
hostname: string;
|
||||
layers: layers[];
|
||||
scheduler_cluster_id: number;
|
||||
}
|
||||
|
||||
export interface createGetImageDistributionJobResponse {
|
||||
image: { layers: layers[] };
|
||||
peers: ImageDistributionpeers[];
|
||||
}
|
||||
|
||||
export async function createTaskJob(request: createTaskJobResquest): Promise<createTaskJobResponse> {
|
||||
const url = new URL(`/api/v1/jobs`, API_URL);
|
||||
const response = await post(url, request);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export async function createGetImageDistributionJob(
|
||||
request: createTaskJobResquest,
|
||||
): Promise<createGetImageDistributionJobResponse> {
|
||||
const url = new URL(`/api/v1/jobs`, API_URL);
|
||||
const response = await post(url, request);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export interface peers {
|
||||
created_at: string;
|
||||
host_type: string;
|
||||
|
|
|
|||
|
|
@ -168,3 +168,8 @@ export const parseTimeDuration = (input: string) => {
|
|||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const extractSHA256Regex = (url: string) => {
|
||||
const match = url.match(/\/sha256:([a-f0-9]{64})/);
|
||||
return match ? match[1] : '';
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue