Apps Script公式リファレンス: Apps Script Reference |障害・課題追跡: IssueTracker |Google Workspace: Status Dashboard - Summary

2020年2月29日土曜日

Salesforce APIでCaseを削除したい


今回やること

登録されているCaseを削除する

使うメソッドはDELETE
"method": "DELETE",


事前準備

接続アプリケーションを作成して
アクセストークンなどのデータをスクリプトのプロパティに保存しておく

手順は以下のブログに書きました。

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)



コード.gs
function deleteData() {
  var url = getProp("instance_url") + "/services/data/v47.0/sobjects/Case/CASE_ID";
  var response = UrlFetchApp.fetch(url, optionsDelete());
  if(response.getResponseCode() === 401) {
    runRefresh();// アクセストークン切れで401ならトークンを更新する
    response = UrlFetchApp.fetch(url, optionsDelete());
  }
  Logger.log([response, response.getResponseCode()]);
}

function optionsDelete() {
  var options = {
    "method": "DELETE",
    "headers": {
      "Authorization": "Bearer " + getProp("access_token"),
      "Content-Type": "application/json"
    },
    "muteHttpExceptions": true
  }
  return options;
}




参考

レコードを削除する
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_delete_record.htm

Salesforce APIでCaseを新規作成したい


今回やること

新規でCaseを作成する

作成する内容は以下のように設定しておく
  var obj = {
        "Status": "新規",
        "Reason": "理由を書く",
        "Origin": "電話",
        "Subject": "POSTで作成",
        "Priority": "中",
  }


使うメソッドはPOST
"method": "POST",


事前準備

接続アプリケーションを作成して
アクセストークンなどのデータをスクリプトのプロパティに保存しておく

手順は以下のブログに書きました。

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)



コード.gs
function postData() {  
  var url = getProp("instance_url") + "/services/data/v47.0/sobjects/Case";
  var response = UrlFetchApp.fetch(url, optionsPost());
  if(response.getResponseCode() === 401) {
    runRefresh();// アクセストークン切れで401ならトークンを更新する
    response = UrlFetchApp.fetch(url, optionsPost());
  }
  Logger.log([response, response.getResponseCode()]);
}

function createPayloadPost() {
  var obj = {
        "Status": "新規",
        "Reason": "理由を書く",
        "Origin": "電話",
        "Subject": "POSTで作成",
        "Priority": "中",
  }
  var json = JSON.stringify(obj);
  return json;
}

function optionsPost() {
  var options = {
    "method": "POST",
    "headers": {
      "Authorization": "Bearer " + getProp("access_token"),
      "Content-Type": "application/json"
    },
    "payload": createPayloadPost(),
    "muteHttpExceptions": true
  }
  return options;
}

function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}



参考

レコードを作成する
https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_sobject_create.htm


2020年2月28日金曜日

Gsuiteでカレンダーの共有権限を設定する(管理者)


カレンダーの公開および共有設定 > 共有オプションを設定する
https://support.google.com/a/answer/60765?hl=ja

に書かれていました。

デフォルトでは
「空き時間情報のみ(予定の詳細は非表示)」
になっているので、共有した予定は「予定あり」としか表示されない。


そこを
「すべての情報を共有する(外部ユーザーにカレンダーの変更を許可しない)」
などに変更すると内容も表示されるようになる。

(設定が反映されるまでに最大で24時間かかることがある)


参考

カレンダーの公開および共有設定 > 共有オプションを設定する
https://support.google.com/a/answer/60765?hl=ja

他のユーザーとカレンダーを共有する
https://support.google.com/calendar/answer/37082?hl=ja

2020年2月22日土曜日

canvasで四角形を描く






コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>
<body>
  <canvas id="myCanvas" width="360" height="360"></canvas>
<script>
  createRect();
  function createRect() { 
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    var x = 100;
    var y = 100;
    var width = 200;
    var height = 200;
    context.strokeStyle = "blue";
    context.lineWidth = 10;
    context.strokeRect(x, y, width, height);
  }
</script>
</body>
</html>



2020年2月17日月曜日

JIRAで複数の課題の変更履歴をシートに書き出したい(ステータス変更だけ)


JIRAで複数の課題の変更履歴をシートに書き出したい
ではすべての変更履歴を取得しました。

今回はfieldが「status」の場合だけシートに書き出したい。



作成時のステータス取得について

今回は下記の方法で取得しています。

  • 作成時の配列を以下のように用意しておく
    • var firstLine = [key, "status", currentStatus, "-", issueCreated];
  • 変更履歴がない場合
    • 現在のステータスをfromの位置(配列の2番目)に代入します
  • 変更履歴がある場合
    • 最初の変更履歴からfromの値を取得して代入します




コード.gs
var ISSUE_URL = 'https://SITENAME.atlassian.net/rest/api/2/issue/';
var ss_url = "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0";

/************************************
これを実行する
************************************/
function getIssuesHistories() {
  var keys = ["KT-12", "KT-13", "KT-14"];// 対象の課題キーたち
  var arrays = [];
  for(var i = 0; i < keys.length; i++) {
    var key = keys[i];
    getIssueHistories(key);
  }
}

/************************************
受け取った課題keyをgetHistoriesに渡して結果をシートに書き込む
************************************/
function getIssueHistories(key){
  var response = getHistories(key);
  var jobj = JSON.parse(response);
  var histories = jobj["changelog"]["histories"];
  var issueCreated = returnFormatDate(jobj["fields"]["created"]);
  var currentStatus = jobj["fields"]["status"]["name"];
  var arrays = [];
  var firstLine = [key, "status", currentStatus, "-", issueCreated];// この課題の最初の配列を用意する(changelogは変更履歴なので、作成時の記録は含まれないためここで作っておく)
  for(var i = 0; i < histories.length; i++) {
    var history = histories[i];
    var created = returnFormatDate(history["created"]);
    var items = history["items"];
    for(var j = 0; j < items.length; j++) {
      var item = items[j];
      var field = item["field"];
      var from = item["fromString"];
      var to = item["toString"];
      if(field === "status") {
        arrays.push([key, field, from, to, created]);
      }
    }
  }
  
  // changelogがなければ現在のステータスでよいが、変更された場合は変更前のfromが最初のステータスになるのでここで書き換える
  if(arrays.length >= 2) {// arraysの初期lengthは1で、changelogが増える度に+1となるため、2以上なら
    firstLine[2] = arrays[1][2];// 最初の配列の2番目である"from"を書き換える
  }
  
  arrays.push(firstLine);// 最初の行をarrays配列に追加する
  setValuesToSheet(arrays);
}

/************************************
履歴を取得して返す
************************************/
function getHistories(key) {
  var options = {
    contentType: "application/json",
    headers: {"Authorization": " Basic " + getProp("token")}
  };
  var url = ISSUE_URL + key + '?expand=changelog';
  var response = UrlFetchApp.fetch(url, options);
  return response;
}


/************************************
シートに書き込む
************************************/
function setValuesToSheet(arrays){
  var sheet = SpreadsheetApp.openByUrl(ss_url).getSheets()[0];
  var last_row = sheet.getLastRow();
  var start_row = last_row + 1;
  var start_col = 1;
  var num_rows = arrays.length;
  var num_cols = arrays[0].length;
  var range = sheet.getRange(start_row, start_col, num_rows, num_cols);
  range.setValues(arrays);
}


/************************************
日付をフォーマットして返す
************************************/
function returnFormatDate(date) {
  return Utilities.formatDate(new Date(date), 'Asia/Tokyo', 'yyyy/MM/dd/HH:mm:ss');
}


/************************************
受け取ったkeyの値をスクリプトのプロパティから返す
************************************/
function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}




関連記事

JIRAで複数の課題の変更履歴をシートに書き出したい

2020年2月16日日曜日

JIRAで複数の課題の変更履歴をシートに書き出したい


JIRAで特定の課題の変更履歴をシートに書き出したい
では1つの課題の履歴を取得して書き出しました。

今回は複数の課題を取得して書き出してくてやってみました。
課題を判別できるよう、A列にkey列を追加しています。



コード.gs
var ISSUE_URL = 'https://SITENAME.atlassian.net/rest/api/2/issue/';
var ss_url = "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0";

/************************************
これを実行する
************************************/
function getIssuesHistories() {
  var keys = ["KT-12", "KT-13", "KT-14"];
  var arrays = [];
  for(var i = 0; i < keys.length; i++) {
    var key = keys[i];
    getIssueHistories(key);
  }
}

/************************************
受け取った課題keyをgetHistoriesに渡して結果をシートに書き込む
************************************/
function getIssueHistories(key){
  var response = getHistories(key);
  var jobj = JSON.parse(response);
  var histories = jobj["changelog"]["histories"];
  var arrays = [];
  for(var i = 0; i < histories.length; i++) {
    var history = histories[i];
    var created = returnFormatDate(history["created"]);
    var items = history["items"];
    for(var j = 0; j < items.length; j++) {
      var item = items[j];
      var field = item["field"];
      var from = item["fromString"];
      var to = item["toString"];
      arrays.push([key, field, from, to, created]);
    }
  }
  setValuesToSheet(arrays);
}

/************************************
履歴を取得して返す
************************************/
function getHistories(key) {
  var options = {
    contentType: "application/json",
    headers: {"Authorization": " Basic " + getProp("token")}
  };
  var url = ISSUE_URL + key + '?expand=changelog';
  var response = UrlFetchApp.fetch(url, options);
  return response;
}


/************************************
シートに書き込む
************************************/
function setValuesToSheet(arrays){
  var sheet = SpreadsheetApp.openByUrl(ss_url).getSheets()[0];
  var last_row = sheet.getLastRow();
  var start_row = last_row + 1;
  var start_col = 1;
  var num_rows = arrays.length;
  var num_cols = arrays[0].length;
  var range = sheet.getRange(start_row, start_col, num_rows, num_cols);
  range.setValues(arrays);
}


/************************************
日付をフォーマットして返す
************************************/
function returnFormatDate(date) {
  return Utilities.formatDate(new Date(date), 'Asia/Tokyo', 'yyyy/MM/dd/HH:mm:ss');
}


/************************************
受け取ったkeyの値をスクリプトのプロパティから返す
************************************/
function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}



関連記事

JIRAで特定の課題の変更履歴をシートに書き出したい

JIRAで特定の課題の変更履歴をシートに書き出したい


特定の課題でどのフィールドが何から何にいつ変更されたかシートに書き出したい。



事前準備
  1. スクリプトのプロパティに「token」という名で値を保存しておく
  2. 以下の値を書き換える
    • var ISSUE_URL
    • var ss_url 
    • var key 



コード.gs
var ISSUE_URL = 'https://SITENAME.atlassian.net/rest/api/2/issue/';
var ss_url = "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0";

/************************************
これを実行する
************************************/
function getIssueHistories(){
  var key = "KT-12";
  var response = getHistories(key);
  var jobj = JSON.parse(response);
  var histories = jobj["changelog"]["histories"];
  var arrays = [];
  for(var i = 0; i < histories.length; i++) {
    var history = histories[i];
    var created = returnFormatDate(history["created"]);
    var items = history["items"];
    for(var j = 0; j < items.length; j++) {
      var item = items[j];
      var field = item["field"];
      var from = item["fromString"];
      var to = item["toString"];
      arrays.push([field, from, to, created]);
    }
  }
  setValuesToSheet(arrays)
}

/************************************
履歴を取得して返す
************************************/
function getHistories(key) {
  var options = {
    contentType: "application/json",
    headers: {"Authorization": " Basic " + getProp("token")}
  };
  var url = ISSUE_URL + key + '?expand=changelog';
  var response = UrlFetchApp.fetch(url, options);
  return response;
}


/************************************
シートに書き込む
************************************/
function setValuesToSheet(arrays){
  var sheet = SpreadsheetApp.openByUrl(ss_url).getSheets()[0];
  var last_row = sheet.getLastRow();
  var start_row = last_row + 1;
  var start_col = 1;
  var num_rows = arrays.length;
  var num_cols = arrays[0].length;
  var range = sheet.getRange(start_row, start_col, num_rows, num_cols);
  range.setValues(arrays);
}


/************************************
日付をフォーマットして返す
************************************/
function returnFormatDate(date) {
  return Utilities.formatDate(new Date(date), 'Asia/Tokyo', 'yyyy/MM/dd/HH:mm:ss');
}


/************************************
受け取ったkeyの値をスクリプトのプロパティから返す
************************************/
function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}



関連記事

JIRAでAPIトークンを取得したい
JIRA APIでissueの変更履歴を取得する
setValuesを使う話

Google Apps ScriptのHtml ServiceでスクリプトのURLを返したい


ScriptApp.getScriptId()
でスクリプトIDを取得できるのでそれを利用します。


スクリプトのアドレスバーを見てみるとこうなっています。
https://script.google.com/d/Script ID/edit?usp=drivesdk


Script IDの位置にScriptApp.getScriptId()で取得した値を入れてHtml側に返します。


今回のコード.gsでは、スクリプトファイルをHtml側から開けるようにしています。



コード.gs
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

function returnScriptUrl(){
  var scriptId = ScriptApp.getScriptId();
  var scriptUrl = "https://script.google.com/d/" + scriptId + "/edit?usp=drivesdk";
  return scriptUrl;
}




index.html
<!DOCTYPE html>
<html>
  <body>

  <a id="scriptUrlLink" target="_blank">Script URL</a>

<script>

getScriptUrl();

function getScriptUrl() {
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccess)
  .returnScriptUrl();
}

function onSuccess(scriptUrl) {
  document.getElementById("scriptUrlLink").href = scriptUrl;
}

function onFailure(e) {
  alert([e.message, e.stack]);
}

</script>

  </body>
</html>




2020年2月12日水曜日

JIRAのワークフローで使わないステータスを選択できなくしたい


選択できなくするためには削除する方法と選択肢に表示しない方法があるらしい。

ステータスの削除方法を調べてみると、アクティブなワークフローではできないようなことが書かれていました。ちょっと手間なので今回はやらない。
https://ja.confluence.atlassian.com/jirakb/cannot-add-transitions-or-delete-steps-in-draft-workflows-203392961.html


今回は、ステータス変更の選択肢に表示しない方法として、トランジションの削除をした手順を書いていきます。


実現した手順

STEP1: プロジェクト設定を選択します


STEP2: ワークフローを選択します


STEP3: アクションの鉛筆アイコンを選択します


STEP4: 対象のトランジションを選択して、トランジションを削除を選択します



STEP5: 削除します


STEP6: 下書きを公開します


これでステータスの選択肢に表示されなくなりました。


参考

ステータスフィールド値の定義
https://ja.confluence.atlassian.com/adminjiraserver/defining-status-field-values-938847108.html

下書きワークフローでトランジションを追加したりステップを削除したりすることができない
https://ja.confluence.atlassian.com/jirakb/cannot-add-transitions-or-delete-steps-in-draft-workflows-203392961.html

2020年2月11日火曜日

JIRA APIで指定した課題にコメントを追加したい


公式リファレンスを参考に、以下のコード.gsでいけました。



事前準備
  • 「BASE_URL」と「issueKey」は各自の値を設定します
  • スクリプトのプロパティに「token」という名でbase64Encodeしたトークンを入れておきます



tokenについては別途こちらにも書きました



コード.gs
var BASE_URL = "https://SITENAME.atlassian.net";
var issueKey = "KT-8";

function addComment() {
  var data = {
    "body": {
      "type": "doc",
      "version": 1,
      "content": [
        {
          "type": "paragraph",
          "content": [
            {
              "text": "added comment",
              "type": "text"
            }
          ]
        }
      ]
    }
  }

  var options = {
    method: 'post',
    contentType: 'application/json',
    headers: {'Authorization': ' Basic ' + getToken()},
    payload: JSON.stringify(data)
  }
  var url = BASE_URL + '/rest/api/3/issue/' + issueKey + "/comment";
  UrlFetchApp.fetch(url, options);
}

function getToken() {
  return PropertiesService.getScriptProperties().getProperty('token');
}





補足

上記は REST API v3 の場合で
v2 の場合は以下のコード2.gsでいけました。


コード2.gs
var BASE_URL = "https://SITENAME.atlassian.net";
var issueKey = "KT-8";

function addComment() {
  var data = {
        "body": "added comment v2"
      }

  var options = {
    method: 'post',
    contentType: 'application/json',
    headers: {'Authorization': ' Basic ' + getToken()},
    payload: JSON.stringify(data)
  }
  var url = BASE_URL + '/rest/api/2/issue/' + issueKey + "/comment";
  UrlFetchApp.fetch(url, options);
}

function getToken() {
  return PropertiesService.getScriptProperties().getProperty('token');
}



参考

Add comment v3
https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-issue-issueIdOrKey-comment-post

Add comment v2
https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-comment-post

Macのモデル別の技術仕様を知りたい


Mac のポートを調べる のページにモデル一覧があり
それぞれのモデルごとの技術仕様を確認できました。

Mac Pro
MacBook Pro
MacBook Air
iMac
Mac mini


参考

Mac のポートを調べる
https://support.apple.com/ja-jp/HT201736

2020年2月9日日曜日

LINEの通知をバイブレーションで受け取りたい(Android Pixel 3a)


Pixel 3aで設定した手順です。

  1. ホームで右上にある歯車をタップする
  2. 設定が開くので通知をタップする
  3. 通知の設定項目を確認する
  4. 通知設定を開いて設定する
  5. メッセージ通知を開いて設定する
  6. 詳細設定を開いて設定する



キャプチャも残しておきます。


STEP1:ホームで右上にある歯車をタップする


STEP2:設定が開くので通知をタップする


STEP3:通知の設定項目を確認する


STEP4:項目内の「通知設定」を開いて設定する


STEP5:同じく項目内の「メッセージ通知」を開いて設定する


STEP6:折りたたまれている「詳細設定」を開いて設定する



補足

音をなしにするには

「音」をタップするとこんな画面になるので「1回のみ」をタップした


開いた画面で「マイサウンド」を選択して


「なし」を選択して「保存」した



2020年2月8日土曜日

「コミュニティ コネクタを使ってみる」をやってみる


データスタジオについてよく理解していないときに、とりあえず以下の公式ラボをやった備忘録。

コミュニティ コネクタを使ってみる
https://developers.google.com/datastudio/connector/get-started?hl=ja

かかった時間:2時間くらい(ブログを書きながら)



最終的に保存したコード

コード.gs
function getAuthType() {
  var response = { type: 'NONE' };
  return response;
}

function getConfig(request) {
  var cc = DataStudioApp.createCommunityConnector();
  var config = cc.getConfig();
  
  config.newInfo()
    .setId('instructions')
    .setText('Enter npm package names to fetch their download count.');
  
  config.newTextInput()
    .setId('package')
    .setName('Enter a single package name')
    .setHelpText('e.g. googleapis or lighthouse')
    .setPlaceholder('googleapis');
  
  config.setDateRangeRequired(true);
  
  return config.build();
}

function getFields(request) {
  var cc = DataStudioApp.createCommunityConnector();
  var fields = cc.getFields();
  var types = cc.FieldType;
  var aggregations = cc.AggregationType;
  
  fields.newDimension()
    .setId('packageName')
    .setType(types.TEXT);
  
  fields.newMetric()
    .setId('downloads')
    .setType(types.NUMBER)
    .setAggregation(aggregations.SUM);
  
  fields.newDimension()
    .setId('day')
    .setType(types.YEAR_MONTH_DAY);
  
  return fields;
}

function getSchema(request) {
  var fields = getFields(request).build();
  return { schema: fields };
}

function responseToRows(requestedFields, response, packageName) {
  // Transform parsed data and filter for requested fields
  return response.map(function(dailyDownload) {
    var row = [];
    requestedFields.asArray().forEach(function (field) {
      switch (field.getId()) {
        case 'day':
          return row.push(dailyDownload.day.replace(/-/g, ''));
        case 'downloads':
          return row.push(dailyDownload.downloads);
        case 'packageName':
          return row.push(packageName);
        default:
          return row.push('');
      }
    });
    return { values: row };
  });
}

function getData(request) {
  var requestedFieldIds = request.fields.map(function(field) {
    return field.name;
  });
  var requestedFields = getFields().forIds(requestedFieldIds);

  // Fetch and parse data from API
  var url = [
    'https://api.npmjs.org/downloads/range/',
    request.dateRange.startDate,
    ':',
    request.dateRange.endDate,
    '/',
    request.configParams.package
  ];
  var response = UrlFetchApp.fetch(url.join(''));
  var parsedResponse = JSON.parse(response).downloads;
  var rows = responseToRows(requestedFields, parsedResponse, request.configParams.package);

  return {
    schema: requestedFields.build(),
    rows: rows
  };
}



appsscript.json
{
  "dataStudio": {
    "name": "npm Downloads - From Codelab",
    "logoUrl": "https://raw.githubusercontent.com/npm/logos/master/npm%20logo/npm-logo-red.png",
    "company": "Codelab user",
    "companyUrl": "https://developers.google.com/datastudio/",
    "addonUrl": "https://github.com/google/datastudio/tree/master/community-connectors/npm-downloads",
    "supportUrl": "https://github.com/google/datastudio/issues",
    "description": "Get npm package download counts.",
    "sources": ["npm"]
  }
}



1. Intro
Community Connectors is a feature for Data Studio that lets you use Apps Script to build connectors to any internet accessible data source. 
Apps Scriptを使って、ネット上のデータソースへのコネクタを構築できるらしい。


このラボで学習できること
  • Google Data Studio Community Connectorの仕組み
  • Google Apps Scriptを使用してコミュニティコネクタを構築する方法
  • Data Studioでコミュニティコネクタを使用する方法

2. Quick Survey

ここは各自でラジオボタンを選択して次へ

3. Overview of Community Connectors
npmでパッケージを公開し、日次でパッケージのダウンロード数を追跡したい。
このコードラボでは、npmパッケージダウンロードカウントAPIからこのデータを取得するコミュニティコネクタを構築する。
次に、Data Studioでそのコミュニティコネクタを使用して、このデータを視覚化するダッシュボードを構築できる。

4. Community Connector Workflow
基本的なコミュニティコネクタでは、次の4つの関数を定義する。
  • getAuthType()
  • getConfig()
  • getSchema()
  • getData()

5. Set up your Apps Script project
Apps Scriptで新規プロジェクトを作成する。
プロジェクト名を「My Codelab Connector」にして保存する。

6. Define getAuthType()
getAuthType()を書く。

コード.gs
function getAuthType() {
  var response = { type: 'NONE' };
  return response;
}

7. Define getConfig()
getConfig()関数のresponseでユーザーに表示する構成オプションを定義できる。
設定画面では、以下のフォーム要素で情報提供やユーザー入力を取得したりできる。
  • TEXTINPUT
  • TEXTAREA
  • SELECT_SINGLE
  • SELECT_MULTIPLE
  • CHECKBOX
  • INFO

INFO要素でユーザーへ指示を提供できる。
TEXTINPUT要素でユーザーから入力パッケージ名を取得できる。
それらのフォーム要素をconfigParamsキーの下にグループ化する。
接続しているAPIはパラメーターとして日付を必要とする。
getConfig()応答でdateRangeRequiredをtrueに設定し、すべてのデータ要求で日付範囲を提供するようにData Studioに指示する。
データソースがパラメーターとして日付を必要としない場合は省略できる。

コード.gsにgetConfig()関数を追加してみる。

コード.gs
function getConfig(request) {
  var cc = DataStudioApp.createCommunityConnector();
  var config = cc.getConfig();
  
  config.newInfo()
    .setId('instructions')
    .setText('Enter npm package names to fetch their download count.');
  
  config.newTextInput()
    .setId('package')
    .setName('Enter a single package name')
    .setHelpText('e.g. googleapis or lighthouse')
    .setPlaceholder('googleapis');
  
  config.setDateRangeRequired(true);
  
  return config.build();
}


8. Define getSchema()
getSchema()関数で、コネクターの選択された構成に関連付けられたスキーマを取得する。
getSchema()によって提供されたresponseに基づいて、ユーザーにフィールド画面を表示し、コネクター内のすべてのフィールドをリストする。
以下を含むスキーマの各フィールドに関する特定のメタデータを提供する。
  • フィールドの名前
  • フィールドのデータ型
  • 意味情報

詳細についてはgetSchema()およびFieldリファレンスを確認する。

コネクタのスキーマは固定されており、次の3つのフィールドが含まれている。
  • パッケージ名
    • ユーザーが提供するnpmパッケージの名前
  • ダウンロード
    • npmパッケージのダウンロード数
    • ダウンロード数の日付

getSchema()関数をコード.gsに追加してみる

コード.gs
function getFields(request) {
  var cc = DataStudioApp.createCommunityConnector();
  var fields = cc.getFields();
  var types = cc.FieldType;
  var aggregations = cc.AggregationType;
  
  fields.newDimension()
    .setId('packageName')
    .setType(types.TEXT);
  
  fields.newMetric()
    .setId('downloads')
    .setType(types.NUMBER)
    .setAggregation(aggregations.SUM);
  
  fields.newDimension()
    .setId('day')
    .setType(types.YEAR_MONTH_DAY);
  
  return fields;
}

function getSchema(request) {
  var fields = getFields(request).build();
  return { schema: fields };
}


9. Define getData() : Part 1
getData()によって提供される応答に基づいて、ダッシュボードでグラフをレンダリングおよび更新する。
以下の場合もgetData()が呼ばれる。
  • ユーザーがダッシュボードにグラフを追加する
  • ユーザーがチャートを編集する
  • ユーザーがダッシュボードを表示する
  • ユーザーは、関連するフィルターまたはデータコントロールを編集する
  • Data Studioにはデータのサンプルが必要です

リクエストオブジェクトの構造

{
  configParams: object,
  scriptParams: object,
  dateRange: {
    startDate: string,
    endDate: string
  },
  fields: [
    {
      name: Field.name
    }
  ]
}

getData()関数からのリクエストの例
{
  configParams: {
    package: 'jquery'
  },
  dateRange: {
    endDate: '2017-07-16',
    startDate: '2017-07-18'
  },
  fields: [
    {
      name: 'day',
    },
    {
      name: 'downloads',
    }
  ]
}


10. Define getData() : Part 2
getData()responseでは、要求されたフィールドにスキーマとデータの両方を提供する必要があり、コードを3つのセグメントに分割する。
  1. 要求されたフィールドのスキーマを作成する
  2. APIからデータを取得して解析する
  3. 解析されたデータを変換し、要求されたフィールドをフィルタリングする

getData()の構造
function getData(request) {

  // TODO: Create schema for requested fields
  
  // TODO: Fetch and parse data from API
  
  // TODO: Transform parsed data and filter for requested fields

  return {
    schema: <filtered schema>,
    rows: <transformed and filtered data>
  };
}


11. Define getData() : Part 3
getData()をコード.gsに書く。

コード.gs
function responseToRows(requestedFields, response, packageName) {
  // Transform parsed data and filter for requested fields
  return response.map(function(dailyDownload) {
    var row = [];
    requestedFields.asArray().forEach(function (field) {
      switch (field.getId()) {
        case 'day':
          return row.push(dailyDownload.day.replace(/-/g, ''));
        case 'downloads':
          return row.push(dailyDownload.downloads);
        case 'packageName':
          return row.push(packageName);
        default:
          return row.push('');
      }
    });
    return { values: row };
  });
}

function getData(request) {
  var requestedFieldIds = request.fields.map(function(field) {
    return field.name;
  });
  var requestedFields = getFields().forIds(requestedFieldIds);

  // Fetch and parse data from API
  var url = [
    'https://api.npmjs.org/downloads/range/',
    request.dateRange.startDate,
    ':',
    request.dateRange.endDate,
    '/',
    request.configParams.package
  ];
  var response = UrlFetchApp.fetch(url.join(''));
  var parsedResponse = JSON.parse(response).downloads;
  var rows = responseToRows(requestedFields, parsedResponse, request.configParams.package);

  return {
    schema: requestedFields.build(),
    rows: rows
  };
}


12. Update manifest
Appsスクリプトエディターで、[表示]> [マニフェストファイルを表示]を開く。


appscript.jsonファイルを書き換えて保存する。

appsscript.json
{
  "dataStudio": {
    "name": "npm Downloads - From Codelab",
    "logoUrl": "https://raw.githubusercontent.com/npm/logos/master/npm%20logo/npm-logo-red.png",
    "company": "Codelab user",
    "companyUrl": "https://developers.google.com/datastudio/",
    "addonUrl": "https://github.com/google/datastudio/tree/master/community-connectors/npm-downloads",
    "supportUrl": "https://github.com/google/datastudio/issues",
    "description": "Get npm package download counts.",
    "sources": ["npm"]
  }
}


これで最初のコミュニティコネクタを構築し、テストドライブの準備ができた。

13. Test your connector in Data Studio

ステップ1:
[公開]> [マニフェストから展開]を選択する。

ステップ2:
Latest Version (Head) をクリックするとリンクが表示されます。


ステップ3:
リンクをクリックして表示された画面で「承認」をクリックします。

Enter a single package name に「lighthouse」を入力して
「接続」をクリックします。


「レポートを作成」をクリックします。


「レポートに追加」をクリックします。


手順通り期間のグラフと期間の選択を配置する。



これで最初のコミュニティコネクタをテストできました。


14. Next steps


参考

コミュニティ コネクタを使ってみる
https://developers.google.com/datastudio/connector/get-started?hl=ja

Connect and visualize all your data in Data Studio
https://codelabs.developers.google.com/codelabs/community-connectors/#0




MacBook Air のモデルと技術仕様を知りたい


MacBook Air のモデルを識別する
https://support.apple.com/ja-jp/HT201862



モデルの確認手順


アップルアイコンの「このMacについて」を選択


出てきた画面の「MacBook Air (11-inch, Mid 2013)」がモデル




技術仕様を見たい

MacBook Air のモデルを識別する
のページでモデルを検索してみる



技術仕様の右のリンクをクリックすると
https://support.apple.com/kb/SP678?locale=ja_JP

そのモデルの技術仕様のページへ行ける



参考

MacBook Air のモデルを識別する
https://support.apple.com/ja-jp/HT201862

2020年2月7日金曜日

GASでアロー関数などが使えるようになった


Release Notes
https://developers.google.com/apps-script/releases#february_5_2020


V8 syntax examples に記載されているリストによると
  • let and const
  • Arrow functions
  • Classes
  • Destructuring assignments
  • Template literals
  • Default parameters
  • Multi-line strings
などが使えるらしい。


手順は簡単で

プロジェクトを開くとこのような表示が出る。(アカウントによってはまだ出ない)
「Enable」をクリックするだけ。



戻したい場合

Run メニューから戻すこともできる
 Run > Disable new Apps Script runtime powered by Chrome V8




既存のRhino runtimeとV8 runtimeの非互換性によって、移行後に既存のコードが失敗する可能性もあるらしい。(ほぼ大丈夫っぽいけど)

https://developers.google.com/apps-script/guides/v8-runtime/migration

失敗したら修正しよう。


参考

https://developers.google.com/apps-script/releases
February 5, 2020
Apps Script now supports the V8 runtime. This enables modern JavaScript features and syntax in Apps Script. You can migrate existing scripts to use V8 and its features.
V8 Runtime Overview
https://developers.google.com/apps-script/guides/v8-runtime

Migrating scripts to the V8 runtime
https://developers.google.com/apps-script/guides/v8-runtime/migration

V8 syntax examples
https://developers.google.com/apps-script/guides/v8-runtime#v8_syntax_examples

Modern JavaScript features
https://developers.google.com/apps-script/guides/services/#modern_javascript_features
The V8 runtime supports modern ECMAScript syntax and features. The Rhino runtime is based on the older JavaScript 1.6 standard, plus a few features from 1.7 and 1.8. You can freely choose which runtime to use with your script, but the V8 runtime is strongly recommended.

2020年2月5日水曜日

Salesforce APIの接続アプリケーションでOAuth範囲の説明を知りたい


接続アプリケーションを作成する際に選択する OAuth Scope について
それぞれの項目の意味を知りたくて調べたときに見つけたページ。

API インテグレーション用の OAuth 設定の有効化
https://help.salesforce.com/articleView?id=connected_app_create_api_integration.htm&type=5


関連記事

接続アプリケーションの作成方法は以下のブログに書きました。

OAuth によるアプリケーションの認証

接続アプリケーションを作成したい
接続アプリケーションを作成したい(Lightning)


2020年2月4日火曜日

Salesforce APIでCaseのコメントを取得したい


指定したCaseのコメントを取得するには
/sobjects/Case/CASE ID/CaseComments

上記のようにCASE IDを指定して/CaseCommentsで取得できました。



ここで使うCase IDとは
対象ケースを開いた時にアドレスバーのCase/の後に表示される文字列↓




事前準備

接続アプリケーションを作成して
アクセストークンなどのデータをスクリプトのプロパティに保存しておく

手順は以下のブログに書きました。

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)



コメントを作成しておく



コード.gs
function getData() {
  var options = {
    "method" : "GET",
    "headers" : {
      "Authorization": "Bearer " + getProp("access_token")
    }
  }
  var url = getProp("instance_url") + "/services/data/v47.0/sobjects/Case/5002w000002HSlkAAG/CaseComments";
  var response = UrlFetchApp.fetch(url, options);
  Logger.log(response);
}

function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}


getData()を実行すると、以下のような結果が返ってきました。

実行結果
{
  "totalSize": 1,
  "done": true,
  "records": [{
    "attributes": {
      "type": "CaseComment",
      "url": "/services/data/v47.0/sobjects/CaseComment/00a2w000000DatqAAC"
    },
    "Id": "00a2w000000DatqAAC",
    "ParentId": "5002w000002HSlkAAG",
    "IsPublished": false,
    "CommentBody": "最初のコメント。",
    "CreatedById": "0052w000001oTfEAAU",
    "CreatedDate": "2020-02-03T02:30:43.000+0000",
    "SystemModstamp": "2020-02-03T02:30:43.000+0000",
    "LastModifiedDate": "2020-02-03T02:30:43.000+0000",
    "LastModifiedById": "0052w000001oTfEAAU",
    "IsDeleted": false
  }]
}


関連記事

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)


参考

レコードの操作
https://developer.salesforce.com/docs/atlas.ja-jp.222.0.api_rest.meta/api_rest/using_resources_working_with_records.htm

サンプルコードを実行する
https://developer.salesforce.com/docs/atlas.ja-jp.222.0.api_rest.meta/api_rest/quickstart_code.htm

Salesforce APIでAccountの情報を更新したい


ここで使うAccount IDとは


今回は「説明」を更新してみます。


公式のPATCHのサンプルでは、jsonファイルを作ってcurlで実行していますが
このブログでは、GASで全部コードの中に書いて実行する例を書きます。


このように更新するデータを指定してJSONデータを作ってやる。

function createPayload() {
  var obj = {
    "Description" : "説明を書き換える。"
  }
  var json = JSON.stringify(obj);
  return json;
}


事前準備

接続アプリケーションを作成して
アクセストークンなどのデータをスクリプトのプロパティに保存しておく

手順は以下のブログに書きました。

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)



コード.gs
function patchData() {
  var options = {
    "method": "PATCH",
    "headers": {
      "Authorization": "Bearer " + getProp("access_token"),
      "Content-Type": "application/json"
    },
    "payload": createPayload()
  }
  var url = getProp("instance_url") + "/services/data/v47.0/sobjects/Account/0012w000004AAugAAG";
  var response = UrlFetchApp.fetch(url, options);
  Logger.log(response);
}

function createPayload() {
  var obj = {
    "Description" : "説明を書き換える。"
  }
  var json = JSON.stringify(obj);
  return json;
}



patchData()を実行すると、Logger.log(response)には何も返ってきていませんが


取引先のページを読み込み直すと「説明」が更新されていました。



関連記事

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)


参考

サンプルコードを実行する
https://developer.salesforce.com/docs/atlas.ja-jp.222.0.api_rest.meta/api_rest/quickstart_code.htm

Salesforce APIで指定したCaseの情報を取得したい


ここで使うCase IDとは
対象ケースを開いた時にアドレスバーのCase/の後に表示される文字列↓




事前準備

接続アプリケーションを作成して
アクセストークンなどのデータをスクリプトのプロパティに保存しておく

手順は以下のブログに書きました。

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)



コード.gs
function getData() {
  var options = {
    "method" : "GET",
    "headers" : {
      "Authorization": "Bearer " + getProp("access_token")
    }
  }
  var url = getProp("instance_url") + "/services/data/v47.0/sobjects/Case/5002w000002HSlkAAG";// Case IDのデータを取得する
  var response = UrlFetchApp.fetch(url, options);
  Logger.log(response);
}

function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}


getData()を実行すると、以下のような結果が返ってきました。

実行結果
{
  "attributes": {
    "type": "Case",
    "url": "/services/data/v47.0/sobjects/Case/5002w000002HSlkAAG"
  },
  "Id": "5002w000002HSlkAAG",
  "IsDeleted": false,
  "MasterRecordId": null,
  "CaseNumber": "00001006",
  "ContactId": "0032w000002UiHqAAK",
  "AccountId": "0012w000004AAugAAG",
  "ParentId": null,
  "SuppliedName": null,
  "SuppliedEmail": null,
  "SuppliedPhone": null,
  "SuppliedCompany": null,
  "Type": "問題",
  "Status": "エスカレーション済み",
  "Reason": "既存の問題",
  "Origin": "Web",
  "Subject": "(サンプル)Service Cloud の使い方",
  "Priority": "中",
  "Description": null,
  "IsClosed": false,
  "ClosedDate": null,
  "IsEscalated": false,
  "OwnerId": "0052w000001oTfEAAU",
  "CreatedDate": "2020-01-16T04:17:22.000+0000",
  "CreatedById": "0052w000001oTfEAAU",
  "LastModifiedDate": "2020-02-03T02:04:50.000+0000",
  "LastModifiedById": "0052w000001oTfEAAU",
  "SystemModstamp": "2020-02-03T02:04:50.000+0000",
  "ContactPhone": "(06) 6666-1111",
  "ContactMobile": "090-0000-0000",
  "ContactEmail": "info@salesforce.com",
  "ContactFax": "(06) 6666-1112",
  "Comments": null,
  "LastViewedDate": "2020-02-03T02:04:50.000+0000",
  "LastReferencedDate": "2020-02-03T02:04:50.000+0000",
  "Channel__c": "<img src=\"/resource/OriginIcon/Web.png\" alt=\"Web\" style=\"height:22px; width:22px;\" border=\"0\"/>",
  "PriortyIcon__c": "<img src=\"/img/samples/flag_yellow.gif\" alt=\"priority flag\" border=\"0\"/>",
  "Product__c": null
}


関連記事

SalesforceでAPIを使うために接続アプリケーションを作成したい
Salesforceで接続アプリケーションを作成したい(Lightningの方で)


参考

サンプルコードを実行する
https://developer.salesforce.com/docs/atlas.ja-jp.222.0.api_rest.meta/api_rest/quickstart_code.htm

Latest post

Google Apps Scriptの障害時はIssueTrackerを見てみる - Incidents for Apps Script are reported on Issue Tracker

IssueTracker > Apps Script issues https://issuetracker.google.com/savedsearches/566234 Google Apps Scriptの障害時は IssueTracker に課題が上がっていることが...