Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(CookieConsent): add CookieConsent component #123

Merged
merged 1 commit into from
Dec 6, 2023
Merged

Conversation

Lakate
Copy link
Contributor

@Lakate Lakate commented Nov 24, 2023

No description provided.

@gravity-ui-bot
Copy link
Contributor

Preview is ready.

@Lakate Lakate force-pushed the feat/cookie-consent branch from 5f6202f to 59df049 Compare November 24, 2023 13:22
@Lakate
Copy link
Contributor Author

Lakate commented Nov 24, 2023

@Lakate Lakate force-pushed the feat/cookie-consent branch from 59df049 to 55bd842 Compare November 27, 2023 14:24
sameSite: true,
};

export enum ConsentType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use enums, or at least let's not force users to use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain please
I see that we already have enums in components and even export them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -0,0 +1,164 @@
import _ from 'lodash';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import _ from 'lodash';
import pick from 'lodash/pick';

@@ -0,0 +1,100 @@
import React, {useEffect} from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We enforce this React import syntax in uikit and plan to do so here.

Suggested change
import React, {useEffect} from 'react';
import React from 'react';

}, 1000);

return () => clearTimeout(timeoutId);
}, [disableInitialOpen]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all dependencies are listed

);
}

export function Collapse({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use Disclosure component form uikit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

<span
className={b('link')}
onClick={onChangeStep(ConsentPopupStep.Manage)}
onKeyDown={onChangeStep(ConsentPopupStep.Manage)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you press any key, for example tab, you go to the next step.

event.stopPropagation();
}}
>
<Checkbox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not place interactive content inside a button; it is not accessible.

onClose,
} = props;

const onClick = useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the use of useCallback is unnecessarily


useEffect(() => {
if (!isNotificationMode) {
consentManager.subscribe(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does unsubscription take place?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

return this.consentEdition;
}

get projectCEdition() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better projectEdition?

@Lakate Lakate force-pushed the feat/cookie-consent branch 5 times, most recently from 27b7e6a to 5dfa8df Compare December 1, 2023 10:04
@Lakate Lakate force-pushed the feat/cookie-consent branch 2 times, most recently from 951f5fe to db5ebb5 Compare December 1, 2023 12:12
@Lakate Lakate force-pushed the feat/cookie-consent branch 2 times, most recently from bc4581b to 761b66f Compare December 1, 2023 12:38
// do something: e.g. sent events to analytics
}, []);

React.useMount(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is useMount? I don't know such a hook in React.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like forgot to fix, thank you
fixed

);

React.useEffect(() => {
setCurrentConsents(getCurrentConsents(consentManager));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need also subscribe to changes of consents?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we need for managing visibility


const b = block('consent-popup');

const getCurrentConsents = (consentManager: ConsentManager) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not a logic of consentManager itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In consentManager we have getConsents that returns actual consents. If we haven't defined consetns yet, we need to show consent component

But in ConsentPopup we need to define all consent types because we need to show them in FoldableList

return getCurrentConsents(consentManager);
});
const [currentStep, setCurrentStep] = React.useState<`${ConsentPopupStep}`>(step);
const onChangeStep = React.useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need useCallback here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

};
});
}, [cookieList, currentConsents]);
const onChoose = React.useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need useCallback here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 4 to 6
value: boolean,
cookiesTypes: `${ConsentType}`[],
onlyNecessary?: boolean,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange interface, if onlyNecessary=true, then value is not used, it's not obvious. Seems better:

function prepareConsent(consent: 'All' | 'None' | 'onlyNecessary', cookiesTypes)

and why is this not part of the ConsentManager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to ConsentManager and change interface

Comment on lines 31 to 35
const isConsentsDefined = consentManager.isAllConsentsDefined();
const shouldOpen = isNotificationMode
? !consentManager.isClosed() || !isConsentsDefined
: !isConsentsDefined;
const differentEdition = consentManager.projectEdition !== consentManager.edition;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems, this logic should be inside consentManager

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disagree, consentManager works only with cookies and managing them
Logic about component visibility should be inside the component

return consentManager.subscribe(() => {
setIsOpened(!consentManager.isAllConsentsDefined());
});
}, [consentManager, isNotificationMode]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it depend on isNotificationMode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

consentManager,
onConsentPopupClose,
disableInitialOpen,
onAction,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use case for this props?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now - we use it in storybook
But anyone can use it if wants to have own callback

step?: `${ConsentPopupStep}`;
cookieList?: ConsentPopupCookieListItem[];
/* To open by the link or button, so the popup should not be opened at this moment */
forceOpenManageStep?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find where this is used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@Lakate Lakate force-pushed the feat/cookie-consent branch 3 times, most recently from b525933 to 98073fc Compare December 4, 2023 13:01
private readonly subscribers: Subscriber[] = [];
private readonly cookieSettings: CookieSettings = CONSENT_COOKIE_SETTINGS;

constructor(mode: `${ConsentMode}`, edition?: number) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
constructor(mode: `${ConsentMode}`, edition?: number) {
constructor({
mode,
edition,
cookieSettings = CONSENT_COOKIE_SETTINGS
}: {mode: `${ConsentMode}`, edition?: number, cookieSettings?: CookieSettings}) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 106 to 120
setCookieSettings(settings: Partial<CookieSettings>) {
Object.assign(this.cookieSettings, settings);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
setCookieSettings(settings: Partial<CookieSettings>) {
Object.assign(this.cookieSettings, settings);
}

I suggest setting it via constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 62 to 69
set mode(newMode: `${ConsentMode}`) {
this.consentMode = newMode;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
set mode(newMode: `${ConsentMode}`) {
this.consentMode = newMode;
}

With current use of ConsentManager it should be done via creating a new ConsentManager.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consentManager should be only one in service

This method is necessary for this scenario: in Notification mode we still want to provide the ability to manage settings. Therefore, when we want to open ConsentPopup on manage step we switch the mode and open it

return this.cookieSettings;
}

getConsents() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think that this should return the same as getCurrentConsents.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

};
}

setConsents(consents: Consents) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this:

Suggested change
setConsents(consents: Consents) {
setConsents(consents: Consents | 'All' | 'OnlyNecessary') {

and make prepareConsent private?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


const onConsentPopupAction = (consents: Consents) => {
consentManager.setConsents(consents);
setIsOpened(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onAction is always called with onClose

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add onConsentPopupClose in onConsentPopupAction

const onButtonClick = (onlyNecessary?: boolean) => {
return () => {
onAction(consentManager.prepareConsent(onlyNecessary ? 'OnlyNecessary' : 'All'));
onClose?.();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onClose is not optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

};
const confirmSelectedConsent = () => {
onAction(currentConsents);
onClose?.();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onClose is not optional.

Copy link
Contributor Author

@Lakate Lakate Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

const onClick = (isAll: boolean) => {
return () => {
onAction(consentManager.prepareConsent(isAll ? 'All' : 'OnlyNecessary'));
onClose?.();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onClose is not optional.

Copy link
Contributor Author

@Lakate Lakate Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted from SimpleConsent

Comment on lines 159 to 162
newValue = {
...newValue,
[AdditionalConsentParams.Closed]: true,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
newValue = {
...newValue,
[AdditionalConsentParams.Closed]: true,
};
newValue[AdditionalConsentParams.Closed] = true;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@Lakate Lakate force-pushed the feat/cookie-consent branch from 98073fc to fc98d41 Compare December 5, 2023 12:27
@Lakate Lakate force-pushed the feat/cookie-consent branch 7 times, most recently from b60ebbc to 56bebb1 Compare December 6, 2023 13:03
@Lakate Lakate force-pushed the feat/cookie-consent branch from 56bebb1 to 108205e Compare December 6, 2023 13:10
@Lakate Lakate merged commit 1572965 into main Dec 6, 2023
3 checks passed
@Lakate Lakate deleted the feat/cookie-consent branch December 6, 2023 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants