@hyvor/design 1.1.22 → 1.1.24-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/HyvorBar/HyvorBar.svelte +23 -16
- package/dist/components/HyvorBar/HyvorBar.svelte.d.ts +2 -0
- package/dist/components/HyvorBar/Notice/BarLicense.svelte +2 -4
- package/dist/components/HyvorBar/Organization/BarOrganization.svelte +107 -0
- package/dist/components/HyvorBar/Organization/BarOrganization.svelte.d.ts +7 -0
- package/dist/components/HyvorBar/Organization/OrgsList.svelte +67 -0
- package/dist/components/HyvorBar/Organization/OrgsList.svelte.d.ts +7 -0
- package/dist/components/HyvorBar/bar.d.ts +12 -1
- package/dist/components/HyvorBar/bar.js +49 -21
- package/dist/marketing/track/track.d.ts +1 -1
- package/dist/marketing/track/track.js +32 -18
- package/package.json +1 -1
|
@@ -3,11 +3,19 @@
|
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
import BarProducts, { PRODUCTS } from './BarProducts.svelte';
|
|
5
5
|
import BarSupport from './BarSupport.svelte';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
barUser,
|
|
8
|
+
initBar,
|
|
9
|
+
setInstanceAndProduct,
|
|
10
|
+
type BarConfig,
|
|
11
|
+
type BarUser as BarUserType
|
|
12
|
+
} from './bar.js';
|
|
7
13
|
import BarUpdates from './BarUpdates.svelte';
|
|
8
14
|
import IconCaretDownFill from '@hyvor/icons/IconCaretDownFill';
|
|
9
15
|
import BarNotice from './Notice/BarNotice.svelte';
|
|
10
16
|
import BarLicense from './Notice/BarLicense.svelte';
|
|
17
|
+
import BarOrganization from './Organization/BarOrganization.svelte';
|
|
18
|
+
import { type BarOrganization as BarOrganizationType } from './bar.js';
|
|
11
19
|
|
|
12
20
|
interface Props {
|
|
13
21
|
instance?: string;
|
|
@@ -27,16 +35,18 @@
|
|
|
27
35
|
authOverride?: {
|
|
28
36
|
user: BarUserType | null;
|
|
29
37
|
logoutUrl: string;
|
|
30
|
-
}
|
|
38
|
+
};
|
|
39
|
+
onOrganizationSwitch?: (org: BarOrganizationType) => void;
|
|
31
40
|
}
|
|
32
41
|
|
|
33
42
|
let {
|
|
34
|
-
instance = 'https://hyvor.com',
|
|
35
|
-
product,
|
|
43
|
+
instance = 'https://hyvor.com',
|
|
44
|
+
product,
|
|
36
45
|
logo = `${instance}/api/public/logo/${product}.svg`,
|
|
37
46
|
config = {},
|
|
38
47
|
cloud = true,
|
|
39
|
-
authOverride = undefined
|
|
48
|
+
authOverride = undefined,
|
|
49
|
+
onOrganizationSwitch = () => {}
|
|
40
50
|
}: Props = $props();
|
|
41
51
|
|
|
42
52
|
let mobileShow = $state(false);
|
|
@@ -61,15 +71,15 @@
|
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
74
|
+
if (authOverride) {
|
|
75
|
+
barUser.set(authOverride.user);
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
onMount(() => {
|
|
65
79
|
setInstanceAndProduct(instance, product);
|
|
66
80
|
|
|
67
81
|
if (cloud) {
|
|
68
82
|
initBar();
|
|
69
|
-
} else {
|
|
70
|
-
if (authOverride) {
|
|
71
|
-
barUser.set(authOverride.user);
|
|
72
|
-
}
|
|
73
83
|
}
|
|
74
84
|
});
|
|
75
85
|
|
|
@@ -87,16 +97,12 @@
|
|
|
87
97
|
<div class="inner hds-box">
|
|
88
98
|
<div class="left">
|
|
89
99
|
<a class="logo" href="/">
|
|
90
|
-
<img
|
|
91
|
-
src={logo}
|
|
92
|
-
alt={product}
|
|
93
|
-
width="20"
|
|
94
|
-
height="20"
|
|
95
|
-
/>
|
|
100
|
+
<img src={logo} alt={product} width="20" height="20" />
|
|
96
101
|
<span class="name">
|
|
97
102
|
{getName()}
|
|
98
103
|
</span>
|
|
99
104
|
</a>
|
|
105
|
+
<BarOrganization onSwitch={onOrganizationSwitch} />
|
|
100
106
|
<BarLicense name={getName()} />
|
|
101
107
|
</div>
|
|
102
108
|
<div class="right">
|
|
@@ -132,7 +138,7 @@
|
|
|
132
138
|
z-index: 100;
|
|
133
139
|
}
|
|
134
140
|
.inner {
|
|
135
|
-
padding:
|
|
141
|
+
padding: 0px 29px;
|
|
136
142
|
display: flex;
|
|
137
143
|
align-items: center;
|
|
138
144
|
border-top-left-radius: 0;
|
|
@@ -143,6 +149,7 @@
|
|
|
143
149
|
display: flex;
|
|
144
150
|
align-items: center;
|
|
145
151
|
flex: 1;
|
|
152
|
+
height: 100%;
|
|
146
153
|
}
|
|
147
154
|
.logo {
|
|
148
155
|
display: flex;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type BarConfig, type BarUser as BarUserType } from './bar.js';
|
|
2
|
+
import { type BarOrganization as BarOrganizationType } from './bar.js';
|
|
2
3
|
interface Props {
|
|
3
4
|
instance?: string;
|
|
4
5
|
product: string;
|
|
@@ -13,6 +14,7 @@ interface Props {
|
|
|
13
14
|
user: BarUserType | null;
|
|
14
15
|
logoutUrl: string;
|
|
15
16
|
};
|
|
17
|
+
onOrganizationSwitch?: (org: BarOrganizationType) => void;
|
|
16
18
|
}
|
|
17
19
|
declare const HyvorBar: import("svelte").Component<Props, {}, "">;
|
|
18
20
|
type HyvorBar = ReturnType<typeof HyvorBar>;
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
return daysDiff(endsAt);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function remainingCancelAtDAys(cancelAt: number | undefined | null)
|
|
25
|
+
function remainingCancelAtDAys(cancelAt: number | undefined | null): null | number {
|
|
26
26
|
if (!cancelAt) {
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
@@ -36,9 +36,7 @@
|
|
|
36
36
|
{#if $barLicense}
|
|
37
37
|
<a class="wrap" href="/console/billing">
|
|
38
38
|
{#if $barLicense.type === 'subscription'}
|
|
39
|
-
<Tooltip
|
|
40
|
-
position="bottom"
|
|
41
|
-
>
|
|
39
|
+
<Tooltip position="bottom">
|
|
42
40
|
{#snippet tooltip()}
|
|
43
41
|
Your current subscription plan for {name}. Click to manage it.
|
|
44
42
|
{/snippet}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Dropdown from '../../Dropdown/Dropdown.svelte';
|
|
3
|
+
import Tooltip from '../../Tooltip/Tooltip.svelte';
|
|
4
|
+
import { barUser, switchOrganization, type BarOrganization } from '../bar.js';
|
|
5
|
+
import IconChevronExpand from '@hyvor/icons/IconChevronExpand';
|
|
6
|
+
import OrgsList from './OrgsList.svelte';
|
|
7
|
+
import toast from '../../Toast/toast.js';
|
|
8
|
+
|
|
9
|
+
let showDropdown = $state(false);
|
|
10
|
+
let showTooltip = $state(true);
|
|
11
|
+
let switching = $state(false);
|
|
12
|
+
|
|
13
|
+
let props: {
|
|
14
|
+
onSwitch: (org: BarOrganization) => void;
|
|
15
|
+
} = $props();
|
|
16
|
+
|
|
17
|
+
async function handleSwitch(org: BarOrganization) {
|
|
18
|
+
showDropdown = false;
|
|
19
|
+
switching = true;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await switchOrganization(org);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
toast.error('Failed to switch organization.');
|
|
25
|
+
switching = false;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
props.onSwitch(org);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
$effect(() => {
|
|
33
|
+
if (showDropdown) {
|
|
34
|
+
showTooltip = false;
|
|
35
|
+
} else {
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
showTooltip = true;
|
|
38
|
+
}, 3000);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#if $barUser}
|
|
44
|
+
<Tooltip position="bottom" text="Switch Organization" disabled={!showTooltip}>
|
|
45
|
+
<span class="wrap">
|
|
46
|
+
<Dropdown bind:show={showDropdown} align="center" width={275} contentPadding={0}>
|
|
47
|
+
{#snippet trigger()}
|
|
48
|
+
<button>
|
|
49
|
+
{#if switching}
|
|
50
|
+
<span class="switching">Switching...</span>
|
|
51
|
+
{:else}
|
|
52
|
+
{$barUser.current_organization_name}
|
|
53
|
+
{/if}
|
|
54
|
+
<IconChevronExpand size={12} />
|
|
55
|
+
</button>
|
|
56
|
+
{/snippet}
|
|
57
|
+
{#snippet content()}
|
|
58
|
+
<OrgsList onSwitch={handleSwitch} />
|
|
59
|
+
{/snippet}
|
|
60
|
+
</Dropdown>
|
|
61
|
+
</span>
|
|
62
|
+
</Tooltip>
|
|
63
|
+
{/if}
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
.wrap {
|
|
67
|
+
height: 100%;
|
|
68
|
+
margin-left: 20px;
|
|
69
|
+
margin-right: 20px;
|
|
70
|
+
display: inline-flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
}
|
|
73
|
+
button {
|
|
74
|
+
height: 100%;
|
|
75
|
+
padding: 0 15px;
|
|
76
|
+
font-size: 14px;
|
|
77
|
+
height: 24px;
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
transition: 0.2s background-color;
|
|
80
|
+
border: 1px solid var(--border);
|
|
81
|
+
border-top: none;
|
|
82
|
+
border-bottom: none;
|
|
83
|
+
}
|
|
84
|
+
button:hover {
|
|
85
|
+
background-color: var(--hover);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.wrap :global(.dropdown),
|
|
89
|
+
.wrap :global(.trigger) {
|
|
90
|
+
display: inline-block;
|
|
91
|
+
height: 100%;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.switching {
|
|
95
|
+
opacity: 0.4;
|
|
96
|
+
animation: switching-pulse 1.5s infinite;
|
|
97
|
+
}
|
|
98
|
+
@keyframes switching-pulse {
|
|
99
|
+
0%,
|
|
100
|
+
100% {
|
|
101
|
+
opacity: 0.4;
|
|
102
|
+
}
|
|
103
|
+
50% {
|
|
104
|
+
opacity: 0.8;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type BarOrganization } from '../bar.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
onSwitch: (org: BarOrganization) => void;
|
|
4
|
+
};
|
|
5
|
+
declare const BarOrganization: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type BarOrganization = ReturnType<typeof BarOrganization>;
|
|
7
|
+
export default BarOrganization;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconMessage from '../../IconMessage/IconMessage.svelte';
|
|
3
|
+
import Loader from '../../Loader/Loader.svelte';
|
|
4
|
+
import { onMount } from 'svelte';
|
|
5
|
+
import { getMyOrganizations, type BarOrganization } from '../bar.js';
|
|
6
|
+
import ActionList from '../../ActionList/ActionList.svelte';
|
|
7
|
+
import ActionListItem from '../../ActionList/ActionListItem.svelte';
|
|
8
|
+
|
|
9
|
+
let loading = $state(true);
|
|
10
|
+
let error = $state('');
|
|
11
|
+
let orgs = $state<BarOrganization[]>([]);
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
onSwitch
|
|
15
|
+
}: {
|
|
16
|
+
onSwitch: (org: BarOrganization) => void;
|
|
17
|
+
} = $props();
|
|
18
|
+
|
|
19
|
+
onMount(() => {
|
|
20
|
+
getMyOrganizations()
|
|
21
|
+
.then((data) => {
|
|
22
|
+
orgs = data;
|
|
23
|
+
})
|
|
24
|
+
.catch((err) => {
|
|
25
|
+
error = 'Failed to load organizations.';
|
|
26
|
+
})
|
|
27
|
+
.finally(() => {
|
|
28
|
+
loading = false;
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
{#if loading}
|
|
34
|
+
<Loader padding={40} block size="small" />
|
|
35
|
+
{:else if error}
|
|
36
|
+
<IconMessage error iconSize={30}>
|
|
37
|
+
{error}
|
|
38
|
+
</IconMessage>
|
|
39
|
+
{:else}
|
|
40
|
+
<div class="list-wrap">
|
|
41
|
+
<ActionList>
|
|
42
|
+
{#each orgs as org}
|
|
43
|
+
<ActionListItem on:select={() => onSwitch(org)}>
|
|
44
|
+
{org.name}
|
|
45
|
+
{#snippet end()}
|
|
46
|
+
<span class="role">
|
|
47
|
+
{org.role.toUpperCase()}
|
|
48
|
+
</span>
|
|
49
|
+
{/snippet}
|
|
50
|
+
</ActionListItem>
|
|
51
|
+
{/each}
|
|
52
|
+
</ActionList>
|
|
53
|
+
</div>
|
|
54
|
+
{/if}
|
|
55
|
+
|
|
56
|
+
<style>
|
|
57
|
+
.role {
|
|
58
|
+
font-size: 10px;
|
|
59
|
+
color: var(--text-light);
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
}
|
|
62
|
+
.list-wrap {
|
|
63
|
+
max-height: 300px;
|
|
64
|
+
overflow-y: auto;
|
|
65
|
+
padding: 10px;
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type BarOrganization } from '../bar.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
onSwitch: (org: BarOrganization) => void;
|
|
4
|
+
};
|
|
5
|
+
declare const OrgsList: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type OrgsList = ReturnType<typeof OrgsList>;
|
|
7
|
+
export default OrgsList;
|
|
@@ -10,6 +10,12 @@ export interface BarUser {
|
|
|
10
10
|
username?: string | null;
|
|
11
11
|
email: string;
|
|
12
12
|
picture_url: string | null;
|
|
13
|
+
current_organization_name: string;
|
|
14
|
+
}
|
|
15
|
+
export interface BarOrganization {
|
|
16
|
+
id: number;
|
|
17
|
+
name: string;
|
|
18
|
+
role: 'admin' | 'billing' | 'manager' | 'member';
|
|
13
19
|
}
|
|
14
20
|
export interface BarUpdate {
|
|
15
21
|
id: number;
|
|
@@ -34,7 +40,12 @@ export declare const barUnreadUpdates: import("svelte/store").Writable<number>;
|
|
|
34
40
|
export declare const barLicense: import("svelte/store").Writable<BarResolvedLicense | null>;
|
|
35
41
|
export declare const barHasFailedInvoices: import("svelte/store").Writable<boolean>;
|
|
36
42
|
export declare function setInstanceAndProduct(instance_: string, product_: string): void;
|
|
37
|
-
|
|
43
|
+
/**
|
|
44
|
+
* @throws Error if initialization fails
|
|
45
|
+
*/
|
|
46
|
+
export declare function initBar(): Promise<void>;
|
|
47
|
+
export declare function getMyOrganizations(): Promise<BarOrganization[]>;
|
|
48
|
+
export declare function switchOrganization(org: BarOrganization): Promise<void>;
|
|
38
49
|
export declare class UnreadUpdatesTimeLocalStorage {
|
|
39
50
|
static KEY: string;
|
|
40
51
|
static get(): number | null;
|
|
@@ -10,35 +10,63 @@ export function setInstanceAndProduct(instance_, product_) {
|
|
|
10
10
|
instance = instance_;
|
|
11
11
|
product = product_;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @throws Error if initialization fails
|
|
15
|
+
*/
|
|
16
|
+
export async function initBar() {
|
|
14
17
|
const query = new URLSearchParams();
|
|
15
18
|
query.set('product', product);
|
|
16
19
|
const lastUnreadTime = UnreadUpdatesTimeLocalStorage.get();
|
|
17
20
|
if (lastUnreadTime) {
|
|
18
21
|
query.set('last_read_updates_at', lastUnreadTime.toString());
|
|
19
22
|
}
|
|
20
|
-
fetch(instance + '/api/public/bar?' + query.toString(), {
|
|
23
|
+
const response = await fetch(instance + '/api/public/bar?' + query.toString(), {
|
|
21
24
|
credentials: 'include'
|
|
22
|
-
})
|
|
23
|
-
.then((response) => response.json())
|
|
24
|
-
.then((data) => {
|
|
25
|
-
barUser.set(data.user);
|
|
26
|
-
barUnreadUpdates.set(data.updates.unread);
|
|
27
|
-
barLicense.set(data.billing.license);
|
|
28
|
-
barHasFailedInvoices.set(data.billing.has_failed_invoices);
|
|
29
|
-
if (lastUnreadTime === null) {
|
|
30
|
-
UnreadUpdatesTimeLocalStorage.setNow();
|
|
31
|
-
}
|
|
32
|
-
if (data.user && track.ready()) {
|
|
33
|
-
track.identify(data.user.id.toString(), {
|
|
34
|
-
name: data.user.name ?? undefined,
|
|
35
|
-
avatar: data.user.picture_url ?? undefined,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
.catch((error) => {
|
|
40
|
-
console.error('Error:', error);
|
|
41
25
|
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error('Failed to initialize bar');
|
|
28
|
+
}
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
barUser.set(data.user);
|
|
31
|
+
barUnreadUpdates.set(data.updates.unread);
|
|
32
|
+
barLicense.set(data.billing.license);
|
|
33
|
+
barHasFailedInvoices.set(data.billing.has_failed_invoices);
|
|
34
|
+
if (lastUnreadTime === null) {
|
|
35
|
+
UnreadUpdatesTimeLocalStorage.setNow();
|
|
36
|
+
}
|
|
37
|
+
if (data.user && track.ready()) {
|
|
38
|
+
track.identify(data.user.id.toString(), {
|
|
39
|
+
name: data.user.name ?? undefined,
|
|
40
|
+
avatar: data.user.picture_url ?? undefined,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export async function getMyOrganizations() {
|
|
45
|
+
/* return [
|
|
46
|
+
{ id: 1, name: 'Org 1', role: 'admin' },
|
|
47
|
+
{ id: 2, name: 'Org 2', role: 'member' },
|
|
48
|
+
{ id: 3, name: 'Org 3', role: 'billing' },
|
|
49
|
+
{ id: 4, name: 'Org 4', role: 'manager' },
|
|
50
|
+
] */
|
|
51
|
+
const response = await fetch(instance + '/api/public/bar/myorgs', {
|
|
52
|
+
credentials: 'include'
|
|
53
|
+
});
|
|
54
|
+
const data = await response.json();
|
|
55
|
+
return data.organizations;
|
|
56
|
+
}
|
|
57
|
+
export async function switchOrganization(org) {
|
|
58
|
+
const response = await fetch(instance + '/api/public/bar/switch-org', {
|
|
59
|
+
method: 'POST',
|
|
60
|
+
credentials: 'include',
|
|
61
|
+
headers: {
|
|
62
|
+
'Content-Type': 'application/json'
|
|
63
|
+
},
|
|
64
|
+
body: JSON.stringify({ organization_id: org.id })
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw new Error('Failed to switch organization');
|
|
68
|
+
}
|
|
69
|
+
await initBar();
|
|
42
70
|
}
|
|
43
71
|
export class UnreadUpdatesTimeLocalStorage {
|
|
44
72
|
static KEY = 'unread_updates';
|
|
@@ -8,8 +8,8 @@ declare class Track {
|
|
|
8
8
|
private op;
|
|
9
9
|
private isProductionDomain;
|
|
10
10
|
init({ forceTrack, openPanelApiUrl, openPanelClientId, context }?: InitOptions): void;
|
|
11
|
-
private checkOp;
|
|
12
11
|
ready(): boolean;
|
|
12
|
+
private warnNoOp;
|
|
13
13
|
context(properties: Record<string, any>): void;
|
|
14
14
|
event(name: string, properties?: Record<string, any>): void;
|
|
15
15
|
identify(profileId: string, props: {
|
|
@@ -21,38 +21,52 @@ class Track {
|
|
|
21
21
|
this.op.setGlobalProperties(context);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
checkOp() {
|
|
25
|
-
if (!this.op) {
|
|
26
|
-
throw new Error('OpenPanel is not initialized. Call track.init() first.');
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
24
|
ready() {
|
|
30
25
|
return this.op !== undefined;
|
|
31
26
|
}
|
|
27
|
+
warnNoOp(message) {
|
|
28
|
+
console.warn(`[Track] Ignoring action: ${message} - OpenPanel is not initialized. Call track.init() first.`);
|
|
29
|
+
}
|
|
32
30
|
// set global context
|
|
33
31
|
context(properties) {
|
|
34
|
-
this.
|
|
35
|
-
|
|
32
|
+
if (this.op) {
|
|
33
|
+
this.op.setGlobalProperties(properties);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.warnNoOp('set context');
|
|
37
|
+
}
|
|
36
38
|
}
|
|
37
39
|
// log an event
|
|
38
40
|
event(name, properties) {
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
+
if (this.op) {
|
|
42
|
+
this.op.track(name, properties);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.warnNoOp(`log event "${name}"`);
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
// identify user
|
|
43
49
|
identify(profileId, props) {
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
if (this.op) {
|
|
51
|
+
this.op.identify({
|
|
52
|
+
profileId: profileId,
|
|
53
|
+
firstName: props.name,
|
|
54
|
+
avatar: props.avatar,
|
|
55
|
+
properties: props.properties
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.warnNoOp(`identify user "${profileId}"`);
|
|
60
|
+
}
|
|
51
61
|
}
|
|
52
62
|
// log out user (clear identity)
|
|
53
63
|
logout() {
|
|
54
|
-
this.
|
|
55
|
-
|
|
64
|
+
if (this.op) {
|
|
65
|
+
this.op.clear();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.warnNoOp('logout user');
|
|
69
|
+
}
|
|
56
70
|
}
|
|
57
71
|
}
|
|
58
72
|
const track = new Track();
|
package/package.json
CHANGED