カレンダーのデータを動的に読み込む

2017-12-18 20:15 to 2017-12-18 23:30

概要

fullCalendarに全ての期間のデータを全部渡し続けるわけにはいかないので、表示した月の分だけを渡す。

今は当月のデータしか渡してないので月移動毎にデータを渡すよう調整する。

目標

一通り作る。

経過

2017-12-18 21:14

すぐ出来た。fullCalendarにコールバックを指定できるのでそこで呼び出すだけだった。

    loadEvents(start, end, timezone, callback) {
      const startDate = start.format('YYYY-MM-DD');
      const endDate = end.format('YYYY-MM-DD');
      axios.get(`/${this.group_id}/schedules/events/${startDate}/${endDate}`)
        .then(response => {
          this.$emit('GET_AJAX_COMPLETE');
          callback(response.data);
        });
    },
  def list_schedules_for_range(group_id, start_date, end_date) do
    query = from s in Schedule,
      where: s.group_id == ^group_id
        and (
          (s.start_date < ^start_date and ^end_date < s.end_date)
          or (^start_date <= s.start_date and s.start_date <= ^end_date)
          or (^start_date <= s.end_date and s.end_date <= ^end_date)
        )
        and is_nil(s.deleted_at)
    Repo.all(query)
    |> Repo.preload(:schedule_category)
  end

重そうなクエリ…

2017-12-18 23:34

ついでにカテゴリの並び替えも作成した。

担当者編集の時に追加していた

https://github.com/SortableJS/Vue.Draggable

を入れたらすぐ出来た。

<template>
  <table class="table">
    <thead>
      <tr>
        <th></th>
        <th>予定メニュー名</th>

        <th></th>
      </tr>
    </thead>
    <draggable v-model="scheduleCategories" :element="'tbody'" :options="{handle: '.handle'}" @end="onEnd">
      <tr v-for="scheduleCategory in scheduleCategories" :key="scheduleCategory.id">
        <td class="handle"><i class="material-icons">drag_handle</i></td>
        <td>
          <span
            v-text="scheduleCategory.name"
            class="event-color-sample"
            v-bind:style="{backgroundColor: scheduleCategory.bg_color, color: scheduleCategory.text_color}"
          ></span>
        </td>

        <td class="text-right">
          <span><a :href="`/${group_id}/schedule-categories/${scheduleCategory.id}/edit`" class="btn btn-default btn-xs">編集</a></span>
          <span>
            <a
              href="#"
              data-confirm="削除してよろしいですか?"
              :data-csrf="csrf"
              data-method="delete"
              :data-to="`/${group_id}/schedule-categories/${scheduleCategory.id}`"
              rel="nofollow"
              class="btn btn-danger btn-xs"
            >削除<div class="ripple-container"></div></a>
          </span>
        </td>
      </tr>
    </draggable>
  </table>
</template>

<style scoped>
.handle {
  cursor: crosshair;
}
</style>

<script>
import draggable from 'vuedraggable'
import axios from 'axios'

export default {
  props: ['group_id', 'schedule_categories'],

  components: {draggable},

  data () {
    return {
      scheduleCategories: this.schedule_categories,
      csrf: document.querySelector('meta[name=csrf]').getAttribute('content'),
    }
  },

  methods: {
    onEnd() {
      axios.put(`/${this.group_id}/schedule-categories/update-order`, {
          ids: this.scheduleCategories.map(c => c.id),
        });
    }
  }
}
</script>

更新側。既存の処理を使いまわせるのでコードは非常に少なくなった。

  def update_schedule_categories_order(group_id, ids) do
    Enum.with_index(ids)
    |> Enum.each(fn{id, index} ->
      schedule_category = get_schedule_category!(id, group_id)
      update_schedule_category(schedule_category, %{"display_order" => index + 1})
    end)
  end

コメント