تعزيز التفاعل مع الرسائل الإلكترونية باستخدام إضافات Google Workspace

1. نظرة عامة

في هذا الدرس التطبيقي حول الترميز، ستستخدم برمجة تطبيقات Google لكتابة إضافة Google Workspace في Gmail تتيح للمستخدمين إضافة بيانات الإيصالات من رسالة إلكترونية إلى جدول بيانات مباشرةً داخل Gmail. عندما يتلقّى المستخدم إيصالاً عبر البريد الإلكتروني، يفتح الإضافة التي تحصل تلقائيًا على معلومات النفقات ذات الصلة من البريد الإلكتروني. يمكن للمستخدم تعديل معلومات النفقات ثم إرسالها لتسجيل نفقاته في جدول بيانات "جداول بيانات Google".

ما ستتعرَّف عليه

  • إنشاء إضافة Google Workspace في Gmail باستخدام "برمجة تطبيقات Google"
  • تحليل رسالة إلكترونية باستخدام "برمجة تطبيقات Google"
  • التفاعل مع "جداول بيانات Google" عبر "برمجة تطبيقات Google"
  • تخزين قيم المستخدمين باستخدام خدمة الخصائص في برمجة تطبيقات Google

المتطلبات

  • الوصول إلى الإنترنت ومتصفّح الويب
  • حساب Google
  • بعض الرسائل، ويفضل إيصالات البريد الإلكتروني، في Gmail

2. الحصول على الرمز النموذجي

أثناء عملك في هذا الدرس التطبيقي حول الترميز، قد يكون من المفيد الرجوع إلى نسخة صالحة من التعليمة البرمجية التي ستكتبها. يحتوي مستودع GitHub على نموذج التعليمات البرمجية الذي يمكنك استخدامه كمرجع.

للحصول على الرمز النموذجي، نفِّذ ما يلي من سطر الأوامر:

git clone https://github.com/googleworkspace/gmail-add-on-codelab.git

3- إنشاء إضافة أساسية

ابدأ بكتابة الرمز لنسخة بسيطة من الإضافة التي تعرض نموذج نفقات إلى جانب رسالة إلكترونية.

أولاً، أنشِئ مشروع "برمجة تطبيقات Google" جديدًا وافتح ملف البيان الخاص به.

  1. انتقِل إلى script.google.com. من هنا، يمكنك إنشاء مشاريع "برمجة تطبيقات Google" وإدارتها ومراقبتها.
  2. لإنشاء مشروع جديد، انقر على مشروع جديد في أعلى يمين الصفحة. يتم فتح المشروع الجديد باستخدام ملف تلقائي باسم "Code.gs". يمكنك ترك "Code.gs" في الوقت الحالي، وستعمل عليه لاحقًا.
  3. انقر على Untitled project (مشروع بلا عنوان)، وأدخِل اسمًا لمشروعك Expense It!، ثم انقر على إعادة تسمية.
  4. على يمين الصفحة، انقر على رمز إعدادات المشروع (Project Settings) إعدادات المشروع.
  5. حدد ملف إظهار "appscript.json" ملف البيان في المحرِّر".
  6. انقر على رمز المحرِّر محرِّر.
  7. لفتح ملف البيان، انقر على الرمز appscript.json على يمين الصفحة.

في appscript.json، حدِّد البيانات الوصفية المرتبطة بالإضافة، مثل اسمها والأذونات التي تتطلّبها. استبدِل محتوى appsscript.json بإعدادات الضبط التالية:

{
  "timeZone": "GMT",
  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.execute"
  ],
  "gmail": {
    "name": "Expense It!",
    "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/receipt_black_24dp.png",
    "contextualTriggers": [{
      "unconditional": {
      },
      "onTriggerFunction": "getContextualAddOn"
    }],
    "primaryColor": "#41f470",
    "secondaryColor": "#94f441"
  }
}

وعليك الانتباه بشكل خاص إلى جزء البيان المسمى contextualTriggers. يحدّد هذا الجزء من البيان الدالة التي يحدّدها المستخدم لطلبها عند تفعيل الإضافة لأول مرة. في هذه الحالة، يطلب التطبيق getContextualAddOn، الذي يحصل على تفاصيل عن الرسالة الإلكترونية المفتوحة ويعرض مجموعة من البطاقات لعرضها للمستخدم.

لإنشاء الدالة getContextualAddOn، اتبع الخطوات التالية:

  1. على يمين الشاشة، اضغط مع الاستمرار على مؤشر الماوس فوق Code.gs، ثم انقر على رمز القائمة قائمة "المزيد" >. إعادة التسمية.
  2. اكتب GetContextualAddOn واضغط على مفتاح Enter. تُلحِق "برمجة التطبيقات" .gs تلقائيًا في اسم الملف، لذلك لن تحتاج إلى كتابة امتداد ملف. إذا كتبت GetContextualAddOn.gs، ستسمي "برمجة التطبيقات" ملفك GetContextualAddOn.gs.gs.
  3. في GetContextualAddOn.gs، استبدِل الرمز التلقائي بالدالة getContextualAddOn:
/**
 * Returns the contextual add-on data that should be rendered for
 * the current e-mail thread. This function satisfies the requirements of
 * an 'onTriggerFunction' and is specified in the add-on's manifest.
 *
 * @param {Object} event Event containing the message ID and other context.
 * @returns {Card[]}
 */
function getContextualAddOn(event) {
  var card = CardService.newCardBuilder();
  card.setHeader(CardService.newCardHeader().setTitle('Log Your Expense'));

  var section = CardService.newCardSection();
  section.addWidget(CardService.newTextInput()
    .setFieldName('Date')
    .setTitle('Date'));
  section.addWidget(CardService.newTextInput()
    .setFieldName('Amount')
    .setTitle('Amount'));
  section.addWidget(CardService.newTextInput()
    .setFieldName('Description')
    .setTitle('Description'));
  section.addWidget(CardService.newTextInput()
    .setFieldName('Spreadsheet URL')
    .setTitle('Spreadsheet URL'));

  card.addSection(section);

  return [card.build()];
}

تتكوّن واجهة المستخدم لكل إضافة في "إضافات Google Workspace" من بطاقات مقسَّمة إلى قسم واحد أو أكثر يحتوي كل منها على أدوات يمكنها عرض المعلومات والحصول عليها من المستخدم. تنشئ الدالة getContextualAddOn بطاقة واحدة تحصل على تفاصيل حول النفقات الواردة في رسالة إلكترونية. تحتوي البطاقة على قسم واحد يحتوي على حقول إدخال نص للبيانات ذات الصلة. تعرض الدالة صفيفًا من بطاقات الإضافة. في هذه الحالة، يتضمن الصفيف المرتجع بطاقة واحدة فقط.

قبل نشر حساب Expense It أنت بحاجة إلى مشروع Google Cloud Platform (GCP)، الذي تستخدمه مشاريع "برمجة التطبيقات" لإدارة الأذونات والخدمات المتقدّمة والتفاصيل الأخرى. لمزيد من المعلومات، يُرجى الانتقال إلى مشاريع Google Cloud Platform.

لنشر الإضافة وتشغيلها، اتّبِع الخطوات التالية:

  1. افتح مشروع Google Cloud Platform وانسخ رقم مشروعه.
  2. من مشروع "برمجة التطبيقات"، انقر على إعدادات المشروع إعدادات المشروع على يمين الصفحة.
  3. ضمن "مشروع Google Cloud Platform (GCP)"، انقر على تغيير المشروع.
  4. أدخِل رقم مشروع مشروع Google Cloud Platform، ثم انقر على ضبط المشروع.
  5. انقر على نشر > اختبار عمليات النشر.
  6. تأكَّد من أنّ نوع النشر هو إضافة Google Workspace. إذا لزم الأمر، في أعلى مربّع الحوار، انقر على رمز تفعيل أنواع النشر تفعيل أنواع النشر واختَر إضافة Google Workspace كنوع النشر.
  7. بجانب التطبيقات: Gmail، انقر على تثبيت.
  8. انقر على تم.

يمكنك الآن الاطّلاع على الإضافة في البريد الوارد في Gmail.

  1. على الكمبيوتر، افتح Gmail.
  2. على اللوحة اليمنى، تظهر Expense It! تظهر إضافة "إنفاق التكاليف! رمز الإيصال". قد تحتاج إلى النقر على رمز المزيد من الإضافات المزيد من الإضافات للعثور عليها.
  3. افتح رسالة بريد إلكتروني، ويفضل إيصال بالنفقات.
  4. لفتح الإضافة، انقر على "نفقتها!" في اللوحة الجانبية اليسرى. إنفاق التكاليف! رمز الإيصال.
  5. وفِّر التكاليف. بالوصول إلى حساب Google بالنقر على تفويض الوصول واتّباع التعليمات.

تعرض الإضافة نموذجًا بسيطًا إلى جانب رسالة Gmail مفتوحة. لا تفعل أي شيء آخر حتى الآن، لكنك ستنشئ وظائفها في القسم التالي.

للاطّلاع على التحديثات التي يتم إجراؤها على الإضافة أثناء مواصلة هذه الميزة الاختبارية، ما عليك سوى حفظ الرمز وإعادة تحميل Gmail. ليست هناك حاجة إلى عمليات نشر إضافية.

4. الوصول إلى الرسائل الإلكترونية

يمكنك إضافة رمز يجلب محتوى الرسائل الإلكترونية ويقسّم الرمز إلى وحدات تنظيمية.

بجانب "الملفات"، انقر على رمز إضافة إضافة ملف >. يمكنك النص البرمجي وإنشاء ملف باسم Cards. أنشئ ملف نص برمجي ثانٍ باسم Helpers. ينشئ Cards.gs البطاقة ويستخدم وظائف من Helpers.gs لتعبئة الحقول في النموذج استنادًا إلى محتوى الرسالة الإلكترونية.

استبدِل الرمز التلقائي في Cards.gs بهذا الرمز:

var FIELDNAMES = ['Date', 'Amount', 'Description', 'Spreadsheet URL'];

/**
 * Creates the main card users see with form inputs to log expenses.
 * Form can be prefilled with values.
 *
 * @param {String[]} opt_prefills Default values for each input field.
 * @param {String} opt_status Optional status displayed at top of card.
 * @returns {Card}
 */
function createExpensesCard(opt_prefills, opt_status) {
  var card = CardService.newCardBuilder();
  card.setHeader(CardService.newCardHeader().setTitle('Log Your Expense'));
  
  if (opt_status) {
    if (opt_status.indexOf('Error: ') == 0) {
      opt_status = '<font color=\'#FF0000\'>' + opt_status + '</font>';
    } else {
      opt_status = '<font color=\'#228B22\'>' + opt_status + '</font>';
    }
    var statusSection = CardService.newCardSection();
    statusSection.addWidget(CardService.newTextParagraph()
      .setText('<b>' + opt_status + '</b>'));
    card.addSection(statusSection);
  }
  
  var formSection = createFormSection(CardService.newCardSection(),
                                      FIELDNAMES, opt_prefills);
  card.addSection(formSection);
  
  return card;
}

/**
 * Creates form section to be displayed on card.
 *
 * @param {CardSection} section The card section to which form items are added.
 * @param {String[]} inputNames Names of titles for each input field.
 * @param {String[]} opt_prefills Default values for each input field.
 * @returns {CardSection}
 */
function createFormSection(section, inputNames, opt_prefills) {
  for (var i = 0; i < inputNames.length; i++) {
    var widget = CardService.newTextInput()
      .setFieldName(inputNames[i])
      .setTitle(inputNames[i]);
    if (opt_prefills && opt_prefills[i]) {
      widget.setValue(opt_prefills[i]);
    }
    section.addWidget(widget);
  }
  return section;
}

تستخدم الدالة createExpensesCard صفيفًا من القيم لملء النموذج مسبقًا كوسيطة اختيارية. يمكن أن تعرض الدالة رسالة حالة اختيارية، تظهر باللون الأحمر إذا كانت الحالة تبدأ بـ "خطأ:"، وتكون خضراء بخلاف ذلك. بدلاً من إضافة كل حقل إلى النموذج يدويًا، تعمل دالة مساعِدة تُسمى createFormSection على تنفيذ عملية إنشاء تطبيقات مصغّرة لإدخال النص، وتضبط كل قيمة تلقائية باستخدام setValue، ثم تضيف التطبيقات المصغّرة إلى الأقسام المعنيّة في البطاقة.

والآن، استبدِل الرمز التلقائي في Helpers.gs بهذا الرمز:

/**
 * Finds largest dollar amount from email body.
 * Returns null if no dollar amount is found.
 *
 * @param {Message} message An email message.
 * @returns {String}
 */
function getLargestAmount(message) {
  return 'TODO';
}

/**
 * Determines date the email was received.
 *
 * @param {Message} message An email message.
 * @returns {String}
 */
function getReceivedDate(message) {
  return 'TODO';
}

/**
 * Determines expense description by joining sender name and message subject.
 *
 * @param {Message} message An email message.
 * @returns {String}
 */
function getExpenseDescription(message) {
  return 'TODO';
}

/**
 * Determines most recent spreadsheet URL.
 * Returns null if no URL was previously submitted.
 *
 * @returns {String}
 */
function getSheetUrl() {
  return 'TODO';
}

يتم استدعاء الدوال في Helpers.gs من قِبل getContextualAddon لتحديد القيم التي تم ملؤها مسبقًا في النموذج. في الوقت الحالي، ستُرجع هذه الدوال السلسلة "TODO" فقط لأنك ستقوم بتنفيذ منطق الملء المسبق في خطوة لاحقة.

بعد ذلك، يجب تعديل الرمز في GetContextualAddon.gs للاستفادة من الرمز في Cards.gs وHelpers.gs. استبدِل الرمز في GetContextualAddon.gs بهذا الرمز:

/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Returns the contextual add-on data that should be rendered for
 * the current e-mail thread. This function satisfies the requirements of
 * an 'onTriggerFunction' and is specified in the add-on's manifest.
 *
 * @param {Object} event Event containing the message ID and other context.
 * @returns {Card[]}
 */
function getContextualAddOn(event) {
  var message = getCurrentMessage(event);
  var prefills = [getReceivedDate(message),
                  getLargestAmount(message),
                  getExpenseDescription(message),
                  getSheetUrl()];
  var card = createExpensesCard(prefills);

  return [card.build()];
}

/**
 * Retrieves the current message given an action event object.
 * @param {Event} event Action event object
 * @return {Message}
 */
function getCurrentMessage(event) {
  var accessToken = event.messageMetadata.accessToken;
  var messageId = event.messageMetadata.messageId;
  GmailApp.setCurrentMessageAccessToken(accessToken);
  return GmailApp.getMessageById(messageId);
}

عليك التعرّف على دالة getCurrentMessage الجديدة التي تستخدم الحدث المدعوم من Gmail لقراءة رسالة المستخدم المفتوحة حاليًا. لكي تعمل هذه الدالة، أضِف نطاقًا إضافيًا إلى بيان النص البرمجي يسمح بالوصول للقراءة فقط إلى رسائل Gmail.

في appscript.json، عدِّل oauthScopes بحيث تطلب أيضًا نطاق https://www.googleapis.com/auth/gmail.addons.current.message.readonly.

"oauthScopes": [
  "https://www.googleapis.com/auth/gmail.addons.execute",
   "https://www.googleapis.com/auth/gmail.addons.current.message.readonly"
],

في Gmail، شغِّل الإضافة وامنح الإذن بالوصول إلى Expense It. لعرض الرسائل الإلكترونية. تم الآن ملء حقول النموذج مسبقًا بـ "قائمة المهام".

5- التفاعل مع "جداول بيانات Google"

تكلفتها! تحتوي الإضافة على نموذج للمستخدم لإدخال تفاصيل حول إحدى النفقات، ولكن هذه التفاصيل ليس لها أي مكان يمكن الانتقال إليه. لنضيف زرًا يرسل بيانات النموذج إلى جدول بيانات Google.

لإضافة زر، سنستخدم الفئة ButtonSet. للتفاعل مع "جداول بيانات Google"، سنستخدم خدمة "جداول بيانات Google".

عدِّل createFormSection لعرض زر يحمل اسم "إرسال". كجزء من قسم النموذج في البطاقة يُرجى تنفيذ ما يلي:

  1. إنشاء زر نصي باستخدام CardService.newTextButton()، يحمل اسم الزر "إرسال" باستخدام CardService.TextButton.setText().
  2. صمِّم الزر على النحو الذي يتم به استدعاء إجراء submitForm التالي عبر CardService.TextButton.setOnClickAction() عند النقر عليه:
/**
 * Logs form inputs into a spreadsheet given by URL from form.
 * Then displays edit card.
 *
 * @param {Event} e An event object containing form inputs and parameters.
 * @returns {Card}
 */
function submitForm(e) {
  var res = e['formInput'];
  try {
    FIELDNAMES.forEach(function(fieldName) {
      if (! res[fieldName]) {
        throw 'incomplete form';
      }
    });
    var sheet = SpreadsheetApp
      .openByUrl((res['Spreadsheet URL']))
      .getActiveSheet();
    sheet.appendRow(objToArray(res, FIELDNAMES.slice(0, FIELDNAMES.length - 1)));
    return createExpensesCard(null, 'Logged expense successfully!').build();
  }
  catch (err) {
    if (err == 'Exception: Invalid argument: url') {
      err = 'Invalid URL';
      res['Spreadsheet URL'] = null;
    }
    return createExpensesCard(objToArray(res, FIELDNAMES), 'Error: ' + err).build();
  }
}

/**
 * Returns an array corresponding to the given object and desired ordering of keys.
 *
 * @param {Object} obj Object whose values will be returned as an array.
 * @param {String[]} keys An array of key names in the desired order.
 * @returns {Object[]}
 */
function objToArray(obj, keys) {
  return keys.map(function(key) {
    return obj[key];
  });
}
  1. يمكنك إنشاء تطبيق مصغّر لمجموعة أزرار باستخدام CardService.newButtonSet() وإضافة زر النص إلى مجموعة الأزرار باستخدام CardService.ButtonSet.addButton().
  2. أضِف التطبيق المصغّر لمجموعة الأزرار إلى قسم النموذج في البطاقة باستخدام CardService.CardSection.addWidget().

في بضعة أسطر من التعليمات البرمجية، يمكننا فتح جدول بيانات بواسطة عنوان URL الخاص به ثم إلحاق صف من البيانات بتلك الورقة. يُرجى العلم أنّه يتم تمرير إدخالات النموذج إلى الدالة كجزء من الحدث e، ونتحقّق من أنّ المستخدم قد قدّم جميع الحقول. بافتراض عدم حدوث أي أخطاء، ننشئ بطاقة نفقات فارغة بحالة إيجابية. في حال رصدنا خطأً، نعيد البطاقة الأصلية التي تم ملؤها مع رسالة الخطأ. تسهّل الدالة المساعدة objToArray تحويل الردود على النموذج إلى مصفوفة، والتي يمكن إلحاقها بعد ذلك بجدول البيانات.

أخيرًا، يمكنك تعديل القسم oauthScopes في appsscript.json لطلب النطاق https://www.googleapis.com/auth/spreadsheets مرة أخرى. عند تفويض هذا النطاق، فإنّه يتيح للإضافة قراءة "جداول بيانات Google" للمستخدم وتعديلها.

"oauthScopes": [
  "https://www.googleapis.com/auth/gmail.addons.execute",
  "https://www.googleapis.com/auth/gmail.addons.current.message.readonly",
  "https://www.googleapis.com/auth/spreadsheets"
],

إذا لم تكن قد أنشأت جدول بيانات جديدًا من قبل، أنشئ جدول بيانات في https://docs.google.com/spreadsheets/.

يجب الآن إعادة تشغيل الإضافة ومحاولة إرسال النموذج. تأكّد من إدخال عنوان URL الكامل لعنوان URL المقصود في حقل نموذج عنوان URL لجدول البيانات.

6- تخزين القيم في خدمة "المواقع"

في كثير من الأحيان، سيقوم المستخدمون بتسجيل العديد من النفقات في نفس جدول البيانات، لذلك سيكون من السهل تقديم أحدث عنوان URL لجدول البيانات كقيمة افتراضية في البطاقة. لمعرفة أحدث عنوان URL لجدول البيانات، سنحتاج إلى تخزين هذه المعلومات في كل مرة يتم فيها استخدام الإضافة.

تتيح لنا خدمة الخصائص تخزين أزواج المفتاح/القيمة. في حالتنا، سيكون المفتاح المعقول هو "SPREADsheet_URL" في حين أن القيمة ستكون عنوان URL نفسه. لتخزين مثل هذه القيمة، يجب تعديل submitForm في Cards.gs ليتم تخزين عنوان URL لجدول البيانات كسمة عند إلحاق صف جديد بورقة البيانات.

تجدر الإشارة إلى أنّ المواقع يمكن أن يكون لها أحد النطاقات الثلاثة: النص البرمجي أو المستخدِم أو المستند. لا ينطبق نطاق المستند على إضافات Gmail، على الرغم من أنّه ذو صلة بنوع منفصل من الإضافات عند تخزين معلومات خاصة بمستند أو جدول بيانات Google معيّن. بالنسبة إلى الإضافة، يكون السلوك المطلوب هو أن يرى الفرد جدول البيانات الخاص به (على عكس جدول البيانات الأحدث الخاص بشخص آخر) كخيار تلقائي في النموذج. وبالتالي، نختار نطاق user بدلاً من نطاق script.

استخدِم PropertiesService.getUserProperties().setProperty() لتخزين عنوان URL لجدول البيانات. إضافة ما يلي إلى submitForm في Cards.gs:

PropertiesService.getUserProperties().setProperty('SPREADSHEET_URL', 
    res['Spreadsheet URL']);

بعد ذلك، عدِّل الدالة getSheetUrl في Helpers.gs لعرض السمة المخزَّنة بحيث يتمكّن المستخدم من الاطّلاع على أحدث عنوان URL في كل مرة يستخدم فيها الإضافة. استخدِم PropertiesService.getUserProperties().getProperty() للحصول على قيمة الموقع.

/**
 * Determines most recent spreadsheet URL.
 * Returns null if no URL was previously submitted.
 *
 * @returns {String}
 */
function getSheetUrl() {
  return PropertiesService.getUserProperties().getProperty('SPREADSHEET_URL');
}

وأخيرًا، للوصول إلى خدمة "الخصائص"، يجب أن يتم أيضًا تفويض النص البرمجي. أضِف النطاق https://www.googleapis.com/auth/script.storage إلى البيان كما في السابق للسماح للإضافة بقراءة معلومات الموقع وكتابتها.

7. تحليل رسالة Gmail

لحفظ أهداف المستخدمين لنملأ النموذج مسبقًا بالمعلومات ذات الصلة حول النفقات من البريد الإلكتروني. لقد أنشأنا دوالاً في Helpers.gs تؤدي هذا الدور، ولكن حتى الآن لم نعرض سوى دالة "TODO" للتاريخ والمبلغ ووصف النفقة.

على سبيل المثال، يمكننا الحصول على تاريخ استلام البريد الإلكتروني واستخدامه كقيمة افتراضية لتاريخ النفقات.

/**
 * Determines date the email was received.
 *
 * @param {Message} message - The message currently open.
 * @returns {String}
 */
function getReceivedDate(message) {
  return message.getDate().toLocaleDateString();
}

نفِّذ الدالتين المتبقيتين:

  1. قد يستلزم getExpenseDescription الانضمام إلى كل من اسم المُرسِل وموضوع الرسالة، على الرغم من توفُّر طرق أكثر تعقيدًا لتحليل نص الرسالة وتقديم وصف أكثر دقة.
  2. بالنسبة إلى getLargestAmount، ننصحك بالبحث عن رموز محدّدة مرتبطة بالأموال. غالبًا ما تتضمّن الإيصالات قيمًا متعددة مُدرَجة، مثل الضرائب والرسوم الأخرى. فكر في كيفية تحديد الكمية الصحيحة. وقد تكون التعبيرات العادية مفيدة أيضًا.

إذا كنت بحاجة إلى أفكار ملهمة إضافية، يمكنك الاطّلاع على المستندات المرجعية لـ GmailMessage أو الاطّلاع على رمز الحلّ الذي نزّلته في بداية الدرس التطبيقي حول الترميز. بعد تصميم آليات التنفيذ الخاصة بك لجميع الدوال في Helpers.gs، جرِّب الإضافة المناسبة. افتح الإيصالات وابدأ في تسجيلها في جدول بيانات!

8. محو النموذج الذي يتضمّن إجراءات متعلقة بالبطاقة

ماذا يحدث في حال استخدام Expense It! يخطئ في تحديد أحد النفقات في رسالة بريد إلكتروني مفتوحة ويملأ النموذج مسبقًا بمعلومات غير صحيحة؟ يمحو المستخدم النموذج. تتيح لنا الفئة CardAction تحديد دالة يتم استدعاؤها عند النقر على الإجراء. دعنا نستخدمه لمنح المستخدم طريقة سريعة لمحو النموذج.

يمكنك تعديل createExpensesCard بحيث يتم تطبيق إجراء على البطاقة باسم "محو النموذج" على البطاقة التي يتم إرجاعها. وعند النقر على استدعاءات الدالة clearForm التالية، والتي يمكنك لصقها في Cards.gs. عليك ضبط opt_status كمَعلمة باسم "الحالة". إلى الإجراء لضمان بقاء رسالة الحالة بعد محو النموذج. ويجب الانتباه إلى أنّ المعلَمات الاختيارية للإجراءات يجب أن تكون من النوع Object.<string, string>، لذلك إذا لم تكن السمة opt_status متوفرة، يجب ضبط السمة {'Status' : ''}.

/**
 * Recreates the main card without prefilled data.
 *
 * @param {Event} e An event object containing form inputs and parameters.
 * @returns {Card}
 */
function clearForm(e) {
  return createExpensesCard(null, e['parameters']['Status']).build();
}

9. إنشاء جدول بيانات

بالإضافة إلى استخدام "برمجة تطبيقات Google" لتعديل جدول بيانات حالي، يمكنك إنشاء جدول بيانات جديد كليًا آليًا. بالنسبة إلى الإضافة، دعنا نسمح للمستخدم بإنشاء جدول بيانات للنفقات. للبدء، يجب إضافة القسم التالي الخاص بالبطاقة إلى البطاقة التي يُرجعها "createExpensesCard".

var newSheetSection = CardService.newCardSection();
var sheetName = CardService.newTextInput()
  .setFieldName('Sheet Name')
  .setTitle('Sheet Name');
var createExpensesSheet = CardService.newAction()
  .setFunctionName('createExpensesSheet');
var newSheetButton = CardService.newTextButton()
  .setText('New Sheet')
  .setOnClickAction(createExpensesSheet);
newSheetSection.addWidget(sheetName);
newSheetSection.addWidget(CardService.newButtonSet().addButton(newSheetButton));
card.addSection(newSheetSection);

الآن، عندما ينقر المستخدم على "ورقة جديدة" تؤدي الإضافة إلى إنشاء جدول بيانات جديد تم تنسيقه بصف رأس تم تجميده بحيث يكون مرئيًا دائمًا. يحدد المستخدم عنوانًا لجدول البيانات الجديد في النموذج، على الرغم من أن تضمين قيمة افتراضية في حال كان النموذج فارغًا قد يكون خيارًا جيدًا. عند تنفيذ createExpensesSheet، يجب إرجاع بطاقة مماثلة تقريبًا للبطاقة الحالية، مع إضافة رسالة حالة مناسبة، بالإضافة إلى ملء حقل عنوان URL مسبقًا بعنوان URL لجدول البيانات الجديد.

10. تهانينا!

لقد نجحت في تصميم وتنفيذ إضافة Gmail بنجاح حيث يمكنها العثور على نفقات في رسالة إلكترونية ومساعدة المستخدمين على تسجيل النفقات في جدول بيانات في ثوانٍ قليلة. لقد استخدمت "برمجة تطبيقات Google" للتفاعل مع العديد من واجهات Google APIs واحتفظت بالبيانات بين عمليات التنفيذ المتعددة للإضافة.

التحسينات المحتملة

دع خيالك يرشدك أثناء تحسين Expense It! ، ولكن إليك بعض الأفكار لإنشاء منتج أكثر فائدة:

  • رابط إلى جدول البيانات بمجرد تسجيل المستخدم لإحدى النفقات
  • إضافة إمكانية تعديل/التراجع عن تسجيل إحدى النفقات
  • دمج واجهات برمجة تطبيقات خارجية للسماح للمستخدمين بإجراء الدفعات وطلب المبالغ المالية

مزيد من المعلومات