@sberid/js-sdk
Version:
Javascript SDK для партнеров Сбер ID, упрощающая подключение SberbankID на сайте.
311 lines (257 loc) • 11.8 kB
text/typescript
import equal from 'fast-deep-equal';
import {generateRandom} from '../sberid-sdk/utils';
import {UserHelper} from '../helper';
import {User} from '../interfaces/common';
import {BUTTON_TEXT} from './constants';
import {SberidButtonText, SberidButtonConfig} from './interfaces';
import {hideLoader, hideOnClickOutside, log, showLoader} from '../utils/common';
import {sendSberAnalytics} from '../sberid-analytics';
import {SberidSDKProps} from '../sberid-sdk';
export class SberidButton {
link: HTMLElement | undefined;
config: SberidButtonConfig;
userHelper: UserHelper;
user: User | undefined;
container: HTMLElement;
changeUserElement: HTMLElement | undefined;
changeUserPopupElement: HTMLElement | undefined;
text: SberidButtonText;
constructor(
config: SberidSDKProps,
container: HTMLElement,
onClick: (e: Event, link?: HTMLElement) => void,
) {
this.config = {
personalization: !!config.personalization,
debug: !!config.debug,
sa: !!config.sa?.enable,
changeUser: !!config.changeUser,
type: config.buttonProps?.type || 'default',
loader: config.buttonProps?.loader ?? true,
logo: config.buttonProps?.logo ?? true,
size: config.buttonProps?.size || 'default',
};
this.container = container;
this.text = {
...BUTTON_TEXT[this.config.type],
...(this.config.type === 'custom' ? config.buttonProps?.custom : {}),
};
this.userHelper = UserHelper.getInstance();
this.userHelper.setListener(this.handleUserChange.bind(this));
this.link = this.create();
if (onClick) {
this.link.addEventListener('click', (e) => {
onClick(e, this.link);
});
}
this.container.appendChild(this.link);
if (this.config.changeUser) {
this.initChangeUser();
}
}
initChangeUser(): void {
this.changeUserElement =
(this.link && this.link.querySelector<HTMLElement>('.sbid-button-change-user')) ||
undefined;
if (this.changeUserElement) {
this.changeUserPopupElement =
this.changeUserElement.querySelector<HTMLElement>(
'.sbid-button-change-user__popup',
) || undefined;
this.changeUserElement.addEventListener('click', (e) => {
if (this.changeUserElement) {
const isClosed = this.changeUserElement.dataset.stage === 'none';
this.changeUserElement.dataset.stage = isClosed ? 'popup' : 'none';
if (isClosed) {
if (this.changeUserPopupElement) {
hideOnClickOutside(this.changeUserPopupElement, () => {
if (this.changeUserElement) {
this.changeUserElement.dataset.stage = 'none';
}
});
}
}
}
e.preventDefault();
e.stopPropagation();
});
if (this.changeUserPopupElement) {
this.changeUserPopupElement.addEventListener('click', this.changeUser.bind(this));
}
}
}
async changeUser(e: Event): Promise<void> {
showLoader();
if (this.config.sa) {
sendSberAnalytics({
eventCategory: 'Login',
eventAction: 'sberid_Change_User_Button_Click',
eventType: 'Click',
});
}
if (this.config.debug) {
log(['Сбрасываем информацию о пользователе'], 'info');
}
if (await this.userHelper.resetUser()) {
if (this.config.debug) {
log(['Данные о пользователе удалены'], 'success');
}
if (this.config.sa) {
sendSberAnalytics({
eventCategory: 'Login',
eventAction: 'sberid_Change_User_Result',
eventType: 'Result',
description: 'success',
});
}
if (this.changeUserElement) {
this.changeUserElement.dataset.stage = 'none';
}
} else {
if (this.config.debug) {
log(['Ошибка при удалении данных о пользователе'], 'error');
}
if (this.config.sa) {
sendSberAnalytics({
eventCategory: 'Login',
eventAction: 'sberid_Change_User_Result',
eventType: 'Result',
description: 'fail',
});
}
if (this.changeUserElement) {
this.changeUserElement.dataset.stage === 'error';
const errorElement =
this.changeUserElement.querySelector<HTMLElement>(
'.sbid-button-change-user__error',
) || undefined;
if (errorElement) {
errorElement.innerHTML = 'Сервис временно недоступен';
hideOnClickOutside(errorElement, () => {
if (this.changeUserElement) {
this.changeUserElement.dataset.stage = 'none';
}
});
}
}
}
hideLoader();
e.preventDefault();
e.stopPropagation();
}
handleUserChange(user?: User): void {
if (!equal(user, this.user)) {
this.user = user;
this.setText();
}
}
getSize(): DOMRect {
const container = document.createElement('div');
const body = document.getElementsByTagName('body')[0];
const link = this.create();
container.className = 'sbid-check-button-container';
container.id = 'i-sbid-check-button-container';
container.appendChild(link);
body.appendChild(container);
const size = link.getBoundingClientRect();
container.remove();
return size;
}
isEnoughSpaceFromPersonalization(): boolean {
const buttonSize = this.getSize();
const changeUserBlockWidth = this.config.changeUser ? 24 : 0;
if (
buttonSize.width + changeUserBlockWidth >=
this.container.getBoundingClientRect()?.width
) {
return false;
}
return true;
}
create(): HTMLElement {
const link = document.createElement('a');
link.className = `sbid-button sbid-button--${this.config.size}`;
link.id = `i-sbid-button-${generateRandom(6)}`;
link.dataset.personalization = 'false';
link.innerHTML = `
${
this.config.logo
? '<span class="sbid-button__logo"><svg style="display: block" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13 0C16.0927 0 18.9337 1.08103 21.1657 2.88421L18.6371 4.74793C17.0315 3.64848 15.0899 3.00354 13 3.00354C7.48924 3.00354 3.00587 7.48999 3.00587 13.0013C3.00587 18.5126 7.48924 22.9965 13 22.9965C18.5134 22.9965 22.9968 18.5126 22.9968 13.0013C22.9968 12.9118 22.9941 12.8223 22.9924 12.7328L25.7912 10.6699C25.9289 11.4245 26 12.2055 26 13.0013C26 20.1807 20.1795 26 13 26C5.82135 26 0 20.1807 0 13.0013C0 5.81931 5.82135 0 13 0ZM23.2856 5.05241C23.9006 5.84651 24.4262 6.71169 24.8456 7.63565L13.0002 16.3673L8.05093 13.2628V9.52921L13.0002 12.6337L23.2856 5.05241Z" fill=":logoFill:"/></svg></span>'
: ''
}
<span class="sbid-button__text">${this.getText().text}</span>
${
this.config.changeUser
? '<span class="sbid-button-change-user" data-stage="none"><svg width="4" height="18" viewBox="0 0 4 18" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="2" cy="2" r="2" fill="white"/><circle cx="2" cy="9" r="2" fill="white"/><circle cx="2" cy="16" r="2" fill="white"/></svg><span class="sbid-button-change-user__popup">Сменить пользователя</span></span><span class="sbid-button-change-user__error"></span></span>'
: ''
}
${
this.config.loader
? '<span class="sbid-button-loader"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve"><path opacity="0.2" fill="#fff" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946 s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634 c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"/><path fill="#fff" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 C22.32,8.481,24.301,9.057,26.013,10.047z"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur="0.5s" repeatCount="indefinite"/></path></svg></span>'
: ''
}
`;
return link;
}
getText(): {
text: string;
personalization: boolean;
} {
if (this.config.personalization && this.user) {
const userName: string[] = [];
if (this.user.firstname) {
userName.push(this.user.firstname);
}
if (this.user.surname) {
userName.push(this.user.surname);
}
return {
text: this.text.personal.replace('{{userName}}', userName.join(' ')),
personalization: true,
};
}
return {
text: this.text.anonymous,
personalization: false,
};
}
setText(): void {
if (this.isEnoughSpaceFromPersonalization() && this.link) {
const buttonText = this.link.querySelector('.sbid-button__text');
const text = this.getText();
if (buttonText) {
buttonText.innerHTML = text.text;
}
this.link.dataset.personalization = text.personalization.toString();
}
}
disable(): void {
this.link?.setAttribute('disabled', 'disabled');
}
enable(): void {
this.link?.removeAttribute('disabled');
}
isDisabled(): boolean | undefined {
return this.link?.hasAttribute('disabled');
}
setUrl(url: string): void {
this.link?.setAttribute('href', url);
}
getButtonElement(): HTMLElement | undefined {
return this.link;
}
}
export class SberidNotificationBannerButton extends SberidButton {
constructor(props: SberidSDKProps, container: HTMLElement, onClick: (e: Event) => void) {
const config: SberidSDKProps = {
...props,
buttonProps: {
type: 'resume',
},
};
super(config, container, onClick);
}
isEnoughSpaceFromPersonalization(): boolean {
return true;
}
}