Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #52 from department-of-veterans-affairs/tjh-apps-s…
Browse files Browse the repository at this point in the history
…caffolding

Scaffolding: Apps
  • Loading branch information
thilton-oddball authored Feb 4, 2022
2 parents 1028d8a + d26642b commit 815171d
Show file tree
Hide file tree
Showing 23 changed files with 477 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ GEM
racc (~> 1.4)
nokogiri (1.13.1-arm64-darwin)
racc (~> 1.4)
nokogiri (1.13.1-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.13.1-x86_64-linux)
racc (~> 1.4)
pagy (5.10.1)
Expand Down Expand Up @@ -259,6 +261,8 @@ GEM
railties (>= 6.0.0)
tailwindcss-rails (2.0.5-arm64-darwin)
railties (>= 6.0.0)
tailwindcss-rails (2.0.5-x86_64-darwin)
railties (>= 6.0.0)
tailwindcss-rails (2.0.5-x86_64-linux)
railties (>= 6.0.0)
thor (1.2.1)
Expand All @@ -283,6 +287,7 @@ GEM
PLATFORMS
arm64-darwin-21
ruby
x86_64-darwin
x86_64-linux

DEPENDENCIES
Expand Down
79 changes: 79 additions & 0 deletions app/controllers/apps_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# frozen_string_literal: true

# Handles creating apps which are owned by a team
class AppsController < ApplicationController
before_action :authorize_session!
before_action :set_team
before_action :set_app, only: %i[show edit update destroy]

# GET /apps or /apps.json
def index
@apps = @team.apps
end

# GET /apps/1 or /apps/1.json
def show; end

# GET /apps/new
def new
@app = @team.apps.build
end

# GET /apps/1/edit
def edit; end

# POST /apps or /apps.json
def create
@app = @team.apps.build(app_params)

respond_to do |format|
if @app.save
format.html { redirect_to team_app_url(@team, @app), notice: 'App was successfully created.' }
format.json { render :show, status: :created, location: @app }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @app.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /apps/1 or /apps/1.json
def update
respond_to do |format|
if @app.update(app_params)
format.html { redirect_to team_app_url(@team, @app), notice: 'App was successfully updated.' }
format.json { render :show, status: :ok, location: @app }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @app.errors, status: :unprocessable_entity }
end
end
end

# DELETE /apps/1 or /apps/1.json
def destroy
@app.destroy

respond_to do |format|
format.html { redirect_to team_url(@team), notice: 'App was successfully destroyed.' }
format.json { head :no_content }
end
end

private

# Use callbacks to share common setup or constraints between actions.
def set_team
@team = Team.find(params[:team_id])
end

# Use callbacks to share common setup or constraints between actions.
def set_app
@app = @team.apps.find(params[:id])
end

# Only allow a list of trusted parameters through.
def app_params
params.require(:app).permit(:name, :team_id)
end
end
1 change: 1 addition & 0 deletions app/controllers/teams_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def destroy
# Use callbacks to share common setup or constraints between actions.
def set_team
@team = Team.find(params[:id])
@apps = @team.apps
end

# Only allow a list of trusted parameters through.
Expand Down
6 changes: 6 additions & 0 deletions app/models/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class App < ApplicationRecord
belongs_to :team
validates :name, presence: true
end
1 change: 1 addition & 0 deletions app/models/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
class Team < ApplicationRecord
belongs_to :owner, polymorphic: true
validates :name, presence: true
has_many :apps, dependent: :nullify
end
7 changes: 7 additions & 0 deletions app/views/apps/_app.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="bg-white shadow overflow-hidden sm:rounded-lg" id="<%= dom_id app %>">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
App: <%= app.name %>
</h3>
</div>
</div>
4 changes: 4 additions & 0 deletions app/views/apps/_app.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

json.extract! app, :id, :name, :team_id, :created_at, :updated_at
json.url team_app_url(@team, app, format: :json)
49 changes: 49 additions & 0 deletions app/views/apps/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<%= form_with(model: [@team, app], class: 'space-y-8') do |form| %>
<% if app.errors.any? %>
<div class="rounded-md bg-red-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<!-- Heroicon name: solid/x-circle -->
<svg class="h-5 w-5 text-red-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800">
<%= pluralize(app.errors.count, "error") %> prohibited this app from being saved:
</h3>
<div class="mt-2 text-sm text-red-700">
<ul role="list" class="list-disc pl-5 space-y-1">
<% app.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
<% end %>

<div class="space-y-8 sm:space-y-5">
<div class="pt-8 divide-y divide-gray-200 space-y-6 sm:pt-10 sm:space-y-5">
<div class="space-y-6 sm:space-y-5">
<div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
<%= form.label :name, class: 'block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2', autofocus: true %>
<div class="mt-1 sm:mt-0 sm:col-span-2">
<%= form.text_field :name, class: 'max-w-lg block w-full shadow-sm focus:ring-blue-900 focus:border-blue-900 sm:max-w-xs sm:text-sm border-gray-300 rounded-md' %>
</div>
</div>
</div>
<div class="pt-5">
<div class="flex justify-end">
<% if app.persisted? %>
<%= link_to 'Cancel', team_app_path(@team,app), class: 'bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' %>
<% else %>
<%= link_to 'Cancel', team_apps_path(@team), class: 'bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' %>
<% end %>
<%= form.submit class: 'ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md cursor-pointer text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' %>
</div>
</div>
<% end %>
</div>
</div>
74 changes: 74 additions & 0 deletions app/views/apps/_team_apps.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<div class="flex justify-between">
<h3 class="text-lg leading-7 text-gray-900 sm:text-lg sm:truncate mt-4">
Team Apps
</h3>
<%= link_to new_team_app_path(@team), class: 'place-self-center inline-flex items-center mt-4 px-2 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' do %>
<span class="sr-only">New app</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
<% end %>
</div>

<br>

<% if @apps.present? %>
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<table class="table-fixed min-w-full divide-y divide-gray-200" id="apps">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase w-full">
Name
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody>
<% @apps.each do |app| %>
<tr class="<%= cycle 'bg-white', 'bg-gray-50' %>">
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
<%= link_to app.name, [@team, app], class: 'text-blue-900 hover:text-blue-800' %>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<div class="flex space-x-2">
<%= link_to 'Edit', edit_team_app_path(@team, app), class: 'inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' %>
<%= button_to 'Destroy', [@team, app], method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } }, class: 'inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-white bg-red-900 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-900 sm:text-sm' %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>

<% if @pagy %>
<div class="md:flex justify-between text-center mt-6 md:mt-0">
<%== pagy_info @pagy %>
<%== pagy_nav @pagy %>
</div>
<% end %>
<% else %>
<div class="text-center border-dashed border-gray-300 hover:border-gray-400 border-2 rounded-lg p-6 max-w-lg m-auto">
<svg width="96" height="96" fill="none" class="mx-auto mb-6 text-gray-900"><path d="M36 28.024A18.05 18.05 0 0025.022 39M59.999 28.024A18.05 18.05 0 0170.975 39" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><ellipse cx="37.5" cy="43.5" rx="4.5" ry="7.5" fill="currentColor"></ellipse><ellipse cx="58.5" cy="43.5" rx="4.5" ry="7.5" fill="currentColor"></ellipse><path d="M24.673 75.42a9.003 9.003 0 008.879 5.563m-8.88-5.562A8.973 8.973 0 0124 72c0-7.97 9-18 9-18s9 10.03 9 18a9 9 0 01-8.448 8.983m-8.88-5.562C16.919 68.817 12 58.983 12 48c0-19.882 16.118-36 36-36s36 16.118 36 36-16.118 36-36 36a35.877 35.877 0 01-14.448-3.017" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M41.997 71.75A14.94 14.94 0 0148 70.5c2.399 0 4.658.56 6.661 1.556a3 3 0 003.999-4.066 12 12 0 00-10.662-6.49 11.955 11.955 0 00-7.974 3.032c1.11 2.37 1.917 4.876 1.972 7.217z" fill="currentColor"></path></svg>
<h3 class="mt-2 text-sm font-medium text-gray-900">No apps</h3>
<p class="mt-1 text-sm text-gray-500">
Get started by creating a new app.
</p>
<div class="mt-6">
<%= link_to new_team_app_path(@team), class: 'inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' do %>
<svg class="-ml-1 mr-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
New App
<% end %>
</div>
</div>
<% end %>
5 changes: 5 additions & 0 deletions app/views/apps/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<h1 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate mt-4">
Editing app
</h1>

<%= render "form", app: @app %>
74 changes: 74 additions & 0 deletions app/views/apps/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<div class="flex justify-between">
<h1 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate mt-4">
Apps
</h1>
<%= link_to new_team_app_path(@team), class: 'place-self-center inline-flex items-center mt-4 px-2 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' do %>
<span class="sr-only">New app</span>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
<% end %>
</div>

<br>

<% if @apps.present? %>
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<table class="table-fixed min-w-full divide-y divide-gray-200" id="apps">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase w-full">
Name
</th>
<th scope="col" class="relative px-6 py-3">
<span class="sr-only">Edit</span>
</th>
</tr>
</thead>
<tbody>
<% @apps.each do |app| %>
<tr class="<%= cycle 'bg-white', 'bg-gray-50' %>">
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
<%= link_to app.name, [@team, app], class: 'text-blue-900 hover:text-blue-800' %>
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<div class="flex space-x-2">
<%= link_to 'Edit', edit_team_app_path(@team, app), class: 'inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500' %>
<%= button_to 'Destroy', [@team, app], method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } }, class: 'inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-white bg-red-900 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-900 sm:text-sm' %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>

<% if @pagy %>
<div class="md:flex justify-between text-center mt-6 md:mt-0">
<%== pagy_info @pagy %>
<%== pagy_nav @pagy %>
</div>
<% end %>
<% else %>
<div class="text-center border-dashed border-gray-300 hover:border-gray-400 border-2 rounded-lg p-6 max-w-lg m-auto">
<svg width="96" height="96" fill="none" class="mx-auto mb-6 text-gray-900"><path d="M36 28.024A18.05 18.05 0 0025.022 39M59.999 28.024A18.05 18.05 0 0170.975 39" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><ellipse cx="37.5" cy="43.5" rx="4.5" ry="7.5" fill="currentColor"></ellipse><ellipse cx="58.5" cy="43.5" rx="4.5" ry="7.5" fill="currentColor"></ellipse><path d="M24.673 75.42a9.003 9.003 0 008.879 5.563m-8.88-5.562A8.973 8.973 0 0124 72c0-7.97 9-18 9-18s9 10.03 9 18a9 9 0 01-8.448 8.983m-8.88-5.562C16.919 68.817 12 58.983 12 48c0-19.882 16.118-36 36-36s36 16.118 36 36-16.118 36-36 36a35.877 35.877 0 01-14.448-3.017" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path><path d="M41.997 71.75A14.94 14.94 0 0148 70.5c2.399 0 4.658.56 6.661 1.556a3 3 0 003.999-4.066 12 12 0 00-10.662-6.49 11.955 11.955 0 00-7.974 3.032c1.11 2.37 1.917 4.876 1.972 7.217z" fill="currentColor"></path></svg>
<h3 class="mt-2 text-sm font-medium text-gray-900">No teams</h3>
<p class="mt-1 text-sm text-gray-500">
Get started by creating a new team.
</p>
<div class="mt-6">
<%= link_to new_team_app_path(@team), class: 'inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' do %>
<svg class="-ml-1 mr-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
New Team
<% end %>
</div>
</div>
<% end %>
3 changes: 3 additions & 0 deletions app/views/apps/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

json.array! @apps, partial: 'apps/app', as: :app
5 changes: 5 additions & 0 deletions app/views/apps/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<h1 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate mt-4">
New app
</h1>

<%= render "form", app: @app %>
13 changes: 13 additions & 0 deletions app/views/apps/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="mt-4">
<%= render @app %>
</div>

<br>

<div class="flex space-x-4">
<%= link_to 'Back to team', team_path(@team), class: 'bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' %>

<%= link_to 'Edit this app', edit_team_app_path(@team, @app), class: 'inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-900 hover:bg-blue-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-900' %>

<%= button_to 'Destroy this app', [@team, @app], method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } }, class: 'inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-white bg-red-900 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-800 sm:text-sm' %>
</div>
3 changes: 3 additions & 0 deletions app/views/apps/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

json.partial! 'apps/app', { team: @team, app: @app }
6 changes: 6 additions & 0 deletions app/views/teams/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@

<%= button_to 'Destroy this team', @team, method: :delete, form: { data: { turbo_confirm: 'Are you sure?' } }, class: 'inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-white bg-red-900 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-800 sm:text-sm' %>
</div>

<br>

<div class="mt-4">
<%= render 'apps/team_apps' %>
</div>
3 changes: 3 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ class Application < Rails::Application
#
# config.time_zone = "Central Time (US & Canada)"
# config.eager_load_paths << Rails.root.join("extras")
# config.generators do |g|
# g.test_framework :minitest
# end
end
end
Loading

0 comments on commit 815171d

Please sign in to comment.