Table: RailsNotes
User: dreamable
Created at: 2021-02-17 00:16:44 UTC
Updated at: 2021-02-17 00:18:45 UTC
Reference:(Table ID 3, Record ID 24)

标题 :
State Machine Transition by JS
笔记 :

I want to show friend status and action in the home page. The friendship status includes:

  1. stranger
  2. friend
  3. pending (request sent)
  4. waiting (request received)
  5. rejected (request rejected)
  6. declined (declined request)

The action includes

  1. stranger: -> request friendship
  2. friend: -> unfriend
  3. pending: -> withdraw
  4. waiting: -> accept; -> reject
  5. rejected
  6. declined: -> accept

I list all states and actions in the home page, and show the state only according to current friendship status

<% h = [:waiting, :declined].include?(status.to_sym) ? {inviter_id: user.id} : {invitee_id: user.id} %>
<% btn_params =  {params: h, remote: true, class: "#{lh_btn_cls} btn-outline-primary btn-sm"} %>
<div class='fsm'  id='fsm-stranger' style='<%=status.to_sym==:stranger ? fmt_show_style : fmt_hide_style%>' >
  <div class="d-inline-block">
    <%= fa_friends_icon %> <%= t('models.friendship.statuses.stranger') %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.request'), activity_request_friendship_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-stranger", "next-state": "fsm-pending"}}) %>
  </div>
</div>
<div class='fsm'  id='fsm-pending' style='<%=status.to_sym==:pending ? fmt_show_style : fmt_hide_style%>' >
  <div class="d-inline-block">
    <%= fa_friends_icon %> <%= t('models.friendship.statuses.pending') %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.withdraw'), activity_withdraw_friendship_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-pending", "next-state": "fsm-stranger"}}) %>
  </div>
</div>
<div class='fsm'  id='fsm-friend' style='<%=status.to_sym==:friend ? fmt_show_style : fmt_hide_style%>' >
  <div class="d-inline-block">
    <%= fa_friends_icon %> <%= t('models.friendship.statuses.friend') %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.unfriend'), activity_unfriend_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-friend", "next-state": "fsm-stranger"}}) %>
  </div>
</div>
<div class='fsm'  id='fsm-rejected' style='<%=status.to_sym==:rejected ? fmt_show_style : fmt_hide_style%>' >
  <%= fa_friends_icon %> <%= t('models.friendship.statuses.rejected') %>
</div>

<div class='fsm'  id='fsm-waiting' style='<%=status.to_sym==:waiting ? fmt_show_style : fmt_hide_style%>' >
  <div class="d-inline-block">
    <%= fa_friends_icon %> <%= t('models.friendship.statuses.waiting') %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.accept'), activity_accept_friendship_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-waiting", "next-state": "fsm-friend"}}) %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.reject'), activity_reject_friendship_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-waiting", "next-state": "fsm-declined"}}) %>
  </div>
</div>
<div class='fsm'  id='fsm-declined' style='<%=status.to_sym==:declined ? fmt_show_style : fmt_hide_style%>' >
  <div class="d-inline-block">
    <%= fa_friends_icon %> <%= t('models.friendship.statuses.declined') %>
  </div>
  <div class="d-inline-block">
    <%= button_to t('models.friendship.operations.accept'), activity_accept_friendship_path(format: :json), btn_params.merge({form: {class: "fsm-switch", "curr-state": "fsm-declined", "next-state": "fsm-friend"}}) %>
  </div>
</div>

The Javascript code:

// button-to with fsm-switch. After success, show  ID specified by "next-state"
// finite-state-machine switch
$(document).on("turbolinks:load", function() {
  $('.fsm-switch').on('ajax:success', function (e) {
    console.log("FSM switch after AJAX success")
    let cid = $(this).attr('curr-state');
    let nid = $(this).attr('next-state');
    console.log(cid);
    console.log(nid);
    $("#"+cid).toggle()
    $("#"+nid).toggle()
  });
});
Tag: