diff --git a/examples/eventCalendar/README.md b/examples/eventCalendar/README.md index 05315752..2a1835a8 100644 --- a/examples/eventCalendar/README.md +++ b/examples/eventCalendar/README.md @@ -2,15 +2,9 @@ ## OSS License -* Moment.js - https://momentjs.com/ - * Author: Tim Wood, Iskren Chernev, Moment.js contributors - * License: [MIT License](https://github.com/moment/moment/blob/2.13.0/LICENSE) * FullCalendar - https://fullcalendar.io/ * Author: Adam Shaw - * License: [MIT License](https://github.com/fullcalendar/fullcalendar/blob/v2.7.3/LICENSE.txt) -* jQuery - https://jquery.com/ - * Author: jQuery Foundation, Inc. - * License: [MIT License](https://github.com/jquery/jquery/blob/2.2.4/LICENSE.txt) + * License: [MIT License](https://github.com/fullcalendar/fullcalendar/blob/v6.1.20/LICENSE.md) * JsRender - https://www.jsviews.com/ * Author: Boris Moore * License: [MIT License](https://github.com/BorisMoore/jsrender/blob/v1.0.5/MIT-LICENSE.txt) diff --git a/examples/eventCalendar/css/customize.css b/examples/eventCalendar/css/customize.css index e36c12bd..4ef91f2c 100644 --- a/examples/eventCalendar/css/customize.css +++ b/examples/eventCalendar/css/customize.css @@ -5,24 +5,21 @@ * Licensed under the MIT License */ /* 日曜日 */ -.fc-head .fc-sun { +.fc-col-header-cell.fc-day-sun { background: rgb(250, 220, 233); } /* 土曜日 */ -.fc-head .fc-sat { +.fc-col-header-cell.fc-day-sat { background: rgb(211, 237, 251); } /* 今日 */ -.fc-today { +.fc-day-today { background: rgb(255, 255, 204); } -.fc-center { +/* ツールバー中央(タイトル)のチャンク */ +.fc-toolbar-chunk:nth-child(2) { margin-right: 1.75em; } - -.fc-clear { - clear: none; -} diff --git a/examples/eventCalendar/js/config.js b/examples/eventCalendar/js/config.js index da1c9d62..78e8ded8 100644 --- a/examples/eventCalendar/js/config.js +++ b/examples/eventCalendar/js/config.js @@ -4,237 +4,236 @@ * * Licensed under the MIT License */ -jQuery.noConflict(); -(function($, PLUGIN_ID) { - 'use strict'; - - // プラグインIDの設定 - const conf = kintone.plugin.app.getConfig(PLUGIN_ID); - - $(document).ready(() => { - const terms = { - 'ja': { - 'event_title': 'イベント名フィールド', - 'event_title_description': 'イベント名として使用する文字列フィールドのフィールド名を選択して下さい。', - 'start_dateTime': '開始日時フィールド', - 'start_dateTime_description': 'イベント開始日時として使用する日時フィールドのフィールド名を選択して下さい。', - 'end_dateTime': '終了日時フィールド', - 'terms.end_dateTime_description': 'イベント終了日時として使用する日時フィールドのフィールド名を選択して下さい。', - 'background': 'ステータス(任意)', - 'background_description': 'プロセス管理のステータスと対応する背景色を指定可能です。\n' +((PLUGIN_ID) => { + 'use strict'; + + // プラグインIDの設定 + const conf = kintone.plugin.app.getConfig(PLUGIN_ID); + + const init = () => { + const terms = { + 'ja': { + 'event_title': 'イベント名フィールド', + 'event_title_description': 'イベント名として使用する文字列フィールドのフィールド名を選択して下さい。', + 'start_dateTime': '開始日時フィールド', + 'start_dateTime_description': 'イベント開始日時として使用する日時フィールドのフィールド名を選択して下さい。', + 'end_dateTime': '終了日時フィールド', + 'terms.end_dateTime_description': 'イベント終了日時として使用する日時フィールドのフィールド名を選択して下さい。', + 'background': 'ステータス(任意)', + 'background_description': 'プロセス管理のステータスと対応する背景色を指定可能です。\n' + '
※背景色は英語、16進数、RGBのいずれも可。 赤:red, #ff0000, rgb(255,0,0) 緑:green, #008000, rgb(0,128,0)', - 'background_status': 'ステータス', - 'background_color': '背景色', - 'save_button': '保存する', - 'cancel_button': 'キャンセル' - }, - 'zh': { - 'event_title': '活动标题', - 'event_title_description': '请选择要作为活动标题的字段。', - 'start_dateTime': '开始时间', - 'start_dateTime_description': '请选择要作为活动开始时间的字段。', - 'end_dateTime': '结束时间', - 'terms.end_dateTime_description': '请选择要作为活动结束时间的字段。', - 'background': '状态(任意)', - 'background_description': '可对流程管理的各状态设置背景色。\n' + 'background_status': 'ステータス', + 'background_color': '背景色', + 'save_button': '保存する', + 'cancel_button': 'キャンセル' + }, + 'zh': { + 'event_title': '活动标题', + 'event_title_description': '请选择要作为活动标题的字段。', + 'start_dateTime': '开始时间', + 'start_dateTime_description': '请选择要作为活动开始时间的字段。', + 'end_dateTime': '结束时间', + 'terms.end_dateTime_description': '请选择要作为活动结束时间的字段。', + 'background': '状态(任意)', + 'background_description': '可对流程管理的各状态设置背景色。\n' + '※背景色可用英语、16进制、RGB的任意一种方式来指定。红:red, #ff0000, rgb(255,0,0) 绿:green, #008000, rgb(0,128,0)', - 'background_status': '状态', - 'background_color': '背景色', - 'save_button': '保存', - 'cancel_button': '取消' - } - }; - - // ログインユーザーの設定言語によって表示言語を切り替える - const lang = kintone.getLoginUser().language; - const i18n = (lang in terms) ? terms[lang] : terms.ja; - const configHtml = $('#EventCalendarPlugin').html(); - const tmpl = $.templates(configHtml); - $('div#EventCalendarPlugin').html(tmpl.render({'terms': i18n})); - - // 既に値が設定されている場合はフィールドに値を設定する - if (typeof (conf.name) !== 'undefined') { - $('#status1').val(conf.status1); - $('#color1').val(conf.color1); - $('#status2').val(conf.status2); - $('#color2').val(conf.color2); - $('#status3').val(conf.status3); - $('#color3').val(conf.color3); - $('#status4').val(conf.status4); - $('#color4').val(conf.color4); - $('#status5').val(conf.status5); - $('#color5').val(conf.color5); - } - // アプリのフォーム情報を取得 - kintone.api('/k/v1/preview/app/form/fields', 'GET', { - app: kintone.app.getId() - }, (resp) => { - const singleLineText = []; - const sDatetime = []; - const eDatetime = []; - let count = 0; - - for (const key in resp.properties) { - if (!Object.prototype.hasOwnProperty.call(resp.properties, key)) { - continue; + 'background_status': '状态', + 'background_color': '背景色', + 'save_button': '保存', + 'cancel_button': '取消' + } + }; + + // ログインユーザーの設定言語によって表示言語を切り替える + const lang = kintone.getLoginUser().language; + const i18n = (lang in terms) ? terms[lang] : terms['ja']; + const container = document.getElementById('EventCalendarPlugin'); + // jsrender をスタンドアロン(jQuery非依存)で使用 + const tmpl = jsrender.templates(container.innerHTML); + container.innerHTML = tmpl.render({'terms': i18n}); + + // 既に値が設定されている場合はフィールドに値を設定する + if (typeof conf['name'] !== 'undefined') { + for (let i = 1; i < 6; i++) { + document.getElementById('status' + i).value = conf['status' + i] || ''; + document.getElementById('color' + i).value = conf['color' + i] || ''; + } } - let confFlg = false; - if (resp.properties[key].type === 'SINGLE_LINE_TEXT') { - singleLineText[count] = { - 'label': resp.properties[key].label, - 'key': resp.properties[key].code, - 'index': String(count) - }; - if (typeof (conf.name) !== 'undefined' && resp.properties[key].code === conf.name) { - confFlg = true; - } - if (confFlg) { - $('#name_code').prepend(''); - } else { - $('#name_code').append(''); - } - } else if (resp.properties[key].type === 'DATETIME') { - sDatetime[count] = { - 'label': resp.properties[key].label, - 'key': resp.properties[key].code, - 'index': String(count) - }; - eDatetime[count] = { - 'label': resp.properties[key].label, - 'key': resp.properties[key].code, - 'index': String(count) - }; - if (typeof (conf.name) !== 'undefined' && resp.properties[key].code === conf.start_datetime) { - $('#start_datetime_code').prepend(''); - $('#end_datetime_code').append(''); - } else if (typeof (conf.name) !== 'undefined' && resp.properties[key].code === conf.end_datetime) { - $('#start_datetime_code').append(''); - $('#end_datetime_code').prepend(''); - } else { - $('#start_datetime_code').append(''); - $('#end_datetime_code').append(''); - } - } - count++; - } - - - // 「保存する」ボタン押下時に入力情報を設定する - $('#submit').click(() => { - const config = {}; - let name; - let start_datetime; - let end_datetime; - singleLineText.filter((item) => { - if (item.label === $('#name_code :selected').text() && - item.index === $('#name_code :selected').attr('name')) { - name = item.key; - return true; - } - }); - sDatetime.filter((item) => { - if (item.label === $('#start_datetime_code :selected').text() && - item.index === $('#start_datetime_code :selected').attr('name')) { - start_datetime = item.key; - return true; - } - }); - eDatetime.filter((item) => { - if (item.label === $('#end_datetime_code :selected').text() && - item.index === $('#end_datetime_code :selected').attr('name')) { - end_datetime = item.key; - return true; - } - }); - const status1 = $('#status1').val(); - const color1 = $('#color1').val(); - const status2 = $('#status2').val(); - const color2 = $('#color2').val(); - const status3 = $('#status3').val(); - const color3 = $('#color3').val(); - const status4 = $('#status4').val(); - const color4 = $('#color4').val(); - const status5 = $('#status5').val(); - const color5 = $('#color5').val(); - - if (name === '' || start_datetime === '' || end_datetime === '') { - alert('入力されていない必須項目があります。'); - return; - } - config.name = name; - config.start_datetime = start_datetime; - config.end_datetime = end_datetime; - config.status1 = status1; - config.color1 = color1; - config.status2 = status2; - config.color2 = color2; - config.status3 = status3; - config.color3 = color3; - config.status4 = status4; - config.color4 = color4; - config.status5 = status5; - config.color5 = color5; - - // カスタマイズビューを追加 - const VIEW_NAME = 'スケジュール'; - kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'GET', { - 'app': kintone.app.getId() - }).then((scheResp) => { - const req = $.extend(true, {}, scheResp); - req.app = kintone.app.getId(); - - // 作成したビューが存在するか - let existFlg = false; - for (const k in req.views) { - if (req.views[k].id === conf.viewId) { - existFlg = true; - break; + const nameSelect = document.getElementById('name_code'); + const startSelect = document.getElementById('start_datetime_code'); + const endSelect = document.getElementById('end_datetime_code'); + + // option 要素を生成する + const createOption = (label, index, selected) => { + const opt = document.createElement('option'); + opt.setAttribute('name', index); + opt.textContent = label; + if (selected) { + opt.selected = true; } - } - - // カスタマイズビューが存在しなければ追加 - if (!existFlg) { - - // 一番上のビュー(デフォルトビュー)に「スケジュール」ビューを作成 - for (const prop in req.views) { - if (Object.prototype.hasOwnProperty.call(req.views, prop)) { - req.views[prop].index = Number(req.views[prop].index) + 1; - } + return opt; + }; + + // アプリのフォーム情報を取得 + kintone.api('/k/v1/preview/app/form/fields', 'GET', { + app: kintone.app.getId() + }, (resp) => { + const singleLineText = []; + const sDatetime = []; + const eDatetime = []; + let count = 0; + + for (const key in resp.properties) { + if (!Object.prototype.hasOwnProperty.call(resp.properties, key)) {continue;} + const property = resp.properties[key]; + if (property.type === 'SINGLE_LINE_TEXT') { + singleLineText[count] = { + 'label': property.label, + 'key': property.code, + 'index': String(count) + }; + const isSelected = typeof conf['name'] !== 'undefined' && property.code === conf['name']; + if (isSelected) { + nameSelect.insertBefore(createOption(property.label, count, true), nameSelect.firstChild); + } else { + nameSelect.appendChild(createOption(property.label, count, false)); + } + } else if (property.type === 'DATETIME') { + sDatetime[count] = { + 'label': property.label, + 'key': property.code, + 'index': String(count) + }; + eDatetime[count] = { + 'label': property.label, + 'key': property.code, + 'index': String(count) + }; + if (typeof conf['name'] !== 'undefined' && property.code === conf['start_datetime']) { + startSelect.insertBefore(createOption(property.label, count, true), startSelect.firstChild); + endSelect.appendChild(createOption(property.label, count, false)); + } else if (typeof conf['name'] !== 'undefined' && property.code === conf['end_datetime']) { + startSelect.appendChild(createOption(property.label, count, false)); + endSelect.insertBefore(createOption(property.label, count, true), endSelect.firstChild); + } else { + startSelect.appendChild(createOption(property.label, count, false)); + endSelect.appendChild(createOption(property.label, count, false)); + } + } + count++; } - req.views[VIEW_NAME] = { - 'type': 'CUSTOM', - 'name': VIEW_NAME, - 'html': '
', - 'filterCond': '', - 'pager': true, - 'index': 0 - }; - - kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'PUT', req).then((putResp) => { - // 作成したビューIDを保存する - const viewId = putResp.views[VIEW_NAME].id; - config.viewId = viewId; - kintone.plugin.app.setConfig(config); + // 「保存する」ボタン押下時に入力情報を設定する + document.getElementById('submit').addEventListener('click', () => { + const config = {}; + let name; + let startDatetime; + let endDatetime; + + const nameSelected = nameSelect.selectedOptions[0]; + singleLineText.filter((item) => { + if (nameSelected && item.label === nameSelected.textContent && + item.index === nameSelected.getAttribute('name')) { + name = item.key; + return true; + } + return false; + }); + const startSelected = startSelect.selectedOptions[0]; + sDatetime.filter((item) => { + if (startSelected && item.label === startSelected.textContent && + item.index === startSelected.getAttribute('name')) { + startDatetime = item.key; + return true; + } + return false; + }); + const endSelected = endSelect.selectedOptions[0]; + eDatetime.filter((item) => { + if (endSelected && item.label === endSelected.textContent && + item.index === endSelected.getAttribute('name')) { + endDatetime = item.key; + return true; + } + return false; + }); + + if (name === '' || startDatetime === '' || endDatetime === '') { + alert('入力されていない必須項目があります。'); + return; + } + config['name'] = name; + config['start_datetime'] = startDatetime; + config['end_datetime'] = endDatetime; + for (let i = 1; i < 6; i++) { + config['status' + i] = document.getElementById('status' + i).value; + config['color' + i] = document.getElementById('color' + i).value; + } + + // カスタマイズビューを追加 + const VIEW_NAME = 'スケジュール'; + kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'GET', { + 'app': kintone.app.getId() + }).then((scheResp) => { + const req = structuredClone(scheResp); + req.app = kintone.app.getId(); + + // 作成したビューが存在するか + let existFlg = false; + for (const k in req.views) { + if (req.views[k].id === conf['viewId']) { + existFlg = true; + break; + } + } + + // カスタマイズビューが存在しなければ追加 + if (!existFlg) { + + // 一番上のビュー(デフォルトビュー)に「スケジュール」ビューを作成 + for (const prop in req.views) { + if (Object.prototype.hasOwnProperty.call(req.views, prop)) { + req.views[prop].index = Number(req.views[prop].index) + 1; + } + } + + req.views[VIEW_NAME] = { + 'type': 'CUSTOM', + 'name': VIEW_NAME, + 'html': '
', + 'filterCond': '', + 'pager': true, + 'index': 0 + }; + + kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'PUT', req).then((putResp) => { + // 作成したビューIDを保存する + config['viewId'] = putResp.views[VIEW_NAME].id; + kintone.plugin.app.setConfig(config); + }); + + } else { + config['viewId'] = conf['viewId']; + kintone.plugin.app.setConfig(config); + } + + }); }); - } else { - config.viewId = conf.viewId; - kintone.plugin.app.setConfig(config); - } + // 「キャンセル」ボタン押下時の処理 + document.getElementById('cancel').addEventListener('click', () => { + history.back(); + }); }); - }); - - // 「キャンセル」ボタン押下時の処理 - $('#cancel').click(() => { - history.back(); - }); + }; - }); - }); + // jQuery の $(document).ready 相当(読み込み済みなら即実行) + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } -})(jQuery, kintone.$PLUGIN_ID); +})(kintone.$PLUGIN_ID); diff --git a/examples/eventCalendar/js/customize.js b/examples/eventCalendar/js/customize.js index e4440445..de6b25cf 100644 --- a/examples/eventCalendar/js/customize.js +++ b/examples/eventCalendar/js/customize.js @@ -4,302 +4,235 @@ * * Licensed under the MIT License */ -jQuery.noConflict(); -(function($, PLUGIN_ID) { - 'use strict'; - - // 文言多言語化 - function createMultilingual(num) { - let user_lang = kintone.getLoginUser().language; - const multilingual = { - 'ja': { - '1': 'YYYY年M月', - '2': 'YYYY年 M月 D日', - '3': 'YYYY年 M月 D日[(]ddd[)]', - '4': '今日', - '5': '月', - '6': '週', - '7': '日', - '8': ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], - '9': ['日曜', '月曜', '火曜', '水曜', '木曜', '金曜', '土曜'], - '10': ['日', '月', '火', '水', '木', '金', '土'], - '11': 'すべて見る', - '12': '未入力項目があります', - '13': '必須です', - '14': '開始日時が終了日時より未来になっています', - '15': '終了日時より過去にして下さい', - '16': '開始日時より未来にして下さい', - '17': '開始日時と終了日時は1分以上あけて下さ' - }, - 'zh': { - '1': 'YYYY年M月', - '2': 'YYYY年 M月 D日', - '3': 'YYYY年 M月 D日[(]ddd[)]', - '4': '今天', - '5': '月', - '6': '周', - '7': '日', - '8': ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], - '9': ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], - '10': ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], - '11': '显示全部', - '12': '有必填项未填', - '13': '必填', - '14': '开始时间比结束时间晚', - '15': '请选择比结束时间早的时间', - '16': '请选择比开始时间晚的时间', - '17': '开始时间和结束时间必须间隔至少1分钟' - } +((PLUGIN_ID) => { + 'use strict'; + + // 文言多言語化 + const createMultilingual = (num) => { + let userLang = kintone.getLoginUser().language; + const multilingual = { + 'ja': { + '11': 'すべて見る', + '12': '未入力項目があります', + '13': '必須です', + '14': '開始日時が終了日時より未来になっています', + '15': '終了日時より過去にして下さい', + '16': '開始日時より未来にして下さい', + '17': '開始日時と終了日時は1分以上あけて下さ' + }, + 'zh': { + '11': '显示全部', + '12': '有必填项未填', + '13': '必填', + '14': '开始时间比结束时间晚', + '15': '请选择比结束时间早的时间', + '16': '请选择比开始时间晚的时间', + '17': '开始时间和结束时间必须间隔至少1分钟' + } + }; + if (!multilingual[userLang]) { + userLang = 'ja'; + } + return multilingual[userLang][num]; }; - if (!multilingual[user_lang]) { - user_lang = 'ja'; - } - return multilingual[user_lang][num]; - } - // カレンダー上でイベントの時間を変更した時の更新処理 - function putRecord(event) { - const putConfig = kintone.plugin.app.getConfig(PLUGIN_ID); - const stdtKey = putConfig.start_datetime; - const eddtKey = putConfig.end_datetime; + // カレンダー上でイベントの時間を変更した時の更新処理 + const putRecord = (calEvent) => { + const putConfig = kintone.plugin.app.getConfig(PLUGIN_ID); + const stdtKey = putConfig.start_datetime; + const eddtKey = putConfig.end_datetime; - kintone.api('/k/v1/record', 'PUT', { - 'app': kintone.app.getId(), - 'id': event.rec, - 'record': (function() { const param = {}; - param[stdtKey] = { - 'value': moment(event.start).add(-9, 'hours').format('YYYY-MM-DDTHH:mm:ssZ') - }; - param[eddtKey] = { - 'value': moment(event.end).add(-9, 'hours').format('YYYY-MM-DDTHH:mm:ssZ') - }; - return param; - })() - }); - } - - // 全件取得関数 - function fetchRecords(appId, query, opt_offset, opt_limit, opt_records) { - const offset = opt_offset || 0; - const limit = opt_limit || 500; - let allRecords = opt_records || []; - const params = {app: appId, query: query + ' limit ' + limit + ' offset ' + offset}; - return kintone.api('/k/v1/records', 'GET', params).then((resp) => { - allRecords = allRecords.concat(resp.records); - if (resp.records.length === limit) { - return fetchRecords(appId, query, offset + limit, limit, allRecords); - } - return allRecords; - }); - } - - // レコード一覧画面表示イベント - kintone.events.on('app.record.index.show', (event) => { - const config = kintone.plugin.app.getConfig(PLUGIN_ID); - if (!config) { - return false; - } - - new kintone.Promise((resolve, reject) => { - - const evTitle = config.name; - const evStart = config.start_datetime; - const evEnd = config.end_datetime; - const query = kintone.app.getQueryCondition(); - - let startDate; - let endDate; + // FullCalendar v6 の event.start / event.end はネイティブ Date(絶対時刻) + // toISOString() で UTC の ISO8601 に変換してそのまま保存する + param[stdtKey] = {value: calEvent.start.toISOString()}; + param[eddtKey] = {value: calEvent.end.toISOString()}; + + kintone.api('/k/v1/record', 'PUT', { + app: kintone.app.getId(), + id: calEvent.extendedProps.rec, + record: param + }); + }; - fetchRecords(kintone.app.getId(), query).then((calRecords) => { + // 全件取得関数 + const fetchRecords = (appId, query, optOffset, optLimit, optRecords) => { + const offset = optOffset || 0; + const limit = optLimit || 500; + let allRecords = optRecords || []; + const params = {app: appId, query: query + ' limit ' + limit + ' offset ' + offset}; + return kintone.api('/k/v1/records', 'GET', params).then((resp) => { + allRecords = allRecords.concat(resp.records); + if (resp.records.length === limit) { + return fetchRecords(appId, query, offset + limit, limit, allRecords); + } + return allRecords; + }); + }; - const records = calRecords; - const recEvents = []; - // アプリにレコードがある場合のみループ - if (records.length !== 0) { - for (let i = 0; i < records.length; i++) { - startDate = moment(records[i][evStart].value); - endDate = moment(records[i][evEnd].value); + // レコード一覧画面表示イベント + kintone.events.on('app.record.index.show', (event) => { + const config = kintone.plugin.app.getConfig(PLUGIN_ID); + if (!config) { + return event; + } - // イベント背景色設定でミスがある場合とプロセス管理無効の場合はデフォルト青色とする - let eventColor = '#0000ff'; - // イベント背景色設定処理 - let eventStatus; - let flag = false; - if (typeof (records[i].ステータス) !== 'undefined') { - eventStatus = records[i].ステータス.value; - } else if (typeof (records[i].状态) !== 'undefined') { - eventStatus = records[i].状态.value; - } else if (typeof (records[i].Status) !== 'undefined') { - eventStatus = records[i].Status.value; - } else { - flag = true; - } + const evTitle = config.name; + const evStart = config.start_datetime; + const evEnd = config.end_datetime; + const query = kintone.app.getQueryCondition(); + + fetchRecords(kintone.app.getId(), query).then((records) => { + const recEvents = []; + for (const record of records) { + // イベント背景色設定でミスがある場合とプロセス管理無効の場合はデフォルト青色とする + let eventColor = '#0000ff'; + // イベント背景色設定処理 + let eventStatus; + let flag = false; + if (typeof record.ステータス !== 'undefined') { + eventStatus = record.ステータス.value; + } else if (typeof record.状态 !== 'undefined') { + eventStatus = record.状态.value; + } else if (typeof record.Status !== 'undefined') { + eventStatus = record.Status.value; + } else { + flag = true; + } - if (flag === false) { - for (let k = 1; k < 6; k++) { - const stsPropName = 'status' + k; - const clrPropName = 'color' + k; - const status = config[stsPropName]; - if (status === eventStatus) { - eventColor = config[clrPropName]; - break; + if (flag === false) { + for (let k = 1; k < 6; k++) { + const status = config['status' + k]; + if (status === eventStatus) { + eventColor = config['color' + k]; + break; + } + } } - } + + recEvents.push({ + title: record[evTitle].value, + // kintone の日時値(UTC ISO8601)を Date に変換。timeZone:'local' で端末TZ表示 + start: new Date(record[evStart].value), + end: new Date(record[evEnd].value), + url: location.protocol + '//' + location.hostname + '/k/' + + kintone.app.getId() + '/show#record=' + record.$id.value, + backgroundColor: eventColor, + borderColor: eventColor, + // カスタムプロパティは extendedProps へ + extendedProps: { + rec: record.$id.value + } + }); } - recEvents.push({ - title: records[i][evTitle].value, - start: startDate.format('YYYY-MM-DD HH:mm:ss'), - end: endDate.format('YYYY-MM-DD HH:mm:ss'), - url: location.protocol + '//' + location.hostname + '/k/' + - kintone.app.getId() + '/show#record=' + records[i].$id.value, - rec: records[i].$id.value, - backgroundColor: eventColor, - borderColor: eventColor + // カレンダーの設定 + const calendarEl = document.getElementById('calendar'); + const calendar = new FullCalendar.Calendar(calendarEl, { + locale: 'ja', + // 上部のボタンやタイトル + headerToolbar: { + left: 'prev,next today', + center: 'title', + right: 'dayGridMonth,timeGridWeek,timeGridDay' + }, + // 各カレンダーの各時間の表記(24時間表記) + slotLabelFormat: {hour: 'numeric', minute: '2-digit', hour12: false}, + eventTimeFormat: {hour: 'numeric', minute: '2-digit', hour12: false}, + // 日曜開始のカレンダーとする + firstDay: 0, + // 週末(土日)を表示 + weekends: true, + // デフォルトは月カレンダー + initialView: 'dayGridMonth', + // イベントをカレンダー上から編集する + editable: true, + eventDurationEditable: true, + eventStartEditable: true, + dragRevertDuration: 100, + // 終日予定は表示しない + allDaySlot: false, + // 0時区切りのカレンダーとする + nextDayThreshold: '00:00:00', + // カレンダーの高さ + height: 700, + contentHeight: 600, + // 時間軸の単位 + slotDuration: '01:00:00', + // 何分刻みでバーを動かすか + snapDuration: '01:00:00', + // 日カレンダーのみ詳細に表示するための設定 + views: { + timeGridDay: { + slotDuration: '00:30:00', + snapDuration: '00:30:00', + scrollTime: '06:00:00' + } + }, + slotMinTime: '00:00:00', + slotMaxTime: '24:00:00', + // 初期時間位置 + scrollTime: '00:00:00', + // 月カレンダーでイベントが多い場合に表示を省略する + dayMaxEvents: true, + moreLinkText: () => createMultilingual('11'), + eventResize: (info) => { + putRecord(info.event); + calendar.unselect(); + }, + eventDrop: (info) => { + putRecord(info.event); + calendar.unselect(); + }, + events: recEvents }); - } - } - - // カレンダーの設定 - $('#calendar').fullCalendar({ - lang: 'ja', - theme: false, - // 上部のボタンやタイトル - header: { - left: 'prev,next, today', - center: 'title', - right: ' month,agendaWeek,agendaDay' - }, - // 各カレンダーの1日毎の表記方法 - columnFormat: { - month: 'ddd', - week: 'M/D[(]ddd[)]', - day: 'M/D[(]ddd[)]' - }, - // 各カレンダーのタイトル - titleFormat: { - month: createMultilingual('1'), - week: createMultilingual('2'), - day: createMultilingual('3') - }, - // ボタン文字列の表記 - buttonText: { - prev: '<', - next: '>', - today: createMultilingual('4'), - month: createMultilingual('5'), - week: createMultilingual('6'), - day: createMultilingual('7') - }, - // 日曜開始のカレンダーとする - firstDay: '0', - // 週末(土日)を表示 - weekends: true, - // デフォルトは月カレンダー - defaultView: 'month', - // 月の表記 - monthNames: createMultilingual('8'), - monthNamesShort: createMultilingual('8'), - // 曜日の表記 - dayNames: createMultilingual('9'), - dayNamesShort: createMultilingual('10'), - // 各カレンダーの各時間の表記 - axisFormat: 'H:mm', - timeFormat: 'H:mm', - // イベントをカレンダー上から編集する - editable: true, - durationEditable: true, - startEditable: true, - unselectAuto: true, - unselectCancel: '', - dragRevertDuration: 100, - // 終日予定は表示しない - allDaySlot: false, - // 0時区切りのカレンダーとする - nextDayThreshold: '00:00:00', - // カレンダーの高さ - height: 700, - contentHeight: 600, - // 時間軸の単位 - slotDuration: '01:00:00', - // 何分刻みでバーを動かすか - snapDuration: '01:00:00', - // 日カレンダーのみ詳細に表示するための設定 - views: { - day: { - slotDuration: '00:30:00', - snapDuration: '00:30:00', - scrollTime: '06:00:00' - } - }, - minTime: '00:00:00', - maxTime: '24:00:00', - // 初期時間位置 - scrollTime: '00:00:00', - // 月カレンダーでイベントが多い場合に表所を省略する - eventLimit: true, - eventLimitText: createMultilingual('11'), - eventResize: function(ev, delta, revertFunc, jsEvent, ui, view) { - putRecord(ev); - $('#calendar').fullCalendar('unselect'); - }, - eventDrop: function(ev, delta, revertFunc, jsEvent, ui, view) { - putRecord(ev); - $('#calendar').fullCalendar('unselect'); - }, - eventSources: [{ - events: recEvents - }] + calendar.render(); }); - resolve(event); - }); - }).then(() => { - return event; + + return event; }); - }); - // レコード作成・編集画面・一覧編集イベント - kintone.events.on(['app.record.create.submit', 'app.record.edit.submit', - 'app.record.index.edit.submit'], (event) => { - const record = event.record; + // レコード作成・編集画面・一覧編集イベント + kintone.events.on(['app.record.create.submit', 'app.record.edit.submit', + 'app.record.index.edit.submit'], (event) => { + const record = event.record; - const config = kintone.plugin.app.getConfig(PLUGIN_ID); - if (!config) { - return false; - } + const config = kintone.plugin.app.getConfig(PLUGIN_ID); + if (!config) { + return event; + } - const evTitleVal = record[config.name].value; - const evStartVal = record[config.start_datetime].value; - const evEndVal = record[config.end_datetime].value; + const evTitleVal = record[config.name].value; + const evStartVal = record[config.start_datetime].value; + const evEndVal = record[config.end_datetime].value; - // イベントタイトル・イベント開始/終了日時は未入力不可 - if (!evTitleVal || !evStartVal || !evEndVal) { - event.error = createMultilingual('12'); - if (!evTitleVal) { - record[config.name].error = createMultilingual('13'); - } - if (!evStartVal) { - record[config.start_datetime].error = createMultilingual('13'); - } - if (!evEndVal) { - record[config.end_datetime].error = createMultilingual('13'); - } - // 開始日時が終了日時より未来の場合はエラー - } else if (moment(evStartVal).format('X') > moment(evEndVal).format('X')) { - event.error = createMultilingual('14'); - record[config.start_datetime].error = createMultilingual('15'); - record[config.end_datetime].error = createMultilingual('16'); - // 開始日時と終了日時が同時刻の場合はエラー(FullCalendarの仕様上の問題) - } else if (moment(evStartVal).format('X') === moment(evEndVal).format('X')) { - event.error = createMultilingual('17'); - record[config.start_datetime].error = createMultilingual('15'); - record[config.end_datetime].error = createMultilingual('16'); - } + // イベントタイトル・イベント開始/終了日時は未入力不可 + if (!evTitleVal || !evStartVal || !evEndVal) { + event.error = createMultilingual('12'); + if (!evTitleVal) { + record[config.name].error = createMultilingual('13'); + } + if (!evStartVal) { + record[config.start_datetime].error = createMultilingual('13'); + } + if (!evEndVal) { + record[config.end_datetime].error = createMultilingual('13'); + } + // 開始日時が終了日時より未来の場合はエラー + } else if (new Date(evStartVal).getTime() > new Date(evEndVal).getTime()) { + event.error = createMultilingual('14'); + record[config.start_datetime].error = createMultilingual('15'); + record[config.end_datetime].error = createMultilingual('16'); + // 開始日時と終了日時が同時刻の場合はエラー(FullCalendarの仕様上の問題) + } else if (new Date(evStartVal).getTime() === new Date(evEndVal).getTime()) { + event.error = createMultilingual('17'); + record[config.start_datetime].error = createMultilingual('15'); + record[config.end_datetime].error = createMultilingual('16'); + } - return event; + return event; - }); + }); -})(jQuery, kintone.$PLUGIN_ID); +})(kintone.$PLUGIN_ID); diff --git a/examples/eventCalendar/manifest.json b/examples/eventCalendar/manifest.json index 67980a97..92239fba 100644 --- a/examples/eventCalendar/manifest.json +++ b/examples/eventCalendar/manifest.json @@ -1,6 +1,6 @@ { "manifest_version": 1, - "version": "1.4.3", + "version": "2.0.0", "type": "APP", "name": { "ja": "kintone イベントカレンダープラグイン", @@ -20,20 +20,17 @@ }, "desktop": { "js": [ - "https://js.cybozu.com/jquery/2.2.4/jquery.min.js", - "https://js.cybozu.com/momentjs/2.13.0/moment-with-locales.min.js", - "https://js.cybozu.com/fullcalendar/v2.7.3/fullcalendar.min.js", + "https://js.cybozu.com/fullcalendar/v6.1.20/index.global.min.js", + "https://js.cybozu.com/fullcalendar/v6.1.20/locale/locales-all.global.min.js", "js/customize.js" ], "css": [ - "https://js.cybozu.com/fullcalendar/v2.7.3/fullcalendar.min.css", "css/customize.css" ] }, "config": { "html": "html/config.html", "js": [ - "https://js.cybozu.com/jquery/1.11.1/jquery.min.js", "https://js.cybozu.com/jsrender/1.0.5/jsrender.min.js", "js/config.js" ],