FileMaker

FileMakerでドラッグ&ドロップ可能なスケジューラを実装する方法

  • このエントリーをはてなブックマークに追加

こんにちは。
ライジングサン・システムコンサルティングの岩佐です。

この記事では、ドラッグ&ドロップ操作が可能なスケジューラーソリューションを、FileMakerのカスタムAppに実装する方法をご紹介します。

ここでいうスケジューラーとは、こちらのスクリーンショットにあるよな、リソース毎のスケジュールを横断的に管理できるようなソリューションです。

Vertical Resource View

Timeline View

2つのスクリーンショットを表示していますが、情報要素としては全く同じです。

前者は、縦軸に時間・横軸にリソース。後者は縦軸にリソースで、横軸に時間を取っています。

同じ情報要素ですが、軸を変えるだけで全く異なった見え方になりますね。一般的に、Excelなどでスケジュール管理をやっている場合は、後者のような見え方で作成するケースが多いようです。

このようなソリューションをFileMakerの標準機能だけで実装することは、不可能ではありませんがあまりスマートなやり方ではありません。また、標準機能だけではドラッグ&ドロップ操作でスケジュールを作成・移動・変更するなどといった操作性を提供することはまず不可能です。

そこで今回は、フリーのオープンソースとして公開されているFullCalendarというJavaScriptライブラリを活用して、ドラッグ&ドロップによるスケジューラーソリューションを、FileMakerで実現する方法をご紹介します。

記事の最後には、無料のサンプルソリューションをダウンロードできる申込みフォームを設けていますので、ぜひお手元で実際に動かして、その操作性の高さを確かめてみてください。

また、配布させていただくソリューションはロックフリーのオープンソースになっています。

その中身を解析してご自身のソリューションに自由に組み込んでいただくことが可能です。

※サンプルソリューションを動かすには、FileMakerのVer17以降が必要です。

1.ドラッグ&ドロップが可能な3つの機能

今回、無料サンプルとしてご提供させていただくソリューションには、ドラッグ&ドロップ操作で可能な3つの機能が組み込まれています。

1-1. タイムスロットをドラッグして新規スケジュールを追加(select)

こちらの動画のように、こちらの動画のように、タイムライン上でスケジュール予約したい時間帯をマウスでドラッグすると、なぞった時間の開始・終了時間が自動的にセットされたイベント入力ウインドウが開きます。

1-2.スケジュールをドラッグ&ドロップで移動(eventDrop)

登録されているイベントは、ドラッグ&ドロップで、別の日にち、及び時間帯に移動することが可能です。頻繁にスケジュール変更が発生するようなソリューションで、この操作感が実現できるのはうれしいですよね。

1-3.イベントの右端・下端をドラッグして時間を変更(eventResize)

こちらは、スケジュールの下端をドラッグすることで、登録されている時間枠を変更できる機能です。これも、時間変更が頻繁に発生する業務でのソリューションに実装できると嬉しい機能ですよね。

2. 表示モードは2種類

スケジューラーの表示は大きく2種類です。1つが Timeline View と呼ばれる縦軸にリソース、横軸に時間を取る見せ方。もう1つが、Vertical Resource View と呼ばれる縦軸に時間、横軸にリソースをとる見せ方です。

2-1. Timeline View

この表示方法は、Excelや紙をつかったスケジュール管理でもよく見られる形です。

この表示方法のメリットとしては、紙やExcelでの管理の延長線のような使い方ができるので、直感的に理解されやすいという点です。また、縦軸にリソースを取るので、非常に大量のリソースを一度に見たい場合には、こちらの表示のほうが恐らく見やすいでしょう。

一方デメリットとしては、どうしても1つのスケジュール内に表示できる情報量が限られてしまうので、詳細情報が把握しづらいという点です。特に15分や30分など短い時間ですと、表示できる情報がかなり限られてしまいます。

2-2. Vertical Resource View

この表示方法は、Googleカレンダーの週表示に似ています。Googleカレンダーの週表示では、横軸に7日分の日付を並べるのですが、こちらのVertical Resource View では、週日ではなくリソースを並べます。こうすることで、各リソースのスケジュールを横串で横断的に確認することが可能です。

この表示方法のメリットとしては、さきのTimeline Veiw と比較して、1つのスケジュール内に表示できる情報が多い点です。1つのタイムスロットを15分刻みに変更(デフォルトは30分)すれば、1時間の予定でもかなりの情報量を表示できます。

一方デメリットとしては、横軸にリソースを取るので、1度に表示したいリソースの数が10を超えると横スクロールが必要となり、かなり見通しが悪くなることが考えられます。

ちなみに今回配布させていただくサンプルソリューションでは、レイアウトの右上にビューの切り替えボタンを実装しているので、双方の表示を瞬時に切り替えていただくことができます。

3.サンプルソリューションの解説

ここからは、この記事の最後にご案内しているサンプルソリューションを例に、具体的な機能や、動作のメカニズムについて解説していきます。

また、このようなソリューションはどうしても文章でお伝えするとなると、膨大な文量が必要となるため、動画による解説に察せていただきたいと思います。

3-1. FullCalendar Scheduler とは

この動画では、今回のソリューションの核となるオープンソースのJavaScriptライブラリである FullCalendar Scheduler について解説します。

3-2. サンプルソリューションの機能概要

この動画では、サンプルソリューションの機能概要を説明します。

3-3. サンプロソリューションの内部構造

この動画では、ダウンロードいただいたサンプルソリューションの内部構造を解説します。今回配布させていただくサンプルソリューションは、完全アクセス権で開くことができますので、FileMakerPro Advancedを使って、ご自身でスクリプトデバッガとデータビューアを駆使しながら内部構造をご確認いただくことができますので、ぜひこちらの動画とセットで動かしてみてください。

3-4. リレーションシップグラフの解説

この動画では、サンプルソリューションのリレーションシップグラフについて解説します。ご存知の通り、FileMakerでの開発においてリレーションシップグラフの理解が極めて重要になりますので、ぜひお手元にダウンロードしたソリューションのリレーションシップグラフを確認しながら、こちらの動画で理解を深めていただければと思います。

3-5. スクリプトの解説

この動画では、サンプルソリューションで動くスクリプトについて解説しています。FullCalendar Scheduler と FileMaker のスクリプトがどのように連携しているのか。また、イベント編集レイアウトのモーダル制御やコミット・ロールバックの制御に関するメカニズムについても解説しておりますので、ぜひ御覧ください。

4. Webビューアで表示するHTMLの解説

この項では、サンプルソリューションのWebビューアに表示するHTMLの構造について解説します。

4-1. ヘッダー要素でJavaScript/CSSの参照先を定義

今回のサンプルソリューションでは、できるだけHTMLの構造をシンプルにするため、FullCalendarやjQueryといったJavaScriptライブラリは全てCDNからの参照としました。CDNからの参照なので、ネットにつながっていることが動かす前提条件となります。

今回のソリューションで参照している各種ライブラリのコードは以下のとおりです。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    
    <!-- CSS@cdnjs  -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.css">

    <!-- JavaScript@cdnjs  -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/locale/ja.js"></script>

  </head>
</html>

注意:
CDNに公開されているFullCalendar、及びjQeuryの最新バージョンは、今回読み込んでいるバージョンとは異なります。あえて古いバージョンを指定しているのは、Windows環境でのWebビューアで正しく動作しない現象によるものです。様々なバージョンの組み合わせでテストをしてみましたが、Windows環境ではひとまず、上記コードのバージョンで動くことが確認できました。

4-2. FullCalendarの制御部分に関する解説

次に、FullCalendarの制御部分について解説します。
FullCalendarは、JSON形式で表示に関する制御を定義します。
以下は、今回のサンプルソリューションで実際に設定している表示制御の部分です。
設定値の簡単な解説も掲載していますので、合わせてご確認ください。

<script>
  $(function() { // document ready
    $('#calendar').fullCalendar({
      schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
      defaultDate: '2018-08-15',
      now: '2018-08-16T09:35:00',
      nowIndicator: true,
      editable: true, // enable draggable events
      selectable: true,
      selectHelper: true,
      height: 1070,
      contentHeight: 1020,
      slotDuration: '00:15:00',
      slotLabelInterval: '01:00',
      minTime: '09:00:00',
      maxTime: '20:00:00',
      resourceAreaWidth: '10%',
      header: false,
      defaultView: 'agendaDay',
      resourceLabelText: 'リソース',
    });
  });
</script>

以下、実際のコードで使用している設定値の解説です。

プロパティ 説明
schedulerLicenseKey
Schedulerを使う場合のライセンスキー設定です。
今回はオープンソースでの公開なので ‘GPL-My-Project-Is-Open-Source’ を設定しています。商用利用の場合は、ライセンスを購入するとライセンスコードが発行されるので、そちらを設定してください。
defaultDate スケジューラーに表示する対象日付をISOフォーマットで設定します。eventsプロパティに複数の日付が含まれる場合、この日付をもつeventのみが表示されます。
now 現在の日時をISOフォーマットで設定します。nowIndicatorがfalseの場合は、設定する必要はありません。
nowIndicator カレンダー上に現在の日時を表すインジケータの表示・非表示をブール値で設定します。trueを設定すると、現在の日時を表す赤いインジケータが表示されます。
editable ドラッグ&ドロップ操作の可否をブール値で設定します。
selectable タイムスロットをドラッグしてのイベント発生可否をブール値で設定します。
height ヘッダ・フッタを含むFullCalendar全体の高さを設定します。設定は数値による設定と、“parent”, “auto”が使えます。
contentHeight ヘッダ・フッタを含まないView部分の高さを設定します。数値による設定と、”auto”での機能設定が可能です。
slotDuration タイムスロットの単位をISOフォーマットで設定します。デフォルトでは”00:30:00”の30分単位ですが、今回のソリューションでは15分単位に設定しています。
slotLabelInterval タイムスロットのラベルを何時間毎に表示するかをISOフォーマットで設定します。デフォルトでは”00:30”の30分単位ですが、今回のソリューションでは”01:00”の1時間単位で表示する設定に変更しています。
 minTime / maxTime カレンダー上の最小・最大時間をISOフォーマットで設定します。
resourceAreaWidth Vertical Resource View におけるリソース表示カラムの幅を百分率で設定します。
header ヘッダコンテンツの表示・非表示を設定します。デフォルトは表示する用になっており、具体的に何を表示するかも設定が可能です。詳しくは公式ドキュメントでご確認ください。
defaultView スケジュールコンテンツの見せ方を設定します。今回は agendaDaytimelineViewの2つを利用します。
resourceLabelText Vertical Resource View をで表示する場合の、リソースカラム上部に表示するヘッダラベル文字列を設定します。

今回は、実際に利用している最低限のプロパティのみをご紹介しましたが、実際にはもっとたくさんの設定が可能です。つまりそれだけ表示や動作を細かくコントロールできるということです。

4-4. FullCalendarとFileMakerの連携メカニズム

次に、FullCalendarとFileMakerがどのように連携するのかのメカニズムについて解説します。
今回のサンプルソリューションでは、FullCalendarが標準で提供しているselect/eventClick/eventDrop/eventResizeの各イベントを拾い、それぞれのイベントが発生したら、FileMaker側にわたす必要のある引数をJavaScriptで生成し、fmpURLプロトコルで各イベントに対応するFileMaker側のスクリプトにわたすという方法を取っています。

以下、それぞれのイベントが発火したときに動くJavaScriptの部分を切り出したコードになります。

4-4-1. selectイベント

selectイベントは、カレンダーのタイムスロット上で、新規スケジュールを登録したい時間帯をドラッグしたときに発生するイベントです。具体的には次のように記述します。


// ----------------------------------------------------------
// function select
// ----------------------------------------------------------
select: function(start, end, jsEvent, view, resource) {
  var strStart = start.toISOString();
  var strEnd = end.toISOString();
  var viewObject = $('#calendar').fullCalendar('getView');
  var viewName = viewObject.name;
  var viewStart = viewObject.start;
  var viewIntervalStart = viewObject.intervalStart.toISOString();
  var viewIntervalEnd = viewObject.intervalEnd.toISOString();
  var strResourceID = resource.id;
  var fmScriptParam = 'fmp://$/FullCalendar_Scheduler_V01?script=FullCalendar.select&$start=' + strStart +
                      '&$end=' + strEnd +
                      '&$viewName=' + viewName +
                      '&$intervalStart=' + viewIntervalStart +
                      '&$intervalEnd=' + viewIntervalEnd +
                      '&$resourceID=' + strResourceID;
  window.location = fmScriptParam;
  $calendar.fullCalendar('renderEvent',
    {
      title: 'TEST',
          start: start,
          end: end
        },
        true
      );
  $calendar.fullCalendar('unselect');
}

上記の例では、セレクトイベントが発火したときに取得できるプロパティを、fmpURLプロトコルを使ってFileMakerのスクリプトを呼び出しています。具体的には、ドラッグした開始・終了日時とリソースIDです。

上記13行目で、FileMakerのスクリプトを呼び出すURLリンクを作成し、19行目でFileMakerのスクリプトをコールしています。

4-4-2. eventClickイベント

eventClickは、カレンダー上で、スケジュールをクリックしたときに発火するイベントです。


// ----------------------------------------------------------
// function eventClic
// ----------------------------------------------------------
eventClick: function( event, jsEvent, view) {
  var strID = event.id;
  var fmScriptParam = 'fmp://$/FullCalendar_Scheduler_V01?script=FullCalendar.eventClick&$ID=' + strID;
  window.location = fmScriptParam;
}

4-4-3. eventDropイベント

eventDropイベントは、カレンダー上でスケジュールをドラッグ&ドロップしたとき、より詳細にはドロップ操作が終了したときに発生します。


// ----------------------------------------------------------
// function eventDrop
// ----------------------------------------------------------
eventDrop: function(event, delta, revertFunc) {
  var eventID = event.id;
  var resourceID = event.resourceId;
  var startDateTime = event.start.format();
  var endDateTime = event.end.format();
  var viewObject = $('#calendar').fullCalendar('getView');
  var viewName = viewObject.name;
  var fmScriptParam = 'fmp://$/FullCalendar_Scheduler_V01?script=FullCalendar.eventDrop' +
                      '&$eventID=' + eventID +
                      '&$resourceID=' + resourceID +
                      '&$start=' + startDateTime +
                      '&$end=' + endDateTime +
                      '&$viewName=' + viewName;
  window.location = fmScriptParam;
},

FileMakerのスクリプトには、どのイベント(スケジュール)が、どのリソースにドロップされたか。そしてドロップされた場所の開始・終了時間は?という情報を渡しています。これだけの情報が渡れば、データベース側の更新は可能ですね。

4-4-4.eventResizeイベント

eventResizeは、カレンダー上で、イベントの終了時間をドラッグ操作で変更されたときに発火する振る舞いを記述します。


// ----------------------------------------------------------
// function eventResize
// ----------------------------------------------------------
eventResize: function(event, delta, revertFunc) {
  var ID = event.id;
  var startDateTime = event.start.toISOString();
  var endDateTime = event.end.toISOString();
  var viewObject = $('#calendar').fullCalendar('getView');
  var viewName = viewObject.name;
  var viewStart = viewObject.start;
  var viewIntervalStart = viewObject.intervalStart.toISOString();
  var viewIntervalEnd = viewObject.intervalEnd.toISOString();
  var fmScriptParam = 'fmp://$/FullCalendar_Scheduler_V01?script=FullCalendar.eventResize&$ID=' + ID +
                      '&$start=' + startDateTime +
                      '&$end=' + endDateTime +
                      '&$viewName=' + viewName +
                      '&$intervalStart=' + viewIntervalStart +
                      '&$intervalEnd=' + viewIntervalEnd;
     window.location = fmScriptParam;
},

今回の例では、FileMaker側に対して、どのイベントが、ドラッグ操作後(リサイズ操作後)に、何時開始・何時終了となったのかを渡しています。

4-5. リソースとイベント情報JSON形式で定義

FullCalendar Scheduler に表示したいリソース、及びイベントの情報は、それぞれFullCalendar側が指定する仕様に従ってJSON形式で渡します。

ご存知の通り、FileMakerではVer16よりJSONデータを効率的に操作できる関数群が提供されたことで、非常に取り回し(Parse)が楽になりました。

今回のサンプルソリューションでは、Resource / Event それぞれのJSONデータをFileMakerのスクリプトで生成し、ひな形として用意したHTMLの固定文字列(@@@resourceJSON@@@ / @@@eventJSON@@@)を、FileMakerのSubstitute関数で書き換えるという方法でデータを渡しています。

4-5-1. Resource JSON を記述する。

Resource JSON は、カレンダー上に記述するリソース情報です。具体的には次のようなフォーマットで渡します。


"resources" : 
[
        {
                "id" : "5DCEF02F-A271-4F20-9285-CC01BB1FB97D",
                "title" : "会議室A"
        },
        {
                "id" : "35D81B4B-4C76-4985-BC93-31A2611E3F5F",
                "title" : "会議室B"
        },
        {
                "id" : "E58240FF-622E-4B2C-92AA-656AF0CBCCA2",
                "title" : "会議室C"
        },
        {
                "id" : "00613DFC-4CE5-4E9C-BCA2-2A0755A5C13E",
                "title" : "会議室D"
        },
        {
                "id" : "0E99B220-D43D-4ED8-A18C-BA308657A36C",
                "title" : "会議室E"
        },
        {
                "id" : "B36D25E4-6756-4B00-9BAF-9457BFBC7DF1",
                "title" : "会議室F"
        },
        {
                "id" : "915EA633-5E6A-4AB7-A380-AFDE457B159C",
                "title" : "会議室G"
        }
]

情報要素としては一目瞭然ですね。

1つのresourceオブジェクトの構成要素はidとtitleです。idは、FileMaker内でPrimaryKeyとして使っているUUID値、titleまリソースのタイトルです。これ以外にも、該当リソース内のイベントにデフォルトで設定するカラーや、リソースのグルーピングを制御することなども可能です。

4-5-2. event JSON を記述する。

event JSON は、カレンダー上に記述するイベント情報です。具体的には次のようなフォーマットで渡します。


"events" : 
[
  {
    "color" : "#C88DE0",
    "end" : "2018-08-15T10:30:00",
    "id" : "053D90FF-0649-4BED-A79A-392A65C14C3F",
    "resourceId" : "35D81B4B-4C76-4985-BC93-31A2611E3F5F",
    "start" : "2018-08-15T09:30:00",
    "title" : "テストでスケジュール追加。タイプはスケジュール1"
  },
  {
    "color" : "#5BBDFF",
    "end" : "2018-08-15T11:00:00",
    "id" : "E90E7D2E-7F3B-438C-8D35-B7F21B51BBE4",
    "resourceId" : "00613DFC-4CE5-4E9C-BCA2-2A0755A5C13E",
    "start" : "2018-08-15T10:00:00",
    "title" : "2件目のスケジュール"
  },
  {
    "color" : "#C9A300",
    "end" : "2018-08-15T13:00:00",
    "id" : "35D9F0E8-0C5E-43E2-B49A-275489BC43CB",
    "resourceId" : "E58240FF-622E-4B2C-92AA-656AF0CBCCA2",
    "start" : "2018-08-15T11:45:00",
    "title" : "ドラッグ&ドロップ操作も快適で問題なし。"
  }
]

こちらもデータを見れば、渡している情報要素は一目瞭然ですね。

FileMakerのJSONFormatElements関数でフォーマッティングしたものを表示しているので、要素名がアルファベット順にソートされてしまい、若干見にくい部分もありますが、概ねどういった情報で構成されているのかはすぐに把握できるのではないかと思います。

以下、eventJSONの要素解説です。

要素名 説明
id FileMaker側のイベントテーブルで生成している、イベントレコードを一意に識別できるUUID値
resourceId FileMkaer側のリソーステーブルで生成している、リソースレコードを一意に識別できるUUID値
title イベントのタイトル
start / end イベントの開始・終了日時。ISOフォーマットにて記述
color  イベントの表示カラー。16進数で設定。

5. FullCalendar Scheduler はライセンス費用が必要

最後に、今回ご紹介したFullCalendarの商用利用に関する注意点です。
今回ご紹介したSchedulerオプションを商用利用するには、別途ライセンスフィーが発生します。

費用の詳細、及びライセンス規約については、こちらのページに詳しく記載されているので、一度しっかりとお読みになった上で、自社のケースに合うライセンスにて利用しましょう。
https://fullcalendar.io/scheduler/license

6.まとめ・サンプルソリューションのダウンロード

今回は、FileMakerの標準機能だけでは実現が難しいドラッグ&ドロップ操作が可能なスケジューラーソリューションの実装方法をお伝えしました。
どうしても記事だけでは伝えきれない部分が多々ございますので、ぜひこちらからサンプルソリューションをダウンロードして、その操作性を体験してみてください。

※サンプルソリューションを動かすには、FileMakerのVer17以降が必要です。

また、サンプルソリューションはロックフリーになっています。

ファイルは完全アクセス権で開くようになっていますので、全ての内部リソースにアクセス可能です。もちろん、このサンプルソリューションをそのまま流用して、あなたのソリューションに組み込んでいただくこともできますし、実際のビジネスにご活用いただくこともできます。

ただし、商用利用の際は、先に書いたとおり別途ライセンスフィーが発生するので、ご注意ください。

ダウンロードURLのリクエスト

    会社名 (必須)

    お名前 (必須)

    メールアドレス (必須)

    最後までお読みいただきありがとうございました。
    この記事にご興味を持たれた方には、こちらの記事もおすすめです。

    • このエントリーをはてなブックマークに追加