Уведомления заставляют пользователей обращать внимание на определенные фрагменты информации и поощряют взаимодействие пользователей с нашим контентом или веб-сайтом.
Что мы будем создавать
В этом посте мы обсудим управление уведомлениями приложений в реальном времени в Vue.js для создания службы уведомлений о заказе еды. Мы будем подписываться на каналы в нашей базе данных и отображать уведомления, когда в каналах происходят изменения.
URL GitHub
https://github.com/Iheanacho-ai/appwrite-food-notification
Предварительные условия
Чтобы получить максимальную отдачу от этого проекта, нам необходимо следующее:
- Базовое понимание CSS, JavaScript и Vue.js.
- Docker Desktop установлен на компьютере, выполните команду
docker -v
, чтобы проверить, установлен ли у нас Docker Desktop, если нет, установите его из документации Get Docker - Экземпляр Appwrite, запущенный на нашем компьютере, ознакомьтесь с этой статьей, чтобы создать локальный экземпляр Appwrite, мы будем использовать надежную базу данных Appwrite и службу Realtime для управления нашим приложением.
Настройка нашего приложения Vue.js
Мы установим Vue CLI, выполнив эти команды терминала для создания нового проекта Vue.
npm install -g @vue/cli
# OR
yarn global add @vue/cli
После установки Vue CLI мы переходим в нужную нам директорию и создаем новый проект.
vue create <name of our project>
Мы меняем директорию на проект и запускаем сервер разработки:
npm run serve
Чтобы посмотреть приложение, переходим на http://localhost:8080/.
Установка зависимостей
Установка Tailwind CSS
Tailwind CSS — это CSS-фреймворк, который позволяет быстро создавать пользовательские интерфейсы для веб-приложений.
Чтобы установить Tailwind CSS в наш проект, выполните следующие команды терминала.
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init -p
Эти команды создают два файла в корневом каталоге нашего проекта, tailwind.config.js
и postcss.config.js
.
В нашем tailwind.config.js
мы добавляем пути ко всем нашим файлам шаблонов с помощью приведенного ниже кода.
module.exports = {
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
content: [],
theme: {
extend: {},
},
plugins: [],
}
Далее мы добавляем директивы tailwind в наш файл src/index.css
.
@tailwind base;
@tailwind components;
@tailwind utilities;
Установка Vue Router
Маршрутизация — это технология, используемая для переключения между различными страницами в нашем приложении на основе изменений в текущем URL.
Мы выполним эту команду терминала, чтобы включить наше приложение для использования Vue Router.
npm install vue-router@4
#or
yarn add vue-router@4
Установка Mosha Vue Toastify
Mosha Vue Toastify — это легкая библиотека Vue, которая позволяет нам создавать супер настраиваемые уведомления.
Выполним эти команды, чтобы установить библиотеку Mosha Vue Toastify в наш проект.
npm install mosha-vue-toastify
#or
yarn add mosha-vue-toastify
Установка Appwrite
Appwrite — это сквозное серверное решение с открытым исходным кодом, которое позволяет разработчикам быстрее создавать приложения.
Чтобы использовать Appwrite в нашем приложении Vue, мы установим клиентский SDK Appwrite для веб-приложений.
npm install appwrite
Создание нового проекта Appwrite
Во время создания экземпляра Appwrite мы указали, какое имя хоста и порт мы видим в нашей консоли. Значение по умолчанию — localhost:80.
Мы переходим на localhost:80 и создаем новую учетную запись, чтобы увидеть нашу консоль.
На нашей консоли есть кнопка Create Project. Нажмите на нее, чтобы начать новый проект.
После создания проекта появится приборная панель нашего проекта. В верхней части страницы находится панель настроек. Нажмите на нее, чтобы получить доступ к ID проекта и конечной точке API.
Мы скопируем ID проекта и конечную точку API, которые нужны нам для инициализации Appwrite Web SDK.
В нашем файле utils/web-init.js
мы инициализируем наш Web SDK с помощью этого фрагмента кода.
import { Appwrite } from 'appwrite';
export const sdk = new Appwrite();
sdk
.setEndpoint('http://localhost/v1') // Replace this with your endpoint
.setProject('projectID'); // Replace this with your ProjectID
Создание анонимной сессии пользователя
Appwrite требует, чтобы пользователь регистрировался перед чтением или записью в базу данных для обеспечения безопасности в нашем приложении. Однако они позволяют нам создать анонимную сессию, чтобы обойти эту политику для простых проектов.
Мы создадим анонимную сессию пользователя в нашем файле utils.js
.
import { Appwrite } from 'appwrite';
export const sdk = new Appwrite();
sdk
.setEndpoint('http://localhost/v1') // Replace this with your endpoint
.setProject('62532ce64d84a58176da'); // Replace this with your ProjectID
// Create an anonymous user session
sdk.account.createAnonymousSession().then(
(response) => {
console.log(response);
},
(error) => {
console.log(error);
}
);
Создание коллекции и атрибутов
Далее мы настроим нашу базу данных, в которой будет храниться статус заказа. В веб-консоли Appwrite мы нажимаем на Database в левой части приборной панели.
Мы создаем коллекцию на вкладке нашей базы данных, нажав на кнопку Добавить коллекцию. Это действие перенаправляет нас на страницу разрешений.
На уровне коллекции мы хотим назначить доступ на чтение и доступ на запись со значением role:all. Мы можем изменить разрешения, чтобы указать, кто имеет доступ на чтение или запись в нашу базу данных.
В правой части страницы разрешений мы копируем идентификатор коллекции, который нам нужен для выполнения операций над документами коллекции.
Далее мы переходим на вкладку Attributes, чтобы создать свойства, которыми должен обладать документ.
Мы создаем строковый атрибут orderStatus.
Создаем наше приложение для уведомления о заказе еды.
Наше приложение для уведомления о заказе еды будет состоять из двух страниц. На одной странице будет размещаться заказ и обновляться статус заказа, который может быть либо принят, либо подготовлен, либо находится в пути, либо доставлен. Вторая страница подписывается на статус заказа и уведомляет нас о любых его обновлениях в режиме реального времени.
Создание страницы заказа
Наша страница заказа будет состоять из кнопки для размещения заказа и списка выбора для обновления статуса заказа.
Мы создаем папку views
в нашей папке src
для создания пользовательского интерфейса. Эта папка src/views
будет содержать файл Home.vue
.
Мы создадим нашу страницу заказа в файле src/views/Home.vue
.
<template>
<div class="home rounded overflow-hidden shadow-lg">
<div class="home-container">
<button type="button" class="bg-gray-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Place Order</button>
<h3>Change Order Status to follow your order</h3>
<select name="order-status" id="order-status" class ="relative w-150 bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="Order Placed" >Order Placed</option>
<option value="Order Accepted" >Order Accepted</option>
<option value="Prepared" >Prepared</option>
<option value="En-route" >En-route</option>
<option value="Delivered">Delivered</option>
</select>
</div>
</div>
</template>
<style>
#app {
display: flex;
justify-content: center;
align-items: center;
height: 80vh;
text-align: center;
}
.app-container{
height: 400px;
}
.page-link{
margin: 10px;
text-decoration: underline;
}
</style>
Маршрутизация на наши страницы
В нашем файле src/main.js
мы разрешаем нашему приложению использовать router
для перехода на различные страницы с помощью этого фрагмента кода.
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './index.css';
createApp(App).use(router).mount('#app')
Далее мы создаем папку router
в нашей папке src
. Наша папка router
будет содержать файл index.js
. Этот файл будет отвечать за определение маршрутов, ведущих к определенным компонентам.
// src/router/index.js
import { createRouter,createWebHistory } from 'vue-router'
import Home from '@/views/Home'
import Notification from '@/views/Notifications'
const routes = [
{
path: '/',
name: 'Home',
component: Home
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router;
Приведенный выше блок кода делает следующее:
- Создает массив
routes
, содержащий путь маршрута и компонент, к которому он должен вести. - Облегчает маршрутизацию с помощью метода Vue
createRouter
, который получает объект в качестве параметра, этот объект имеет два поля, поле history и поле route, значением которого является наш массив route.
Далее, в нашем файле App.vue
мы добавляем ссылки, которые будут ссылаться на эти страницы.
<template>
<div class="app-container">
<router-view ></router-view>
<router-link class="page-link" to="/"> Home Page</router-link>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
#app {
display: flex;
justify-content: center;
align-items: center;
height: 80vh;
text-align: center;
}
.app-container{
height: 400px;
}
.page-link{
margin: 10px;
text-decoration: underline;
}
</style>
- Компонент router-view представляет наш компонент. В блоке кода выше мы указываем, в какой позиции находится наше приложение.
- Компонент
router-link
действует как тег якоря, создавая ссылки, ведущие к различным маршрутам.
Чтобы избежать ошибок, возникающих из-за не многоуровневых имен компонентов, создайте файл ..eslintrc.js
в нашей папке views
.
Этот файл views/..eslintrc.js
будет содержать следующий код.
module.exports = {
rules: {
'vue/multi-word-component-names': 0,
},
}
Перейдите на наш сайт http://localhost:8080/, чтобы увидеть нашу главную страницу.
Создание страницы уведомлений
В папке src/views
мы создадим файл Notifications.vue
для отображения статуса нашего заказа.
<template>
<div class="notifications rounded overflow-hidden shadow-lg">
<div class="order-container">
<h2>Order Placed</h2>
</div>
</div>
</template>
<style scoped>
.notifications{
width: 350px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
Мы добавляем маршрут в объект routes
в файле src/router/index.js
для просмотра страницы уведомлений в браузере.
// src/router/index.js
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/notification-page',
name: 'Notification',
component: Notification
}
]
Вот как выглядит наш файл src/router/index.js
.
import { createRouter,createWebHistory } from 'vue-router'
import Home from '@/views/Home'
import Notification from '@/views/Notifications'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/notification-page',
name: 'Notification',
component: Notification
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router;
Далее мы добавляем еще один router-link
в наш файл App.vue
в качестве тега якоря для ссылки на страницу уведомлений.
<template>
<div class="app-container">
<router-view ></router-view>
<router-link class="page-link" to="/"> Home Page</router-link>
<!-- link to notification page -->
<router-link class="page-link" to="/notification-page">Notification Page</router-link>
</div>
</template>
Чтобы увидеть нашу страницу уведомлений, перейдите по адресу http://localhost:8080/notification-page.
Добавьте взаимодействие с нашей базой данных
Когда пользователь размещает заказ, мы создаем документ в нашей базе данных, который содержит строку «Заказ размещен». Любые обновления статуса заказа с помощью списка выбора будут автоматически обновлять документ в нашей базе данных Appwrite.
Наш файл src/views/Home.vue
будет отвечать за создание и обновление документа нашей базы данных.
Создание документа базы данных
<script>
import { sdk } from "../../utils";
export default {
name: 'Home',
data(){
return{
documentID: null,
}
},
methods: {
placeOrder: async function(){
try {
let promise = await sdk.database.createDocument('collectionID', 'unique()', {
"orderStatus": "Order Placed"
})
this.documentID = promise.$id;
alert("order successfully placed")
} catch (error) {
console.log(error)
}
},
updateOrder: async function(e){
try {
let orderValue = e.target.value
await sdk.database.updateDocument('collectionID', this.documentID, {
"orderStatus": orderValue
})
alert(orderValue);
} catch (error) {
console.log(error)
}
}
}
}
</script>
В приведенном выше блоке кода мы делаем следующее:
- Создаем переменную
documentID
в нашем объектеdata
, которая будет содержать идентификатор нашего недавно созданного документа. - Создаем функцию
placeOrder
для создания документа в нашей базе данных с помощьюcreateDocument
от Appwrite - Создайте функцию
updateOrder
, которую мы передадим в список выбора позже в этом руководстве, где функция будет собирать значение элемента option и использовать его для обновления нашего документа в базе данных.
В нашем файле Home.vue
мы передаем функцию placeOrder
слушателю события on-click для нашей кнопки и функцию updateDocument
слушателю события on-change для нашего списка select
.
<template>
<div class="home rounded overflow-hidden shadow-lg">
<div class="home-container">
<button type="button" @click = 'placeOrder' class="bg-gray-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Place Order</button>
<h3>Change Order Status to follow your order</h3>
<select name="order-status" id="order-status" v-on:change = "updateOrder" class ="relative w-150 bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<option value="Order Placed" >Order Placed</option>
<option value="Order Accepted" >Order Accepted</option>
<option value="Prepared" >Prepared</option>
<option value="En-route" >En-route</option>
<option value="Delivered">Delivered</option>
</select>
</div>
</div>
</template>
Вот как выглядит наш файл Home.vue
.
(https://gist.github.com/Iheanacho-ai/9e47a71adb7fc17b1c5df85c7387dfef)
Мы размещаем заказ на просмотр нашего документа в нашей базе данных.
Подписка на обновления документа
Мы подписываемся на наш документ базы данных Appwrite в нашем src/views/Notifications.vue
.
<script>
import { sdk } from "../../utils";
export default {
name: 'Notification',
data(){
return{
orderStatus: ""
}
},
mounted(){
if(sdk.account.get !== null){
try {
sdk.subscribe('collections.collectionID.documents', response => {
this.orderStatus = response.payload.orderStatus
});
} catch (error) {
console.log(error, 'error')
}
}
}
}
</script>
В приведенном выше блоке кода мы делаем следующее:
- Создаем переменную
orderStatus
для хранения полезной нагрузки нашего ответа - Проверяем наличие активной сессии пользователя перед подпиской на наш канал коллекций
- Подписываемся на канал с помощью метода
subscribe
Appwrite, который получает два параметра, канал, на который мы подписываемся, и функцию обратного вызова; чтобы узнать больше о различных каналах, на которые мы можем подписаться, ознакомьтесь с Каналы реального времени Appwrite - Обновление переменной
orderStatus
Далее мы отобразим нашу переменную orderStatus
как текст в файле Notifications.vue
.
<template>
<div class="notifications rounded overflow-hidden shadow-lg">
<div class="order-container">
<h2>{{orderStatus}}</h2>
</div>
</div>
</template>
Вот как выглядит наш файл Notifications.vue
.
(https://gist.github.com/Iheanacho-ai/0f23cf72b2a43be4251f2fb2aa22b7d8)
Создание нашего уведомления
Чтобы использовать уведомление mosha-vue-toastify в нашем приложении, мы импортируем его в наш src/views/Notifications.vue
.
import { sdk } from "../../utils";
import { createToast } from 'mosha-vue-toastify';
import 'mosha-vue-toastify/dist/style.css'
Мы используем объект watch
для прослушивания изменения переменной в нашем приложении. Прослушивая переменную orderStatus
, мы можем запускать метод createToast
каждый раз, когда переменная обновляется.
export default {
name: 'Notification',
data(){
return{
orderStatus: ""
}
},
watch: {
orderStatus: function(){
createToast(this.orderStatus)
}
},
mounted(){
...
}
}
Вот как выглядит наше приложение.
Заключение
В этой статье мы рассмотрели использование функции Realtime в Appwrite для подписки на события приложения.
Ресурсы
- Начало работы с Appwrite для веб
- Mosha Vue Toastify
- Что такое Appwrite и как его эффективно использовать.