Skip to content

Commit 19307fd

Browse files
authored
Pricing pages and paywalls (#1627)
1 parent 9878ae5 commit 19307fd

File tree

16 files changed

+448
-533
lines changed

16 files changed

+448
-533
lines changed

frontend/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@
4343
<link
4444
rel="preload"
4545
as="style"
46-
href="https://cdn.jsdelivr.net/npm/remixicon@3.1.1/fonts/remixicon.css"
46+
href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css"
4747
/>
4848

4949
<link
5050
rel="stylesheet"
51-
href="https://cdn.jsdelivr.net/npm/remixicon@3.1.1/fonts/remixicon.css"
51+
href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css"
5252
media="print"
5353
onload="this.media='all'"
5454
/>
@@ -60,7 +60,7 @@
6060
/>
6161
<link
6262
as="style"
63-
href="https://cdn.jsdelivr.net/npm/remixicon@3.1.1/fonts/remixicon.css"
63+
href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css"
6464
/>
6565
</noscript>
6666
<script type="text/javascript">

frontend/src/modules/automation/automation-limit.js

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,13 @@
11
import Plans from '@/security/plans';
22
import { router } from '@/router';
33
import ConfirmDialog from '@/shared/dialog/confirm-dialog';
4-
5-
const workflowMax = {
6-
scale: 'unlimited',
7-
enterprise: 'unlimited',
8-
growth: 10,
9-
essential: 2,
10-
};
4+
import { planLimits } from '@/security/plans-limits';
115

126
/**
137
* @param {*} plan tenant plan (Essential | Growth | Enterprise)
148
* @returns maximum number of workflows
159
*/
16-
export const getWorkflowMax = (plan) => {
17-
if (plan === Plans.values.scale) {
18-
return workflowMax.scale;
19-
}
20-
if (plan === Plans.values.enterprise) {
21-
return workflowMax.enterprise;
22-
}
23-
if (
24-
plan === Plans.values.growth
25-
) {
26-
return workflowMax.growth;
27-
}
28-
29-
return workflowMax.essential;
30-
};
10+
export const getWorkflowMax = (plan) => planLimits.automation[plan];
3111

3212
export const showWorkflowLimitDialog = ({
3313
planWorkflowCountMax,
@@ -36,10 +16,11 @@ export const showWorkflowLimitDialog = ({
3616
vertical: true,
3717
type: 'danger',
3818
title:
39-
`You have reached the limit of ${planWorkflowCountMax} automations on your current plan`,
19+
`You have reached the limit of ${planWorkflowCountMax} active automations on your current plan`,
4020
message:
41-
'Upgrade your plan to get unlimited automations and take full advantage of this feature',
21+
'Upgrade your plan to increase the active automations quota and take full advantage of this feature',
4222
confirmButtonText: 'Upgrade plan',
23+
showCancelButton: false,
4324
}).then(() => {
4425
router.push('settings?activeTab=plans');
4526
});

frontend/src/modules/layout/pages/paywall-page.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ const section = computed(
112112
const page = computed(() => pageContent[section.value]);
113113
const computedFeaturePlan = computed(() => {
114114
if (config.isCommunityVersion) return 'Custom plan';
115-
if (page.value.headerTitle === 'Eagle Eye') return 'Growth and Eagle Eye plans';
116-
return 'Growth plan';
115+
if (page.value.headerTitle === 'Eagle Eye') return 'Scale and Eagle Eye plans';
116+
return 'Scale plan';
117117
});
118118
</script>
119119

frontend/src/modules/member/components/list/member-list-toolbar.vue

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,19 @@
2626
</el-dropdown-item>
2727
<el-tooltip
2828
placement="top"
29-
content="Selected contacts lack an associated GitHub profile or Email"
29+
:content="!isEnrichmentFeatureEnabled()
30+
? 'Upgrade your plan to increase your quota of available contact enrichments'
31+
: 'Selected contacts lack an associated GitHub profile or Email'"
3032
:disabled="
31-
elegibleEnrichmentMembersIds.length
32-
|| isEditLockedForSampleData
33+
!elegibleEnrichmentMembersIds.length
34+
|| isEditLockedForSampleData || isEnrichmentFeatureEnabled()
3335
"
3436
popper-class="max-w-[260px]"
3537
>
3638
<span>
3739
<el-dropdown-item
3840
:command="{ action: 'enrichMember' }"
39-
:disabled="
40-
!elegibleEnrichmentMembersIds.length
41-
|| isEditLockedForSampleData
42-
"
41+
:disabled="isEnrichmentActionDisabled"
4342
class="mb-1"
4443
>
4544
<app-svg
@@ -116,7 +115,7 @@
116115

117116
<script setup>
118117
119-
import { computed, ref } from 'vue';
118+
import { computed, ref, onMounted } from 'vue';
120119
import { MemberPermissions } from '@/modules/member/member-permissions';
121120
import { useMemberStore } from '@/modules/member/store/pinia';
122121
import { storeToRefs } from 'pinia';
@@ -127,7 +126,7 @@ import Message from '@/shared/message/message';
127126
import pluralize from 'pluralize';
128127
import { getExportMax, showExportDialog, showExportLimitDialog } from '@/modules/member/member-export-limit';
129128
import {
130-
checkEnrichmentLimit,
129+
isEnrichmentFeatureEnabled,
131130
checkEnrichmentPlan,
132131
getEnrichmentMax,
133132
showEnrichmentLoadingMessage,
@@ -220,6 +219,9 @@ const markAsTeamMemberOptions = computed(() => {
220219
};
221220
});
222221
222+
const isEnrichmentActionDisabled = computed(() => !elegibleEnrichmentMembersIds.value.length
223+
|| isEditLockedForSampleData.value || !isEnrichmentFeatureEnabled());
224+
223225
const handleMergeMembers = () => {
224226
const [firstMember, secondMember] = selectedMembers.value;
225227
return MemberService.merge(firstMember, secondMember)
@@ -232,6 +234,10 @@ const handleMergeMembers = () => {
232234
});
233235
};
234236
237+
onMounted(() => {
238+
doRefreshCurrentUser({});
239+
});
240+
235241
const doDestroyAllWithConfirm = () => ConfirmDialog({
236242
type: 'danger',
237243
title: 'Delete contacts',
@@ -421,7 +427,7 @@ const handleCommand = async (command) => {
421427
422428
// Check if it has reached enrichment maximum
423429
// If so, show dialog to upgrade plan
424-
if (checkEnrichmentLimit(planEnrichmentCountMax)) {
430+
if (!isEnrichmentFeatureEnabled()) {
425431
return;
426432
}
427433

frontend/src/modules/member/components/member-dropdown.vue

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@
3737
</router-link>
3838
<el-tooltip
3939
placement="top"
40-
content="Contact enrichment requires an associated GitHub profile or Email"
41-
:disabled="!isEnrichmentDisabled"
40+
:content="!isEnrichmentFeatureEnabled()
41+
? 'Upgrade your plan to increase your quota of available contact enrichments'
42+
: 'Contact enrichment requires an associated GitHub profile or Email'"
43+
:disabled="isEnrichmentDisabledForMember || isEnrichmentFeatureEnabled()"
4244
popper-class="max-w-[260px]"
4345
>
4446
<span>
@@ -48,10 +50,7 @@
4850
member,
4951
}"
5052
class="h-10 mb-1"
51-
:disabled="
52-
isEnrichmentDisabled
53-
|| isEditLockedForSampleData
54-
"
53+
:disabled="isEnrichmentActionDisabled"
5554
>
5655
<app-svg
5756
name="enrichment"
@@ -61,7 +60,7 @@
6160
<span
6261
class="ml-2 text-xs"
6362
:class="{
64-
'text-gray-400': isEnrichmentDisabled,
63+
'text-gray-400': isEnrichmentDisabledForMember,
6564
}"
6665
>{{
6766
member.lastEnriched
@@ -85,34 +84,43 @@
8584
</el-dropdown-item>
8685

8786
<!-- Hubspot -->
88-
<el-dropdown-item
89-
v-if="!isSyncingWithHubspot"
90-
class="h-10"
91-
:command="{
92-
action: 'syncHubspot',
93-
member: member,
94-
}"
95-
:disabled="!isHubspotConnected || member.emails.length === 0"
96-
>
97-
<app-svg name="hubspot" class="h-4 w-4 text-current" />
98-
<span
99-
class="text-xs pl-2"
100-
>Sync with HubSpot</span>
101-
</el-dropdown-item>
102-
<el-dropdown-item
103-
v-else
104-
class="h-10"
105-
:command="{
106-
action: 'stopSyncHubspot',
107-
member: member,
108-
}"
109-
:disabled="!isHubspotConnected || member.emails.length === 0"
87+
<el-tooltip
88+
placement="top"
89+
content="Upgrade your plan to create a 2-way sync with HubSpot"
90+
:disabled="isHubspotFeatureEnabled"
91+
popper-class="max-w-[260px]"
11092
>
111-
<app-svg name="hubspot" class="h-4 w-4 text-current" />
112-
<span
113-
class="text-xs pl-2"
114-
>Stop sync with HubSpot</span>
115-
</el-dropdown-item>
93+
<span>
94+
<el-dropdown-item
95+
v-if="!isSyncingWithHubspot"
96+
class="h-10"
97+
:command="{
98+
action: 'syncHubspot',
99+
member: member,
100+
}"
101+
:disabled="isHubspotActionDisabled"
102+
>
103+
<app-svg name="hubspot" class="h-4 w-4 text-current" />
104+
<span
105+
class="text-xs pl-2"
106+
>Sync with HubSpot</span>
107+
</el-dropdown-item>
108+
<el-dropdown-item
109+
v-else
110+
class="h-10"
111+
:command="{
112+
action: 'stopSyncHubspot',
113+
member: member,
114+
}"
115+
:disabled="isHubspotActionDisabled"
116+
>
117+
<app-svg name="hubspot" class="h-4 w-4 text-current" />
118+
<span
119+
class="text-xs pl-2"
120+
>Stop sync with HubSpot</span>
121+
</el-dropdown-item>
122+
</span>
123+
</el-tooltip>
116124

117125
<el-dropdown-item
118126
v-if="!member.attributes.isTeamMember?.default"
@@ -206,6 +214,8 @@ import { useMemberStore } from '@/modules/member/store/pinia';
206214
import { CrowdIntegrations } from '@/integrations/integrations-config';
207215
import { HubspotEntity } from '@/integrations/hubspot/types/HubspotEntity';
208216
import { HubspotApiService } from '@/integrations/hubspot/hubspot.api.service';
217+
import { isEnrichmentFeatureEnabled } from '@/modules/member/member-enrichment';
218+
import { FeatureFlag, FEATURE_FLAGS } from '@/utils/featureFlag';
209219
210220
export default {
211221
name: 'AppMemberDropdown',
@@ -227,6 +237,7 @@ export default {
227237
pair: [],
228238
};
229239
},
240+
230241
computed: {
231242
...mapGetters({
232243
currentTenant: 'auth/currentTenant',
@@ -240,12 +251,6 @@ export default {
240251
).edit === false
241252
);
242253
},
243-
isEnrichmentDisabled() {
244-
return (
245-
!this.member.username?.github?.length
246-
&& !this.member.emails?.length
247-
);
248-
},
249254
isEditLockedForSampleData() {
250255
return new MemberPermissions(
251256
this.currentTenant,
@@ -258,6 +263,15 @@ export default {
258263
this.currentUser,
259264
).destroyLockedForSampleData;
260265
},
266+
isEnrichmentDisabledForMember() {
267+
return (
268+
!this.member.username?.github?.length
269+
&& !this.member.emails?.length
270+
);
271+
},
272+
isEnrichmentActionDisabled() {
273+
return this.isEnrichmentDisabledForMember || this.isEditLockedForSampleData || !this.isEnrichmentFeatureEnabled();
274+
},
261275
isSyncingWithHubspot() {
262276
return this.member.attributes?.syncRemote?.hubspot || false;
263277
},
@@ -266,12 +280,27 @@ export default {
266280
const enabledFor = hubspot.settings?.enabledFor || [];
267281
return hubspot.status === 'done' && enabledFor.includes(HubspotEntity.MEMBERS);
268282
},
283+
isHubspotDisabledForMember() {
284+
return props.member.emails.length === 0;
285+
},
286+
isHubspotFeatureEnabled() {
287+
return FeatureFlag.isFlagEnabled(
288+
FEATURE_FLAGS.hubspot,
289+
);
290+
},
291+
isHubspotActionDisabled() {
292+
return !this.isHubspotConnected || this.isHubspotDisabledForMember || !this.isHubspotFeatureEnabled;
293+
},
294+
},
295+
created() {
296+
this.doRefreshCurrentUser({});
269297
},
270298
methods: {
271299
...mapActions({
272300
doFind: 'member/doFind',
273301
doDestroy: 'member/doDestroy',
274302
doEnrich: 'member/doEnrich',
303+
doRefreshCurrentUser: 'auth/doRefreshCurrentUser',
275304
}),
276305
...piniaMapActions(useMemberStore, ['fetchMembers']),
277306
async doDestroyWithConfirm(id) {
@@ -362,6 +391,7 @@ export default {
362391
363392
return null;
364393
},
394+
isEnrichmentFeatureEnabled,
365395
},
366396
};
367397
</script>

0 commit comments

Comments
 (0)