Merge branch 'main' into fix-sms-message-id

This commit is contained in:
Darshan
2024-12-17 10:52:38 +05:30
committed by GitHub
27 changed files with 146 additions and 25 deletions
+2
View File
@@ -36,6 +36,7 @@
"plausible-tracker": "^0.3.9",
"pretty-bytes": "^6.1.1",
"prismjs": "^1.29.0",
"remarkable": "^2.0.1",
"svelte-confetti": "^1.4.0",
"tippy.js": "^6.3.7"
},
@@ -52,6 +53,7 @@
"@testing-library/user-event": "^14.5.2",
"@types/deep-equal": "^1.0.4",
"@types/prismjs": "^1.26.5",
"@types/remarkable": "^2.0.8",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitest/ui": "^1.6.0",
+28
View File
@@ -59,6 +59,9 @@ importers:
prismjs:
specifier: ^1.29.0
version: 1.29.0
remarkable:
specifier: ^2.0.1
version: 2.0.1
svelte-confetti:
specifier: ^1.4.0
version: 1.4.0(svelte@4.2.19)
@@ -102,6 +105,9 @@ importers:
'@types/prismjs':
specifier: ^1.26.5
version: 1.26.5
'@types/remarkable':
specifier: ^2.0.8
version: 2.0.8
'@typescript-eslint/eslint-plugin':
specifier: ^7.18.0
version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)
@@ -1327,6 +1333,9 @@ packages:
'@types/pug@2.0.10':
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
'@types/remarkable@2.0.8':
resolution: {integrity: sha512-eKXqPZfpQl1kOADjdKchHrp2gwn9qMnGXhH/AtZe0UrklzhGJkawJo/Y/D0AlWcdWoWamFNIum8+/nkAISQVGg==}
'@types/shimmer@1.2.0':
resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==}
@@ -1559,6 +1568,9 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
autolinker@3.16.2:
resolution: {integrity: sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==}
available-typed-arrays@1.0.7:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
@@ -3062,6 +3074,11 @@ packages:
resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==}
engines: {node: '>= 0.4'}
remarkable@2.0.1:
resolution: {integrity: sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==}
engines: {node: '>= 6.0.0'}
hasBin: true
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -5143,6 +5160,8 @@ snapshots:
'@types/pug@2.0.10': {}
'@types/remarkable@2.0.8': {}
'@types/shimmer@1.2.0': {}
'@types/stack-utils@2.0.3': {}
@@ -5435,6 +5454,10 @@ snapshots:
asynckit@0.4.0: {}
autolinker@3.16.2:
dependencies:
tslib: 2.8.1
available-typed-arrays@1.0.7:
dependencies:
possible-typed-array-names: 1.0.0
@@ -7144,6 +7167,11 @@ snapshots:
es-errors: 1.3.0
set-function-name: 2.0.2
remarkable@2.0.1:
dependencies:
argparse: 1.0.10
autolinker: 3.16.2
require-directory@2.1.1: {}
require-in-the-middle@7.4.0:
+53 -6
View File
@@ -1,6 +1,9 @@
<script lang="ts">
import { Remarkable } from 'remarkable';
import Template from './template.svelte';
const markdownInstance = new Remarkable();
import { Alert, AvatarInitials, Code, LoadingDots, SvgIcon } from '$lib/components';
import { user } from '$lib/stores/user';
import { useCompletion } from 'ai/svelte';
@@ -19,8 +22,6 @@
credentials: 'include'
});
let question = $input;
const examples = [
'How to add platform in the console?',
'How can I manage users, permissions, and access control in Appwrite?',
@@ -87,10 +88,47 @@
$: answer = parseCompletion($completion);
function renderMarkdown(answer: string): string {
const trimmedAnswer = answer
.trim()
.replace(/[ \t]+/g, ' ')
.replace(/\n[ \t]+/g, '\n')
.replace(/\n+/g, '\n');
// targeting links in plain text.
const processedAnswer = trimmedAnswer
.replace(/(\[(.*?)]\((.*?)\))|https?:\/\/\S+/g, (match, fullMarkdownLink, _, __) =>
fullMarkdownLink ? match : `[${match}](${match})`
)
.replace(/https?:\/\/\S+##/g, (url) => url.replace(/##/, '#'));
const formattedAnswer = processedAnswer.replace(
/(^|\n)Sources:/g,
(_, prefix) => `${prefix}\nSources:`
);
let renderedHTML = markdownInstance.render(formattedAnswer);
// add target blank to open links in a new tab.
renderedHTML = renderedHTML.replace(/<a\s+href="([^"]+)"/g, '<a href="$1" target="_blank"');
return renderedHTML;
}
function getInitials(name: string) {
const [first, last] = name.split(' ');
return `${first?.[0] ?? ''}${last?.[0] ?? ''}`;
}
let previousQuestion = '';
$: if ($input) {
previousQuestion = $input;
}
$: if (!$isLoading && answer) {
// reset input if answer received.
$input = '';
}
</script>
<Template
@@ -142,7 +180,7 @@
<div class="content">
<div class="u-flex u-gap-8 u-cross-center">
<div class="avatar is-size-x-small">{getInitials($user.name)}</div>
<p class="u-opacity-75">{question}</p>
<p class="u-opacity-75">{previousQuestion}</p>
</div>
<div class="u-flex u-gap-8 u-margin-block-start-24">
<div class="logo">
@@ -154,7 +192,7 @@
{:else}
{#each answer as part}
{#if part.type === 'text'}
<p>{part.value.trimStart()}</p>
<p>{@html renderMarkdown(part.value.trim())}</p>
{:else if part.type === 'code'}
{#key part.value}
<div
@@ -196,7 +234,6 @@
class="input-text-wrapper u-width-full-line"
style="--amount-of-buttons: 1;"
on:submit|preventDefault={(e) => {
question = $input;
handleSubmit(e);
}}>
<!-- svelte-ignore a11y-autofocus -->
@@ -269,10 +306,20 @@
.answer {
overflow: hidden;
p {
p:first-of-type {
white-space: pre-wrap;
}
}
:global(.answer ul),
:global(.answer ol) {
gap: 1rem;
display: grid;
}
:global(.answer a) {
text-decoration: underline;
}
}
.footer {
@@ -140,6 +140,7 @@
<InputText
id="taxId"
label="Tax ID"
autofocus
placeholder="Tax ID"
bind:value={taxId} />
</div>
+2 -2
View File
@@ -56,9 +56,9 @@
<style lang="scss">
// TODO: remove once pink is updated
.collapsible-item {
.collapsible-item:not(.is-info) {
.collapsible-wrapper {
padding-left: 0;
padding-left: 0.5rem;
}
.collapsible-wrapper.is-disabled {
cursor: not-allowed;
+8 -2
View File
@@ -24,11 +24,17 @@
let error: string;
onMount(() => {
if (element && autofocus) {
element.focus();
if (autofocus) {
addInputFocus();
}
});
export function addInputFocus() {
if (element) {
element.focus();
}
}
const handleInvalid = (event: Event) => {
event.preventDefault();
@@ -71,6 +71,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Function"
bind:id={$createFunction.$id}
@@ -48,6 +48,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Function"
bind:id={$createFunction.$id}
@@ -73,6 +73,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Function"
bind:id={$templateConfig.$id}
@@ -75,7 +75,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Organization" bind:id />
<CustomId autofocus bind:show={showCustomId} name="Organization" bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">
+6 -1
View File
@@ -125,7 +125,12 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Organization" isProject bind:id />
<CustomId
autofocus
bind:show={showCustomId}
name="Organization"
isProject
bind:id />
{/if}
{#if isCloud}
<div class="u-margin-block-start-8">
@@ -40,7 +40,12 @@
Apply Appwrite credits to your organization.
<FormList>
<InputText placeholder="Promo code" id="code" label="Add promo code" bind:value={coupon} />
<InputText
placeholder="Promo code"
id="code"
autofocus
label="Add promo code"
bind:value={coupon} />
</FormList>
<svelte:fragment slot="footer">
@@ -84,6 +84,7 @@
<InputNumber
placeholder="Add budget cap"
id="cap"
autofocus
label="Budget cap (USD)"
bind:value={budget} />
{/if}
@@ -61,7 +61,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Project" isProject bind:id />
<CustomId autofocus bind:show={showCustomId} name="Project" isProject bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">
@@ -31,6 +31,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Project"
isProject={true}
@@ -58,7 +58,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Team" bind:id />
<CustomId autofocus bind:show={showCustomId} name="Team" bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">
@@ -84,7 +84,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showDropdown} name="User" bind:id />
<CustomId autofocus bind:show={showDropdown} name="User" bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">
@@ -8,6 +8,7 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { project } from '../../store';
import { tick } from 'svelte';
let passwordHistory = $project?.authPasswordHistory < 1 ? 5 : $project?.authPasswordHistory;
let passwordHistoryEnabled = ($project?.authPasswordHistory ?? 0) !== 0;
@@ -34,6 +35,14 @@
trackError(error, Submit.AuthPasswordHistoryUpdate);
}
}
let maxSessionInputField: InputNumber | null = null;
$: if (passwordHistoryEnabled && maxSessionInputField) {
tick().then(() => {
maxSessionInputField.addInputFocus();
});
}
</script>
<Form onSubmit={updatePasswordHistoryLimit}>
@@ -59,6 +68,7 @@
min={1}
id="max-session"
label="Limit"
bind:this={maxSessionInputField}
disabled={!passwordHistoryEnabled}
bind:value={passwordHistory} />
</FormList>
@@ -9,6 +9,7 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { project } from '../../store';
import { tick } from 'svelte';
let isLimited = $project?.authLimit !== 0;
let newLimit = isLimited ? $project?.authLimit : 100;
@@ -41,6 +42,14 @@
trackError(error, Submit.AuthLimitUpdate);
}
}
let maxUsersInputField: HTMLInputElement | null = null;
$: if (isLimited && maxUsersInputField) {
tick().then(() => {
maxUsersInputField.focus();
});
}
</script>
<CardGrid>
@@ -96,7 +105,8 @@
class="input-text"
max="10000"
disabled={!isLimited}
bind:value={newLimit} />
bind:value={newLimit}
bind:this={maxUsersInputField} />
</div>
</li>
</ul>
@@ -29,7 +29,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Document" bind:id={customId} />
<CustomId autofocus bind:show={showCustomId} name="Document" bind:id={customId} />
{/if}
{/if}
</ul>
@@ -71,10 +71,10 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Collection"
bind:id
autofocus={false}
fullWidth={true} />
{/if}
</FormList>
@@ -52,6 +52,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Function"
bind:id={$createFunction.id}
@@ -63,7 +63,7 @@
</script>
<Form onSubmit={update}>
<CardGrid hideFooter={message.status != 'draft'}>
<CardGrid hideFooter={message.status !== 'draft'}>
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16">
<Heading tag="h6" size="7">Message</Heading>
</div>
@@ -72,12 +72,12 @@
<InputText
id="subject"
label="Subject"
disabled={message.status != 'draft'}
disabled={message.status !== 'draft'}
bind:value={subject}></InputText>
<InputTextarea
id="message"
label="Message"
disabled={message.status != 'draft'}
disabled={message.status !== 'draft'}
bind:value={content}></InputTextarea>
<InputSwitch label="HTML mode" id="html" bind:value={html}>
<svelte:fragment slot="description">
@@ -58,7 +58,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Topic" bind:id />
<CustomId autofocus bind:show={showCustomId} name="Topic" bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">
@@ -115,6 +115,7 @@
</div>
{:else}
<CustomId
autofocus
bind:show={showCustomId}
name="Message"
bind:id={$messageParams[$providerType].messageId}
@@ -62,7 +62,7 @@
</div>
{:else}
<div class="custom-id-wrapper">
<CustomId bind:show={showCustomId} name="File" bind:id={$createFile.id} />
<CustomId autofocus bind:show={showCustomId} name="File" bind:id={$createFile.id} />
</div>
{/if}
</FormList>
@@ -63,7 +63,7 @@
</Pill>
</div>
{:else}
<CustomId bind:show={showCustomId} name="Bucket" bind:id />
<CustomId autofocus bind:show={showCustomId} name="Bucket" bind:id />
{/if}
</FormList>
<svelte:fragment slot="footer">