GoogleドライブとGoogle Apps Scriptを用いて匿名のファイルアップローダを作成する

概要 GoogleドライブとGoogle Apps Scriptを用いて匿名のファイルアップローダを作成する機会がありましたので、その備忘録です。 以下の記事などを参考にさせていただきました。 https://qiita.com/v2okimochi/items/06ed1ce7c56a877a1e10 ウェブアプリの作成 まず、以下のURLから、Apps Scriptにアクセスします。 https://script.google.com/ 「新しいプロジェクト」をクリック。 以下のような画面が表示されます。 以下のコードをコピペします。2行目の<Google Driveのアップロード用フォルダのID>について、事前にGoogleドライブでアップロード用のフォルダを作成しておき、そのIDを取得しておいてください。 // 定数: Google Driveのアップロード用フォルダのID const FOLDER_ID = '<Google Driveのアップロード用フォルダのID>'; // doGet関数: index.htmlファイルを表示する function doGet() { return HtmlService.createHtmlOutputFromFile('index'); } // processForm関数: フォームオブジェクトを受け取り、Google Driveにファイルをアップロードする function processForm(formObject) { // フォームからファイルデータを取得 var formBlob = formObject.myFile; // アップロード用フォルダを取得 var uploadFolder = DriveApp.getFolderById(FOLDER_ID); // 現在の日時をフォルダ名に使用 var today = new Date(); const folderName = today.toString(); // アップロード用フォルダ内に新しいフォルダを作成 const customFolder = uploadFolder.createFolder(folderName); // 新しいフォルダ内にファイルをアップロード customFolder.createFile(formBlob); // 新しいフォルダ名を戻り値として返す return folderName; } 次に、画面左上の「+」ボタンを押して、HTMLを選択します。 ファイル名に「index」を与えます。 以下のコードをコピペします。 <!DOCTYPE html> <html> <head> <base target="_top"> <script> // フォームのデフォルトの送信動作を無効にする function preventFormSubmit() { var forms = document.querySelectorAll('form'); for (var i = 0; i < forms.length; i++) { forms[i].addEventListener('submit', function(event) { event.preventDefault(); }); } } window.addEventListener('load', preventFormSubmit); // アップロードボタンを最初は無効にする document.addEventListener("DOMContentLoaded", function () { document.getElementById("upload").disabled = true; }, false); // 制限サイズ以内のファイルが選択されたらアップロードボタンを有効にする function changeSubmitButton() { const len = document.getElementById("file").files.length; const size = document.getElementById("file").files[0].size; const maxSize = 1024 * 1024 * 10; // 10MB const uploadButton = document.getElementById("upload"); if (len > 0 && size < maxSize) { uploadButton.disabled = false; } else { uploadButton.disabled = true; } } // アップロードボタンが押されたらファイルをアップロード function handleFormSubmit(formObject) { document.getElementById("upload").disabled = true; const div = document.getElementById('progress'); div.innerHTML = 'アップロード中...'; // アップロード成功した場合はupdateView()実行 google.script.run.withSuccessHandler(updateView).processForm(formObject); } // アップロード完了画面に変える(動的) function updateView(id) { var div = document.getElementById('myform'); div.innerHTML = `<div>アップロードが完了しました。</div>`; } </script> </head> <body> <div id="myform" style="text-align:center;"> ファイルを選択してからアップロードしてください(10MBまで)<br><br> <form onsubmit="handleFormSubmit(this)"> <input id="file" name="myFile" type="file" onchange="changeSubmitButton()" /> <input id="upload" type="submit" value="アップロード" /> </form> <div id="progress"></div> </div> </body> </html> デプロイ 画面右上の「デプロイ」ボタンをクリック後、「新しいデプロイ」をクリックします。 ...

2023年5月11日 · 更新: 2023年5月11日 · 2 分 · Nakamura

Google スプレッドシートの更新をGitHubに通知する

概要 Google Apps Scriptを用いて、Googleスプレッドシートが更新された際、GitHubに通知を送る方法を調べました。合わせて、StrapiやContentfulからGitHubに通知を送る方法も調べたので、備忘録として記録します。 Google Apps Script 以下のようなスクリプトを用意することで、スプレッドシートの更新をGitHubに通知できました。 const token = "ghp_xxx" const owner = "yyy" const repo = "zzz" const event_type = "aaa" function postSheetChange() { const headers = { "Accept": "application/vnd.github+json", "Authorization": `Bearer ${token}`, "Content-Type": "application/json" } var payload = JSON.stringify({ event_type }); var requestOptions = { method: 'POST', headers, payload, }; UrlFetchApp.fetch(`https://api.github.com/repos/${owner}/${repo}/dispatches`, requestOptions) } トリガーの設定方法などは以下の記事が参考になりました。 https://businesschatmaster.com/slack/spreadsheet-change-notification なお、Googleスプレッドシートの更新の都度、GitHubへの通知が行くので、GitHub Actionsのほうで、以下のようなconcurrencyを設定しておくほうがよさそうです。 または、トリガーを特定のセル(列)が更新された時だけ、などにすることも考えられます。 name: Build Test concurrency: cancel-in-progress: true on: repository_dispatch: types: - update_content jobs: build: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 ... Strapi Strapiのwebhookでは、bodyをカスタマイズできないため、以下のようなプロキシサーバを立てる必要があるようです。 ...

2023年4月27日 · 更新: 2023年4月27日 · 1 分 · Nakamura

Auth0 プロバイダーと Strapi のチュートリアル

概要 Auth0 を使用して Strapi を認証する方法を試しました。以下の記事の通りに進めることで、実現することができました。 https://strapi.io/blog/auth0-provider-and-strapi-tutorial-1 ただし、Allowed Callback URLsを指定する箇所で、http://localhost:1337/connect/auth0/callbackとなっている箇所を、http://localhost:1337/api/connect/auth0/callbackに修正する必要がありました。 (参考)github 上記手順を参考に、githubをプロパイダーとして使用する方法もうまく設定できました。

2023年4月24日 · 更新: 2023年4月24日 · 1 分 · Nakamura

DrupalでTypeError: array_keys()...への対処

graphqlモジュールで以下のエラーが発生しました。 The website encountered an unexpected error. Please try again later. TypeError: array_keys(): Argument #1 ($array) must be of type array, null given in array_keys() (line 40 of /bitnami/drupal/modules/contrib/graphql/graphql.install). そこで、以下の記事を参考に、ソースコードを修正しました。 https://www.drupal.org/project/google_tag/issues/3319621 具体的には、以下のように書き換えることで、エラーが解消しました。 // $negotiation = $languageTypes->get('negotiation'); $negotiation = $languageTypes->get('negotiation') ?? []; 最新のバージョンでは修正されていると思いますが、同様のエラーでお困りの方の参考になりましたら幸いです。

2023年4月24日 · 更新: 2023年4月24日 · 1 分 · Nakamura

Drupal: ネストされたフィールドを検索する一例

概要 以下の記事で、Strapiを用いたネストされたフィールドに対する検索方法を調査しました。 今回は同様のことをDrupalで行う方法を調査します。この調査にあたり、以下の記事で、BookとAuthorのコンテンツを登録済みです。 フィルタリングの方法については、以下の記事が参考になりました。 https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/filtering 検索例 以下に対する検索を行います。 /jsonapi/node/book? hobby=danceであるauthorを含むbookの検索 SHORT filter[field_authors.field_hobby]=dance または filter[field_authors.field_hobby][value]=dance NORMAL filter[ex1][condition][path]=field_authors.field_hobby&filter[ex1][condition][value]=dance hobbyにdanを含むauthorを含むbookの検索 SHORT filter[field_authors.field_hobby][operator]=CONTAINS&filter[field_authors.field_hobby][value]=dan NORMAL filter[ex1][condition][path]=field_authors.field_hobby&filter[ex1][condition][operator]=CONTAINS&filter[ex1][condition][value]=dan (参考)hobbyがplayまたはsingであるauthorを含むbookの検索 filter[ex1][condition][path]=field_authors.field_hobby&filter[ex1][condition][operator]=IN&filter[ex1][condition][value][1]=sing&filter[ex1][condition][value][2]=play (参考)Search APIを使う 以下のモジュールを使用することで、複数のコンテンツタイプに対する検索や、フィールド名の指定、ファセットの追加、などができそうです。 https://www.drupal.org/project/jsonapi_search_api 以下の記事で使い方を紹介していますので、参考にしてください。 <https://nakamura196.pages.dev/ja/posts/8d7aa7c33abffc/#search-api> indexの作成 例えば、Search APIのindexとして、以下のように設定します。 これにより、以下のURLからもbookの情報が得られます。 /jsonapi/index/book 通常のjsonapi(/jsonapi/node/bookなど)と比較して、metaという項目にcountが含まれることで、検索結果の全数が確認できます。(通常のjsonapiでも追加する方法があるかもしれませんが、調査不足により不明です。) { "jsonapi": { "version": "1.0", "meta": { "links": { "self": { "href": "http://jsonapi.org/format/1.0/" } } } }, "data": [...], "meta": { "count": 4 }, "links": { "self": { "href": "https://xxx/jsonapi/index/book" } } } フィルタリング また、「hobby=danceであるauthorを含むbookの検索」については、先のindex作成において、Property path「field_authors:entity:field_hobby」をMachine name「field_hobby」に割り当てましたので、以下のシンプルなクエリで実行できました。 SHORT filter[field_hobby]=dance NORMAL filter[ex1][condition][path]=field_hobby&filter[ex1][condition][value]=dance ファセット さらに、(本記事執筆時点での不確かな知識において、)Search APIを使用する大きな利点の一つとして、facetsが使用できるようになる点が挙げられます。 { "facets": [ { "id": "field_hobby", "label": "authors » Content » hobby", "path": "field_hobby", "terms": [ { "url": "https://xxx/jsonapi/index/book?filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bpath%5D=field_hobby&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Boperator%5D=IN&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bvalue%5D%5B0%5D=dance&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bvalue%5D%5B1%5D=play", "values": { "value": "play", "label": "play", "active": false, "count": 1 } }, { "url": "https://xxx/jsonapi/index/book?filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bpath%5D=field_hobby&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Boperator%5D=IN&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bvalue%5D%5B0%5D=dance&filter%5Bfield_hobby-facet%5D%5Bcondition%5D%5Bvalue%5D%5B1%5D=sing", "values": { "value": "sing", "label": "sing", "active": false, "count": 1 } }, { "url": "https://xxx/jsonapi/index/book?filter%5Bfield_hobby%5D=dance", "values": { "value": "dance", "label": "dance", "active": true, "count": 2 } } ] } ] } まとめ 不正確な情報もあるかもしれませんが、Drupalでのnested構造に対する検索と、JSON:APIとSearch APIの組み合わせについて、参考になりましたら幸いです。 ...

2023年4月24日 · 更新: 2023年4月24日 · 1 分 · Nakamura

Drupal: Feedsを用いた一括登録と更新の例

概要 以下の記事で、Strapiを用いたネストされたフィールドに対する検索方法を調査しました。 今回は同様のことをDrupalで行うにあたり、その準備である、コンテンツの一括登録及び更新方法に関する備忘録です。上記の記事と類似の構造を設定するために、BookとAuthorという2つのコンテンツタイプを対象にします。 content typeの作成 BookとAuthorのcontent typeを作成します。 Author 以下、Authorの例です。 id, name, hobbyというフィールドを作成します。feedsは後から追加されるものなので無視してください。 Book Bookのフィールドとして、authorsを作成し、Cotentをフィールドとして選択します。 Reference typeのcontent typeとしてAuthorを選択しました。 feedsの設定 一括登録のための設定を行います。 Author 以下にアクセス /admin/structure/feeds csvをアップロードして登録するため、以下のように設定します。 フィールドNAMEとHOBBYを以下のように設定します。titleは必須項目としていたため、設定しています。またifをUniqueな項目としています。 Book Bookに関する注意点として、authorsは他のコンテンツタイプのidを指定するようにしています。具体的には、以下の図のように、Reference byに「node.field_id」を指定しています。 feedsによる一括登録 /admin/content/feed Author 先に作成したcsvファイルアップロードすることで、以下のように登録が完了します。 Book authorsに正しくcontent typeがauthorのコンテンツが紐付けられています。 (参考)Feedsを用いた更新 authorのfeeds設定を設定するために、以下にアクセス /admin/structure/feeds/manage/author?destination=/admin/structure/feeds 以下のように、「Update existing content items」で「Update existing content items」とすることで、更新を行うことができました。「field_id」をUniqueとしたため、この値に基づいて、新規・更新が判定されます。 ! 「Replace existing content items」や「Update existing content items」などの挙動の違いを十分に理解できていないため、使用される際は検証の上、ご利用ください。 まとめ Feedsを用いた一括登録と更新、および異なるコンテンツタイプとの関連付けを行いました。参考になりましたら幸いです。

2023年4月23日 · 更新: 2023年4月23日 · 1 分 · Nakamura

Strapi: 深くネストされたフィールドで結果をフィルタリングする方法

概要 以下での記事で、深くネストされたフィールドで結果をフィルタリングする方法が紹介されています。 https://strapi.io/blog/deep-filtering-alpha-26 上記の通り、コンテンツタイプやフィールドを用意することで、意図した結果を得ることができました。 注意点 上記の記事のコメントにもありますが、本文中で「\」が含まれていますが、これは不要なようです。 誤 GET /api/books?filters\[authors\][hobby][$contains]=dance 以下のように、「\」なしのクエリにより、意図した結果が得られました。 正 GET /api/books?filters[authors][hobby][$contains]=dance まとめ 参考になりましたら幸いです。

2023年4月22日 · 更新: 2023年4月22日 · 1 分 · Nakamura

Drupal: カスタムモジュールを用いて、コンテンツタイプとフィールドを追加する

概要 Drupalのカスタムモジュールを用いて、コンテンツタイプとフィールドを追加する方法の備忘録です。 以下の2つの記事が参考になりました。 https://www.drupal.org/docs/drupal-apis/entity-api/creating-a-custom-content-type-in-drupal-8 https://www.digitalnadeem.com/drupal/how-to-create-content-type-fields-and-view-while-installing-custom-module-in-drupal-9-using-configuration-manager/ Car Brandの例 先に紹介した一つ目の記事の通り進めると、コンテンツタイプ「Car Brand」、フィールド「body」を追加することができました。 なお、上記の記事ではカスタムモジュールの作成の部分がスキップされています。まずはじめに以下のようなフォルダ、およびファイルを作成します。 name: foobar description: サンプルモジュール package: Custom type: module version: 1.0 core_version_requirement: ^8 || ^9 独自のフィールドの追加 上記を参考に、コンテンツタイプを追加することができましたが、独自のフィールドを追加するには、Fieldに加えて、Field storageというものも追加する必要がありました。 このField storageのymlの記述方法がわからなかった際に、冒頭で紹介した2つ目のリンクである、以下の記事が参考になりました。 https://www.digitalnadeem.com/drupal/how-to-create-content-type-fields-and-view-while-installing-custom-module-in-drupal-9-using-configuration-manager/ モジュール「Configuration Manager」を使うことで、すでに登録済みのFieldやField storageの定義内容を確認することができました。 上記を踏まえて、IIIF Mediaというコンテンツタイプを作成して、iiif_image_urlという文字列を格納するフィールドと、iiif_image_widthとiiif_image_heightという数値を格納するフィールドを作成してみます。以下のようなファイルが必要です。 コンテンツタイプ modules/custom/foobar/config/install/node.type.iiif_media.yml # node.type.iiif_media.yml langcode: en status: true dependencies: enforced: module: - foobar # This is the name of the module we're using for this example name: 'IIIF Media' type: iiif_media description: 'Content type for IIIF Media' help: '' new_revision: false preview_mode: 1 display_submitted: true フィールド:iiif_image_url(string) Field storage modules/custom/foobar/config/install/field.storage.node.field_iiif_image_url.yml ...

2023年4月21日 · 更新: 2023年4月21日 · 2 分 · Nakamura

Drupal: 異なるコンテンツタイプのコンテンツを相互にリンクさせる

概要 異なるコンテンツタイプのコンテンツを相互にリンクさせる方法を調べたので、その備忘録です。 具体的には、以下のitem 1がimage 1というコンテンツをiiif_image2というフィールドを介してつながっています。 上記に対して、image 1というページに、item 1へのリンクを設けることが目的です。 この実現にあたり、以下の記事を参考にしました。 https://drupal.stackexchange.com/questions/255447/view-for-entity-reference-reverse-backwards-forwards 方法 ビューの追加 /admin/structure/views に移動し、 +ビューを追加 「Create a block」オプションをチェックします ビューの設定 次のページで、Advancedの設定を行います。 リレーションシップ field_iiif_image2のリレーションシップを追加します。これは、2つのコンテンツタイプを関連付けるために重要です。 Require this relationshipにチェックを入れる必要があります。このフィールドを持たない場合には表示しない、という挙動になるものと理解しました。 コンテキストフィルター 次に、現在のコンテンツタイプのランディングページにコンテキストフィルターを追加します。このようにして、ビューで使用される実際のノードIDを取得します。これで、field_iiif_image2で同じノードIDを持つページのみを見つけることができます。 IDで探す(コンテンツ) デフォルト値を提供-> URL からのコンテンツ IDにチェックを入れます 次のような結果になります。 Update previewの箇所で、メディアのノードID(ここでは、62602)を入力してみます。本メディアが参照されているアイテムへのリンクが表示されます。 ブロックの追加 以下にアクセスします。 /admin/structure/block 例えば、「Content」の横の「Place block」ボタンを押します。 /node/*に配置してみます。 結果、冒頭のように、当該imageが属するitemを表示することができます。 まとめ 使用している用語に統一性がなく、わかりにくい点が多く恐縮ですが、参考になりましたら幸いです。

2023年4月20日 · 更新: 2023年4月20日 · 1 分 · Nakamura

ORCIDのRDFを確認する

ORCIDのRDFを確認する方法です。 以下のORCID IDを対象にします。 https://orcid.org/0000-0001-8245-7925 閲覧には、神崎正英氏が開発されているLinked Data Browswerを使用します。 https://www.kanzaki.com/works/2014/pub/ld-browser 例えば、以下のURLからRDFデータを閲覧できます。 https://www.kanzaki.com/works/2014/pub/ld-browser?u=https%3A%2F%2Forcid.org%2F0000-0001-8245-7925 具体的なRDFデータは以下です。 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:prov="http://www.w3.org/ns/prov#" xmlns:pav="http://purl.org/pav/" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:gn="http://www.geonames.org/ontology#" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#"> <foaf:PersonalProfileDocument rdf:about="http://pub.orcid.org/orcid-pub-web/experimental_rdf_v1/0000-0001-8245-7925"> <pav:createdOn rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime" >2017-07-14T00:27:17.421Z</pav:createdOn> <prov:generatedAtTime rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime" >2022-12-14T02:40:04.693Z</prov:generatedAtTime> <pav:lastUpdateOn rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime" >2022-12-14T02:40:04.693Z</pav:lastUpdateOn> <pav:createdWith rdf:resource="https://orcid.org"/> <prov:wasAttributedTo> <prov:Person rdf:about="https://orcid.org/0000-0001-8245-7925"> <foaf:account> <foaf:OnlineAccount rdf:about="https://orcid.org/0000-0001-8245-7925#orcid-id"> <rdfs:label>0000-0001-8245-7925</rdfs:label> <foaf:accountName>0000-0001-8245-7925</foaf:accountName> <foaf:accountServiceHomepage rdf:resource="https://orcid.org"/> </foaf:OnlineAccount> </foaf:account> <foaf:publications> <foaf:Document rdf:about="https://orcid.org/0000-0001-8245-7925#workspace-works"/> </foaf:publications> <foaf:page rdf:resource="https://researchmap.jp/nakamura.satoru/?lang=english"/> <foaf:based_near> <gn:Feature> <gn:parentCountry> <rdf:Description rdf:about="http://sws.geonames.org/1861060/"> <gn:name>Japan</gn:name> <gn:countryCode>JP</gn:countryCode> <rdfs:label>Japan</rdfs:label> </rdf:Description> </gn:parentCountry> <gn:countryCode>JP</gn:countryCode> </gn:Feature> </foaf:based_near> <foaf:familyName>Nakamura</foaf:familyName> <foaf:givenName>Satoru</foaf:givenName> <rdfs:label>Satoru Nakamura</rdfs:label> <rdf:type rdf:resource="http://xmlns.com/foaf/0.1/Person"/> </prov:Person> </prov:wasAttributedTo> <pav:createdBy rdf:resource="https://orcid.org/0000-0001-8245-7925"/> <foaf:maker rdf:resource="https://orcid.org/0000-0001-8245-7925"/> <foaf:primaryTopic rdf:resource="https://orcid.org/0000-0001-8245-7925"/> </foaf:PersonalProfileDocument> </rdf:RDF> 参考になりましたら幸いです。

2023年4月20日 · 更新: 2023年4月20日 · 1 分 · Nakamura

Drupal: カスタムRESTリソースを作成する

概要 以下を参考に、カスタムRESTリソースを作成しました。 https://www.drupal.org/docs/drupal-apis/restful-web-services-api/custom-rest-resources 上記の記事の通り進めることで、以下のURLから、JSONの結果を得ることができました。 /demo_rest_api/demo_resource { "message": "Hello, this is a rest service" } REST UIモジュール 上記の記事において、以下の記載がありました。 If you are using the REST UI contrib module, you should now be able to see it in the list of available endpoints and you should be able to configure the GET method. この点については、以下の記事を参考に、REST UIモジュールを有効化しました。 https://www.studio-umi.jp/blog/12/357 IIIF Presentation APIの試作 次に、コンテンツ毎にJSON作成に取り組みます。具体的には、/iiif/3/{id}/manifestというパスにアクセスすると、IIIF Presentation API v3に基づく情報を出力するようにしてみます。 以下の記事が参考になりました。 https://medium.com/drupaljournal/create-custom-rest-resource-for-get-and-post-method-in-drupal-8-e445330be3ff 以下のようなファイルを作成します。以下の例では、とりあえず$nodeからtitleを取得しています。これを応用することで、他のフィールドの情報も取得することができそうです。 <?php namespace Drupal\demo_rest_api\Plugin\rest\resource; use Drupal\node\Entity\Node; use Drupal\node\NodeInterface; use Drupal\rest\Plugin\ResourceBase; use Drupal\rest\ResourceResponse; /** * Annotation for get method * * @RestResource( * id = "iiif_presentation_3", * label = @Translation("IIIF Presentation API v3"), * uri_paths = { * "canonical" = "/iiif/3/{id}/manifest" * } * ) */ class Presentation3 extends ResourceBase { /** * Responds to GET requests. It will return serialize json format of node * object. * * @param $id * Node id. */ public function get($id) { if ($id) { // Load node $node = Node::load($id); if ($node instanceof NodeInterface) { $manifest = [ "@context" => "http://iiif.io/api/presentation/3/context.json", "type" => "Manifest", "label" => [ "none" => [ $node->get("title")[0]->get("value")->getValue() ] ] ]; $response = new ResourceResponse($manifest); // Configure caching for results if ($response instanceof CacheableResponseInterface) { $response->addCacheableDependency($node); } return $response; } return new ResourceResponse('Article doesn\'t exist', 400); } return new ResourceResponse('Article Id is required', 400); } } パーミッションの許可 以下のページで、Anonymous userにチェックを入れて、外部からのアクセスを許可します。 ...

2023年4月20日 · 更新: 2023年4月20日 · 2 分 · Nakamura

DrupalのRESTful Viewsを使ってカスタムAPIを作成する

概要 以下の記事を参考に、DrupalのRESTful Viewsを使ってカスタムAPIを作成したので、その備忘録です。 https://acret.jp/drupal/node/434 上記の記事の内容に加えて、ページネーションに関する設定方法も記載しています。 Viewsの作成 上記のサイトの通りに進めました。 ページネーションを許可する 以下の記事を参考にしました。 https://www.drupal.org/forum/support/post-installation/2015-12-04/rest-export-pagination ViewsのPagerを選択します。以下の通り、Fullとしました。Miniでも大丈夫そうでした。 「Allow user to control the number of items displayed in this view」と「Allow user to specify number of items skipped from beginning of this view.」にチェックを入れます。 結果、以下のようなパラメータが使えるようになりました。 /my_custom_api?items_per_page=10 /my_custom_api?items_per_page=10&offset=1 /my_custom_api?items_per_page=50 まとめ カスタムAPIを作成する際の参考になりましたら幸いです。

2023年4月20日 · 更新: 2023年4月20日 · 1 分 · Nakamura

Drupalのビューで結果の合計数を表示する

概要 Drupalのビューで結果の合計数を表示する方法を調べたので、その備忘録です。以下のように、検索結果の合計数などが表示されます。 方法 以下の記事を参考にしました。 https://ostraining.com/blog/drupal/count-views/ 以下のページにアクセス /admin/structure/views/view/content Header横のAddボタンを押す Result summaryを選択 Applyを押して、Saveを押します。 まとめ 参考になりましたら幸いです。

2023年4月20日 · 更新: 2023年4月20日 · 1 分 · Nakamura

Omeka SにGoogle Analytics 4 gtag.jsを追加する

概要 Omeka SにGoogle Analyticsを設定するモジュールとして以下があります。 https://omeka.org/s/modules/GoogleAnalytics/ 2023年4月時点では上記のモジュールもGA4に対応していますが、2022年4月時点では以下の記事にある通り、非対応だったようです。 https://forum.omeka.org/t/google-analytics-4-gtag-js/15034 そこで、以下のモジュールが紹介されていたので、試してみます。 https://omeka.org/s/modules/AnalyticsSnippet/ なお、繰り返しになりますが、2023年4月時点では、冒頭のモジュールもGA4に対応していますので、Google Analyticsの設定にあたり、どちらのモジュールを使用してもよさそうです。 インストール 一般的なインスール方法と同様です。今回は、version=3.3.3.4をインストールします。 cd /modules version=3.3.3.4 wget https://github.com/Daniel-KM/Omeka-S-module-AnalyticsSnippet/releases/download/$version/AnalyticsSnippet-$version.zip unzip AnalyticsSnippet-$version.zip 設定 サイトの設定画面で、コードを貼り付けます。 コードは、Google Anayticsの設定画面から取得です。 まとめ Omeka SにGA4を設定する際の参考になりましたら幸いです。

2023年4月19日 · 更新: 2023年4月19日 · 1 分 · Nakamura

TEI Critical Apparatus Toolboxを用いてTEI XMLをLaTeXに変換してみる

概要 TEI Critical Apparatus Toolboxは、a tool for people preparing a natively digital TEI critical editionです。日本語訳の一例は以下です。 ネイティブ デジタル TEI クリティカル エディションを準備する人々のためのツール http://teicat.huma-num.fr/index.php 校異情報を可視化する機能を提供する他、複数の便利な機能を提供しています。 その中で、「TEI から LaTeX および PDF への変換」機能があることを教えていただいたので試してみます。 Print an edition 以下にアクセスします。 http://teicat.huma-num.fr/print.php this dummy edition fileという文字列のリンクをクリックして、以下のサンプルデータをダウンロードします。 http://teicat.huma-num.fr/print-feature-test-file.xml 上記のファイルを本ツールにアップロードします。変換に関する様々なオプションが用意されていますが、デフォルト設定のまま、画面下部の「送信」ボタンをクリックします。 すると、zipファイルがダウンロードされます。myEditionというフォルダが展開され、.log、.pdf、.texの3つのファイルが格納されていることが確認できます。 PDFの例は以下です。 TEXの例は以下です。 注意 2023年4月時点において、上記の機能は日本語を含むxmlファイルではうまく出力できませんでした。この点の改善についても今後検討してみたいと思います。 まとめ TEI/XMLファイルの変換ツール、フローを検討する上で、参考になりましたら幸いです。

2023年4月19日 · 更新: 2023年4月19日 · 1 分 · Nakamura

JPCOARスキーマ(v1)を用いたxmlファイルのバリデーションツールの試作

以前に以下の記事を執筆しました。JPCOARスキーマを用いたxmlファイルのバリデーションを試しました。 今回は、上記の記事での検証を元に、Google Colabを用いた検証ツールを作成しました。以下のURLからお試しいただけます。 https://colab.research.google.com/github/nakamura196/ndl_ocr/blob/main/JPCOARスキーマ_v1を用いたxmlファイルのバリデーション.ipynb 公開済みのxmlファイルのURLを指定する、またはローカルファイルをアップロードすることで、対象ファイルのバリデーションを行うことができます。 JPCOARスキーマ(v1)を用いたxmlファイルの作成にあたり、参考になりましたら幸いです。

2023年4月19日 · 更新: 2023年4月19日 · 1 分 · Nakamura

VueUseを用いたテキスト選択(Nuxt3)

概要 Nuxt3(Vue3)を用いたテキストの選択機能の実装にあたり、VueUseを使用してみましたので、その備忘録です。 https://vueuse.org/ デモ 以下のページからお試しいただけます。 https://nuxt3-demo-git-main-nakamura196.vercel.app/textSelection ソースコードは以下です。 https://github.com/nakamura196/nuxt3-demo/blob/main/pages/textSelection.vue インストール方法 以下のページに記載があります。 https://vueuse.org/guide/ 具体的な手順は、以下のとおりです。 npm i -D @vueuse/nuxt @vueuse/core // nuxt.config.ts export default defineNuxtConfig({ modules: [ '@vueuse/nuxt', ], }) まとめ テキスト選択以外にも、便利な機能が色々と使えるようなので、引き続き試してみたいと思います。

2023年4月19日 · 更新: 2023年4月19日 · 1 分 · Nakamura

Next.js for DrupalにおけるDrupal Search APIを用いた検索(ファセット検索など)

概要 Next.js for Drupalを試してみました。 https://next-drupal.org/ 以下の「Get Started」の通りにすすめることで、Next.jsとDrupalを連携させることができました。 https://next-drupal.org/learn/quick-start また、以下の記事で、ファセット検索の実装例が紹介されています。 https://next-drupal.org/guides/search-api 本記事では、特に後者のファセット検索の実現に関する備忘録です。 Search API 以下、Serverとindexを作成します。 公式サイトでは以下が参考になります。 https://www.drupal.org/docs/contributed-modules/search-api 日本語サイトでは以下が参考になります。 https://www.acquia.com/jp/blog/introduction-to-search-api-1 Serverの作成 indexの作成 今回、test_index_20230417というインデックスを作成します。 さらに、タイトルをフィールドとして追加しました。 その後、インデクシングを行います。 JSON:API 上記を行ったところで、キャッシュをクリアします。 /admin/config/development/performance その後、以下のURLからエンドポイントにアクセスできるようになります。 /jsonapi/index/test_index_20230417 以下のようなクエリパラメータによって、検索結果の絞り込みができます。 /jsonapi/index/test_index_20230417?filter[title]=更新したタイトル { "jsonapi": { "version": "1.0", "meta": { "links": { "self": { "href": "http://jsonapi.org/format/1.0/" } } } }, "data": [ { "type": "node--service", "id": "82a34c35-f1b7-49eb-81ac-f15d0deac22c", "links": { "self": { "href": "https://xxx/jsonapi/node/service/82a34c35-f1b7-49eb-81ac-f15d0deac22c?resourceVersion=id%3A5075" } }, "attributes": { "drupal_internal__nid": 4, "drupal_internal__vid": 5075, "langcode": "en", "revision_timestamp": "2023-04-12T08:19:00+00:00", "revision_log": null, "status": true, "title": "更新したタイトル", "created": "2023-04-11T02:09:35+00:00", "changed": "2023-04-12T08:19:00+00:00", "promote": false, "sticky": false, "default_langcode": true, "revision_translation_affected": true, ... Facets 以下にアクセスします。 ...

2023年4月17日 · 更新: 2023年4月17日 · 1 分 · Nakamura

Contentfulの全文検索は2文字以上の検索語が必要?

Contentfulを使用していますが、2文字以上の検索語が必要そうでした。 A query will ignore search tokens with less than 2 characters. https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters/full-text-search-on-a-field この点は日本語などを含むデータに対して注意が必要そうです。 追記 microCMSでは、1文字からの検索が可能でした。 https://microcms.io/

2023年4月14日 · 更新: 2023年4月14日 · 1 分 · Nakamura

Drupalのコンテンツの一括削除の方法

概要 Drupalのコンテンツの一括削除の方法を調べたので、その備忘録です。以下の記事が参考になりました。 https://www.webwash.net/how-to-bulk-delete-content-in-drupal/ 以下の3つの方法が紹介されていました。 Drupal コア UI の使用 (Using Drupal Core UI) Drush の使用 (Using Drush) ビューの一括操作 (VBO) の使用 (Using Drupal Views Bulk Operations (VBO)) Drupal コア UI の使用 以下、日本語訳です。 小さな Drupal サイトがあり、削除するノードが約 300 未満の場合は、この方法を使用する必要があります。これは、Drupal コアの UI を使用すると、デフォルトで一度に 50 ノードしか削除できないためです。サイトが大きくなると、これは面倒になります。 Drush の使用 以下、日本語訳です。 コマンド ラインを使用すると、Drush を使用できます。これが推奨される方法です。 例えば以下では、記事コンテンツ タイプのすべてのノードを削除します。 drush entity:delete node --bundle=article ただ、上記のサイトにも記載がありましたが、PHP メモリ制限にひっかかることがあるようです。Amazon Lightsail上に立てた512MBメモリの環境において、5,000件のコンテンツの一括削除を試みたところ、以下のように制限に引っかかってしまいました。ただし、再度同じコマンドを実行することで、無事に一括削除ができました。 drush entity:delete node --bundle=article 2550/5057 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░] 50% PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /opt/bitnami/drupal/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php on line 76 PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 32768 bytes) in /opt/bitnami/drupal/vendor/symfony/http-foundation/Response.php on line 895 specify the chunk/batch size デフォルトでは50件ずつ処理されますが、–chunks=100のように引数を加えることで、バッチサイズを変更できました。 ...

2023年4月14日 · 更新: 2023年4月14日 · 1 分 · Nakamura