diff --git a/frontend/src/features/storages/ui/edit/storages/EditAzureBlobStorageComponent.tsx b/frontend/src/features/storages/ui/edit/storages/EditAzureBlobStorageComponent.tsx
new file mode 100644
index 0000000..6021175
--- /dev/null
+++ b/frontend/src/features/storages/ui/edit/storages/EditAzureBlobStorageComponent.tsx
@@ -0,0 +1,226 @@
+import { DownOutlined, InfoCircleOutlined, UpOutlined } from '@ant-design/icons';
+import { Input, Radio, Tooltip } from 'antd';
+import { useState } from 'react';
+
+import type { Storage } from '../../../../../entity/storages';
+
+interface Props {
+ storage: Storage;
+ setStorage: (storage: Storage) => void;
+ setUnsaved: () => void;
+}
+
+export function EditAzureBlobStorageComponent({ storage, setStorage, setUnsaved }: Props) {
+ const hasAdvancedValues =
+ !!storage?.azureBlobStorage?.prefix || !!storage?.azureBlobStorage?.endpoint;
+ const [showAdvanced, setShowAdvanced] = useState(hasAdvancedValues);
+
+ return (
+ <>
+
+
Auth method
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ authMethod: e.target.value,
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ >
+ Account key
+ Connection string
+
+
+
+ {storage?.azureBlobStorage?.authMethod === 'CONNECTION_STRING' && (
+
+
Connection
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ connectionString: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="DefaultEndpointsProtocol=https;AccountName=..."
+ />
+
+
+
+
+
+ )}
+
+ {storage?.azureBlobStorage?.authMethod === 'ACCOUNT_KEY' && (
+ <>
+
+
Account name
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ accountName: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="mystorageaccount"
+ />
+
+
+
+
Account key
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ accountKey: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="your-account-key"
+ />
+
+ >
+ )}
+
+
+
Container name
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ containerName: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="my-container"
+ />
+
+
+
+
setShowAdvanced(!showAdvanced)}
+ >
+ Advanced settings
+
+ {showAdvanced ? (
+
+ ) : (
+
+ )}
+
+
+
+ {showAdvanced && (
+ <>
+ {storage?.azureBlobStorage?.authMethod === 'ACCOUNT_KEY' && (
+
+
Endpoint
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ endpoint: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="https://myaccount.blob.core.windows.net (optional)"
+ />
+
+
+
+
+
+ )}
+
+
+
Blob prefix
+
{
+ if (!storage?.azureBlobStorage) return;
+
+ setStorage({
+ ...storage,
+ azureBlobStorage: {
+ ...storage.azureBlobStorage,
+ prefix: e.target.value.trim(),
+ },
+ });
+ setUnsaved();
+ }}
+ size="small"
+ className="w-full max-w-[250px]"
+ placeholder="my-prefix/ (optional)"
+ />
+
+
+
+
+
+ >
+ )}
+
+
+ >
+ );
+}
diff --git a/frontend/src/features/storages/ui/show/ShowStorageComponent.tsx b/frontend/src/features/storages/ui/show/ShowStorageComponent.tsx
index bf81758..94b5d64 100644
--- a/frontend/src/features/storages/ui/show/ShowStorageComponent.tsx
+++ b/frontend/src/features/storages/ui/show/ShowStorageComponent.tsx
@@ -1,6 +1,7 @@
import { type Storage, StorageType } from '../../../../entity/storages';
import { getStorageLogoFromType } from '../../../../entity/storages/models/getStorageLogoFromType';
import { getStorageNameFromType } from '../../../../entity/storages/models/getStorageNameFromType';
+import { ShowAzureBlobStorageComponent } from './storages/ShowAzureBlobStorageComponent';
import { ShowGoogleDriveStorageComponent } from './storages/ShowGoogleDriveStorageComponent';
import { ShowNASStorageComponent } from './storages/ShowNASStorageComponent';
import { ShowS3StorageComponent } from './storages/ShowS3StorageComponent';
@@ -37,6 +38,12 @@ export function ShowStorageComponent({ storage }: Props) {
{storage?.type === StorageType.NAS && }
+
+
+ {storage?.type === StorageType.AZURE_BLOB && (
+
+ )}
+
);
}
diff --git a/frontend/src/features/storages/ui/show/storages/ShowAzureBlobStorageComponent.tsx b/frontend/src/features/storages/ui/show/storages/ShowAzureBlobStorageComponent.tsx
new file mode 100644
index 0000000..58d5dfa
--- /dev/null
+++ b/frontend/src/features/storages/ui/show/storages/ShowAzureBlobStorageComponent.tsx
@@ -0,0 +1,56 @@
+import type { Storage } from '../../../../../entity/storages';
+
+interface Props {
+ storage: Storage;
+}
+
+export function ShowAzureBlobStorageComponent({ storage }: Props) {
+ return (
+ <>
+