Кто-то учится, наблюдая, кто-то учится, делая. Для меня знакомство с продуктом действительно помогает понять, как он работает. Создание чего-то интересного и увлекательного всегда было отличным мотиватором при изучении новых инструментов, поэтому, когда я впервые начал свой путь в Zendesk и получил возможность создать приложение с помощью Zendesk Apps Framework (ZAF), естественно, моей первой мыслью было: давайте создадим Покедекс!

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

Концептуализация

Первым шагом в начале процесса сборки моего приложения было определение варианта использования. В этом сценарии я бы создал Pokédex для гипотетического продавца покемонов. Pokédex должен будет разрешить агентам доступ к данным о покемонах, не полагаясь на сторонние веб-сайты. Кроме того, Pokédex должен иметь возможность напрямую взаимодействовать с билетами, например, заполнять настраиваемые поля. Наконец, Pokédex должен быть легко доступен и интуитивно понятен в использовании. Итак, имея в виду эти условия, я решил, что мой подход будет следующим:

  1. Интегрируйте данные непосредственно в приложение, чтобы позволить агентам получать доступ к указанным данным, не выходя из своего экземпляра Zendesk; сначала используя внешний API, а затем перебирая пользовательские объекты.
  2. Использование методов ZAF для обеспечения взаимодействия между приложением и Tickets API.
  3. Использование местоположения боковой панели заявки для приложения и обеспечение отображения только релевантной информации интуитивно понятным способом.

Теперь, когда заложена основа и проделана небольшая работа по дизайну, я был готов приступить к созданию приложения.

Настраивать

Прежде всего, мне нужно было настроить проект. Это стало очень просто благодаря использованию интерфейса командной строки Zendesk или ZCLI. ZCLI предоставляет вам множество различных вариантов настройки проекта, и я рекомендую вам заглянуть в репозиторий GitHub, чтобы узнать больше об этом замечательном инструменте! Для целей этого проекта я начал с того, что раскрутил базовое приложение, а затем добавил в него немного магии React. Для начала нужно сделать всего пару простых шагов:

  1. Откройте терминал и перейдите туда, где вы хотите создать папку проекта.
  2. Скопируйте и вставьте приведенный ниже код и обязательно замените данные-заполнители своими собственными: zcli apps:new --appName=appName --authorEmail=yourEmail --authorName=yourName --path=destinationFolder
  3. Сделанный!

И это все! Приложение готово к созданию. Вы можете проверить это, перейдя в корневой каталог приложения в своем терминале, запустив zcli apps:server, а затем открыв экземпляр Zendesk и добавив ?zcli_apps=true в конец URL-адреса. Вы должны увидеть что-то вроде этого:

Хотя у меня было все, что мне нужно, чтобы начать работу, раскрутив приложение с помощью ZCLI выше, для целей этого приложения я хотел добавить немного React. Для этого мне нужно было добавить немного сахара в проект. Здесь я шаг за шагом опишу, как я настроил React и запустил свой проект. Если вы хотите увидеть код и следовать ему, вы также можете посетить репозиторий GitHub. Хорошо, давайте сделаем это!

  1. Перед началом работы вам необходимо установить необходимые зависимости. Сначала запустите npm init, чтобы создать файл package.json. Затем скопируйте и вставьте из списка ниже, чтобы начать работу: npm install react react-dom regenerator-runtime core-js и npm install —-save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin css-loader sass sass-loader style-loader svg-inline-loader @babel/core babel-loader @babel/preset-env @babel/preset-react
  2. Затем вам нужно создать папку /dist в корневом каталоге и переместить туда папку с ресурсами, папку с переводами и файл manifest.json.
  3. Далее вы создадите каталог src. Переместите iframe.html из папки dist/assets в папку src. Это будет использоваться в качестве шаблона для веб-пакета для создания рабочего файла в папке ресурсов во время сборки. В файле iframe.html создайте <div> с идентификатором «root» в <body>.
  4. Затем создайте файл index.js и файл App.js. Это будут ваши начальные файлы React. Документация React — отличное место, чтобы начать изучать структуру файлов React.
  5. Затем создайте файл webpack.config.js. Вот где происходит волшебство. Webpack и babel объединят и преобразуют необходимые фрагменты, необходимые для запуска нашего приложения, и сгенерируют файл iframe.html, который нам нужен, в папке dist/assets.
  6. И последнее, но не менее важное: мы добавим несколько скриптов в наш файл package.json для передачи команд в webpack.

И вот оно! Теперь у вас есть полнофункциональное приложение React, работающее с ZAF. Чтобы увидеть его в действии, в терминале запустите npm run build, чтобы скомпилировать ваши файлы, npm run watch, чтобы веб-пакет отслеживал изменения во время сборки, а затем zcli apps:server ./dist с ?zcli_apps=true в конце URL-адреса Zendesk.

Опять же, чтобы увидеть код, используемый в этой настройке, не стесняйтесь проверить репозиторий, указанный выше!

Вызовы API с использованием метода запросов ZAF

После того, как я создал базовую функциональность приложения, пришло время приступить к работе с данными. Поскольку нужные мне данные о покемонах не были доступны в локальной базе данных (пока), мне нужно было получить необходимые данные через PokeAPI. Для этого в ZAF есть встроенный метод выполнения HTTP-запросов: client.request(). Метод принимает один аргумент options, который может быть либо URL-адресом запрашиваемого ресурса (например, https://pokeapi.com/api/v2/pokemon), либо объектом, содержащим такие свойства, как URL-адрес, заголовки запроса, типы данных и т. д. Полный список свойств можно посмотреть здесь.

Итак, вот пример из моего приложения, извлекающего данные из pokeAPI через асинхронную функцию и сохраняющего возвращенный объект в состоянии:

Давайте разберем это шаг за шагом:

  1. Мы создали асинхронную функцию под названием getPokeData, которую мы будем использовать для выполнения нашего запроса.
  2. Мы создали объект параметров, который будет использоваться в качестве аргумента в нашем методе запроса. В этом примере у нас есть URL-адрес, к которому мы делаем запрос, и тип или метод запроса, в данном случае запрос GET.
  3. Внутри оператора try/catch мы делаем вызов client.request(), используя вышеупомянутый аргумент options, и устанавливаем состояние на основе результата, если запрос выполнен успешно. Примечание: клиентский объект здесь называется «zafClient», так как он импортирован из компонента в приложении с именем zafClient.
  4. Наконец, если мы получаем какие-либо ошибки, мы записываем ответ в консоль и устанавливаем для нашего состояния ошибки значение true.

Теперь данные доступны в состоянии для использования по мере необходимости в приложении. Сначала у меня было несколько вызовов API, разбросанных по всему приложению для разных целей; далее в этой статье мы расскажем, как я импортировал унифицированные данные в пользовательские объекты.

Вы можете найти подробное объяснение того, как работает метод client.request() здесь.

ZAF и API билетов

Теперь, когда у меня были нужные данные, следующим шагом было создание функциональности, обеспечивающей взаимодействие между приложением и заявкой. Цель здесь состояла в том, чтобы позволить агентам заполнять настраиваемые поля данными непосредственно из приложения. Кроме того, приложению также необходимо распознавать, присутствует ли значение в настраиваемых полях при загрузке страницы, и отображать соответствующие данные на основе этого. Представляем: методы client.get() и client.set().

Клиент.get()

Метод client.get() используется для извлечения данных из пользовательского интерфейса в ваше приложение. Он принимает один аргумент paths, который может быть отдельной строкой пути (например, ticket.subject) или массивом путей. Примечание. Запрос выполняется асинхронно и возвращает обещание.

Клиент.set()

Метод client.set() используется для установки данных в пользовательском интерфейсе через API Zendesk. Он принимает два аргумента: keyпуть для установки значения (например, ticket.requester) или объект, содержащий ключи и значения, если у вас есть несколько полей для обновления.

С помощью этих методов у меня был доступ к API Zendesk, чтобы иметь возможность обновлять как заявку, так и приложение в зависимости от потребностей пользователя. Вот пример метода client.set() в действии:

Давайте распакуем это очень быстро:

  1. Мы создали функцию под названием populateCustomField. В этом случае функция вызывалась нажатием кнопки в навигации приложения.
  2. Внутри populateCustomField у нас есть zafClient.set(), где мы передаем объект, содержащий две пары ключ/значение. Ключевыми путями являются ticket.customField, за которыми следует двоеточие и другое значение. Некоторые пути могут принимать аргументы, которые вы можете указать, поэтому в этом случае мы специально нацеливаемся на настраиваемое поле на основе его идентификатора. Вы можете узнать больше о запросе пользовательских полей заявки здесь. Также напомню: объект клиента здесь называется zafClient, так как он импортирован из компонента приложения с именем zafClient.
  3. Наконец, у нас есть значение, которое мы обновляем — в данном случае pokeData.name и pokeData.index.

И это все! Пользовательские поля теперь будут отражать данные, которые только что были переданы в пользовательский интерфейс. Теперь, если бы мы хотели получить данные из API в приложение, мы бы использовали метод client.get(). Вот пример из приложения Pokédex:

Давайте посмотрим, что здесь происходит:

  1. Поскольку метод client.get() возвращает обещание, мы создали асинхронную функцию под названием preCheck. В приложении Pokédex эта функция вызывается при монтировании компонента.
  2. Затем у нас есть zafClient.get(), где мы передаем один аргумент пути и присваиваем возвращаемое значение переменной с именем data.
  3. Поскольку ответ является объектом, мы берем фактическое значение пользовательского поля и присваиваем его переменной с именем pokeName.
  4. Наконец, мы проверяем, что pokeName не равно null, и присваиваем значение нашему состоянию.

Теперь наше приложение может проверить, было ли предварительно заполнено настраиваемое поле, и соответствующим образом отобразить соответствующую информацию. Кроме того, с помощью метода client.set() мы можем обновлять настраиваемые поля прямо из нашего приложения одним нажатием кнопки. Классная вещь!

Пользовательские объекты

Как упоминалось ранее в статье, одной из целей создания приложения Pokédex было снижение зависимости от сторонних ресурсов. Итак, хотя у меня были соответствующие данные, необходимые для отображения информации нашим агентам путем доступа к pokeAPI, мне нужен был способ локального хранения этих данных. Это обеспечит надежный доступ к данным и позволит нам вносить любые обновления или изменения по мере необходимости. Введите: Пользовательские объекты.

Согласно документации: API пользовательских объектов позволяет вам определить новый тип объекта в Zendesk, а затем создавать объекты из нового типа объекта. API хранит ваши объекты в инфраструктуре Zendesk. Вы также можете использовать его для определения и управления отношениями с другими объектами, включая собственные объекты Zendesk, такие как заявки и пользователи.

API пользовательских объектов открывает массу возможностей для работы с данными в Zendesk. Основные моменты, которые необходимо знать для целей этой статьи:

  • Типы объектов: план объектов, которые вы создаете. Тип объекта состоит из ключевого атрибута, который представляет собой имя, идентифицирующее тип объекта, и атрибута схемы, описывающего данные.
  • Записи объекта: экземпляр типа объекта. Запись объекта состоит из строки типа, которая соответствует ключевому атрибуту из типа объекта, и объекта атрибутов, который содержит атрибуты, определенные вами в схеме типа объекта.

Здесь — отличная статья, которая покажет вам все, что вам нужно для начала работы с пользовательскими объектами.

Итак, для этого приложения мне нужно было создать тип объекта, который предоставил бы основу для данных, хранящихся в нем, и мне нужно было определить записи объектов, которые в этом случае будут отдельными покемонами и статистикой, которая мне нужна о каждом из них. Прежде всего, давайте посмотрим, как я создал тип объекта, начиная с файла JSON:

Как упоминалось выше, тип объекта — это, по сути, схема для записей объектов, которые вы создаете. Здесь вы увидите, что у нас есть ключевой атрибут pokeData, который идентифицирует тип объекта. Далее у нас есть атрибут схемы, который содержит атрибут свойств. Свойства в основном описывают объект, который вы будете создавать. В этом случае каждый объект может иметь связанное с ним свойство имени, индекса, изображения, высоты и веса. Наконец, мы устанавливаем, какие свойства потребуются при создании записи объекта. Задавать требуемые свойства необязательно, но в данном случае мы потребовали, чтобы в создаваемой нами записи объекта присутствовали по крайней мере свойство имени и индекса. Взгляните на эту ссылку для получения дополнительной информации о создании схемы для типов объектов.

Затем мне нужно было создать тип объекта в моем экземпляре Zendesk. Прежде чем что-либо делать, вам необходимо убедиться, что пользовательские объекты включены в вашей учетной записи. Сделать это можно в центре администрирования → солнечный свет → объекты. Теперь, когда пользовательские объекты включены, вот пример того, как я отправил эти данные:

Успех! Тип объекта создан и готов к работе. Вы также можете просмотреть тип объекта и связанные свойства в центре администрирования. После создания типа объекта следующим шагом будет создание записей объектов для использования в проекте. Нет смысла иметь тип объекта без записей, верно? Вот пример того, как я вытащил все соответствующие данные в качестве записей объектов:

Давайте рассмотрим это шаг за шагом:

  1. Мы создаем асинхронную функцию pokeCall, извлекающую первый пакет данных из pokeAPI и назначающую ответ в формате JSON переменной res.
  2. Затем у нас есть переменная objectList, в которой мы перебираем результаты ответа, используя метод массива более высокого порядка .map. На каждой итерации мы снова вызываем pokeAPI для получения детальных данных от каждой отдельной конечной точки покемонов. Эти данные хранятся в объекте с именем objRec, который был структурирован в соответствии со схемой, которую мы описали в нашем типе объекта. objRec будет выведен в виде массива объектов методом .map.
  3. Наконец, у нас есть objectJob, который содержит данные, которые будут отправлены в API заданий пользовательских объектов для обновления наших записей объектов. Объект имеет тип, действие и свойства данных. Свойство data — это место, где будет храниться наш массив объектов покемонов objectList.

Теперь мне просто нужно было отправить данные в Custom Objects Jobs API. Вот пример того, как это сделать, шаг за шагом:

  1. Мы создали асинхронную функцию setObjectRecords.
  2. Затем мы сохраняем возвращаемое значение функции pokeCall, описанной выше, в переменную с именем payload.
  3. Мы создаем объект параметров, в котором мы определяем настройки для нашего вызова API.
  4. Наконец, мы отправляем данные, используя метод client.request(), который мы рассмотрели ранее в статье. Это создаст идентификатор задания, который вы можете использовать для запроса конечной точки /api/sunshine/jobs/{custom_object_job_id}, чтобы определить результат задания. Вы можете узнать больше о Custom Objects Jobs здесь.

И это все! Я определил пользовательский тип объекта, который затем заполнил записями объектов на основе данных, которые мы получили из pokeAPI. Это гарантировало, что у меня был доступ к данным локально, и я мог вносить изменения и обновления в записи объектов по мере необходимости.

Резюме

Итак, давайте пройдемся по целям из начала статьи и посмотрим, как мы это сделали:

  1. Интегрируйте данные в приложение сначала с помощью внешних API, а затем с помощью пользовательских объектов ✅
  2. Разрешить интеграцию между приложением и экземпляром Zendesk ✅
  3. Интуитивно понятный пользовательский интерфейс с использованием боковой панели билетов ✅

Хороший! Отмечены все флажки, которые были установлены в начале 🎉 После завершения сборки последним шагом в процессе является загрузка и установка приложения в вашей учетной записи. Подробные инструкции о том, как загрузить и установить приложение Zendesk, см. в этой замечательной статье из нашего руководства по началу работы.

Фреймворк Zendesk Apps предоставляет массу вариантов гибкости для взаимодействия с Zendesk и API. Здесь мы лишь коснулись того, что возможно, но, надеюсь, это дало вам некоторое представление о том, что вы можете делать с помощью доступных инструментов, я имею в виду, кто бы мог подумать, что Zendesk Pokédex — это вещь! Если вы хотите ознакомиться с проектом полностью, вот ссылка на репозиторий GitHub.

Следите за будущими статьями на более интересные темы, и если у вас есть какие-либо вопросы или пожелания, не стесняйтесь комментировать ниже!