Skip to content

Commit

Permalink
Merge pull request #181 from codeforamerica/admin-interface
Browse files Browse the repository at this point in the history
Add Admin interface to API app
  • Loading branch information
monfresh committed Jul 15, 2014
2 parents 83e0c01 + dcda003 commit 641410a
Show file tree
Hide file tree
Showing 218 changed files with 5,411 additions and 492 deletions.
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@ Style/ClassLength:
CountComments: false
Max: 100

Style/GuardClause:
MinBodyLength: 3

Rails/HasAndBelongsToMany:
Enabled: false
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ end
group :test do
gem 'database_cleaner', '>= 1.0.0.RC1'
gem 'capybara'
gem 'poltergeist'
gem 'shoulda-matchers', require: false
gem 'coveralls', require: false
gem 'rubocop'
Expand Down
72 changes: 40 additions & 32 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (4.1.2)
actionpack (= 4.1.2)
actionview (= 4.1.2)
actionmailer (4.1.4)
actionpack (= 4.1.4)
actionview (= 4.1.4)
mail (~> 2.5.4)
actionpack (4.1.2)
actionview (= 4.1.2)
activesupport (= 4.1.2)
actionpack (4.1.4)
actionview (= 4.1.4)
activesupport (= 4.1.4)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.2)
activesupport (= 4.1.2)
actionview (4.1.4)
activesupport (= 4.1.4)
builder (~> 3.1)
erubis (~> 2.7.0)
active_model_serializers (0.8.1)
activemodel (>= 3.0)
activemodel (4.1.2)
activesupport (= 4.1.2)
activemodel (4.1.4)
activesupport (= 4.1.4)
builder (~> 3.1)
activerecord (4.1.2)
activemodel (= 4.1.2)
activesupport (= 4.1.2)
activerecord (4.1.4)
activemodel (= 4.1.4)
activesupport (= 4.1.4)
arel (~> 5.0.0)
activesupport (4.1.2)
activesupport (4.1.4)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
Expand All @@ -44,15 +44,16 @@ GEM
bootstrap-sass (2.3.2.2)
sass (~> 3.2)
builder (3.2.2)
bullet (4.11.2)
bullet (4.11.3)
activesupport (>= 3.0.0)
uniform_notifier (>= 1.6.0)
capybara (2.3.0)
capybara (2.4.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
cliver (0.3.2)
coderay (1.1.0)
coffee-rails (4.0.1)
coffee-script (>= 2.2.0)
Expand Down Expand Up @@ -125,7 +126,7 @@ GEM
nokogiri (1.6.2.1)
mini_portile (= 0.6.0)
orm_adapter (0.5.0)
parser (2.2.0.pre.2)
parser (2.2.0.pre.3)
ast (>= 1.1, < 3.0)
slop (~> 3.4, >= 3.4.5)
passenger (4.0.45)
Expand All @@ -137,6 +138,11 @@ GEM
activerecord (>= 3.1)
activesupport (>= 3.1)
arel
poltergeist (1.5.1)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.5)
powerpack (0.0.9)
protected_attributes (1.0.8)
Expand All @@ -148,24 +154,24 @@ GEM
rack-test (0.6.2)
rack (>= 1.0)
rack-timeout (0.0.4)
rails (4.1.2)
actionmailer (= 4.1.2)
actionpack (= 4.1.2)
actionview (= 4.1.2)
activemodel (= 4.1.2)
activerecord (= 4.1.2)
activesupport (= 4.1.2)
rails (4.1.4)
actionmailer (= 4.1.4)
actionpack (= 4.1.4)
actionview (= 4.1.4)
activemodel (= 4.1.4)
activerecord (= 4.1.4)
activesupport (= 4.1.4)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.2)
railties (= 4.1.4)
sprockets-rails (~> 2.0)
rails_12factor (0.0.2)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.1)
rails_stdout_logging (0.0.2)
railties (4.1.2)
actionpack (= 4.1.2)
activesupport (= 4.1.2)
railties (4.1.4)
actionpack (= 4.1.4)
activesupport (= 4.1.4)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.0.0)
Expand Down Expand Up @@ -193,9 +199,9 @@ GEM
rspec-mocks (~> 3.0.0)
rspec-support (~> 3.0.0)
rspec-support (3.0.0)
rubocop (0.24.0)
rubocop (0.24.1)
json (>= 1.7.7, < 2)
parser (>= 2.2.0.pre.2, < 3.0)
parser (>= 2.2.0.pre.3, < 3.0)
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
Expand All @@ -214,8 +220,8 @@ GEM
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
slop (3.5.0)
spring (1.1.2)
spring-commands-rspec (1.0.1)
spring (1.1.3)
spring-commands-rspec (1.0.2)
spring (>= 0.9.1)
sprockets (2.11.0)
hike (~> 1.2)
Expand Down Expand Up @@ -243,6 +249,7 @@ GEM
uniform_notifier (1.6.2)
warden (1.2.3)
rack (>= 1.0)
websocket-driver (0.3.3)
xpath (2.0.0)
nokogiri (~> 1.3)

Expand Down Expand Up @@ -275,6 +282,7 @@ DEPENDENCIES
passenger
pg
pg_search
poltergeist
protected_attributes
quiet_assets (>= 1.0.2)
rack-cors
Expand Down
16 changes: 11 additions & 5 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ local [Admin Interface][admin] if it's pointing to your local API.

### Verify the app is returning JSON

[http://localhost:8080/api/locations](http://localhost:8080/api/locations)
[http://lvh.me:8080/api/locations](http://lvh.me:8080/api/locations)

[http://localhost:8080/api/search?keyword=food](http://localhost:8080/api/search?keyword=food)
[http://lvh.me:8080/api/search?keyword=food](http://lvh.me:8080/api/search?keyword=food)

We recommend the [JSONView][jsonview] Google Chrome extension for formatting
the JSON response so it is easier to read in the browser.
Expand Down Expand Up @@ -151,11 +151,17 @@ To reset your local database and populate it again with your clean data:
script/import
```

### User authentication (for the developer portal)
### User and Admin authentication (for the developer portal and admin interface)

The app automatically sets up users you can [sign in][sign_in] with.
The app automatically sets up users and admins you can sign in with.
Their username and password are stored in [db/seeds.rb][seeds].

[sign_in]: http://localhost:8080/users/sign_in
[seeds]: https://github.com/codeforamerica/ohana-api/blob/master/db/seeds.rb

To set an admin as a Super Admin:

psql ohana_api_development
UPDATE "admins" SET super_admin = true WHERE id = 3;
\q

To access the admin interface, visit [http://lvh.me:8080/admin/](http://lvh.me:8080/admin/).
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,33 @@

[![Stories in Ready](https://badge.waffle.io/codeforamerica/ohana-api.png?label=ready)](https://waffle.io/codeforamerica/ohana-api) [![Build Status](https://travis-ci.org/codeforamerica/ohana-api.png?branch=master)](https://travis-ci.org/codeforamerica/ohana-api)

This is the API portion of the [Ohana API](http://ohanapi.org) project, an open source community resource platform developed by [@monfresh](https://github.com/monfresh), [@spara](https://github.com/spara), and [@anselmbradford](https://github.com/anselmbradford) during their Code for America Fellowship in 2013, in partnership with San Mateo County's Human Services Agency. The goal of the project is to make it easier for residents in need to find services they are eligible for.
This is the API + Admin Interface portion of the [Ohana API](http://ohanapi.org) project, an open source community resource platform developed by [@monfresh](https://github.com/monfresh), [@spara](https://github.com/spara), and [@anselmbradford](https://github.com/anselmbradford) during their Code for America Fellowship in 2013, in partnership with San Mateo County's Human Services Agency. Ohana makes it easy for communities to publish a database of social services, and allows developers to build impactful applications that serve underprivileged residents.

Before we started working on the Ohana API, the search interface that residents and social workers in San Mateo County had access to was the Peninsula Library System's [CIP portal](http://catalog.plsinfo.org:81/). As a demonstration of the kind of applications that can be built on top of the Ohana API, we developed a [better search interface](http://smc-connect.org) ([repo link](https://github.com/codeforamerica/human_services_finder)) that consumes the API via our [Ruby wrapper](https://github.com/codeforamerica/ohanakapa). We also built an [admin site](https://github.com/codeforamerica/ohana-api-admin) to allow organizations to update their own information.
Before we started working on the Ohana API, the search interface that residents and social workers in San Mateo County had access to was the Peninsula Library System's [CIP portal](http://catalog.plsinfo.org:81/). As a demonstration of the kind of applications that can be built on top of the Ohana API, we developed a [better search interface](http://smc-connect.org) ([repo link](https://github.com/codeforamerica/ohana-web-search)) that consumes the API via our [Ruby wrapper](https://github.com/codeforamerica/ohanakapa).

## Stack Overview

* Ruby version 2.1.1
* Rails version 4.1.1
* Rails version 4.1.4
* Postgres
* Testing Frameworks: RSpec, Factory Girl, Capybara

## Demo
You can see a running version of the application at
[http://ohana-api-demo.herokuapp.com/](http://ohana-api-demo.herokuapp.com/).
You can see a running version of the different parts of the application here:

**Developer portal**: [http://ohana-api-demo.herokuapp.com/](http://ohana-api-demo.herokuapp.com/) (see [db/seeds.rb][seeds] for a list of usernames and passwords you can sign in with.)

**API**: [http://ohana-api-demo.herokuapp.com/api](http://ohana-api-demo.herokuapp.com/api)

**Admin Interface**: [http://ohana-api-demo.herokuapp.com/admin](http://ohana-api-demo.herokuapp.com/admin) (see [db/seeds.rb][seeds] for a list of usernames and passwords you can sign in with.)

[seeds]: https://github.com/codeforamerica/ohana-api/blob/master/db/seeds.rb

## Current Status
We are happy to announce that this project has been awarded a [grant from the Knight Foundation](http://www.knightfoundation.org/grants/201447979/), which means we get to keep working on it in 2014! Our primary goals this year are: simplifying the installation process, streamlining the code, reducing dependencies, and preparing the project for broader installation by a variety of organizations and governments.

## Data Schema
If you would like to try out the current version of the project that uses Postgres, please read the Wiki article about [Populating the Postgres DB from a JSON file](https://github.com/codeforamerica/ohana-api/wiki/Populating-the-Postgres-database-from-a-JSON-file). That article documents the current schema and data dictionary, but please note that this will be in flux as we are working with various interested parties to define a [Human Services Data Specification](https://github.com/codeforamerica/OpenReferral).
If you would like to try out the current version of the project, please read the Wiki article about [Populating the Postgres DB from a JSON file](https://github.com/codeforamerica/ohana-api/wiki/Populating-the-Postgres-database-from-a-JSON-file). That article documents the current schema and data dictionary, but please note that this will be in flux as we are working with various interested parties to define a [Human Services Data Specification](https://github.com/codeforamerica/OpenReferral).

## API documentation
[http://ohanapi.herokuapp.com/api/docs](http://ohana-api-demo.herokuapp.com/api/docs)
Expand All @@ -41,12 +48,10 @@ If you've built one, let us know and we'll add it here.
By default, this project uses the [Open Eligibility](http://openeligibility.org) taxonomy to assign Services to [Categories](https://github.com/codeforamerica/ohana-api/blob/master/app/models/category.rb).
If you would like to use your own taxonomy, feel free to update this rake task to [create your own hierarchy or tree structure](https://github.com/codeforamerica/ohana-api/blob/master/lib/tasks/oe.rake). Then run `rake create_categories`.

The easiest way to assign categories to a service is to use the [Ohana API Admin](https://github.com/codeforamerica/ohana-api-admin/blob/master/app/controllers/hsa_controller.rb#L183-187) interface. Here's a screenshot:
The easiest way to assign categories to a service is to use the Admin interface. Here's a screenshot:

![Editing categories in Ohana API Admin](https://github.com/codeforamerica/ohana-api/raw/master/categories-in-ohana-api-admin.png)

You can also try it from the Rails console, mimicking how the API would do it when it receives a [PUT request to update a service's categories](https://github.com/codeforamerica/ohana-api/blob/master/app/api/ohana.rb#L239-257).

## Apps that are using the Ohana API
[SMC-Connect](http://www.smc-connect.org)
[GitHub repo for SMC-Connect](https://github.com/codeforamerica/human_services_finder)
Expand Down
78 changes: 78 additions & 0 deletions app/assets/javascripts/admin/categories_form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
var main = (function () {
"use strict";

var NUM_LEVELS = 2;

// initalize the application
function init()
{
var checkboxes = $('#categories input');

var currentCheckbox;
for (var i=0; i < checkboxes.length; i++)
{
currentCheckbox = checkboxes[i];
_checkState('depth',0,currentCheckbox);
}

var lnks = $('#categories input');

var curr;
for (var l=0; l < lnks.length; l++)
{
curr = lnks[l];
$(curr).click(_linkClickedHandler)
}
}

function _linkClickedHandler(evt)
{
var el = evt.target;
if (el.nodeName == 'INPUT')
{
_checkState('depth',0,el);
}

}

function _checkState(prefix,depth,checkbox)
{
var item = $(checkbox).parent(); // parent li item
var id = prefix+String(depth);
while(!item.hasClass(id))
{
depth++;
id = prefix+String(depth);
}

id = 'li.'+prefix+String(depth+1);
var lnks = $(id,item);
var curr;
for (var l=0; l < lnks.length; l++)
{
curr = lnks[l];
if (checkbox.checked)
{
$(curr).removeClass('hide');
}
else
{
$(curr).addClass('hide');
checkbox = $('input',$(curr))
checkbox.prop('checked', false);
_checkState(prefix,depth,checkbox)
}
}

}

// return internally scoped var as value of globally scoped object
return {
init:init
};

})();

$(document).ready(function(){
main.init();
});
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require bootstrap-modal
//= require_tree .
23 changes: 23 additions & 0 deletions app/assets/javascripts/form.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
jQuery ->
$('.edit_entry').on 'click', '.delete_association', (event) ->
$(this).prevAll('input[type=hidden]').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()

$('.edit_entry').on 'click', '.delete_attribute', (event) ->
$(this).closest('fieldset').find('input').val('')
$(this).closest('fieldset').hide()
event.preventDefault()

$('.edit_entry').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()

$('.edit_entry').on 'click', '.add_array_fields', (event) ->
time = new Date().getTime()
$(this).before($(this).data('fields'))
inputs = $(this).parent().find('input')
inputs[inputs.length - 1].setAttribute('id', time)
event.preventDefault()
Loading

0 comments on commit 641410a

Please sign in to comment.