forked from coracle/flotilla
Update alert form to include push notifications
This commit is contained in:
+45
-7
@@ -14,6 +14,8 @@ import {
|
|||||||
AUTH_JOIN,
|
AUTH_JOIN,
|
||||||
ROOMS,
|
ROOMS,
|
||||||
COMMENT,
|
COMMENT,
|
||||||
|
ALERT_REQUEST_PUSH,
|
||||||
|
ALERT_REQUEST_EMAIL,
|
||||||
isSignedEvent,
|
isSignedEvent,
|
||||||
makeEvent,
|
makeEvent,
|
||||||
displayProfile,
|
displayProfile,
|
||||||
@@ -54,7 +56,6 @@ import {
|
|||||||
PROTECTED,
|
PROTECTED,
|
||||||
userMembership,
|
userMembership,
|
||||||
INDEXER_RELAYS,
|
INDEXER_RELAYS,
|
||||||
ALERT,
|
|
||||||
NOTIFIER_PUBKEY,
|
NOTIFIER_PUBKEY,
|
||||||
NOTIFIER_RELAY,
|
NOTIFIER_RELAY,
|
||||||
userRoomsByUrl,
|
userRoomsByUrl,
|
||||||
@@ -368,7 +369,7 @@ export const makeComment = ({event, content, tags = []}: CommentParams) =>
|
|||||||
export const publishComment = ({relays, ...params}: CommentParams & {relays: string[]}) =>
|
export const publishComment = ({relays, ...params}: CommentParams & {relays: string[]}) =>
|
||||||
publishThunk({event: makeComment(params), relays})
|
publishThunk({event: makeComment(params), relays})
|
||||||
|
|
||||||
export type AlertParams = {
|
export type EmailAlertParams = {
|
||||||
feed: Feed
|
feed: Feed
|
||||||
cron: string
|
cron: string
|
||||||
email: string
|
email: string
|
||||||
@@ -376,7 +377,13 @@ export type AlertParams = {
|
|||||||
claims: Record<string, string>
|
claims: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const makeAlert = async ({cron, email, feed, claims, description}: AlertParams) => {
|
export const makeEmailAlert = async ({
|
||||||
|
cron,
|
||||||
|
email,
|
||||||
|
feed,
|
||||||
|
claims,
|
||||||
|
description,
|
||||||
|
}: EmailAlertParams) => {
|
||||||
const tags = [
|
const tags = [
|
||||||
["feed", JSON.stringify(feed)],
|
["feed", JSON.stringify(feed)],
|
||||||
["cron", cron],
|
["cron", cron],
|
||||||
@@ -384,7 +391,6 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP
|
|||||||
["locale", LOCALE],
|
["locale", LOCALE],
|
||||||
["timezone", TIMEZONE],
|
["timezone", TIMEZONE],
|
||||||
["description", description],
|
["description", description],
|
||||||
["channel", "email"],
|
|
||||||
[
|
[
|
||||||
"handler",
|
"handler",
|
||||||
"31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1737058597050",
|
"31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1737058597050",
|
||||||
@@ -397,7 +403,7 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP
|
|||||||
tags.push(["claim", relay, claim])
|
tags.push(["claim", relay, claim])
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeEvent(ALERT, {
|
return makeEvent(ALERT_REQUEST_EMAIL, {
|
||||||
content: await signer.get().nip44.encrypt(NOTIFIER_PUBKEY, JSON.stringify(tags)),
|
content: await signer.get().nip44.encrypt(NOTIFIER_PUBKEY, JSON.stringify(tags)),
|
||||||
tags: [
|
tags: [
|
||||||
["d", randomId()],
|
["d", randomId()],
|
||||||
@@ -406,5 +412,37 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const publishAlert = async (params: AlertParams) =>
|
export const publishEmailAlert = async (params: EmailAlertParams) =>
|
||||||
publishThunk({event: await makeAlert(params), relays: [NOTIFIER_RELAY]})
|
publishThunk({event: await makeEmailAlert(params), relays: [NOTIFIER_RELAY]})
|
||||||
|
|
||||||
|
export type PushAlertParams = {
|
||||||
|
feed: Feed
|
||||||
|
description: string
|
||||||
|
claims: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makePushAlert = async ({feed, claims, description}: PushAlertParams) => {
|
||||||
|
const tags = [
|
||||||
|
["feed", JSON.stringify(feed)],
|
||||||
|
["locale", LOCALE],
|
||||||
|
["timezone", TIMEZONE],
|
||||||
|
["description", description],
|
||||||
|
["token", ""],
|
||||||
|
["platform", ""],
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const [relay, claim] of Object.entries(claims)) {
|
||||||
|
tags.push(["claim", relay, claim])
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeEvent(ALERT_REQUEST_PUSH, {
|
||||||
|
content: await signer.get().nip44.encrypt(NOTIFIER_PUBKEY, JSON.stringify(tags)),
|
||||||
|
tags: [
|
||||||
|
["d", randomId()],
|
||||||
|
["p", NOTIFIER_PUBKEY],
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const publishPushAlert = async (params: PushAlertParams) =>
|
||||||
|
publishThunk({event: await makePushAlert(params), relays: [NOTIFIER_RELAY]})
|
||||||
|
|||||||
@@ -13,22 +13,34 @@
|
|||||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||||
import {alerts, getMembershipUrls, getMembershipRoomsByUrl, userMembership} from "@app/state"
|
import {alerts, getMembershipUrls, getMembershipRoomsByUrl, userMembership} from "@app/state"
|
||||||
import {loadAlertStatuses, requestRelayClaims} from "@app/requests"
|
import {loadAlertStatuses, requestRelayClaims} from "@app/requests"
|
||||||
import {publishAlert} from "@app/commands"
|
import {publishEmailAlert, publishPushAlert} from "@app/commands"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
channel?: string
|
||||||
|
relay?: string
|
||||||
|
notifyChat?: boolean
|
||||||
|
notifyThreads?: boolean
|
||||||
|
notifyCalendar?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
relay = "",
|
||||||
|
channel = "email",
|
||||||
|
notifyChat = true,
|
||||||
|
notifyThreads = true,
|
||||||
|
notifyCalendar = true,
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
const timezoneOffset = parseInt(TIMEZONE.slice(3)) / 100
|
const timezoneOffset = parseInt(TIMEZONE.slice(3)) / 100
|
||||||
const minute = randomInt(0, 59)
|
const minute = randomInt(0, 59)
|
||||||
const hour = (17 - timezoneOffset) % 24
|
const hour = (17 - timezoneOffset) % 24
|
||||||
const WEEKLY = `0 ${minute} ${hour} * * 1`
|
const WEEKLY = `0 ${minute} ${hour} * * 1`
|
||||||
const DAILY = `0 ${minute} ${hour} * * *`
|
const DAILY = `0 ${minute} ${hour} * * *`
|
||||||
|
|
||||||
let loading = false
|
let loading = $state(false)
|
||||||
let cron = WEEKLY
|
let cron = $state(WEEKLY)
|
||||||
let email = $alerts.map(a => getTagValue("email", a.tags)).filter(identity)[0] || ""
|
let email = $state($alerts.map(a => getTagValue("email", a.tags)).filter(identity)[0] || "")
|
||||||
let relay = ""
|
|
||||||
let notifyThreads = true
|
|
||||||
let notifyCalendar = true
|
|
||||||
let notifyChat = false
|
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
@@ -84,7 +96,10 @@
|
|||||||
const cadence = cron?.endsWith("1") ? "Weekly" : "Daily"
|
const cadence = cron?.endsWith("1") ? "Weekly" : "Daily"
|
||||||
const description = `${cadence} alert for ${displayList(display)} on ${displayRelayUrl(relay)}, sent via email.`
|
const description = `${cadence} alert for ${displayList(display)} on ${displayRelayUrl(relay)}, sent via email.`
|
||||||
const feed = makeIntersectionFeed(feedFromFilters(filters), makeRelayFeed(relay))
|
const feed = makeIntersectionFeed(feedFromFilters(filters), makeRelayFeed(relay))
|
||||||
const thunk = await publishAlert({cron, email, feed, claims, description})
|
const thunk =
|
||||||
|
channel === "email"
|
||||||
|
? await publishEmailAlert({cron, email, feed, claims, description})
|
||||||
|
: await publishPushAlert({feed, claims, description})
|
||||||
|
|
||||||
await thunk.result
|
await thunk.result
|
||||||
await loadAlertStatuses($pubkey!)
|
await loadAlertStatuses($pubkey!)
|
||||||
@@ -105,25 +120,38 @@
|
|||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<FieldInline>
|
<FieldInline>
|
||||||
{#snippet label()}
|
{#snippet label()}
|
||||||
<p>Email Address*</p>
|
<p>Alert Type*</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet input()}
|
{#snippet input()}
|
||||||
<label class="input input-bordered flex w-full items-center gap-2">
|
<select bind:value={channel} class="select select-bordered">
|
||||||
<input placeholder="email@example.com" bind:value={email} />
|
<option value="push">Push Notification</option>
|
||||||
</label>
|
<option value="email">Email Digest</option>
|
||||||
{/snippet}
|
|
||||||
</FieldInline>
|
|
||||||
<FieldInline>
|
|
||||||
{#snippet label()}
|
|
||||||
<p>Frequency*</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet input()}
|
|
||||||
<select bind:value={cron} class="select select-bordered">
|
|
||||||
<option value={WEEKLY}>Weekly</option>
|
|
||||||
<option value={DAILY}>Daily</option>
|
|
||||||
</select>
|
</select>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</FieldInline>
|
</FieldInline>
|
||||||
|
{#if channel === "email"}
|
||||||
|
<FieldInline>
|
||||||
|
{#snippet label()}
|
||||||
|
<p>Email Address*</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet input()}
|
||||||
|
<label class="input input-bordered flex w-full items-center gap-2">
|
||||||
|
<input placeholder="email@example.com" bind:value={email} />
|
||||||
|
</label>
|
||||||
|
{/snippet}
|
||||||
|
</FieldInline>
|
||||||
|
<FieldInline>
|
||||||
|
{#snippet label()}
|
||||||
|
<p>Frequency*</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet input()}
|
||||||
|
<select bind:value={cron} class="select select-bordered">
|
||||||
|
<option value={WEEKLY}>Weekly</option>
|
||||||
|
<option value={DAILY}>Daily</option>
|
||||||
|
</select>
|
||||||
|
{/snippet}
|
||||||
|
</FieldInline>
|
||||||
|
{/if}
|
||||||
<FieldInline>
|
<FieldInline>
|
||||||
{#snippet label()}
|
{#snippet label()}
|
||||||
<p>Space*</p>
|
<p>Space*</p>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {displayRelayUrl} from "@welshman/util"
|
import {displayRelayUrl, getTagValue} from "@welshman/util"
|
||||||
import {deriveRelay} from "@welshman/app"
|
import {pubkey, deriveRelay} from "@welshman/app"
|
||||||
import {fly} from "@lib/transition"
|
import {fly} from "@lib/transition"
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
@@ -13,6 +13,8 @@
|
|||||||
import SpaceExit from "@app/components/SpaceExit.svelte"
|
import SpaceExit from "@app/components/SpaceExit.svelte"
|
||||||
import SpaceJoin from "@app/components/SpaceJoin.svelte"
|
import SpaceJoin from "@app/components/SpaceJoin.svelte"
|
||||||
import ProfileList from "@app/components/ProfileList.svelte"
|
import ProfileList from "@app/components/ProfileList.svelte"
|
||||||
|
import AlertAdd from "@app/components/AlertAdd.svelte"
|
||||||
|
import AlertDelete from "@app/components/AlertDelete.svelte"
|
||||||
import RoomCreate from "@app/components/RoomCreate.svelte"
|
import RoomCreate from "@app/components/RoomCreate.svelte"
|
||||||
import MenuSpaceRoomItem from "@app/components/MenuSpaceRoomItem.svelte"
|
import MenuSpaceRoomItem from "@app/components/MenuSpaceRoomItem.svelte"
|
||||||
import InfoMissingRooms from "@app/components/InfoMissingRooms.svelte"
|
import InfoMissingRooms from "@app/components/InfoMissingRooms.svelte"
|
||||||
@@ -23,7 +25,9 @@
|
|||||||
deriveUserRooms,
|
deriveUserRooms,
|
||||||
deriveOtherRooms,
|
deriveOtherRooms,
|
||||||
hasNip29,
|
hasNip29,
|
||||||
|
alerts,
|
||||||
} from "@app/state"
|
} from "@app/state"
|
||||||
|
import {loadAlerts} from "@app/requests"
|
||||||
import {notifications} from "@app/notifications"
|
import {notifications} from "@app/notifications"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
@@ -36,6 +40,7 @@
|
|||||||
const calendarPath = makeSpacePath(url, "calendar")
|
const calendarPath = makeSpacePath(url, "calendar")
|
||||||
const userRooms = deriveUserRooms(url)
|
const userRooms = deriveUserRooms(url)
|
||||||
const otherRooms = deriveOtherRooms(url)
|
const otherRooms = deriveOtherRooms(url)
|
||||||
|
const alert = $derived($alerts.find(a => getTagValue("feed", a.tags)?.includes(url)))
|
||||||
|
|
||||||
const openMenu = () => {
|
const openMenu = () => {
|
||||||
showMenu = true
|
showMenu = true
|
||||||
@@ -62,6 +67,10 @@
|
|||||||
|
|
||||||
const addRoom = () => pushModal(RoomCreate, {url}, {replaceState})
|
const addRoom = () => pushModal(RoomCreate, {url}, {replaceState})
|
||||||
|
|
||||||
|
const addAlert = () => pushModal(AlertAdd, {relay: url, channel: "push"})
|
||||||
|
|
||||||
|
const deleteAlert = () => pushModal(AlertDelete, {alert})
|
||||||
|
|
||||||
let showMenu = $state(false)
|
let showMenu = $state(false)
|
||||||
let replaceState = $state(false)
|
let replaceState = $state(false)
|
||||||
let element: Element | undefined = $state()
|
let element: Element | undefined = $state()
|
||||||
@@ -72,6 +81,7 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
replaceState = Boolean(element?.closest(".drawer"))
|
replaceState = Boolean(element?.closest(".drawer"))
|
||||||
|
loadAlerts($pubkey!)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -86,7 +96,7 @@
|
|||||||
<Popover hideOnClick onClose={toggleMenu}>
|
<Popover hideOnClick onClose={toggleMenu}>
|
||||||
<ul
|
<ul
|
||||||
transition:fly
|
transition:fly
|
||||||
class="menu absolute z-popover mt-2 w-full rounded-box bg-base-100 p-2 shadow-xl">
|
class="menu absolute z-popover mt-2 w-full gap-1 rounded-box bg-base-100 p-2 shadow-xl">
|
||||||
<li>
|
<li>
|
||||||
<Button onclick={showMembers}>
|
<Button onclick={showMembers}>
|
||||||
<Icon icon="user-rounded" />
|
<Icon icon="user-rounded" />
|
||||||
@@ -99,6 +109,21 @@
|
|||||||
Create Invite
|
Create Invite
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
|
{#if alert}
|
||||||
|
<li>
|
||||||
|
<Button onclick={deleteAlert}>
|
||||||
|
<Icon icon="bell" />
|
||||||
|
Disable alerts
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
{:else}
|
||||||
|
<li>
|
||||||
|
<Button onclick={addAlert}>
|
||||||
|
<Icon icon="bell" />
|
||||||
|
Enable alerts
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
{/if}
|
||||||
<li>
|
<li>
|
||||||
{#if $userRoomsByUrl.has(url)}
|
{#if $userRoomsByUrl.has(url)}
|
||||||
<Button onclick={leaveSpace} class="text-error">
|
<Button onclick={leaveSpace} class="text-error">
|
||||||
|
|||||||
+4
-3
@@ -25,6 +25,9 @@ import {
|
|||||||
EVENT_TIME,
|
EVENT_TIME,
|
||||||
AUTH_INVITE,
|
AUTH_INVITE,
|
||||||
COMMENT,
|
COMMENT,
|
||||||
|
ALERT_REQUEST_EMAIL,
|
||||||
|
ALERT_REQUEST_PUSH,
|
||||||
|
ALERT_STATUS,
|
||||||
matchFilters,
|
matchFilters,
|
||||||
getTagValues,
|
getTagValues,
|
||||||
getTagValue,
|
getTagValue,
|
||||||
@@ -53,8 +56,6 @@ import {
|
|||||||
import {createScroller} from "@lib/html"
|
import {createScroller} from "@lib/html"
|
||||||
import {daysBetween} from "@lib/util"
|
import {daysBetween} from "@lib/util"
|
||||||
import {
|
import {
|
||||||
ALERT,
|
|
||||||
ALERT_STATUS,
|
|
||||||
NOTIFIER_RELAY,
|
NOTIFIER_RELAY,
|
||||||
INDEXER_RELAYS,
|
INDEXER_RELAYS,
|
||||||
getDefaultPubkeys,
|
getDefaultPubkeys,
|
||||||
@@ -348,7 +349,7 @@ export const makeCalendarFeed = ({
|
|||||||
export const loadAlerts = (pubkey: string) =>
|
export const loadAlerts = (pubkey: string) =>
|
||||||
load({
|
load({
|
||||||
relays: [NOTIFIER_RELAY],
|
relays: [NOTIFIER_RELAY],
|
||||||
filters: [{kinds: [ALERT], authors: [pubkey]}],
|
filters: [{kinds: [ALERT_REQUEST_EMAIL, ALERT_REQUEST_PUSH], authors: [pubkey]}],
|
||||||
})
|
})
|
||||||
|
|
||||||
export const loadAlertStatuses = (pubkey: string) =>
|
export const loadAlertStatuses = (pubkey: string) =>
|
||||||
|
|||||||
+4
-5
@@ -41,6 +41,9 @@ import {
|
|||||||
ROOM_JOIN,
|
ROOM_JOIN,
|
||||||
ROOM_ADD_USER,
|
ROOM_ADD_USER,
|
||||||
ROOM_REMOVE_USER,
|
ROOM_REMOVE_USER,
|
||||||
|
ALERT_REQUEST_EMAIL,
|
||||||
|
ALERT_REQUEST_PUSH,
|
||||||
|
ALERT_STATUS,
|
||||||
getGroupTags,
|
getGroupTags,
|
||||||
getRelayTagValues,
|
getRelayTagValues,
|
||||||
getPubkeyTagValues,
|
getPubkeyTagValues,
|
||||||
@@ -84,10 +87,6 @@ export const ROOM = "h"
|
|||||||
|
|
||||||
export const PROTECTED = ["-"]
|
export const PROTECTED = ["-"]
|
||||||
|
|
||||||
export const ALERT = 32830
|
|
||||||
|
|
||||||
export const ALERT_STATUS = 32831
|
|
||||||
|
|
||||||
export const NOTIFIER_PUBKEY = import.meta.env.VITE_NOTIFIER_PUBKEY
|
export const NOTIFIER_PUBKEY = import.meta.env.VITE_NOTIFIER_PUBKEY
|
||||||
|
|
||||||
export const NOTIFIER_RELAY = import.meta.env.VITE_NOTIFIER_RELAY
|
export const NOTIFIER_RELAY = import.meta.env.VITE_NOTIFIER_RELAY
|
||||||
@@ -344,7 +343,7 @@ export type Alert = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const alerts = deriveEventsMapped<Alert>(repository, {
|
export const alerts = deriveEventsMapped<Alert>(repository, {
|
||||||
filters: [{kinds: [ALERT]}],
|
filters: [{kinds: [ALERT_REQUEST_EMAIL, ALERT_REQUEST_PUSH]}],
|
||||||
itemToEvent: item => item.event,
|
itemToEvent: item => item.event,
|
||||||
eventToItem: async event => {
|
eventToItem: async event => {
|
||||||
const tags = parseJson(await decrypt(signer.get(), NOTIFIER_PUBKEY, event.content))
|
const tags = parseJson(await decrypt(signer.get(), NOTIFIER_PUBKEY, event.content))
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M18.7491 9.70957V9.00497C18.7491 5.13623 15.7274 2 12 2C8.27256 2 5.25087 5.13623 5.25087 9.00497V9.70957C5.25087 10.5552 5.00972 11.3818 4.5578 12.0854L3.45036 13.8095C2.43882 15.3843 3.21105 17.5249 4.97036 18.0229C9.57274 19.3257 14.4273 19.3257 19.0296 18.0229C20.789 17.5249 21.5612 15.3843 20.5496 13.8095L19.4422 12.0854C18.9903 11.3818 18.7491 10.5552 18.7491 9.70957Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path d="M7.5 19C8.15503 20.7478 9.92246 22 12 22C14.0775 22 15.845 20.7478 16.5 19" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 674 B |
@@ -9,6 +9,7 @@
|
|||||||
import {switcher} from "@welshman/lib"
|
import {switcher} from "@welshman/lib"
|
||||||
import AddSquare from "@assets/icons/Add Square.svg?dataurl"
|
import AddSquare from "@assets/icons/Add Square.svg?dataurl"
|
||||||
import ArrowsALogout2 from "@assets/icons/Arrows ALogout 2.svg?dataurl"
|
import ArrowsALogout2 from "@assets/icons/Arrows ALogout 2.svg?dataurl"
|
||||||
|
import Bell from "@assets/icons/Bell.svg?dataurl"
|
||||||
import Bookmark from "@assets/icons/Bookmark.svg?dataurl"
|
import Bookmark from "@assets/icons/Bookmark.svg?dataurl"
|
||||||
import BillList from "@assets/icons/Bill List.svg?dataurl"
|
import BillList from "@assets/icons/Bill List.svg?dataurl"
|
||||||
import Code2 from "@assets/icons/Code 2.svg?dataurl"
|
import Code2 from "@assets/icons/Code 2.svg?dataurl"
|
||||||
@@ -108,6 +109,7 @@
|
|||||||
const data = switcher(icon, {
|
const data = switcher(icon, {
|
||||||
"add-square": AddSquare,
|
"add-square": AddSquare,
|
||||||
"arrows-a-logout-2": ArrowsALogout2,
|
"arrows-a-logout-2": ArrowsALogout2,
|
||||||
|
bell: Bell,
|
||||||
bookmark: Bookmark,
|
bookmark: Bookmark,
|
||||||
"bill-list": BillList,
|
"bill-list": BillList,
|
||||||
"code-2": Code2,
|
"code-2": Code2,
|
||||||
|
|||||||
Reference in New Issue
Block a user