Skip to content

Commit

Permalink
feat: share qr code with tenant logo, retrieve tenant data and config…
Browse files Browse the repository at this point in the history
… from api
  • Loading branch information
nzambello committed Dec 5, 2023
1 parent 863941f commit 42cf28f
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 21 deletions.
4 changes: 4 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import cx from 'classnames';
import {
Memori,
Message,
Tenant,
Venue,
} from '@memori.ai/memori-api-client/dist/types';
import Button from '../ui/Button';
Expand All @@ -21,6 +22,7 @@ import Clear from '../icons/Clear';
export interface Props {
className?: string;
memori: Memori;
tenant?: Tenant;
history: Message[];
position?: Venue;
setShowPositionDrawer: (show: boolean) => void;
Expand All @@ -39,6 +41,7 @@ export interface Props {
const Header: React.FC<Props> = ({
className,
memori,
tenant,
history,
position,
setShowPositionDrawer,
Expand Down Expand Up @@ -151,6 +154,7 @@ const Header: React.FC<Props> = ({
<ShareButton
className="memori-header--button memori-header--button-share"
title={memori.name}
tenant={tenant}
showQrCode
align="left"
/>
Expand Down
1 change: 1 addition & 0 deletions src/components/MemoriWidget/MemoriWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,7 @@ const MemoriWidget = ({

const headerProps: HeaderProps = {
memori,
tenant,
history,
showShare: showShare ?? integrationConfig?.showShare ?? true,
position,
Expand Down
26 changes: 23 additions & 3 deletions src/components/ShareButton/ShareButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import ShareButton, { Props } from './ShareButton';
import { tenant } from '../../mocks/data';

import './ShareButton.css';

Expand Down Expand Up @@ -40,15 +41,34 @@ Default.args = {
align: 'right',
};

export const Alignment = TemplateRight.bind({});
Alignment.args = {
url: 'https://memori.ai',
align: 'left',
};

export const WithQrCode = Template.bind({});
WithQrCode.args = {
url: 'https://memori.ai',
showQrCode: true,
align: 'right',
};

export const Alignment = TemplateRight.bind({});
Alignment.args = {
export const WithQrCodeAndTenant = Template.bind({});
WithQrCodeAndTenant.args = {
url: 'https://memori.ai',
align: 'left',
showQrCode: true,
align: 'right',
tenant: tenant,
};

export const WithQrCodeAndOtherTenant = Template.bind({});
WithQrCodeAndOtherTenant.args = {
url: 'https://memori.ai',
showQrCode: true,
align: 'right',
tenant: {
...tenant,
theme: 'tailoor',
},
};
13 changes: 13 additions & 0 deletions src/components/ShareButton/ShareButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { render } from '@testing-library/react';
import ShareButton from './ShareButton';
import { tenant } from '../../mocks/data';

it('renders ShareButton unchanged', () => {
const { container } = render(<ShareButton />);
Expand Down Expand Up @@ -31,3 +32,15 @@ it('renders ShareButton aligned left unchanged', () => {
const { container } = render(<ShareButton align="left" />);
expect(container).toMatchSnapshot();
});

it('renders ShareButton with tenant img set unchanged', () => {
const { container } = render(<ShareButton tenant={tenant} />);
expect(container).toMatchSnapshot();
});

it('renders ShareButton with other tenant img set unchanged', () => {
const { container } = render(
<ShareButton tenant={{ ...tenant, theme: 'tailoor' }} />
);
expect(container).toMatchSnapshot();
});
19 changes: 15 additions & 4 deletions src/components/ShareButton/ShareButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Facebook from '../icons/Facebook';
import Twitter from '../icons/Twitter';
Expand All @@ -13,8 +13,10 @@ import { QRCodeCanvas } from 'qrcode.react';
import { Menu } from '@headlessui/react';
import Button from '../ui/Button';
import cx from 'classnames';
import { Tenant } from '@memori.ai/memori-api-client/dist/types';

export interface Props {
tenant?: Tenant;
url?: string;
title?: string;
className?: string;
Expand All @@ -25,6 +27,7 @@ export interface Props {
}

const ShareButton: React.FC<Props> = ({
tenant,
url,
title = '',
className,
Expand All @@ -36,6 +39,16 @@ const ShareButton: React.FC<Props> = ({
const { t } = useTranslation();
const [targetUrl, setTargetUrl] = useState(url);

const qrImageURL = useMemo(
() =>
tenant?.theme
? `${baseUrl ?? 'https://app.twincreator.com'}/images/${
tenant.theme
}/square_logo.png`
: `${baseUrl ?? 'https://app.twincreator.com'}/images/memori_logo.png`,
[tenant, baseUrl]
);

useEffect(() => {
if (!url) setTargetUrl(window.location.href);
}, [url]);
Expand Down Expand Up @@ -167,9 +180,7 @@ const ShareButton: React.FC<Props> = ({
level={'H'}
includeMargin={false}
imageSettings={{
src: `${
baseUrl || 'https://app.twincreator.com'
}/images/memori_logo.png`,
src: qrImageURL,
x: undefined,
y: undefined,
height: 32,
Expand Down
70 changes: 70 additions & 0 deletions src/components/ShareButton/__snapshots__/ShareButton.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,76 @@ exports[`renders ShareButton with button not primary unchanged 1`] = `
</div>
`;

exports[`renders ShareButton with other tenant img set unchanged 1`] = `
<div>
<div
class="memori-share-button"
data-headlessui-state=""
>
<button
aria-expanded="false"
aria-haspopup="true"
class="memori-button memori-button--circle memori-button--icon-only memori-share-button--button memori-button--primary"
data-headlessui-state=""
id="headlessui-menu-button-:re:"
title="widget.share"
type="button"
>
<div
class="memori-button--icon"
>
<svg
aria-hidden="true"
focusable="false"
role="img"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M752 664c-28.5 0-54.8 10-75.4 26.7L469.4 540.8a160.68 160.68 0 0 0 0-57.6l207.2-149.9C697.2 350 723.5 360 752 360c66.2 0 120-53.8 120-120s-53.8-120-120-120-120 53.8-120 120c0 11.6 1.6 22.7 4.7 33.3L439.9 415.8C410.7 377.1 364.3 352 312 352c-88.4 0-160 71.6-160 160s71.6 160 160 160c52.3 0 98.7-25.1 127.9-63.8l196.8 142.5c-3.1 10.6-4.7 21.8-4.7 33.3 0 66.2 53.8 120 120 120s120-53.8 120-120-53.8-120-120-120zm0-476c28.7 0 52 23.3 52 52s-23.3 52-52 52-52-23.3-52-52 23.3-52 52-52zM312 600c-48.5 0-88-39.5-88-88s39.5-88 88-88 88 39.5 88 88-39.5 88-88 88zm440 236c-28.7 0-52-23.3-52-52s23.3-52 52-52 52 23.3 52 52-23.3 52-52 52z"
/>
</svg>
</div>
</button>
</div>
</div>
`;

exports[`renders ShareButton with tenant img set unchanged 1`] = `
<div>
<div
class="memori-share-button"
data-headlessui-state=""
>
<button
aria-expanded="false"
aria-haspopup="true"
class="memori-button memori-button--circle memori-button--icon-only memori-share-button--button memori-button--primary"
data-headlessui-state=""
id="headlessui-menu-button-:rc:"
title="widget.share"
type="button"
>
<div
class="memori-button--icon"
>
<svg
aria-hidden="true"
focusable="false"
role="img"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M752 664c-28.5 0-54.8 10-75.4 26.7L469.4 540.8a160.68 160.68 0 0 0 0-57.6l207.2-149.9C697.2 350 723.5 360 752 360c66.2 0 120-53.8 120-120s-53.8-120-120-120-120 53.8-120 120c0 11.6 1.6 22.7 4.7 33.3L439.9 415.8C410.7 377.1 364.3 352 312 352c-88.4 0-160 71.6-160 160s71.6 160 160 160c52.3 0 98.7-25.1 127.9-63.8l196.8 142.5c-3.1 10.6-4.7 21.8-4.7 33.3 0 66.2 53.8 120 120 120s120-53.8 120-120-53.8-120-120-120zm0-476c28.7 0 52 23.3 52 52s-23.3 52-52 52-52-23.3-52-52 23.3-52 52-52zM312 600c-48.5 0-88-39.5-88-88s39.5-88 88-88 88 39.5 88 88-39.5 88-88 88zm440 236c-28.7 0-52-23.3-52-52s23.3-52 52-52 52 23.3 52 52-23.3 52-52 52z"
/>
</svg>
</div>
</button>
</div>
</div>
`;

exports[`renders ShareButton with title unchanged 1`] = `
<div>
<div
Expand Down
47 changes: 47 additions & 0 deletions src/helpers/tenant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Tenant } from '@memori.ai/memori-api-client/dist/types';

const defaultTenant: Tenant = {
id: 'app.twincreator.com',
theme: 'twincreator',
config: {
name: 'Memori',
showNewUser: false,
requirePosition: false,
},
};

export const getTenant = async (
tenantID: string,
baseURL?: string
): Promise<Tenant> => {
const apiBaseUrl = baseURL
? new URL(
`${
baseURL.startsWith('http')
? ''
: baseURL.includes('localhost')
? 'http://'
: 'https://'
}${baseURL}`
).host
: 'https://app.twincreator.com';

try {
const response = await fetch(`${apiBaseUrl}/api/tenant/${tenantID}`);
const { tenant } = await response.json();

if (!tenant) {
return {
...defaultTenant,
tenantID,
};
}

return tenant;
} catch (error) {
return {
...defaultTenant,
tenantID,
};
}
};
24 changes: 15 additions & 9 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import PropTypes from 'prop-types';
import {
DialogState,
Memori as IMemori,
Tenant,
} from '@memori.ai/memori-api-client/dist/types';
import memoriApiClient from '@memori.ai/memori-api-client';
import MemoriWidget, {
Props as WidgetProps,
} from './components/MemoriWidget/MemoriWidget';
import { getTenant } from './helpers/tenant';

import i18n from './i18n';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -107,6 +109,7 @@ const Memori: React.FC<Props> = ({
userAvatar,
}) => {
const [memori, setMemori] = useState<IMemori>();
const [tenant, setTenant] = useState<Tenant>();
const [speechKey, setSpeechKey] = useState<string | undefined>(
AZURE_COGNITIVE_SERVICES_TTS_KEY
);
Expand Down Expand Up @@ -171,6 +174,17 @@ const Memori: React.FC<Props> = ({
fetchMemori();
}, [fetchMemori, tenantID]);

/**
* Fetches the Tenant data from the backend
*/
const fetchTenant = useCallback(async () => {
const tenant = await getTenant(tenantID, baseURL);
if (tenant) setTenant(tenant);
}, [tenantID, apiURL]);
useEffect(() => {
fetchTenant();
}, [fetchTenant]);

/**
* Sets the language in the i18n instance
*/
Expand Down Expand Up @@ -204,15 +218,7 @@ const Memori: React.FC<Props> = ({
}}
memoriLang={spokenLang ?? memori.culture?.split('-')?.[0]}
multilingual={multilingual}
tenant={{
id: tenantID,
theme: 'twincreator',
config: {
name: tenantID,
showNewUser: false,
requirePosition: !!memori.needsPosition,
},
}}
tenant={tenant}
secret={secretToken}
sessionID={sessionID}
showShare={showShare}
Expand Down
38 changes: 33 additions & 5 deletions src/mocks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,42 @@ import {
export const sessionID = '131165be-9d1a-42fb-a3ce-e8f86d40c88f';

export const tenant: Tenant = {
id: 'locahost:3000',
theme: 'twincreator',
adminCount: 3,
config: {
name: 'Memori',
showNewUser: true,
feedbackURL:
'https://form.asana.com/?k=XC7S3JWQeIhnjipBuA3gbw&d=1199599736247413',
name: 'TwinCreator',
requirePosition: false,
feedbackURL: 'https://form.asana.com/',
showNewUser: true,
},
creationTimestamp: '2023-05-31T14:32:48.885287Z',
description: 'TwinCreator',
disableRegistration: false,
id: 'app.twincreator.com',
lastChangeTimestamp: '2023-05-31T14:32:48.885287Z',
logoURL: 'https://app.twincreator.com/images/twincreator/logo.png',
maxAdmins: 0,
maxCompletions: 0,
maxCompletionsPerUser: 0,
maxFreeSessions: 400,
maxFreeSessionsPerUser: 100,
maxMemoriPerAdmin: 0,
maxMemoriPerUser: 3,
maxTotalMemori: 0,
maxUsers: 0,
memoriCount: 0,
name: 'app.twincreator.com',
nonFreeSessionCost: 0.02,
paying: true,
tenantID: '96caa4b4-31a4-48e5-8163-dec61869a2a7',
theme: 'twincreator',
userCount: 0,
usersCanAccessAPI: false,
usersCanCreateMemori: false,
usersCanEditDynamicIntents: false,
usersCanEditIntegrations: false,
usersCanEditMemoriChaining: false,
usersCanRunSnippets: false,
};

export const memori: Memori = {
Expand Down

0 comments on commit 42cf28f

Please sign in to comment.