Skip to content

Commit 3ae5e3f

Browse files
sathishlxgSathish Kumar Thangaraj
andauthored
Jupyterlab Workflows frontend plugin initial commit (#526)
* Jupyterlab Workflows frontend plugin initial commit * Fix minor UI issues and refactor duplicate styled components --------- Co-authored-by: Sathish Kumar Thangaraj <sathishlxg@gmail.com>
1 parent 7cf42f9 commit 3ae5e3f

File tree

102 files changed

+19902
-5300
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+19902
-5300
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dist
33
coverage
44
**/*.d.ts
55
tests
6+
lib
67

78
**/__tests__
89
ui-tests

package.json

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
"@emotion/styled": "^11.10.4",
6060
"@jupyterlab/application": "^4",
6161
"@jupyterlab/apputils": "^4",
62+
"@jupyterlab/codeeditor": "^4",
63+
"@jupyterlab/codemirror": "^4",
6264
"@jupyterlab/coreutils": "^6",
6365
"@jupyterlab/filebrowser": "^4",
6466
"@jupyterlab/launcher": "^4",
@@ -72,21 +74,35 @@
7274
"@mui/icons-material": "^5.10.9",
7375
"@mui/material": "^5.10.6",
7476
"@mui/system": "^5.10.6",
77+
"@mui/x-date-pickers": "^6.19.3",
7578
"@types/react-dom": "^18.0.5",
7679
"cronstrue": "^2.12.0",
80+
"elkjs": "^0.9.1",
81+
"email-validator": "^2.0.4",
82+
"lodash": "^4.17.21",
83+
"moment": "^2.30.1",
84+
"nanoid": "^3.3.7",
7785
"react": "^18.2.0",
7886
"react-dom": "^18.2.0",
79-
"tzdata": "^1.0.33"
87+
"react-hook-form": "^7.50.1",
88+
"react-resizable-panels": "^2.0.9",
89+
"react-router-dom": "^6.22.0",
90+
"react-show-more-text": "^1.7.1",
91+
"reactflow": "^11.10.3",
92+
"tzdata": "^1.0.33",
93+
"zustand": "^4.5.0"
8094
},
8195
"devDependencies": {
8296
"@babel/core": "^7.0.0",
8397
"@babel/preset-env": "^7.0.0",
8498
"@jupyterlab/builder": "^4",
8599
"@jupyterlab/testutils": "^4",
86100
"@types/jest": "^29",
87-
"@typescript-eslint/eslint-plugin": "^4.8.1",
88-
"@typescript-eslint/parser": "^4.8.1",
89-
"eslint": "^7.14.0",
101+
"@types/lodash": "4.14.192",
102+
"@types/react-show-more-text": "^1.4.5",
103+
"@typescript-eslint/eslint-plugin": "^7.12.0",
104+
"@typescript-eslint/parser": "^7.12.0",
105+
"eslint": "^8.57.0",
90106
"eslint-config-prettier": "^6.15.0",
91107
"eslint-plugin-prettier": "^3.1.4",
92108
"jest": "^29",
@@ -100,7 +116,8 @@
100116
"stylelint-config-standard": "~24.0.0",
101117
"stylelint-prettier": "^2.0.0",
102118
"ts-jest": "^29",
103-
"typescript": "~4.3.0"
119+
"typescript": "~5.1.6",
120+
"zustand-types": "^0.1.0"
104121
},
105122
"resolutions": {
106123
"@types/react": "^17.0.1",

schema/plugin.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
"command": "scheduling:create-from-filebrowser",
99
"selector": ".jp-DirListing-item[data-file-type=\"notebook\"]",
1010
"rank": 3.9
11+
},
12+
{
13+
"command": "workflows:create-from-filebrowser",
14+
"selector": ".jp-DirListing-item[data-file-type=\"notebook\"]",
15+
"rank": 4
1116
}
1217
]
1318
},
@@ -17,6 +22,11 @@
1722
"name": "create-job",
1823
"command": "scheduling:create-from-notebook",
1924
"rank": 46
25+
},
26+
{
27+
"name": "create-workflow",
28+
"command": "workflows:create-from-notebook",
29+
"rank": 47
2030
}
2131
]
2232
},
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React from 'react';
2+
import { caretDownIcon, caretUpIcon, LabIcon } from '@jupyterlab/ui-components';
3+
import TableHead from '@mui/material/TableHead';
4+
import TableCell from '@mui/material/TableCell';
5+
6+
import { AdvancedTableColumn, AdvancedTableQuery } from './advanced-table';
7+
import { Scheduler } from '../../handler';
8+
9+
type AdvancedTableHeaderProps<Q extends AdvancedTableQuery> = {
10+
columns: AdvancedTableColumn[];
11+
query: Q;
12+
setQuery: React.Dispatch<React.SetStateAction<Q>>;
13+
};
14+
15+
export function AdvancedTableHeader<Q extends AdvancedTableQuery>(
16+
props: AdvancedTableHeaderProps<Q>
17+
): JSX.Element {
18+
return (
19+
<TableHead>
20+
{props.columns.map((column, idx) => (
21+
<AdvancedTableHeaderCell
22+
key={idx}
23+
column={column}
24+
query={props.query}
25+
setQuery={props.setQuery}
26+
/>
27+
))}
28+
</TableHead>
29+
);
30+
}
31+
32+
const sortAscendingIcon = (
33+
<LabIcon.resolveReact icon={caretUpIcon} tag="span" />
34+
);
35+
const sortDescendingIcon = (
36+
<LabIcon.resolveReact icon={caretDownIcon} tag="span" />
37+
);
38+
39+
type AdvancedTableHeaderCellProps<Q extends AdvancedTableQuery> = Pick<
40+
AdvancedTableHeaderProps<Q>,
41+
'query' | 'setQuery'
42+
> & {
43+
column: AdvancedTableColumn;
44+
};
45+
46+
function AdvancedTableHeaderCell<Q extends AdvancedTableQuery>(
47+
props: AdvancedTableHeaderCellProps<Q>
48+
): JSX.Element {
49+
const sort = props.query.sort_by;
50+
const defaultSort = sort?.[0];
51+
52+
const headerIsDefaultSort =
53+
defaultSort && defaultSort.name === props.column.sortField;
54+
const isSortedAscending =
55+
headerIsDefaultSort &&
56+
defaultSort &&
57+
defaultSort.direction === Scheduler.SortDirection.ASC;
58+
const isSortedDescending =
59+
headerIsDefaultSort &&
60+
defaultSort &&
61+
defaultSort.direction === Scheduler.SortDirection.DESC;
62+
63+
const sortByThisColumn = () => {
64+
// If this field is not sortable, do nothing.
65+
if (!props.column.sortField) {
66+
return;
67+
}
68+
69+
// Change the sort of this column.
70+
// If not sorted at all or if sorted descending, sort ascending. If sorted ascending, sort descending.
71+
const newSortDirection = isSortedAscending
72+
? Scheduler.SortDirection.DESC
73+
: Scheduler.SortDirection.ASC;
74+
75+
// Set the new sort direction.
76+
const newSort: Scheduler.ISortField = {
77+
name: props.column.sortField,
78+
direction: newSortDirection
79+
};
80+
81+
// If this field is already present in the sort list, remove it.
82+
const oldSortList = sort || [];
83+
const newSortList = [
84+
newSort,
85+
...oldSortList.filter(item => item.name !== props.column.sortField)
86+
];
87+
88+
// Sub the new sort list in to the query.
89+
props.setQuery(query => ({ ...query, sort_by: newSortList }));
90+
};
91+
92+
return (
93+
<TableCell
94+
onClick={sortByThisColumn}
95+
sx={props.column.sortField ? { cursor: 'pointer' } : {}}
96+
>
97+
{props.column.name}
98+
{isSortedAscending && sortAscendingIcon}
99+
{isSortedDescending && sortDescendingIcon}
100+
</TableCell>
101+
);
102+
}

0 commit comments

Comments
 (0)