зеркало из https://github.com/microsoft/pai.git
[Webportal] Support Job Priority in job-list (#5525)
* update hivedScheduler.jobPriorityClass spell in db controller * add jobPriority to frameworkConverter * update * update * update * update * update swagger * add default jobPriority support * fix * fix * add job priority to table and ordering * add priority filter * update * fix * fix * fix lint
This commit is contained in:
Родитель
6625542870
Коммит
5153a4d9a6
|
@ -186,7 +186,7 @@ class Snapshot {
|
||||||
);
|
);
|
||||||
const jobPriority = _.get(
|
const jobPriority = _.get(
|
||||||
loadedConfig,
|
loadedConfig,
|
||||||
'extras.hivedscheduler.jobPriorityClass',
|
'extras.hivedScheduler.jobPriorityClass',
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
// Job status change notification
|
// Job status change notification
|
||||||
|
|
|
@ -17,10 +17,11 @@ info:
|
||||||
version 2.2.4: support sorting by completionTime in get the list of jobs
|
version 2.2.4: support sorting by completionTime in get the list of jobs
|
||||||
version 2.2.5: add alert related api
|
version 2.2.5: add alert related api
|
||||||
version 2.2.6: update type of taskUid
|
version 2.2.6: update type of taskUid
|
||||||
|
version 2.2.7: add jobPriority list jobs parameter
|
||||||
license:
|
license:
|
||||||
name: MIT License
|
name: MIT License
|
||||||
url: "https://github.com/microsoft/pai/blob/master/LICENSE"
|
url: "https://github.com/microsoft/pai/blob/master/LICENSE"
|
||||||
version: 2.2.6
|
version: 2.2.7
|
||||||
externalDocs:
|
externalDocs:
|
||||||
description: Find out more about OpenPAI
|
description: Find out more about OpenPAI
|
||||||
url: "https://github.com/microsoft/pai"
|
url: "https://github.com/microsoft/pai"
|
||||||
|
@ -1150,6 +1151,11 @@ paths:
|
||||||
description: filter jobs with tags. When multiple tags are specified, every job selected should have none of these tags
|
description: filter jobs with tags. When multiple tags are specified, every job selected should have none of these tags
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
- name: jobPriority
|
||||||
|
in: query
|
||||||
|
description: filter jobs with jobPriority, fields include oppo, test, prod, and default (default means jobPriorityClass in job config is null)
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
- name: offset
|
- name: offset
|
||||||
in: query
|
in: query
|
||||||
description: list job offset
|
description: list job offset
|
||||||
|
@ -1164,7 +1170,7 @@ paths:
|
||||||
in: query
|
in: query
|
||||||
description: 'order of job list.
|
description: 'order of job list.
|
||||||
It follows the format <field>,<ASC|DESC>, default value is "submissionTime,DESC".
|
It follows the format <field>,<ASC|DESC>, default value is "submissionTime,DESC".
|
||||||
Available fields include: jobName, submissionTime, username, vc, retries, totalTaskNumber, totalGpuNumber, state, completionTime.
|
Available fields include: jobName, submissionTime, username, vc, retries, totalTaskNumber, totalGpuNumber, state, completionTime, jobPriority.
|
||||||
CompletionTime maybe null for some jobs, these jobs will be returned at the end of the list when sorting by ASC order & at the beginning when sorting by DESC order.'
|
CompletionTime maybe null for some jobs, these jobs will be returned at the end of the list when sorting by ASC order & at the beginning when sorting by DESC order.'
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1197,6 +1203,7 @@ paths:
|
||||||
completedTime: 0
|
completedTime: 0
|
||||||
appExitCode: 0
|
appExitCode: 0
|
||||||
virtualCluster: unknown
|
virtualCluster: unknown
|
||||||
|
jobPriority: prod
|
||||||
"500":
|
"500":
|
||||||
$ref: "#/components/responses/UnknownError"
|
$ref: "#/components/responses/UnknownError"
|
||||||
"/api/v2/jobs/{user}~{job}":
|
"/api/v2/jobs/{user}~{job}":
|
||||||
|
@ -2223,6 +2230,10 @@ components:
|
||||||
debugId:
|
debugId:
|
||||||
type: string
|
type: string
|
||||||
description: md5 hash name for the job in framework controller, used for debug purpose
|
description: md5 hash name for the job in framework controller, used for debug purpose
|
||||||
|
jobPriority:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
description: job priority
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- username
|
- username
|
||||||
|
|
|
@ -81,6 +81,22 @@ const list = asyncHandler(async (req, res) => {
|
||||||
{ virtualCluster: { [Op.substring]: req.query.keyword } },
|
{ virtualCluster: { [Op.substring]: req.query.keyword } },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
if ('jobPriority' in req.query) {
|
||||||
|
const jobPriorityFilter = req.query.jobPriority.split(',');
|
||||||
|
const index = jobPriorityFilter.indexOf('default');
|
||||||
|
if (index !== -1) {
|
||||||
|
jobPriorityFilter.splice(index, 1);
|
||||||
|
if (filters[Op.or] === undefined) {
|
||||||
|
filters[Op.or] = [];
|
||||||
|
}
|
||||||
|
filters[Op.or].push({ jobPriority: { [Op.is]: null } });
|
||||||
|
if (jobPriorityFilter.length > 0) {
|
||||||
|
filters[Op.or].push({ jobPriority: jobPriorityFilter });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filters.jobPriority = jobPriorityFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ('order' in req.query) {
|
if ('order' in req.query) {
|
||||||
const [field, ordering] = req.query.order.split(',');
|
const [field, ordering] = req.query.order.split(',');
|
||||||
if (
|
if (
|
||||||
|
@ -94,6 +110,7 @@ const list = asyncHandler(async (req, res) => {
|
||||||
'totalGpuNumber',
|
'totalGpuNumber',
|
||||||
'state',
|
'state',
|
||||||
'completionTime',
|
'completionTime',
|
||||||
|
'jobPriority',
|
||||||
].includes(field)
|
].includes(field)
|
||||||
) {
|
) {
|
||||||
if (ordering === 'ASC' || ordering === 'DESC') {
|
if (ordering === 'ASC' || ordering === 'DESC') {
|
||||||
|
@ -106,6 +123,10 @@ const list = asyncHandler(async (req, res) => {
|
||||||
const orderingWithNulls =
|
const orderingWithNulls =
|
||||||
ordering === 'ASC' ? 'ASC NULLS LAST' : 'DESC NULLS FIRST';
|
ordering === 'ASC' ? 'ASC NULLS LAST' : 'DESC NULLS FIRST';
|
||||||
order.push(['completionTime', orderingWithNulls]);
|
order.push(['completionTime', orderingWithNulls]);
|
||||||
|
} else if (field === 'jobPriority') {
|
||||||
|
const orderingWithNulls =
|
||||||
|
ordering === 'ASC' ? 'ASC NULLS LAST' : 'DESC NULLS FIRST';
|
||||||
|
order.push(['jobPriority', orderingWithNulls]);
|
||||||
} else {
|
} else {
|
||||||
order.push([field, ordering]);
|
order.push([field, ordering]);
|
||||||
}
|
}
|
||||||
|
@ -129,6 +150,7 @@ const list = asyncHandler(async (req, res) => {
|
||||||
'totalGpuNumber',
|
'totalGpuNumber',
|
||||||
'totalTaskNumber',
|
'totalTaskNumber',
|
||||||
'totalTaskRoleNumber',
|
'totalTaskRoleNumber',
|
||||||
|
'jobPriority',
|
||||||
'retries',
|
'retries',
|
||||||
'retryDelayTime',
|
'retryDelayTime',
|
||||||
'platformRetries',
|
'platformRetries',
|
||||||
|
|
|
@ -75,6 +75,7 @@ const convertFrameworkSummary = (framework) => {
|
||||||
totalGpuNumber: framework.totalGpuNumber,
|
totalGpuNumber: framework.totalGpuNumber,
|
||||||
totalTaskNumber: framework.totalTaskNumber,
|
totalTaskNumber: framework.totalTaskNumber,
|
||||||
totalTaskRoleNumber: framework.totalTaskRoleNumber,
|
totalTaskRoleNumber: framework.totalTaskRoleNumber,
|
||||||
|
jobPriority: framework.jobPriority,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,6 +188,7 @@ const convertFrameworkDetail = async (
|
||||||
debugId: frameworkWithLatestAttempt.metadata.name,
|
debugId: frameworkWithLatestAttempt.metadata.name,
|
||||||
name: jobName,
|
name: jobName,
|
||||||
tags: tags.reduce((arr, curr) => [...arr, curr.name], []),
|
tags: tags.reduce((arr, curr) => [...arr, curr.name], []),
|
||||||
|
jobPriority: frameworkWithLatestAttempt.jobPriority,
|
||||||
jobStatus: {
|
jobStatus: {
|
||||||
username: userName,
|
username: userName,
|
||||||
state: convertState(
|
state: convertState(
|
||||||
|
|
|
@ -337,6 +337,7 @@ const convertToJobAttempt = async (framework) => {
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
const totalTaskRoleNumber = framework.spec.taskRoles.length;
|
const totalTaskRoleNumber = framework.spec.taskRoles.length;
|
||||||
|
const jobPriority = framework.jobPriority;
|
||||||
const diagnostics = completionStatus ? completionStatus.diagnostics : null;
|
const diagnostics = completionStatus ? completionStatus.diagnostics : null;
|
||||||
const exitDiagnostics = generateExitDiagnostics(diagnostics);
|
const exitDiagnostics = generateExitDiagnostics(diagnostics);
|
||||||
const appExitTriggerMessage =
|
const appExitTriggerMessage =
|
||||||
|
@ -417,6 +418,7 @@ const convertToJobAttempt = async (framework) => {
|
||||||
totalGpuNumber,
|
totalGpuNumber,
|
||||||
totalTaskNumber,
|
totalTaskNumber,
|
||||||
totalTaskRoleNumber,
|
totalTaskRoleNumber,
|
||||||
|
jobPriority,
|
||||||
taskRoles,
|
taskRoles,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,11 +11,13 @@ class Filter {
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
keyword = '',
|
keyword = '',
|
||||||
|
priorities = new Set(),
|
||||||
users = new Set(),
|
users = new Set(),
|
||||||
virtualClusters = new Set(),
|
virtualClusters = new Set(),
|
||||||
statuses = new Set(),
|
statuses = new Set(),
|
||||||
) {
|
) {
|
||||||
this.keyword = keyword;
|
this.keyword = keyword;
|
||||||
|
this.priorities = priorities;
|
||||||
this.users = users;
|
this.users = users;
|
||||||
this.virtualClusters = virtualClusters;
|
this.virtualClusters = virtualClusters;
|
||||||
this.statuses = statuses;
|
this.statuses = statuses;
|
||||||
|
@ -26,6 +28,7 @@ class Filter {
|
||||||
save() {
|
save() {
|
||||||
const content = JSON.stringify({
|
const content = JSON.stringify({
|
||||||
users: Array.from(this.users),
|
users: Array.from(this.users),
|
||||||
|
priorities: Array.from(this.priorities),
|
||||||
virtualClusters: Array.from(this.virtualClusters),
|
virtualClusters: Array.from(this.virtualClusters),
|
||||||
statuses: Array.from(this.statuses),
|
statuses: Array.from(this.statuses),
|
||||||
keyword: this.keyword,
|
keyword: this.keyword,
|
||||||
|
@ -36,10 +39,19 @@ class Filter {
|
||||||
load() {
|
load() {
|
||||||
try {
|
try {
|
||||||
const content = window.localStorage.getItem(LOCAL_STORAGE_KEY);
|
const content = window.localStorage.getItem(LOCAL_STORAGE_KEY);
|
||||||
const { users, virtualClusters, statuses, keyword } = JSON.parse(content);
|
const {
|
||||||
|
priorities,
|
||||||
|
users,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
keyword,
|
||||||
|
} = JSON.parse(content);
|
||||||
if (Array.isArray(users)) {
|
if (Array.isArray(users)) {
|
||||||
this.users = new Set(users);
|
this.users = new Set(users);
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(priorities)) {
|
||||||
|
this.priorities = new Set(priorities);
|
||||||
|
}
|
||||||
if (Array.isArray(virtualClusters)) {
|
if (Array.isArray(virtualClusters)) {
|
||||||
this.virtualClusters = new Set(virtualClusters);
|
this.virtualClusters = new Set(virtualClusters);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +65,7 @@ class Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply() {
|
apply() {
|
||||||
const { keyword, users, virtualClusters, statuses } = this;
|
const { keyword, priorities, users, virtualClusters, statuses } = this;
|
||||||
|
|
||||||
const query = {};
|
const query = {};
|
||||||
if (keyword && keyword !== '') {
|
if (keyword && keyword !== '') {
|
||||||
|
@ -62,6 +74,22 @@ class Filter {
|
||||||
if (users && users.size > 0) {
|
if (users && users.size > 0) {
|
||||||
query.username = Array.from(users).join(',');
|
query.username = Array.from(users).join(',');
|
||||||
}
|
}
|
||||||
|
if (priorities && priorities.size > 0) {
|
||||||
|
query.jobPriority = Array.from(priorities)
|
||||||
|
.map(priority => {
|
||||||
|
switch (priority) {
|
||||||
|
case 'Opportunistic':
|
||||||
|
return 'oppo';
|
||||||
|
case 'Product':
|
||||||
|
return 'prod';
|
||||||
|
case 'Test':
|
||||||
|
return 'test';
|
||||||
|
default:
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join(',');
|
||||||
|
}
|
||||||
if (virtualClusters && virtualClusters.size > 0) {
|
if (virtualClusters && virtualClusters.size > 0) {
|
||||||
query.vc = Array.from(virtualClusters).join(',');
|
query.vc = Array.from(virtualClusters).join(',');
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ export default class Ordering {
|
||||||
'status',
|
'status',
|
||||||
'taskCount',
|
'taskCount',
|
||||||
'gpuCount',
|
'gpuCount',
|
||||||
|
'jobPriority',
|
||||||
].includes(field)
|
].includes(field)
|
||||||
) {
|
) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
|
@ -78,6 +79,8 @@ export default class Ordering {
|
||||||
query = 'totalTaskNumber';
|
query = 'totalTaskNumber';
|
||||||
} else if (field === 'gpuCount') {
|
} else if (field === 'gpuCount') {
|
||||||
query = 'totalGpuNumber';
|
query = 'totalGpuNumber';
|
||||||
|
} else if (field === 'jobPriority') {
|
||||||
|
query = 'jobPriority';
|
||||||
}
|
}
|
||||||
|
|
||||||
return { order: `${query},${descending ? 'DESC' : 'ASC'}` };
|
return { order: `${query},${descending ? 'DESC' : 'ASC'}` };
|
||||||
|
|
|
@ -187,6 +187,26 @@ export default function Table() {
|
||||||
headerClassName: FontClassNames.medium,
|
headerClassName: FontClassNames.medium,
|
||||||
isResizable: true,
|
isResizable: true,
|
||||||
});
|
});
|
||||||
|
const priorityColumn = applySortProps({
|
||||||
|
key: 'jobPriority',
|
||||||
|
minWidth: 95,
|
||||||
|
name: 'Priority',
|
||||||
|
className: FontClassNames.mediumPlus,
|
||||||
|
headerClassName: FontClassNames.medium,
|
||||||
|
isResizable: true,
|
||||||
|
onRender(job) {
|
||||||
|
switch (job.jobPriority) {
|
||||||
|
case 'oppo':
|
||||||
|
return 'Opportunistic';
|
||||||
|
case 'test':
|
||||||
|
return 'Test';
|
||||||
|
case 'prod':
|
||||||
|
return 'Product';
|
||||||
|
default:
|
||||||
|
return 'Default';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
const statusColumn = applySortProps({
|
const statusColumn = applySortProps({
|
||||||
key: 'status',
|
key: 'status',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
|
@ -272,6 +292,7 @@ export default function Table() {
|
||||||
retriesColumn,
|
retriesColumn,
|
||||||
taskCountColumn,
|
taskCountColumn,
|
||||||
gpuCountColumn,
|
gpuCountColumn,
|
||||||
|
priorityColumn,
|
||||||
statusColumn,
|
statusColumn,
|
||||||
actionsColumn,
|
actionsColumn,
|
||||||
];
|
];
|
||||||
|
|
|
@ -41,8 +41,14 @@ function KeywordSearchBox() {
|
||||||
const { filter, setFilter } = useContext(Context);
|
const { filter, setFilter } = useContext(Context);
|
||||||
|
|
||||||
function onKeywordChange(keyword) {
|
function onKeywordChange(keyword) {
|
||||||
const { users, virtualClusters, statuses } = filter;
|
const { priorities, users, virtualClusters, statuses } = filter;
|
||||||
const newFilter = new Filter(keyword, users, virtualClusters, statuses);
|
const newFilter = new Filter(
|
||||||
|
keyword,
|
||||||
|
priorities,
|
||||||
|
users,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
);
|
||||||
setFilter(newFilter);
|
setFilter(newFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +82,13 @@ function TopBar() {
|
||||||
Failed: true,
|
Failed: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const priorityItems = {
|
||||||
|
Product: true,
|
||||||
|
Test: true,
|
||||||
|
Opportunistic: true,
|
||||||
|
Default: true,
|
||||||
|
};
|
||||||
|
|
||||||
const { refreshJobs, selectedJobs, stopJob, filter, setFilter } = useContext(
|
const { refreshJobs, selectedJobs, stopJob, filter, setFilter } = useContext(
|
||||||
Context,
|
Context,
|
||||||
);
|
);
|
||||||
|
@ -127,11 +140,17 @@ function TopBar() {
|
||||||
}
|
}
|
||||||
setVirtualClusters(vcs);
|
setVirtualClusters(vcs);
|
||||||
const allValidVC = Object.keys(data);
|
const allValidVC = Object.keys(data);
|
||||||
const { keyword, users, virtualClusters, statuses } = filter;
|
const {
|
||||||
|
keyword,
|
||||||
|
priorities,
|
||||||
|
users,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
} = filter;
|
||||||
const filterVC = new Set(
|
const filterVC = new Set(
|
||||||
allValidVC.filter(vc => virtualClusters.has(vc)),
|
allValidVC.filter(vc => virtualClusters.has(vc)),
|
||||||
);
|
);
|
||||||
setFilter(new Filter(keyword, users, filterVC, statuses));
|
setFilter(new Filter(keyword, priorities, users, filterVC, statuses));
|
||||||
} else {
|
} else {
|
||||||
const data = await response.json().catch(() => {
|
const data = await response.json().catch(() => {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -289,6 +308,33 @@ function TopBar() {
|
||||||
>
|
>
|
||||||
<KeywordSearchBox />
|
<KeywordSearchBox />
|
||||||
<Stack horizontal>
|
<Stack horizontal>
|
||||||
|
<FilterButton
|
||||||
|
styles={{ root: { backgroundColor: 'transparent' } }}
|
||||||
|
text='Priority'
|
||||||
|
iconProps={{ iconName: 'Sort' }}
|
||||||
|
items={Object.keys(priorityItems)}
|
||||||
|
selectedItems={Array.from(filter.priorities)}
|
||||||
|
onSelect={priorities => {
|
||||||
|
const {
|
||||||
|
keyword,
|
||||||
|
userFilter,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
} = filter;
|
||||||
|
const priorityFilter = new Set(priorities);
|
||||||
|
setFilter(
|
||||||
|
new Filter(
|
||||||
|
keyword,
|
||||||
|
priorityFilter,
|
||||||
|
userFilter,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
searchBox
|
||||||
|
clearButton
|
||||||
|
/>
|
||||||
<FilterButton
|
<FilterButton
|
||||||
styles={{ root: { backgroundColor: 'transparent' } }}
|
styles={{ root: { backgroundColor: 'transparent' } }}
|
||||||
text='User'
|
text='User'
|
||||||
|
@ -296,14 +342,25 @@ function TopBar() {
|
||||||
items={userItems}
|
items={userItems}
|
||||||
selectedItems={selectedItems}
|
selectedItems={selectedItems}
|
||||||
onSelect={users => {
|
onSelect={users => {
|
||||||
const { keyword, virtualClusters, statuses } = filter;
|
const {
|
||||||
|
keyword,
|
||||||
|
priorities,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
} = filter;
|
||||||
const userFilter = new Set(users);
|
const userFilter = new Set(users);
|
||||||
if (userFilter.has(CURRENT_USER_KEY)) {
|
if (userFilter.has(CURRENT_USER_KEY)) {
|
||||||
userFilter.delete(CURRENT_USER_KEY);
|
userFilter.delete(CURRENT_USER_KEY);
|
||||||
userFilter.add(currentUser);
|
userFilter.add(currentUser);
|
||||||
}
|
}
|
||||||
setFilter(
|
setFilter(
|
||||||
new Filter(keyword, userFilter, virtualClusters, statuses),
|
new Filter(
|
||||||
|
keyword,
|
||||||
|
priorities,
|
||||||
|
userFilter,
|
||||||
|
virtualClusters,
|
||||||
|
statuses,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
searchBox
|
searchBox
|
||||||
|
@ -316,10 +373,11 @@ function TopBar() {
|
||||||
items={Object.keys(virtualClusters)}
|
items={Object.keys(virtualClusters)}
|
||||||
selectedItems={Array.from(filter.virtualClusters)}
|
selectedItems={Array.from(filter.virtualClusters)}
|
||||||
onSelect={virtualClusters => {
|
onSelect={virtualClusters => {
|
||||||
const { keyword, users, statuses } = filter;
|
const { keyword, priorities, users, statuses } = filter;
|
||||||
setFilter(
|
setFilter(
|
||||||
new Filter(
|
new Filter(
|
||||||
keyword,
|
keyword,
|
||||||
|
priorities,
|
||||||
users,
|
users,
|
||||||
new Set(virtualClusters),
|
new Set(virtualClusters),
|
||||||
statuses,
|
statuses,
|
||||||
|
@ -335,10 +393,11 @@ function TopBar() {
|
||||||
items={Object.keys(statuses)}
|
items={Object.keys(statuses)}
|
||||||
selectedItems={Array.from(filter.statuses)}
|
selectedItems={Array.from(filter.statuses)}
|
||||||
onSelect={statuses => {
|
onSelect={statuses => {
|
||||||
const { keyword, users, virtualClusters } = filter;
|
const { keyword, priorities, users, virtualClusters } = filter;
|
||||||
setFilter(
|
setFilter(
|
||||||
new Filter(
|
new Filter(
|
||||||
keyword,
|
keyword,
|
||||||
|
priorities,
|
||||||
users,
|
users,
|
||||||
virtualClusters,
|
virtualClusters,
|
||||||
new Set(statuses),
|
new Set(statuses),
|
||||||
|
|
|
@ -44,7 +44,11 @@ export default function JobList() {
|
||||||
|
|
||||||
const initialFilter = useMemo(() => {
|
const initialFilter = useMemo(() => {
|
||||||
const query = querystring.parse(location.search.replace(/^\?/, ''));
|
const query = querystring.parse(location.search.replace(/^\?/, ''));
|
||||||
if (['vcName', 'status', 'user', 'keyword'].some(x => !isEmpty(query[x]))) {
|
if (
|
||||||
|
['vcName', 'status', 'user', 'jobPriority', 'keyword'].some(
|
||||||
|
x => !isEmpty(query[x]),
|
||||||
|
)
|
||||||
|
) {
|
||||||
const queryFilter = new Filter();
|
const queryFilter = new Filter();
|
||||||
if (query.vcName) {
|
if (query.vcName) {
|
||||||
queryFilter.virtualClusters = new Set([query.vcName]);
|
queryFilter.virtualClusters = new Set([query.vcName]);
|
||||||
|
@ -55,6 +59,9 @@ export default function JobList() {
|
||||||
if (query.user) {
|
if (query.user) {
|
||||||
queryFilter.users = new Set([query.user]);
|
queryFilter.users = new Set([query.user]);
|
||||||
}
|
}
|
||||||
|
if (query.jobPriority) {
|
||||||
|
queryFilter.priorities = new Set([query.jobPriority]);
|
||||||
|
}
|
||||||
if (query.keyword) {
|
if (query.keyword) {
|
||||||
queryFilter.keyword = query.user;
|
queryFilter.keyword = query.user;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче