Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/src/api/tenant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ export default (app) => {
)
app.post(`/tenant/:tenantId/sampleData`, safeWrap(require('./tenantGenerateSampleData').default))
app.delete(`/tenant/:tenantId/sampleData`, safeWrap(require('./tenantDeleteSampleData').default))
app.post(
`/tenant/:tenantId/viewOrganizations`,
safeWrap(require('./tenantViewOrganizations').default),
)
}
7 changes: 7 additions & 0 deletions backend/src/api/tenant/tenantViewOrganizations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import TenantService from '../../services/tenantService'

export default async (req, res) => {
const payload = await new TenantService(req).viewOrganizations()

await req.responseHandler.success(req, res, payload)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE public."settings" DROP COLUMN "organizationsViewed";
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE public."settings" ADD COLUMN "organizationsViewed" bool;
3 changes: 3 additions & 0 deletions backend/src/database/models/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export default (sequelize, DataTypes) => {
slackWebHook: {
type: DataTypes.STRING(1024),
},
organizationsViewed: {
type: DataTypes.BOOLEAN(),
},
attributeSettings: {
type: DataTypes.JSONB,
allowNull: false,
Expand Down
55 changes: 47 additions & 8 deletions backend/src/services/quickstartGuideService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { IServiceOptions } from './IServiceOptions'
import isFeatureEnabled from '../feature-flags/isFeatureEnabled'
import {
DEFAULT_GUIDES,
DEFAULT_GUIDES_V2,
QuickstartGuideMap,
QuickstartGuideSettings,
QuickstartGuideType,
Expand All @@ -14,6 +15,8 @@ import IntegrationRepository from '../database/repositories/integrationRepositor
import MemberService from './memberService'
import TenantUserRepository from '../database/repositories/tenantUserRepository'
import ReportRepository from '../database/repositories/reportRepository'
import AutomationRepository from '../database/repositories/automationRepository'
import SettingsRepository from '@/database/repositories/settingsRepository'

export default class QuickstartGuideService extends LoggerBase {
options: IServiceOptions
Expand All @@ -39,7 +42,10 @@ export default class QuickstartGuideService extends LoggerBase {
}

async find(): Promise<QuickstartGuideMap> {
const guides: QuickstartGuideMap = JSON.parse(JSON.stringify(DEFAULT_GUIDES))
const isGuidesV2Enabled = await isFeatureEnabled(FeatureFlag.QUICKSTART_V2, this.options)
const guides: QuickstartGuideMap = JSON.parse(
JSON.stringify(isGuidesV2Enabled ? DEFAULT_GUIDES_V2 : DEFAULT_GUIDES),
)

const integrationCount: number = await IntegrationRepository.count({}, this.options)

Expand All @@ -66,21 +72,54 @@ export default class QuickstartGuideService extends LoggerBase {
this.options,
)

guides[QuickstartGuideType.CONNECT_INTEGRATION].completed = integrationCount > 1
guides[QuickstartGuideType.ENRICH_MEMBER].completed = enrichedMembers.count > 0
guides[QuickstartGuideType.VIEW_REPORT].completed = viewedReports.count > 0
guides[QuickstartGuideType.INVITE_COLLEAGUES].completed = allTenantUsers.some(
(tu) => tu.invitedById === this.options.currentUser.id,
const automations = await new AutomationRepository(this.options).findAndCountAll({})
const tenantSettings = await SettingsRepository.getTenantSettings(
this.options.currentTenant.id,
this.options,
)

if (await isFeatureEnabled(FeatureFlag.EAGLE_EYE, this.options)) {
if (QuickstartGuideType.CONNECT_INTEGRATION in guides) {
guides[QuickstartGuideType.CONNECT_INTEGRATION].completed = integrationCount > 1
}
if (QuickstartGuideType.ENRICH_MEMBER in guides) {
guides[QuickstartGuideType.ENRICH_MEMBER].completed = enrichedMembers.count > 0
}
if (QuickstartGuideType.VIEW_REPORT in guides) {
guides[QuickstartGuideType.VIEW_REPORT].completed = viewedReports.count > 0
}
if (QuickstartGuideType.INVITE_COLLEAGUES in guides) {
guides[QuickstartGuideType.INVITE_COLLEAGUES].completed = allTenantUsers.some(
(tu) => tu.invitedById === this.options.currentUser.id,
)
}

if (QuickstartGuideType.CONNECT_FIRST_INTEGRATION in guides) {
guides[QuickstartGuideType.CONNECT_FIRST_INTEGRATION].completed = integrationCount > 0
}

if (QuickstartGuideType.CREATE_AUTOMATIONS in guides) {
guides[QuickstartGuideType.CREATE_AUTOMATIONS].completed = automations.count > 0
}

if (QuickstartGuideType.EXPLORE_ORGANIZATIONS in guides) {
guides[QuickstartGuideType.EXPLORE_ORGANIZATIONS].completed =
tenantSettings.organizationsViewed
}

if (
QuickstartGuideType.SET_EAGLE_EYE in guides &&
(await isFeatureEnabled(FeatureFlag.EAGLE_EYE, this.options))
) {
guides[QuickstartGuideType.SET_EAGLE_EYE].completed = tenantUser.settings.eagleEye.onboarded
} else {
delete guides[QuickstartGuideType.SET_EAGLE_EYE]
}

// try to find an enrichable member for button CTA of enrich member guide
if (!guides[QuickstartGuideType.ENRICH_MEMBER].completed) {
if (
QuickstartGuideType.ENRICH_MEMBER in guides &&
!guides[QuickstartGuideType.ENRICH_MEMBER].completed
) {
const enrichableMembers = await ms.findAndCountAll({
advancedFilter: {
and: [
Expand Down
4 changes: 4 additions & 0 deletions backend/src/services/tenantService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ export default class TenantService {
}
}

async viewOrganizations() {
return SettingsService.save({ organizationsViewed: true }, this.options)
}

async updatePlanUser(id, planStripeCustomerId, planUserId) {
const transaction = await SequelizeRepository.createTransaction(this.options)

Expand Down
49 changes: 48 additions & 1 deletion backend/src/types/quickstartGuideTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export enum QuickstartGuideType {
VIEW_REPORT = 'view-report',
SET_EAGLE_EYE = 'set-eagle-eye',
INVITE_COLLEAGUES = 'invite-colleagues',
CONNECT_FIRST_INTEGRATION = 'connect-first-integration',
EXPLORE_ORGANIZATIONS = 'explore-organizations',
CREATE_AUTOMATIONS = 'create-automations',
}

export interface QuickstartGuideMap {
Expand All @@ -14,6 +17,7 @@ export interface QuickstartGuide {
title: string
body: string
videoLink: string
learnMoreLink: string
buttonLink: string
buttonText: string
completed: boolean
Expand All @@ -30,6 +34,17 @@ const connectIntegrationGuide: QuickstartGuide = {
title: 'Connect your first 2 integrations',
body: 'Connect with our built-in integrations to start syncing data from your digital channels.',
videoLink: 'https://www.loom.com/share/578ea6ef431c48e0b338cf975d3b80bc',
learnMoreLink: 'https://docs.crowd.dev/docs/getting-started/integrations',
buttonLink: '/integrations',
buttonText: 'Connect integrations',
completed: false,
}

const connectFirstIntegrationGuide: QuickstartGuide = {
title: 'Connect your first integration',
body: 'Connect with our built-in integrations to start syncing data from your digital channels.',
videoLink: 'https://www.loom.com/share/578ea6ef431c48e0b338cf975d3b80bc',
learnMoreLink: 'https://docs.crowd.dev/docs/getting-started/integrations',
buttonLink: '/integrations',
buttonText: 'Connect integrations',
completed: false,
Expand All @@ -39,6 +54,7 @@ const enrichMemberGuide: QuickstartGuide = {
title: 'Enrich a contact',
body: 'Get more insights about contacts by enriching them with attributes such as emails, seniority, OSS contributions and much more.',
videoLink: 'https://www.loom.com/share/8fdbdd2c0d4c4ab59ae845248b1db04f',
learnMoreLink: 'https://www.loom.com/share/8fdbdd2c0d4c4ab59ae845248b1db04f',
buttonLink: '/contacts',
buttonText: 'Try enrichment',
completed: false,
Expand All @@ -47,9 +63,10 @@ const enrichMemberGuide: QuickstartGuide = {
}

const viewReportGuide: QuickstartGuide = {
title: 'Look into a report',
title: 'Look into reports',
body: 'Check our specially crafted default reports and dig into the inner workings of your community.',
videoLink: 'https://www.loom.com/share/545e7dfc692540d09115ee32653640ca',
learnMoreLink: 'https://docs.crowd.dev/docs/guides/reports',
buttonLink: '/reports',
buttonText: 'Explore reports',
completed: false,
Expand All @@ -59,6 +76,7 @@ const setEagleEyeGuide: QuickstartGuide = {
title: 'Discover content in your niche',
body: 'Discover and engage with relevant content across various community platforms in order to gain developers’ mindshare and increase your community awareness.',
videoLink: 'https://www.loom.com/share/7900b1c0ea0b4a33a2cf85d3b175b1b7',
learnMoreLink: 'https://www.loom.com/share/7900b1c0ea0b4a33a2cf85d3b175b1b7',
buttonLink: '/eagle-eye',
buttonText: 'Explore Eagle Eye',
completed: false,
Expand All @@ -68,15 +86,44 @@ const inviteColleaguesGuide: QuickstartGuide = {
title: 'Invite your colleagues',
body: 'Invite colleagues to your crowd.dev workspace by giving full access or read-only permissions.',
videoLink: 'https://www.loom.com/share/f12d87814e7447edab4282eab6bb3ccf',
learnMoreLink: 'https://docs.crowd.dev/docs/getting-started/getting-set-up',
buttonLink: '/settings',
buttonText: 'Invite colleagues',
completed: false,
}

const exploreOrganizations: QuickstartGuide = {
title: 'Explore organizations',
body: 'Discover organizations with developers engaging with your ecosystem or technology and see which companies fit your ICP.',
videoLink: 'https://www.loom.com/share/f12d87814e7447edab4282eab6bb3ccf',
learnMoreLink: 'https://docs.crowd.dev/docs/guides/organizations',
buttonLink: '/organizations',
buttonText: 'Explore organizations',
completed: false,
}

const createAutomations: QuickstartGuide = {
title: 'Create automations',
body: 'Stop focusing on repetitive tasks and concentrate on building deeper relationships with your community by automating your workflows via HubSpot syncs, Slack notifications, or Webhooks.',
videoLink: 'https://www.loom.com/share/f12d87814e7447edab4282eab6bb3ccf',
learnMoreLink: 'https://docs.crowd.dev/docs/guides/automations',
buttonLink: '/automations',
buttonText: 'Create automations',
completed: false,
}

export const DEFAULT_GUIDES = {
[QuickstartGuideType.CONNECT_INTEGRATION]: connectIntegrationGuide,
[QuickstartGuideType.INVITE_COLLEAGUES]: inviteColleaguesGuide,
[QuickstartGuideType.ENRICH_MEMBER]: enrichMemberGuide,
[QuickstartGuideType.VIEW_REPORT]: viewReportGuide,
[QuickstartGuideType.SET_EAGLE_EYE]: setEagleEyeGuide,
}

export const DEFAULT_GUIDES_V2 = {
[QuickstartGuideType.CONNECT_FIRST_INTEGRATION]: connectFirstIntegrationGuide,
[QuickstartGuideType.INVITE_COLLEAGUES]: inviteColleaguesGuide,
[QuickstartGuideType.EXPLORE_ORGANIZATIONS]: exploreOrganizations,
[QuickstartGuideType.VIEW_REPORT]: viewReportGuide,
[QuickstartGuideType.CREATE_AUTOMATIONS]: createAutomations,
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/quickstart/jesse.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import { useAutomationStore } from '@/modules/automation/store';
import Message from '@/shared/message/message';
import { i18n } from '@/i18n';
import formChangeDetector from '@/shared/form/form-change';
import { useQuickStartStore } from '@/modules/quickstart/store';
import { automationTypes } from '../config/automation-types';

const props = defineProps({
Expand All @@ -130,6 +131,7 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue', 'update:automation']);

const { createAutomation, updateAutomation, getAutomations } = useAutomationStore();
const { getGuides } = useQuickStartStore();

const isDrawerOpen = computed({
get() {
Expand Down Expand Up @@ -206,6 +208,7 @@ const doSubmit = () => {
.then(() => {
getAutomations();
emit('update:modelValue', null);
getGuides();
})
.catch(() => {
Message.error('There was an error creating automation, please try again later.');
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/modules/dashboard/components/dashboard-guides.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
</p>
</header>
<section class="pb-1 px-4">
<el-collapse v-model="activeView" accordion>
<el-collapse v-model="activeView" accordion class="dashboard-guides">
<el-tooltip
v-for="guide of guides"
:key="guide.key"
Expand Down Expand Up @@ -93,14 +93,14 @@ import {
mapGetters,
} from '@/shared/vuex/vuex.helpers';
import ConfirmDialog from '@/shared/dialog/confirm-dialog';
import { QuickstartGuideService } from '@/modules/quickstart-guide/services/quickstart-guide.service';
import { useQuickStartGuideStore } from '@/modules/quickstart-guide/store';
import { QuickstartGuideService } from '@/modules/quickstart/services/quickstart-guide.service';
import { useQuickStartStore } from '@/modules/quickstart/store';
import { TenantEventService } from '@/shared/events/tenant-event.service';

const { currentTenant, currentTenantUser } = mapGetters('auth');
const { doRefreshCurrentUser } = mapActions('auth');

const storeQuickStartGuides = useQuickStartGuideStore();
const storeQuickStartGuides = useQuickStartStore();
const { guides, notcompletedGuides } = storeToRefs(
storeQuickStartGuides,
);
Expand Down Expand Up @@ -205,7 +205,7 @@ export default {
</script>

<style lang="scss">
.el-collapse {
.dashboard-guides.el-collapse {
@apply border-none;

.el-collapse-item__header {
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/modules/dashboard/pages/dashboard-page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
: '100vh',
}"
>
<app-dashboard-guides />
<app-dashboard-guides v-if="!isQuickstartEnabled()" />
<app-dashboard-integrations class="mb-10" />
<app-dashboard-task />
</aside>
Expand All @@ -76,6 +76,7 @@ import AppDashboardMembers from '@/modules/dashboard/components/dashboard-member
import AppDashboardOrganizations from '@/modules/dashboard/components/dashboard-organizations.vue';
import AppDashboardTask from '@/modules/dashboard/components/dashboard-task.vue';
import AppDashboardFilters from '@/modules/dashboard/components/dashboard-filters.vue';
import { FeatureFlag } from '@/utils/featureFlag';

const { currentTenant } = mapGetters('auth');
const { showBanner } = mapGetters('tenant');
Expand Down Expand Up @@ -128,6 +129,9 @@ watch(currentTenant, (updatedTenant, previousTenant) => {
deep: true,
immediate: true,
});

const isQuickstartEnabled = () => FeatureFlag.isFlagEnabled(FeatureFlag.flags.quickstartV2);

</script>

<style lang="scss" scoped>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import report from '@/modules/report/report-module';
import automation from '@/modules/automation/automation-module';
import organization from '@/modules/organization/organization-module';
import task from '@/modules/task/task-module';
import quickstart from '@/modules/quickstart/quickstart-module';

import eagleEye from '@/premium/eagle-eye/eagle-eye-module';
import user from '@/modules/user/user-module';
Expand All @@ -34,6 +35,7 @@ const modules: Record<string, any> = {
report,
automation,
task,
quickstart,
user,
eagleEye,
organization,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/modules/layout/components/menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<cr-menu-workspace v-if="currentTenant" />

<div class="px-3 pt-4 pb-2 flex flex-col grow">
<cr-menu-quickstart v-if="isQuickstartEnabled" :collapsed="isCollapsed" />

<!-- Menu items -->
<cr-menu-links class="mb-2" :links="mainMenu" :collapsed="isCollapsed" link-class="text-sm" />

Expand Down Expand Up @@ -40,6 +42,8 @@ import CrMenuWorkspace from '@/modules/layout/components/menu/menu-workspace.vue
import CrMenuLinks from '@/modules/layout/components/menu/menu-links.vue';
import { bottomMenu, mainMenu } from '@/modules/layout/config/menu';
import CrMenuSupport from '@/modules/layout/components/menu/menu-support.vue';
import CrMenuQuickstart from '@/modules/layout/components/menu/menu-quickstart.vue';
import { FeatureFlag } from '@/utils/featureFlag';

const store = useStore();
const { currentTenant } = mapGetters('auth');
Expand All @@ -61,6 +65,8 @@ const isCollapsed = computed(
function toggleMenu() {
store.dispatch('layout/toggleMenu');
}

const isQuickstartEnabled = computed(() => FeatureFlag.isFlagEnabled(FeatureFlag.flags.quickstartV2));
</script>

<script>
Expand Down
Loading