mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'users' of github.com:appwrite/appwrite-console-poc into storage
This commit is contained in:
+2
-1
@@ -1 +1,2 @@
|
||||
VITE_APPWRITE_ENDPOINT=
|
||||
VITE_APPWRITE_ENDPOINT=
|
||||
VITE_GOOGLE_ANALYTICS=
|
||||
Generated
+13
@@ -22,6 +22,7 @@
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/svelte": "^3.1.3",
|
||||
"@testing-library/user-event": "^14.2.0",
|
||||
"@types/gtag.js": "^0.0.10",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.1",
|
||||
"@typescript-eslint/parser": "^5.27.1",
|
||||
"eslint": "^8.17.0",
|
||||
@@ -1476,6 +1477,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/gtag.js": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.10.tgz",
|
||||
"integrity": "sha512-98Hy7woUb3jMAMXkZQwfIOYNyfxmI0+U4m0PpCGdnd/FHk0tDpQFCqgXdNkdEoXsKkcGya/2Gew1cAJjKJspVw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||
@@ -8960,6 +8967,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/gtag.js": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.10.tgz",
|
||||
"integrity": "sha512-98Hy7woUb3jMAMXkZQwfIOYNyfxmI0+U4m0PpCGdnd/FHk0tDpQFCqgXdNkdEoXsKkcGya/2Gew1cAJjKJspVw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/istanbul-lib-coverage": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/svelte": "^3.1.3",
|
||||
"@testing-library/user-event": "^14.2.0",
|
||||
"@types/gtag.js": "^0.0.10",
|
||||
"@typescript-eslint/eslint-plugin": "^5.27.1",
|
||||
"@typescript-eslint/parser": "^5.27.1",
|
||||
"eslint": "^8.17.0",
|
||||
|
||||
Vendored
+4
@@ -1 +1,5 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
/// <reference types="@types/gtag.js" />
|
||||
interface Window {
|
||||
GOOGLE_ANALYTICS: string | false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { Action } from 'svelte/action';
|
||||
|
||||
export type AnalyticsActionParam = {
|
||||
name: string;
|
||||
action: string;
|
||||
parameters?: Record<string, string>;
|
||||
event?: keyof HTMLElementEventMap;
|
||||
};
|
||||
|
||||
export const event: Action<HTMLElement, AnalyticsActionParam> = (node, param) => {
|
||||
if (!isTrackingAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.addEventListener(param.event ?? 'click', () =>
|
||||
gtag('event', param.name, {
|
||||
...param.parameters,
|
||||
action: param.action
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const isTrackingAllowed = () => {
|
||||
if (!('gtag' in window)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window.navigator?.doNotTrack) {
|
||||
if (navigator.doNotTrack === '1' || navigator.doNotTrack === 'yes') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
|
||||
import { page } from '$app/stores';
|
||||
|
||||
$: project = $page.params.project;
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
import { browser } from '$app/env';
|
||||
import { app } from '$lib/stores/app';
|
||||
|
||||
if (browser) {
|
||||
window.GOOGLE_ANALYTICS = import.meta.env.VITE_GOOGLE_ANALYTICS?.toString() ?? false;
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
if (!$user) {
|
||||
@@ -42,6 +46,22 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#if browser && window.GOOGLE_ANALYTICS}
|
||||
<script
|
||||
async
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${window.GOOGLE_ANALYTICS}`}></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
gtag('config', window.GOOGLE_ANALYTICS);
|
||||
</script>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<Notifications />
|
||||
|
||||
<slot />
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { project } from '../store';
|
||||
import { authMethods } from '$lib/stores/auth-methods';
|
||||
import { OAuthProviders } from '$lib/stores/oauth-providers';
|
||||
import { event } from '$lib/actions/analytics';
|
||||
import type { Provider } from '$lib/stores/oauth-providers';
|
||||
|
||||
$: projectId = $project.$id;
|
||||
@@ -64,6 +65,14 @@
|
||||
selectedProvider = provider;
|
||||
showModal = true;
|
||||
}}
|
||||
use:event={{
|
||||
name: 'console_users',
|
||||
action: 'click_update',
|
||||
event: 'click',
|
||||
parameters: {
|
||||
provider: provider.name
|
||||
}
|
||||
}}
|
||||
class="card u-flex u-flex-vertical u-cross-center">
|
||||
<div class="image-item">
|
||||
<img
|
||||
@@ -74,8 +83,9 @@
|
||||
</div>
|
||||
<p class="u-margin-block-start-8">{provider.name}</p>
|
||||
<div class="u-margin-block-start-24">
|
||||
<Pill success={provider.active}
|
||||
>{provider.active ? 'Enabled' : 'Disabled'}</Pill>
|
||||
<Pill success={provider.active}>
|
||||
{provider.active ? 'Enabled' : 'Disabled'}
|
||||
</Pill>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
TableRowLink
|
||||
} from '$lib/elements/table';
|
||||
import Create from './_createUser.svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { goto } from '$app/navigation';
|
||||
import { event } from '$lib/actions/analytics';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { usersList } from './store';
|
||||
import { onMount } from 'svelte';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
|
||||
let showCreate = false;
|
||||
let search = '';
|
||||
@@ -52,9 +53,18 @@
|
||||
|
||||
<Container>
|
||||
<Search bind:search placeholder="Search Name, Email, or ID">
|
||||
<Button on:click={() => (showCreate = true)}>
|
||||
<span class="icon-plus" aria-hidden="true" /> <span class="text">Create User</span>
|
||||
</Button>
|
||||
<span
|
||||
use:event={{
|
||||
name: 'console_users',
|
||||
action: 'click_create',
|
||||
parameters: {
|
||||
type: 'user'
|
||||
}
|
||||
}}>
|
||||
<Button on:click={() => (showCreate = true)}>
|
||||
<span class="icon-plus" aria-hidden="true" /> <span class="text">Create User</span>
|
||||
</Button>
|
||||
</span>
|
||||
</Search>
|
||||
{#if $usersList?.response?.total}
|
||||
<Table>
|
||||
@@ -112,16 +122,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</Empty>
|
||||
<div
|
||||
class="u-flex u-margin-block-start-32
|
||||
u-main-space-between">
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {$usersList.response.total}</p>
|
||||
<Pagination {limit} bind:offset sum={$usersList.response.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty dashed centered>
|
||||
<div class="u-flex u-flex-vertical u-cross-center">
|
||||
<div class="common-section">
|
||||
<div
|
||||
class="common-section"
|
||||
use:event={{
|
||||
name: 'console_users',
|
||||
action: 'click_create',
|
||||
parameters: {
|
||||
type: 'user'
|
||||
}
|
||||
}}>
|
||||
<Button secondary round on:click={() => (showCreate = true)}>
|
||||
<i class="icon-plus" />
|
||||
</Button>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import { Empty, Pagination, Avatar, Search } from '$lib/components';
|
||||
import Create from './_createTeam.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { event } from '$lib/actions/analytics';
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
@@ -47,9 +48,18 @@
|
||||
|
||||
<Container>
|
||||
<Search bind:search placeholder="Search by Name">
|
||||
<Button on:click={() => (showCreate = true)}>
|
||||
<span class="icon-plus" aria-hidden="true" /> <span class="text">Create Team</span>
|
||||
</Button>
|
||||
<span
|
||||
use:event={{
|
||||
name: 'console_users',
|
||||
action: 'click_create',
|
||||
parameters: {
|
||||
type: 'team'
|
||||
}
|
||||
}}>
|
||||
<Button on:click={() => (showCreate = true)}>
|
||||
<span class="icon-plus" aria-hidden="true" /> <span class="text">Create Team</span>
|
||||
</Button>
|
||||
</span>
|
||||
</Search>
|
||||
{#if $teamsList?.response?.total}
|
||||
<Table>
|
||||
@@ -91,15 +101,21 @@
|
||||
<Button secondary on:click={() => (search = '')}>Clear Search</Button>
|
||||
</div>
|
||||
</Empty>
|
||||
<div
|
||||
class="u-flex u-margin-block-start-32
|
||||
u-main-space-between">
|
||||
<div class="u-flex u-margin-block-start-32 u-main-space-between">
|
||||
<p class="text">Total results: {$teamsList.response.total}</p>
|
||||
<Pagination {limit} bind:offset sum={$teamsList.response.total} />
|
||||
</div>
|
||||
{:else}
|
||||
<Empty dashed centered>
|
||||
<div class="common-section">
|
||||
<div
|
||||
class="common-section"
|
||||
use:event={{
|
||||
name: 'console_users',
|
||||
action: 'click_create',
|
||||
parameters: {
|
||||
type: 'team'
|
||||
}
|
||||
}}>
|
||||
<Button secondary round on:click={() => (showCreate = true)}>
|
||||
<i class="icon-plus" />
|
||||
</Button>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
let showError: false | 'name' | 'email' | 'password' = false;
|
||||
let errorMessage = 'Something went wrong';
|
||||
let errorType: 'error' | 'warning' | 'success' = 'error';
|
||||
let teamName: string = null;
|
||||
let teamName: string = $team.response.name;
|
||||
|
||||
function addError(location: typeof showError, message: string, type: typeof errorType) {
|
||||
showError = location;
|
||||
@@ -27,7 +27,6 @@
|
||||
try {
|
||||
await sdkForProject.teams.update($page.params.team, teamName);
|
||||
$team.response.name = teamName;
|
||||
teamName = null;
|
||||
addNotification({
|
||||
message: 'Name has been updated',
|
||||
type: 'success'
|
||||
@@ -68,7 +67,7 @@
|
||||
<InputText
|
||||
id="name"
|
||||
label="Name"
|
||||
placeholder={$team.response.name}
|
||||
placeholder="Enter team name"
|
||||
autocomplete={false}
|
||||
bind:value={teamName} />
|
||||
{#if showError === 'name'}
|
||||
@@ -79,7 +78,7 @@
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={!teamName}
|
||||
disabled={teamName === $team.response.name}
|
||||
on:click={() => {
|
||||
updateName();
|
||||
}}>Update</Button>
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
let showError: false | 'name' | 'email' | 'phone' | 'password' = false;
|
||||
let errorMessage = 'Something went wrong';
|
||||
let errorType: 'error' | 'warning' | 'success' = 'error';
|
||||
let userName: string = null,
|
||||
userEmail: string = null,
|
||||
userPhone: string = null,
|
||||
let userName: string = $user.response.name,
|
||||
userEmail: string = $user.response.email,
|
||||
userPhone: string = $user.response.phone,
|
||||
newPassword: string = null,
|
||||
newPref = false,
|
||||
newKey: string = null,
|
||||
@@ -113,7 +113,6 @@
|
||||
try {
|
||||
await sdkForProject.users.updateName($user.response.$id, userName);
|
||||
$user.response.name = userName;
|
||||
userName = null;
|
||||
showError = false;
|
||||
addNotification({
|
||||
message: 'Name has been updated',
|
||||
@@ -127,7 +126,6 @@
|
||||
try {
|
||||
await sdkForProject.users.updateEmail($user.response.$id, userEmail);
|
||||
$user.response.email = userEmail;
|
||||
userEmail = null;
|
||||
showError = false;
|
||||
addNotification({
|
||||
message: 'Email has been updated',
|
||||
@@ -141,7 +139,6 @@
|
||||
try {
|
||||
await sdkForProject.users.updatePhone($user.response.$id, userPhone);
|
||||
$user.response.phone = userPhone;
|
||||
userPhone = null;
|
||||
showError = false;
|
||||
addNotification({
|
||||
message: 'Phone has been updated',
|
||||
@@ -284,7 +281,7 @@
|
||||
<InputText
|
||||
id="name"
|
||||
label="Name"
|
||||
placeholder={$user.response.name}
|
||||
placeholder="Enter name"
|
||||
autocomplete={false}
|
||||
bind:value={userName} />
|
||||
{#if showError === 'name'}
|
||||
@@ -295,7 +292,7 @@
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={!userName}
|
||||
disabled={userName === $user.response.name}
|
||||
on:click={() => {
|
||||
updateName();
|
||||
}}>Update</Button>
|
||||
@@ -308,7 +305,7 @@
|
||||
<InputEmail
|
||||
id="email"
|
||||
label="Email"
|
||||
placeholder={$user.response.email}
|
||||
placeholder="Enter email"
|
||||
autocomplete={false}
|
||||
bind:value={userEmail} />
|
||||
{#if showError === 'email'}
|
||||
@@ -319,7 +316,7 @@
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={!userEmail}
|
||||
disabled={userEmail === $user.response.email}
|
||||
on:click={() => {
|
||||
updateEmail();
|
||||
}}>Update</Button>
|
||||
@@ -332,7 +329,7 @@
|
||||
<InputPhone
|
||||
id="phone"
|
||||
label="Phone"
|
||||
placeholder={$user.response.phone || '+4915739638796'}
|
||||
placeholder="Enter phone number"
|
||||
autocomplete={false}
|
||||
bind:value={userPhone} />
|
||||
{#if showError === 'phone'}
|
||||
@@ -343,7 +340,7 @@
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={!userPhone}
|
||||
disabled={userPhone === $user.response.phone}
|
||||
on:click={() => {
|
||||
updatePhone();
|
||||
}}>Update</Button>
|
||||
|
||||
Reference in New Issue
Block a user