Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCS-0145: Zone model, controller, and views #21

Merged
merged 4 commits into from May 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 64 additions & 0 deletions app/controllers/zones_controller.rb
@@ -0,0 +1,64 @@
class ZonesController < ApplicationController
load_and_authorize_resource

def index
sort = params[:sort] || :id
direction = params[:direction] || :asc

@zones = Zone.accessible_by(current_ability)
.search(params.slice(:name_contains, :by_owner_id))
.order(sort => direction)
.page(params[:page])
end

def show
@zone = Zone.find(params[:id])
end

def new
@zone = Zone.new
end

def create
@zone = Zone.new(zone_params)

if @zone.save
redirect_to @zone
else
render 'new'
end
end

def edit
@zone = Zone.find(params[:id])
end

def update
@zone = Zone.find(params[:id])

if @zone.update(zone_params)
redirect_to @zone
else
render 'edit'
end
end

def destroy
@zone = Zone.find(params[:id])
@zone.destroy

redirect_to zones_path
end

private

def zone_params
params.require(:zone).permit(:name,
:filename,
:author,
:owner_id,
:min_vnum,
:max_vnum)
end

end
3 changes: 3 additions & 0 deletions app/models/ability.rb
Expand Up @@ -13,15 +13,18 @@ def initialize(user)
can [:read, :update, :create], Social
can :read, User
can :update, User, id: user.id
can :read, Zone

when 'builder'
can :read, Social
can :read, User
can :update, User, id: user.id
can :read, Zone

when 'guest'
can :read, Social, id: 1..10
cannot :manage, User
can :read, Zone
end
end
end
5 changes: 5 additions & 0 deletions app/models/user.rb
Expand Up @@ -16,6 +16,7 @@ class User < ApplicationRecord

scope :name_contains, ->(name) { where('first_name ILIKE ?', "%#{name}%") }
scope :by_role_id, ->(role_id) { where(role_id: role_id) }
scope :internal, -> { joins(:role).where.not('roles.name': 'guest') }

PRONOUN_CLASSES = %i[female male neutral]

Expand Down Expand Up @@ -44,6 +45,10 @@ def gsa?
role.name == 'gsa'
end

def to_s
name_display
end

def name_display
last_name.blank? ? first_name : "#{first_name} #{last_name}"
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/zone.rb
@@ -0,0 +1,14 @@
class Zone < ApplicationRecord
include Searchable

belongs_to :owner, class_name: "User"

validates_presence_of :name, :filename, :author, :owner_id, :min_vnum, :max_vnum

scope :name_contains, ->(name) { where('name ILIKE ?', "%#{name}%") }
scope :by_owner_id, ->(owner_id) { where(owner_id: owner_id) }

def owner_id_display
owner.name_display
end
end
4 changes: 2 additions & 2 deletions app/views/layouts/application.html.erb
Expand Up @@ -30,9 +30,9 @@
<nav id="top-nav" class="row">
<%= link_to 'Socials', socials_path, class: 'navbar-link pr-1' %>|
<% if can? :read, User %>
<%= link_to 'Users', users_path, class: 'navbar-link pl-1' if can? :read, User %>|
<%= link_to 'Users', users_path, class: 'navbar-link px-1' if can? :read, User %>|
<% end %>
Zones
<%= link_to 'Zones', zones_path, class: 'navbar-link pl-1' if can? :read, Zone %>
</nav>
<% end %>

Expand Down
26 changes: 26 additions & 0 deletions app/views/zones/_form.html.erb
@@ -0,0 +1,26 @@
<%= simple_form_for @zone, wrapper: :horizontal_form do |f| %>
<div class="row">
<div class="col-md-12">
<%= render partial: 'alerts/validation_errors', locals: { f: f } %>
</div>

<div class="col-md-12">
<fieldset>
<legend><%= I18n.t('zone.fieldset.metadata') %></legend>
<%= f.input :name, as: :string %>
<%= f.input :filename, as: :string %>
<%= f.input :author, as: :string %>
<%= f.input :owner_id,
as: :select,
collection: User.internal,
prompt: I18n.t('activerecord.attributes.zone.owner_id_prompt') %>
<%= f.input :min_vnum, as: :integer %>
<%= f.input :max_vnum, as: :integer %>
</fieldset>

<%= f.button :submit unless action_name == 'show' %>
</div>
</div>
<% end %>


26 changes: 26 additions & 0 deletions app/views/zones/_index_table.html.erb
@@ -0,0 +1,26 @@
<div id="index-table">

<table class=" table table-striped">
<tr>
<%= sortable 'name' %>
<%= sortable 'owner_id' %>
<%= sortable 'min_vnum' %>
<th colspan="3" class="actions"></th>
</tr>

<% @zones.each do |zone| %>
<tr>
<td><%= zone.name %></td>
<td><%= zone.owner_id_display %></td>
<td><%= zone.min_vnum %>&ndash;<%= zone.max_vnum %></td>
<td><%= link_to 'View', zone_path(zone) %></td>
<td><%= link_to 'Edit', edit_zone_path(zone) if can?(:edit, zone) %></td>
<td><%= link_to 'Delete', zone_path(zone), method: :delete, data: { confirm: 'Are you sure?' } if can?(:destroy, zone) %></td>
</tr>
<% end %>
</table>

<%= paginate @zones, theme: 'twitter-bootstrap-4',
pagination_class: 'pagination-md',
nav_class: 'd-inline-b' %>
</div>
24 changes: 24 additions & 0 deletions app/views/zones/_search.html.erb
@@ -0,0 +1,24 @@
<%= form_tag zones_path, method: 'get', class: 'search-form' do %>
<fieldset>
<legend>
<span><%= I18n.t('search.title') %></span>
</legend>
<div class="search-field-top">
<label><%= I18n.t('search.name_contains') %></label>
<%= text_field_tag :name_contains,
params['name_contains'],
class: 'search-text' %>
</div>
<div class="search-field">
<label><%= I18n.t('search.by_owner_id') %></label>
<%= select_tag :by_owner_id,
options_for_select(User.internal.collect { |u| [u.to_s, u.id] }, params[:by_owner_id]),
prompt: I18n.t('select.owner'),
class: 'search-select' %>
</div>
<div class="search-buttons">
<%= submit_tag I18n.t('button.search.submit'), name: nil, class: 'btn btn-default' %>
<%= link_to I18n.t('button.search.clear'), zones_path, class: 'btn btn-clear' %>
</div>
</fieldset>
<% end %>
3 changes: 3 additions & 0 deletions app/views/zones/edit.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.edit', record: @zone.name) %>

<%= render 'form' %>
11 changes: 11 additions & 0 deletions app/views/zones/index.html.erb
@@ -0,0 +1,11 @@
<% content_for :title, I18n.t('page.action_title.index', model: 'Zones') %>

<div class="row">
<div class="col-lg-9">
<%= render 'index_table' %>
</div>

<div class="col-lg-3">
<%= render 'search' %>
</div>
</div>
3 changes: 3 additions & 0 deletions app/views/zones/new.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.new', model: 'Zone') %>

<%= render 'form' %>
3 changes: 3 additions & 0 deletions app/views/zones/show.html.erb
@@ -0,0 +1,3 @@
<% content_for :title, I18n.t('page.action_title.show', record: @zone.name) %>

<%= render 'form' %>
40 changes: 40 additions & 0 deletions config/initializers/new_framework_defaults_5_2.rb
@@ -0,0 +1,40 @@
# Be sure to restart your server when you modify this file.
#
# This file contains migration options to ease your Rails 5.2 upgrade.
#
# Once upgraded flip defaults one by one to migrate to the new default.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.

# Make Active Record use stable #cache_key alongside new #cache_version method.
# This is needed for recyclable cache keys.
# Rails.application.config.active_record.cache_versioning = true

# Use AES-256-GCM authenticated encryption for encrypted cookies.
# Also, embed cookie expiry in signed or encrypted cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 5.2.
#
# Existing cookies will be converted on read then written with the new scheme.
# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true

# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
# Rails.application.config.active_support.use_authenticated_message_encryption = true

# Add default protection from forgery to ActionController::Base instead of in
# ApplicationController.
# Rails.application.config.action_controller.default_protect_from_forgery = true

# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
# 'f' after migrating old data.
# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true

# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
# Rails.application.config.active_support.use_sha1_digests = true

# Make `form_with` generate id attributes for any generated HTML tags.
# Rails.application.config.action_view.form_with_generates_ids = true

Rails.application.config.active_record.belongs_to_required_by_default = false
1 change: 1 addition & 0 deletions config/locales/layout.yml
Expand Up @@ -24,4 +24,5 @@ en:
show: "View %{record}"
show_command: "View command: %{record}"
select:
owner: "-- Select Owner --"
role: "-- Select Role --"
21 changes: 21 additions & 0 deletions config/locales/models/zone/en.yml
@@ -0,0 +1,21 @@
en:
activerecord:
attributes:
zone:
author: "Author"
filename: "Area Filename"
max_vnum: "Maximum VNUM"
min_vnum: "Minimum VNUM"
name: "Name"
owner: "Owner"
owner_id: "Owner"
owner_id_prompt: "-- Select Builder --"
errors:
models:
zone:
attributes:
owner_id:
required: "must be an internal user"
zone:
fieldset:
metadata: "Zone Metadata"
1 change: 1 addition & 0 deletions config/locales/search.yml
@@ -1,5 +1,6 @@
en:
search:
by_owner_id: "Owner"
by_role_id: "User Role"
name_contains: "Name Contains"
title: "Search Options"
4 changes: 4 additions & 0 deletions config/locales/sortable.yml
Expand Up @@ -8,3 +8,7 @@ en:
first_name: "Name"
role_id: "Role"
updated_at: "Last Update"
zones:
min_vnum: "VNUM Range"
name: "Name"
owner_id: "Owner"
2 changes: 2 additions & 0 deletions config/routes.rb
Expand Up @@ -12,4 +12,6 @@
end

resources :users, path: 'profiles'

resources :zones
end
14 changes: 14 additions & 0 deletions db/migrate/20190510122217_create_zones.rb
@@ -0,0 +1,14 @@
class CreateZones < ActiveRecord::Migration[5.2]
def change
create_table :zones do |t|
t.string :name, null: false
t.string :filename, null: false
t.string :author, null: false
t.references :owner, index: true, foreign_key: { to_table: :users }
t.integer :min_vnum, null: false
t.integer :max_vnum, null: false

t.timestamps
end
end
end
15 changes: 14 additions & 1 deletion db/schema.rb
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2019_03_26_235517) do
ActiveRecord::Schema.define(version: 2019_05_10_122217) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -54,4 +54,17 @@
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

create_table "zones", force: :cascade do |t|
t.string "name", null: false
t.string "filename", null: false
t.string "author", null: false
t.bigint "owner_id"
t.integer "min_vnum", null: false
t.integer "max_vnum", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["owner_id"], name: "index_zones_on_owner_id"
end

add_foreign_key "zones", "users", column: "owner_id"
end