Русский
Русский
English
Статистика
Реклама

Airtable

Делаем страницу на React с базой сотрудников при помощи Airtable и Quarkly

31.01.2021 16:07:40 | Автор: admin

Слышали про такой инструмент, как Airtable, но не знали, с чего начать? Тогда приглашаем в мир визуального программирования построения БД!


Этим постом мы начинаем цикл обучающих статей, в которых будем давать практические примеры работы с нашим инструментом Quarkly. В этом уроке мы сделаем простое веб-приложение, которое будет показывать сотрудников компании. При создании приложения ни один сотрудник РЖД не пострадал.


Фронт будем делать при помощи Quarkly, а данные подтягивать из базы в Airtable. На выходе получим react-приложение, синхронизированное с базой данных.



Преамбула. Почему Airtable


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


Если вы впервые слышите про Airtable, перед началом работы не будет лишним почитать официальное руководство на сайте компании. Также советуем не стесняться и задавать вопросы в чатике Airtable Chat & Community в телеграм.


Фронтендная часть работ будет сделана в Quarkly, и для этого мы будем использовать всего два компонента:


  • Карточка сотрудника. В ней будут фото, текстовые данные и две кнопки: отправить email и позвонить. Эти данные карточка будет получать от родительского компонента обертки.
  • Обертка. Она будет принимать данные из Airtable, генерировать карточки и передавать в них данные.

Для тех, у кого нет времени вникать в пост в печатном формате, мы подготовили видео с субтитрами и таймкодами:




Часть 1. Делаем визуал в Quarkly


Создание карточки:


  1. Создадим новый проект в Quarkly, назовем его Airtable Example;
  2. Перейдем внутрь проекта;
  3. Добавим готовый блок с карточками сотрудников. Для этого кликаем на черную кнопку + посередине и выбираем блок из категории Team;



  4. Выбираем на панели слоев первую карточку (StackItem) и преобразуем её в компонент;



    Для этого нажмите на троеточие и выберите пункт Convert to Component. Назовем этот компонент EmployeeCard.

  5. Теперь мы можем свободно редактировать код этого react-компонента, но пока этого делать не будем и перейдем к созданию компонента-обертки.

Создание обертки:


  1. Подготовим обертку к преобразованию в компонент. Для этого сначала удалим оставшиеся три карточки, они нам не нужны;

  2. Теперь вытащим EmployeeCard из Stack. Затем преобразуем Stack в компонент, как мы уже делали ранее с EmployeeCard: правая панель, кнопка троеточие и Convert to Component. Компонент назовем EmployeeTable.



    На этом пока всё, подготовительный этап завершен. Оставим компоненты и займемся базой в Airtable.


Часть 2. Создаем базу данных в Airtable


Переходим на сайт Airtable и регистрируемся/авторизуемся.


  1. Кликаем на кнопку Add a base, чтобы создать новую базу. Из выпадающего меню выберите пункт Start with a template;

  2. Выбираем категорию HR & Recruiting и шаблон Employee directory. Далее кликаем на кнопку Use template;

  3. Переходим в созданный проект;


На данном этапе здесь мы ничего менять не будем, в текущем виде база уже нас устраивает.



Часть 3. Получаем доступ к API


Изначально Airtable интересен для нас именно за счет удобного API. При этом, что немаловажно, возможность забирать данные и отправлять их в нашу базу Airtable предоставляет бесплатно.


  1. Переходим на страницу выбора API проектов: https://airtable.com/api

  2. Выбираем наш проект Employee directory. В появившейся документации переходим на раздел AUTHENTICATION.

  3. Скопируйте две строчки, расположенные ниже заголовка EXAMPLE USING BEARER TOKEN (RECOMMENDED).

    У меня они выглядят так:

    $ curl https://api.airtable.com/v0/app2MdLITmRTBsrkg/Employee%20directory \
    -H "Authorization: Bearer YOUR_API_KEY"
  4. Теперь нам нужен YOUR_API_KEY. Это уникальный ключ доступа, который генерируется для каждого аккаунта. Найти его можно в настройках.

  5. На открывшейся странице перейдите в раздел API и нажмите на кнопку Generate API key;

  6. Скопируйте ключ. Сохраните его рядом со строчками из пункта 3. Они пригодятся нам далее.


Часть 4. Интегрируем базу Airtable в Quarkly


На этом этапе мы добавим в компонент EmployeeTable код, который будет забирать данные из API.


  1. Переходим в редактирование кода компонента. Для этого откроем вкладку Components и нажмем на кнопку <> у EmployeeTable (она появится при наведении курсора на компонент);

  2. Сейчас код компонента выглядит так:

  3. Заменим:

    import React from "react";
    

    на:

    import React, { useEffect, useState } from "react";
    

    Таким образом мы импортируем хуки useEffect и useState, которые помогут нам в дальнейшем;
  4. Ниже добавляем строчку, чтобы импортировать наш компонент EmployeeCard:

    import EmployeeCard from "./EmployeeCard";
    
  5. Заменим children (они нам пока не нужны) на override (пригодятся, чтобы выбирать элементы и стилизовать их на странице):

    const EmployeeTable = props => {const {children,rest} = useOverrides(props, overrides, defaultProps);
    

    на:

    const EmployeeTable = props => {const {override,rest} = useOverrides(props, overrides, defaultProps);
    
  6. Ниже добавим вызов хука useState, который будет следить за состоянием:

    const [employees, setEmployees] = useState([]);
    
  7. Далее добавим хук useEffect, который будет делать запросы к API Airtable и помещать полученные данные в наше состояние через функцию setEmployees.

    Добавляем сюда строчки, которые скопировали ранее. В fetch мы добавляем URL адрес нашей базы, добавляя параметр ?view=All%20employees. В headers мы добавляем параметры авторизации и непосредственно сам API ключ, который мы сгенерировали в 3 части этой статьи, подпункт 4.

    useEffect(() => {fetch("https://api.airtable.com/v0/appWw7KBKSc9bPjZE/Employee%20directory?view=All%20employees", {headers: {'Authorization': 'Bearer YOUR_API_KEY'}}).then(response => response.json()).then(data => setEmployees(data.records.map(({ fields }) => fields)));}, []);
    
  8. Теперь будем генерировать карточки из полученных данных, передавая им props с данными и override. Он нужен, чтобы выбирать и стилизовать элементы на странице.

    Меняем:

    return <Stack {...rest}>{children}</Stack>;};
    

    на:

    return <Stack {...rest}>{employees.map(employee => <EmployeeCard  {...override("employeeCard")}  employee={employee} />)}</Stack>;};
    
  9. Нажмите Ctrl + S (или Cmd + S на Mac). Окончательный код выглядит так:

    import React, { useEffect, useState } from "react";import { useOverrides, Stack } from "@quarkly/components";import EmployeeCard from "./EmployeeCard";const defaultProps = {"margin-top": "40px"};const overrides = {};const EmployeeTable = props => {const {override,rest} = useOverrides(props, overrides, defaultProps);const [employees, setEmployees] = useState([]);useEffect(() => {fetch("https://api.airtable.com/v0/appWw7KBKSc9bPjZE/Employee%20directory?view=All%20employees", {headers: {'Authorization': 'Bearer YOUR_API_KEY'}}).then(response => response.json()).then(data => setEmployees(data.records.map(({ fields }) => fields)));}, []);return <Stack {...rest}>{employees.map(employee => <EmployeeCard  {...override("employeeCard")} employee={employee} />)}</Stack>;};Object.assign(EmployeeTable, {...Stack,defaultProps,overrides});export default EmployeeTable;
    

    Важно: не забудьте вставить свой уникальный API ключ вместо текста YOUR_API_KEY.

Готово! Теперь мы получаем данные от Airtable, помещаем их в employees и проходимся по нему методом map. На каждую запись в employees мы создаем <EmployeeCard/>, в который передаем как пропс конкретные данные.


Осталось научить EmpolyeeCard принимать эти данные и показывать их в нужном месте.



Часть 5. Учим EmpolyeeCard работать с БД


Здесь мы научим карточку сотрудника принимать данные и показывать их.


  1. Откроем код компонента. Для этого заходим во вкладку Components, ищем там EmployeeCard, наводим курсор и жмем на кнопку <>.
  2. Сейчас код компонента выглядит так:

    import React from "react";import { useOverrides, Override, StackItem } from "@quarkly/components";import { Box, Text } from "@quarkly/widgets";const defaultProps = {"width": "25%","lg-width": "50%","sm-width": "100%"};const overrides = {"box": {"kind": "Box","props": {"height": "0","margin": "0 0 20px 0","padding-bottom": "100%","background": "url(http://personeltest.ru/aways/images.unsplash.com/photo-1503443207922-dff7d543fd0e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=582&q=80) 50% 0/cover no-repeat"}},"text": {"kind": "Text","props": {"color": "--grey","margin": "0","children": "CEO"}},"text1": {"kind": "Text","props": {"as": "h3","font": "--headline3","margin": "5px 0 20px 0","children": "Nathan K. Joe"}},"text2": {"kind": "Text","props": {"as": "p","margin": "20px 0 5px 0","children": "This space is 100% editable. Use it to introduce a team member, describe their work experience and role within the company. This is also a great place to highlight a team member's strong sides."}}};const EmployeeCard = props => {const {override,children,rest} = useOverrides(props, overrides, defaultProps);return <StackItem {...rest}><Override slot="StackItemContent" flex-direction="column" /><Box {...override("box")} /><Text {...override("text")} /><Text {...override("text1")} /><Text {...override("text2")} />{children}</StackItem>;};Object.assign(EmployeeCard, { ...StackItem,defaultProps,overrides});export default EmployeeCard;
    
  3. Ищем строчку:

    } = useOverrides(props, overrides, defaultProps);
    

    и добавляем ниже:

    const { employee = {} } = rest;
    

    В объект employee помещаем наши данные.
  4. На примере фотографии сотрудника проверим, что всё работает, как нужно. Ищем строку и меняем:

    <Box {...override("box")} />
    

    на:

    <Box {...override("box")} background-image={`url(${employee.Photo && employee.Photo[0] && employee.Photo[0].url})`}/>
    

    Также ищем:

    "background": "url(http://personeltest.ru/aways/images.unsplash.com/photo-1503443207922-dff7d543fd0e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=582&q=80) 50% 0/cover no-repeat"
    

    и меняем на:

    "background-size": "cover","background-position": "center","background-image": "url(http://personeltest.ru/aways/images.unsplash.com/photo-1503443207922-dff7d543fd0e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=582&q=80) 50% 0/cover no-repeat"
    

    Должно получится так:

  5. Смотрим, какие поля у нас есть. Документация для API в Airtable сделана очень хорошо. Название полей можно посмотреть в https://airtable.com/api, выбрав свою базу.

    Далее ищем раздел EMPLOYEE DIRECTORY TABLE.

    Итак, у нас есть:

    Name
    Department
    Home address
    Email address
    DOB
    Start date
    Phone
    Reports to
    Title
    Status
    Photo
    Location
  6. Добавим Title. Для этого заменим:

    <Text {...override("text")} />
    

    на:

    <Text {...override("title")} children={employee.Title} />
    

    И не забудем отредактировать overrides этого компонента, чтобы мы могли его выбирать и редактировать на странице.

    Меняем:

    "text": {"kind": "Text","props": {"color": "--grey","margin": "0","children": "CEO"}},
    

    на:

    "title": {"kind": "Text","props": {"color": "--grey","margin": "0","children": "Title"}},
    

    Сохраняем и проверяем:



    Результат: в карточки добавилась строка с профессией.
  7. Повторим такие же действия для Name и Home address.

    Заменим:

    <Text {...override("text1")} /><Text {...override("text2")} />
    

    на:

    <Text {...override("name")} children={employee.Name} /><Text {...override("address")} children={employee['Home address']} />
    

    И поправим их overrides. Для этого заменим:

    "text1": {"kind": "Text","props": {"as": "h3","font": "--headline3","margin": "5px 0 20px 0","children": "Nathan K. Joe"}},"text2": {"kind": "Text","props": {"as": "p","margin": "20px 0 5px 0","children": "This space is 100% editable. Use it to introduce a team member, describe their work experience and role within the company. This is also a great place to highlight a team member's strong sides."}}
    

    на:

    "name": {"kind": "Text","props": {"as": "h3","font": "--headline3","margin": "5px 0 5px 0","children": "Name"}},"address": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Home address"}},
    

    Сохраняем и снова проверяем:

  8. Добавим ещё несколько Text по аналогии. Для простоты мы не будем брать Department и Reports to, потому что эти данные находятся в другой базе DEPARTMENTS TABLE.

    Добавляем:

    <Text {...override("address")} children={employee['Home address']} /><Text {...override("Start date")} children={`Start date: ${employee['Start date']}`} /><Text {...override("Status")} children={employee['Status']} /><Text {...override("DOB")} children={`Birth date: ${employee['DOB']}`} />
    

    и

    "address": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Home address"}},"Start date": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Start date"}},"Status": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Status"}},"DOB": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Birth date"}},
    

    Проверяем результат:

  9. Теперь добавим два компонента Link, в которых у нас будут Phone и Email:

    import { Box, Text } from "@quarkly/widgets";
    

    меняем на:

    import { Box, Text, Link } from "@quarkly/widgets";
    

    И добавляем следующие строки:

    <Link {...override("Email address")} children={employee['Email address']} href={`mailto:${employee['Email address']}`} /><Link {...override("Phone")} children={employee['Phone']} href={`tel:${employee['Phone']}`}/>
    

    Не забыв про их overrides:

    "Email address": {"kind": "Link","props": {"margin": "10px 0 5px 0","color": "--primary","text-decoration": "none","children": "Email"}},"Phone": {"kind": "Link","props": {"margin": "10px 0 5px 0","color": "--primary","text-decoration": "none","children": "Phone"}},
    

    Проверяем результат:


Финально наш код выглядит так:

import React from "react";import { useOverrides, Override, StackItem } from "@quarkly/components";import { Box, Text, Link } from "@quarkly/widgets";const defaultProps = {"width": "25%","lg-width": "50%","sm-width": "100%"};const overrides = {"box": {"kind": "Box","props": {"height": "0","margin": "0 0 20px 0","padding-bottom": "100%","background-size": "cover","background-position": "center","background-image": "url(http://personeltest.ru/aways/images.unsplash.com/photo-1503443207922-dff7d543fd0e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=582&q=80) 50% 0/cover no-repeat"}},"title": {"kind": "Text","props": {"color": "--grey","margin": "0","children": "title"}},"name": {"kind": "Text","props": {"as": "h3","font": "--headline3","margin": "5px 0 5px 0","children": "Name"}},"address": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Home address"}},"Start date": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Start date"}},"Status": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Status"}},"DOB": {"kind": "Text","props": {"as": "p","margin": "10px 0 5px 0","children": "Birth date"}},"Email address": {"kind": "Link","props": {"margin": "10px 0 5px 0","color": "--primary","text-decoration": "none","children": "Email"}},"Phone": {"kind": "Link","props": {"margin": "10px 0 5px 0","color": "--primary","text-decoration": "none","children": "Phone"}},};const EmployeeCard = props => {const {override,children,rest} = useOverrides(props, overrides, defaultProps);const { employee = {} } = rest;return <StackItem {...rest}><Override slot="StackItemContent" flex-direction="column" /><Box {...override("box")} background-image={`url(${employee.Photo[0].url})`}/><Text {...override("title")} children={employee.Title} /><Text {...override("name")} children={employee.Name} /><Text {...override("address")} children={employee['Home address']} /><Text {...override("Start date")} children={`Start date: ${employee['Start date']}`} /><Text {...override("Status")} children={employee['Status']} /><Text {...override("DOB")} children={`Birth date: ${employee['DOB']}`} /><Link {...override("Email address")} children={employee['Email address']} href={`mailto:${employee['Email address']}`} /><Link {...override("Phone")} children={employee['Phone']} href={`tel:${employee['Phone']}`}/>{children}</StackItem>;};Object.assign(EmployeeCard, { ...StackItem,defaultProps,overrides});export default EmployeeCard;

Делаем коммит в GitHub и публикуем на Netlify:





Ждем несколько минут и проверяем: https://keen-varahamihira-c54ae1.netlify.app/



Для проверки синхронизации меняем данные в базе:


Теперь они появятся в приложении:


В дальнейшем мы можем как угодно стилизовать наши элементы с карточками, не нарушая настроенный импорт из Airtable. Пример можно посмотреть здесь.


Репозиторий на GitHub: https://github.com/quarkly-dev/Getting-data-from-Airtable-tutorial


Спасибо за внимание!


Если у вас остались вопросы не стесняйтесь задавать их в комментариях. В следующем уроке рассмотрим ещё один пример работы с данными, покажем как интерактивно их визуализировать, дав возможность пользователю менять фильтры прямо в приложении.

Подробнее..

Бот в инструментах no code. Детали реализации

18.06.2020 12:21:50 | Автор: admin
Продолжаем экспериментировать с парадигмой no code (и отчасти low code).
Собрали чатбота, помогающего дочитывать большие архивы статей.
В статье расскажем, какие инструменты взяли и на какие их ограничения наткнулись.

image

Материал для статьи и проект собраны вместе с roman_nebel.

Disclaimer. Да, нам тоже проще написать чистым кодом. Но суть nocode-упражнения именно в том, чтобы собирать полезные сервисы из готовых инструментов. Начали давно, продолжаем, нравится. Постепенно обо всём расскажем.

Аудитории Хабра, видимо, интересны технические, а не продуктовые подробности. Если о продуктовом слое работы в no code проектах без погружения в детали реализации тоже есть смысл рассказывать дайте знать в комментариях.

Что хотели сделать


Хотели помочь людям (и себе):

  • приучить читать на английском;
  • уходить на обед: Вот статья, почитаешь за столом.


Делать такой микропродукт решили через Telegram-бота:

  1. Раз в день присылает ссылку на статью из архива. Для пробы раздербанили архив статей про дизайн ReadingDesign. Будет ещё.
  2. Спрашивает читателя, понравилась статья или нет. Результаты складываем, копим данные, потом сможем найти самые интересные статьи и оценить активность пользователей.

Бота можно щупать: @bracho_read_bot
Баги есть. Идеи по фичам тоже есть. И план нового релиза есть.
Короче, всё есть, но много не мало, так что кидайте и свои мысли.

Что использовали

Chatforma. Один из многих (выбирали) конструкторов для чатов. Не идеальный, но хоть как-то делает что нужно. О выборе ниже.

Integromat. Передаёт данные туда-сюда по правилам и с условиями. Выбор по умолчанию для no code проектов.

Airtable. База данных с продвинутым интерфейсом и хорошей интеграцией с другими инструментами. Тоже выбор по умолчанию (а ещё мы её давно используем в автоматизации своих бизнес-процессов, но это другой разговор).

Детали по инструментам

Bot Father

Для начала нам нужен сам бот, точнее аккаунт для него в Telegram. Самый простой способ найти Отца Ботов (@BotFather) в Телеграм и в нем зарегистировать нового бота. Пошаговое описание гуглится на любой вкус, если в двух словах: придумываем имя бота, его логин и все. После успеха вам придет токен (ключ для идентификации и связи бота с внешним миром), который и был нам нужен на этом этапе.

Chatforma

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

Самый распространенный паттерн: пришел покупатель, с ним поздоровались, спросили, что нужно, облизали и начали навязчиво рассылать спам. Все это делается с помощью простых текстовых развилок и интеграции данных (например, с Битрикс24). Никакого интерактива.

Конечно, есть и решения вроде DialogFlow на Google Cloud, но чем в них разобраться, проще написать все ручками. Поэтому берем вариант попроще.

Взяли Chatforma. Из всего не такого уж многообразия у него у одного есть хоть какое-то API и поддержка Webhook. А раз так, то мы сможем доверить чатбот-платформе функцию непосредственно отправки, а логику настроить где-то в другом месте.

Да, предыдущий no code проект мы делали на AIMyLogic. К сожалению, интеграция с внешними сервисами у него устроена на ноль с плюсом. Так что увы, не в этот раз.

Airtable

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

Да, можно было и в Google Таблицах (на них мы уже сделали и эксплуатируем коммерческий no code проект, внезапно это дизайн-задачник). И в SQL можно было. И много где еще.

Причин выбора Airtable две: он приятный на мордочку и замечательно интегрируется со всем и вся. Получаешь токен API прямо в приложении и гоняешь данные в обе стороны как хочешь и где хочешь. Легко и приятно. А мы хотели, чтобы легко и приятно хоть где-нибудь и в чём-нибудь.

Integromat

И, наконец, мозги. Сложно назвать преимущества перед тем же Zapier, тут чистая вкусовщина. Мы уже использовали Integromat в предыдущих проектах, он как-то привычнее. Кстати, собирали список статей из архива мы тоже с помощью него.

Немного суровой коммерции

Все инструменты разной степени платности. Нас не парят микроплатежи в пределах 1000 рублей в месяц. В конце концов, для нашей мегакорпорации это посильные деньги. Но да, если для вас бесплатность инструментов это дело принципа, то в no code игрушки лучше не играть, там почти за всё приходится отстёгивать копеечку.

Как мы это сделали

Базовые настройки

Задача 0 в Chatforma завести нового бота, чтобы он просто был. Регистрируемся на платформе, радуемся, что у нас всего 14 бесплатных дней. Заходим во вкладку боты и находим заветную кнопку Добавить бота. Называем его (имя только для Chatforma, сам бот уже назван) и выбираем соцсеть (Telegram).

После этого сразу идем в нового бота и в разделе настройки прописываем тот самый токен, который дал нам Отец Ботов, без этого ничего работать не будет.
image
Настройка для токена спрятана хорошо, надо еще поискать

Первое, что должен сделать уважающий себя ботостроитель научить бота здороваться. Все просто: идем в Конструктор и видим два заготовленных сообщения: стартовое и по умолчанию. В чем разница: первое это сообщение придет, если вы только запустили бота (нажали Старт). Второе это универсальная заглушка на любое сообщение, которое бот не понимает.image
А еще там можно добавлять инлайн-клавиатуру, но это уже совсем баловство

Собираем пользователей

Для учёта статистики и раздачи уникальных ссылок каждому нам понадобится список пользователей, запустивших бота. Он есть в разделе Пользователи, но практической пользы не несет никакой, кроме возбуждения эго количеством подписавшихся.
image
По шапке таблицы можете легко определить ее полезность

Нам пригодится Integromat, Airtable и API запрос. В Integromat этим запросом вытаскиваем список пользователей и записываем в нужную таблицу в Airtable. Чтобы не плодить дубли, перед записью проверяем на наличие пользователя в таблице по ID. Если такой уже есть отсеиваем, остальных записываем.
image
Отдельный фетиш в Integromat пытаться там все выровнять

Настраиваем рассылку

Дальше интереснее. Нам нужно каждый день генерировать рассылку по всем участникам, вставляя туда рандомную ссылку из Airtable. А еще лучше рандомную ссылку каждому. А еще лучше что-нибудь написать перед ней. Что-то персональное и не повторяющееся каждый день. Идем в раздел Рассылки в надежде воплотить задуманное Все очень плохо.
image
Сейчас объясним, почему

Дело вот в чём. Chatforma умеет создавать два вида рассылок: обычные и авторассылки. Первые подойдут, если нужно единоразово отправить всем (или некоторым) участникам определенный текст, картинку, опрос и так далее. Второй позволяет настроить рассылку по расписанию и дням недели, но функционал отправки ограничен только текстом и медиа, опросы так отправлять нельзя.
image
Просто рассылка

image
Авторассылка

Вернемся к рассылке. То, что предлагает платформа, нам не подходит. Мы не можем сделать персонализированную рассылку и динамически вставлять туда любую информацию. Только заранее заготовленную. А ручками это делать не хочется. Когда у бота два пользователя, это еще ничего, но если их уже три Поэтому решаем проблему с помощью Integromat.

Создаем сценарий со следующей логикой: Получаем список статей из Airtable Оттуда же берем список пользователей, который мы занесли туда ранее Каждый пользователь проходит итерацию, где генерируется рандомное число и статья под таким номером строки отправляется через POST-запрос в Chatforma. Для этого пришлось залезть в документацию к API и найти там нужный метод.

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

Еще нам нужно имитировать интерактив с сообщениями, предшествующими ссылке. Добавляем в базу варианты сообщений и формируем итоговое, используя имя пользователя в телеграмме, рандомную фразу и рандомную ссылку.
image
Вариация на тему бизнес-логики

Вот что после этого происходит на стороне Chatforma. Когда Integromat отправил сообщение, Chatforma его получает и формирует единичную рассылку для конкретного пользователя. В тексте все тоже, что сформировал Integromat. Вроде работает.

Тут же обнаружилась проблема: мало того, что есть задержка при получении данных извне, так еще и Chatforma долго (до 15 минут) проводит уже сформированные рассылки. Получается, что десятичасовая рассылка может прийти и в 10:01 и в 10:16, Техподдержка этот феномен изучала 4 дня и без особых успехов.
image
Но поддержка отзывчивая, и это приятно

Голосовалка

Ссылку все получили, кто-то даже прочитал содержимое. Теперь нужно эту статью оценить. У API Chatforma есть два ограничения, которые не дают нам простора для творчества: мы можем в сторонние сервисы отправлять только ответы, полученные из такой сущности, как Опрос. По API мы можем возвращать только текст, нужный нам опрос мы можем создать только внутри Chatforma, а значит можем пользоваться только теми видами рассылки, который описали ранее.

В итоге сделали следующее: расплодили опросы о качестве статьи на каждый день для всех подписчиков, поставили его на 11:00. После того, как пользователь проголосует, результат через webhook уходит в Integromat, и на основании ответа последней присланной статье для нужного пользователя проставляются баллы. Подсчет такой: за Огонь +1 балл проголосовавшему и +1 балл статье, за Не очень -1 балл статье и +1 пользователю. За Не читал ничего. Еще планировали отправлять пользователю сообщение-отбивку после голосования, но от этой идеи отказались. Потому что скорость доставки в духе Почты России в её лучшие годы.
image
В это голосование ЕР не вмешается

Итого по инструментам

Airtable

Никаких проблем при интеграции, записи и получении данных.

Integromat

Сервис хорошо справляется с линейными операциями. Если появляется логика if/else и сравнение данных, схема получается достаточно запутанной. Но работает.
Приходится много оптимизировать процессы, так как все тарифы ограничены по количеству выполненных элементов.

Chatforma

Сервис сырой, есть много недоработок, они злят. При этом очень хорошо организована техподдержка, она оперативная и достаточно компетентная. Большое количество инструкций и вебинаров по функционалу, они актуальные.

Найденные недостатки.
  1. Ограничение видов контента в зависимости от вида рассылки.
  2. Содержание рассылки, направленной через API, ограничено только текстом.
  3. Webhook умеет отправлять только результаты опроса, а не любые действия пользователя.
  4. Большая задержка при отправке рассылок.
  5. Баги с задержкой внесения изменений после сохранения.
  6. Лог не хранит присланные пользователем сообщения, только ответы на опросы.
  7. Заплатить за сервис целый квест, и нужно очень хотеть, чтобы его пройти.


Вопросы к вам


  1. Бота можно щупать: @bracho_read_bot и конечно, просим репортить о багах и предлагать фичи.
  2. Какие ещё архивы англоязычных статей зашить в бота? Кое-что уже отобрали, хотим ещё.
  3. Продуктоведы, вы тут есть? Вам о продуктовой части no code рассказывать или ну его и сами с усами?
  4. Набор no code инструментов. Есть ли что получше для этой задачи? Конечно, в кандидатах на вылет в основном Chatforma.
Подробнее..

HR-автоматизация за один день как экономить 8 часов в неделю на рекрутинге

15.12.2020 18:16:33 | Автор: admin
Привет, Хабр. Меня зовут Шагане Мирзоян, я отвечаю за продуктовую аналитику в СберМаркете. Мы с командой следим за тем, что происходит с нашим пользователем на сайте и в приложении, и ищем в этом процессе точки роста. Сегодня я расскажу, как мы пережили рост сервиса в 15 раз за 2020 год, а рост команды с 6 до 29 человек за 6 месяцев.

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

Почему у нас нет стартового собеседования с рекрутером? Обычно такие нужны при поиске ребят младших позиций и призваны для того, чтобы отобрать самых классных. Мы решаем эту задачу иначе и отбираем самых мотивированных ребят тестовым заданием, которое помогает экономить время HR и ускорять подбор. Так ни нам, ни кандидату не придется ожидать свободного слота в календаре менеджера по персоналу.

Если все так классно, то к чему вообще это статья? Когда ты быстро растешь, то рискуешь так же быстро терять отклики из-за плохо отлаженных процессов. Это случилось и с нами. Под катом рассказываю, как мы решили эту проблему с помощью простой автоматизации.





Раньше процесс подбора новичков был устроен просто. Отклики летели на нашу общую почту команды. На первый взгляд это отличное решение:

  • Все в одном месте.
  • Любой член команды аналитики может просмотреть CV и дать фидбек.
  • Push-уведомления при новых откликах мы всегда в курсе, что происходит.
  • Когда в команду требуется 2-3 новых члена в год, это очень удобно. Но если количество коллег растет по экспоненте (в какой-то момент мы стали получать по 1000 писем в неделю), общая почта сплошной бардак
  • Отклики на разные вакансии перемешиваются (теперь все в одном месте не такой уж и плюс).
  • Google очевидно завидует вашему кратному росту и ругается, когда в аккаунт пытаются зайти с десятка разных устройств. В итоге получение доступа к почте становится квестом.
  • Кто-то может случайно открыть чужое письмо и отклик потерян, а по ту сторону экрана грустит расстроенный кандидат.




Просуммирую: так историю изменений непросто найти, а кандидатов легко потерять. Хочется, конечно, наоборот.

Автоматизация на коленке


Решить проблему нам помогли два облачных сервиса: конструктор баз данных Airtable и Zapier, клей для наших костылей. Если вы зерокодер, то вы наверняка про них слышали.

В Airtable можно создать view по определенным условиям, например, показать только те записи, которые были созданы вчера. Zapier умеет в качестве триггера принимать появление новой записи в отдельном view. Таким образом, мы можем построить цепочку Если произошло событие Х, то нужно сделать действие Y.
Кастомизировать эти истории под себя можно сколько угодно этим мы и занялись. Теперь у нас появилась своя CRM-ка с кандидатами. Соискатели и их тестовые задания лежат в одном месте с привязкой к вакансии и статусу. Отклики приходят не на почту в Google, а в таблицу, как и любят все аналитики :). Бонусом буквально в пару кликов с помощью такого же принципа можно настроить пуши в Slack. Это помогает нам следить за прогрессом и вовремя отвечать соискателям. Бот тэгает только ownerа вакансии и не отвлекает остальных членов команды.

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



Как это выглядит на примере воронки джуна



  1. Общая форма для всех вакансий. Кандидат выбирает, на что хочет откликнуться, пишет короткое сопроводительное письмо, прикрепляет CV.
  2. Ответ после отклика уходит автоматически это красивое сверстанное письмо с приветствием, ссылкой на тестовое и кнопкой отправить работу. Ссылка на задание вставляется динамически и может отличаться для разных вакансий. Кнопка с сабмитом тоже хитрая, об этом ниже.
  3. В Airtable появляется карточка со всеми данными по отклику.
  4. В наш канал в Slack падает уведомление о новом кандидате и тегом owner-а вакансии (я знаю, что вы уже догадались, что тег тоже подтягивается динамически). В один клик мы можем получить об отклике всю доступную информацию.




Фронт и бэк откликов :)

5. После того, как кандидат сделал тестовое, он отправляет его через форму из письма. Тестовые задания лежат в другой таблице, но мы научились связывать их с помощью prefill_ тегов в URL, которые заботливо добавляем кандидатам в адрес формы на шаге 2.



Для каждого отклика у нас есть SLA-отбивка. Например, мы обещаем вернуться с фидбеком на тестовое задание в течение трех рабочих дней. Мы создаем ожидания у кандидатов и должны им соответствовать, поэтому в тот же Slack приходят автоматизированные алерты для ownerа вакансии, если тот опаздывает с ответом Оговорюсь, что иногда мы все-таки факапим: теряем кандидатов или отвечаем позже обещанного срока. Здесь всегда есть человеческий фактор, но автоматизация позволила значительно его снизить и ошибаться реже.

Оговорюсь, что иногда мы все-таки факапим: теряем кандидатов или отвечаем позже обещанного срока. Здесь всегда есть человеческий фактор, но автоматизация позволила значительно его снизить и ошибаться реже.



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



Результат 8 свободных часов в неделю



Это достаточно усредненная цифра. Она зависит от вашего количество откликов, но оценить его просто. Минимум 5 минут с каждого отклика уходит на переключение контекстов и интерфейсов (со вкладки с тестовым кодом в gmail, с отвеченного письма на неотвеченное и так далее). Когда у тебя 100 тестовых заданий, эти минуты превращаются в часы.

Сама автоматизация заняла у нас часов пять. Если вы никогда не работали с Airtable и Zapier, знакомство с функционалом займет у вас еще день или два. В общем, у вас есть все вводные, чтобы оценить возврат инвестиций от этой затеи и принять решение о том, нужна ли вам такая автоматизация.

Посыл всего поста экономьте время и хакайте рутину. Например, если вы хотите классно сверстанное письмо, то вам не обязательно просить знакомого html-разработчика или оставлять свою почту на съедение онлайн-конструкторам писем при регистрации. Ваша компания наверняка уже отправляет кучу писем клиентам, в том числе и вам. Откройте такое письмо, загляните в код страницы и вытащите html. Все, что осталось поменять текст и ссылки на нужные вам. Готово вы великолепны.



Для этого поста мне даже не пришлось считать воронку. Все можно сделать силами того же Airtable

P.S.
А ещё мы продолжаем расширять команду Data & Growth СберМаркета и ищем новых коллег! Наши вакансии:

Middle Product Analyst
Middle/Senior DS на персонализацию сервиса
Marketplace Efficiency Analyst
Junior Finance Analyst
Middle Finance Analyst
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru