Автор оригинала: FreeCodeCamp Community Member.
Даниэль Ирсон
Я недавно наткнулся на Скрипты Apps Google , платформа, которая позволяет пользователям расширить G Google G Suite On Online Products через язык сценариев, полученного из JavaScript. Это аналогично VBA , который встроен в большую часть продуктов Microsoft Office.
Сценарии Apps Google невероятно мощные и включают в себя сложные системы, которые будут построены сверху Google Services. Это может быть отличным выбором, когда вам нужно быстро прототип идеи или разработать решение, настраиваемое нетехническими пользователями. Отличный способ сделать доступное решение – построить поверх продукции, с которыми пользователи уже знакомы.
В этой статье я пройду через простой новый пример создания «системы управления контентом» (CMS) для онлайн-блога с использованием листов Google, Google Forms и Script Poogle App.
Блог будет разработан как приложение одним страницей с Pagination и возможность фильтрации по категории Post. Сообщения в блоге будут храниться в электронной таблице Google Pailets. Новые сообщения будут добавлены через Google Forms, поскольку он предоставляет удобный интерфейс. Сценарий приложений Google будет использоваться для создания API, чтобы сделать содержимое электронной таблицы доступным в простой в использовании формате.
Отказ от ответственности
Я не использую это в производстве, и я понятия не имею, если он будет масштабироваться. Подумайте об этом как о доказательстве концепции, чтобы показать, что возможно. Вы должны выполнять свои собственные исследования, если вы хотите использовать его в производственной среде. Я подозреваю, что трафик будет включен, если вы попадете возле верхних пределов квот услуг. Там жесткий предел 20 000 URL Petches В день на сценариях для бесплатных учетных записей Google, и на месте также могут быть и другие ограничения.
Хранение данных
Листы Google будут использоваться в качестве базы данных Flat-файлов для хранения сообщений в блоге. База данных плоских файлов хранит данные в простом тексте в одной таблице. Напротив, реляционная база данных захватывает отношения между таблицами и обеспечивает структуру этих отношений, чтобы минимизировать дублирование и максимизировать целостность данных.
Хотя более ограниченный, плоская структура файла легко начать и подходит для нашего использования в случае небольшого блога.
Структура электронной таблицы
Каждая строка будет представлять собой новый пост блога, а столбцы будут использоваться для захвата отдельных полей полей блога. В структуре flat-файлов нет концепции первичных и внешних ключей, таких как в реляционной модели. Информация, которая захвачена в столбцах, таких как категория и автор, будет дублирована по сообщениям в блоге, когда общие.
Начиная
Создайте новую электронную таблицу Google Pailets и подключите его к Google Forms, собираясь на Инструменты> Создать fo RM в строке меню. После выбора этой опции вы будете представлены редактором для определения вопросов формы. Они сопоставлены на столбцы электронных таблиц.
Для моей демонстрации я добавил четыре вопроса для Название , Категория , Автор, и Содержание Отказ
У каждого поля был тип текста, кроме Категория , который был радиоприемником с четырьмя гипотетическими категориями: общий, маркетинг, финансовые, технологии.
Когда представление формы производится, на электронную таблицу листов Google прилагается ряд. А Timestamp Поле автоматически добавляется для каждой строки, которую мы будем использовать для расчета даты записи.
Чтобы позволить проекту постов, я также добавил логическое значение Опубликовано? поле как первый столбец. API должен возвращать только посты со значением правда Отказ Это позволяет рассмотреть сообщения и редактировать до их публикации.
Создание API
Сценарий приложений Google построен на верхней части стандарта JavaScript Ecmascript 5 (ES5). При создании API мы не можем использовать функции ES6, такие как Scoped переменные, функции стрелки или параметры по умолчанию. Если вы не уверены в том, что доступно в ES5, я бы порекомендовал консультироваться на MDN Docs Столы совместимости.
Несмотря на отсутствие ES6, скрипты Apps Google все еще могут использоваться для создания достаточно сложных приложений на вершине G Sublite Products.
Начиная
Вы можете получить доступ к онлайн-редактору сценариев Google Apps, собираясь на Инструменты> Сценарий Редактировать Или в строке меню от электронной таблицы листов Google. Редактор скрипта откроется с пустым файлом NAM ED код .gs. Поскольку это простое приложение, мы поставим нашу логику в этот один скрипт, но вы также можете легко расстаться на приложение в отдельные сценарии.
Возвращение ответа
Мы можем использовать doget
и Допост
Функции обратного вызова для ответа на запросы HTTP. Это просто обычные функции, которые скрипт Google Apps смотрит, чтобы вызвать, когда запрос GET или POST соответственно сделан для API.
Чтобы генерировать ответ, мы будем использовать Софинсервис Отказ Объект JavaScript может быть передан на Json.stringify
а потом к CreateTextoutput
На эту услугу, чтобы построить ответ JSON. Если тип MIME установлен на Contentservice.mimetype.json
Это будет соответственно установить тип содержимого в Приложение/JSON
Отказ
Создание ответа JSON так же просто, как следующее:
function doGet(e) { var output = JSON.stringify({ status: 'success', message: 'It worked', }); return ContentService.createTextOutput(output) .setMimeType(ContentService.MimeType.JSON);}
По запросам анализа
doget
Обратный вызов всегда вызывается с событием, созданным из запроса. Из этого события мы можем получить доступ к параметрам строки запросов, которые мы будем использовать для поддержки различных опций API. Простая аутентификация без гражданства будет реализована через ключ
параметр. Это просто проверит, что ключ
Значение параметра соответствует жесткому значению ключа. Запросы, которые не совпадают, будет показан несанкционированный ответ.
А категория
Параметр будет использоваться так, чтобы пользователи могли запросить сообщения из одной категории. Это экономит их от необходимости фильтрации по категориям на переднем углу. Pagination также будет реализован через страница
параметр.
Эти опции должны быть добавлены к URL-адресу при выполнении запроса API.
GET https://apiurl?key=abcdef&category=general&page=1
Этот запрос будет генерировать следующее событие:
{ "queryString": "key=abcdef&category=general&page=1", "parameter": {}, "contextPath": "", "parameters": { "key": [ "abcdef" ], "category": [ "general" ], "page": [ "1" ] }, "contentLength": -1}
Давайте сначала аутентифицируйте событие. Мы сделаем это, проверив, что ключ
был предоставлен и что он соответствует определенному ключу API.
var API_KEY = 'abcdef';
function doGet(e) { if (!isAuthorized(e)) { return buildErrorResponse('not authorized'); } return buildSuccessResponse('authorized');}
function isAuthorized(e) { return 'key' in e.parameters && e.parameters.key[0] === API_KEY;}
function buildSuccessResponse(message) { var output = JSON.stringify({ status: 'success', message: message }); return ContentService.createTextOutput(output) .setMimeType(ContentService.MimeType.JSON);}
function buildErrorResponse(message) { var output = JSON.stringify({ status: 'error', message: message }); return ContentService.createTextOutput(output) .setMimeType(ContentService.MimeType.JSON);}
Ключ API определяется как abcdef
в верхней части файла. неавторизован
Функция возвращает логическое значение для аутентификации. Если это возвращает false a не авторизован
Сообщение возвращается через builderrorresponse
помощник. Если неавторизован
Возвращает true, функция разрешена продолжать до тех пор, пока не будет возвращен успешной ответ на buildsuccessResponse
Отказ
Недостаток, который я нашел, когда создание приложений в скрипте Apps Google в том, что у вас нет возможности устанавливать коды состояния для ответов. Они могут быть использованы для указывания, был ли ответ успешным, и если нет, почему.
Например, 401 Неаутентификация Код состояния подразумевает, что учетные данные пользователя не совпадают и что они должны попробовать еще раз, используя разные учетные данные. Ответы всегда имеют 200 ОК код состояния при использовании doget
даже для обработки неудачных ответов. Я получаю это, добавив Статус
Значение всем ответам API. Для этого простого примера статус может быть либо Успех
или Ошибка
. , но легко посмотреть, как этот шаблон может быть расширен для других более гранулированных статусов, если требуется.
Давайте создадим две функции для анализа категория
и страница
Параметры. Если допустимый численный страница
не поставляется, его значение по умолчанию должно быть 1
Отказ Аналогично, если категория не предоставлена, значение по умолчанию должно быть установлено на null
В каком случае должны быть возвращены сообщения от всех категорий.
function getPageParam(e) { if ('page' in e.parameters) { var page = parseInt(e.parameters['page'][0]); if (!isNaN(page) && page > 0) { return page; } } return 1}
function getCategoryParam(e) { if ('category' in e.parameters) { return e.parameters['category'][0]; } return null}
Чтение от электронной таблицы
Сценарий приложений Google создает различные доступные глобальные объекты, которые могут использоваться для взаимодействия с продуктами G Suite. Мы будем использовать ExplationSeathervice Чтобы загрузить нашу электронную таблицу по ID и прочитайте сообщения в блоге. Самый простой способ поиска идентификатора электронной таблицы – проверять URL-адрес листов Google.
https://docs.google.com/spreadsheets/d/{id}/edit
После загрузки электронной таблицы через Openbyid
Метод на глобальном ExplationSeathervice
Нам нужно получить активное диапазон данных от первого листа. Чтобы вернуть самые последние сообщения сначала, мы должны отсортировать на Timestamp столбец, который является второй колонкой.
var SPREADSHEET_ID = '12345';var spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);var worksheet = spreadsheet.getSheets()[0];var rows = worksheet.getDataRange() .sort({column: 2, ascending: false}) .getValues();
Ряды
массив от GetDataRange
Содержит как заголовки столбцов в качестве первого элемента массива, так и в блоге Post Rows в качестве последующих элементов массива. Заголовки могут быть сопоставлены в такие сообщения в блоге, чтобы API мог вернуть полные объекты в блоге, а не только значения столбцов.
var headings = rows[0].map(String.toLowerCase);var posts = rows.slice(1);var postsWithHeadings = addHeadings(posts, headings);
function addHeadings(posts, headings) { return posts.map(function(postAsArray) { var postAsObj = {}; headings.forEach(function(heading, i) { postAsObj[heading] = postAsArray[i]; }); return postAsObj; });}
Фильтрация нерелевантных сообщений
Сообщения блога должны быть возвращены только в том случае, если их категория соответствует запрошенному запросу, и должно быть возвращено посты со всех категорий, если не было запрошено. Сообщения в блоге также должны быть дополнительно возвращены только в том случае, если у них есть Опубликовано Значение правда Отказ
Давайте создадим функцию для удаления черновиков сообщений Массивный фильтр :
var postsPublic = removeDrafts(postsWithHeadings);
function removeDrafts(posts, category) { return posts.filter(function(post) { return post['published'] === true; });}
И другая функция для Фильтр
На посту категории:
var category = getCategoryParam(e);var postsFiltered = filter(postsPublic, category);
function filter(posts, category) { return posts.filter(function(post) { if (category !== null) { var c1 = post['category'].toLowerCase() var c2 = category.toLowerCase() return c1 === c2; } else { return true; } });}
Пагиновые отзывы
По причинам эффективности мы должны ограничить максимальное количество постов, возвращаемых одним ответом API. Клиент должен быть в состоянии запросить следующую страницу сообщений, увеличивая страница
Параметр запроса.
Давайте реализуем это через функцию Pagination, которая возвращает объект, содержащий отфильтрованные сообщения в блоге под Сообщения
и пегированные ссылки под Страницы
Отказ Если есть все или предыдущие результаты, Страницы
Содержит соответствующий номер страницы под Следующий
и предыдущий
соответственно.
var RESULTS_PER_PAGE = 5;var page = getPageParam(e)var paginated = paginate(postsFiltered, page);
function paginate(posts, page) { var postsCopy = posts.slice(); var postsChunked = []; var postsPaginated = { posts: [], pages: { previous: null, next: null } }; while (postsCopy.length > 0) { postsChunked.push(postsCopy.splice(0, RESULTS_PER_PAGE)); } if (page - 1 in postsChunked) { postsPaginated.posts = postsChunked[page - 1]; } else { postsPaginated.posts = []; }
if (page > 1 && page <= postsChunked.length) { postsPaginated.pages.previous = page - 1; } if (page >= 1 && page < postsChunked.length) { postsPaginated.pages.next = page + 1; } return postsPaginated;}
Наше buildsuccessResponse
Хельпер от ранее может быть обновлен, чтобы обработать Сообщения
и Страницы
Отказ API должен затем готов к развертыванию.
function buildSuccessResponse(posts, pages) { var output = JSON.stringify({ status: 'success', data: posts, pages: pages }); return ContentService.createTextOutput(output) .setMimeType(ContentService.MimeType.JSON);}
Развертывание API.
С помощью скрипта доработаны, API может быть предоставлен публично, собираясь на Опубликовать> Развернуть как Weba PP из строки меню редактора скриптов. Убедитесь, что приложение выполняется как я и й У кого-нибудь, даже аноним имеет доступ.
Развертывание вернет URL, который будет выглядеть следующим образом:
https://script.google.com/macros/s/{id}/exec
Добавьте ключ API на URL-адрес, а затем введите его в веб-браузер, чтобы убедиться, что API работает правильно. Надеюсь, вы должны увидеть ответ JSON с тремя клавишами верхнего уровня: Статус
, Сообщения
, Страницы
Отказ
https://script.google.com/macros/s/{id}/exec?key=abcdef
Резюме
Если вы следите за вами, теперь вы должны иметь функциональный CMS, построенный на листах Google, Google Forms и Google Apps Script. Это не продвинуто, но было легко начать и доставляет основные требования CMS. Подключение его к интерфейсу было за пределами объема этой статьи, но если вы хотите увидеть, как это сделано, вы должны проверить демо, которую я собрал на Github Отказ
В следующий раз, когда вы собираетесь добраться до технологического аромата дня, я бросаю вам вызов вам занять несколько моментов, чтобы подумать о том, есть ли более простое решение, которое можно построить с использованием существующего программного обеспечения. Это решение может не быть полностью представлено, но часто уводит вас 80% пути там на 20% усилий , что во многих случаях будет достаточно хорош. Я надеюсь, что этот пост блога продемонстрировал, что и что вы изучали вещь или два о сценарии Apps Google по пути.