From 94a6732fc8010a81852ede9f93198c1513e3e1ab Mon Sep 17 00:00:00 2001 From: jared-dickman Date: Wed, 5 Jun 2024 17:40:00 -0400 Subject: [PATCH 1/5] chore: add generic typing to table component (#259) --- src/components/data-display/Table/Table.tsx | 7 ++++--- src/components/data-display/Tag/Tag.tsx | 2 +- src/components/data-entry/QueryItem/Cascader.stories.tsx | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/data-display/Table/Table.tsx b/src/components/data-display/Table/Table.tsx index cc15733ba..499f66224 100644 --- a/src/components/data-display/Table/Table.tsx +++ b/src/components/data-display/Table/Table.tsx @@ -1,17 +1,18 @@ import { Table as AntTable } from 'antd' import { type TableProps as AntTableProps } from 'antd' +import { type AnyObject } from 'antd/es/_util/type' import { ConfigProvider } from 'src/components' import { type ColumnType, type ExpandableConfig } from 'antd/es/table/interface' import { type ColumnsType, type TableProps } from 'antd/es/table' -export interface ITableProps extends AntTableProps {} +export interface ITableProps extends AntTableProps {} export type { ColumnType, ExpandableConfig, ColumnsType, TableProps } -export const Table = (props: ITableProps) => { +export const Table = (props: ITableProps) => { return ( - + {...props} /> ) } diff --git a/src/components/data-display/Tag/Tag.tsx b/src/components/data-display/Tag/Tag.tsx index 001183cf0..50dacfedd 100644 --- a/src/components/data-display/Tag/Tag.tsx +++ b/src/components/data-display/Tag/Tag.tsx @@ -1,6 +1,6 @@ import { Tag as AntTag } from 'antd' import { type TagProps as AntTagProps } from 'antd' -import { type CheckableTagProps as AntCheckableTagProps } from 'antd/lib/tag' +import { type CheckableTagProps as AntCheckableTagProps } from 'antd/es/tag' import { ConfigProvider } from 'src/components' export interface ITagProps extends AntTagProps { diff --git a/src/components/data-entry/QueryItem/Cascader.stories.tsx b/src/components/data-entry/QueryItem/Cascader.stories.tsx index 24b1cb3fc..c74d9844e 100644 --- a/src/components/data-entry/QueryItem/Cascader.stories.tsx +++ b/src/components/data-entry/QueryItem/Cascader.stories.tsx @@ -103,7 +103,7 @@ export const Error: Story = { }, } -export const Icon: Story = { +export const WithIcon: Story = { args: { placeholder: 'QueryItem.ValueSelector.Cascader Icon', options: exampleOptions, @@ -140,4 +140,4 @@ export const LoadData: Story = { console.log(value) }, }, -} +} \ No newline at end of file From ae9a2b0387b7474d13950078cd5b2ee663848ba7 Mon Sep 17 00:00:00 2001 From: Gaby Zifferman Date: Thu, 6 Jun 2024 23:30:55 +0200 Subject: [PATCH 2/5] feat: minimap active state (#263) --- .../GlobalNavigation.stories.tsx | 3 ++- .../GlobalNavigationItems.d.ts | 1 + .../GlobalNavigation/HomeButton.tsx | 2 ++ src/components/navigation/MiniMap/MiniMap.tsx | 1 + .../navigation/MiniMap/SvgLinker.tsx | 19 +++++++++++---- src/components/navigation/MiniMap/miniMap.css | 24 +++++++++++++++++++ src/utils/utils.css | 4 ++-- 7 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/components/navigation/GlobalNavigation/GlobalNavigation.stories.tsx b/src/components/navigation/GlobalNavigation/GlobalNavigation.stories.tsx index 6b7edc59f..69cc029bc 100644 --- a/src/components/navigation/GlobalNavigation/GlobalNavigation.stories.tsx +++ b/src/components/navigation/GlobalNavigation/GlobalNavigation.stories.tsx @@ -487,7 +487,8 @@ export const MP: Story = { overviewHref: '/', onLinkClick: link => alert(link.href), onUnauthorizedClick: link => alert(`unauthorized ${link?.href} `), - unauthorizedLinks: ['oversight', 'dataPlatform'], + unauthorizedLinks: ['dataPlatform'], + activeLink: 'oversight', links: [ { linkId: 'oversight', href: '/oversight' }, { linkId: 'dataPlatform', href: '/data-platform' }, diff --git a/src/components/navigation/GlobalNavigation/GlobalNavigationItems.d.ts b/src/components/navigation/GlobalNavigation/GlobalNavigationItems.d.ts index 7bc4055f1..557c4849f 100644 --- a/src/components/navigation/GlobalNavigation/GlobalNavigationItems.d.ts +++ b/src/components/navigation/GlobalNavigation/GlobalNavigationItems.d.ts @@ -44,4 +44,5 @@ export interface IMiniMapOptions { onLinkClick: (link: MiniMapLink) => void onUnauthorizedClick: (link?: MiniMapLink) => void unauthorizedLinks: MiniMapLinks[] + activeLink: MiniMapLinks } diff --git a/src/components/navigation/GlobalNavigation/HomeButton.tsx b/src/components/navigation/GlobalNavigation/HomeButton.tsx index 22e823d63..f4f061833 100644 --- a/src/components/navigation/GlobalNavigation/HomeButton.tsx +++ b/src/components/navigation/GlobalNavigation/HomeButton.tsx @@ -38,6 +38,7 @@ function MinimapWithPopover(props: MinimapWithPopoverProps) { links={props.links} onLinkClick={props.onLinkClick} unauthorizedLinks={props.unauthorizedLinks} + activeLink={props.activeLink} /> )} placement="rightBottom" @@ -68,6 +69,7 @@ export function HomeButton(props: HomeButtonProps) { onLinkClick={props.minimapOptions.onLinkClick} unauthorizedLinks={props.minimapOptions.unauthorizedLinks} onPopoverClick={props.onMpHomeClick} + activeLink={props.minimapOptions.activeLink} /> ) } diff --git a/src/components/navigation/MiniMap/MiniMap.tsx b/src/components/navigation/MiniMap/MiniMap.tsx index 450bbc239..d57dc54f9 100644 --- a/src/components/navigation/MiniMap/MiniMap.tsx +++ b/src/components/navigation/MiniMap/MiniMap.tsx @@ -25,6 +25,7 @@ const Minimap = (props: IMiniMapProps) => { href: link.href, variant: 'drop-shadow', isUnauthorized: props.unauthorizedLinks.includes(link.linkId), + isActive: props.activeLink === link.linkId, })) return ( diff --git a/src/components/navigation/MiniMap/SvgLinker.tsx b/src/components/navigation/MiniMap/SvgLinker.tsx index 2c435147f..94f2667a2 100644 --- a/src/components/navigation/MiniMap/SvgLinker.tsx +++ b/src/components/navigation/MiniMap/SvgLinker.tsx @@ -6,6 +6,7 @@ export interface ISvgLink { href: string variant?: 'regular' | 'black' | 'drop-shadow' isUnauthorized?: boolean + isActive?: boolean } interface ISvgLinkerProps { @@ -21,10 +22,16 @@ export const SvgLinker = (props: ISvgLinkerProps) => { const href = target.closest('a')?.getAttribute('href') const link = props.links.find(b => b.href === href) - if (link) props.onLinkClick(link) + if (link) { + props.onLinkClick(link) + } } - return
{wrapButtonsIntoLinks(props.children)}
+ return ( +
+ {wrapButtonsIntoLinks(props.children)} +
+ ) function wrapButtonsIntoLinks(parent: React.ReactNode): React.ReactNode { const wrapElement = (element: ReactElement): ReactElement => { @@ -32,9 +39,11 @@ export const SvgLinker = (props: ISvgLinkerProps) => { const link = props.links.find(b => b.elementId === id) if (link) { - const className = `svg-linker-root__button svg-linker-root__button--${link.variant}${ - link.isUnauthorized ? ' svg-linker-root__button--disabled' : '' - }` + const isActiveClass = link.isActive ? ' svg-linker-root__button--active' : '' + const isUnauthorizedClass = link.isUnauthorized ? ' svg-linker-root__button--disabled' : '' + const linkStateClass = isActiveClass || isUnauthorizedClass + + const className = `svg-linker-root__button svg-linker-root__button--${link.variant} ${linkStateClass} ` return ( diff --git a/src/components/navigation/MiniMap/miniMap.css b/src/components/navigation/MiniMap/miniMap.css index 5fe049ab9..7d5ba38b4 100644 --- a/src/components/navigation/MiniMap/miniMap.css +++ b/src/components/navigation/MiniMap/miniMap.css @@ -1,7 +1,12 @@ +.svg-linker__container svg { + overflow: visible; +} +/* disabled general */ .svg-linker-root__button.svg-linker-root__button--disabled { cursor: default; } +/* disabled variant-regular */ .svg-linker-root__button.svg-linker-root__button--disabled.svg-linker-root__button--regular rect:first-child { fill: transparent; stroke: var(--color-border); @@ -15,6 +20,8 @@ fill: transparent; } + +/* disabled - variant: shadow */ .svg-linker-root__button.svg-linker-root__button--disabled.svg-linker-root__button--drop-shadow > g > g > rect { fill: var(--mp-brand-secondary-3); } @@ -27,6 +34,7 @@ filter: none; } +/* disabled - variant: black */ .svg-linker-root__button.svg-linker-root__button--disabled.svg-linker-root__button--black rect:first-child { fill: var(--mp-brand-secondary-6); } @@ -35,10 +43,12 @@ fill: var(--mp-brand-secondary-6); } +/* general - variant: shadow */ .svg-linker-root__button.svg-linker-root__button--drop-shadow:hover { filter: drop-shadow(0px 9px 28px rgba(0, 0, 0, 0.05)) drop-shadow(0px 3px 6px rgba(0, 0, 0, 0.12)) drop-shadow(0px 6px 16px rgba(0, 0, 0, 0.08)); } +/* general - variant: black */ .svg-linker-root__button.svg-linker-root__button--regular:hover rect:first-child { fill: var(--mp-brand-primary-2); } @@ -46,3 +56,17 @@ .svg-linker-root__button.svg-linker-root__button--black:hover rect:first-child { fill: var(--mp-brand-secondary-7); } + +/* for the active state */ +.svg-linker-root__button--active > g > rect + rect { + stroke: var(--mp-brand-primary-6); + stroke-width: var(--line-width-bold) +} + +/* some fixes so the shadow on hover looks good without changing the svg */ +#clip0_5505_13516 { + display: none; +} +#Frame\ 481773 > #Frame\ 481772 > rect { + display: none; +} \ No newline at end of file diff --git a/src/utils/utils.css b/src/utils/utils.css index e49aed216..24b3cb166 100644 --- a/src/utils/utils.css +++ b/src/utils/utils.css @@ -11,5 +11,5 @@ } .u-padding-sm { - padding:var(--padding-sm) -} \ No newline at end of file + padding:var(--padding-sm) !important; +} From 21a399c3afb60bde0737d472db095fba22c41d63 Mon Sep 17 00:00:00 2001 From: Gaby Zifferman Date: Fri, 7 Jun 2024 12:24:04 +0200 Subject: [PATCH 3/5] fix: hide minimap after user clicks on a button (#264) --- .../GlobalNavigation/HomeButton.tsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/components/navigation/GlobalNavigation/HomeButton.tsx b/src/components/navigation/GlobalNavigation/HomeButton.tsx index f4f061833..31253d12f 100644 --- a/src/components/navigation/GlobalNavigation/HomeButton.tsx +++ b/src/components/navigation/GlobalNavigation/HomeButton.tsx @@ -1,7 +1,7 @@ -import React from 'react' +import React, { useState } from 'react' import { Center, Icon, Popover, Tooltip } from 'src/components' import MiniMap from 'src/components/navigation/MiniMap/MiniMap' -import { IMiniMapOptions } from 'src/components/navigation/GlobalNavigation/GlobalNavigationItems' +import { IMiniMapOptions, MiniMapLink } from 'src/components/navigation/GlobalNavigation/GlobalNavigationItems' interface MpHomeButtonProps { onClick: () => void @@ -29,19 +29,30 @@ function MpHomeButton(props: MpHomeButtonProps) { } function MinimapWithPopover(props: MinimapWithPopoverProps) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false) + const handleLinkClick = (link: MiniMapLink) => { + setIsPopoverOpen(false) + props.onLinkClick(link) + } + const handlePopoverOpenChange = (newPopoverState: boolean) => { + setIsPopoverOpen(newPopoverState) + } + return ( ( + content={ - )} + } placement="rightBottom" + open={isPopoverOpen} + onOpenChange={handlePopoverOpenChange} arrow={false}> From 8ab9ce9a5e08284b5956ed91b9a1581b00b4678f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Tib=C3=BArcio?= Date: Fri, 7 Jun 2024 14:18:50 -0300 Subject: [PATCH 4/5] feat: allows UPS to receive cookie config options (#261) Co-authored-by: mparticle-automation --- CHANGELOG.md | 19 ++++ package-lock.json | 102 ++++++++---------- package.json | 3 +- .../user-preferences-service.spec.ts | 15 +-- .../user-preferences/user-preferences.ts | 15 ++- src/utils/Cookies.ts | 51 +++++++-- 6 files changed, 120 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36d02e8d9..effd9c6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +# [1.17.0-ups-configurable-cookie.2](https://github.com/mParticle/aquarium/compare/v1.17.0-ups-configurable-cookie.1...v1.17.0-ups-configurable-cookie.2) (2024-06-07) + + +### Bug Fixes + +* hide minimap after user clicks on a button ([#264](https://github.com/mParticle/aquarium/issues/264)) ([21a399c](https://github.com/mParticle/aquarium/commit/21a399c3afb60bde0737d472db095fba22c41d63)) + + +### Features + +* minimap active state ([#263](https://github.com/mParticle/aquarium/issues/263)) ([ae9a2b0](https://github.com/mParticle/aquarium/commit/ae9a2b0387b7474d13950078cd5b2ee663848ba7)) + +# [1.17.0-ups-configurable-cookie.1](https://github.com/mParticle/aquarium/compare/v1.16.1...v1.17.0-ups-configurable-cookie.1) (2024-06-03) + + +### Features + +* allows UPS to receive cookie config options instead of only the key ([517d030](https://github.com/mParticle/aquarium/commit/517d03066bb1d55968d650bb7a2a6162a1567ad7)) + ## [1.16.1](https://github.com/mParticle/aquarium/compare/v1.16.0...v1.16.1) (2024-06-03) diff --git a/package-lock.json b/package-lock.json index dc29e5d79..7c1af3658 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mparticle/aquarium", - "version": "1.16.1", + "version": "1.17.0-ups-configurable-cookie.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mparticle/aquarium", - "version": "1.16.1", + "version": "1.17.0-ups-configurable-cookie.2", "license": "Apache-2.0", "dependencies": { "lodash.clonedeep": "4.5.0" @@ -48,6 +48,7 @@ "stylelint-config-recommended": "14.0.0", "stylelint-config-standard": "36.0.0", "stylelint-no-indistinguishable-colors": "2.1.0", + "type-fest": "^4.20.0", "typescript": "5.3.3", "vite": "5.0.12", "vite-plugin-dts": "3.7.2", @@ -5543,19 +5544,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@semantic-release/npm/node_modules/parse-json/node_modules/type-fest": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.13.1.tgz", - "integrity": "sha512-ASMgM+Vf2cLwDMt1KXSkMUDSYCxtckDJs8zsaVF/mYteIsiARKCVtyXtcK38mIKbLTctZP8v6GMqdNaeI3fo7g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@semantic-release/npm/node_modules/path-key": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", @@ -5589,19 +5577,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@semantic-release/npm/node_modules/read-pkg/node_modules/type-fest": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.13.1.tgz", - "integrity": "sha512-ASMgM+Vf2cLwDMt1KXSkMUDSYCxtckDJs8zsaVF/mYteIsiARKCVtyXtcK38mIKbLTctZP8v6GMqdNaeI3fo7g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@semantic-release/npm/node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -5686,6 +5661,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@semantic-release/npm/node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/npm/node_modules/unique-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", @@ -5872,19 +5860,6 @@ "node": ">=10" } }, - "node_modules/@semantic-release/release-notes-generator/node_modules/type-fest": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.13.1.tgz", - "integrity": "sha512-ASMgM+Vf2cLwDMt1KXSkMUDSYCxtckDJs8zsaVF/mYteIsiARKCVtyXtcK38mIKbLTctZP8v6GMqdNaeI3fo7g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@semantic-release/release-notes-generator/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -6706,6 +6681,18 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/csf/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/docs-mdx": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-3.0.0.tgz", @@ -7000,6 +6987,18 @@ "node": ">=10" } }, + "node_modules/@storybook/react/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@storybook/react/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -25556,19 +25555,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/type-fest": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.13.1.tgz", - "integrity": "sha512-ASMgM+Vf2cLwDMt1KXSkMUDSYCxtckDJs8zsaVF/mYteIsiARKCVtyXtcK38mIKbLTctZP8v6GMqdNaeI3fo7g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/semantic-release/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -27474,12 +27460,12 @@ } }, "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.0.tgz", + "integrity": "sha512-MBh+PHUHHisjXf4tlx0CFWoMdjx8zCMLJHOjnV1prABYZFHqtFOyauCIK2/7w4oIfwkF8iNhLtnJEfVY2vn3iw==", "dev": true, "engines": { - "node": ">=12.20" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/package.json b/package.json index 07d4b0a12..856b47b00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mparticle/aquarium", - "version": "1.16.1", + "version": "1.17.0-ups-configurable-cookie.2", "description": "mParticle Component Library", "license": "Apache-2.0", "keywords": [ @@ -65,6 +65,7 @@ "stylelint-config-recommended": "14.0.0", "stylelint-config-standard": "36.0.0", "stylelint-no-indistinguishable-colors": "2.1.0", + "type-fest": "^4.20.0", "typescript": "5.3.3", "vite": "5.0.12", "vite-plugin-dts": "3.7.2", diff --git a/src/services/user-preferences/user-preferences-service.spec.ts b/src/services/user-preferences/user-preferences-service.spec.ts index 786bbb2e2..212303cd9 100644 --- a/src/services/user-preferences/user-preferences-service.spec.ts +++ b/src/services/user-preferences/user-preferences-service.spec.ts @@ -51,9 +51,8 @@ describe('When testing the User Preferences Service', () => { userPreferencesService = new UserPreferencesService( definitions, compositeUserPreferencesService, - cookieKey, lowLevelScope, - () => new Date(), + { key: cookieKey }, ) await userPreferencesService.init() @@ -82,9 +81,8 @@ describe('When testing the User Preferences Service', () => { userPreferencesService = new UserPreferencesService( definitions, compositeUserPreferencesService, - cookieKey, currentScope, - () => new Date(), + { key: cookieKey }, ) await userPreferencesService.init() @@ -109,9 +107,8 @@ describe('When testing the User Preferences Service', () => { userPreferencesService = new UserPreferencesService( definitions, compositeUserPreferencesService, - cookieKey, someScope, - () => new Date(), + { key: cookieKey }, ) await userPreferencesService.init() @@ -148,9 +145,8 @@ describe('When testing the User Preferences Service', () => { userPreferencesService = new UserPreferencesService( definitions, compositeUserPreferencesService, - cookieKey, lowLevelScope, - () => new Date(), + { key: cookieKey }, ) await userPreferencesService.init() @@ -182,9 +178,8 @@ describe('When testing the User Preferences Service', () => { userPreferencesService = new UserPreferencesService( definitions, compositeUserPreferencesService, - cookieKey, lowLevelScope, - () => new Date(), + { key: cookieKey }, ) await userPreferencesService.init() diff --git a/src/services/user-preferences/user-preferences.ts b/src/services/user-preferences/user-preferences.ts index f6290bec6..608bb9a1e 100644 --- a/src/services/user-preferences/user-preferences.ts +++ b/src/services/user-preferences/user-preferences.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-extraneous-class,no-unused-vars,@typescript-eslint/no-unused-vars */ -import * as Cookies from '../../utils/Cookies' import { type UserPreferences } from 'src/services/user-preferences/models/storage-models/user-preferences' import { type CompositeUserPreferences } from 'src/services/user-preferences/models/user-preferences/composite-user-preferences' import { type UserPreferenceScope } from 'src/services/user-preferences/models/storage-models/user-preference-scope' import { type UserPreferenceDefinitions } from 'src/services/user-preferences/models/definitions/user-preference-definitions' import { type CompositeUserPreferencesService } from 'src/services/user-preferences/composite-user-preferences-service' +import * as Cookies from 'src/utils/Cookies' +import { type CookieOptions } from 'src/utils/Cookies' export class UserPreferencesService { public preferences!: CompositeUserPreferences @@ -12,9 +13,8 @@ export class UserPreferencesService { constructor( private readonly definitions: UserPreferenceDefinitions, private readonly compositeUserPreferencesService: CompositeUserPreferencesService, - private readonly cookieKey: string, private readonly currentScope: UserPreferenceScope, - public dateFormatter: () => Date, + private readonly cookieOptions: CookieOptions & { key: string }, private readonly onUpdate?: (resolvedPreferences: CompositeUserPreferences) => void, ) {} @@ -43,7 +43,7 @@ export class UserPreferencesService { // @ts-expect-error const { allowedScope } = this.definitions[userPreferenceId] - const currentStoredPreferences = Cookies.getObject(this.cookieKey) + const currentStoredPreferences = Cookies.getObject(this.cookieOptions.key) const storedPreferences = this.compositeUserPreferencesService.getUpdatedUserPreferenceStorageObject( userPreferenceId, @@ -69,14 +69,11 @@ export class UserPreferencesService { } private async getStoredPreferences(): Promise> { - return await Promise.resolve(Cookies.getObject(this.cookieKey) ?? {}) + return await Promise.resolve(Cookies.getObject(this.cookieOptions.key) ?? {}) } private async setStoredPreferences(storedPreferences: UserPreferences): Promise { - Cookies.putObject(this.cookieKey, storedPreferences, { - expires: this.dateFormatter(), - path: '/', - }) + Cookies.putObject(this.cookieOptions.key, storedPreferences, this.cookieOptions) await Promise.resolve() } diff --git a/src/utils/Cookies.ts b/src/utils/Cookies.ts index 267b7c3e1..61783dd04 100644 --- a/src/utils/Cookies.ts +++ b/src/utils/Cookies.ts @@ -1,3 +1,5 @@ +import { RequireOneOrNone } from 'type-fest' + export function get(key: string): string | null { const cookies = getAll() return cookies?.[key] ? cookies[key] : null @@ -12,23 +14,58 @@ export function getObject(key: string): string | null { return value ? JSON.parse(value) : value } -export function put(key: string, value: string | null, options: any /* TODO fix any */ = {}): void { - let expires = options.expires - if (value == null) expires = 'Thu, 01 Jan 1970 00:00:01 GMT' - if (typeof expires === 'string') expires = new Date(expires) +export type CookieOptions = RequireOneOrNone< + { + path?: string + domain?: string + secure?: boolean + expiresISOString: string + permanent: boolean + }, + 'expiresISOString' | 'permanent' +> + +export function put(key: string, value: string | null, options: CookieOptions = {}): void { let str = `${_encode(key)}=${value != null ? _encode(value) : ''}` if (options.path) str += `; path=${options.path}` if (options.domain) str += `; domain=${options.domain}` - if (options.expires) str += `; expires=${expires.toUTCString()}` + if (options.permanent || options.expiresISOString) + str += `; expires=${calculateExpires(value, options.permanent, options.expiresISOString)}` if (options.secure) str += '; secure' document.cookie = str } -export function putObject(key: string, value: Record, options = {}): void { +/** + * This code came from the aurelia-cookie plugin initially and the way they remove a cookie + * is by calling the put method with a null value and the same options as the cookie that needs to be removed. + * + * This null value makes the cookie expire immediately by setting the expires attribute to a date in the past. + * I'm keeping the same logic, but we should consider using a more robust library for cookie management. + * + * If we don't set the expires option, the cookie Expires property in the browser becomes "Session", which + * doesn't seem to have a predictable behaviour across different browsers. + * + * @see https://stackoverflow.com/questions/4132095/when-does-a-cookie-with-expiration-time-at-end-of-session-expire + */ +function calculateExpires(value: string | null, permanent?: boolean, expires?: string): string { + const defaultExpires = 'Thu, 01 Jan 1970 00:00:01 GMT' + + if (value === null) { + return defaultExpires + } + + if (permanent) { + return 'Sat, 31 Dec 2044 23:59:59 GMT' + } + + return expires ?? defaultExpires +} + +export function putObject(key: string, value: Record, options: CookieOptions = {}): void { put(key, JSON.stringify(value), options) } -export function remove(key: string, options = {}): void { +export function remove(key: string, options: CookieOptions = {}): void { put(key, null, options) } From 63f8c3d98fd8ff67bda9d286e0e380962b416931 Mon Sep 17 00:00:00 2001 From: mparticle-automation Date: Fri, 7 Jun 2024 17:20:55 +0000 Subject: [PATCH 5/5] chore(release): 1.17.0 [skip ci] # [1.17.0](https://github.com/mParticle/aquarium/compare/v1.16.1...v1.17.0) (2024-06-07) ### Bug Fixes * hide minimap after user clicks on a button ([#264](https://github.com/mParticle/aquarium/issues/264)) ([21a399c](https://github.com/mParticle/aquarium/commit/21a399c3afb60bde0737d472db095fba22c41d63)) ### Features * allows UPS to receive cookie config options ([#261](https://github.com/mParticle/aquarium/issues/261)) ([8ab9ce9](https://github.com/mParticle/aquarium/commit/8ab9ce9a5e08284b5956ed91b9a1581b00b4678f)) * minimap active state ([#263](https://github.com/mParticle/aquarium/issues/263)) ([ae9a2b0](https://github.com/mParticle/aquarium/commit/ae9a2b0387b7474d13950078cd5b2ee663848ba7)) --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index effd9c6f9..98243052e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [1.17.0](https://github.com/mParticle/aquarium/compare/v1.16.1...v1.17.0) (2024-06-07) + + +### Bug Fixes + +* hide minimap after user clicks on a button ([#264](https://github.com/mParticle/aquarium/issues/264)) ([21a399c](https://github.com/mParticle/aquarium/commit/21a399c3afb60bde0737d472db095fba22c41d63)) + + +### Features + +* allows UPS to receive cookie config options ([#261](https://github.com/mParticle/aquarium/issues/261)) ([8ab9ce9](https://github.com/mParticle/aquarium/commit/8ab9ce9a5e08284b5956ed91b9a1581b00b4678f)) +* minimap active state ([#263](https://github.com/mParticle/aquarium/issues/263)) ([ae9a2b0](https://github.com/mParticle/aquarium/commit/ae9a2b0387b7474d13950078cd5b2ee663848ba7)) + # [1.17.0-ups-configurable-cookie.2](https://github.com/mParticle/aquarium/compare/v1.17.0-ups-configurable-cookie.1...v1.17.0-ups-configurable-cookie.2) (2024-06-07) diff --git a/package-lock.json b/package-lock.json index 7c1af3658..441576719 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mparticle/aquarium", - "version": "1.17.0-ups-configurable-cookie.2", + "version": "1.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mparticle/aquarium", - "version": "1.17.0-ups-configurable-cookie.2", + "version": "1.17.0", "license": "Apache-2.0", "dependencies": { "lodash.clonedeep": "4.5.0" diff --git a/package.json b/package.json index 856b47b00..3668c09eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mparticle/aquarium", - "version": "1.17.0-ups-configurable-cookie.2", + "version": "1.17.0", "description": "mParticle Component Library", "license": "Apache-2.0", "keywords": [