Skip to content

Commit d141ef0

Browse files
authored
Merge pull request #1564 from ItzNotABug/fix-support
New layout for support and add subject
2 parents f632082 + c75db74 commit d141ef0

File tree

7 files changed

+233
-105
lines changed

7 files changed

+233
-105
lines changed

src/lib/components/support.svelte

Lines changed: 162 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,141 @@
11
<script lang="ts">
22
import { Button } from '$lib/elements/forms';
3-
import { app } from '$lib/stores/app';
43
import { wizard } from '$lib/stores/wizard';
54
import SupportWizard from '$routes/(console)/supportWizard.svelte';
6-
import { showSupportModal } from '$routes/(console)/wizard/support/store';
7-
import { isCloud } from '$lib/system';
5+
import { isSupportOnline, showSupportModal } from '$routes/(console)/wizard/support/store';
86
import { trackEvent } from '$lib/actions/analytics';
9-
import { localeTimezoneName, utcHourToLocaleHour } from '$lib/helpers/date';
7+
import { localeShortTimezoneName, utcHourToLocaleHour } from '$lib/helpers/date';
108
import { upgradeURL } from '$lib/stores/billing';
9+
import { Card } from '$lib/components/index';
10+
import { app } from '$lib/stores/app';
1111
import { currentPlan } from '$lib/stores/organization';
12+
import { isCloud } from '$lib/system';
1213
1314
export let show = false;
1415
16+
export let showHeader = true;
17+
1518
$: hasPremiumSupport = $currentPlan?.premiumSupport ?? false;
1619
17-
$: supportTimings = `${utcHourToLocaleHour('16:00')} - ${utcHourToLocaleHour('00:00')} ${localeTimezoneName()}`;
20+
$: supportTimings = `${utcHourToLocaleHour('16:00')} - ${utcHourToLocaleHour('00:00')} ${localeShortTimezoneName()}`;
21+
22+
type SupportOption = {
23+
cta?: string;
24+
icon: string;
25+
label: string;
26+
link?: string;
27+
description: string;
28+
showSupport: boolean;
29+
};
30+
31+
const supportOptions: SupportOption[] = [
32+
{
33+
showSupport: true,
34+
icon: 'support',
35+
label: 'Premium support',
36+
description: 'Get priority email support from the Appwrite team'
37+
},
38+
39+
{
40+
icon: 'discord',
41+
cta: 'Discord',
42+
showSupport: false,
43+
label: 'Community support',
44+
link: 'https://appwrite.io/discord',
45+
description: 'Get support from our community through Discord'
46+
},
47+
{
48+
icon: 'github',
49+
cta: 'Open issue',
50+
showSupport: false,
51+
label: 'Open GitHub issue',
52+
link: 'https://github.com/appwrite/appwrite/issues/new/choose',
53+
description: 'Report a bug or pitch a new feature'
54+
}
55+
];
56+
57+
const showCloudSupport = (index) => {
58+
return (index === 0 && isCloud) || index > 0;
59+
};
1860
</script>
1961

20-
{#if isCloud}
21-
<section class="drop-section u-grid u-gap-24 u-padding-24">
22-
<div>
23-
<h4 class="eyebrow-heading-3">Premium support</h4>
24-
{#if hasPremiumSupport}
25-
<p class="u-line-height-1-5 u-margin-block-start-8">
26-
Get personalized support from the Appwrite team from <b>{supportTimings}</b>
27-
</p>
28-
{/if}
29-
</div>
30-
{#if !hasPremiumSupport}
31-
<Button
32-
fullWidth
33-
href={$upgradeURL}
34-
on:click={() => {
35-
trackEvent('click_organization_upgrade', {
36-
from: 'button',
37-
source: 'support_menu'
38-
});
39-
}}>
40-
<span class="text">Get Premium support</span>
41-
</Button>
42-
{:else}
43-
<Button
44-
secondary
45-
fullWidth
46-
on:click={() => {
47-
show = false;
48-
$showSupportModal = false;
49-
wizard.start(SupportWizard);
50-
}}>
51-
<span class="text">Contact our Support Team</span>
52-
</Button>
62+
<section class="drop-section support-section">
63+
{#if showHeader}
64+
<h4 class="heading-level-6">Support</h4>
65+
{/if}
66+
67+
{#each supportOptions as option, index}
68+
{#if showCloudSupport(index)}
69+
<Card
70+
isTile
71+
class="support-option-card u-flex u-flex-vertical u-gap-16"
72+
style="border-radius: var(--border-radius-small, 8px); padding: 0.65rem;">
73+
<div class="u-flex u-flex-vertical u-gap-4">
74+
<h4 class="body-text-2 u-bold">{option.label}</h4>
75+
76+
<p class="u-line-height-1-5">
77+
{option.description}
78+
</p>
79+
</div>
80+
81+
{#if option.showSupport}
82+
<div class="u-flex u-gap-12 u-cross-center">
83+
{#if !hasPremiumSupport}
84+
<Button
85+
href={$upgradeURL}
86+
on:click={() => {
87+
trackEvent('click_organization_upgrade', {
88+
from: 'button',
89+
source: 'support_menu'
90+
});
91+
}}>
92+
<span class="text">Get Premium support</span>
93+
</Button>
94+
{:else}
95+
<Button
96+
secondary
97+
class="secondary-button"
98+
on:click={() => {
99+
show = false;
100+
$showSupportModal = false;
101+
wizard.start(SupportWizard);
102+
}}>
103+
<span class="text">Contact support</span>
104+
</Button>
105+
{/if}
106+
107+
<div class="u-flex u-gap-6 u-cross-center">
108+
<span
109+
aria-hidden="true"
110+
class="{isSupportOnline()
111+
? 'icon-check-circle u-color-text-success'
112+
: 'icon-x-circle'} u-padding-block-end-1" />
113+
114+
{supportTimings}
115+
</div>
116+
</div>
117+
{:else}
118+
<Button
119+
href={option.link}
120+
external
121+
secondary
122+
class="secondary-button u-flex u-cross-center u-gap-6"
123+
on:click={() => {
124+
trackEvent('click_organization_upgrade', {
125+
from: 'button',
126+
source: 'support_menu'
127+
});
128+
}}>
129+
<span class={`icon-${option.icon}`} />
130+
<span>{option.cta}</span>
131+
</Button>
132+
{/if}
133+
</Card>
53134
{/if}
54-
</section>
55-
{/if}
56-
<section class="drop-section u-grid u-gap-24 u-padding-24">
57-
<div>
58-
<h4 class="eyebrow-heading-3">Troubleshooting</h4>
135+
{/each}
59136

60-
<div class="u-margin-block-start-8 u-width-full-line">
137+
{#if isCloud}
138+
<div class="u-width-full-line">
61139
{#key $app.themeInUse}
62140
<iframe
63141
style="color-scheme: none"
@@ -72,49 +150,44 @@
72150
</iframe>
73151
{/key}
74152
</div>
75-
</div>
76-
77-
<div class="u-flex u-gap-16">
78-
<a
79-
href="https://appwrite.io/docs"
80-
target="_blank"
81-
rel="noopener noreferrer"
82-
class="button is-secondary u-padding-inline-12 u-stretch u-main-center u-gap-4 u-flex-basis-auto">
83-
<span class="icon-book-open" aria-hidden="true" />
84-
<span class="text">Docs</span>
85-
</a>
86-
<a
87-
href="https://github.com/appwrite/appwrite/issues"
88-
aria-label="Open issue on GitHub"
89-
target="_blank"
90-
rel="noopener noreferrer"
91-
class="button is-secondary u-padding-inline-12 u-stretch u-main-center u-gap-4 u-flex-basis-auto">
92-
<span class="icon-github" aria-hidden="true" />
93-
<span class="text">Open issue</span>
94-
</a>
95-
</div>
96-
</section>
97-
<section class="drop-section u-grid u-gap-8 u-padding-24">
98-
<div>
99-
<h4 class="eyebrow-heading-3">Community support</h4>
100-
<p class="text u-margin-block-start-8">Get help from our community</p>
101-
</div>
102-
<ul class="u-flex u-gap-8">
103-
<li>
104-
<Button href="https://github.com/appwrite" text noMargin external ariaLabel="Github">
105-
<span class="icon-github" aria-hidden="true" />
106-
</Button>
107-
</li>
108-
<li>
109-
<Button
110-
href="https://appwrite.io/discord"
111-
round
112-
text
113-
noMargin
114-
external
115-
ariaLabel="Discord">
116-
<span class="icon-discord" aria-hidden="true" />
117-
</Button>
118-
</li>
119-
</ul>
153+
{/if}
120154
</section>
155+
156+
<style lang="scss">
157+
.support-section {
158+
gap: 1rem;
159+
padding: 1rem;
160+
display: flex;
161+
flex-direction: column;
162+
163+
@media (max-width: 768px) {
164+
gap: 1.25rem;
165+
padding: 0.5rem;
166+
}
167+
}
168+
169+
:global(.u-gap-6) {
170+
gap: 0.375rem;
171+
}
172+
173+
:global(.support-option-card) {
174+
padding: 0.75rem !important;
175+
}
176+
177+
:global(.theme-dark .support-option-card) {
178+
background: var(--color-bgColor-neutral-default, #19191c);
179+
}
180+
181+
:global(.theme-dark .support-option-card .secondary-button) {
182+
background: var(--color-bgColor-neutral-primary, #131315);
183+
}
184+
185+
:global(.theme-light .support-option-card) {
186+
border: 1px solid var(--color-border-neutral, #ededf0);
187+
background: var(--color-bgColor-neutral-default, #fafafb);
188+
}
189+
190+
:global(.theme-light .support-option-card .secondary-button) {
191+
background: var(--color-bgColor-neutral-primary, #fff);
192+
}
193+
</style>

src/lib/helpers/date.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,23 @@ export const localeTimezoneName = () => {
128128
return dateWithTimezone.split(', ')[1];
129129
};
130130

131+
/**
132+
* This function processes the timezone name using regex to:
133+
*
134+
* 1. Trim and simplify the text for UI display (e.g., IST, UST, etc.).
135+
* 2. Handle cases where `timeZoneName: 'shortGeneric'` returns names like `India Time`,
136+
* which do not fit well in the support modal UI.
137+
* 3. Not using `timeZoneName: 'short'`, as it can display `GMT+-` formatted timezones,
138+
* which may not be ideal.
139+
*
140+
* Refer to:
141+
* https://github.com/appwrite/console/pull/1564#discussion_r1913977798
142+
*/
143+
export const localeShortTimezoneName = () => {
144+
const timezone = localeTimezoneName();
145+
return timezone.match(/[A-Z]/g)?.join('') || timezone;
146+
};
147+
131148
export const isSameDay = (date1: Date, date2: Date) => {
132149
return (
133150
date1.getFullYear() === date2.getFullYear() &&

src/lib/layout/header.svelte

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,19 @@
125125
<Feedback />
126126
</svelte:fragment>
127127
</DropList>
128-
129-
{#if isCloud}
130-
<DropList width="18.5" bind:show={showSupport} scrollable={true}>
131-
<Button text on:click={() => (showSupport = !showSupport)}>
132-
<span class="text">Support</span>
133-
</Button>
134-
<svelte:fragment slot="other">
135-
<Support bind:show={showSupport} />
136-
</svelte:fragment>
137-
</DropList>
138-
{/if}
128+
<DropList
129+
class="support-drop-section"
130+
bind:show={showSupport}
131+
scrollable={true}
132+
noArrow
133+
placement="bottom-end">
134+
<Button text on:click={() => (showSupport = !showSupport)}>
135+
<span class="text">Support</span>
136+
</Button>
137+
<svelte:fragment slot="other">
138+
<Support bind:show={showSupport} />
139+
</svelte:fragment>
140+
</DropList>
139141
<Button
140142
actions={[
141143
(node) => {
@@ -265,3 +267,10 @@
265267
{/if}
266268
</nav>
267269
</div>
270+
271+
<style>
272+
:global(.support-drop-section) {
273+
width: 28.375rem;
274+
margin-block-start: 0.15rem;
275+
}
276+
</style>

src/routes/(console)/supportWizard.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
onDestroy(() => {
2121
$supportData = {
2222
message: null,
23+
subject: null,
2324
category: 'general',
2425
file: null
2526
};
@@ -39,8 +40,8 @@
3940
'Content-Type': 'application/json'
4041
},
4142
body: JSON.stringify({
42-
subject: 'support',
4343
email: $user.email,
44+
subject: $supportData.subject,
4445
firstName: $user?.name || 'Unknown',
4546
message: $supportData.message,
4647
tags: ['cloud'],
@@ -75,6 +76,7 @@
7576
function resetData() {
7677
$supportData = {
7778
message: null,
79+
subject: null,
7880
category: 'general',
7981
file: null,
8082
project: null

src/routes/(console)/wizard/support/mobileSupportModal.svelte

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@
55
export let show: boolean;
66
</script>
77

8-
<Modal title="Contact us" bind:show>
9-
<Support />
10-
</Modal>
8+
<div class="mobile-support-dialog-modal">
9+
<Modal title="Support" headerDivider={false} size="small" bind:show>
10+
<div class="inner-modal-wrapper">
11+
<Support showHeader={false} />
12+
</div>
13+
</Modal>
14+
</div>
15+
16+
<style>
17+
:global(.mobile-support-dialog-modal dialog) {
18+
background-color: #fff;
19+
}
20+
21+
:global(.theme-dark .mobile-support-dialog-modal dialog) {
22+
background-color: #131315;
23+
}
24+
25+
.inner-modal-wrapper {
26+
padding-block-start: 0.5rem;
27+
}
28+
</style>

0 commit comments

Comments
 (0)