noesya/osuny

View on GitHub
app/views/server/universities/_sso_mapping.html.erb

Summary

Maintainability
Test Coverage
<%
kind = object.class.name.underscore.gsub('/', '_')
if kind == 'university'
  mapping_keys = ['email', 'first_name', 'last_name', 'role', 'mobile_phone', 'language', 'picture_url']
else
  mapping_keys = ['email', 'first_name', 'last_name', 'mobile_phone', 'language', 'picture_url']
end
%>

<%# Include vue.js before call Vue.createApp %>
<%= javascript_include_tag 'vue' %>

<div id="app" v-cloak>
  <div class="spinner-border text-primary" role="status">
    <span class="sr-only"><%= t('loading') %></span>
  </div>

  <div class="app-form">
    <draggable :list="fields" handle=".dragHandle" >
      <div v-for="(field, index) in fields">
        <div class="card">
          <div class="card-header d-flex justify-content-between">
            <div>
              <i class="<%= Icon::SORT %> dragHandle"></i>
              &nbsp;
              <a data-bs-toggle="collapse" :href="'#sso_mapping_collapse_' + index ">
                {{index + 1}}. {{ field.sso_key }} -> {{ keys[field.internal_key]}}
              </a>
            </div>
            <a
              v-on:click="fields.splice(fields.indexOf(field), 1)"
              title="Remove field">
              <i class="<%= Icon::DELETE %>"></i>
            </a>
          </div>
          <div class="card-body collapse pt-0" :id="'sso_mapping_collapse_' + index ">
            <hr class="mt-0">
            <div class="form-group">
              <label for="" class="form-control-label"><%= t('university.sso_key') %> <abbr title="required">*</abbr></label>
              <input
                v-model="field.sso_key"
                type="text" class="form-control">
            </div>
            <div class="form-group">
              <label for="" class="form-control-label"><%= t('university.internal_key') %> <abbr title="required">*</abbr></label>
              <select v-model="field.internal_key" id="" class="form-select" required>
                <option v-for="(label, key) in keys" :value="key">{{ label }}</option>
              </select>
            </div>
            <% if kind == 'university' %>
              <div v-if="field.internal_key === 'role'">
                <hr class="mt-4">
                <% User.roles.keys.each do |role| %>
                  <div class="form-group">
                    <label for="" class="form-label"><%= t("activerecord.attributes.user.roles.#{role}") %></label>
                    <input v-model="field.roles.<%= role %>" type="text" class="form-control">
                  </div>
                <% end %>
              </div>
            <% end %>
          </div>
        </div>
      </div>
    </draggable>

    <a v-on:click="fields.push({sso_key: 'key', internal_key: 'email', roles: {}})" class="btn btn-primary btn-sm">
      <%= t('add_field') %>
    </a>
  </div>

  <textarea name="<%= kind %>[sso_mapping]" id="<%= kind %>_sso_mapping" rows="20" cols="200" class="d-none">
    {{ JSON.stringify(fields) }}
  </textarea>

</div>

<script nonce="<%= request.content_security_policy_nonce %>">
  var app = Vue.createApp({
    components: {
      draggable: VueDraggableNext.VueDraggableNext,
    },
    data() {
      return {
        fields: <%= object.sso_mapping.blank? ? '[]' : object.sso_mapping.to_json.html_safe %>,
        keys: <%= mapping_keys.map { |key| [key, User.human_attribute_name(key)] }.to_h.to_json.html_safe %>
      }
    }
  });

  window.addEventListener('load', function(){
    setTimeout(function() {
      app.mount('#app');
    }, 1000);
  });
</script>