From c0d16975b2196e53e1e8423f6e47a6d82cbc8d8b Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 13 Apr 2023 15:42:02 +0200 Subject: [PATCH 1/4] refactor: feedback dropdown and wizard --- .../{ => feedback}/evaluation.svelte | 0 .../feedback.svelte} | 47 +++--- .../feedback/feedbackGeneral.svelte | 19 +++ .../components/feedback/feedbackNPS.svelte | 30 ++++ src/lib/components/feedback/index.ts | 3 + src/lib/components/feedbackNPS.svelte | 78 ---------- src/lib/components/index.ts | 3 - src/lib/images/feedback/feedback-dark.svg | 138 ++++++++++++++++++ src/lib/images/feedback/feedback-light.svg | 126 ++++++++++++++++ src/lib/layout/header.svelte | 20 +-- src/lib/layout/navigation.svelte | 38 ++++- src/lib/stores/app.ts | 79 ---------- src/lib/stores/feedback.ts | 122 ++++++++++++++++ src/routes/console/+layout.svelte | 2 +- src/routes/console/feedbackWizard.svelte | 30 ++++ .../createAttribute.svelte | 2 +- .../console/wizardFeedback/step1.svelte | 39 +++++ .../console/wizardFeedback/step2.svelte | 18 +++ 18 files changed, 588 insertions(+), 206 deletions(-) rename src/lib/components/{ => feedback}/evaluation.svelte (100%) rename src/lib/components/{feedbackGeneral.svelte => feedback/feedback.svelte} (55%) create mode 100644 src/lib/components/feedback/feedbackGeneral.svelte create mode 100644 src/lib/components/feedback/feedbackNPS.svelte create mode 100644 src/lib/components/feedback/index.ts delete mode 100644 src/lib/components/feedbackNPS.svelte create mode 100644 src/lib/images/feedback/feedback-dark.svg create mode 100644 src/lib/images/feedback/feedback-light.svg create mode 100644 src/lib/stores/feedback.ts create mode 100644 src/routes/console/feedbackWizard.svelte create mode 100644 src/routes/console/wizardFeedback/step1.svelte create mode 100644 src/routes/console/wizardFeedback/step2.svelte diff --git a/src/lib/components/evaluation.svelte b/src/lib/components/feedback/evaluation.svelte similarity index 100% rename from src/lib/components/evaluation.svelte rename to src/lib/components/feedback/evaluation.svelte diff --git a/src/lib/components/feedbackGeneral.svelte b/src/lib/components/feedback/feedback.svelte similarity index 55% rename from src/lib/components/feedbackGeneral.svelte rename to src/lib/components/feedback/feedback.svelte index 7cef18c388..f9e9561d72 100644 --- a/src/lib/components/feedbackGeneral.svelte +++ b/src/lib/components/feedback/feedback.svelte @@ -1,22 +1,23 @@ + + + + + + diff --git a/src/lib/components/feedback/feedbackNPS.svelte b/src/lib/components/feedback/feedbackNPS.svelte new file mode 100644 index 0000000000..613e10514a --- /dev/null +++ b/src/lib/components/feedback/feedbackNPS.svelte @@ -0,0 +1,30 @@ + + + + How likely are you to recommend Appwrite to a friend or colleague? + +{#if $feedbackData.value} + + + + + +{/if} diff --git a/src/lib/components/feedback/index.ts b/src/lib/components/feedback/index.ts new file mode 100644 index 0000000000..15d522683d --- /dev/null +++ b/src/lib/components/feedback/index.ts @@ -0,0 +1,3 @@ +export { default as Feedback } from './feedback.svelte'; +export { default as FeedbackGeneral } from './feedbackGeneral.svelte'; +export { default as FeedbackNPS } from './feedbackNPS.svelte'; diff --git a/src/lib/components/feedbackNPS.svelte b/src/lib/components/feedbackNPS.svelte deleted file mode 100644 index a9276b4a75..0000000000 --- a/src/lib/components/feedbackNPS.svelte +++ /dev/null @@ -1,78 +0,0 @@ - - -
-
-

How are we doing?

- -
-
- At Appwrite, we value the feedback of our users. That means you! We'd love to hear what you - think. -
- -
- - How likely are you to recommend Appwrite to a friend or colleague? - - {#if value} - - - - - - {/if} -
- - -
-
-
diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index f891b82552..f2cf6e0eed 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -31,9 +31,6 @@ export { default as Box } from './box.svelte'; export { default as Search } from './search.svelte'; export { default as SearchQuery } from './searchQuery.svelte'; export { default as GridItem1 } from './gridItem1.svelte'; -export { default as FeedbackGeneral } from './feedbackGeneral.svelte'; -export { default as FeedbackNPS } from './feedbackNPS.svelte'; -export { default as Evaluation } from './evaluation.svelte'; export { default as Steps } from './steps.svelte'; export { default as Step } from './step.svelte'; export { default as Code } from './code.svelte'; diff --git a/src/lib/images/feedback/feedback-dark.svg b/src/lib/images/feedback/feedback-dark.svg new file mode 100644 index 0000000000..8f0b553d6b --- /dev/null +++ b/src/lib/images/feedback/feedback-dark.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/images/feedback/feedback-light.svg b/src/lib/images/feedback/feedback-light.svg new file mode 100644 index 0000000000..d7ace402f4 --- /dev/null +++ b/src/lib/images/feedback/feedback-light.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/layout/header.svelte b/src/lib/layout/header.svelte index e9ec88e7fa..099c1411f4 100644 --- a/src/lib/layout/header.svelte +++ b/src/lib/layout/header.svelte @@ -1,26 +1,20 @@ @@ -122,6 +133,24 @@ Storage +
  • + trackEvent('click_menu_settings')} + class:is-selected={$page.url.pathname.startsWith( + `${projectPath}/settings` + )} + title="Settings" + use:tooltip={{ + content: 'Settings', + placement: 'right', + disabled: !narrow + }}> + +
  • @@ -129,7 +158,7 @@ {/if} diff --git a/src/lib/stores/app.ts b/src/lib/stores/app.ts index 11afe9d6af..7c4b2a1849 100644 --- a/src/lib/stores/app.ts +++ b/src/lib/stores/app.ts @@ -1,5 +1,4 @@ import { browser } from '$app/environment'; -import { VARS } from '$lib/system'; import { writable } from 'svelte/store'; export type AppStore = { @@ -7,89 +6,11 @@ export type AppStore = { themeInUse: 'light' | 'dark'; }; -export type Feedback = { - elapsed: number; - visualized: number; - notification: boolean; - type: 'nps' | 'general'; - show: boolean; -}; - export const app = writable({ theme: 'auto', themeInUse: 'light' }); -function createFeedbackStore() { - const { subscribe, update } = writable({ - elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0, - visualized: browser ? parseInt(localStorage.getItem('feedbackVisualized')) : 0, - notification: false, - type: 'general', - show: false - }); - return { - subscribe, - update, - toggleFeedback: () => { - update((feedback) => { - feedback.show = !feedback.show; - return feedback; - }); - }, - toggleNotification: () => - update((feedback) => { - feedback.notification = !feedback.notification; - return feedback; - }), - switchType: (feedType: Feedback['type']) => - update((feedback) => { - feedback.type = feedType; - return feedback; - }), - addVisualization: () => - update((feedback) => { - feedback.visualized += 1; - localStorage.setItem('feedbackVisualized', feedback.visualized.toString()); - return feedback; - }), - - increaseElapsed: (time: number) => { - update((feedback) => { - feedback.elapsed += time; - localStorage.setItem('feedbackElapsed', feedback.elapsed.toString()); - return feedback; - }); - }, - submitFeedback: async ( - subject: string, - message: string, - firstname?: string, - email?: string, - value?: number - ) => { - if (!VARS.GROWTH_ENDPOINT) return; - const response = await fetch(`${VARS.GROWTH_ENDPOINT}/feedback`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - subject, - message, - email, - firstname: firstname ? firstname : undefined, - customFields: value ? [{ id: '40655', value }] : undefined - }) - }); - if (response.status >= 400) { - throw new Error('Failed to submit feedback'); - } - } - }; -} -export const feedback = createFeedbackStore(); - if (browser) { app.update((n) => ({ ...n, diff --git a/src/lib/stores/feedback.ts b/src/lib/stores/feedback.ts new file mode 100644 index 0000000000..7afdbee524 --- /dev/null +++ b/src/lib/stores/feedback.ts @@ -0,0 +1,122 @@ +import { browser } from '$app/environment'; +import { VARS } from '$lib/system'; +import { writable } from 'svelte/store'; +import type { SvelteComponent } from 'svelte'; +import FeedbackGeneral from '$lib/components/feedback/feedbackGeneral.svelte'; +import FeedbackNps from '$lib/components/feedback/feedbackNPS.svelte'; + +export type Feedback = { + elapsed: number; + visualized: number; + notification: boolean; + type: 'nps' | 'general'; + show: boolean; +}; + +export type FeedbackData = { + message: string; + name?: string; + email?: string; + value?: number; +}; + +export const feedbackData = writable({ + message: '', + name: '', + email: '', + value: 0 +}); + +export type FeedbackOption = { + type: Feedback['type']; + title: string; + desc: string; + component: typeof SvelteComponent; +}; + +export const feedbackOptions: FeedbackOption[] = [ + { + type: 'general', + title: 'How can we improve?', + desc: 'Your feedback is important to us. Please be honest and tell us what you think.', + component: FeedbackGeneral + }, + { + type: 'nps', + title: 'How are we doing?', + desc: "At Appwrite, we value the feedback of our users. That means you! We'd love to hear what you think.", + component: FeedbackNps + } +]; + +export const selectedFeedback = writable(); + +function createFeedbackStore() { + const { subscribe, update } = writable({ + elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0, + visualized: browser ? parseInt(localStorage.getItem('feedbackVisualized')) : 0, + notification: false, + type: 'general', + show: false + }); + return { + subscribe, + update, + toggleFeedback: () => { + update((feedback) => { + feedback.show = !feedback.show; + return feedback; + }); + }, + toggleNotification: () => + update((feedback) => { + feedback.notification = !feedback.notification; + return feedback; + }), + switchType: (feedType: Feedback['type']) => + update((feedback) => { + feedback.type = feedType; + return feedback; + }), + addVisualization: () => + update((feedback) => { + feedback.visualized += 1; + localStorage.setItem('feedbackVisualized', feedback.visualized.toString()); + return feedback; + }), + + increaseElapsed: (time: number) => { + update((feedback) => { + feedback.elapsed += time; + localStorage.setItem('feedbackElapsed', feedback.elapsed.toString()); + return feedback; + }); + }, + submitFeedback: async ( + subject: string, + message: string, + firstname?: string, + email?: string, + value?: number + ) => { + if (!VARS.GROWTH_ENDPOINT) return; + const response = await fetch(`${VARS.GROWTH_ENDPOINT}/feedback`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + subject, + message, + email, + firstname: firstname ? firstname : undefined, + customFields: value ? [{ id: '40655', value }] : undefined + }) + }); + if (response.status >= 400) { + throw new Error('Failed to submit feedback'); + } + } + }; +} +export const feedback = createFeedbackStore(); diff --git a/src/routes/console/+layout.svelte b/src/routes/console/+layout.svelte index 870794b406..04518a68c4 100644 --- a/src/routes/console/+layout.svelte +++ b/src/routes/console/+layout.svelte @@ -7,7 +7,7 @@ import Header from '$lib/layout/header.svelte'; import SideNavigation from '$lib/layout/navigation.svelte'; import Shell from '$lib/layout/shell.svelte'; - import { feedback } from '$lib/stores/app'; + import { feedback } from '$lib/stores/feedback'; import { log } from '$lib/stores/logs'; import { newOrgModal } from '$lib/stores/organization'; import { wizard } from '$lib/stores/wizard'; diff --git a/src/routes/console/feedbackWizard.svelte b/src/routes/console/feedbackWizard.svelte new file mode 100644 index 0000000000..44c023874d --- /dev/null +++ b/src/routes/console/feedbackWizard.svelte @@ -0,0 +1,30 @@ + + + diff --git a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/createAttribute.svelte b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/createAttribute.svelte index 8f6c647493..acc0890462 100644 --- a/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/createAttribute.svelte +++ b/src/routes/console/project-[project]/databases/database-[database]/collection-[collection]/createAttribute.svelte @@ -10,7 +10,7 @@ import type { Attributes } from './store'; import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { preferences } from '$lib/stores/preferences'; - import { feedback } from '$lib/stores/app'; + import { feedback } from '$lib/stores/feedback'; export let showCreate = false; export let selectedOption: string = null; diff --git a/src/routes/console/wizardFeedback/step1.svelte b/src/routes/console/wizardFeedback/step1.svelte new file mode 100644 index 0000000000..c3a6655903 --- /dev/null +++ b/src/routes/console/wizardFeedback/step1.svelte @@ -0,0 +1,39 @@ + + + + {$selectedFeedback.title} + {$selectedFeedback.desc} + + + diff --git a/src/routes/console/wizardFeedback/step2.svelte b/src/routes/console/wizardFeedback/step2.svelte new file mode 100644 index 0000000000..1e91272cfd --- /dev/null +++ b/src/routes/console/wizardFeedback/step2.svelte @@ -0,0 +1,18 @@ + + + + Thanks for the feedback! + +
    + {#if $app.themeInUse === 'dark'} + + {:else} + + {/if} +
    +
    From f2622f0f78beedf131b43f6fcc3bcee24495e08b Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 23 May 2023 15:05:58 +0200 Subject: [PATCH 2/4] fix: reset data after submission --- src/lib/components/feedback/feedback.svelte | 4 +-- src/lib/stores/feedback.ts | 31 ++++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/lib/components/feedback/feedback.svelte b/src/lib/components/feedback/feedback.svelte index f9e9561d72..98cb759bdb 100644 --- a/src/lib/components/feedback/feedback.svelte +++ b/src/lib/components/feedback/feedback.svelte @@ -22,13 +22,13 @@ type: 'success', message: 'Feedback submitted successfully' }); + feedback.toggleFeedback(); + feedbackData.reset(); } catch (error) { addNotification({ type: 'error', message: error.message }); - } finally { - feedback.toggleFeedback(); } } diff --git a/src/lib/stores/feedback.ts b/src/lib/stores/feedback.ts index 7afdbee524..d63e1d2ec1 100644 --- a/src/lib/stores/feedback.ts +++ b/src/lib/stores/feedback.ts @@ -20,13 +20,6 @@ export type FeedbackData = { value?: number; }; -export const feedbackData = writable({ - message: '', - name: '', - email: '', - value: 0 -}); - export type FeedbackOption = { type: Feedback['type']; title: string; @@ -51,6 +44,30 @@ export const feedbackOptions: FeedbackOption[] = [ export const selectedFeedback = writable(); +function createFeedbackDataStore() { + const { subscribe, update } = writable({ + message: '', + name: '', + email: '', + value: 0 + }); + return { + subscribe, + update, + reset: () => { + update((feedbackData) => { + feedbackData.message = ''; + feedbackData.name = ''; + feedbackData.email = ''; + feedbackData.value = 0; + return feedbackData; + }); + } + }; +} + +export const feedbackData = createFeedbackDataStore(); + function createFeedbackStore() { const { subscribe, update } = writable({ elapsed: browser ? parseInt(localStorage.getItem('feedbackElapsed')) : 0, From ac4d003a14cfd1bbb0249d917a648013225610c1 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 31 May 2023 17:42:10 +0200 Subject: [PATCH 3/4] fix: mobile wizard not closing --- src/lib/layout/navigation.svelte | 3 +++ src/routes/console/+layout.svelte | 5 ++++- src/routes/console/feedbackWizard.svelte | 13 ++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/lib/layout/navigation.svelte b/src/lib/layout/navigation.svelte index 3b8e6b1d4f..96892c26bb 100644 --- a/src/lib/layout/navigation.svelte +++ b/src/lib/layout/navigation.svelte @@ -9,6 +9,8 @@ import { wizard } from '$lib/stores/wizard'; import Create from '$routes/console/feedbackWizard.svelte'; + export let isOpen = false; + $: project = $page.params.project; $: projectPath = `${base}/console/project-${project}`; @@ -32,6 +34,7 @@ } function openWizard() { + isOpen = false; wizard.start(Create); } diff --git a/src/routes/console/+layout.svelte b/src/routes/console/+layout.svelte index 04518a68c4..38e74b324b 100644 --- a/src/routes/console/+layout.svelte +++ b/src/routes/console/+layout.svelte @@ -15,6 +15,8 @@ import { loading } from '../store'; import Create from './createOrganization.svelte'; + let isOpen = false; + onMount(() => { loading.set(false); @@ -47,12 +49,13 @@
    - +