1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
/*
* Garoon white board sample program
* Copyright (c) 2019 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
(function($) {
'use strict';
// momentの設定を日本にする
moment.locale('ja');
function makeXMLHeader(service, action) {
const xmlns = 'soap="http://www.w3.org/2003/05/soap-envelope"';
return (
'<?xml version="1.0" encoding="UTF-8"?>' +
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" ' +
'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" ' +
'xmlns:' + xmlns + '>' +
'<SOAP-ENV:Header>' +
'<Action SOAP-ENV:mustUnderstand="1" ' +
'xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing">' + action + '</Action>' +
'<Timestamp SOAP-ENV:mustUnderstand="1" Id="id" ' +
'xmlns="http://schemas.xmlsoap.org/ws/2002/07/utility">' +
'<Created>2037-08-12T14:45:00Z</Created>' +
'<Expires>2037-08-12T14:45:00Z</Expires>' +
'</Timestamp>' +
'<Locale>jp</Locale>' +
'</SOAP-ENV:Header>'
);
}
function runAjax(url, method, data, token) {
const settings = {
type: method,
url: url,
data: data,
};
settings.headers = {
'Content-Type': 'text/xml; charset=UTF-8',
'X-Cybozu-API-Token': 'XMLHttpRequest'
};
// Promiseでラップする
return new garoon.Promise((resolve, reject) => {
$.ajax(settings)
.done(resolve)
.fail(reject);
});
}
// SOAP API BaseGetUsersByIdを実行する
function getBaseGetUsersById() {
const xmlGetUsers = makeXMLHeader('base', 'BaseGetUsersById') +
'<SOAP-ENV:Body>' +
'<BaseGetUsersById>' +
'<parameters>' +
'<user_id>' + garoon.base.user.getLoginUser().garoonId + '</user_id>' +
'</parameters>' +
'</BaseGetUsersById>' +
'</SOAP-ENV:Body></SOAP-ENV:Envelope>';
// ユーザーの詳細情報を取得する
return runAjax('/g/cbpapi/base/api.csp', 'POST', xmlGetUsers)
.then((resUsers) => {
return resUsers;
}).catch((err) => {
return err;
});
}
// garoon.api() を使って、レコード検索を一括で行う
// 途中でエラーが発生した場合でも処理は続行する
function fetchDatas(aryobj, opt_datas, pidx) {
let allDatas = opt_datas || [],
idx = pidx || 0;
return garoon.api(aryobj[idx], 'GET', {}).catch((err) => {
return err;
}).then((resp) => {
allDatas = allDatas.concat(resp);
idx += 1;
if (aryobj.length !== idx) {
return fetchDatas(aryobj, allDatas, idx);
}
return allDatas;
});
}
// 日時から日付または時刻を返す
function getDateOrTime(dt) {
// dtが当日だったら、時刻を返す
if (moment(dt).format('YYYYMMDD') === moment().format('YYYYMMDD')) {
return moment(dt).format('HH:mm');
}
// dtが当日でなければ、日付を返す
return moment(dt).format('MM/DD');
}
// 行動掲示板を作成する
function makeOutBoard(users, psch) {
let sch, starthhmm, endhhmm;
$('.schtr').remove();
// 画面更新時の日時を表示
$('#currenttime').html(moment().format('YYYY年MM月DD日(ddd) HH:mm'));
// テーブルの1行の構成を定義する
const comptr = _.template(
'<tr class="schtr">' +
'<td id="tdschuser<%- userid %>" class="nowrap_grn" scope="row"></td>' +
'<td><ul id="uischevents<%- userid %>" class="schedule_board_item_grn">' +
'</ul></td>' +
'<td id="tdschreturn<%- userid %>"></td>' +
'<td><ul id="uischcurrent<%- userid %>" ' +
'class="schedule_board_item_grn schedule_board_item_current_grn">' +
'</ul></td>' +
'</tr>'
);
// 外出予定セルの構成を定義する
const compsch = _.template(
'<li><a href="/g/schedule/view.csp?event=<%- evid %>" target="_blank">' +
'<span class="schedule_board_time_grn"><%- evtime %></span>' +
'<span class="<%- evcolor %> schedule_board_event_grn"><%- evmenu %></span>' +
'<span><%- evsubject %></span>' +
'</a></li>'
);
// 一般的なセルの構成を定義する
const comptext = _.template(
'<div class="tddiv"><span><%- txtbody %></span></div>'
);
// スケジュール表示部分を定義する
const complist = _.template(
'<li><span><%- libody %></span></li>'
);
// スケジュールのメニューに対応する色を返す
const eventcolor = function(pmenu) {
if (pmenu === '出張') {
return 'event_color3_grn';
} else if (pmenu === '往訪') {
return 'event_color5_grn';
} else if (pmenu === '休み') {
return 'event_color4_grn';
}
return 'event_color2_grn';
};
// テーブルにユーザーごとのスケジュールを記入する
for (let i = 0; i < users.length; i += 1) {
if (!psch[i].statusCode || psch[i].statusCode > 201) continue;
sch = psch[i].data.events;
// テーブルの要素を追加
$('#schtbody').append(comptr({userid: users[i].id}));
// 名前の列に氏名を表示
$('#tdschuser' + users[i].id).append(comptext({txtbody: users[i].name}));
// スケジュールの内容をテーブルに表示
for (let j = 0; j < sch.length; j += 1) {
// スケジュールの開始日時と終了日時
// 日付が当日であれば時刻のみ、当日でなければ日時を取得する
starthhmm = getDateOrTime(sch[j].start.dateTime);
endhhmm = sch[j].end ? getDateOrTime(sch[j].end.dateTime) : '';
// メニューが「往訪」「 出張」「 休み」 に該当する場合は、予定に表示
if (sch[j].eventMenu === '往訪' ||
sch[j].eventMenu === '出張' ||
sch[j].eventMenu === '休み') {
// 「外出予定」列に、日時、メニュー、題目を表示する
$('#uischevents' + users[i].id).append(
compsch({
evid: sch[j].id,
evtime: starthhmm + ' - ' + endhhmm,
evmenu: sch[j].eventMenu,
evsubject: sch[j].subject,
evcolor: eventcolor(sch[j].eventMenu)
})
);
// スケジュールの日時が現在の時間に該当する場合は、「現在の予定」の列に表示
if (moment(sch[j].start.dateTime) < moment() &&
(!sch[j].end || moment() < moment(sch[j].end.dateTime))) {
$('#uischcurrent' + users[i].id).append(
complist({libody: sch[j].subject})
);
}
}
// メニューが「帰社」に該当する場合は、「帰社時刻」の列に日時を表示
if (sch[j].eventMenu === '帰社') {
// 終了日時が入っていれば終了日時、なければ開始日時
$('#tdschreturn' + users[i].id).append(
comptext({txtbody: endhhmm ? endhhmm : starthhmm})
);
}
}
}
return null;
}
// グループのメンバーとスケジュールを取得する
function getScheduleData(porgid) {
const orgid = porgid ? porgid : $('#selorgs').val();
let users;
// 優先する組織に所属しているメンバーを取得する
return garoon.api('/api/v1/base/organizations/' + orgid + '/users', 'GET', {}).then((res) => {
const aryquery = [],
aryurl = [];
users = res.data.users;
if (users.length < 1) {
return null;
}
// スケジュールのソート指定: 開始時刻の昇順
aryquery.push('orderBy=start asc');
// スケジュールを検索する日時の範囲:開始時間(現在の時刻)
aryquery.push('rangeStart=' + moment().utc().format('YYYY-MM-DDTHH:mm:ss') + 'Z');
// スケジュールを検索する日時の範囲:終了時間(東京時間で翌日朝5時)
aryquery.push('rangeEnd=' + moment().format('YYYY-MM-DD') + 'T20:00:00Z');
// スケジュールの検索対象:ユーザー
aryquery.push('targetType=user');
// スケジュールを検索するユーザーのid
aryquery.push('target=');
const queryhead = aryquery.join('&');
// 所属メンバーのスケジュールを取得する
for (let i = 0; i < users.length; i += 1) {
aryurl.push('/api/v1/schedule/events?' + queryhead + users[i].id);
}
// 人数分のスケジュールを一括で取得する
return fetchDatas(aryurl);
}).then((resusers) => {
// 行動掲示板を作成する
return makeOutBoard(users, resusers);
});
}
// 処理開始
function init() {
$('#divbody').append('<div id="divschtop"><select id="selorgs"></select></div>');
// 組織選択セレクトボックスの値が変わったら、選択した組織でスケジュールを表示
$('#selorgs').change(() => {
getScheduleData($('#selorgs').val());
});
// 更新ボタンがおされたら、スケジュールデータの再読み込みを行う
$('.schedule_board_update_button_base_grn').click(() => {
getScheduleData($('#selorgs').val());
});
// 組織情報を取得する
return garoon.api('/api/v1/base/organizations', 'GET', {}).then((resorgs) => {
// 組織情報
const orgs = resorgs.data.organizations;
// 組織の登録がない場合
if (!orgs || orgs.length === 0) {
throw new Error('組織が登録されていません');
}
// 組織セレクトボックスのオプション
const compopt = _.template('<option value="<%- orgid %>"><%- orgname %></option>');
// 組織選択セレクトボックスに組織をセットする
for (let i = 0; i < orgs.length; i += 1) {
$('#selorgs').append(compopt({orgid: orgs[i].id, orgname: orgs[i].name}));
}
// ログインユーザーの情報を取得する
return getBaseGetUsersById();
}).then((resUsers) => {
// 優先する組織のidを取得する
// 優先する組織がない場合は、組織リストボックスの一番上の組織とする
const porg = $(resUsers).find('user').attr('primary_organization') ||
$('#selorgs option')[0].value;
// 組織選択リストボックスを、表示する組織が選択された状態にする
$('#selorgs').val(porg);
// スケジュールデータを取得する
return getScheduleData(porg);
}).then((resresult) => {
// 処理がすべて終わってから、予定表を表示する
$('.schedule_board_grn').css('display', 'block');
}).catch((err) => {
alert(err);
});
}
init();
})(jQuery.noConflict(true));
|