Core view migration fixes (#14166)
Bugs found with feature flag IS_CORE_VIEW_ENABLED: - Switching a view type does switches but does not update the option dropdown selected menu item, we have to refresh ==> **fixed** - Reordering a field in the option dropdown causes a bug because it tries to update with a decimal position like 1.5 but the position field on core views is integer ==> **fixed** Hidding a field triggers the update, but making it visible again right after that does not trigger the DB update, we have to refresh the app ==> **not fixed, medium bug** Reordering core view groups in option dropdown fails ==> **fixed** Showing / hidding core view groups fails ==> **fixed** Creating a table group view works but if we select kanban right after it fails ==> **fixed** Move right / move left on kanban core view group doesn’t do anything ==> **fixed** Deleting a view from the view dropdown fails ==> **fixed** Creating a view from another view does not copy the view groups ==> **not fixed, medium bug** Move left / right has a strange behavior, not working consistently, it sends always the same position ==> **not fixed, medium bug** View re-order optimistic update is broken, but the DB update works ==> **now it's dancing not fixed, medium bug** Next steps: - we should re-work the optimistic behaviors of view updates but let's clean the code first
This commit is contained in:
+2
-21
@@ -93,29 +93,10 @@ export const useSetViewTypeFromLayoutOptionsMenu = () => {
|
||||
if (availableFieldsForKanban.length === 0) {
|
||||
throw new Error('No fields for kanban - should not happen');
|
||||
}
|
||||
const previouslySelectedKanbanField = availableFieldsForKanban.find(
|
||||
(fieldsForKanban) =>
|
||||
fieldsForKanban.id ===
|
||||
currentView.viewGroups[0].fieldMetadataId,
|
||||
);
|
||||
|
||||
const kanbanField = isDefined(previouslySelectedKanbanField)
|
||||
? previouslySelectedKanbanField
|
||||
: availableFieldsForKanban[0];
|
||||
|
||||
if (!isDefined(previouslySelectedKanbanField)) {
|
||||
updateCurrentViewParams.kanbanFieldMetadataId =
|
||||
currentView.viewGroups[0].fieldMetadataId;
|
||||
}
|
||||
|
||||
const hasViewGroups = currentView.viewGroups.some(
|
||||
(viewGroup: ViewGroup) =>
|
||||
viewGroup.fieldMetadataId === kanbanField.id,
|
||||
);
|
||||
|
||||
if (!hasViewGroups) {
|
||||
if (currentView.viewGroups.length === 0) {
|
||||
const viewGroups = await createViewGroupAssociatedWithKanbanField(
|
||||
kanbanField.id,
|
||||
availableFieldsForKanban[0].id,
|
||||
currentView.id,
|
||||
);
|
||||
loadRecordIndexStates(
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@ import { recordGroupFieldMetadataComponentState } from '@/object-record/record-g
|
||||
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
|
||||
import { type RecordGroupAction } from '@/object-record/record-group/types/RecordGroupActions';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
@@ -34,6 +35,7 @@ type UseRecordGroupActionsParams = {
|
||||
export const useRecordGroupActions = ({
|
||||
viewType,
|
||||
}: UseRecordGroupActionsParams) => {
|
||||
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
|
||||
const navigate = useNavigateSettings();
|
||||
const location = useLocation();
|
||||
|
||||
@@ -66,7 +68,7 @@ export const useRecordGroupActions = ({
|
||||
);
|
||||
|
||||
const { reorderRecordGroups } = useReorderRecordGroups({
|
||||
viewBarId: objectMetadataItem.id,
|
||||
recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ export const useRecordGroupReorderConfirmationModal = ({
|
||||
useState<Parameters<OnDragEndResponder> | null>(null);
|
||||
|
||||
const { reorderRecordGroups } = useReorderRecordGroups({
|
||||
viewBarId: recordIndexId,
|
||||
recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
|
||||
+10
-6
@@ -14,7 +14,7 @@ import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
type UseReorderRecordGroupsParams = {
|
||||
viewBarId: string;
|
||||
recordIndexId: string;
|
||||
viewType: ViewType;
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ type ReorderRecordGroupsParams = {
|
||||
};
|
||||
|
||||
export const useReorderRecordGroups = ({
|
||||
viewBarId,
|
||||
recordIndexId,
|
||||
viewType,
|
||||
}: UseReorderRecordGroupsParams) => {
|
||||
const { setRecordGroups } = useSetRecordGroups();
|
||||
@@ -32,7 +32,7 @@ export const useReorderRecordGroups = ({
|
||||
|
||||
const visibleRecordGroupIdsFamilySelector = useRecoilComponentCallbackState(
|
||||
visibleRecordGroupIdsComponentFamilySelector,
|
||||
viewBarId,
|
||||
recordIndexId,
|
||||
);
|
||||
|
||||
const { saveViewGroups } = useSaveCurrentViewGroups();
|
||||
@@ -80,16 +80,20 @@ export const useReorderRecordGroups = ({
|
||||
];
|
||||
}, []);
|
||||
|
||||
setRecordGroups(updatedRecordGroups, viewBarId, objectMetadataItem.id);
|
||||
setRecordGroups(
|
||||
updatedRecordGroups,
|
||||
recordIndexId,
|
||||
objectMetadataItem.id,
|
||||
);
|
||||
saveViewGroups(
|
||||
mapRecordGroupDefinitionsToViewGroups(updatedRecordGroups),
|
||||
);
|
||||
},
|
||||
[
|
||||
objectMetadataItem,
|
||||
objectMetadataItem.id,
|
||||
recordIndexId,
|
||||
saveViewGroups,
|
||||
setRecordGroups,
|
||||
viewBarId,
|
||||
viewType,
|
||||
visibleRecordGroupIdsFamilySelector,
|
||||
],
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ export const usePersistViewGroupRecords = () => {
|
||||
apolloClient.mutate<{ updateCoreViewGroup: ViewGroup }>({
|
||||
mutation: UPDATE_CORE_VIEW_GROUP,
|
||||
variables: {
|
||||
idToUpdate: viewGroup.id,
|
||||
id: viewGroup.id,
|
||||
input: {
|
||||
isVisible: viewGroup.isVisible,
|
||||
position: viewGroup.position,
|
||||
|
||||
@@ -1,17 +1,55 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
|
||||
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
|
||||
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FeatureFlagKey, useDeleteCoreViewMutation } from '~/generated/graphql';
|
||||
|
||||
export const useDeleteView = () => {
|
||||
const featureFlags = useFeatureFlagsMap();
|
||||
const isCoreViewEnabled = featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
|
||||
|
||||
const [deleteCoreViewMutation] = useDeleteCoreViewMutation();
|
||||
const { refreshCoreViews } = useRefreshCoreViews();
|
||||
const { deleteOneRecord } = useDeleteOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const deleteView = useRecoilCallback(
|
||||
() => async (viewId: string) => {
|
||||
await deleteOneRecord(viewId);
|
||||
},
|
||||
[deleteOneRecord],
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
const currentView = snapshot
|
||||
.getLoadable(
|
||||
prefetchViewFromViewIdFamilySelector({
|
||||
viewId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(currentView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCoreViewEnabled) {
|
||||
await deleteCoreViewMutation({
|
||||
variables: {
|
||||
id: viewId,
|
||||
},
|
||||
});
|
||||
|
||||
await refreshCoreViews(currentView.objectMetadataId);
|
||||
} else {
|
||||
await deleteOneRecord(viewId);
|
||||
}
|
||||
},
|
||||
[
|
||||
deleteCoreViewMutation,
|
||||
deleteOneRecord,
|
||||
isCoreViewEnabled,
|
||||
refreshCoreViews,
|
||||
],
|
||||
);
|
||||
|
||||
return { deleteView };
|
||||
|
||||
@@ -3,7 +3,9 @@ import { useRecoilCallback } from 'recoil';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { convertUpdateViewInputToCore } from '@/views/utils/convertUpdateViewInputToCore';
|
||||
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
|
||||
@@ -22,6 +24,7 @@ export const useUpdateCurrentView = () => {
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
const { refreshCoreViews } = useRefreshCoreViews();
|
||||
|
||||
const [updateOneCoreView] = useUpdateCoreViewMutation();
|
||||
|
||||
@@ -32,6 +35,18 @@ export const useUpdateCurrentView = () => {
|
||||
.getLoadable(currentViewIdCallbackState)
|
||||
.getValue();
|
||||
|
||||
const currentView = snapshot
|
||||
.getLoadable(
|
||||
prefetchViewFromViewIdFamilySelector({
|
||||
viewId: currentViewId ?? '',
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(currentView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(currentViewId)) {
|
||||
if (isCoreViewEnabled) {
|
||||
const input = convertUpdateViewInputToCore(view);
|
||||
@@ -42,6 +57,7 @@ export const useUpdateCurrentView = () => {
|
||||
input,
|
||||
},
|
||||
});
|
||||
await refreshCoreViews(currentView.objectMetadataId);
|
||||
} else {
|
||||
await updateOneRecord({
|
||||
idToUpdate: currentViewId,
|
||||
@@ -53,6 +69,7 @@ export const useUpdateCurrentView = () => {
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
isCoreViewEnabled,
|
||||
refreshCoreViews,
|
||||
updateOneCoreView,
|
||||
updateOneRecord,
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user