add notices

enable loading
This commit is contained in:
Danil Kovtonyuk 2020-11-03 17:35:46 +10:00
parent 9e0253f46b
commit 0fe0b3bbc5
15 changed files with 308 additions and 17 deletions

View File

@ -0,0 +1,3 @@
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.2886 0.146442C14.0933 -0.048806 13.7767 -0.0488222 13.5815 0.146442L7.21751 6.5104L0.853547 0.146442C0.658299 -0.048806 0.341705 -0.0488222 0.14644 0.146442C-0.0488189 0.341702 -0.0488081 0.658301 0.14644 0.853549L6.5104 7.21751L0.14644 13.5815C-0.0488189 13.7767 -0.0488081 14.0933 0.14644 14.2886C0.341689 14.4838 0.658288 14.4838 0.853547 14.2886L7.21751 7.92462L13.5815 14.2886C13.7767 14.4838 14.0933 14.4838 14.2886 14.2886C14.4838 14.0933 14.4838 13.7767 14.2886 13.5815L7.92461 7.21751L14.2886 0.853549C14.4838 0.658285 14.4838 0.341691 14.2886 0.146442Z" fill="#6B6B6B"/>
</svg>

After

Width:  |  Height:  |  Size: 697 B

View File

@ -0,0 +1,3 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.67711 0.322889C9.24659 -0.107627 8.5486 -0.107633 8.11807 0.322889L5 3.44096L1.88193 0.322889C1.45141 -0.107627 0.753411 -0.107633 0.322889 0.322889C-0.107621 0.753399 -0.107627 1.45141 0.322889 1.88193L3.44096 5L0.322889 8.11807C-0.107633 8.5486 -0.107627 9.24659 0.322889 9.67711C0.753405 10.1076 1.4514 10.1076 1.88193 9.67711L5 6.55904L8.11807 9.67711C8.54859 10.1076 9.24659 10.1076 9.67711 9.67711C10.1076 9.24659 10.1076 8.54859 9.67711 8.11807L6.55904 5L9.67711 1.88193C10.1076 1.4514 10.1076 0.753405 9.67711 0.322889Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 659 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="12">
<path fill-rule="evenodd" d="M9 12H1a1 1 0 0 1 0-2h3V6H1a1 1 0 0 1 0-2h4a1 1 0 0 1 1 1v5h3a1 1 0 0 1 0 2zM5 2H4a1 1 0 0 1 0-2h1a1 1 0 0 1 0 2z"/>
</svg>

After

Width:  |  Height:  |  Size: 221 B

View File

@ -0,0 +1,3 @@
<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.279335 2.85355C-0.0931092 3.21057 -0.0931144 3.78942 0.279335 4.14645L2.97686 6.73224C3.34931 7.08926 3.95317 7.08925 4.32562 6.73224L9.72066 1.56066C10.0931 1.20364 10.0931 0.624788 9.72066 0.267765C9.34822 -0.0892575 8.74435 -0.0892525 8.3719 0.267765L3.65124 4.79289L1.6281 2.85355C1.25565 2.49653 0.65178 2.49654 0.279335 2.85355Z" fill="#0E0E0E"/>
</svg>

After

Width:  |  Height:  |  Size: 466 B

View File

@ -0,0 +1,3 @@
<svg width="2" height="12" viewBox="0 0 2 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 0C0.447723 0 0 0.447716 0 1V7C0 7.55229 0.447723 8 1 8C1.55228 8 2 7.55229 2 7V1C2 0.447716 1.55228 0 1 0ZM1 12C1.55228 12 2 11.5523 2 11C2 10.4477 1.55228 10 1 10C0.447723 10 0 10.4477 0 11C0 11.5523 0.447723 12 1 12Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39.9 39.9"><path d="M40,19.4A17.3,17.3,0,0,0,22.8,2.8,17.1,17.1,0,0,0,8.6,10.4,11.3,11.3,0,0,1,19.3,0,17.1,17.1,0,0,0,2.8,17.1a16.8,16.8,0,0,0,7.7,14.2A11.3,11.3,0,0,1,0,20.6a17.1,17.1,0,0,0,31.3,9A11.4,11.4,0,0,1,20.6,39.9,17.1,17.1,0,0,0,37.1,22.8,17.3,17.3,0,0,0,29.5,8.6,11.8,11.8,0,0,1,40,19.4ZM20,27.2a7.4,7.4,0,0,1-5.2-2.1,7.1,7.1,0,0,1-2-5.1A7.2,7.2,0,1,1,20,27.2Z" fill="#94febf"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39.9 39.9"><path d="M40,19.4A17.3,17.3,0,0,0,22.8,2.8,17.1,17.1,0,0,0,8.6,10.4,11.3,11.3,0,0,1,19.3,0,17.1,17.1,0,0,0,2.8,17.1a16.8,16.8,0,0,0,7.7,14.2A11.3,11.3,0,0,1,0,20.6a17.1,17.1,0,0,0,31.3,9A11.4,11.4,0,0,1,20.6,39.9,17.1,17.1,0,0,0,37.1,22.8,17.3,17.3,0,0,0,29.5,8.6,11.8,11.8,0,0,1,40,19.4ZM20,27.2a7.4,7.4,0,0,1-5.2-2.1,7.1,7.1,0,0,1-2-5.1A7.2,7.2,0,1,1,20,27.2Z" fill="#44f1a6"/></svg>

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 450 B

View File

@ -21,6 +21,8 @@
@import 'components/modal';
@import 'components/flag';
@import 'components/dropdown';
@import 'components/loading';
@import 'components/notice';
.title {
span {
@ -41,13 +43,13 @@
.delete {
border-radius: 0;
height: .902rem;
max-height: .902rem;
max-width: .902rem;
min-height: .902rem;
min-width: .902rem;
width: .902rem;
background-color: #FFFFFF;
height: 1rem;
max-height: 1rem;
max-width: 1rem;
min-height: 1rem;
min-width: 1rem;
width: 1rem;
background-color: #6B6B6B;
mask-size: contain;
mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.2131 1.07106C15.0179 0.875816 14.7013 0.875799 14.506 1.07106L8.14207 7.43502L1.77811 1.07106C1.58286 0.875816 1.26627 0.875799 1.071 1.07106C0.875742 1.26632 0.875752 1.58292 1.071 1.77817L7.43496 8.14213L1.071 14.5061C0.875742 14.7014 0.875752 15.018 1.071 15.2132C1.26625 15.4084 1.58285 15.4085 1.77811 15.2132L8.14207 8.84924L14.506 15.2132C14.7013 15.4084 15.0179 15.4085 15.2131 15.2132C15.4084 15.0179 15.4084 14.7013 15.2131 14.5061L8.84918 8.14213L15.2131 1.77817C15.4084 1.58291 15.4084 1.26631 15.2131 1.07106Z' fill='%23C0D4F3'/%3E%3C/svg%3E%0A");
@ -56,6 +58,6 @@
}
&:hover, &:focus {
background-color: #6B6B6B;
background-color: #fff;
}
}

View File

@ -5,6 +5,8 @@ $control-padding-horizontal: calc(1.063rem - #{$control-border-width});
$primary: #44f1a6;
$primary-invert: #000000;
$warning: #FF8F50;
$danger: #F44C6A;
$size-normal: 0.875rem;
@ -69,6 +71,12 @@ $dropdown-item-active-color: $white;
$dropdown-content-padding-bottom: 0;
$dropdown-content-padding-top: 0;
$loading-background-legacy: #000;
$loading-background: rgba(0,0,0,0.95);
$notification-background-color: #1F1F1F;
$notification-radius: 6px;
@import '~bulma/sass/base/_all';
@import '~bulma/sass/helpers/_all';
@import '~bulma/sass/elements/_all';

View File

@ -7,8 +7,8 @@
mask-repeat: no-repeat;
.trnd-48px {
height: 2rem;
width: 2rem;
height: 1.875rem;
width: 1.875rem;
}
&-tool {
@ -42,4 +42,68 @@
&-github {
mask-image: url("data:image/svg+xml,%3Csvg width='24' height='23' viewBox='0 0 24 23' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 0C5.37 0 0 5.28 0 11.792C0 17.003 3.438 21.422 8.205 22.98C8.805 23.091 9.025 22.726 9.025 22.413C9.025 22.133 9.015 21.391 9.01 20.408C5.672 21.119 4.968 18.826 4.968 18.826C4.422 17.465 3.633 17.101 3.633 17.101C2.546 16.37 3.717 16.385 3.717 16.385C4.922 16.467 5.555 17.6 5.555 17.6C6.625 19.403 8.364 18.882 9.05 18.581C9.158 17.818 9.467 17.299 9.81 17.004C7.145 16.709 4.344 15.695 4.344 11.177C4.344 9.89 4.809 8.838 5.579 8.013C5.444 7.715 5.039 6.516 5.684 4.892C5.684 4.892 6.689 4.576 8.984 6.101C9.944 5.839 10.964 5.709 11.984 5.703C13.004 5.709 14.024 5.839 14.984 6.101C17.264 4.576 18.269 4.892 18.269 4.892C18.914 6.516 18.509 7.715 18.389 8.013C19.154 8.838 19.619 9.89 19.619 11.177C19.619 15.707 16.814 16.704 14.144 16.994C14.564 17.348 14.954 18.071 14.954 19.176C14.954 20.754 14.939 22.022 14.939 22.405C14.939 22.714 15.149 23.083 15.764 22.965C20.565 21.417 24 16.995 24 11.792C24 5.28 18.627 0 12 0Z' fill='%23838BAD'/%3E%3C/svg%3E%0A");
}
&-loading {
height: 1.875rem;
width: 1.875rem;
background: conic-gradient(from 180deg at 50% 50%, $primary 0deg, rgba(255, 255, 255, 0) 360deg);
animation: spin 2s linear infinite;
position: relative;
border-radius: 100%;
&:after {
content: '';
position: absolute;
height: 22px;
width: 22px;
background: $notification-background-color;
left: calc(50% - 11px);
top: calc(50% - 11px);
border-radius: 100%;
}
}
&-info {
height: 1.875rem;
width: 1.875rem;
background-image: url('../images/icons/notice/info.svg');
background-position: center;
background-repeat: no-repeat;
border-radius: 100%;
}
&-success {
height: 1.875rem;
width: 1.875rem;
background-image: url('../images/icons/notice/success.svg');
background-position: center;
background-repeat: no-repeat;
border-radius: 100%;
}
&-warning {
height: 1.875rem;
width: 1.875rem;
background-image: url('../images/icons/notice/warning.svg');
background-position: center;
background-repeat: no-repeat;
border-radius: 100%;
background-color: $warning;
}
&-danger {
height: 1.875rem;
width: 1.875rem;
background-image: url('../images/icons/notice/danger.svg');
background-position: center;
background-repeat: no-repeat;
border-radius: 100%;
background-color: $danger;
}
}
@keyframes spin{
0% {
transform:rotate(0deg)
}
to {
transform:rotate(-1turn)
}
}

View File

@ -0,0 +1,37 @@
.loading-overlay {
.loading-container {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.loading-tornado {
&:after {
content: '';
display: block;
height: 60px;
width: 60px;
background-image: url('../images/logo.svg');
animation: spinAroundReverse 2000ms infinite linear;
}
}
.loading-message {
padding-top: .5rem;
color: $primary;
text-align: center;
+ .button {
margin-top: .5rem;
}
}
}
}
@keyframes spinAroundReverse {
from {
transform: rotate(359deg); }
to {
transform: rotate(0deg); }
}

View File

@ -0,0 +1,27 @@
.notices {
.notification {
min-width: 280px;
pointer-events: auto;
padding: 1.071rem 3.214rem 1.071rem 1.071em;
a:not(.button):not(.dropdown-item) {
color: $primary;
display: block;
margin-top: .15rem;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.media {
align-items: center;
}
.delete {
right: 1rem;
top: calc(50% - .5rem);
}
}
}

View File

@ -3,20 +3,26 @@
<div class="loading-container">
<div class="loading-tornado"></div>
<div class="loading-message">{{ message }}...</div>
<b-button v-if="txHash" tag="a" type="is-primary" :href="txExplorerUrl(txHash)" target="_blank">
<!-- <b-button
v-if="txHash"
tag="a"
type="is-primary"
:href="txExplorerUrl(txHash)"
target="_blank"
>
{{ $t('viewInExplorer') }}
</b-button>
</b-button> -->
</div>
</b-loading>
</template>
<script>
import { mapState, mapGetters } from 'vuex'
import { mapState } from 'vuex'
export default {
computed: {
...mapGetters('txHashKeeper', ['txExplorerUrl']),
// ...mapGetters('txStorage', ['txExplorerUrl']),
...mapState('loading', ['enabled', 'message', 'txHash']),
...mapState('metamask', ['providerName'])
}
...mapState('metamask', ['providerName']),
},
}
</script>

43
components/Notices.vue Normal file
View File

@ -0,0 +1,43 @@
<template>
<div class="notices is-top">
<b-notification
v-for="notice in notices"
:key="notice.id"
class="is-top-right"
has-icon
:icon="notice.type"
:aria-close-label="$t('closeNotification')"
role="alert"
@close="close(notice.id)"
>
<i18n :path="notice.title.path || notice.title" tag="span">
<template v-slot:value>
<b>{{ notice.title.value }}</b>
</template>
</i18n>
<a
v-if="notice.txHash"
:href="txExplorerUrl(notice.txHash)"
target="_blank"
>
{{ $t('viewOnEtherscan') }}
</a>
</b-notification>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapState('notice', ['notices']),
...mapGetters('txHashKeeper', ['txExplorerUrl']),
},
methods: {
...mapActions('notice', ['deleteNotice']),
close(id) {
this.deleteNotice({ id })
},
},
}
</script>

View File

@ -7,18 +7,24 @@
</div>
</section>
<Footer />
<Loading />
<Notices />
</div>
</template>
<script>
import Navbar from '@/components/Navbar'
import Footer from '@/components/Footer'
import Loading from '@/components/Loading'
import Notices from '@/components/Notices'
import { mapActions } from 'vuex'
export default {
components: {
Navbar,
Footer,
Loading,
Notices,
},
mounted() {
this.initProvider()

83
store/notice.js Normal file
View File

@ -0,0 +1,83 @@
const NOTICE_INTERVAL = 10000
export const state = () => {
return {
notices: [],
timers: {},
}
}
export const mutations = {
ADD_NOTICE(state, notice) {
state.notices.push(notice)
},
UPDATE_NOTICE(state, { index, notice }) {
this._vm.$set(state.notices, index, notice)
},
DELETE_NOTICE(state, index) {
this._vm.$delete(state.notices, index)
},
ADD_NOTICE_TIMER(state, { id, timerId }) {
this._vm.$set(state.timers, id, { timerId })
},
DELETE_NOTICE_TIMER(state, id) {
this._vm.$delete(state.timers, id)
},
}
export const actions = {
addNotice({ commit }, { notice }) {
return new Promise((resolve) => {
const id = `f${(+new Date()).toString(16)}`
commit('ADD_NOTICE', { ...notice, id })
resolve(id)
})
},
addNoticeTimer({ commit, dispatch }, { id, interval }) {
if (interval === true || !interval) {
interval = NOTICE_INTERVAL
}
const timerId = setTimeout(() => {
dispatch('deleteNotice', { id })
}, interval)
commit('ADD_NOTICE_TIMER', { id, timerId })
},
deleteNoticeTimer({ state, commit }, { id }) {
if (state.timers[id]) {
clearTimeout(state.timers[id].timerId)
commit('DELETE_NOTICE_TIMER', id)
}
},
addNoticeWithInterval({ dispatch }, { notice, interval }) {
return new Promise((resolve) => {
dispatch('addNotice', { notice }).then((id) => {
dispatch('addNoticeTimer', { id, interval })
resolve(id)
})
})
},
deleteNotice({ state, commit, dispatch }, { id }) {
const index = state.notices.findIndex((i) => {
return i.id === id
})
commit('DELETE_NOTICE', index)
dispatch('deleteNoticeTimer', { id })
},
updateNotice({ state, commit, dispatch }, { id, notice, interval }) {
const { notices } = state
const index = notices.findIndex((i) => {
return i.id === id
})
commit('UPDATE_NOTICE', {
index,
notice: {
...notices[index],
...notice,
},
})
if (interval) {
dispatch('deleteNoticeTimer', { id })
dispatch('addNoticeTimer', { id, interval })
}
},
}