7 Commits
v2.0 ... v2.2

Author SHA1 Message Date
e89b2e0a02 Added service descriptions.
Pages now use service descriptions to describe services, falling back on the
service type's displayable value if no description is given.
2015-04-14 15:13:21 -05:00
c7bee5009a Continued work on API documentation. 2015-04-10 19:14:30 -05:00
cad957394e Fleahed out documentation. 2015-04-09 21:47:48 -05:00
8eb7918f7f Added favicon in ICO format. 2015-03-30 21:07:17 -05:00
b7970f6af8 Increment minor version so new work is on v2.2 2015-03-30 02:17:49 -05:00
4580709d29 Version 2.1: Default to MP3s instead of OGGs for song files. 2015-03-30 02:15:06 -05:00
2bf0412629 Increment minor version so new work is on v2.1. 2015-03-23 04:16:09 -05:00
9 changed files with 252 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -7,6 +7,7 @@ public class Service implements Serializable {
int id
private LocalDate date
ServiceType serviceType
String description
public boolean equals(Object thatObj) {
if (thatObj == null) return false

View File

@ -13,5 +13,5 @@ public class NLSongsContext {
public static String makeUrl(Service service, Song song) {
return mediaBaseUrl + '/' + service.@date.toString('yyyy-MM-dd') + '_' +
service.serviceType.name().toLowerCase() + '_' +
song.name.replaceAll(/[\s'"\\\/\?!]/, '') + '.ogg' }
song.name.replaceAll(/[\s'"\\\/\?!]/, '') + '.mp3' }
}

View File

@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS services (
id SERIAL,
date DATE NOT NULL,
service_type VARCHAR(16) DEFAULT NULL,
description VARCHAR(255) DEFAULT NULL,
CONSTRAINT uc_serviceTypeAndDate UNIQUE (date, service_type),
PRIMARY KEY (id));

View File

@ -65,7 +65,11 @@ table {
pre { margin-left: 1rem; }
h3 { margin: 1rem 0; }
h2 {
border-bottom: solid 2px $dark;
margin-top: 2em; }
h3 { margin: 2rem 0 1rem 0; }
dl {
margin: 1rem;
@ -75,7 +79,20 @@ table {
font-family: $monoFont;
font-weight: bold; }
& > dd { padding: 0 0 0.5rem 1rem; } } }
& > dd { padding: 0 0 0.5rem 1rem; } }
table.method-summary {
padding: 0 2rem;
width: 100%;
th {
border-bottom: solid thin $dark;
text-align: left; }
th.action, td.action { width: 6em; }
th.path, td.path { width: 17em; }
th.public, td.public { width: 4em; }
} }
@include forSize(notSmall) {
@ -109,7 +126,7 @@ table {
text-align: center;
& > h2 { display: none; }
& > h2.song-name, & > h2.service-date { display: block; }
& > h2.song-name, & > h2.service-desc { display: block; }
& > nav > ul > li {
display: inline-block;

View File

@ -21,8 +21,8 @@
</header>
<section id=api-overview>
The New Life Songs database exposes a REST API. This allows
programatic access and modification to the data. Version 1 of the
API defines several endpoints, all of which are built off of
programatic access to and modification of the data. Version 1 of
the API defines several endpoints, all of which are built off of
<code>http://newlifesongs.jdbernard.com/api/v1</code> as a base
URL.
@ -64,6 +64,46 @@
"Michael W. Smith"
]
}</pre>
<h3>Method Summary</h3>
<table class=method-summary>
<thead>
<tr><th class=action>HTTP Action</th>
<th class=path>Path</th>
<th class=desc>Description</th>
<th class=public>Public?</th></tr>
</thead>
<tbody>
<tr><td class=action>GET</td>
<td class=path><code>/songs</code></td>
<td class=desc>Retrieve all songs.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>POST</td>
<td class=path><code>/songs</code></td>
<td class=desc>Create a new song record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/songs/&lt;songId&gt;</code></td>
<td class=desc>Retrieve a single record.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>PUT</td>
<td class=path><code>/songs/&lt;songId&gt;</code></td>
<td class=desc>Update a song record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>DELETE</td>
<td class=path><code>/songs/&lt;songId&gt;</code></td>
<td class=desc>Delete a song record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/songs/forService/&lt;serviceId&gt;</code></td>
<td class=desc>Retrieve all songs performed in a given service.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/songs/byArtist/&lt;artist&gt;</code></td>
<td class=desc>Retrieve all songs performed by a given artist.</td>
<td class=public>yes</td></tr>
</tbody>
</table>
<ul class=method-list>
<li><h3><code>GET /songs</code></h3>
@ -71,22 +111,22 @@
<p><h4>Response</h4>
A list of <a href="song-object">song objects</a>
<h4>Example</h4>
<p><h4>Example</h4>
<pre>
GET http://newlifesongs.jdbernard.com/api/v1/songs</pre>
<p><pre>
HTTP/1.1 200 OK
Content-Length: 5146
Content-Length: 433
Content-Type: application/json
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Server: Jetty(6.1.25)
[{"id":1,"name":"Welcome Holy Spirit","artists":["Mark Condon"]},
{"id":3,"name":"Let's Sing Praises to our God","artists":["Traditional"]},
{"id":5,"name":"Blessed Assurance","artists":["Frances J. Crosby"]},
{"id":8,"name":"Here I Am To Worship","artists":["Tim Hughes", "Chris Tomlin", "Michael W. Smith"]},
{"id":12,"name":"Healer","artists":["Kari Jobe", "Hillsong"]},
{"id":15,"name":"I Am Free","artists":["Newsboys"]}]</pre></li>
{"id":15,"name":"I Am Free","artists":["Newsboys"]}]
</pre></li>
<li><h3><code>POST /songs</code></h3>
@ -105,10 +145,185 @@ Server: Jetty(6.1.25)
The newly-created song record.
<p><h4>Example</h4>
<pre>
</pre></li>
<li><h3><code>GET /songs/&lt;songId&gt;</code></h3>
<p>Retrieve song data for the given song id.
<p><h4>Response</h4>
A <a href="song-object">song object</a>.
<p><h4>Example</h4>
<pre>
GET http://newlifesongs.jdbernard.com/api/v1/songs/1</pre>
<p><pre>
HTTP/1.1 200 OK
Content-Length: 63
Content-Type: application/json
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
{"id":1,"name":"Welcome Holy Spirit","artists":["Mark Condon"]}
</pre></li>
</li>
<li><h3><code>PUT /songs/&lt;songId&gt;</code></h3>
<p>Method description
<p><h4>Request Body</h4>
Request body description
<p><h4>Response</h4>
Return value description
<p><h4>Example</h4>
<pre>
</pre></li>
</li>
<li><h3><code>DELETE /songs/&lt;songId&gt;</code></h3>
<p>Method description
<p><h4>Request Body</h4>
Request body description
<p><h4>Response</h4>
Return value description
<p><h4>Example</h4>
<pre>
</pre></li>
</li>
<li><h3><code>GET /songs/forService/&lt;serviceId&gt;</code></h3>
<p>Method description
<p><h4>Request Body</h4>
Request body description
<p><h4>Response</h4>
Return value description
<p><h4>Example</h4>
<pre>
GET /api/v1/songs/forService/1 HTTP/1.1</pre>
<p><pre>
HTTP/1.1 200 OK
Content-Length: 256
Content-Type: application/json
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
[{"id":7,"name":"Mighty God","artists":[""]},
{"id":8,"name":"Here I Am To Worship","artists":["Tim Hughes: Chris Tomlin, Michael W. Smith"]},
{"id":9,"name":"Worthy","artists":[""]},
{"id":4,"name":"I Am A Friend Of God","artists":["Israel Houghton"]}]j
</pre></li>
</li>
<li><h3><code>GET /songs/byArtist/&lt;artist&gt;</code></h3>
<p>Method description
<p><h4>Request Body</h4>
Request body description
<p><h4>Response</h4>
Return value description
<p><h4>Example</h4>
<pre>
</pre></li>
</li>
</section>
<section id=services>
<h2><code>/services</code></h2>
<h3 id=service-object>Service object</h3>
A Service object is defined with the following fields:
<dl><dt>id</dt>
<dd>An identifier unique to this service record among all
service records. <em>Type: integer</em></dd>
<dt>date</dt>
<dd>The date of the service. <em>Type: Date</em></dd>
<dt>serviceType</dt>
<dd>Service type. <em>Type: string</em> Valid values:
<table><thead><tr><th>Value</th><th>Description</th></tr></thead>
<tbody>
<tr><td><code>SUN_AM</code></td>
<td>Sunday morning service.</td></tr>
<tr><td><code>SUN_PM</code></td>
<td>Sunday evening service</td></tr>
<tr><td><code>WED</code></td>
<td>Wednesday, midweek Bible study.</td></tr>
</tbody>
</table>
</dd>
</dl>
<h4>Example</h4>
<pre>
{
"id": 1,
"date": 1235887200000,
"serviceType": "SUN_PM"
}</pre>
<h3>Method Summary</h3>
<table class=method-summary>
<thead>
<tr><th class=action>HTTP Action</th>
<th class=path>Path</th>
<th class=desc>Description</th>
<th class=public>Public?</th></tr>
</thead>
<tbody>
<tr><td class=action>GET</td>
<td class=path><code>/services</code></td>
<td class=desc>Retrieve all services.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>POST</td>
<td class=path><code>/services</code></td>
<td class=desc>Create a new service record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/services/&lt;serviceId&gt;</code></td>
<td class=desc>Retrieve a single service record.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>PUT</td>
<td class=path><code>/services/&lt;serviceId&gt;</code></td>
<td class=desc>Update a service record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>DELETE</td>
<td class=path><code>/services/&lt;serviceId&gt;</code></td>
<td class=desc>Delete a service record.</td>
<td class=public>no</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/services/withSong/&lt;serviceId&gt;</code></td>
<td class=desc>Retrieve all services in which the given song was performed.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/services/byDate/after/&lt;date&gt;</code></td>
<td class=desc>Retrieve all services after the given date.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/services/byDate/before/&lt;date&gt;</code></td>
<td class=desc>Retrieve all services before the given date.</td>
<td class=public>yes</td></tr>
<tr><td class=acion>GET</td>
<td class=path><code>/services/byDate/between/&lt;date1&gt;/&lt;date2&gt;</code></td>
<td class=desc>Retrieve all services between the two given dates.</td>
<td class=public>yes</td></tr>
</tbody>
</table>
</section>
<section id=users>
<h2><code>/users</code></h2>

View File

@ -38,8 +38,8 @@ if (!service) { response.sendError(response.SC_NOT_FOUND); return }
<body>
<header>
<h1><a href="../">New Life Songs</a></h1>
<h2 class=service-date><%= service.@date.toString("yyyy-MM-dd") %> (<%=
service.serviceType.displayName %>)</h2>
<h2 class=service-desc><%= service.@date.toString("yyyy-MM-dd") %>: (<%=
service.description ?: service.serviceType.displayName %>)</h2>
<nav><ul>
<li><a href="../admin/">Admin</a></li>

View File

@ -45,7 +45,8 @@ songsDB = NLSongsContext.songsDB
<% songsDB.findAllServices().sort { it.date }.reverse().each { service -> %>
<tr><td class=date><a href="../service/<%= service.id %>"><%=
service.@date.toString("yyyy-MM-dd") %></a></td>
<td class=service-type><%= service.serviceType.displayName %></td></tr><% } %>
<td class=service-type><%= service.description ?:
service.serviceType.displayName %></td></tr><% } %>
</tbody>
<!--<tfoot><tr>
<th class="dt-left">Date</th>

View File

@ -1,6 +1,6 @@
#
#Mon Mar 23 03:03:08 CDT 2015
#Tue Apr 14 15:12:24 CDT 2015
major=2
version.release=true
minor=0
build=101
version.release=false
minor=2
build=13