mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-02 03:39:03 +00:00
feat(homepage): add reset to default template functionality and update home page settings option (#14202)
This commit is contained in:
parent
bcee2a4fb7
commit
b1ef86b83e
@ -102,6 +102,9 @@ public class MeResolver implements DataFetcher<CompletableFuture<AuthenticatedUs
|
||||
platformPrivileges.setManageApplications(
|
||||
ApplicationAuthorizationUtils.canManageApplications(context));
|
||||
platformPrivileges.setManageFeatures(AuthorizationUtils.canManageFeatures(context));
|
||||
platformPrivileges.setManageHomePageTemplates(
|
||||
AuthorizationUtils.canManageHomePageTemplates(context));
|
||||
|
||||
// Construct and return authenticated user object.
|
||||
final AuthenticatedUser authUser = new AuthenticatedUser();
|
||||
authUser.setCorpUser(corpUser);
|
||||
|
||||
@ -86,7 +86,16 @@ public class UpdateUserHomePageSettingsResolver implements DataFetcher<Completab
|
||||
@Nonnull final CorpUserHomePageSettings settings,
|
||||
@Nonnull final UpdateUserHomePageSettingsInput input) {
|
||||
|
||||
if (input.getPageTemplate() != null) {
|
||||
Boolean shouldRemoveTemplate = input.getRemovePageTemplate();
|
||||
|
||||
if (input.getPageTemplate() != null && Boolean.TRUE.equals(shouldRemoveTemplate)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid inputs: Cannot specify both pageTemplate and removePageTemplate.");
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(shouldRemoveTemplate)) {
|
||||
settings.data().remove("pageTemplate");
|
||||
} else if (input.getPageTemplate() != null) {
|
||||
settings.setPageTemplate(UrnUtils.getUrn(input.getPageTemplate()));
|
||||
}
|
||||
|
||||
|
||||
@ -169,9 +169,11 @@ public class CorpUserMapper {
|
||||
@Nonnull final com.linkedin.identity.CorpUserHomePageSettings homePageSettings) {
|
||||
CorpUserHomePageSettings result = new CorpUserHomePageSettings();
|
||||
|
||||
if (homePageSettings.hasPageTemplate()) {
|
||||
if (homePageSettings.getPageTemplate() != null) {
|
||||
result.setPageTemplate(
|
||||
(DataHubPageTemplate) UrnToEntityMapper.map(null, homePageSettings.getPageTemplate()));
|
||||
} else {
|
||||
result.setPageTemplate(null);
|
||||
}
|
||||
|
||||
if (homePageSettings.hasDismissedAnnouncements()) {
|
||||
|
||||
@ -192,6 +192,11 @@ type PlatformPrivileges {
|
||||
Whether the user can manage platform features.
|
||||
"""
|
||||
manageFeatures: Boolean!
|
||||
|
||||
"""
|
||||
Whether the user can manage default home page template.
|
||||
"""
|
||||
manageHomePageTemplates: Boolean!
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
@ -12503,6 +12503,11 @@ input UpdateUserHomePageSettingsInput {
|
||||
The list of urns of announcement posts dismissed by the user.
|
||||
"""
|
||||
newDismissedAnnouncements: [String]
|
||||
|
||||
"""
|
||||
Whether to remove the page template for the user.
|
||||
"""
|
||||
removePageTemplate: Boolean
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
@ -3741,6 +3741,7 @@ export const mocks = [
|
||||
viewStructuredPropertiesPage: true,
|
||||
manageApplications: true,
|
||||
manageFeatures: true,
|
||||
manageHomePageTemplates: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -4027,6 +4028,7 @@ export const platformPrivileges: PlatformPrivileges = {
|
||||
viewStructuredPropertiesPage: true,
|
||||
manageApplications: true,
|
||||
manageFeatures: true,
|
||||
manageHomePageTemplates: true,
|
||||
};
|
||||
|
||||
export const DomainMock1 = {
|
||||
|
||||
@ -89,6 +89,7 @@ describe('handleAccessRoles', () => {
|
||||
viewStructuredPropertiesPage: true,
|
||||
manageApplications: true,
|
||||
manageFeatures: true,
|
||||
manageHomePageTemplates: true,
|
||||
__typename: 'PlatformPrivileges',
|
||||
},
|
||||
__typename: 'AuthenticatedUser',
|
||||
@ -174,6 +175,7 @@ describe('handleAccessRoles', () => {
|
||||
viewStructuredPropertiesPage: true,
|
||||
manageApplications: true,
|
||||
manageFeatures: true,
|
||||
manageHomePageTemplates: true,
|
||||
__typename: 'PlatformPrivileges',
|
||||
},
|
||||
__typename: 'AuthenticatedUser',
|
||||
@ -267,6 +269,7 @@ describe('handleAccessRoles', () => {
|
||||
viewStructuredPropertiesPage: true,
|
||||
manageApplications: true,
|
||||
manageFeatures: true,
|
||||
manageHomePageTemplates: true,
|
||||
__typename: 'PlatformPrivileges',
|
||||
},
|
||||
__typename: 'AuthenticatedUser',
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
import { Button, Tooltip } from '@components';
|
||||
import React, { useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import analytics, { EventType } from '@app/analytics';
|
||||
import { usePageTemplateContext } from '@app/homeV3/context/PageTemplateContext';
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-right: 42px;
|
||||
`;
|
||||
|
||||
export default function EditDefaultTemplateButton() {
|
||||
const { setIsEditingGlobalTemplate, isEditingGlobalTemplate } = usePageTemplateContext();
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
setIsEditingGlobalTemplate(true);
|
||||
analytics.event({
|
||||
type: EventType.HomePageTemplateGlobalTemplateEditingStart,
|
||||
});
|
||||
}, [setIsEditingGlobalTemplate]);
|
||||
|
||||
// TODO: also hide this if you don't have permissions - CH-510
|
||||
if (isEditingGlobalTemplate) return null;
|
||||
|
||||
return (
|
||||
<ButtonWrapper>
|
||||
<Tooltip title="Edit the home page that users see by default">
|
||||
<Button
|
||||
icon={{ icon: 'PencilSimpleLine', color: 'gray', source: 'phosphor' }}
|
||||
variant="text"
|
||||
onClick={onClick}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonWrapper>
|
||||
);
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
|
||||
import EditDefaultTemplateBar from '@app/homeV3/EditDefaultTemplateBar';
|
||||
import EditDefaultTemplateButton from '@app/homeV3/EditDefaultTemplateButton';
|
||||
import { Announcements } from '@app/homeV3/announcements/Announcements';
|
||||
import EditDefaultTemplateBar from '@app/homeV3/settings/EditDefaultTemplateBar';
|
||||
import EditHomePageSettingsButton from '@app/homeV3/settings/EditHomePageSettingsButton';
|
||||
import { CenteredContainer, ContentContainer, ContentDiv } from '@app/homeV3/styledComponents';
|
||||
import Template from '@app/homeV3/template/Template';
|
||||
|
||||
@ -11,7 +11,7 @@ const HomePageContent = () => {
|
||||
<ContentContainer>
|
||||
<CenteredContainer>
|
||||
<ContentDiv>
|
||||
<EditDefaultTemplateButton />
|
||||
<EditHomePageSettingsButton />
|
||||
<Announcements />
|
||||
<Template />
|
||||
<EditDefaultTemplateBar />
|
||||
|
||||
@ -22,7 +22,8 @@ export const PageTemplateProvider = ({ children }: { children: ReactNode }) => {
|
||||
} = useTemplateState();
|
||||
|
||||
// Template operations
|
||||
const { updateTemplateWithModule, removeModuleFromTemplate, upsertTemplate } = useTemplateOperations();
|
||||
const { updateTemplateWithModule, removeModuleFromTemplate, upsertTemplate, resetTemplateToDefault } =
|
||||
useTemplateOperations(setPersonalTemplate);
|
||||
|
||||
// Modal state
|
||||
const moduleModalState = useModuleModalState();
|
||||
@ -56,6 +57,7 @@ export const PageTemplateProvider = ({ children }: { children: ReactNode }) => {
|
||||
upsertModule,
|
||||
moduleModalState,
|
||||
moveModule,
|
||||
resetTemplateToDefault,
|
||||
}),
|
||||
[
|
||||
personalTemplate,
|
||||
@ -71,6 +73,7 @@ export const PageTemplateProvider = ({ children }: { children: ReactNode }) => {
|
||||
upsertModule,
|
||||
moduleModalState,
|
||||
moveModule,
|
||||
resetTemplateToDefault,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@ -92,6 +92,7 @@ const mockMoveModule = vi.fn();
|
||||
const mockUpdateTemplateWithModule = vi.fn();
|
||||
const mockRemoveModuleFromTemplate = vi.fn();
|
||||
const mockUpsertTemplate = vi.fn();
|
||||
const mockResetTemplateToDefault = vi.fn();
|
||||
|
||||
describe('PageTemplateContext', () => {
|
||||
beforeEach(() => {
|
||||
@ -113,6 +114,7 @@ describe('PageTemplateContext', () => {
|
||||
updateTemplateWithModule: mockUpdateTemplateWithModule,
|
||||
removeModuleFromTemplate: mockRemoveModuleFromTemplate,
|
||||
upsertTemplate: mockUpsertTemplate,
|
||||
resetTemplateToDefault: mockResetTemplateToDefault,
|
||||
});
|
||||
|
||||
mockUseModuleOperations.mockReturnValue({
|
||||
|
||||
@ -52,6 +52,8 @@ const mockModule: PageModuleFragment = {
|
||||
},
|
||||
};
|
||||
|
||||
const setPersonalTemplate = vi.fn();
|
||||
|
||||
describe('useTemplateOperations', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@ -61,7 +63,7 @@ describe('useTemplateOperations', () => {
|
||||
|
||||
describe('updateTemplateWithModule', () => {
|
||||
it('should add module to new row when rowIndex is undefined', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: undefined,
|
||||
@ -77,7 +79,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should add module to existing row on the left side', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 0,
|
||||
@ -94,7 +96,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should add module to existing row on the right side', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 0,
|
||||
@ -111,7 +113,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should create new row when rowIndex is out of bounds', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 5,
|
||||
@ -127,7 +129,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should handle template with no rows', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithoutRows: PageTemplateFragment = {
|
||||
urn: 'urn:li:pageTemplate:empty',
|
||||
@ -162,7 +164,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should return null when template is null', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 0,
|
||||
@ -177,7 +179,7 @@ describe('useTemplateOperations', () => {
|
||||
|
||||
describe('removeModuleFromTemplate', () => {
|
||||
it('should remove module by moduleIndex when provided', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithMultipleModules: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -231,7 +233,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should handle duplicate URNs correctly with moduleIndex', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithDuplicateUrns: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -297,7 +299,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should fall back to URN search when moduleIndex is invalid', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithMultipleModules: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -351,7 +353,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should fall back to URN search when moduleIndex URN does not match', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithMultipleModules: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -405,7 +407,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should remove entire row when last module is removed', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithSingleModule: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -462,7 +464,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should return original template when module is not found', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 0,
|
||||
@ -480,7 +482,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should return original template when rowIndex is invalid', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 5, // Invalid index
|
||||
@ -498,7 +500,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should return original template when rowIndex is undefined', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: undefined,
|
||||
@ -516,7 +518,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should return original template when template is null', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const position: ModulePositionInput = {
|
||||
rowIndex: 0,
|
||||
@ -530,7 +532,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should handle edge case with no modules in row', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithEmptyRow: PageTemplateFragment = {
|
||||
...mockTemplate,
|
||||
@ -562,7 +564,7 @@ describe('useTemplateOperations', () => {
|
||||
|
||||
describe('upsertTemplate', () => {
|
||||
it('should upsert personal template with correct input', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
mockUpsertPageTemplateMutation.mockResolvedValue({
|
||||
data: {
|
||||
@ -593,7 +595,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should upsert existing personal template with URN', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
mockUpsertPageTemplateMutation.mockResolvedValue({
|
||||
data: {
|
||||
@ -624,7 +626,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should upsert global template with correct input', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
mockUpsertPageTemplateMutation.mockResolvedValue({
|
||||
data: {
|
||||
@ -655,7 +657,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should update user settings when creating personal template', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
mockUpsertPageTemplateMutation.mockResolvedValue({
|
||||
data: {
|
||||
@ -679,7 +681,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should not update user settings when updating existing personal template', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
mockUpsertPageTemplateMutation.mockResolvedValue({
|
||||
data: {
|
||||
@ -697,7 +699,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should handle template with empty rows', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const templateWithEmptyRows: PageTemplateFragment = {
|
||||
urn: 'urn:li:pageTemplate:empty',
|
||||
@ -742,7 +744,7 @@ describe('useTemplateOperations', () => {
|
||||
});
|
||||
|
||||
it('should handle mutation error', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations());
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
const error = new Error('Mutation failed');
|
||||
mockUpsertPageTemplateMutation.mockRejectedValue(error);
|
||||
@ -750,4 +752,61 @@ describe('useTemplateOperations', () => {
|
||||
await expect(result.current.upsertTemplate(mockTemplate, true, null)).rejects.toThrow('Mutation failed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetTemplateToDefault', () => {
|
||||
it('should call setPersonalTemplate with null', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
act(() => {
|
||||
result.current.resetTemplateToDefault();
|
||||
});
|
||||
|
||||
expect(setPersonalTemplate).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should call updateUserHomePageSettingsMutation with pageTemplate: null', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
act(() => {
|
||||
result.current.resetTemplateToDefault();
|
||||
});
|
||||
|
||||
expect(mockUpdateUserHomePageSettings).toHaveBeenCalledWith({
|
||||
variables: {
|
||||
input: {
|
||||
removePageTemplate: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should call setPersonalTemplate and mutation exactly once on multiple calls', () => {
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
act(() => {
|
||||
result.current.resetTemplateToDefault();
|
||||
result.current.resetTemplateToDefault();
|
||||
});
|
||||
|
||||
expect(setPersonalTemplate).toHaveBeenCalledTimes(2);
|
||||
expect(mockUpdateUserHomePageSettings).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should handle async mutation call correctly', async () => {
|
||||
const { result } = renderHook(() => useTemplateOperations(setPersonalTemplate));
|
||||
|
||||
await act(async () => {
|
||||
await result.current.resetTemplateToDefault();
|
||||
});
|
||||
|
||||
expect(setPersonalTemplate).toHaveBeenCalledWith(null);
|
||||
expect(mockUpdateUserHomePageSettings).toHaveBeenCalledWith({
|
||||
variables: {
|
||||
input: {
|
||||
removePageTemplate: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -43,7 +43,7 @@ const isValidRemovalPosition = (template: PageTemplateFragment | null, position:
|
||||
return rowIndex !== undefined && rowIndex >= 0 && rowIndex < rows.length;
|
||||
};
|
||||
|
||||
export function useTemplateOperations() {
|
||||
export function useTemplateOperations(setPersonalTemplate: (template: PageTemplateFragment | null) => void) {
|
||||
const [upsertPageTemplateMutation] = useUpsertPageTemplateMutation();
|
||||
const [updateUserHomePageSettings] = useUpdateUserHomePageSettingsMutation();
|
||||
|
||||
@ -194,9 +194,21 @@ export function useTemplateOperations() {
|
||||
[upsertPageTemplateMutation, updateUserHomePageSettings],
|
||||
);
|
||||
|
||||
const resetTemplateToDefault = () => {
|
||||
setPersonalTemplate(null);
|
||||
updateUserHomePageSettings({
|
||||
variables: {
|
||||
input: {
|
||||
removePageTemplate: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
updateTemplateWithModule,
|
||||
removeModuleFromTemplate,
|
||||
upsertTemplate,
|
||||
resetTemplateToDefault,
|
||||
};
|
||||
}
|
||||
|
||||
@ -60,4 +60,5 @@ export type PageTemplateContextState = {
|
||||
moduleModalState: ModuleModalState;
|
||||
removeModule: (input: RemoveModuleInput) => void;
|
||||
moveModule: (input: MoveModuleInput) => void;
|
||||
resetTemplateToDefault: () => void;
|
||||
};
|
||||
|
||||
@ -0,0 +1,116 @@
|
||||
import { Button, Dropdown, colors } from '@components';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import analytics, { EventType } from '@app/analytics';
|
||||
import { useUserContext } from '@app/context/useUserContext';
|
||||
import { usePageTemplateContext } from '@app/homeV3/context/PageTemplateContext';
|
||||
import { ConfirmationModal } from '@app/sharedV2/modals/ConfirmationModal';
|
||||
|
||||
const ButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: ${colors.white};
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
position: fixed;
|
||||
right: 32px;
|
||||
bottom: 32px;
|
||||
border-radius: 200px;
|
||||
box-shadow: 0px 4px 12px 0px rgba(9, 1, 61, 0.12);
|
||||
`;
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
border-radius: 12px;
|
||||
box-shadow: 0px 4px 12px 0px rgba(9, 1, 61, 0.12);
|
||||
background-color: white;
|
||||
overflow: hidden; // Cleanly rounds edges
|
||||
|
||||
.ant-dropdown-menu-item {
|
||||
padding: 8px 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function EditHomePageSettingsButton() {
|
||||
const user = useUserContext();
|
||||
const canEditDefaultTemplate = user.platformPrivileges?.manageHomePageTemplates;
|
||||
|
||||
const { setIsEditingGlobalTemplate, isEditingGlobalTemplate, resetTemplateToDefault, personalTemplate } =
|
||||
usePageTemplateContext();
|
||||
|
||||
const isOnPersonalTemplate = !!personalTemplate;
|
||||
|
||||
const [showConfirmResetModal, setShowConfirmResetModal] = useState(false);
|
||||
|
||||
const startGlobalTemplateEdit = useCallback(() => {
|
||||
setIsEditingGlobalTemplate(true);
|
||||
analytics.event({
|
||||
type: EventType.HomePageTemplateGlobalTemplateEditingStart,
|
||||
});
|
||||
}, [setIsEditingGlobalTemplate]);
|
||||
|
||||
const handleResetToDefault = useCallback(() => {
|
||||
resetTemplateToDefault();
|
||||
setShowConfirmResetModal(false);
|
||||
analytics.event({
|
||||
type: EventType.HomePageTemplateResetToGlobalTemplate,
|
||||
});
|
||||
}, [resetTemplateToDefault]);
|
||||
|
||||
if (isEditingGlobalTemplate || (!canEditDefaultTemplate && !isOnPersonalTemplate)) return null;
|
||||
|
||||
const menu = {
|
||||
items: [
|
||||
...(canEditDefaultTemplate
|
||||
? [
|
||||
{
|
||||
label: 'Edit Organization Default',
|
||||
key: 'edit-organization-default',
|
||||
style: {
|
||||
color: colors.gray[600],
|
||||
fontSize: '14px',
|
||||
},
|
||||
onClick: startGlobalTemplateEdit,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(isOnPersonalTemplate
|
||||
? [
|
||||
{
|
||||
label: 'Reset to Organization Default',
|
||||
key: 'reset-to-organization-default',
|
||||
style: {
|
||||
color: colors.red[1000],
|
||||
fontSize: '14px',
|
||||
},
|
||||
onClick: () => setShowConfirmResetModal(true),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonWrapper>
|
||||
<Dropdown
|
||||
menu={menu}
|
||||
trigger={['click']}
|
||||
dropdownRender={(menuNode) => <DropdownContainer>{menuNode}</DropdownContainer>}
|
||||
>
|
||||
<Button icon={{ icon: 'Gear', color: 'gray', source: 'phosphor', size: '4xl' }} variant="text" />
|
||||
</Dropdown>
|
||||
</ButtonWrapper>
|
||||
<ConfirmationModal
|
||||
isOpen={!!showConfirmResetModal}
|
||||
handleConfirm={handleResetToDefault}
|
||||
handleClose={() => setShowConfirmResetModal(false)}
|
||||
modalTitle="Confirm reset to default template"
|
||||
modalText="Are you sure you want to reset your homepage to the organization's default template? You will lose all your personal modules."
|
||||
closeButtonText="Cancel"
|
||||
confirmButtonText="Confirm"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -54,7 +54,7 @@ export const ConfirmationModal = ({
|
||||
centered
|
||||
footer={
|
||||
<ButtonsContainer>
|
||||
<Button variant="text" onClick={handleClose} data-testid="modal-cancel-button">
|
||||
<Button variant="text" color="gray" onClick={handleClose} data-testid="modal-cancel-button">
|
||||
{closeButtonText || 'Cancel'}
|
||||
</Button>
|
||||
<Button variant="filled" onClick={handleConfirm} data-testid="modal-confirm-button">
|
||||
|
||||
@ -69,6 +69,7 @@ query getMe {
|
||||
viewStructuredPropertiesPage
|
||||
manageApplications
|
||||
manageFeatures
|
||||
manageHomePageTemplates
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user