Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(email management): add functionality for managing email subscriptions #3907

Merged
merged 68 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
175a5b7
feat: add subscribtion form to email report
wa0x6e Apr 15, 2023
62f887b
Merge branch 'develop' into email-report
samuveth Apr 19, 2023
7ea4146
Merge branch 'develop' into email-report
wa0x6e Apr 20, 2023
40acba0
feat: add the email notification form to profile page
wa0x6e Apr 20, 2023
8aac6c2
feat: show subscription result in modal
wa0x6e Apr 20, 2023
0cb9d75
fix(UI): move the whole subscribe logic into modal
wa0x6e Apr 28, 2023
be0ef51
refactor: move the subscription handler into a composable
wa0x6e May 6, 2023
7881d5c
feat: require wallet ownership proof
wa0x6e May 6, 2023
0a8aa9d
fix: fix typo
wa0x6e May 7, 2023
0a4df1f
Update src/locales/default.json
wa0x6e May 7, 2023
14314e0
Merge branch 'email-report' of https://github.com/snapshot-labs/snaps…
wa0x6e May 7, 2023
bd289e2
fix: remove redundant submit button
wa0x6e May 7, 2023
8cdbc19
refactor: extract sign function into helper and UI improvement
wa0x6e May 7, 2023
603530b
fix: fix form input not passing the value
wa0x6e May 7, 2023
9a8cc2e
refactor: remove `timestamp` from data type
wa0x6e May 7, 2023
e3a73c9
Update src/components/ModalEmailSubscription.vue
wa0x6e May 7, 2023
c68b773
Merge branch 'develop' into email-report
samuveth May 7, 2023
f2ad74b
fix(email modal): remove unnecessary event
Todmy May 9, 2023
c3d1c6c
fix(email subscription): add translation to button caption
Todmy May 9, 2023
091a547
fix(helpers:sign): fix signer defining and remove check ignore comment
Todmy May 9, 2023
8102d5b
fix(eslint): update .eslintrc-auto-import.json file
Todmy May 9, 2023
13b23ff
fix(text): fix default text for emailSubscription.inputCaption
Todmy May 9, 2023
a19c479
fix(text): change texting for success message of email subscription
Todmy May 9, 2023
4258b78
feat(email subscription): add subscribe form to the modal after voting
Todmy May 9, 2023
6bf092c
fix(email subscription): Changed the view of email subscription succe…
Todmy May 10, 2023
2ef9cd0
fix(email subscription): change text for success subscription modal
Todmy May 10, 2023
325cfb2
Merge branch 'develop' into email-report
samuveth May 15, 2023
d607765
fix(texting): fix placeholder for email input
Todmy May 15, 2023
9ce4172
fix(texting): fix translation for email form
Todmy May 15, 2023
9fd475d
Merge branch 'develop' into email-report
samuveth May 15, 2023
bea327b
Merge branch 'develop' of github.com:snapshot-labs/snapshot into emai…
Todmy May 15, 2023
52ebff9
fix(UI): improve success message UI
wa0x6e May 16, 2023
e899a44
Merge branch 'develop' into email-report
samuveth May 17, 2023
fa2baee
feat(jsonrpc): add interfaces for JSON-RPC
Todmy May 17, 2023
2b821ba
refactor(sign): simplified interface for `sign` helper
Todmy May 18, 2023
b86427d
refactor(useEmailSubscription): flattify structure
Todmy May 18, 2023
dc2dbcf
feat(subscr.managm.): load current user subscriptions on page load
Todmy May 18, 2023
48d03b1
feat(subscriptions): Add new prop to `useEmailSubscription` composable
Todmy May 18, 2023
abf511e
feat(subscr.update): add method for updating subscriptions
Todmy May 18, 2023
5c43e75
refactor(subscriptions): minor changes to code
Todmy May 18, 2023
9fa182c
feat(subscr.managm.): add modal
Todmy May 18, 2023
c5bc446
feat(menu): udated menu to show proper modal
Todmy May 18, 2023
b1684ae
refactor(subscriptions): replace redundant prop to composable
Todmy May 18, 2023
8e70ab5
refactor(change naming): Change name for email management modal
Todmy May 18, 2023
842c48a
refactor(subscriptions): add HOC component for defining which modal t…
Todmy May 18, 2023
591306b
feat(signing): change method from regular sign to signing with alias
Todmy May 18, 2023
d064bb3
refactor(comment): remove old commented code
Todmy May 18, 2023
4d4211d
feat(translations): add translations
Todmy May 18, 2023
6b848ae
fix(scaffolds): remove redundat scaffolding code
Todmy May 18, 2023
ea8ff50
refactor(email managm.): remove redundat function wrapper
Todmy May 18, 2023
f4f970d
fix(CR): fix CR comments
Todmy May 20, 2023
229ccc6
fix(HOC): remove HOC component since it is redundant
Todmy May 24, 2023
749d7b8
fix(ui-lib): use tune checkbox
Todmy May 24, 2023
0fde087
fix(navbar): prevent rendering navbar account component until account…
Todmy May 26, 2023
b2ae3bc
refactor(useEmailSubscription): split composable on multiple for sepa…
Todmy May 26, 2023
1dc653b
fix(types): remove redundant interfaces
Todmy May 26, 2023
d9be37e
fix(eof): add empty line
Todmy May 26, 2023
b3d9a33
fix(useFetch): remove redundant arguments
Todmy May 26, 2023
c24c05e
Merge branch 'develop' into email-report
samuveth May 27, 2023
653b211
Merge branch 'develop' into email-report
samuveth May 29, 2023
2bd0225
Merge branch 'develop' into email-report
samuveth May 29, 2023
d0378b6
Merge branch 'email-report' of github.com:snapshot-labs/snapshot into…
Todmy May 29, 2023
a439376
Merge branch 'feat/email-notifications' of github.com:snapshot-labs/s…
Todmy May 29, 2023
b166aa1
fix(lint): fix lint errors
Todmy May 29, 2023
76423fe
fix(switch): change custom switch to ui lib `tune`
Todmy May 30, 2023
115ac03
chore(tune): update version
Todmy May 30, 2023
fa222bf
fix(CR): remove old styles
Todmy May 30, 2023
2b7261b
fix(CR): remove custom styles
Todmy May 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .eslintrc-auto-import.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
"useCssModule": true,
"useCssVars": true,
"useDelegate": true,
"useEmailSubscription": true,
"useEns": true,
"useExtendedSpaces": true,
"useFlashNotification": true,
Expand Down Expand Up @@ -114,6 +113,8 @@
"watchSyncEffect": true,
"watchTxStatus": true,
"toValue": true,
"useFlaggedMessageStatus": true
"useFlaggedMessageStatus": true,
"useEmailSubscription": true,
"useEmailFetchClient": true
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@snapshot-labs/lock": "^0.1.1015",
"@snapshot-labs/pineapple": "^0.1.0-beta.1",
"@snapshot-labs/snapshot.js": "^0.4.86",
"@snapshot-labs/tune": "^0.1.21",
"@snapshot-labs/tune": "0.1.24",
"@vue/apollo-composable": "4.0.0-beta.4",
"@vueuse/core": "^10.1.2",
"@vueuse/head": "^1.1.26",
Expand Down
24 changes: 18 additions & 6 deletions src/components/MenuAccount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ const { t } = useI18n();

const { domain } = useApp();
const { logout } = useWeb3();
const { isSubscribed, loadEmailSubscriptions } = useEmailSubscription();

onMounted(loadEmailSubscriptions);

const router = useRouter();
const modalEmailSubscriptionOpen = ref(false);
const showModalEmail = ref(false);

function handleAction(e) {
if (e === 'viewProfile')
Expand All @@ -26,7 +30,7 @@ function handleAction(e) {
name: 'delegate'
});
if (e === 'subscribeEmail') {
modalEmailSubscriptionOpen.value = true;
showModalEmail.value = true;
return true;
}
return logout();
Expand All @@ -53,7 +57,9 @@ function handleAction(e) {
extras: { icon: 'switch' }
},
{
text: t('emailSubscription.subscribe'),
text: isSubscribed
? t('emailSubscription.manage')
: t('emailSubscription.subscribe'),
action: 'subscribeEmail',
extras: { icon: 'mail' }
},
Expand Down Expand Up @@ -89,11 +95,17 @@ function handleAction(e) {
</template>
</BaseMenu>
</div>

<teleport to="#modal">
<ModalEmailSubscription
:open="modalEmailSubscriptionOpen"
:address="address"
@close="modalEmailSubscriptionOpen = false"
v-if="!isSubscribed"
:open="showModalEmail"
@close="showModalEmail = false"
/>
<ModalEmailManagement
v-else
:open="showModalEmail"
@close="showModalEmail = false"
/>
</teleport>
</template>
84 changes: 84 additions & 0 deletions src/components/ModalEmailManagement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<script setup lang="ts">
defineProps<{
open: boolean;
}>();

const emit = defineEmits(['close']);

const {
loading,
clientSubscriptions,
shouldRemoveEmail,
updateSubscriptions: update,
isSubscribed
} = useEmailSubscription();
const { t } = useI18n();

const canRemoveEmail = computed(() => {
const { newProposal, closedProposal, summary } = clientSubscriptions.value;
return !newProposal && !closedProposal && !summary;
});

const updateSubscriptions = (key, value) => {
clientSubscriptions.value = { ...clientSubscriptions.value, [key]: value };
};

const submit = async () => {
await update();
// TODO: canRemoveEmail check should be removed when `shouldRemoveEmail` will be implemented
if (shouldRemoveEmail.value && canRemoveEmail.value) {
isSubscribed.value = false;
emit('close');
}
};
</script>

<template>
<BaseModal :open="open" max-height="510px" @close="$emit('close')">
<template #header>
<div class="flex flex-row items-center justify-center">
<h3>{{ $t('emailManagement.title') }}</h3>
</div>
</template>

<div class="mx-4 mb-4 mt-2 text-center">
<p class="text-sm text-skin-text opacity-60">
{{ t('emailManagement.subtitle') }}
</p>
</div>

<form class="mx-6 my-4 flex flex-col space-y-4" @submit.prevent="submit">
<TuneSwitch
:model-value="clientSubscriptions.newProposal"
:label="t('emailManagement.optionNewProposal')"
:sublabel="t('emailManagement.optionNewProposalDescription')"
@update:model-value="updateSubscriptions('newProposal', $event)"
/>

<TuneSwitch
:model-value="clientSubscriptions.closedProposal"
:label="t('emailManagement.optionClosedProposal')"
:sublabel="t('emailManagement.optionClosedProposalDescription')"
@update:model-value="updateSubscriptions('closedProposal', $event)"
/>

<TuneSwitch
:model-value="clientSubscriptions.summary"
:label="t('emailManagement.optionSummary')"
:sublabel="t('emailManagement.optionSummaryDescription')"
@update:model-value="updateSubscriptions('summary', $event)"
/>

<TuneCheckbox
v-if="canRemoveEmail"
v-model="shouldRemoveEmail"
:hint="t('emailManagement.removeEmail')"
class="pointer-events-none ml-3 text-sm opacity-60"
/>

<BaseButton class="mt-6 w-full" primary type="submit" :loading="loading">
{{ t('emailManagement.updatePreferences') }}
</BaseButton>
</form>
</BaseModal>
</template>
23 changes: 15 additions & 8 deletions src/components/ModalEmailSubscription.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
<script setup lang="ts">
const props = defineProps<{
defineProps<{
open: boolean;
address: string;
}>();

const emit = defineEmits(['close']);
const { web3Account } = useWeb3();
const email = ref('');
const { subscribe, reset, postSubscribeState, status, loading, Status } =
useEmailSubscription();
const {
subscribe,
reset,
postSubscribeState,
isSuccessful,
loading,
loadEmailSubscriptions
} = useEmailSubscription();

function close() {
reset();
email.value = '';
emit('close');
loadEmailSubscriptions();
}

function submit() {
subscribe(email.value, props.address);
subscribe(email.value, web3Account.value);
}
</script>

Expand All @@ -27,7 +34,7 @@ function submit() {
<h3>{{ $t('emailSubscription.title') }}</h3>
</div>
</template>
<div v-if="status === Status.success" class="m-4 text-center">
<div v-if="isSuccessful" class="m-4 text-center">
<i-ho-check-circle
class="mx-auto my-4 text-center text-[3em] text-green"
/>
Expand All @@ -46,7 +53,7 @@ function submit() {
<div v-else class="m-4">
{{ $t('emailSubscription.description') }}
</div>
<form v-if="status !== Status.success" class="m-4" @submit.prevent="submit">
<form v-if="!isSuccessful" class="m-4" @submit.prevent="submit">
<BaseInput
v-model="email"
placeholder="Your email"
Expand All @@ -73,7 +80,7 @@ function submit() {
</BaseButton>
</form>

<template v-if="status === Status.success" #footer>
<template v-if="isSuccessful" #footer>
<BaseButton class="w-full" primary @click="close">
{{ $t('close') }}
</BaseButton>
Expand Down
2 changes: 1 addition & 1 deletion src/components/NavbarAccount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ watchEffect(() => {
</script>

<template>
<template v-if="auth.isAuthenticated.value">
<template v-if="auth.isAuthenticated && web3Account">
<MenuAccount :address="web3Account" @switchWallet="modalAccountOpen = true">
<BaseButton
:loading="web3.authLoading || loadingProfiles || reloadingProfile"
Expand Down
77 changes: 77 additions & 0 deletions src/composables/useEmailFetchClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import sign, { DataType } from '@/helpers/sign';
import { createFetch } from '@vueuse/core';

const SubscribeSchema: DataType = {
Subscribe: [
{ name: 'address', type: 'address' },
{ name: 'email', type: 'string' }
]
};

const UpdateSubscriptionsSchema: DataType = {
Subscriptions: [
{ name: 'address', type: 'address' },
{ name: 'email', type: 'string' },
{ name: 'subscriptions', type: 'string[]' }
]
};

const useEmailFetch = createFetch({
baseUrl: import.meta.env.VITE_ENVELOP_URL,
options: {
headers: {
'Content-Type': 'application/json'
}
}
});

export function useEmailFetchClient() {
function signWithAlias(message, typesSchema) {
const { aliasWallet, actionWithAlias } = useAliasAction();

return actionWithAlias(() => {
const wallet = aliasWallet.value;
const address = aliasWallet.value.address;
return sign(wallet, address, message, typesSchema);
});
}

const fetchSubscriptions = body => {
return useEmailFetch('/subscriber').post(body).json();
};

const subscribeWithEmail = async unsignedParams => {
const signature = await signWithAlias(unsignedParams, SubscribeSchema);
const body = {
method: 'snapshot.subscribe',
params: {
...unsignedParams,
signature
}
};

return useEmailFetch('/').post(body).json();
};

const updateEmailSubscriptions = async unsignedParams => {
const signature = await signWithAlias(
unsignedParams,
UpdateSubscriptionsSchema
);
const body = {
method: 'snapshot.update',
params: {
...unsignedParams,
signature
}
};

return useEmailFetch('/').post(body).json();
};

return {
fetchSubscriptions,
subscribeWithEmail,
updateEmailSubscriptions
};
}
Loading