顯示具有 Calendar 標籤的文章。 顯示所有文章
顯示具有 Calendar 標籤的文章。 顯示所有文章

2016年10月25日 星期二

Cloud9-RoR-fullcalendar-rails & CRUD Part.1

*2016/11/1-更新calendar.coffee、calendar.controller,將_form.html.erb改回new.html.erb。

參考來源(jquery-ui):https://rubygems.org/gems/fullcalendar-rails/versions
參考來源(CRUD):http://vinsol.com/fullcalendar-demo

C:會套用前幾篇中提到的one-to-many頁面。
R:使用jquery-ui的套件,將事件的detail顯示在dialog裡。
U:本篇不做。
D:依附在read底下,點選某一日曆上的事件時才會載入delete按鈕,如該事件已有人回復/預訂,則不可刪除。

首先安裝 jquery-ui-rails
打開Gemfile檔,加入
# jquery-ui
gem 'jquery-ui-rails'

編輯application.js,加入
//= require jquery-ui

編輯application.css,加入
*= require jquery-ui

執行指令
$ bundle install


CRUP實做
編輯calendars_controller.rb
  before_action :set_calendar, :only => [ :destroy]
  def index
    @calendars = Calendar.
    select("calendars.id", "IF(calendars.user_id = '#{current_user.id}', 1, 0) AS isedit",
    "IF(rcalendars.fb_nickname IS NULL, 1, 0) AS reserved",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, ':00:00') AS dt", 
    "CONCAT(users.username, ' ', IFNULL(rcalendars.fb_nickname, '')) AS title",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, '點<br/>', IFNULL(rcalendars.content, '')) AS description").
    joins("LEFT JOIN users ON users.id = calendars.user_id LEFT JOIN rcalendars ON rcalendars.calendar_id = calendars.id")
    #if json file(index.json.jbuilder) like to link use json.url calendar_path(calendar)
  end

  def new
    @calendar = []
    15.times do
      @calendar << Calendar.new
    end
    render :layout => false
  end
  
  def create
    if params.has_key?("calendar")
      @calendar = Calendar.create(calendar_params(params["calendar"]))
    else
      params["calendars"].each do |calendar|
        if calendar["issave"] && calendar["vdate"] != ""
          @calendar = Calendar.create(calendar_params(calendar))
        end
      end
    end
    
    #json
    respond_to do |format|
      if @calendar.save
        format.html { redirect_to calendars_url, notice: 'calendar was successfully created.' }
        format.json { render action: 'index', status: :created, location: @calendar }
      else
        format.html { render action: 'new' }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end 
    #json
  end  

  def destroy
    @calendar.destroy
    redirect_to calendars_url
    flash[:alert] = "calendar was successfully deleted"
  end
  
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_calendar
      @calendar = Calendar.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def calendar_params(my_params)
      my_params.permit(:user_id, :vdate, :vtime)
    end  

編輯calendar.coffee
$(document).ready ->
  # page is now ready, initialize the calendar...
  $('#new_event').click (event) ->
    $.get '/calendars/new', (data) ->
      #初始將a.html include div#iframe
      $('#create_event').html data
      return
    $('#create_event_dialog').dialog
      title: '新增'
      modal: true
      width: 500
      close: (event, ui) ->
        $('#create_event_dialog').dialog 'destroy'
        return
    return
    
  $('#create_event_dialog, #desc_dialog').on 'submit', '#event_form', (event) ->
    $spinner = $('.spinner')
  
    show_spinner = ->
      $spinner.show()
      return
  
    hide_spinner = ->
      $spinner.hide()
      return
  
    handle_error = (xhr) ->
      alert xhr.responseText
      return
  
    event.preventDefault()
    $.ajax
      type: 'POST'
      data: $(this).serialize()
      url: $(this).attr('action')
      beforeSend: show_spinner
      complete: hide_spinner
      success: refetch_events_and_close_dialog
      error: handle_error
    return
    
  $('#calendar').fullCalendar
    header:
      left: 'prev,next today'
      center: 'title'
      right: 'month'
    defaultView: 'month'
    loading: (bool) ->
      if bool
        $('#loading').show()
      else
        $('#loading').hide()
      return
    events: '/calendars.json'
    timeFormat: 'Ahh點'
    eventClick: (event, jsEvent, view) ->
      showEventDetails event
      return  
  return

showEventDetails = (event) ->
  $('#event_desc').html event.description
  title = event.title
  if event.isedit and event.reserved
    $('#delete_event').html '<form class="button_to" method="post" action="/calendars/' + event.id + '"><input type="hidden" name="_method" value="delete" /><input type="hidden" name="authenticity_token" value="' + $('meta[name="csrf-token"]').attr('content') + '" /><input data-confirm="Are you sure?" type="submit" value="Delete" /></form>'
  else
    $('#delete_event').html ''
  $('#desc_dialog').dialog
    title: title
    modal: true
    width: 500
    close: (event, ui) ->
      $('#desc_dialog').dialog 'destroy'
      return
  return

refetch_events_and_close_dialog = ->
  $('#calendar').fullCalendar 'refetchEvents'
  $('.dialog:visible').dialog 'destroy'
  return

編輯calendars.scss
.fc-h-event {
    cursor: pointer;
}

編輯calendars/index.html.erb
<div><%=link_to '新增', new_calendar_path, :id => 'new_event' %></div>

<div id="calendar"></div>

<!--隱藏表單 //-->
<div id = "desc_dialog" class="dialog" style ="display:none;">
  <div id = "event_desc">
  </div>
  <br/>
  <br/>
  <div id = "event_actions">
    <span id = "edit_event"></span>
    <span id = "delete_event"></span>
  </div>
</div>
<div id = "create_event_dialog" class="dialog" style ="display:none;">
  <div id = "create_event">
  </div>
</div>

新增的畫面

點開日曆事件時的畫面
可編輯自己的部份:

不可編輯他人的資料:

後台總算告個段落,只剩下套版了。

Cloud9-RoR-fullcalendar-rails & json

範例下載:https://github.com/FerPerales/fullcalendar_and_rails_example

請下載範例檔,使用現成的檔案就行嘍!(CRUD不使用本範例的套件)

套用json至fullcalendar
Copy app\views\events 下的index.json.jbuilder至cloud9中,@events及event的部份請更改成自己的model名稱哦!
json.array!(@calendars) do |calendar|
  json.extract! calendar, :id, :title
  json.start calendar.dt
end

編輯calendar_controller.rb,萬一欄位跟範例的不一樣該怎麼辦呢?我就剛好遇到這個問題,請參考index select()裡的寫法,joins不需要的人就拿掉吧!
  def index
    @calendars = calendar.select("calendars.id, CONCAT(calendars.vdate , ' ', calendars.vtime, ':00:00') AS dt , users.username AS title").joins(:user)
  end

編輯app\assets\javascripts底下的calendar.coffee
$(document).ready ->
  $('#calendar').fullCalendar
    header:
      left: 'prev,next today'
      center: 'title'
      right: 'month'
    defaultView: 'month'
    slotMinutes: 15
    loading: (bool) ->
      if bool
        $('#loading').show()
      else
        $('#loading').hide()
      return
    events: '/calendars.json'
    timeFormat: 'Ahh點'
  return

完成後的內容會像下圖



下一篇會教怎麼加入CRD,U的部份我不需要,加上沒時間,就跳過不做了。

2016年10月10日 星期一

Cloud9-RoR-fullcalendar-rails 安裝

參考來源:https://rubygems.org/gems/fullcalendar-rails/versions
參考文章/下載來源:https://github.com/bokmann/fullcalendar-rails
官網:https://fullcalendar.io/
doc說明:https://fullcalendar.io/docs/
範例參考(1):http://vinsol.com/fullcalendar-demo
範例參考(1)下載來源:https://github.com/vinsol/fullcalendar_rails
範例參考(2):http://blog.crowdint.com/2014/02/18/fancy-calendars-for-your-web-application-with-fullcalendar.html
輔助套件(必裝):https://github.com/derekprior/momentjs-rails

p.s.範例參考都有提供GitHub下載,可以用clould9另開一個新專案載入後試玩看看。

fullcalendar-rails需要用到momentjs-rails,所以我們先安裝monentjs-rails套件。如果想先檢查有沒有相關套件,可以執行以下指令:
$ gem list
底下會列出主機上所有安裝的gem套件,已經安裝的人可以跳過安裝步驟哦。

momentjs-rails
執行安裝指令
$ gem install momentjs-rails
$ bundle install

在Gemfile檔加上兩行
# momentjs
gem 'momentjs-rails'

編輯application.js檔,加入
//= require moment 

編輯test/test_helper.rb檔,加入
  test "truth" do
    assert_kind_of Module, Momentjs::Rails
  end

然後上傳下列的檔案到指定的資料夾中
  • lib:momentjs-rails.rb
  • vendor\assets\javascripts:moment.js、moment folder

fullcalendar-rails
執行安裝指令
$ gem install fullcalendar-rails
$ bundle install

在Gemfile檔加上兩行
# full calendar
gem 'fullcalendar-rails'

編輯application.css檔,加入
 *= require fullcalendar

編輯application.js檔,加入
//= require fullcalendar

如果想要轉換語系,再加入
//= require fullcalendar/lang/zh-tw

接下來有兩種套用方式,model跟view。

model:在app\assets\javascripts\找到該mode的.coffee檔,加入
$(document).ready ->
  $("#calendar").fullCalendar(
    lang: 'zh-tw' #轉換語系
    editable: true
    header:
      left: 'prev,next today'
      center: 'title'
      right: 'month,agendaWeek,agendaDay,listWeek'
    defaultView: 'month'
    height: 500
    slotMinutes: 15
  )

打開該model下的view(.html.erb)檔,再加入
<div id="calendar"></div>
就會顯示月曆了。

view:想套用單一頁面則打開該view(.html.erb)檔後,加入
<scrip>
$(document).ready(function(){
  $('#calendar').fullCalendar({
    lang: 'zh-tw', //轉換語系
    editable: true,
    header: {
      left: 'prev,next today',
      center: 'title',
      right: 'month,agendaWeek,agendaDay,listWeek'
    },
    defaultView: 'month',
    height: 500,
    slotMinutes: 15
  });
});
</scrip>

<div id="calendar"></div>

從這段起跟列印有關,不需要用到列印功能的人可以跳過。
----------------------------------------------------------------------------------
在stylesheets資料夾下新增一個application-print.css.scss檔。

編輯config/application.rb檔,加上
config.assets.precompile += ['application-print.css']

在需要列印的view頁面加入
<%= stylesheet_link_tag "application-print", :media => "print" %>
----------------------------------------------------------------------------------

上傳下列檔案
  • lib:fullcalendar-rails.rb及fullcalendar-rails folder
  • vendor\assets\javascripts:fullcalendar folder、fullcalendar.js
  • vendor\assets\stylesheets:fullcalendar.css、fullcalendar.print.css
希望大家都能順利的完成嘍!