Как оптимизировать загрузку изображений в Appwrite и Vuejs

Виджеты загрузки изображений позволяют пользователям предварительно просматривать изображения, которые они загружают в приложение или базу данных через формы, Google Drive и т.д. Эти виджеты позволяют пользователю принять решение о просмотре или удалении изображений, выбранных для отправки.

Что мы будем создавать

В этом посте рассматривается загрузка изображений с помощью виджета загрузки изображений Cloudinary и хранение полученного URL изображения в базе данных Appwrite для создания каталога товаров электронной коммерции.

URL GitHub

https://github.com/Iheanacho-ai/optimised-image-upload-vue

Предварительные условия

Чтобы получить максимальную отдачу от этого проекта, необходимо следующее:

  • Базовое понимание 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;
Войти в полноэкранный режим Выход из полноэкранного режима

Установка Appwrite

Appwrite Appwrite – это сквозное серверное решение с открытым исходным кодом, которое позволяет разработчикам быстрее создавать приложения.

Чтобы использовать Appwrite в нашем приложении Vue, мы установим клиентский SDK Appwrite для веб-приложений.

    npm install appwrite
Вход в полноэкранный режим Выход из полноэкранного режима

Создание нового проекта Appwrite

Во время создания экземпляра Appwrite мы указали, какое имя хоста и порт мы используем для нашей консоли. Значение по умолчанию – localhost:80.

Мы переходим на localhost:80 и создаем новую учетную запись, чтобы увидеть нашу консоль.

На нашей консоли есть кнопка Создать проект. Нажмите на нее, чтобы начать новый проект.

После создания проекта появится приборная панель нашего проекта. В верхней части страницы находится панель настроек. Нажмите на нее, чтобы получить доступ к ID проекта и конечной точке API.

Мы копируем ID проекта и конечную точку API, которые нам нужны для инициализации Appwrite Web SDK.

Мы создаем файл init.js в корневом каталоге нашего проекта для инициализации Appwrite 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 требует, чтобы пользователь регистрировался перед чтением или записью в базу данных для обеспечения безопасности в нашем приложении. Однако они позволяют нам создать анонимную сессию, чтобы обойти эту политику для простых проектов. Мы сделаем это в нашем файле init.js.

    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
   // Create an anonymous user session
    sdk.account.createAnonymousSession().then(
        (response) => {
            console.log(response);
        },
        (error) => {
            console.log(error);
        }
    );
Вход в полноэкранный режим Выход из полноэкранного режима

Создание коллекции и атрибутов

Далее мы настроим нашу базу данных, которая будет хранить статус нашего заказа. В веб-консоли Appwrite мы нажимаем на Database в левой части приборной панели.

Мы создаем коллекцию на вкладке нашей базы данных, нажав на кнопку Добавить коллекцию. Это действие перенаправляет нас на страницу разрешений.

На уровне коллекции мы хотим назначить доступ на чтение и доступ на запись со значением role:all. Мы можем изменить разрешения, чтобы указать, кто имеет доступ на чтение или запись в нашу базу данных.

Справа на странице Разрешения мы копируем идентификатор коллекции, который нам нужен для выполнения операций над документами коллекции.

Далее мы переходим на вкладку Attributes, чтобы создать свойства, которыми должен обладать документ.

Мы создаем три строковых атрибута: productName, productPrice и productImage.

Создание страницы создания продукта

Мы создаем страницу создания продукта в файле App.vue. Эта страница создания продукта будет содержать два раздела: первый включает форму для сбора информации о продукте, а второй раздел перечисляет продукты в нашей базе данных.

Здесь мы создадим форму для отправки названия, цены и изображения товара в базу данных. Мы добавим следующий фрагмент кода в файл index.js для создания формы, оформленной с помощью Tailwind CSS.

    <template>
      <div class= 'product-catalog'>
          <div class="product-container mt-5 md:mt-0 md:col-span-2">
          <div class="shadow sm:rounded-md sm:overflow-hidden">
            <div class="px-4 py-5 bg-white space-y-6 sm:p-6">
              <div>
                <label for="price" class="block text-sm font-medium text-gray-700">Product Name</label>
                <div class="mt-1 relative rounded-md shadow-sm">
                  <input type="text" name="price" v-model="productName" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full pl-7 pr-12 sm:text-sm border-gray-300 rounded-md" placeholder="product name" />
                </div>
              </div>
              <div>
                <label for="price" class="block text-sm font-medium text-gray-700">Price</label>
                <div class="mt-1 relative rounded-md shadow-sm">
                  <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                    <span class="text-gray-500 sm:text-sm"> $ </span>
                  </div>
                  <input type="text" name="price" v-model="productPrice" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full pl-7 pr-12 sm:text-sm border-gray-300 rounded-md" placeholder="0.00" />
                </div>
              </div>
              <button nclass="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
                Upload files
              </button>
              <div className="px-4 py-3 bg-gray-50 text-right sm:px-6">
              <button
                type="button"
                className="cursor inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
              >
                Save
              </button>
            </div>
            </div>
          </div>
        </div>
      </div>
    </template>
Вход в полноэкранный режим Выход из полноэкранного режима

В секции style нашего файла App.vue мы создаем стили Tailwind CSS с помощью этих стилей CSS.

    <style>
      .product-container{
        margin-left: 37%;
        width: 30%;
      }
    </style>
Вход в полноэкранный режим Выход из полноэкранного режима

Вот как выглядит наша форма создания продукта.

Встраивание виджета Cloudinary Upload

В этом проекте кнопка Upload File открывает виджет загрузки изображений Cloudinary, позволяющий нам загружать изображения в базу данных Appwrite.

Чтобы понять, как встроить виджет загрузки изображений Cloudinary в наш проект, ознакомьтесь с этой статьей.

Добавьте взаимодействие с нашей базой данных

Когда пользователь нажимает на кнопку сохранения, мы хотим сохранить информацию о товарах в базе данных Appwrite и вывести список сохраненных товаров в нашем приложении.

Хранение информации о товаре в базе данных

Мы храним информацию в базе данных Appwrite в виде документов. В разделе сценария нашего файла App.vue мы создаем четыре переменные в объекте data.

    <script>
      export default {
        name: 'App',
        data(){
          return{
            productName: '',
            productPrice: '',
            productImage: '',
            products: []
          }
        },
      }
    </script>
Вход в полноэкранный режим Выйти из полноэкранного режима

В переменных хранится следующая информация.

  • Переменная productName содержит имя продукта, которое будет храниться в базе данных.
  • Переменная productPrice содержит цену продукта, которая будет храниться в базе данных.
  • Переменная productImage содержит URL изображения продукта для хранения в базе данных
  • Переменная products представляет собой массив всех продуктов, хранящихся в базе данных.

Далее мы импортируем экземпляр sdk из нашего файла init.js в файл App.vue.

    import {sdk} from '../init';
Вход в полноэкранный режим Выход из полноэкранного режима

Затем мы создаем функцию handleProductSubmit в нашем файле App.vue для создания документов в нашей базе данных.

    handleProductSubmit: async function(){
      try {
          await sdk.database.createDocument(collectionID, 'unique()', {
        "productName" : this.productName,
        "productPrice": this.productPrice,
        "productImage": this.productImage
      });
       alert('your job item has been successfully saved')
       this.productName= '',
       this.productPrice= '',
       this.productImage= ''
      } catch (error) {
        console.log(error)
      }
    },
Вход в полноэкранный режим Выход из полноэкранного режима

Функция handleProductSubmit делает следующее:

  • Создает новый документ с помощью функции createDocument() от Appwrite, передавая в качестве параметров ID коллекции и значения атрибутов.
  • Предупреждает нас об успешном сохранении документа, затем очищает информацию в локальных переменных состояния
  • Записывает в консоль любую ошибку, возникшую при создании документа.

https://gist.github.com/Iheanacho-ai/d20d8322de5e1d51d0ad89febeac996e

Вывод списка продуктов

В файле App.vue мы создаем функцию listProducts для получения информации о товарах, хранящейся в нашей базе данных.

    listProducts: async function(){
      try {
        let response = await sdk.database.listDocuments('628a9019078ea3c2b384');
        this.products = response.documents
      } catch (error) {
        console.log(error)

      }
    },
Вход в полноэкранный режим Выход из полноэкранного режима

Функция listProducts делает следующее:

  • Перечисляет все документы в коллекции
  • Сохраняет документы в массиве products
  • Записывает в консоль все возникшие ошибки

Затем мы вызываем функцию listProducts в нашей функции handleProductSubmit и жизненном цикле mounted.

    mounted: function(){
      this.listProducts()
    },
    mounted: function(){
      handleProductSubmit: async function(){
          try {
              ...
           this.listProducts()
          } catch (error) {
            console.log(error)
          }
        },
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Удаление продуктов

Далее мы создадим функцию handleDelete в нашем файле App.vue, чтобы удалить любой продукт и информацию о нем из нашей базы данных Appwrite.

    handleDelete: async function(documentid){
      try {
        await sdk.database.deleteDocument(collectionID, documentid);
        alert("item have been deleted successfully")
        this.listProducts()
      } catch (error) {
        console.log(error)
      }
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Эта функция handleDelete делает следующее:

  • Удаляет документ из нашей коллекции базы данных Appwrite с помощью функции deleteDocument. Эта функция deleteDocument находит документ, используя его ID документа и параметр ID коллекции.
  • Предупреждает пользователя об успешном удалении документа.
  • Перечисляет оставшиеся продукты в нашей базе данных с помощью функции listProducts.
  • Записывает в журнал все ошибки, возникшие при удалении документа.

После создания наших функций вот как выглядит наш файл App.vue.

https://gist.github.com/Iheanacho-ai/7a7eb7a1649bfc492cf9e3282101fcb8

Далее мы передаем переменные productName и productPrice в элементы input нашей формы.

    <input type="text" name="price" v-model="productName" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full pl-7 pr-12 sm:text-sm border-gray-300 rounded-md" placeholder="product name" />


    <input type="text" name="price" v-model="productPrice" class="focus:ring-indigo-500 focus:border-indigo-500 block w-full pl-7 pr-12 sm:text-sm border-gray-300 rounded-md" placeholder="0.00" />
Вход в полноэкранный режим Выход из полноэкранного режима

Наконец, мы передаем функцию handleProductSubmit нашей кнопке Save.

    <button
      type="button"
      @click="handleProductSubmit"
      className="cursor inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
    >
      Save
    </button>
Вход в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: Мы используем кнопку с type= button, чтобы переопределить стандартное поведение кнопки при отправке.

После выполнения этих шагов вот как выглядит наш файл App.vue.

https://gist.github.com/Iheanacho-ai/8f5106c552eee8cf1d4cd4efc8a3d5fa

Создание пользовательского интерфейса листинга товаров

Чтобы создать пользовательский интерфейс для отображения товаров, хранящихся в базе данных Appwrite, мы вставим этот код в наш файл App.vue.

    <div className="bg-white">
        <div className="max-w-2xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:max-w-7xl lg:px-8">
          <h2 className="sr-only">Products</h2>
            <div className="grid grid-cols-1 gap-y-10 sm:grid-cols-2 gap-x-6 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8">
              <a href="#" v-for= 'product in products' :key= 'product.productName' className="group">
                <div className="w-full aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden xl:aspect-w-7 xl:aspect-h-8">
                  <img :src="product.productImage" alt="Tall slender porcelain bottle with natural clay textured body and cork stopper." className="w-full h-full object-center object-cover group-hover:opacity-75" />
                </div>
                <h3 className="mt-4 text-sm text-gray-700">{{product.productName}}</h3>
                <p className="mt-1 text-lg font-medium text-gray-900">${{product.productPrice}}</p>
                <button
                  type="button"
                  className="cursor inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                @click="handleDelete(product.$id)" 
                >
                  Delete
                </button>
              </a>   
            </div>
        </div>
      </div>
Вход в полноэкранный режим Выйти из полноэкранного режима

В приведенном выше блоке кода мы:

  • Пройдитесь по массиву products для визуализации каждого продукта.
  • Передайте переменные productName, productPrice и productImage в массив products.
  • Передайте функцию handleDelete и параметр ID документа слушателю события @Click на кнопке Delete button.

Вот как выглядит файл App.vue.

https://gist.github.com/Iheanacho-ai/03f5eb3f75fa8e799fd217c23229b97e

Заполните форму, чтобы увидеть, как выглядит каталог товаров.

Заключение

В этой статье мы рассмотрели управление оптимизированной загрузкой изображений с помощью Cloudinary и хранение изображений в базе данных Appwrite. Используя эту информацию, мы создали каталог товаров. Вы можете изменить поля, чтобы разместить больше информации о продукте.

Ресурсы

Вот некоторые ресурсы, которые могут оказаться полезными.

  • Загрузка файлов Vue и Rich Media в два простых шага
  • Создание локального экземпляра Appwrite в 3 шага
  • API базы данных

Оцените статью
Procodings.ru
Добавить комментарий