) => void;
+ changeCredential: (name: string, value: string) => void;
}
function CredentialField({
active,
- fieldIndex,
- index,
item,
- onChangeCredential,
+ changeCredential,
}: CredentialFieldProps) {
const [showPassword, setShowPassword] = useState(false);
const onToggleVisibility = useCallback(() => {
@@ -465,7 +295,7 @@ function CredentialField({
return (
-
))}
diff --git a/client/src/features/project/components/cloudStorage/projectCloudStorage.api.ts b/client/src/features/project/components/cloudStorage/projectCloudStorage.api.ts
index 4c7f01be70..c0d8bc0a34 100644
--- a/client/src/features/project/components/cloudStorage/projectCloudStorage.api.ts
+++ b/client/src/features/project/components/cloudStorage/projectCloudStorage.api.ts
@@ -77,7 +77,7 @@ const projectCloudStorageApi = createApi({
>({
query: ({ storage_id, ...params }) => {
return {
- method: "PATCH",
+ method: "PUT",
url: `storage/${storage_id}`,
body: { ...params },
};
diff --git a/client/src/features/project/components/cloudStorage/projectCloudStorage.constants.ts b/client/src/features/project/components/cloudStorage/projectCloudStorage.constants.ts
index 1a0b1af051..af9f11a3cb 100644
--- a/client/src/features/project/components/cloudStorage/projectCloudStorage.constants.ts
+++ b/client/src/features/project/components/cloudStorage/projectCloudStorage.constants.ts
@@ -30,6 +30,23 @@ export const CLOUD_STORAGE_CONFIGURATION_PLACEHOLDER =
export const CLOUD_STORAGE_OVERRIDE = {
storage: {
+ azureblob: {
+ position: 3,
+ },
+ drive: {
+ hide: true,
+ },
+ gcs: {
+ hide: true,
+ },
+ // eslint-disable-next-line spellcheck/spell-checker
+ dropbox: {
+ hide: true,
+ },
+ // eslint-disable-next-line spellcheck/spell-checker
+ onedrive: {
+ hide: true,
+ },
s3: {
description:
"Amazon S3 Compliant Storage Providers including AWS, CloudFlare, DigitalOcean and many others",
@@ -40,19 +57,29 @@ export const CLOUD_STORAGE_OVERRIDE = {
},
},
},
- drive: {
- position: 2,
- },
webdav: {
- position: 3,
- },
- azureblob: {
- position: 4,
+ description:
+ "WebDAV compatible services, including PolyBox and SwitchDrive",
+ position: 2,
},
} as Record>,
};
export const CLOUD_OPTIONS_OVERRIDE = {
+ azureblob: {
+ account: {
+ friendlyName: "Account Name",
+ help: "Set this to the Azure Storage Account Name in use. Leave blank to use SAS URL or Emulator, otherwise it needs to be set.",
+ },
+ client_certificate_path: { advanced: true },
+ client_certificate_password: { advanced: true },
+ env_auth: { hide: true },
+ key: { friendlyName: "Shared Key" },
+ sas_url: { advanced: true },
+ tenant: { friendlyName: "Tenant ID", advanced: true },
+ client_id: { friendlyName: "Client ID", advanced: true },
+ client_secret: { friendlyName: "Client Secret", advanced: true },
+ },
s3: {
env_auth: { hide: true }, // ? uses the ENV variables
location_constraint: { hide: true }, // ? only for creating buckets
@@ -68,6 +95,16 @@ export const CLOUD_OPTIONS_OVERRIDE = {
help: "Endpoint for S3 API. You should leave this blank if you entered the region already.",
},
},
+ webdav: {
+ pass: {
+ friendlyName: "Token (or password)",
+ help: "This is the token to access the WebDAV service. Mind that providing the user's password directly here won't usually work.",
+ },
+ bearer_token: { friendlyName: "Bearer Token" },
+ url: { friendlyName: "URL" },
+ user: { friendlyName: "Username" },
+ vendor: { advanced: true },
+ },
} as Record>>;
export const CLOUD_STORAGE_MOUNT_PATH_HELP = {
diff --git a/client/src/features/project/components/cloudStorage/projectCloudStorage.types.ts b/client/src/features/project/components/cloudStorage/projectCloudStorage.types.ts
index 95d07be07c..072683d1fc 100644
--- a/client/src/features/project/components/cloudStorage/projectCloudStorage.types.ts
+++ b/client/src/features/project/components/cloudStorage/projectCloudStorage.types.ts
@@ -82,6 +82,12 @@ export type CloudStorageOptionTypes =
| "number"
| "secret";
+export type CloudStorageSchemaOptionExample = {
+ value: string; // ? Potential value for the option
+ help: string; // ? Help text for the _value_
+ provider: string; // ? empty for "all providers"
+};
+
export interface CloudStorageSchemaOptions {
name: string;
help: string;
@@ -89,16 +95,10 @@ export interface CloudStorageSchemaOptions {
default: number | string | boolean;
default_str: string;
value: null | number | string | boolean;
- examples: [
- {
- value: string; // ? Potential value for the option
- help: string; // ? Help text for the _value_
- provider: string; // ? empty for "all providers"
- }
- ];
+ examples: CloudStorageSchemaOptionExample[];
required: boolean;
ispassword: boolean; // eslint-disable-line spellcheck/spell-checker
- sensitive: boolean; // ? The service doesn't store it -- "more" sensitive? 😁
+ sensitive: boolean;
advanced: boolean; // ? Only shown when advanced options are enabled
exclusive: boolean; // ? Only one of the examples can be used when this is true
datatype: string;
@@ -107,12 +107,14 @@ export interface CloudStorageSchemaOptions {
convertedType?: CloudStorageOptionTypes;
convertedDefault?: number | string | boolean;
convertedHide?: boolean;
+ filteredExamples: CloudStorageSchemaOptionExample[];
friendlyName?: string;
}
export interface CloudStorageSchema {
name: string;
description: string;
+ hide?: boolean;
prefix: string; // ? weird naming; it's the machine readable name
position?: number;
options: CloudStorageSchemaOptions[];
diff --git a/client/src/features/project/utils/projectCloudStorage.utils.ts b/client/src/features/project/utils/projectCloudStorage.utils.ts
index c38fcaa84a..ffa087b6c9 100644
--- a/client/src/features/project/utils/projectCloudStorage.utils.ts
+++ b/client/src/features/project/utils/projectCloudStorage.utils.ts
@@ -118,12 +118,14 @@ export function getSchemaStorage(
Object.keys(CLOUD_STORAGE_OVERRIDE.storage).includes(element.prefix)
) {
const override = CLOUD_STORAGE_OVERRIDE.storage[element.prefix];
- current.push({
- ...element,
- name: override.name ?? element.name,
- description: override.description ?? element.description,
- position: override.position ?? element.position,
- });
+ if (!override.hide) {
+ current.push({
+ ...element,
+ name: override.name ?? element.name,
+ description: override.description ?? element.description,
+ position: override.position ?? element.position,
+ });
+ }
} else {
current.push(element);
}
@@ -292,7 +294,6 @@ export function getSchemaOptions(
}
// type conversion is scary; for the default and value, we _try_ to convert it
- // TODO: we should consider using "example" as enum, but that might turn out to be a bad idea
try {
if (option.default != undefined && option.default !== "") {
if (convertedOption.convertedType === "number")
@@ -301,7 +302,9 @@ export function getSchemaOptions(
);
else if (convertedOption.convertedType === "boolean")
convertedOption.convertedDefault =
- option.default.toString().toLowerCase() === "true";
+ option.default.toString().toLowerCase() === "true"
+ ? true
+ : undefined;
else if (option.default.toString() !== "[object Object]")
convertedOption.convertedDefault = option.default.toString();
} else if (option.value != undefined && option.value !== "") {
@@ -311,7 +314,9 @@ export function getSchemaOptions(
);
else if (convertedOption.convertedType === "boolean")
convertedOption.convertedDefault =
- option.value.toString().toLowerCase() === "true";
+ option.value.toString().toLowerCase() === "true"
+ ? true
+ : undefined;
else if (option.value.toString() !== "[object Object]")
convertedOption.convertedDefault = option.value.toString();
}
@@ -319,6 +324,22 @@ export function getSchemaOptions(
convertedOption.convertedDefault = undefined;
}
+ // examples should be filtered by the provider
+ if (option.examples) {
+ const filteredExamples = option.examples.filter((e) => {
+ if (!targetProvider || !e.provider) return true;
+ if (e.provider.startsWith("!")) {
+ const providers = e.provider.slice(1).split(",");
+ return !providers.includes(targetProvider);
+ }
+ const providers = e.provider.split(",");
+ return providers.includes(targetProvider);
+ });
+ if (filteredExamples.length) {
+ convertedOption.filteredExamples = filteredExamples;
+ }
+ }
+
return convertedOption;
})
: optionsFiltered;