diff --git a/CHANGELOG-more-workspace-api-exercise.md b/CHANGELOG-more-workspace-api-exercise.md new file mode 100644 index 0000000000..9a98738d80 --- /dev/null +++ b/CHANGELOG-more-workspace-api-exercise.md @@ -0,0 +1 @@ +- Demostrate the Workspaces API to start jobs and collect job information. diff --git a/context/app/static/js/components/workspaces/WorkspacesList.jsx b/context/app/static/js/components/workspaces/WorkspacesList.jsx index 5087a720fd..3fc7783412 100644 --- a/context/app/static/js/components/workspaces/WorkspacesList.jsx +++ b/context/app/static/js/components/workspaces/WorkspacesList.jsx @@ -6,37 +6,53 @@ import { AppContext } from 'js/components/Providers'; import { DeleteIcon, AddIcon } from 'js/shared-styles/icons'; import { SpacedSectionButtonRow } from 'js/shared-styles/sections/SectionButtonRow'; -import { createNotebookWorkspace } from './utils'; -import { useWorkspacesList } from './hooks'; +import { createNotebookWorkspace, startJob } from './utils'; +import { useWorkspacesList, useJobsList } from './hooks'; import { StyledButton } from './style'; function WorkspacesList() { const { workspacesEndpoint, workspacesToken } = useContext(AppContext); const { workspacesList } = useWorkspacesList(); + const { jobsList } = useJobsList(); async function handleDelete() { + // eslint-disable-next-line no-alert + alert('TODO: API does not yet support deletion.'); // TODO: Put up modal and get user input. // TODO: Update workspacesList // Waiting on delete to be implemented. } async function handleCreate() { - // TODO: Put up modal and get user input. - // TODO: Update workspacesList + // TODO: Put up a better modal and get user input. + // eslint-disable-next-line no-alert + const content = prompt('Intial content for notebook'); createNotebookWorkspace({ workspacesEndpoint, workspacesToken, workspaceName: 'Workspace Timestamp', workspaceDescription: 'TODO: description', - notebookContent: 'TODO', + notebookContent: content, }); + // TODO: Update list on page + } + + function createHandleStart(workspaceId) { + async function handleStart() { + startJob({ workspaceId, workspacesEndpoint, workspacesToken }); + } + return handleStart; } return ( <> [TODO: Count] Workspaces} + leftText={ + + {workspacesList.length} Workspace{workspacesList.length && 's'} + + } buttons={ <> @@ -49,9 +65,32 @@ function WorkspacesList() { } /> - {`TODO: Use token "${workspacesToken}" with "${workspacesEndpoint}"`} -
- {JSON.stringify(workspacesList)} + {workspacesList.map((workspace) => ( +
+
+ JSON +
{JSON.stringify(workspace, null, 2)}
+
+
+ {workspace.name} | Created {workspace.datetime_created.slice(0, 10)} +
+ +
+ ))} +
+ Jobs} /> + + TODO: The current API responses give us no way to connect Workspaces to Jobs. + {jobsList.map((job) => ( +
+
+ JSON +
{JSON.stringify(job, null, 2)}
+
+
+ ))}
); diff --git a/context/app/static/js/components/workspaces/hooks.js b/context/app/static/js/components/workspaces/hooks.js index a533fba8fa..8f92458396 100644 --- a/context/app/static/js/components/workspaces/hooks.js +++ b/context/app/static/js/components/workspaces/hooks.js @@ -25,7 +25,7 @@ function useWorkspacesList() { } const results = await response.json(); - setWorkspacesList(results); + setWorkspacesList(results.data.workspaces); // TODO: // setIsLoading(false); } @@ -35,4 +35,36 @@ function useWorkspacesList() { return { workspacesList }; } -export { useWorkspacesList }; +function useJobsList() { + // TODO: Right now the API does not support querying, so we just need to get the whole list. + const [jobsList, setJobsList] = useState([]); + + const { workspacesEndpoint, workspacesToken } = useContext(AppContext); + + useEffect(() => { + async function getAndSetJobsList() { + const response = await fetch(`${workspacesEndpoint}/jobs`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'UWS-Authorization': `Token ${workspacesToken}`, + }, + }); + + if (!response.ok) { + console.error('Workspaces API failed', response); + return; + } + const results = await response.json(); + + setJobsList(results.data.jobs); + // TODO: + // setIsLoading(false); + } + getAndSetJobsList(); + }, [workspacesEndpoint, workspacesToken]); + + return { jobsList }; +} + +export { useWorkspacesList, useJobsList }; diff --git a/context/app/static/js/components/workspaces/utils.js b/context/app/static/js/components/workspaces/utils.js index 4ba7589132..a41a1350b8 100644 --- a/context/app/static/js/components/workspaces/utils.js +++ b/context/app/static/js/components/workspaces/utils.js @@ -27,4 +27,18 @@ async function createNotebookWorkspace({ }); } -export { createNotebookWorkspace }; +async function startJob({ workspaceId, workspacesEndpoint, workspacesToken }) { + await fetch(`${workspacesEndpoint}/workspaces/${workspaceId}/start`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'UWS-Authorization': `Token ${workspacesToken}`, + }, + body: JSON.stringify({ + job_type: 'JupyterLabJob', + job_details: {}, + }), + }); +} + +export { createNotebookWorkspace, startJob };