Skip to content

Commit

Permalink
New error/success notification (#644)
Browse files Browse the repository at this point in the history
* add notification stack

* finish to bind with vuex on stack

* set variants based on alert-type

* update styling

* binding to tx link

* amend detail styling

* update icon & styling

* change to kebap-case

* remain kebap-case

* clean up

* update styling on feedback

* update css

* change success message more detail

* clean up

* clean up

* updates based on feedback

* add copied state as alertType

* hide overflow-x

* add types on computed values
  • Loading branch information
sirius651 authored Jan 15, 2023
1 parent 1322230 commit 6cab4f9
Show file tree
Hide file tree
Showing 15 changed files with 409 additions and 31 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"dependencies": {
"@astar-network/astar-sdk-core": "^0.1.8",
"@astar-network/astar-ui": "^0.0.69",
"@astar-network/astar-ui": "^0.0.71",
"@ethersproject/bignumber": "^5.5.0",
"@polkadot/api": "^9.10.2",
"@polkadot/api-contract": "^9.10.2",
Expand Down
3 changes: 3 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
:alert-type="showAlert.alertType"
/>
</transition>
<notification-stack />

<cookie-policy />
</div>
Expand All @@ -41,6 +42,7 @@ import { useStore } from 'src/store';
import ModalLoading from 'components/common/ModalLoading.vue';
import AlertBox from 'components/common/AlertBox.vue';
import CookiePolicy from 'components/common/CookiePolicy.vue';
import NotificationStack from './components/common/Notification/NotificationStack.vue';
import 'animate.css';
import {
BusyMessage,
Expand All @@ -61,6 +63,7 @@ export default defineComponent({
ModalLoading,
AlertBox,
CookiePolicy,
NotificationStack,
},
setup() {
useAppRouter();
Expand Down
2 changes: 1 addition & 1 deletion src/components/assets/Account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default defineComponent({
copy(currentAccount.value);
store.dispatch('general/showAlertMsg', {
msg: t('toast.copyAddressSuccessfully'),
alertType: 'success',
alertType: 'copied',
});
};
Expand Down
1 change: 1 addition & 0 deletions src/components/assets/transfer/LocalTransfer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export default defineComponent({
await transferAsset({
transferAmt: Number(transferAmt.value),
toAddress: toAddress.value,
symbol: props.token.metadata.symbol,
});
};
Expand Down
248 changes: 248 additions & 0 deletions src/components/common/Notification/NotificationBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
<template>
<div
:class="[
'noti',
alertType,
'animate__animated',
show && 'show',
show ? 'animate__fadeInRight' : 'animate__fadeOutRight',
]"
>
<div class="noti-content" @mouseover="showCloseBtn = true">
<div class="row--close">
<div class="column--title">
<span v-if="isSuccessType || isCopiedType" class="icon--check">
<astar-icon-circle-check size="20" />
</span>
<span v-else class="icon--check">
<astar-icon-warning size="20" />
</span>
{{ alertTypeTitle }}
</div>
<div v-if="showCloseBtn" class="column--close" @click="close">
<astar-icon-close />
</div>
</div>
<div v-if="!isCopiedType">
<div class="message">{{ alertMsg }}</div>
<astar-button v-if="isSuccessType && txHash" class="btn--check" @click="goToSubscan">{{
$t('toast.checkYourTransactions')
}}</astar-button>
</div>
</div>
</div>
</template>

<script lang="ts">
import { AlertType } from 'src/store/general/state';
import { useNetworkInfo } from 'src/hooks';
import { endpointKey } from 'src/config/chainEndpoints';
import { useI18n } from 'vue-i18n';
import { defineComponent, toRefs, PropType, computed, ref } from 'vue';
export default defineComponent({
name: 'NotificationBar',
props: {
show: {
type: Boolean,
default: false,
},
alertType: {
type: String as PropType<AlertType>,
required: true,
},
alertMsg: {
type: String,
required: true,
},
txHash: {
type: String,
default: null,
},
},
emits: ['close'],
setup(props, { emit }) {
const close = () => {
emit('close');
};
const { t } = useI18n();
const alertTypeTitle = computed<string>(() => {
if (props.alertType === AlertType.Success) {
return t('toast.success');
} else if (props.alertType === AlertType.Warning) {
return t('toast.note');
} else if (props.alertType === AlertType.Error) {
return t('toast.error');
} else {
return t('toast.copied');
}
});
const showCloseBtn = ref<boolean>(false);
const isSuccessType = computed<boolean>(() => props.alertType === AlertType.Success);
const isCopiedType = computed<boolean>(() => props.alertType === AlertType.Copied);
const { currentNetworkIdx } = useNetworkInfo();
const isShiden = computed<boolean>(() => currentNetworkIdx.value === endpointKey.SHIDEN);
const goToSubscan = () => {
if (!props.txHash) return;
let rootName = 'astar';
if (isShiden.value) {
rootName = 'shiden';
}
const link = `https://${rootName}.subscan.io/extrinsic/${props.txHash}`;
window.open(link, '_blank');
};
return {
...toRefs(props),
alertTypeTitle,
isSuccessType,
isCopiedType,
showCloseBtn,
goToSubscan,
close,
};
},
});
</script>

<style lang="scss" scoped>
@import 'src/css/quasar.variables.scss';
.noti {
display: none;
border: 1px solid $astar-blue;
border-radius: 6px;
color: $gray-5-selected;
width: 100%;
background: #e5f2ff;
mix-blend-mode: normal;
box-shadow: 4px 4px 4px 0px rgb(0 0 0 / 12%);
&::before {
content: '';
position: absolute;
left: 0;
background: $astar-blue;
height: 100%;
width: 8px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
.icon--check {
color: $astar-blue;
margin-left: 8px;
margin-right: 8px;
}
}
.noti-content {
padding: 16px;
}
.warning {
background: #fdf8e6;
border-color: $warning-yellow;
&::before {
background: $warning-yellow;
}
.icon--check {
color: $warning-yellow;
}
}
.error {
background: #ffeee8;
border-color: $warning-red;
&::before {
background: $warning-red;
}
.icon--check {
color: $warning-red;
}
}
.noti.show {
display: block;
}
.row--close {
display: flex;
color: #b1b7c1;
justify-content: space-between;
font-weight: 330;
}
.column--title {
display: flex;
justify-content: center;
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 19px;
color: $gray-5-selected;
}
.column--close {
width: 16px;
height: 16px;
border: 1px solid $gray-3;
border-radius: 30px;
color: $gray-3;
font-size: 30px;
font-weight: 10;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.message {
width: 310px;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: $gray-5-selected;
text-align: left;
padding-left: 12px;
padding-right: 12px;
margin-top: 8px;
word-break: break-all;
}
.btn--check {
width: 90%;
height: 33px;
margin-top: 10px;
background: transparent;
border: 1px solid $astar-blue;
color: $astar-blue;
}
.body--dark {
.noti {
background: #001a33;
box-shadow: 4px 4px 4px 0px rgb(0 0 0 / 25%);
}
.warning {
background: #302502;
}
.error {
background: #331106;
}
.column--title {
color: $gray-1;
}
.column--close {
color: $gray-4;
border-color: $gray-4;
}
.message {
color: $gray-1;
}
}
</style>
80 changes: 80 additions & 0 deletions src/components/common/Notification/NotificationStack.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<template>
<div>
<div class="stack--wrapper">
<div v-for="(t, index) in alertStack" :key="index">
<notification-bar
:alert-type="t.alertType"
:alert-msg="t.alertMsg"
:tx-hash="t.txHash"
:show="true"
@close="() => closeNoti(index)"
/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useNetworkInfo } from 'src/hooks';
import { endpointKey } from 'src/config/chainEndpoints';
import { AlertBox, AlertType } from 'src/store/general/state';
import { useStore } from 'src/store';
import NotificationBar from './NotificationBar.vue';
export default defineComponent({
components: { NotificationBar },
setup() {
const store = useStore();
const closeNoti = (index: number) => {
store.dispatch(
'general/removeAlertMsg',
{
index: index,
},
{ root: true }
);
};
const alertStack = computed<AlertBox[]>(() => store.getters['general/alertStack']);
const { currentNetworkIdx } = useNetworkInfo();
const isShiden = computed<boolean>(() => currentNetworkIdx.value === endpointKey.SHIDEN);
const goToSubscan = (txHash: string) => {
if (!txHash) return;
let rootName = 'astar';
if (isShiden.value) {
rootName = 'shiden';
}
const link = `https://${rootName}.subscan.io/extrinsic/${txHash}`;
window.open(link, '_blank');
};
return { alertStack, AlertType, closeNoti, goToSubscan };
},
});
</script>
<style lang="scss" scoped>
@import 'src/css/quasar.variables.scss';
.stack--wrapper {
display: flex;
flex-direction: column;
position: fixed;
z-index: 120;
top: 104px;
left: 0;
right: 0;
margin: auto;
width: 340px;
max-height: calc(100vh - 110px);
text-align: center;
overflow-y: auto;
overflow-x: hidden;
gap: 10px;
@media (min-width: $md) {
top: 96px;
left: auto;
right: 40px;
}
}
</style>
2 changes: 1 addition & 1 deletion src/components/dapp-staking/dapp/ProjectDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export default defineComponent({
copy(address);
store.dispatch('general/showAlertMsg', {
msg: t('toast.copyAddressSuccessfully'),
alertType: 'success',
alertType: 'copied',
});
};
Expand Down
Loading

0 comments on commit 6cab4f9

Please sign in to comment.