Skip to content

Instantly share code, notes, and snippets.

@Fl0pZz
Last active January 18, 2017 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fl0pZz/bb25c47a282a6bfe62710a168d895a93 to your computer and use it in GitHub Desktop.
Save Fl0pZz/bb25c47a282a6bfe62710a168d895a93 to your computer and use it in GitHub Desktop.
Реализация стека уведомлений на vuex, vue
import { PUSH_NOTICE, DELETE_NOTICE, CHANGE_NOTICE } from './../mutation-types'
const state = {
/**
* structure of notice obj:
* {
* type: 'error'|'notification',
* messages: [],
* action: 'nothing'|'close'|'waiting' <-- action in notification
* }
*/
notices: new Map(),
id: 0, // идентификатор, который будет присвоен следующему уведомлению
old_id: null, // идентификатор, которым обладает самое старое уведомление
size: 0
}
// getters
const getters = {
isEmpty: state => (state.size === 0),
getId: state => state.id,
getOldId: state => state.old_id
}
// mutations
const mutations = {
[PUSH_NOTICE] (state, notice) {
if (state.old_id === null) {
state.old_id = state.id
}
/*
Каждому уведомлению присваивается уникальный id, по которым компоненты могут управлять временем жизни уведомления
Например форма входа в аккаунт: если в поле email было введен не email, то вывесем уведомление и
как только ошибка исправлена, уведомление можно скрыть
*/
state.notices.set(state.id++, notice)
state.size = state.notices.size
},
[CHANGE_NOTICE] (state, { id, notice }) {
state.notices.set(id, notice)
},
[DELETE_NOTICE] (state, id) {
if (state.notices.has(id)) {
state.notices.delete(id)
state.size = state.notices.size
}
if (state.notices.size !== 0) {
/*
если в очереди еще есть уведомления, то переходим к новому
*/
state.old_id++
} else {
/*
чтобы не было траблов, когда уведомлений нет, но old_id и id не равны 0
*/
state.id = 0
state.notices.clear()
state.old_id = null
state.size = 0
}
}
}
// actions
const actions = {
asyncPushNotice ({ getters, commit }, notice) {
/**
* Пушим новое сообщение и получаем его id
*/
let id = getters.getId
commit(PUSH_NOTICE, notice)
return id
},
asyncShiftNotice ({ state, commit, getters }, id = null) {
/**
* Достаем самое старое сообщение или то, которое соответствует нужному id.
* ВАЖНО! удаляем сообщение, чтобы не было неопределенного поведения при совместном доступе к уведомлению с одним id
*/
let notice = null
if (id === null) {
notice = state.notices.get(getters.getOldId)
} else {
notice = state.notices.get(id)
}
commit(DELETE_NOTICE, getters.getOldId)
return notice
}
}
export default {
state,
getters,
mutations,
actions
}
import { mapGetters, mapActions } from 'vuex'
// import store from './../../store/store'
// const MAX_AMOUNT_NOTIFICATION = 5
const TIME_SHOW_NOTIFICATION = 4000
const TIME_SHOW_ERROR = 3000000
export default {
name: 'notification',
data: () => {
return {
count: 0
}
},
watch: {
isEmpty: function (empty) {
if (!empty) {
this.creator()
}
}
},
computed: {
...mapGetters([
'isEmpty'
])
},
mounted () {
if (!this.isEmpty) {
this.creator()
}
},
methods: {
creator () {
let $this = this
while (!this.isEmpty) {
this.shiftNotice()
.then((notice) => {
switch (notice.type) {
case 'error':
Materialize.toast($this.createNotification(notice), TIME_SHOW_ERROR)
break
case 'notification':
Materialize.toast($this.createNotification(notice), TIME_SHOW_NOTIFICATION)
break
default:
console.log('Что ты мне дал?!')
}
})
}
},
createNotification ({ messages, action }) {
let notice = ''
switch (action) {
case 'waiting':
break
case 'close':
notice = '<i class="material-icons right">close</i>'
break
case 'nothing':
break
default:
console.log('wtf?')
}
messages.forEach((message, i, messages) => {
notice += `${message}`
if (messages.length > 1) {
notice += '<br>'
}
})
return notice
},
...mapActions({
shiftNotice: 'asyncShiftNotice'
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment