[Nuxt.js]2.9以下 Google material icon(マテリアルアイコン)を使う

みんな大好きGoogle fontsではアイコンも利用できますね。私は少し前までfontawesomeを使用していたのですが、最近はちょっと非推奨の環境が増えてきたので、Google fontsのアイコンに鞍替えしました。

以下はnuxt.js2.9以下で実装するための手順です。それ以降はこちらの記事にまとめました。

[Nuxt.js]2.9以上 Google material icon(マテリアルアイコン)を使う

参考

https://developers.google.com/fonts/docs/material_icons

https://fonts.google.com/icons?selected=Material+Icons

nuxt.config.jsにリンクを追加

nuxt.config.jsにGoogle Material Iconsのリンクを追加します。


    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
      {
        rel: 'stylesheet',
        href: 'https://fonts.googleapis.com/icon?family=Material+Icons',
      },
    ],

Google fontsサイトから使いたいアイコンを取得

下記サイトでアイコンを検索し、任意のアイコンを選択します。

https://fonts.google.com/icons?selected=Material+Icons

選択すると右側にコードが出ますので。

material icon

コピーします。

ページやコンポーネントにペースト

試しにheader.vueへ入れてみました。

header.vue
header.vue

表示結果

※左端のシェアアイコンです

[Nuxt.js]コンポーネントが表示されない(nuxt.config.jsにパスは通した?)

久しぶりにNuxtプロジェクト作成していつも通りコンポーネント作成したらコンポーネントが表示されなくて困ったので備忘録。Atomic Design(アトミックデザイン)など、componentsフォルダの中に分類のためのフォルダを作成している人のための記事です。

結論から言うと、

  • 新バージョンではコンポーネント名に内包されているフォルダ名をつけなければいけない(例:Atomsフォルダに入っているButton.vueコンポーネントは<AtomsButton/>と表記)
  • それが嫌ならnuxt.config.jsでパス通してね(下記に記載)

ということでした。

全部公式に載ってます。

https://nuxtjs.org/docs/directory-structure/components/#nested-directories

当方環境

  • @nuxt/cli v2.15.8
  • MacOS 12.1

nuxt.config.jsでパスを通す

以下公式からの引用ですが、

components/
  base/
      foo/
         CustomButton.vue

このような階層構造を持つコンポーネントをほかのコンポーネントやページで使用する際、コンポーネントの記載はこのようになります。

<BaseFooCustomButton />

でもいちいち上位フォルダの名前記載するの面倒ですよね。というわけパスを通します。
nuxt.config.jsを開き、componentsの箇所に追記します。

以下、Atomic Designを採用している場合の例です。

  components: {
    dirs: [
      '~/components',
      '~/components/atoms',
      '~/components/molecules',
      '~/components/organisms',
    ],
  },

これで、今まで(?)通り、コンポーネントのタグ名は<Button />のみでOKとなりました!

 

めでたしめでたし。

 

 

Webサイト制作 開発環境構築(Local環境)の流れ

備忘録です。

環境・前提

下記の環境・前提で開発しています。

  • Mac OS Monterey 12.1
  • Google Chrome  101.0.4951.54(Official Build) (arm64)
  • VSCode
  • Git管理

免責

仕事としてのWebサイト制作業務経験は多くなく、初学者です。

ドメイン名・サーバの確認

※ドメイン名とサーバがどのようにローカル環境に関わってくるか

 

ディレクトリを作成

デスクトップやDocumentsの中など、任意の場所にプロジェクトフォルダを作成します。

ネーミングは[projectname_frontend]などのようにしています。

例:

  • NPO法人Xのフロント作成の場合 … npox_frontend
  • 株式会社Yのバックエンド作成の場合 … y_backend

VSCodeで開く

VSCodeを起動し、⌘+Oから作成したプロジェクトフォルダを選択。

まだ何もない状態

New Fileを選択したらindex.htmlを作成します。

作成したhtml内で半角!を入力し、tabキーを押下するとhtmlのフォーマットが出てくるはずです。

あるいはHTMLテンプレートのBoilerplateを使っても良いと思います。

https://html5boilerplate.com/

langをjaに変更、title入力など現時点でわかる箇所を入力し、保存(⌘+S)。

全体の骨組みだけ先にマークアップしておきます。

VSCodeの場合は(htmlファイル内で)下記画像の状態でEnterキーを押すとHTMLに変換してくれます。省エネ!

VSCode成形前
VSCode成形後

ざっくり枠組み

<div id="wrap" class="st-wrap">
  <header id="header" class="sp-header">
     <h1 class="sp-header-logo">
       <a href="">
         <img src="" alt="" />
       </a>
     </h1>
     <p>test view</p>
  </header>

  <main id="container" class="sp-container"></main>

  <div class="sp-pagetop js-scrolltop" style="display: none"></div>

  <footer id="footer" class="sp-footer"></footer>
</div>
ちなみに保存したプロジェクトを素早くブラウザで確認するためのプラグインがあります。下記にまとめましたので、気になる方はぜひ。
https://nolyc.net/programming/vscode-live-server/

git管理

チームで分業したりしているとgit管理が必要になります。そうでなくても、一通りコーディングを終えた後にやっぱり前のバージョンに戻したい!という時があるので、私はどのプロジェクトでもgit管理はしておくことにしています。
会社ではbacklogを使用していますが、個人の方であればgithub(非公開)で管理するなどすれば良いと思います。
githubでのやり方は下記にまとめました。
https://nolyc.net/programming/git-connect-localtoremote/
上記記事ではSourceTreeを使用したGit管理方法を記載していますが、何もSourceTreeを使用せずともGit管理はVSCode上でできます。
https://code.visualstudio.com/docs/editor/versioncontrol
ここでは詳しい操作は省きますが、気になる方はググってみてください。
私が行った手順は以下の通りです。

VSCode上でのGit初期化

赤のアンダーラインが実行コードです

VSCode上でのGit初期化
VSCode上でのGit初期化
  1. VSCode上で⌘ + jでターミナルを開き
  2. cd ディレクトリパス(パスはVSCodeのフォルダ名を選択しOption + ⌘ +Cで取得できる)で該当ディレクトリに移動
  3. gitを初期化(git init)
  4. ブランチ名を変更(git branch)
  5. 現在のワークツリーの内容を全てindexに追加(git add *)
  6. コミット(git commit -m ‘first commit’)

GitHubへのリモートリポジトリへのpush方法は先ほど紹介した記事「[git]すでに作成したフォルダをgit管理してリモートと紐付け」にも書きました。

 

以降、随時アップデートしていく予定です。

 

 

WordPress プラグインYoast SEOのフィルター一覧

ただの備忘録。

WordPressのプラグインYoast SEOを使っているのですが、便利機能故にカスタマイズしにくい…と思いきや、ちょっとしたカスタマイズのためにTeam Yoastからフィルターが提供されていました。

フィルター一覧が載っています↓

http://hookr.io/plugins/yoast-seo/4.7.1/filters/

例えば私は別のプラグイン、Polylangで多言語サイトを作成しているのですが、固定ページには個別のtitle, descriptionを設定する箇所が管理画面下の方に用意してされているものの、

TOPページは管理画面サイドメニューのSEO>検索での見え方 から設定する仕様となっているため、英語ページのTOP(/en)でも日本語のmeta情報が採用されてしまうのです。

なので、上記サイトHOOKERからそれらしき単語を検索し(meta description関係はdescで出てくる)、欲しいフィルターかどうかチェックします。

以下、英語のトップページでのみtitleとmeta descriptionを変える場合のコードです。function.phpに記載しました。

function get_current_url() {
return(is_ssl()? 'https':'http').'://'.$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
}
$current_uri = get_current_url();
$home_uri = home_url('/');

// define the wpseo_title callback 
function my_en_title($title) {
return 'Welcome to the new environment|Hellow World!';
}
// define the wpseo_metadesc callback 
function filter_wpseo_metadesc( $trim ) { 
// make filter magic happen here... 
return 'Hellow world is a whole new approach to internet environments, one designed with the knowledge and know-how based on xxx years....'; 
}; 

if($current_uri == $home_uri.'en/' || $current_uri == $home_uri.'en') {
add_filter('wpseo_title', 'my_en_title');
add_filter( 'wpseo_metadesc', 'filter_wpseo_metadesc', 10, 1 ); 
}

参照: http://hookr.io/plugins/yoast-seo/4.7.1/filters/wpseo_metadesc/

 

 

GAS(Google Apps Script)でGoogleフォームを作成-選ばれた選択肢でメール送信先を変更

つい最近、Google Apps Script(以下GAS)というGoogleフォームを操作・カスタマイズできる機能を知ったので、備忘録。

GAS公式 https://developers.google.com/apps-script

今回やりたいこと

  • Googleフォームで用意した選択肢の内容によって、連絡先を変更する。

店舗をいくつか持っている会社があるとしましょう。ユーザからの問い合わせは選択された店舗の担当者に対応してもらいたいので、回答は店舗担当者に送信されるようにカスタマイズします。

 

そもそもGASとはなんぞ

公式の日本語ドキュメントがないので(ないよね?)アレルギー起こしている人も多いのではないかと思います。

冒頭ではGoogle Formを操作できる〜と申し上げましたが、公式を見ると他の色々なGoogleアプリを操作・カスタマイズできる機能のようですね。以下公式から引用。

Google Apps Script is a rapid application development platform that makes it fast and easy to create business applications that integrate with Google Workspace. You write code in modern JavaScript and have access to built-in libraries for favorite Google Workspace applications like Gmail, Calendar, Drive, and more. There’s nothing to install—we give you a code editor right in your browser, and your scripts run on Google’s servers.

GメールやGoogleカレンダー、ドライブ、といったGoogleのワークスペースと統合できるアプリ開発のプラットフォーム、とありますね。アプリのインストール不要、ブラウザ上で開発できて、みんな大好きJavaScriptで書けるので便利だよ!というわけです。

ご丁寧に、JavaScriptをご存じない方にはレッスンの案内もされています。

Codecademy https://www.codecademy.com/catalog/language/javascript

GASで具体的に何ができるのか

こちらも公式からの引用ですが、

  • GoogleドキュメントやGoogleスプレッドシート、Googleフォームでのオリジナルメニュー、ダイアログ、サイドバーの作成
  • Googleスプレッドシートでのオリジナル機能、マクロの作成
  • Webアプリの開発…Googleサイトでの独立した、あるいは埋め込みのアプリを作ってローンチ
  • Google AdSenseやGoogleカレンダー、Googleドライブ、Gメール、Googleマップとの連携
  • Google Workspace Marketplaceでアドオンを作成して公開

(意訳ですので参考程度でお願いします)

Googleフォームを作成

できることは色々あれど、今回はこのGASを使ってGoogleフォームをカスタマイズ。

  • Googleフォームで用意した選択肢の内容によって、連絡先を変更する

のですが、細分化するとこんな感じ

  1. Googleフォームの送信
  2. 回答者にメール送信
  3. 管理者側へのメール送信(回答の選択肢によってメール振り分け)

1,2まではGAS使わなくてもできますね。ただ、GASで用意しておくと同じフォームを秒で作れるようになるのでその点でも便利です。

Google フォームを作成

今回は、Googleフォームで受け取った値を元に色々操作してみたいと思いますので、一旦Googleフォームを作成して、返ってくる値を確かめてみようと思います。

フォームの内容はこんな感じ

冒頭のメールアドレス設定はタブの設定>回答>メールアドレスを収集するのトグルをONにするとできます。

GASを作成

フォームのメニュー3点リーダからスクリプトメニューを選択します。

初期状態はこれ。

function myFunction(e) {

}

function myFunction() {}とありますね。この{}の中に、カスタマイズしたい処理を書いていきます。myFunctionの部分は、好きな名前に変更してもOKです。今回はフォーム送信時に、連絡のない店舗へお知らせが届くようにしたいのでautoNotifyとします。

ここで()内に引数(今回はeとします。eventのeですが、なんでもOKです)を入れておくと、送信ボタンが押された際に、回答データがeに入り、あらかじめ用意されている関数onSubmitに渡されます。では実際にどのような内容が入っているのか確認してみましょう。

function autoNotify(e) {
  console.log(e)
}

Google フォームとGASを紐付け

Googleフォームの送信ボタンが押された時にスクリプトが実行されるよう、Google フォームとGASを紐付けします。

トリガーを設定

左のサイドメニュー時計アイコンのトリガーを選択し、

トリガーを追加。

トリガーの設定内容は以下の通り。設定できたら保存ボタンを押下します。

  • 実行する関数を選択 -> autoNotify
  • 実行するデプロイを選択 -> Head
  • イベントのソースを選択 -> フォームから
  • イベントの種類を選択 -> フォーム送信時
  • エラー通知設定 -> 毎日通知を受け取る

保存ボタンを押すとGASを承認するためのポップアップが出ますので、任意のGoogleアカウントを選択して次に進んでください。

これでトリガーが設定できました。

フォームが送信された時に入っている値を見てみよう

先ほどGASで書いたeの部分を確認してみましょう。実際にフォームを入力して、送信します。

フォーム画面右上の送信ボタンから、フォーム回答のための共有リンクを取得できます。

個人の別Googleアカウントからフォームを入力し、回答を送信しました。

GASの編集画面に戻り、左サイドメニュー実行数から、ログを確認できます。

オブジェクトで色々な値が取れていますね。

ちなみにconsole.logではなくLogger.logを使うとオブジェクトが返ってきていることしかわかりません。

console.logとLogger.logの使い分けは下の記事で詳しく解説していただいていました(謝謝!)。

GASでログ出力する2つの方法(Logger.logとconsole.log)の紹介と使い分け

回答データeはこのようにオブジェクトで返ってきているので、その返ってきている値から必要な情報を取り出し、処理を書きます。

今回は、

2. 回答者にメール送信
3. 管理者側へのメール送信(回答の選択肢によってメール振り分け)

をするので、回答者のメールアドレスと、選択された店舗情報を取り出す必要があります。回答内容は、Googleフォーム送信ボタンを押して返ってきた情報(e)の中の、response内、getItemResponses部分から取得できます(e.response.getItemResponses)。

{
toString: [Function],
authMode: {
toString: [Function: toString],
name: [Function: toString],
toJSON: [Function: toString],
ordinal: [Function: ordinal],
compareTo: [Function: compareTo],

// ちょっと省略

FULL: [Circular]
},
response: {
toString: [Function],
submit: [Function],
getId: [Function],
getTimestamp: [Function],
getRespondentEmail: [Function],
getItemResponses: [Function],
getGradableItemResponses: [Function],
getResponseForItem: [Function],
getGradableResponseForItem: [Function],
withItemResponse: [Function],
withItemGrade: [Function],
toPrefilledUrl: [Function],
getEditResponseUrl: [Function]
},

// だいぶ省略

triggerUid: '11025413'
}

フォームのレスポンス(e.response)から値を取り出すメソッドは公式にまとめられています。

https://developers.google.com/apps-script/reference/forms/form-response

getItemResponses() ItemResponse[] Gets all item responses contained in a form response, in the same order that the items appear in the form.

*フォームから受け取った値の全てのresponseアイテムを取得。値はフォームに入っているのと同様の順番で格納されています。

便利ですね〜

では早速これで値を取り出して見てみましょう。

GASのエディタに戻り、コードを書き換えます。

function autoNotify(e) {
  // 質問内容と回答を取得
  const itemResponse = e.response.getItemResponses();

  console.log(itemResponse);
}

スクリプトを保存(⌘+s)したら、フォームをもう一度送信し、GASメニューのログを確認します。

[{
toString: [Function],
getScore: [Function],
setScore: [Function],
getFeedback: [Function],
getResponse: [Function],
getItem: [Function],
setFeedback: [Function]
},
{
toString: [Function],
getScore: [Function],
setScore: [Function],
getFeedback: [Function],
getResponse: [Function],
getItem: [Function],
setFeedback: [Function]
},
{
toString: [Function],
getScore: [Function],
setScore: [Function],
getFeedback: [Function],
getResponse: [Function],
getItem: [Function],
setFeedback: [Function]
},
{
toString: [Function],
getScore: [Function],
setScore: [Function],
getFeedback: [Function],
getResponse: [Function],
getItem: [Function],
setFeedback: [Function]
},
{
toString: [Function],
getScore: [Function],
setScore: [Function],
getFeedback: [Function],
getResponse: [Function],
getItem: [Function],
setFeedback: [Function]
}
]

配列の中に、それぞれの質問内容と回答の情報がオブジェクトに格納されています。

1つ目の質問・回答群から順に、配列の[0],[1],[2]…と格納されています。

最初のメールアドレスはフォーム作成時の設定内のトグルから作成したため、e.response.getItemResponsesとは別の場所に格納されています(後述)。

 

フォームで送信された質問と回答をログ出力してみる

では、空の配列 answerListを用意して、フォームから得られた質問と回答を入れてみましょう。

function autoNotify(e) {
  // 質問内容と回答を取得
  const itemResponse = e.response.getItemResponses();

  let answerList = [];

  // 答えた質問の数だけ繰り返し
  for (let i=0; i<itemResponse.length; i++) {
    let question = itemResponse[i].getItem().getTitle();
    let answer = itemResponse[i].getResponse();

    // 回答が入力されていればその値を、そうでなければ未回答を入れる
    answer ? answerList.push(question + ':' + answer)
      : answerList.push(question + ':' + '未回答');
  }
console.log(answerList);
}

スクリプトを保存(⌘+s)したら、フォームをもう一度送信し、GASメニューのログを確認します。

いい感じですね!

回答者にメール送信

フォームの回答ボタンが押されたらまず回答者にお礼メールを送りたいですね。

メール送信には、GmailAppというGメールアプリへのアクセスを提供するクラスを使用します。メソッド一覧はこちら

https://developers.google.com/apps-script/reference/gmail/gmail-app

上記リファレンスのsendEmailメソッドを使います。

まずはsubjectに件名、bodyに本文を定義します。

// 回答者にメール送信
// 回答者のメールアドレスを取得
const recipient = e.response.getRespondentEmail();
// 件名
const subject = '【回答者側 自動通知】お問い合わせ受付完了'
 
// 本文
const body = 'お問い合わせ受付が完了しました。\n\n内容にお間違いがないかご確認頂きますようお願いいたします。\n\n============\n' + answerList.join('\n') + '\n============\n';

その下にメソッドを追加

Gmailapp.sendEmail(recipient, subject, body);

実はGASのスクリプト内でGmailApp.sendEmail(...と入力すると文法も出てきてくれます。便利!

再びフォームを入力してデバッグしましょう!

スクリプトを保存(⌘+s)したら、フォームをもう一度送信し、スクリプトを保存(⌘+s)したら、入力したメールアドレスに届いたメールを確認します。

私はこの際、マニフェストを登録しておらず引っかかりました。ログから下記のようなエラーが出る場合は、マニフェストを追記しましょう。

やり方は以下の記事にまとめました。

GASのメール送信ができない…それならマニフェスト設定だ(appsscript.json)

のですが、調べていたらどうやらGmailAppよりMailAppの方が良さそうだ(配信速度が速いとかなんとか)…ということでメール送信部分は下記のようにしました。

Mailapp.sendEmail(recipient, subject, body);

管理者側へのメール送信(回答の選択肢によってメール振り分け)

さて、メール送信ができたところで今度は、設問1で選ばれた値によって、メール送信先の店舗先を変える…という機能を追加します。

設問1

設問1はitemResponse[0]に格納されています。getResponseメソッドでユーザーの選択した回答を取得し、mailGetShopに代入しました。Array.isArrayで、返ってきた値が配列であることを確認します。

// 管理者側へのメール送信(回答の選択肢によってメール振り分け)
let mailGetShop = itemResponse[0].getResponse();

// console.log(mailGetShop); // ['◯◯工務店','□□ハウス']
// console.log(Array.isArray(mailGetShop)); // true

今回は試しに'◯◯工務店','□□ハウス'の2店舗にチェックを入れて、テストをします。店舗ごとに、名前とメールアドレスがセットになったオブジェクトを作成し、配列shopListに代入。

今回は'◯◯工務店','□□ハウス'の2つがチェックされたので、hogehoge@hogemail.comunchi@hogemail.comにメールが配信されるようにしたいです。

let adminRecipient = [];
const shopList = [
{'◯◯工務店':'hogehoge@hogemail.com'},
{'□□ハウス':'unchi@hogemail.com'},
{'△△不動産':'nekoinochi@hogemail.com'}
];

shopListの数だけ、mailGetShopに入っている値を検索します。やり方はいろいろありましょうが…私は、indexOfで検索した値がなかった場合は-1を返すという特性を利用して、trueだった時にmailGetShopのメールアドレスをadminRecipientへpushする方法を取りました。


for (let i=0; i<shopList.length;i++) {
let target = Object.keys(shopList[i]).toString();
let result = mailGetShop.indexOf(target);
0<=result ? adminRecipient.push(Object.values(shopList[i])): null;
}
console.log(adminRecipient);  // ['hogehoge@hogemail.com','unchi@hogemail.com']

次は、adminRecipient内のアドレスへお知らせメールを送信します。これは先ほどの、回答者へのメール送信と同様ですね。

// 管理者へのメール文
let adminSubject = "【管理者側 自動通知】Googleフォームで新規回答を受け付けました";

let adminBody = 'Googleフォームで新規回答を受け付けました。\n\n内容を確認しご対応をお願いいたします。\n\n============\n'
+ answerList.join('\n')
+ '\n============\n';

//管理者にメール送信
MailApp.sendEmail(strAdminRecipient, adminSubject, adminBody);

ただ、先ほど得られたメールアドレスですが、配列の方がその後色々いじりやすいかと思っていたものの、MailApp.sendEmail()のrecipient(第一引数)はカンマ区切りのStringで渡さなければいけないらしいです。

recipient String the addresses of the recipients, separated by comma

https://developers.google.com/apps-script/reference/mail/mail-app#sendemailrecipient,-subject,-body

というわけで、MailApp.sendEmail(strAdminRecipient, adminSubject, adminBody);の前に以下を1行足します。

let strAdminRecipient = adminRecipient.join(',');

コードがかけたら例に倣って保存し、フォームを送信してデバッグ内容を確認します。

無事通りましたか?通ってくれ!

 

GASのメール送信ができない…それならマニフェスト設定だ(appsscript.json)

Googleフォームで入力されたメールアドレス宛にメールを自動送信するよう設定したく、GAS(Google Apps Script)でGmailApp.sendEmailを使おうとしたら権限がないって蹴られちゃいました。

Exception: スクリプトにはその操作を行う権限がありません。その操作を行うには「(https://www.googleapis.com/auth/gmail.send || https://www.googleapis.com/auth/gmail.compose || https://www.googleapis.com/auth/gmail.modify || https://mail.google.com/ || https://www.googleapis.com/auth/gmail.addons.current.action.compose)」権限が必要です。
at autoNotify(コード:27:12)

気を取り直してMailApp.sendEmailを使っても同じようなエラー。console.logでメールアドレス自体は取れているけれど、メール送信ができていません。

Exception: MailApp.sendEmail を呼び出す権限がありません。必要な権限: https://www.googleapis.com/auth/script.send_mail
at autoNotify(コード:28:11)

https://www.googleapis.com/auth/script.send_mail

You are receiving this error either because your input OAuth2 scope name is invalid or it refers to a newer scope that is outside the domain of this legacy API.

This API was built at a time when the scope name format was not yet standardized. This is no longer the case and all valid scope names (both old and new) are catalogued at https://developers.google.com/identity/protocols/oauth2/scopes. Use that webpage to lookup (manually) the scope name associated with the API you are trying to call and use it to craft your OAuth2 request.

APIが別ドメインなのでOAuth的に良くないよ、ってことなんでしょうか。

兎にも角にもGAS上でマニフェストを設定することにします。

appsscript.jsonにoauthScopesを追加

左サイドメニューのプロジェクトの設定>

【GAS】GmailAppに対するマニフェスト設定>全般設定から「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れます。

エディタに戻るとappscript.jsonが可視化されるようになりました。

ここにoauthScopesを加えて、指摘のあったapiを配列で追加します。

{
  "timeZone": "America/New_York",
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.send_mail",
    "https://www.googleapis.com/auth/gmail.modify"
  ],
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}

公式のリファレンスはこちら

https://developers.google.com/apps-script/concepts/scopes

トリガーを削除・再登録

appsscript.jsonを保存し、トリガーを登録し直します。

削除したら再登録。再登録の際は認証を求められます。しめしめ。

ついでに、GmailAppよりMailAppの方が配信速度が速いらしいのでコードもMailApp.sendEmail()に書き換え。

再度フォームを送信して、ログと、メールが送信できているか確認。

メールOK!ログ、OK!

終わりに。

appsscript.jsonにoauthScopes追加したスコープなのですが、実はどのスコープを追加すればいいのか記載してある箇所がわからなかったため、参考サイトを元に追加しました。詳しい方いたら教えてください。私は上記2つのスコープ追加でメール送信ができました。

参考:

https://qiita.com/hisayuki/items/725110707d8abc8796d8

 

[git]すでに作成したフォルダをgit管理してリモートと紐付け

すでにローカル上で作成したプロジェクトのディレクトリをgit管理にし、リモートと紐付ける際の手順を自分用にまとめます。

環境・使用ツール

  • Mac OS Monterey 12.1
  • VSCode
  • Sourcetree
  • GitHub

まずはローカルフォルダをgit管理

Finderで対象ディレクトリを右クリックし、Optionボタンを押すと”directory name”のパス名をコピーという選択肢が現れて便利です。terminalの移動ではこれを選択し、cdの後に貼り付け。git initします。

cd /Users/neko/Documents/my_project
git init

SourceTreeの設定

New…からAdd Existing Local Repositoryを選び、対象ディレクトリを選択するだけ。

リモートリポジトリを設定

まずはGitHubでリポジトリを作成

GitHubでは右上の+ボタンからNew Repositoryを選択。

任意のリポジトリ名、設定を行い、Create repositoryボタンを押下。

ぶっちゃけここで出てくる画面にリモートリポジトリの追加方法は書いてありますが、必要なのはこの情報です。HTTPS方式でやるか、SSH方式でやるかでURLのやり方は変わります。

  • HTTPS
git remote add origin https://github.com/userName/test-repository.git
  • SSH
git remote add origin git@github.com:userName/test-repository.git

ディレクトリ内全てをステージング・ファイル追加

一旦、ディレクトリ内全てのファイルをステージングし、Git管理下にします。

git add *

そしてコミット

git commit -m 'first Commit.'

プッシュ

git push origin master

HTTPSとSSHのやり方を混ぜ込んでしまった人(俺)はここでエラーが出ます。URLを修正しましょう。

現在のリモートURLを確認し、新しいリモートURLに変更

git remote -v
git remote set-url origin {new url}

参考:gitのremote urlを変更する(レポジトリ移行時)

 

弊社ではSourcetreeを使っているため、この後はSourcetree BranchメニューにてRemoteにmasterブランチを作成し、ローカルにdevelopブランチ、feature/20220401_functionブランチを作成しました。

補足

GitHub使われている方、git push origin branch名すると、今はエラーが出ます。どうやら2021年8月にパスワード認証が廃止されたそう。パーソナルアクセストークンが必要です。

参考:GitHubでhttpsのパスワード認証が廃止された。Please use a personal access token instead.

 

 

[Sourcetree基礎]プロジェクトで使用する際の最初の一歩

どうもお世話になっております。

Sourcetreeを使用したGitの管理方法について、会社でやったことを備忘録として残しておきます。

当方、Sourcetreeを使うのはもう10年以上前に遡りまして…記憶もクソもなかったため、使い方がおぼつかなくとても恥ずかしかったです、はい。

そもそもGitの管理はVSCodeでできるという話もありましょうが、Sourcetreeを使用しているところはまだまだたくさんあると想像しますので、この記事がいつかの誰か(主に自分w)のためになればなと思います。

そもそもSourcetreeってなに?という方は、Googleさんに聞けば私なんぞのところより詳しい記事がたくさん転がっておりますのでそちらをご参照ください。

プロジェクトで主に必要なSourcetreeの使い方

プロジェクトのソースを自分のPCに引っ張ってきたい

「これ、プルして動かせるようにしておいて」

そう言われて渡されたのはあるURL。

https://xcompany. backlog.com/git/PROJECT/task.git

URLをブラウザで叩いてもアクセスできません。(←バカ〜!)

どないせーっちゅうんじゃ!とあわてふためき、調べつつもう一人の同僚に相談させてもらいつつ何とかプルして動かせるようにできました。

まずはSourcetreeを開きます。

メニューバー下の新規から「URLからクローン」を選択します。

こんな具合で保存先に空のディレクトリを指定し、「クローン」を押します。パス?何じゃら?という方は赤枠の「…」を選ぶと、GUI形式で保存先を指定します。空のファイルを作成しましょう。

クローンできました!あとは、VSCodeなり何なりでプロジェクトを開き、runさせるだけです。(これにまた時間がかかったのですが、こればっかりは開発環境に左右されますので個別のツールやアプリケーションのやり方を調べてください。

自分の作業範囲をメインブランチと分ける

さあ、プロジェクトをクローンできたのは良かったものの、このままローカルで自分の作業範囲を終えプッシュしたら袋叩きに会います。というわけで、新しく自分のブランチを切り(ブランチの作成)、切り替えましょう(チェックアウト)。

Sourcetreeのプロジェクト画面の右上アイコンの中の、「ブランチ」を選択します。

こんな感じでスラッシュを入れるとフォルダっぽく管理できます。

これで「ブランチを作成」ボタンを押すと、ブランチが作成できます。

できた!

該当ブランチへ切り替えるには、ダブルクリックするだけ。太字で◯がついているのが、現在選択されているブランチです。試しに何かファイルを作成し、コミットしてから他の作業ブランチに切り替えると、finderから確認できるファイル構成が変わっていることが確認できると思います。

自分の作業範囲をプロジェクトで共有

さて、適宜コミットしつつ、この作業範囲をプロジェクトで共有したいとするでしょう。実はこれ、あなたの役割ではございません。作成した作業範囲をプロジェクトにマージするのは、プロジェクトを管理している方のお仕事。

なぜかというと、競合が起こった際の直しをする必要があるから。

なので、あなたはひたすらコミットコミットコミット、プッシュ。絶対に、元のブランチにマージなどということはしてはなりません。袋叩きです。

キリのいいところまでできたらプロジェクト管理者に報告。管理者は都度あなたのブランチを確認し、必要に応じてマージして行きます。

 

会社の誰かが、自分の作業範囲に必要なソースをアップした

ある機能の実装作業を行うのに、「〇〇追加しといたからdevelop(マージ元)を自分のブランチにマージしといて〜」などと言われます。他の方が作った機能を、今自分が作業しているブランチに取り入れたいのですが、ここでただマージを行うと、自分のところで競合が起きないとも限りません。

そんなわけで、このような際には

  1. まずはマージ元(今回は仮にdevelopとします)をプル
  2. 自分の作業ブランチ(上画像のfeature/20210823_invoiceDetail)から新規ブランチ(仮にtmpと名付けましょう)を作成
  3. developをtmpへマージ
  4. 競合が起きないか確認
  5. 問題なければtmpをfeature/20210823_invoiceDetailへマージ

マージ元を選択した状態でマージ元を他へマージできないため、マージする際はマージ先を選択した状態で、マージ元を右クリックします。(伝わる?w)

具体例で説明すると、上記ステップ3(developをtmpへマージ)において、developを選択した状態でdevelopをtmpへマージできないんです。ので、まずはtmpをダブルクリックし、ブランチの切り替えを行ってから(tmpが太字になって、◯がついていますね)、developを右クリックし、「developをtempにマージ」を選択します。

これを確認したら、同じように今度はブランチをfeature/20210823_invoiceDetailに切り替えて、tmpを右クリックしてtmpをfeature/20210823_invoiceDetailにマージします。

問題なくマージが完了したら、tmpを右クリックし、「強制的に削除」にチェックを入れ、削除しておきます。

まとめ

ひとまずはこんなもんでしょうか。

会社によってやり方は異なると思いますので、適宜先輩や上司に確認しながら進めるのが良いですよ。また、Gitはあくまで手動管理なので、人的ミスで消してしまったり、以前のバージョンに戻れなくなったりしてしまうこともあります。

そんな時はTimeMachine機能を使用し、いつでも以前の状態に簡単に戻れるよう保険をかけておきましょう(Macの場合です)。

こちらの記事が詳しかったですよ!

https://smart-phone.783783783.com/2015/02/23/mac-timemachine/

 

[Nuxt.js, Vue.js, ESLint]監視プロパティwatchではアロー関数が使えない

いつもお世話になっております。

監視プロパティwatcherの挙動を勉強していて気づいたことを備忘録。

監視プロパティwatch内ではアロー関数を使うべきではない

nuxt.jsで、監視プロパティであるwatchのオプションdeepの挙動を調べていたら、怒られました。

<script>
export default {
  data() {
    return {
      colors: [
        { name: 'red' },
        { name: 'blue' },
        { name: 'green' },
      ],
    }
  },
  watch: {
    colors: {
      handler:(newValue, oldValue) => {
        console.log('updated!')
      },
      deep: true,
    },
  },
}
</script>
ESLint caution: You should not use an arrow function to define a watcher
はい

なぜなら、アロー関数はthisの挙動が変わってしまうため。アロー関数は親のコンテキストをバインドしており、thisの挙動が意図しているVueインスタンスとは異なってしまう。

This rules disallows using arrow functions to defined watcher.The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect.(see here for more details (opens new window))

eslint-plugin-vue

thisの挙動についてはここがわかりやすかったです!

https://qiita.com/mejileben/items/69e5facdb60781927929

というわけで、こう


<script>
export default {
  data() {
    return {
      colors: [
        { name: 'red' },
        { name: 'blue' },
        { name: 'green' },
      ],
    }
  },
  watch: {
    colors: {
      // handler:(newValue, oldValue) => {
      handler(newValue, oldValue) {
        console.log('updated!')
      },
      deep: true,
    },
  },
}
</script>

 

[VSCode]Prettierの自動整形がうまくいかないんですけど!? チートコード

Nuxt.jsを使用したプロジェクトで、ESLint(文法チェックツール)とPrettier(コードの自動整形ツール。コードフォーマッター)を使用しているのですが、上司と画面共有を行いながらコードレビューをしていた際、どうやらPrettierが機能していないことが発覚!(自分で気づかんかい)

今までESLint様のお眼鏡に叶うようちまちまコードを直していたのですが、Prettierさえ動いてくれればそんな手間暇とはオサラバ!!

ということでPrettier機能有効化までの道のりを残しておきたいと思います。

command + ,(Windows: Ctrl + ,)

で設定画面を開き

右上のこのマークをクリック

VSCode setting

VSCodeのsettings.jsonファイルを開きます。

ESLint、Prettier関連の設定も含めたコード全部コピペしました(チートやん)。

{
    "php.executablePath": "/usr/bin/php",
    "php.validate.executablePath": "/usr/bin/php",
    "git.enabled": false,
    "git.path": "/usr/bin/git",
    "workbench.editor.enablePreview": false,
    "workbench.startupEditor": "newUntitledFile",
    "editor.tabCompletion": "on",
    "editor.quickSuggestionsDelay": 500,
    "editor.snippetSuggestions": "top",
    "editor.hover.enabled": false,
    "php-cs-fixer.rules": "@PSR2",
    "php-cs-fixer.formatHtml": true,
    "php-cs-fixer.executablePath": "/usr/local/bin/php-cs-fixer",
    "editor.minimap.enabled": false,
    "editor.insertSpaces": false,
    "editor.detectIndentation": false,
    "terminal.integrated.rendererType": "dom",
    "C_Cpp.updateChannel": "Insiders",
    "editor.acceptSuggestionOnEnter": "smart",
    "php-cs-fixer.onsave": true,
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "editor.formatOnPaste": true,
    /*
    "[vue]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    */
    "eslint.options": {
        "configFile": "./.eslintrc.js"
    },
    "editor.formatOnSave": false,
    // vueはfalse
    /*
    "[vue]": {
        "editor.formatOnSave": false,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    */
    "editor.codeActionsOnSaveTimeout": 3000,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true,
        "source.fixAll.tslint": true,
        "source.fixAll": true
    },
    // "eslint.autoFixOnSave": true,
    /*
    "files.associations": {
        "*.vue": "vue"
    },
    */
    "eslint.validate": [
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact",
        "vue",
        /*
        {
            "language": "vue",
            "autoFix": true
        }
        */
    ],
    "javascript.updateImportsOnFileMove.enabled": "always",
    "explorer.confirmDragAndDrop": false,
    "liveSassCompile.settings.generateMap": false,
    "terminal.integrated.copyOnSelection": true,
    "terminal.integrated.rightClickBehavior": "paste",
    "nativescript.analytics.enabled": false,
    "vscode-php-cs-fixer.toolPath": "/usr/local/bin/php-cs-fixer",
    "yaml.format.enable": true,
    "yaml.completion": true,
    "yaml.validate": true,
}
 

後から個別に調べるから今は許して…

個人ブログだから…

(懺悔)