mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-22 09:35:00 +02:00
Setting plugin (#328)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import setting from '@anticrm/setting'
|
||||
import type { Integration, IntegrationType } from '@anticrm/setting'
|
||||
import PluginCard from './PluginCard.svelte'
|
||||
|
||||
const typeQuery = createQuery()
|
||||
const integrationQuery = createQuery()
|
||||
|
||||
let integrations: Integration[] = []
|
||||
let integrationTypes: IntegrationType[] = []
|
||||
|
||||
typeQuery.query(setting.class.IntegrationType, {}, (res) => (integrationTypes = res))
|
||||
integrationQuery.query(setting.class.Integration, {}, (res) => (integrations = res))
|
||||
</script>
|
||||
|
||||
<div class="cards-container">
|
||||
{#each integrationTypes as integrationType (integrationType._id)}
|
||||
<PluginCard integration={integrations.find((p) => p.type === integrationType._id)} {integrationType} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.cards-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(20rem, auto));
|
||||
grid-auto-rows: minmax(12.5rem, auto);
|
||||
grid-gap: 1.5rem;
|
||||
padding: 3rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let length: number = 6
|
||||
export let value: string = ''
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let digits: string[] = []
|
||||
let areas: HTMLInputElement[] = []
|
||||
let selected: number = 0
|
||||
let filled: number
|
||||
|
||||
for (let i = 0; i < length; i++) digits[i] = ''
|
||||
|
||||
const onInput = (ev?: Event, n?: number): void => {
|
||||
selected = -1
|
||||
filled = 0
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (digits[i] && digits[i].length > 1) {
|
||||
if (i < length - 1) digits[i + 1] = digits[i].substring(1)
|
||||
digits[i] = digits[i][0]
|
||||
}
|
||||
if (digits[i]) filled++
|
||||
if (selected < 0 && selected < length && digits[i] === '') selected = i
|
||||
}
|
||||
digits = digits
|
||||
if (filled === length) {
|
||||
if ((ev as InputEvent).inputType === 'insertFromPaste' && n && n < length) selected = n
|
||||
if ((ev as InputEvent).inputType === 'insertText' && selected < 0 && (n || n === 0)) selected = n + 1
|
||||
if (selected === length) selected--
|
||||
value = ''
|
||||
for (let i = 0; i < length; i++) value += digits[i]
|
||||
dispatch('filled', value)
|
||||
}
|
||||
if (selected !== -1 && selected < length) {
|
||||
areas[selected].focus()
|
||||
areas[selected].select()
|
||||
}
|
||||
}
|
||||
|
||||
const selectInput = (n: number): void => {
|
||||
if (areas[n]) {
|
||||
areas[n].focus()
|
||||
areas[n].select()
|
||||
}
|
||||
}
|
||||
|
||||
const keyPressed = (ev: Event, n: number): void => {
|
||||
if ((ev as KeyboardEvent).key === 'Backspace' && n > 0 && digits[n] === '') {
|
||||
digits[n - 1] = ''
|
||||
digits = digits
|
||||
onInput(undefined, n - 1)
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (areas[0]) onInput()
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="flex-between">
|
||||
{#each digits as digit, i}
|
||||
<input
|
||||
class="fs-title digit"
|
||||
type="text"
|
||||
bind:this={areas[i]}
|
||||
bind:value={digit}
|
||||
on:input={(ev) => {
|
||||
onInput(ev, i)
|
||||
}}
|
||||
on:keydown={async (ev) => keyPressed(ev, i)}
|
||||
on:click={async () => selectInput(i)}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.digit {
|
||||
width: 2.5rem;
|
||||
height: 3rem;
|
||||
text-align: center;
|
||||
background-color: var(--theme-card-bg-dark);
|
||||
border: 1px solid transparent;
|
||||
border-style: none;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid var(--primary-button-focused-border);
|
||||
box-shadow: 0 0 0 3px var(--primary-button-outline);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Button, Component, Label, Link } from '@anticrm/ui'
|
||||
import { getMetadata } from '@anticrm/platform'
|
||||
import { showPopup } from '@anticrm/ui'
|
||||
import type { Integration, IntegrationType } from '@anticrm/setting'
|
||||
import setting from '@anticrm/setting'
|
||||
import { getClient } from '@anticrm/presentation'
|
||||
import type { Ref, Space } from '@anticrm/core'
|
||||
import login from '@anticrm/login'
|
||||
|
||||
export let integrationType: IntegrationType
|
||||
export let integration: Integration | undefined
|
||||
const accountId = getMetadata(login.metadata.LoginEmail)
|
||||
const client = getClient()
|
||||
|
||||
async function close(res: any): Promise<void> {
|
||||
if (res.value) {
|
||||
await client.createDoc(setting.class.Integration, accountId as Ref<Space>, {
|
||||
type: integrationType._id,
|
||||
value: res.value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnect(): Promise<void> {
|
||||
if (integration !== undefined) {
|
||||
await client.removeDoc(setting.class.Integration, accountId as Ref<Space>, integration._id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex-col plugin-container">
|
||||
<div class="flex-row-center header">
|
||||
<div class="icon mr-4"><Component is={integrationType.icon} /></div>
|
||||
<div class="flex-grow flex-col">
|
||||
<div class="fs-title max-label overflow-label"><Label label={integrationType.label} /></div>
|
||||
<div class="small-text content-dark-color max-label overflow-label">
|
||||
<Label label={integrationType.description} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp</div>
|
||||
<div class="footer">
|
||||
{#if integration}
|
||||
<Button label={'Disconnect'} on:click={disconnect} />
|
||||
{:else}
|
||||
<Button
|
||||
label={'Add'}
|
||||
primary
|
||||
on:click={(e) => {
|
||||
showPopup(integrationType.createComponent, {}, e.target, close)
|
||||
}}
|
||||
/>
|
||||
<Link label={'Learn more'} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.plugin-container {
|
||||
background-color: var(--theme-button-bg-enabled);
|
||||
border: 1px solid var(--theme-bg-accent-color);
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
.header {
|
||||
margin: 1.5rem 1.5rem 1rem;
|
||||
}
|
||||
.max-label {
|
||||
max-width: calc(100% - 6.25rem);
|
||||
}
|
||||
.icon {
|
||||
flex-shrink: 0;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
}
|
||||
.content {
|
||||
margin: 0 1.5rem 0.25rem;
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
.footer {
|
||||
flex-shrink: 0;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
direction: rtl;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
column-gap: 1rem;
|
||||
padding: 1.5rem 1.75rem 1.25rem;
|
||||
height: 5.25rem;
|
||||
mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 1.25rem, rgba(0, 0, 0, 1) 2.5rem);
|
||||
overflow: hidden;
|
||||
border-radius: 0 0 1.25rem 1.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 36 36"
|
||||
style="enable-background:new 0 0 36 36;"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path
|
||||
fill={'#FFFFFF'}
|
||||
d="M0,12.8c0-4.5,0-6.7,0.9-8.4c0.8-1.5,2-2.7,3.5-3.5C6.1,0,8.3,0,12.8,0h10.4c4.5,0,6.7,0,8.4,0.9 c1.5,0.8,2.7,2,3.5,3.5c0.9,1.7,0.9,4,0.9,8.4v10.4c0,4.5,0,6.7-0.9,8.4c-0.8,1.5-2,2.7-3.5,3.5c-1.7,0.9-4,0.9-8.4,0.9H12.8 c-4.5,0-6.7,0-8.4-0.9c-1.5-0.8-2.7-2-3.5-3.5C0,29.9,0,27.7,0,23.2V12.8z"
|
||||
/>
|
||||
<path fill={'#EA4335'} d="M25.8,8.4l-7.7,6l-7.9-6v0l0,0v8.4l7.8,6.1l7.8-5.9V8.4z" />
|
||||
<path fill={'#FBBC05'} d="M27.8,6.9l-2,1.5V17l6.4-4.9V9.2C32.1,9.2,31.4,5,27.8,6.9z" />
|
||||
<path fill={'#34A853'} d="M25.8,17v11.2h4.9c0,0,1.4-0.1,1.5-1.7V12.2L25.8,17z" />
|
||||
<path fill={'#C5221F'} d="M10.2,28.3V16.8l0,0L10.2,28.3z" />
|
||||
<path fill={'#C5221F'} d="M10.2,8.4l-2-1.5C4.6,5,3.9,9.2,3.9,9.2v2.9l6.4,4.6V8.4z" />
|
||||
<path fill={'#C5221F'} d="M10.2,8.4v8.4l0,0L10.2,8.4L10.2,8.4z" />
|
||||
<path fill={'#4285F4'} d="M3.9,12.2v14.4c0.1,1.6,1.5,1.7,1.5,1.7h4.9l0-11.5L3.9,12.2z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
// Copyright © 2021 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 36 36"
|
||||
style="enable-background:new 0 0 36 36;"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<linearGradient
|
||||
id="SVGID_TELEGRAM_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="18"
|
||||
y1="-36"
|
||||
x2="18"
|
||||
y2="-72"
|
||||
gradientTransform="matrix(1 0 0 -1 0 -36)"
|
||||
>
|
||||
<stop offset="0" style="stop-color:#37BBFE" />
|
||||
<stop offset="1" style="stop-color:#007DBB" />
|
||||
</linearGradient>
|
||||
<path
|
||||
fill={'url(#SVGID_TELEGRAM_)'}
|
||||
d="M0,12.8c0-4.5,0-6.7,0.9-8.4c0.8-1.5,2-2.7,3.5-3.5C6.1,0,8.3,0,12.8,0h10.4c4.5,0,6.7,0,8.4,0.9 c1.5,0.8,2.7,2,3.5,3.5c0.9,1.7,0.9,4,0.9,8.4v10.4c0,4.5,0,6.7-0.9,8.4c-0.8,1.5-2,2.7-3.5,3.5c-1.7,0.9-4,0.9-8.4,0.9H12.8 c-4.5,0-6.7,0-8.4-0.9c-1.5-0.8-2.7-2-3.5-3.5C0,29.9,0,27.7,0,23.2V12.8z"
|
||||
/>
|
||||
<path
|
||||
fill={'#FFFFFF'}
|
||||
d="M27,10.6c0.2-1-0.8-1.9-1.7-1.4L7.5,17.2c-0.6,0.3-0.6,1.3,0.1,1.5l3.7,1.2c0.7,0.2,1.5,0.1,2.1-0.3l8.3-5.9 c0.2-0.2,0.5,0.2,0.3,0.4l-6,6.3c-0.6,0.6-0.5,1.7,0.2,2.1l6.7,4.3c0.7,0.5,1.7,0,1.9-0.9L27,10.6z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,83 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { IconClose, Label } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-bg" />
|
||||
<div class="flex-between header">
|
||||
<div class="overflow-label fs-title"><Label label={'Connect Email account'} /></div>
|
||||
<div
|
||||
class="tool"
|
||||
on:click={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
>
|
||||
<IconClose size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">Not implemented yet</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 20rem;
|
||||
min-width: 20rem;
|
||||
max-width: 20rem;
|
||||
border-radius: 1.25rem;
|
||||
|
||||
.header {
|
||||
flex-shrink: 0;
|
||||
margin: 1.75rem 1.75rem 1.25rem;
|
||||
|
||||
.tool {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
&:active {
|
||||
color: var(--theme-content-accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
height: fit-content;
|
||||
margin: 0 1.75rem 0.5rem;
|
||||
}
|
||||
|
||||
.card-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--theme-card-bg);
|
||||
border-radius: 1.25rem;
|
||||
backdrop-filter: blur(15px);
|
||||
box-shadow: var(--theme-card-shadow);
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,183 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getMetadata, serialize } from '@anticrm/platform'
|
||||
import { Button, EditBox, IconClose, Label } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import login from '@anticrm/login'
|
||||
import PinPad from '../PinPad.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let requested = false
|
||||
let secondFactor = false
|
||||
let phone: string = ''
|
||||
let code: string = ''
|
||||
let password: string = ''
|
||||
const url = getMetadata(login.metadata.TelegramUrl)
|
||||
|
||||
async function requestCode(): Promise<void> {
|
||||
const res = await sendRequest('/auth', { phone: phone })
|
||||
if (res.next === 'code') {
|
||||
requested = true
|
||||
}
|
||||
}
|
||||
|
||||
async function sendPassword(): Promise<void> {
|
||||
const res = await sendRequest('/auth/pass', { pass: password })
|
||||
if (res.next === 'end') {
|
||||
dispatch('close', { value: phone })
|
||||
}
|
||||
}
|
||||
|
||||
async function sendCode(): Promise<void> {
|
||||
const res = await sendRequest('/auth/code', { code: code })
|
||||
if (res.next === 'pass') {
|
||||
secondFactor = true
|
||||
} else if (res.next === 'end') {
|
||||
dispatch('close', { value: phone })
|
||||
}
|
||||
}
|
||||
|
||||
async function sendRequest(path: string, data: any): Promise<any> {
|
||||
const response = await fetch(url + path, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + getMetadata(login.metadata.LoginToken),
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: serialize(data)
|
||||
})
|
||||
const res = await response.json()
|
||||
if (res.err != null) {
|
||||
throw new Error(res.err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function back() {
|
||||
password = ''
|
||||
code = ''
|
||||
phone = ''
|
||||
requested = false
|
||||
secondFactor = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-bg" />
|
||||
<div class="flex-between header">
|
||||
<div class="overflow-label fs-title"><Label label={'Connect Telegram account'} /></div>
|
||||
<div
|
||||
class="tool"
|
||||
on:click={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
>
|
||||
<IconClose size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
{#if secondFactor}
|
||||
<p><Label label={'Enter your second factor password'} /></p>
|
||||
<EditBox label={'Password'} password placeholder={'password'} bind:value={password} />
|
||||
<div class="footer">
|
||||
<Button label={'Connect'} primary disabled={!password.length} on:click={sendPassword} />
|
||||
<a class="link" href={'#'} on:click={back}><Label label={'Back'} /></a>
|
||||
</div>
|
||||
{:else if requested}
|
||||
<p><Label label={'Enter the 5-digit code you received on your Telegram account.'} /></p>
|
||||
<PinPad length={5} bind:value={code} />
|
||||
<div class="footer">
|
||||
<Button label={'Connect'} primary disabled={!code.match(/^\d{5}$/)} on:click={sendCode} />
|
||||
<a class="link" href={'#'} on:click={back}><Label label={'Back'} /></a>
|
||||
</div>
|
||||
{:else}
|
||||
<p><Label label={'Enter your Telegram phone number to connect your account.'} /></p>
|
||||
<EditBox label={'Phone number'} placeholder={'+1 555 333 7777'} bind:value={phone} />
|
||||
<div class="footer">
|
||||
<Button label={'Next'} primary disabled={!phone.match(/^\+\d{9,15}$/)} on:click={requestCode} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 20rem;
|
||||
min-width: 20rem;
|
||||
max-width: 20rem;
|
||||
border-radius: 1.25rem;
|
||||
|
||||
.header {
|
||||
flex-shrink: 0;
|
||||
margin: 1.75rem 1.75rem 1.25rem;
|
||||
|
||||
.tool {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
&:active {
|
||||
color: var(--theme-content-accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
height: fit-content;
|
||||
margin: 0 1.75rem 0.5rem;
|
||||
p {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 1.75rem 1.75rem;
|
||||
|
||||
.link {
|
||||
color: var(--theme-content-dark-color);
|
||||
&:hover {
|
||||
color: var(--theme-caption-color);
|
||||
}
|
||||
&:active {
|
||||
color: var(--theme-content-accent-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--theme-card-bg);
|
||||
border-radius: 1.25rem;
|
||||
backdrop-filter: blur(15px);
|
||||
box-shadow: var(--theme-card-shadow);
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user