Skip to content

カレンダーへの祝日表示の標準機能化 ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.8.1

カレンダーには祝日を表示する機能がありません。本体を改修せずに表示する方法(CSS 方式・拡張スクリプトで祝日マスタを読む方式)は カレンダー にあります。このページは、祝日マスタを本体の機能として読み込む改修の設計メモです。本体の標準機能ではありません。

前提にした現行実装(1.5.8.1) ​

カレンダーの種類 ​

種類実装CalendarTypes
標準サーバーで HTML の表を出力(HtmlCalendar.cs)Standard = 1
FullCalendarFullCalendar(@fullcalendar/core 6.1.21)をブラウザで初期化(calendar.ts)FullCalendar = 2

既定は General.json の DefaultCalendarType: 2(FullCalendar)です(SiteSettings.cs、General.json)。

標準カレンダーの日付セル ​

月表示の日付セル(td)に付くクラスは container、当日の today、表示月以外の other-month だけです。data-id に yyyy/M/d の日付が入ります(HtmlCalendar.cs)。曜日のクラス(sunday・saturday など、DayOfWeekCss() が DayOfWeek を小文字にしたもの)は見出しの th にだけ付きます(HtmlCalendar.cs)。

FullCalendar の初期化 ​

calendar.ts で $p.fullCalendars[calendarSuffix] に FullCalendar.Calendar を作ります。レコードは events: getEventsData(calendarSuffix) で、隠し項目 #CalendarJson{サフィックス} の JSON から作っています(calendar.ts)。

参考にするアナウンス機能 ​

アナウンスは Service.json の AnnouncementSiteId で指定した期限付きテーブルから、Status < CompletionCode かつ StartTime <= 現在 <= CompletionTime のレコードを IssueCollection で読み、画面上部に出します(HtmlHeaders.cs)。IssueCollection の取得は渡した条件(サイト ID・状況・日時)だけで SELECT し、権限の条件は足しません(IssueCollection.cs)。そのため、マスタのサイトに読み取り権限が無いユーザーやログイン前の画面にも表示されます。表示制御の詳細は アナウンス機能の改善 にあります。

設計 ​

アナウンスとの対応 ​

項目アナウンス祝日(追加)
テーブル期限付きテーブル記録テーブル
パラメータAnnouncementSiteIdHolidaySiteId(追加)
日付StartTime / CompletionTimeDateA
名称TitleTitle
有効・無効Status < CompletionCodeStatus < CompletionCode
表示先画面上部カレンダーの日付

パラメータ ​

Implem.ParameterAccessor/Parts/Service.cs に public long HolidaySiteId { get; set; } を足し、App_Data/Parameters/Service.json に "HolidaySiteId": 0 を足します。0 なら機能は動きません。

祝日マスタ ​

項目用途例
Title祝日の名前元日
DateA日付2026/01/01
Status有効・無効100

Status が CompletionCode(既定 900)未満のものを有効とし、レコードを消さずに 900 以上にして無効にできるようにします。複数年分を登録でき、表示中の期間で DateA を絞ります。

csharp
public static ResultCollection GetHolidays(Context context, DateTime begin, DateTime end)
{
    var siteId = Parameters.Service.HolidaySiteId;
    if (siteId <= 0) return null;
    var ss = SiteSettingsUtilities.Get(context: context, siteId: siteId);
    return new ResultCollection(
        context: context,
        ss: ss,
        where: Rds.ResultsWhere()
            .SiteId(siteId)
            .Status(_operator: $"<{Parameters.General.CompletionCode}")
            .DateA(begin, _operator: ">=")
            .DateA(end, _operator: "<="));
}

図を読み込み中…

標準カレンダー ​

月表示(MonthlyTable)と週表示の日付セルで、祝日の日に holiday クラスと名前の span を足します。

csharp
var holidays = GetHolidays(context, begin, end)?
    .ToDictionary(
        r => r.DateA.ToLocal(context: context).Date,
        r => r.Title.Value);
var isHoliday = holidays?.ContainsKey(currentDate) == true;
// .Class("container" + … + (isHoliday ? " holiday" : string.Empty))
// 日付の div のあとに
// .Span(css: "holiday-name", action: () => hb.Text(holidays[currentDate]), _using: isHoliday)

同じ日付の祝日が複数あると ToDictionary が失敗するので、実装では日付でまとめるか重複を除きます。

スタイルは legacy.scss と style.scss(Implem.PleasanterFrontend/wwwroot/src/styles/)に足します。

scss
.CalendarBody .holiday {
    background-color: var(--commonColor02Sub);
}
.CalendarBody .holiday .holiday-name {
    display: block;
    font-size: 0.75em;
    color: var(--commonColor02);
}

FullCalendar ​

FullCalendar は display: 'background' の背景イベントを持てます。祝日を別のイベントソースとして渡し、レコードのイベントとは別の層に出します。

csharp
// HtmlCalendar.cs の CalendarBody の隠し項目に追加
hb.Hidden(
    controlId: $"HolidayJson{suffix}",
    value: GetHolidays(context, begin, end)?
        .Select(r => new
        {
            Title = r.Title.Value,
            DateA = r.DateA.ToLocal(context: context).ToString("yyyy-MM-dd")
        })
        .ToJson());
ts
const getHolidayEvents = (calendarSuffix: string) => {
    const json = String($(`#HolidayJson${calendarSuffix}`).val() ?? '');
    if (!json) return [];
    return JSON.parse(json).map((holiday: { Title: string; DateA: string }) => ({
        title: holiday.Title,
        start: holiday.DateA,
        display: 'background',
        classNames: ['holiday-event']
    }));
};

// 初期化の events を eventSources にする
// eventSources: [
//     { events: getEventsData(calendarSuffix) },
//     { events: getHolidayEvents(calendarSuffix) }
// ]

改修箇所 ​

ファイル内容
Implem.ParameterAccessor/Parts/Service.csHolidaySiteId
App_Data/Parameters/Service.jsonHolidaySiteId
Libraries/HtmlParts/HtmlCalendar.cs祝日の取得、日付セルのクラスと名前、HolidayJson の隠し項目
wwwroot/src/scripts/generals/calendar.ts背景イベントの追加
wwwroot/src/styles/legacy.scss・style.scss.holiday

カレンダーの一部の処理は CodeDefiner のテンプレート App_Data/Definitions/Definition_Code/Model_Utilities_Calendar_Body.txt から生成されます。各モデルの *Utilities.cs 側に手を入れる場合はテンプレートも直してください(CodeDefiner)。パラメータの追加だけなら生成コードには影響しません。

考慮事項 ​

  • 件数と負荷: 祝日は年に 20 件程度なので、表示のたびに引いても負荷は小さいです。月を切り替えるたびにクエリが走るのを避けたい場合はメモリキャッシュを検討しますが、マスタを更新したときの無効化が必要になります。
  • 権限: アナウンスと同じく ResultCollection で引くと権限の条件は入らないので、マスタのサイトの権限に関係なく全員のカレンダーに祝日が出ます。祝日は全員に見せる情報なのでこれで困りませんが、マスタの編集はサイトの権限で管理者に絞ります。権限で出し分けたい場合は、Permissions.SetPermissionsWhere() などで権限の条件を足す必要があります。
  • 標準と FullCalendar の両方: 作りが違う(サーバーの HTML と、ブラウザのイベント)ので、別々に実装します。

関連ページ ​

変更履歴

第1版リンク項目の列指定と JOIN の組み立て、一覧のスクロール読み込みの解説と、一覧・カレンダー・サイトメニューまわりの改修・設計メモを追加