Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
5680d96
fix(duckdb): load https extension after setting custom repository
ddecrulle Dec 22, 2025
990e9e8
Bump web version
ddecrulle Dec 22, 2025
eb0dbc7
Automatic patch bump of chart version to 10.30.14
actions-user Dec 22, 2025
6fae1d9
Update oidc-spa to v9
garronej Jan 6, 2026
c0e7049
Bump web version
garronej Jan 6, 2026
6d0ca28
Automatic patch bump of chart version to 10.30.15
actions-user Jan 6, 2026
a726bc0
Enable DPoP
garronej Jan 7, 2026
938a869
Bump web version
garronej Jan 7, 2026
6ff516d
Automatic minor bump of chart version to 10.31.0
actions-user Jan 7, 2026
ce73d84
Disable dpop until the onboarding API supports it
garronej Jan 7, 2026
ce64292
Bump web version
garronej Jan 7, 2026
602bbd4
Automatic patch bump of chart version to 10.31.1
actions-user Jan 7, 2026
71e0174
Fix autologin full page redirect bug
garronej Jan 7, 2026
4e0b181
Bump version
garronej Jan 7, 2026
3963ae2
Automatic patch bump of chart version to 10.31.2
actions-user Jan 7, 2026
f2b9e2f
Only make the sql query with offset when it's not for the first page
garronej Jan 12, 2026
aeb80f1
Update oidc-spa
garronej Jan 12, 2026
56b403d
Bump web version
garronej Jan 12, 2026
5fc19ec
Automatic patch bump of chart version to 10.31.3
actions-user Jan 12, 2026
c7efac0
Enable DPoP if the AS supports it, unless the Go Onboarding API is en…
garronej Jan 13, 2026
b762444
Bump web version
garronej Jan 13, 2026
a0e33a8
Automatic minor bump of chart version to 10.32.0
actions-user Jan 13, 2026
c5cb2d5
Configure figma mcp
marchufschmitt Mar 2, 2026
d3728a0
UI - Add S3 Navigation Bar
marchufschmitt Mar 2, 2026
32488b7
UI - Add Pinned Bookmarks (List and entry Point List)
marchufschmitt Mar 2, 2026
d5d514b
UI - Add S3 Profile Selector
marchufschmitt Mar 2, 2026
bbb9707
Improve comment in S3ExplorerNavigationBar.tsx
marchufschmitt Mar 2, 2026
8bc432f
Save spec
garronej Mar 2, 2026
b7eac83
Update S3Uri implementation
garronej Mar 3, 2026
9c6aa4b
Moving specs of the S3UriBar outside of the implementation
garronej Mar 3, 2026
e2316ef
Start a spec file where we put general instruction for LLM agents to …
garronej Mar 3, 2026
4a9b527
Increase timeout
garronej Mar 3, 2026
b6abe46
FIx focus
garronej Mar 3, 2026
bcf6318
Remove extra delimiter
garronej Mar 3, 2026
a181d22
Two states for bookmarked and not bookmarked
garronej Mar 3, 2026
5ae4255
Update progress on S3UriBar
garronej Mar 3, 2026
a8db0d3
Enhance S3UriBar: Add root icon for navigation crumbs and adjust styles
garronej Mar 3, 2026
b1920b0
Enhance S3UriBar: Add root icon styling and adjust border radius
garronej Mar 3, 2026
c55f7c3
Enhance S3UriBar styles: Adjust height and add box-sizing for better …
garronej Mar 3, 2026
4046c00
Update icons
garronej Mar 3, 2026
abea101
Enhance S3UriBar styles: Add right padding for improved layout
garronej Mar 3, 2026
b2705e1
Enhance S3UriBar: Exclude segment crumbs from current styling adjustm…
garronej Mar 3, 2026
ff80673
Enhance S3UriBar styles: Update padding for segment key first element
garronej Mar 3, 2026
8b2dca6
Enhance S3UriBar styles: Reduce left and right padding for improved l…
garronej Mar 3, 2026
d648923
Enhance S3UriBar styles: Add cursor style for text input
garronej Mar 3, 2026
7b5a563
Fix type check for event target in S3UriBar component
garronej Mar 3, 2026
ffc4222
Enhance S3UriBar styles: Add left padding to input for better spacing
garronej Mar 3, 2026
57619e9
Enhance S3UriBar: Add edit mode toggle button with tooltip and styling
garronej Mar 3, 2026
8324b21
Better positioning of the autocomplete modal
garronej Mar 4, 2026
0177f18
Enhance S3UriBar: Add support for shortcut hints and improve hint typ…
garronej Mar 4, 2026
554b0d3
Enhance S3UriBar: Add hint type labels and icons for better user expe…
garronej Mar 4, 2026
d445c31
Enhance S3UriBar: Update shortcut hints for improved clarity and add …
garronej Mar 4, 2026
845ffed
Enhance S3UriBar: Add auto-scrolling for active hint in editing mode
garronej Mar 4, 2026
f6cb312
Enhance S3UriBar: Add support for collapsing long hint names with ell…
garronej Mar 4, 2026
bebeb86
Refactor code structure for improved readability and maintainability
garronej Mar 4, 2026
8575e74
Specs for S3BookmarksBar
marchufschmitt Mar 4, 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
9 changes: 9 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"servers": {
"figma": {
"url": "http://127.0.0.1:3845/mcp",
"type": "http"
}
},
"inputs": []
}
2 changes: 1 addition & 1 deletion helm-chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
version: 10.30.13
version: 10.32.0
8 changes: 4 additions & 4 deletions helm-chart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ingress:
- host: datalab.my-domain.net
EOF

helm install onyxia onyxia/onyxia --version "10.30.13" -f onyxia-values.yaml
helm install onyxia onyxia/onyxia --version "10.32.0" -f onyxia-values.yaml
```

### Using the Keycloak Theme (Optional)
Expand All @@ -44,7 +44,7 @@ extraInitContainers: |
args:
- -c
- |
curl -L -f -S -o /extensions/onyxia.jar https://github.com/InseeFrLab/onyxia/releases/download/v10.30.13/keycloak-theme.jar
curl -L -f -S -o /extensions/onyxia.jar https://github.com/InseeFrLab/onyxia/releases/download/v10.32.0/keycloak-theme.jar
volumeMounts:
- name: extensions
mountPath: /extensions
Expand All @@ -71,7 +71,7 @@ After that, you should be able to select *onyxia* as *Login Theme*.
Documentation reference for the available configuration parameter of the Onyxia Helm Chart.

- [The REST API (`api`)](https://github.com/InseeFrLab/onyxia-api/blob/v4.11.0/README.md#configuration)
- [The Web Application (`web`)](https://github.com/InseeFrLab/onyxia/blob/web-v4.56.19/web/.env)
- [The Web Application (`web`)](https://github.com/InseeFrLab/onyxia/blob/web-v4.58.0/web/.env)

Below is a sample `onyxia-values.yaml` file that illustrates where to specify the `api` and `web` configuration parameters.

Expand Down Expand Up @@ -107,4 +107,4 @@ Below is a sample `onyxia-values.yaml` file that illustrates where to specify th
If you are building your own service catalog for Onyxia ([learn how](https://docs.onyxia.sh/catalog-of-services)).
Here are defined the onyxia reserved parameter and the structure of the dynamic context:

[`values.schema.json` `"x-onyxia"` specifications](https://github.com/InseeFrLab/onyxia/blob/web-v4.56.19/web/src/core/ports/OnyxiaApi/XOnyxia.ts)
[`values.schema.json` `"x-onyxia"` specifications](https://github.com/InseeFrLab/onyxia/blob/web-v4.58.0/web/src/core/ports/OnyxiaApi/XOnyxia.ts)
4 changes: 4 additions & 0 deletions helm-chart/templates/web/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ spec:
value: {{ $value | quote }}
{{- end -}}
{{- end }}
{{- if .Values.onboarding.enabled }}
- name: OIDC_DISABLE_DPOP
value: "true"
{{- end }}
ports:
- name: http
containerPort: {{ .Values.web.containerPort }}
Expand Down
2 changes: 1 addition & 1 deletion helm-chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ web:
replicaCount: 1
image:
repository: inseefrlab/onyxia-web
tag: 4.56.19
tag: 4.58.0
pullPolicy: IfNotPresent

## Pod priority settings
Expand Down
3 changes: 3 additions & 0 deletions web/.env
Original file line number Diff line number Diff line change
Expand Up @@ -887,3 +887,6 @@ ONYXIA_VERSION_URL=
SCREEN_SCALER=true

OIDC_DEBUG_LOGS=false

# NOTE: Temporary workaround until the Go onboarding API supports it.
OIDC_DISABLE_DPOP=false
4 changes: 2 additions & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "onyxia-web",
"homepage": "https://onyxia.sh",
"type": "module",
"version": "4.56.19",
"version": "4.58.0",
"license": "MIT",
"scripts": {
"postinstall": "yarn install-git-hooks && yarn postinstall:code-gen",
Expand Down Expand Up @@ -69,7 +69,7 @@
"memoizee": "^0.4.17",
"minimal-polyfills": "^2.2.3",
"mui-icons-material-lazy": "^1.0.4",
"oidc-spa": "^8.6.3",
"oidc-spa": "10.0.1-rc.6",
"onyxia-ui": "^6.7.8",
"pathe": "^2.0.3",
"powerhooks": "^2.0.1",
Expand Down
3 changes: 1 addition & 2 deletions web/src/core/adapters/oidc/mock.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Oidc } from "core/ports/Oidc";
import { createMockOidc } from "oidc-spa/mock";
import { createMockOidc } from "oidc-spa/core-mock";

export async function createOidc(params: {
isUserInitiallyLoggedIn: boolean;
Expand All @@ -8,7 +8,6 @@ export async function createOidc(params: {

const oidc = await createMockOidc({
isUserInitiallyLoggedIn,
homeUrl: import.meta.env.BASE_URL,
mockedTokens: {
decodedIdToken: {}
}
Expand Down
2 changes: 1 addition & 1 deletion web/src/core/adapters/oidc/oidc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Oidc } from "core/ports/Oidc";
import { createOidc as createOidcSpa } from "oidc-spa";
import { createOidc as createOidcSpa } from "oidc-spa/core";
import { isKeycloak } from "oidc-spa/keycloak";
import type { OidcParams, OidcParams_Partial } from "core/ports/OnyxiaApi";
import { objectKeys } from "tsafe/objectKeys";
Expand Down
12 changes: 8 additions & 4 deletions web/src/core/adapters/sqlOlap/sqlOlap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ export const createDuckDbSqlOlap = (params: {

await conn.query(
[
"LOAD httpfs;",
`SET custom_extension_repository = '${window.location.origin}${import.meta.env.BASE_URL}duckdb-extensions';`
`SET custom_extension_repository = '${window.location.origin}${import.meta.env.BASE_URL}duckdb-extensions';`,
"LOAD httpfs;"
].join("\n")
);

Expand Down Expand Up @@ -278,7 +278,7 @@ export const createDuckDbSqlOlap = (params: {
sourceUrl = sourceUrl_noRedirect;
}

const sqlQuery = `SELECT * FROM ${(() => {
let sqlQuery = `SELECT * FROM ${(() => {
switch (fileType) {
case "csv":
return `read_csv('${sourceUrl}')`;
Expand All @@ -287,7 +287,11 @@ export const createDuckDbSqlOlap = (params: {
case "json":
return `read_json('${sourceUrl}')`;
}
})()} LIMIT ${rowsPerPage} OFFSET ${rowsPerPage * (page - 1)}`;
})()} LIMIT ${rowsPerPage}`;

if (page !== 1) {
sqlQuery += ` OFFSET ${rowsPerPage * (page - 1)}`;
}

const conn = await db.connect();
const stmt = await conn.prepare(sqlQuery);
Expand Down
7 changes: 3 additions & 4 deletions web/src/core/ports/Oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ export declare type Oidc = Oidc.LoggedIn | Oidc.NotLoggedIn;

export declare namespace Oidc {
export type Common = {
params: {
issuerUri: string;
clientId: string;
};
issuerUri: string;
clientId: string;
validRedirectUri: string;
};

export type NotLoggedIn = Common & {
Expand Down
232 changes: 232 additions & 0 deletions web/src/core/tools/S3Uri.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
import { assert, type Equals, id } from "tsafe";
import { same } from "evt/tools/inDepth/same";
import { z } from "zod";

export type S3Uri = S3Uri.Object | S3Uri.Prefix;

export namespace S3Uri {
type Common = {
bucket: string;
delimiter: string;
keySegments: string[];
};

export type Object = Common & {
type: "object";
keyBasename: string;
};

export type Prefix = Prefix.TerminatedByDelimiter | Prefix.NonTerminatedByDelimiter;

export namespace Prefix {
type Common_Prefix = Common & {
type: "prefix";
};

export type TerminatedByDelimiter = Common_Prefix & {
isDelimiterTerminated: true;
};

export type NonTerminatedByDelimiter = Common_Prefix & {
isDelimiterTerminated: false;
nextKeySegmentPrefix: string;
};
}
}

export function stringifyS3Uri(s3Uri: S3Uri): string {
let s3UriStr = [
"s3://",
`${s3Uri.bucket}/`,
s3Uri.keySegments.map(keySegment => `${keySegment}${s3Uri.delimiter}`).join("")
].join("");

switch (s3Uri.type) {
case "object":
s3UriStr += s3Uri.keyBasename;
break;
case "prefix":
if (!s3Uri.isDelimiterTerminated) {
s3UriStr += s3Uri.nextKeySegmentPrefix;
}
break;
default:
assert<Equals<typeof s3Uri, never>>;
}

return s3UriStr;
}

export function getS3UriKeyOrKeyPrefix(s3Uri: S3Uri): string {
return stringifyS3Uri(s3Uri).slice(`s3://${s3Uri.bucket}/`.length);
}

export function parseS3Uri(params: {
value: string;
delimiter: string;
isPrefix: false;
}): S3Uri.Object;
export function parseS3Uri(params: {
value: string;
delimiter: string;
isPrefix: true;
}): S3Uri.Prefix;
export function parseS3Uri(params: {
value: string;
delimiter: string;
isPrefix: boolean;
}): S3Uri {
const { value, delimiter, isPrefix } = params;

const match = value.match(/^s3:\/\/([^/]+)(\/?.*)$/);

if (match === null) {
throw new Error(`Malformed S3 URI: ${value}`);
}

const bucket = match[1];

const group2 = match[2];

if (group2 === "" || group2 === "/") {
return id<S3Uri.Prefix.TerminatedByDelimiter>({
type: "prefix",
bucket,
delimiter,
keySegments: [],
isDelimiterTerminated: true
});
}

const key = group2.slice(1);

const [last, ...rest_reversed] = key.split(delimiter).reverse();

const keySegments = rest_reversed.reverse();

if (last === "") {
assert(isPrefix);
return id<S3Uri.Prefix.TerminatedByDelimiter>({
type: "prefix",
bucket,
delimiter,
keySegments,
isDelimiterTerminated: true
});
}

if (isPrefix) {
return id<S3Uri.Prefix.NonTerminatedByDelimiter>({
type: "prefix",
bucket,
delimiter,
keySegments,
isDelimiterTerminated: false,
nextKeySegmentPrefix: last
});
}

return id<S3Uri.Object>({
type: "object",
bucket,
delimiter,
keySegments,
keyBasename: last
});
}

export function getIsInside(params: {
s3UriPrefix: S3Uri.Prefix;
s3Uri: S3Uri;
}): { isInside: false; isTopLevel?: never } | { isInside: true; isTopLevel: boolean } {
const { s3UriPrefix, s3Uri } = params;

if (!stringifyS3Uri(s3Uri).startsWith(stringifyS3Uri(s3UriPrefix))) {
return { isInside: false };
}
return {
isInside: true,
isTopLevel: same(s3UriPrefix.keySegments, s3Uri.keySegments)
};
}

export const zS3UriObject = (() => {
type TargetType = S3Uri.Object;

const zTargetType = z.object({
type: z.literal("object"),
bucket: z.string(),
delimiter: z.string(),
keySegments: z.array(z.string()),
keyBasename: z.string()
});

type InferredType = z.infer<typeof zTargetType>;

assert<Equals<TargetType, InferredType>>;

return id<z.ZodType<TargetType>>(zTargetType);
})();

export const zS3UriPrefixDelimiterTerminated = (() => {
type TargetType = S3Uri.Prefix.TerminatedByDelimiter;

const zTargetType = z.object({
type: z.literal("prefix"),
bucket: z.string(),
delimiter: z.string(),
keySegments: z.array(z.string()),
isDelimiterTerminated: z.literal(true)
});

type InferredType = z.infer<typeof zTargetType>;

assert<Equals<TargetType, InferredType>>;

return id<z.ZodType<TargetType>>(zTargetType);
})();

export const zS3UriPrefixNonDelimiterTerminated = (() => {
type TargetType = S3Uri.Prefix.NonTerminatedByDelimiter;

const zTargetType = z.object({
type: z.literal("prefix"),
bucket: z.string(),
delimiter: z.string(),
keySegments: z.array(z.string()),
isDelimiterTerminated: z.literal(false),
nextKeySegmentPrefix: z.string()
});

type InferredType = z.infer<typeof zTargetType>;

assert<Equals<TargetType, InferredType>>;

return id<z.ZodType<TargetType>>(zTargetType);
})();

export const zS3UriPrefix = (() => {
type TargetType = S3Uri.Prefix;

const zTargetType = z.union([
zS3UriPrefixDelimiterTerminated,
zS3UriPrefixNonDelimiterTerminated
]);

type InferredType = z.infer<typeof zTargetType>;

assert<Equals<TargetType, InferredType>>;
return id<z.ZodType<TargetType>>(zTargetType);
})();

export const zS3Uri = (() => {
type TargetType = S3Uri;

const zTargetType = z.union([zS3UriObject, zS3UriPrefix]);

type InferredType = z.infer<typeof zTargetType>;

assert<Equals<TargetType, InferredType>>;

return id<z.ZodType<TargetType>>(zTargetType);
})();
Loading
Loading