File - Migrate core pictures (workspace and member logo) + workflow attachments (#17924)

- Create a common file-by-id download controller
- Create core picture module with resolver and logic to handle
workspaceLogo and workspaceMemberProfilePicture update
- Create workflow file module (same)
- Data migration
This commit is contained in:
Etienne
2026-02-17 16:42:50 +01:00
committed by GitHub
parent 963f2de864
commit 163c1175cb
85 changed files with 2212 additions and 335 deletions
@@ -2,14 +2,21 @@ import { useRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { ImageInput } from '@/ui/input/components/ImageInput';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { buildSignedPath } from 'twenty-shared/utils';
import {
FeatureFlagKey,
useUpdateWorkspaceMutation,
useUploadWorkspaceLogoLegacyMutation,
useUploadWorkspaceLogoMutation,
} from '~/generated-metadata/graphql';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
import { buildSignedPath } from 'twenty-shared/utils';
export const WorkspaceLogoUploader = () => {
const isCorePictureMigrated = useIsFeatureEnabled(
FeatureFlagKey.IS_CORE_PICTURE_MIGRATED,
);
const [uploadLogoLegacy] = useUploadWorkspaceLogoLegacyMutation();
const [uploadLogo] = useUploadWorkspaceLogoMutation();
const [updateWorkspace] = useUpdateWorkspaceMutation();
const [currentWorkspace, setCurrentWorkspace] = useRecoilState(
@@ -23,17 +30,32 @@ export const WorkspaceLogoUploader = () => {
if (!currentWorkspace?.id) {
throw new Error('Workspace id not found');
}
await uploadLogo({
variables: {
file,
},
onCompleted: (data) => {
setCurrentWorkspace({
...currentWorkspace,
logo: buildSignedPath(data.uploadWorkspaceLogo),
});
},
});
if (isCorePictureMigrated) {
await uploadLogo({
variables: {
file,
},
onCompleted: (data) => {
setCurrentWorkspace({
...currentWorkspace,
logo: data.uploadWorkspaceLogo.url,
});
},
});
} else {
await uploadLogoLegacy({
variables: {
file,
},
onCompleted: (data) => {
setCurrentWorkspace({
...currentWorkspace,
logo: buildSignedPath(data.uploadWorkspaceLogoLegacy),
});
},
});
}
};
const onRemove = async () => {