Skip to content

Commit 4a18444

Browse files
committed
Add generated clients for Logos and Icons
Signed-off-by: Charles Thao <[email protected]>
1 parent b02953a commit 4a18444

File tree

7 files changed

+120
-24
lines changed

7 files changed

+120
-24
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4f0a29dec0d3c9f0d0f02caab4dc84101bfef8b0
1+
ec35a7c28bea82770c2f6af1ee35d3135114d451

workspaces/frontend/src/app/hooks/__tests__/useWorkspaceCountPerKind.spec.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ describe('useWorkspaceCountPerKind', () => {
6666
listWorkspaceKinds: mockListWorkspaceKinds,
6767
createWorkspaceKind: jest.fn(),
6868
getWorkspaceKind: jest.fn(),
69+
getWorkspaceKindIcon: jest.fn(),
70+
getWorkspaceKindLogo: jest.fn(),
6971
},
7072
};
7173

workspaces/frontend/src/app/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
2+
AssetsImageRef,
23
WorkspacekindsImageConfigValue,
3-
WorkspacekindsImageRef,
44
WorkspacekindsPodConfigValue,
55
WorkspacekindsPodMetadata,
66
WorkspacekindsPodVolumeMounts,
@@ -50,8 +50,8 @@ export interface WorkspaceKindProperties {
5050
deprecated: boolean;
5151
deprecationMessage: string;
5252
hidden: boolean;
53-
icon: WorkspacekindsImageRef;
54-
logo: WorkspacekindsImageRef;
53+
icon: AssetsImageRef;
54+
logo: AssetsImageRef;
5555
}
5656

5757
export interface WorkspaceKindImageConfigValue extends WorkspacekindsImageConfigValue {

workspaces/frontend/src/generated/Workspacekinds.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,42 @@ export class Workspacekinds<SecurityDataType = unknown> extends HttpClient<Secur
8686
format: 'json',
8787
...params,
8888
});
89+
/**
90+
* @description Returns the icon image for a specific workspace kind. If the icon is stored in a ConfigMap, it serves the image content. If the icon is a remote URL, returns 404 (browser should fetch directly).
91+
*
92+
* @tags workspacekinds
93+
* @name GetWorkspaceKindIcon
94+
* @summary Get workspace kind icon
95+
* @request GET:/workspacekinds/{name}/assets/icon.svg
96+
* @response `200` `string` SVG image content
97+
* @response `404` `ApiErrorEnvelope` Not Found. Icon uses remote URL or resource does not exist.
98+
* @response `500` `ApiErrorEnvelope` Internal server error.
99+
*/
100+
getWorkspaceKindIcon = (name: string, params: RequestParams = {}) =>
101+
this.request<string, ApiErrorEnvelope>({
102+
path: `/workspacekinds/${name}/assets/icon.svg`,
103+
method: 'GET',
104+
type: ContentType.Json,
105+
format: 'blob',
106+
...params,
107+
});
108+
/**
109+
* @description Returns the logo image for a specific workspace kind. If the logo is stored in a ConfigMap, it serves the image content. If the logo is a remote URL, returns 404 (browser should fetch directly).
110+
*
111+
* @tags workspacekinds
112+
* @name GetWorkspaceKindLogo
113+
* @summary Get workspace kind logo
114+
* @request GET:/workspacekinds/{name}/assets/logo.svg
115+
* @response `200` `string` SVG image content
116+
* @response `404` `ApiErrorEnvelope` Not Found. Logo uses remote URL or resource does not exist.
117+
* @response `500` `ApiErrorEnvelope` Internal server error.
118+
*/
119+
getWorkspaceKindLogo = (name: string, params: RequestParams = {}) =>
120+
this.request<string, ApiErrorEnvelope>({
121+
path: `/workspacekinds/${name}/assets/logo.svg`,
122+
method: 'GET',
123+
type: ContentType.Json,
124+
format: 'blob',
125+
...params,
126+
});
89127
}

workspaces/frontend/src/generated/Workspaces.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ export class Workspaces<SecurityDataType = unknown> extends HttpClient<SecurityD
4848
* @summary List workspaces by namespace
4949
* @request GET:/workspaces/{namespace}
5050
* @response `200` `ApiWorkspaceListEnvelope` Successful operation. Returns a list of workspaces in the specified namespace.
51-
* @response `400` `ApiErrorEnvelope` Bad Request. Invalid namespace format.
5251
* @response `401` `ApiErrorEnvelope` Unauthorized. Authentication is required.
5352
* @response `403` `ApiErrorEnvelope` Forbidden. User does not have permission to list workspaces.
53+
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Validation error.
5454
* @response `500` `ApiErrorEnvelope` Internal server error. An unexpected error occurred on the server.
5555
*/
5656
listWorkspacesByNamespace = (namespace: string, params: RequestParams = {}) =>
@@ -69,12 +69,13 @@ export class Workspaces<SecurityDataType = unknown> extends HttpClient<SecurityD
6969
* @summary Create workspace
7070
* @request POST:/workspaces/{namespace}
7171
* @response `201` `ApiWorkspaceEnvelope` Workspace created successfully
72-
* @response `400` `ApiErrorEnvelope` Bad Request. Invalid request body or namespace format.
72+
* @response `400` `ApiErrorEnvelope` Bad Request.
7373
* @response `401` `ApiErrorEnvelope` Unauthorized. Authentication is required.
7474
* @response `403` `ApiErrorEnvelope` Forbidden. User does not have permission to create workspace.
7575
* @response `409` `ApiErrorEnvelope` Conflict. Workspace with the same name already exists.
7676
* @response `413` `ApiErrorEnvelope` Request Entity Too Large. The request body is too large.
7777
* @response `415` `ApiErrorEnvelope` Unsupported Media Type. Content-Type header is not correct.
78+
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Validation error.
7879
* @response `500` `ApiErrorEnvelope` Internal server error. An unexpected error occurred on the server.
7980
*/
8081
createWorkspace = (
@@ -102,9 +103,10 @@ export class Workspaces<SecurityDataType = unknown> extends HttpClient<SecurityD
102103
* @response `401` `ApiErrorEnvelope` Unauthorized. Authentication is required.
103104
* @response `403` `ApiErrorEnvelope` Forbidden. User does not have permission to access the workspace.
104105
* @response `404` `ApiErrorEnvelope` Not Found. Workspace does not exist.
106+
* @response `409` `ApiErrorEnvelope` Conflict. Workspace not in valid state for action.
105107
* @response `413` `ApiErrorEnvelope` Request Entity Too Large. The request body is too large.
106108
* @response `415` `ApiErrorEnvelope` Unsupported Media Type. Content-Type header is not correct.
107-
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Workspace is not in appropriate state.
109+
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Validation error.
108110
* @response `500` `ApiErrorEnvelope` Internal server error. An unexpected error occurred on the server.
109111
*/
110112
updateWorkspacePauseState = (
@@ -129,10 +131,10 @@ export class Workspaces<SecurityDataType = unknown> extends HttpClient<SecurityD
129131
* @summary Get workspace
130132
* @request GET:/workspaces/{namespace}/{workspace_name}
131133
* @response `200` `ApiWorkspaceEnvelope` Successful operation. Returns the requested workspace details.
132-
* @response `400` `ApiErrorEnvelope` Bad Request. Invalid namespace or workspace name format.
133134
* @response `401` `ApiErrorEnvelope` Unauthorized. Authentication is required.
134135
* @response `403` `ApiErrorEnvelope` Forbidden. User does not have permission to access the workspace.
135136
* @response `404` `ApiErrorEnvelope` Not Found. Workspace does not exist.
137+
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Validation error.
136138
* @response `500` `ApiErrorEnvelope` Internal server error. An unexpected error occurred on the server.
137139
*/
138140
getWorkspace = (namespace: string, workspaceName: string, params: RequestParams = {}) =>
@@ -151,10 +153,10 @@ export class Workspaces<SecurityDataType = unknown> extends HttpClient<SecurityD
151153
* @summary Delete workspace
152154
* @request DELETE:/workspaces/{namespace}/{workspace_name}
153155
* @response `204` `void` Workspace deleted successfully
154-
* @response `400` `ApiErrorEnvelope` Bad Request. Invalid namespace or workspace name format.
155156
* @response `401` `ApiErrorEnvelope` Unauthorized. Authentication is required.
156157
* @response `403` `ApiErrorEnvelope` Forbidden. User does not have permission to delete the workspace.
157158
* @response `404` `ApiErrorEnvelope` Not Found. Workspace does not exist.
159+
* @response `422` `ApiErrorEnvelope` Unprocessable Entity. Validation error.
158160
* @response `500` `ApiErrorEnvelope` Internal server error. An unexpected error occurred on the server.
159161
*/
160162
deleteWorkspace = (namespace: string, workspaceName: string, params: RequestParams = {}) =>

workspaces/frontend/src/generated/data-contracts.ts

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,39 @@ export enum FieldErrorType {
5555
ErrorTypeTypeInvalid = 'FieldValueTypeInvalid',
5656
}
5757

58+
export enum AssetsImageRefErrorCode {
59+
ImageRefErrorCodeConfigMapMissing = 'CONFIGMAP_MISSING',
60+
ImageRefErrorCodeConfigMapKeyMissing = 'CONFIGMAP_KEY_MISSING',
61+
ImageRefErrorCodeConfigMapUnknown = 'CONFIGMAP_UNKNOWN',
62+
ImageRefErrorCodeUnknown = 'UNKNOWN',
63+
}
64+
65+
export enum ApiErrorCauseOrigin {
66+
OriginInternal = 'INTERNAL',
67+
OriginKubernetes = 'KUBERNETES',
68+
}
69+
5870
export interface ActionsWorkspaceActionPause {
5971
paused: boolean;
6072
}
6173

74+
export interface ApiConflictError {
75+
/**
76+
* A human-readable description of the cause of the error.
77+
* This field may be presented as-is to a reader.
78+
*/
79+
message?: string;
80+
/**
81+
* Origin indicates where the conflict error originated.
82+
* If value is empty, the origin is unknown.
83+
*/
84+
origin?: ApiErrorCauseOrigin;
85+
}
86+
6287
export interface ApiErrorCause {
88+
/** ConflictCauses contains details about conflict errors that caused the request to fail. */
89+
conflict_cause?: ApiConflictError[];
90+
/** ValidationErrors contains details about validation errors that caused the request to fail. */
6391
validation_errors?: ApiValidationError[];
6492
}
6593

@@ -68,8 +96,11 @@ export interface ApiErrorEnvelope {
6896
}
6997

7098
export interface ApiHTTPError {
99+
/** Cause contains detailed information about the cause of the error. */
71100
cause?: ApiErrorCause;
101+
/** Code is a string representation of the HTTP status code. */
72102
code: string;
103+
/** Message is a human-readable description of the error. */
73104
message: string;
74105
}
75106

@@ -78,9 +109,32 @@ export interface ApiNamespaceListEnvelope {
78109
}
79110

80111
export interface ApiValidationError {
81-
field: string;
82-
message: string;
83-
type: FieldErrorType;
112+
/**
113+
* The field of the resource that has caused this error, as named by its JSON serialization.
114+
* May include dot and postfix notation for nested attributes.
115+
* Arrays are zero-indexed.
116+
* Fields may appear more than once in an array of causes due to fields having multiple errors.
117+
*
118+
* Examples:
119+
* "name" - the field "name" on the current resource
120+
* "items[0].name" - the field "name" on the first array entry in "items"
121+
*/
122+
field?: string;
123+
/**
124+
* A human-readable description of the cause of the error.
125+
* This field may be presented as-is to a reader.
126+
*/
127+
message?: string;
128+
/**
129+
* Origin indicates where the validation error originated.
130+
* If value is empty, the origin is unknown.
131+
*/
132+
origin?: ApiErrorCauseOrigin;
133+
/**
134+
* A machine-readable description of the cause of the error.
135+
* If value is empty, there is no information available.
136+
*/
137+
type?: FieldErrorType;
84138
}
85139

86140
export interface ApiWorkspaceActionPauseEnvelope {
@@ -107,6 +161,11 @@ export interface ApiWorkspaceListEnvelope {
107161
data: WorkspacesWorkspace[];
108162
}
109163

164+
export interface AssetsImageRef {
165+
error?: AssetsImageRefErrorCode;
166+
url: string;
167+
}
168+
110169
export interface HealthCheckHealthCheck {
111170
status: HealthCheckServiceStatus;
112171
systemInfo: HealthCheckSystemInfo;
@@ -135,10 +194,6 @@ export interface WorkspacekindsImageConfigValue {
135194
redirect?: WorkspacekindsOptionRedirect;
136195
}
137196

138-
export interface WorkspacekindsImageRef {
139-
url: string;
140-
}
141-
142197
export interface WorkspacekindsOptionLabel {
143198
key: string;
144199
value: string;
@@ -196,8 +251,8 @@ export interface WorkspacekindsWorkspaceKind {
196251
description: string;
197252
displayName: string;
198253
hidden: boolean;
199-
icon: WorkspacekindsImageRef;
200-
logo: WorkspacekindsImageRef;
254+
icon: AssetsImageRef;
255+
logo: AssetsImageRef;
201256
name: string;
202257
podTemplate: WorkspacekindsPodTemplate;
203258
}
@@ -225,10 +280,6 @@ export interface WorkspacesImageConfig {
225280
redirectChain?: WorkspacesRedirectStep[];
226281
}
227282

228-
export interface WorkspacesImageRef {
229-
url: string;
230-
}
231-
232283
export interface WorkspacesLastProbeInfo {
233284
/** Unix Epoch time in milliseconds */
234285
endTimeMs: number;
@@ -363,8 +414,8 @@ export interface WorkspacesWorkspaceCreate {
363414
}
364415

365416
export interface WorkspacesWorkspaceKindInfo {
366-
icon: WorkspacesImageRef;
367-
logo: WorkspacesImageRef;
417+
icon: AssetsImageRef;
418+
logo: AssetsImageRef;
368419
missing: boolean;
369420
name: string;
370421
}

workspaces/frontend/src/shared/mock/mockNotebookApis.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ export const mockNotebookApisImpl = (): NotebookApis => ({
4343
},
4444
workspaceKinds: {
4545
listWorkspaceKinds: async () => ({ data: mockWorkspaceKinds }),
46+
getWorkspaceKindIcon: async (kind) =>
47+
mockWorkspaceKinds.find((w) => w.name === kind)?.icon.url ?? '',
48+
getWorkspaceKindLogo: async (kind) => mockWorkspaceKinds.find((w) => w.name === kind)!.logo.url,
4649
getWorkspaceKind: async (kind) => ({
4750
data: mockWorkspaceKinds.find((w) => w.name === kind)!,
4851
}),

0 commit comments

Comments
 (0)