Skip to content
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
628e71d
Save example queue - does not return to robot page for some reason
noemifrisina May 26, 2026
f90ab19
Add daq queue to helm chart
noemifrisina May 27, 2026
1cc9276
Save basic query for interrogating the queue
noemifrisina May 27, 2026
c0a9717
A first displayed queue
noemifrisina May 27, 2026
7d9d847
Tidy up and add colour to chips
noemifrisina May 27, 2026
766ac30
Display plan parameters as a string and add a comment about it
noemifrisina May 27, 2026
ff7585e
Fix typing in test
noemifrisina May 28, 2026
f0bbc56
Actually save the patch queue state
noemifrisina May 28, 2026
8423d9f
Add generated types from queue fastapi
jacob720 May 28, 2026
19f7ee6
Update generated queue types
jacob720 May 28, 2026
a8a0161
Add script to generate queue types
jacob720 May 28, 2026
0e7c48e
Update mock data
jacob720 May 28, 2026
380459a
Add pause queue toggle button
jacob720 May 28, 2026
ef8f904
Use SSE to get event driven updates
jacob720 May 29, 2026
4842f66
Add button to cancel tasks
jacob720 May 29, 2026
c00f0be
Allow re-ordering of tasks
jacob720 May 29, 2026
9165e79
Add toggle to show historic tasks and button to delete history
jacob720 May 29, 2026
1c957fc
Fix move task logic
jacob720 May 29, 2026
70ebbf1
Disable clear history button unless historic tasks shown
jacob720 Jun 1, 2026
6fc8aab
Use more up to date node image for dev container
jacob720 Jun 1, 2026
ad76f2c
Rename pause queue component
jacob720 Jun 1, 2026
b975de0
Only make tasks draggable if status is 'Queued'
jacob720 Jun 2, 2026
eabc095
Don't display task ID
jacob720 Jun 2, 2026
1b56518
PR suggestion
jacob720 Jun 2, 2026
b3b2697
Have a local queue server dev mode
jacob720 Jun 2, 2026
263faa7
Improve docs
jacob720 Jun 2, 2026
62ee74b
Link to issue about displaying params
jacob720 Jun 3, 2026
eaf1247
Display when not connected to queue
jacob720 Jun 4, 2026
89ec400
Small change
jacob720 Jun 4, 2026
d0966f9
Put queue status panel inside table bar
jacob720 Jun 4, 2026
b3f2e4b
Add tests WIP
jacob720 Jun 4, 2026
16922b0
Add tests for queue status panel
jacob720 Jun 4, 2026
6ea2328
Make queue pause button smaller
jacob720 Jun 4, 2026
a8b173a
Add tests for QueueView
jacob720 Jun 8, 2026
e9bbded
Put move logic in a helper function
jacob720 Jun 8, 2026
766aec7
Add test for new position calculation
jacob720 Jun 8, 2026
03c13b8
Fix lint
jacob720 Jun 8, 2026
3b54cb1
Fix bug
jacob720 Jun 8, 2026
bfdf52b
Fix some lint issues
jacob720 Jun 9, 2026
a9b726e
PR comments
jacob720 Jun 10, 2026
b1660b3
Fix lockfile
jacob720 Jun 10, 2026
15b20d1
Merge branch 'main' into 1625-display-queue
jacob720 Jun 10, 2026
fcf191f
Fix lint in tests
jacob720 Jun 10, 2026
9e29162
Move generated folder
jacob720 Jun 10, 2026
ffa221a
Ignore lint for generated code
jacob720 Jun 10, 2026
5f1f547
Try to fix deployed UI
jacob720 Jun 10, 2026
25ce7bc
Revert unneeded fix
jacob720 Jun 10, 2026
14be2f3
Remove .devcontainer/devcontainer-lock.json
jacob720 Jun 11, 2026
198474d
PR comments
jacob720 Jun 11, 2026
47d17f1
Fix the mocks for the history of the queue
DominicOram Jun 12, 2026
92151ca
Fix typo for endpoint
DominicOram Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ dist-ssr
*.njsproj
*.sln
*.sw?
.devcontainer/*lock.json
**/.devcontainer/*lock.json

# Turborepo
.turbo
Expand Down
8 changes: 5 additions & 3 deletions apps/i15-1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The initial aim of this app to provide a science facing UI for the waffle projec
To run this locally:

1. Start the devcontainer in VSCode
1. To make sure you have the most up-to-date environment either run `pnpm install` in the container or rebuild the container (via the Ctrl+Shift+P menu in VSCode)
1. Run `turbo dev --filter @atlas/i15-1`
1. Navigate to http://localhost:5173/
2. To make sure you have the most up-to-date environment either run `pnpm install` in the container or rebuild the container (via the Ctrl+Shift+P menu in VSCode)
3. In a terminal in this devcontainer run either:
- `VITE_QUEUE_MODE=local turbo dev --filter @atlas/i15-1` if running a local queue server on http://127.0.0.1:8001, **OR**
- `turbo dev --filter @atlas/i15-1` to use mocked backends
4. Navigate to http://localhost:5173/
2 changes: 1 addition & 1 deletion apps/i15-1/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { globalIgnores } from "eslint/config";
import { defineConfig } from "eslint/config";

export default defineConfig([
globalIgnores(["dist"]),
globalIgnores(["dist", "generated"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
Expand Down
16 changes: 16 additions & 0 deletions apps/i15-1/generated/queue/client.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// This file is auto-generated by @hey-api/openapi-ts

import { type Client, type ClientOptions, type Config, createClient, createConfig } from './client';
import type { ClientOptions as ClientOptions2 } from './types.gen';

/**
* The `createClientConfig()` function will be called on client initialization
* and the returned object will become the client's initial configuration.
*
* You may want to initialize your client this way instead of calling
* `setConfig()`. This is useful for example if you're using Next.js
* to ensure your client always has the correct values.
*/
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;

export const client: Client = createClient(createConfig<ClientOptions2>({ baseUrl: 'https://raw.githubusercontent.com' }));
277 changes: 277 additions & 0 deletions apps/i15-1/generated/queue/client/client.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
// This file is auto-generated by @hey-api/openapi-ts

import { createSseClient } from '../core/serverSentEvents.gen';
import type { HttpMethod } from '../core/types.gen';
import { getValidRequestBody } from '../core/utils.gen';
import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
import {
buildUrl,
createConfig,
createInterceptors,
getParseAs,
mergeConfigs,
mergeHeaders,
setAuthParams,
} from './utils.gen';

type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
body?: any;
headers: ReturnType<typeof mergeHeaders>;
};

export const createClient = (config: Config = {}): Client => {
let _config = mergeConfigs(createConfig(), config);

const getConfig = (): Config => ({ ..._config });

const setConfig = (config: Config): Config => {
_config = mergeConfigs(_config, config);
return getConfig();
};

const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();

const beforeRequest = async <
TData = unknown,
TResponseStyle extends 'data' | 'fields' = 'fields',
ThrowOnError extends boolean = boolean,
Url extends string = string,
>(
options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
) => {
const opts = {
..._config,
...options,
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
headers: mergeHeaders(_config.headers, options.headers),
serializedBody: undefined as string | undefined,
};

if (opts.security) {
await setAuthParams(opts);
}

if (opts.requestValidator) {
await opts.requestValidator(opts);
}

if (opts.body !== undefined && opts.bodySerializer) {
opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;
}

// remove Content-Type header if body is empty to avoid sending invalid requests
if (opts.body === undefined || opts.serializedBody === '') {
opts.headers.delete('Content-Type');
}

const resolvedOpts = opts as typeof opts &
ResolvedRequestOptions<TResponseStyle, ThrowOnError, Url>;
const url = buildUrl(resolvedOpts);

return { opts: resolvedOpts, url };
};

const request: Client['request'] = async (options) => {
const throwOnError = options.throwOnError ?? _config.throwOnError;
const responseStyle = options.responseStyle ?? _config.responseStyle;

let request: Request | undefined;
let response: Response | undefined;

try {
const { opts, url } = await beforeRequest(options);
const requestInit: ReqInit = {
redirect: 'follow',
...opts,
body: getValidRequestBody(opts),
};

request = new Request(url, requestInit);

for (const fn of interceptors.request.fns) {
if (fn) {
request = await fn(request, opts);
}
}

// fetch must be assigned here, otherwise it would throw the error:
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
const _fetch = opts.fetch!;

response = await _fetch(request);

for (const fn of interceptors.response.fns) {
if (fn) {
response = await fn(response, request, opts);
}
}

const result = {
request,
response,
};

if (response.ok) {
const parseAs =
(opts.parseAs === 'auto'
? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json';

if (response.status === 204 || response.headers.get('Content-Length') === '0') {
let emptyData: any;
switch (parseAs) {
case 'arrayBuffer':
case 'blob':
case 'text':
emptyData = await response[parseAs]();
break;
case 'formData':
emptyData = new FormData();
break;
case 'stream':
emptyData = response.body;
break;
case 'json':
default:
emptyData = {};
break;
}
return opts.responseStyle === 'data'
? emptyData
: {
data: emptyData,
...result,
};
}

let data: any;
switch (parseAs) {
case 'arrayBuffer':
case 'blob':
case 'formData':
case 'text':
data = await response[parseAs]();
break;
case 'json': {
// Some servers return 200 with no Content-Length and empty body.
// response.json() would throw; read as text and parse if non-empty.
const text = await response.text();
data = text ? JSON.parse(text) : {};
break;
}
case 'stream':
return opts.responseStyle === 'data'
? response.body
: {
data: response.body,
...result,
};
}

if (parseAs === 'json') {
if (opts.responseValidator) {
await opts.responseValidator(data);
}

if (opts.responseTransformer) {
data = await opts.responseTransformer(data);
}
}

return opts.responseStyle === 'data'
? data
: {
data,
...result,
};
}

const textError = await response.text();
let jsonError: unknown;

try {
jsonError = JSON.parse(textError);
} catch {
// noop
}

throw jsonError ?? textError;
} catch (error) {
let finalError = error;

for (const fn of interceptors.error.fns) {
if (fn) {
finalError = await fn(finalError, response, request, options as ResolvedRequestOptions);
}
}

finalError = finalError || {};

if (throwOnError) {
throw finalError;
}

// TODO: we probably want to return error and improve types
return responseStyle === 'data'
? undefined
: {
error: finalError,
request,
response,
};
}
};

const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
request({ ...options, method });

const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
const { opts, url } = await beforeRequest(options);
return createSseClient({
...opts,
body: opts.body as BodyInit | null | undefined,
method,
onRequest: async (url, init) => {
let request = new Request(url, init);
for (const fn of interceptors.request.fns) {
if (fn) {
request = await fn(request, opts);
}
}
return request;
},
serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
url,
});
};

const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });

return {
buildUrl: _buildUrl,
connect: makeMethodFn('CONNECT'),
delete: makeMethodFn('DELETE'),
get: makeMethodFn('GET'),
getConfig,
head: makeMethodFn('HEAD'),
interceptors,
options: makeMethodFn('OPTIONS'),
patch: makeMethodFn('PATCH'),
post: makeMethodFn('POST'),
put: makeMethodFn('PUT'),
request,
setConfig,
sse: {
connect: makeSseFn('CONNECT'),
delete: makeSseFn('DELETE'),
get: makeSseFn('GET'),
head: makeSseFn('HEAD'),
options: makeSseFn('OPTIONS'),
patch: makeSseFn('PATCH'),
post: makeSseFn('POST'),
put: makeSseFn('PUT'),
trace: makeSseFn('TRACE'),
},
trace: makeMethodFn('TRACE'),
} as Client;
};
27 changes: 27 additions & 0 deletions apps/i15-1/generated/queue/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This file is auto-generated by @hey-api/openapi-ts

export type { Auth } from '../core/auth.gen';
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
export {
formDataBodySerializer,
jsonBodySerializer,
urlSearchParamsBodySerializer,
} from '../core/bodySerializer.gen';
export { buildClientParams } from '../core/params.gen';
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
export type { ClientMeta } from '../core/types.gen';
export { createClient } from './client.gen';
export type {
Client,
ClientOptions,
Config,
CreateClientConfig,
Options,
RequestOptions,
RequestResult,
ResolvedRequestOptions,
ResponseStyle,
TDataShape,
} from './types.gen';
export { createConfig, mergeHeaders } from './utils.gen';
Loading
Loading