Skip to content

Commit

Permalink
Merge pull request #90 from timwis/edit-categories
Browse files Browse the repository at this point in the history
Edit categories
  • Loading branch information
timwis committed Apr 14, 2016
2 parents 5128d8d + da19e75 commit b5cf1d6
Show file tree
Hide file tree
Showing 17 changed files with 209 additions and 128 deletions.
17 changes: 0 additions & 17 deletions _config.yml
Expand Up @@ -10,23 +10,6 @@ gatekeeper_host:
# Dataset schema
schema: default

# Categories
category_list:
- Arts / Culture / History
- Budget / Finance
- Economy
- Education
- Elections / Politics
- Environment
- Food
- Health / Human Services
- Parks / Recreation
- Planning / Zoning
- Public Safety
- Real Estate / Land Records
- Transportation
- Uncategorized

# Link for the "fork me on github" banner. Remove this line to suppress banner.
fork_me_url: https://github.com/timwis/jkan

Expand Down
14 changes: 14 additions & 0 deletions _data/categories.yml
@@ -0,0 +1,14 @@
- name: Arts / Culture / History
- name: Budget / Finance
- name: Economy
- name: Education
- name: Elections / Politics
- name: Environment
- name: Food
- name: Health / Human Services
- name: Parks / Recreation
- name: Planning / Zoning
- name: Public Safety
- name: Real Estate / Land Records
- name: Transportation
- name: Uncategorized
4 changes: 4 additions & 0 deletions _data/schemas/default.yml
Expand Up @@ -53,3 +53,7 @@ organization_fields:
label: Description
- field_name: logo
label: Logo

category_fields:
- field_name: name
label: Name
11 changes: 11 additions & 0 deletions _includes/admin-form-category.html
@@ -0,0 +1,11 @@
<div class="editable-list-item" data-hook="item">
<fieldset>
{% for field in category_fields %}
{% assign template = field.form_template | default: "form/text.html" %}
{% capture field_name %}categories[][{{ field.field_name }}]{% endcapture %}
{% assign value = category[field[field_name]] %}
{% include {{ template }} field=field field_name=field_name value=value %}
{% endfor %}
</fieldset>
<button type="button" class="btn btn-danger btn-sm" data-hook="remove-item-btn"><i class="fa fa-minus"></i> Remove</button>
</div>
6 changes: 3 additions & 3 deletions _includes/dataset-form-resource.html
@@ -1,11 +1,11 @@
<div class="resource-row" data-hook="resource-row">
<fieldset class="resource-fieldset">
<div class="editable-list-item" data-hook="item">
<fieldset>
{% for field in resource_fields %}
{% assign template = field.form_template | default: "form/text.html" %}
{% capture field_name %}resources[][{{ field.field_name }}]{% endcapture %}
{% assign value = resource[field[field_name]] %}
{% include {{ template }} field=field field_name=field_name value=value %}
{% endfor %}
</fieldset>
<button type="button" class="btn btn-danger btn-sm" data-hook="remove-resource-btn" title="Remove resource" data-toggle="tooltip"><i class="fa fa-minus"></i> Remove Resource</button>
<button type="button" class="btn btn-danger btn-sm" data-hook="remove-item-btn"><i class="fa fa-minus"></i> Remove Resource</button>
</div>
19 changes: 11 additions & 8 deletions _includes/dataset-form.html
Expand Up @@ -24,12 +24,19 @@
</fieldset>

<h2>Resources</h2>
<div data-hook="resource-rows">
{% for resource in include.dataset.resources %}
<div data-component="editable-list" data-item-label="resource">
<div data-hook="items">
{% for resource in include.dataset.resources %}
{% include dataset-form-resource.html %}
{% endfor %}
</div>

<button type="button" class="btn btn-default" data-hook="add-item-btn" title="Add resource"><i class="fa fa-plus"></i> Add Resource</button>

<script type="text/template" data-hook="item-template">
{% include dataset-form-resource.html %}
{% endfor %}
</script>
</div>
<button type="button" class="btn btn-default" data-hook="add-resource-btn" title="Add resource"><i class="fa fa-plus"></i> Add Resource</button>

<fieldset>
<h2>Additional Info</h2>
Expand All @@ -52,7 +59,3 @@ <h2>Additional Info</h2>
</button>
{% endif %}
</form>

<script type="text/template" data-hook="tmpl-resource-row">
{% include dataset-form-resource.html %}
</script>
4 changes: 2 additions & 2 deletions _includes/form/category.html
@@ -1,8 +1,8 @@
<div class="form-group">
<label for="{{ include.field_name }}[]">{{ include.field.label }}</label>
<select class="form-control select2" id="{{ include.field_name }}[]" name="{{ include.field_name }}[]" multiple="multiple" style="width: 100%">
{% for category in site.category_list %}
<option{% if include.value == category or include.value contains category %} selected="selected"{% endif %}>{{ category }}</option>
{% for category in site.data.categories %}
<option{% if include.value == category.name or include.value contains category.name %} selected="selected"{% endif %}>{{ category.name }}</option>
{% endfor %}
</select>
</div>
112 changes: 73 additions & 39 deletions admin.html
Expand Up @@ -5,56 +5,90 @@
---
{% include breadcrumbs.html %}

<div class="alert alert-success" role="alert" data-hook="alert-success" style="display: none;">
These settings have been <a href="#" data-hook="commit-url">saved</a> and the site is currently regenerating.
</div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#general" aria-controls="general" role="tab" data-toggle="tab">General</a></li>
<li role="presentation"><a href="#authentication" aria-controls="authentication" role="tab" data-toggle="tab">Authentication</a></li>
<li role="presentation"><a href="#categories" aria-controls="categories" role="tab" data-toggle="tab">Categories</a></li>
<li role="presentation"><a href="#maintenance" aria-controls="maintenance" role="tab" data-toggle="tab">Maintenance</a></li>
</ul>

<div class="alert alert-danger" role="alert" data-hook="alert-error" style="display: none;">
There was an error saving this page
</div>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="general">
<h2>General</h2>
<form data-component="admin-form" data-file-path="_config.yml">

<fieldset>

<div class="form-group">
<label for="title">Site Title</label>
<input type="text" class="form-control" id="title" name="title" value="{{ site.title }}">
</div>

<h1>Administration</h1>
<form data-component="admin-form" data-file-path="_config.yml">
<div class="form-group">
<label for="description">Site Description</label>
<textarea class="form-control" id="description" name="description">{{ site.description }}</textarea>
</div>

<fieldset>
<div class="form-group">
<label for="baseurl">Base URL</label>
<input type="text" class="form-control" id="baseurl" name="baseurl" value="{{ site.baseurl }}" placeholder="ie. /JKAN">
</div>

<div class="form-group">
<label for="title">Site Title</label>
<input type="text" class="form-control" id="title" name="title" value="{{ site.title }}">
</div>
<button type="submit" class="btn btn-primary">Submit</button>

<div class="form-group">
<label for="description">Site Description</label>
<textarea class="form-control" id="description" name="description">{{ site.description }}</textarea>
</div>
</fieldset>

<div class="form-group">
<label for="baseurl">Base URL</label>
<input type="text" class="form-control" id="baseurl" name="baseurl" value="{{ site.baseurl }}" placeholder="ie. /JKAN">
</div>
</form>
</div>

<h3>Authentication</h3>
<div role="tabpanel" class="tab-pane" id="authentication">
<h2>Authentication</h2>
<form data-component="admin-form" data-file-path="_config.yml">

<div class="form-group">
<label for="github_client_id">GitHub Client ID</label>
<input type="text" class="form-control" id="github_client_id" name="github_client_id" value="{{ site.github_client_id }}" placeholder="ie. 9098sdf876sdfs768az">
<p class="help-block"><a href="https://github.com/settings/applications/new">Register a Github application</a> to get a Client ID</p>
</div>
<fieldset>

<div class="form-group">
<label for="gatekeeper_host">Gatekeeper Host</label>
<input type="text" class="form-control" id="gatekeeper_host" name="gatekeeper_host" value="{{ site.gatekeeper_host }}" placeholder="ie. http://jkan-gatekeeper.herokuapp.com">
<p class="help-block">Authentication server you deployed</p>
</div>
<div class="form-group">
<label for="github_client_id">GitHub Client ID</label>
<input type="text" class="form-control" id="github_client_id" name="github_client_id" value="{{ site.github_client_id }}" placeholder="ie. 9098sdf876sdfs768az">
<p class="help-block"><a href="https://github.com/settings/applications/new">Register a Github application</a> to get a Client ID</p>
</div>

<button type="submit" class="btn btn-primary">Submit</button>
<div class="form-group">
<label for="gatekeeper_host">Gatekeeper Host</label>
<input type="text" class="form-control" id="gatekeeper_host" name="gatekeeper_host" value="{{ site.gatekeeper_host }}" placeholder="ie. http://jkan-gatekeeper.herokuapp.com">
<p class="help-block">Authentication server you deployed</p>
</div>

<h3>Site Maintenance</h3>
<button type="submit" class="btn btn-primary">Submit</button>

<div class="form-group">
<a href="https://github.com/{{ site.github.owner_name }}/{{ site.github.project_title }}/compare/gh-pages...timwis:gh-pages?expand=1" class="btn btn-info">Check for updates</a>
</div>
</fieldset>

</fieldset>
</form>
</div>

</form>
<div role="tabpanel" class="tab-pane" id="categories">
<h2>Categories</h2>
{% assign category_fields = site.data.schemas[site[schema]].category_fields %}
<form data-component="categories-form editable-list" data-file-path="_data/categories.yml" data-item-label="category">
<div data-hook="items">
{% for category in site.data.categories %}
{% include admin-form-category.html %}
{% endfor %}
</div>
<div class="form-group">
<button type="button" class="btn btn-default" data-hook="add-item-btn"><i class="fa fa-plus"></i> Add Category</button>
</div>

<button type="submit" class="btn btn-primary">Submit</button>

<script type="text/template" data-hook="item-template">
{% include admin-form-category.html %}
</script>
</form>
</div>

<div role="tabpanel" class="tab-pane" id="maintenance">
<h2>Site Maintenance</h2>
<a href="https://github.com/{{ site.github.owner_name }}/{{ site.github.project_title }}/compare/gh-pages...timwis:gh-pages?expand=1" class="btn btn-info">Check for updates</a>
</div>
</div>
2 changes: 1 addition & 1 deletion css/main.css
Expand Up @@ -39,7 +39,7 @@ dataset {
display: none;
}

.resource-row {
.editable-list-item {
padding: 19px;
margin-bottom: 20px;
background-color: #f5f5f5;
Expand Down
18 changes: 9 additions & 9 deletions scripts/dist/bundle.js

Large diffs are not rendered by default.

17 changes: 15 additions & 2 deletions scripts/src/components/admin-form.js
Expand Up @@ -14,12 +14,12 @@ export default class {
filePath: opts.el.data('file-path')
})

opts.el.on('submit', function (e) {
opts.el.on('submit', (e) => {
const formData = opts.el.serializeJSON()

file.read()
.then((contents) => {
const newContents = file.updateYamlString(contents, formData)
const newContents = this._updateYamlString(contents, formData)
file.save(newContents)
.then((response) => {
const commitUrl = response.commit.html_url
Expand All @@ -36,4 +36,17 @@ export default class {
e.preventDefault()
})
}

_updateYamlString (yamlString, updateObject) {
for (let key in updateObject) {
const regex = new RegExp(`^( *${key}: +?).*`, 'm')
const match = yamlString.match(regex)
if (match) {
yamlString = yamlString.replace(regex, match[1] + updateObject[key])
} else {
yamlString += `\n${key}: ${updateObject[key]}`
}
}
return yamlString
}
}
9 changes: 9 additions & 0 deletions scripts/src/components/categories-form.js
@@ -0,0 +1,9 @@
import jsyaml from 'js-yaml'

import Form from './form'

export default class extends Form {
_formatData (formData) {
return jsyaml.safeDump(formData.categories || [])
}
}
23 changes: 1 addition & 22 deletions scripts/src/components/dataset-form.js
@@ -1,34 +1,13 @@
import $ from 'jquery'
import 'select2'
import 'jquery-serializejson'
import notie from 'notie'

import {queryByHook} from '../util'

export default class {
constructor (opts) {
const elements = {
tmplResourceRow: queryByHook('tmpl-resource-row'),
select2: $('.select2', opts.el),
resourceRows: queryByHook('resource-rows', opts.el),
addResourceBtn: queryByHook('add-resource-btn', opts.el),
deleteBtn: queryByHook('delete-dataset-btn', opts.el)
select2: $('.select2', opts.el)
}
const TmplResourceRow = elements.tmplResourceRow.html()

// Initialize select2 plugin
elements.select2.select2()

// Add resource button
elements.addResourceBtn.on('click', function (e) {
elements.resourceRows.append(TmplResourceRow)
})

// "Remove resource" buttons
elements.resourceRows.on('click', '[data-hook~=remove-resource-btn]', (e) => {
notie.confirm('Delete this resource?', 'Yes', 'Cancel', () => {
$(e.currentTarget).closest('[data-hook~=resource-row]').remove()
})
})
}
}
41 changes: 41 additions & 0 deletions scripts/src/components/editable-list.js
@@ -0,0 +1,41 @@
/**
* Usage:
* <div data-component="editable-list" data-item-label="category">
* <div data-hook="items">
* <div data-hook="item">
* <button data-hook="remove-item-btn">Remove</button>
* </div>
* </div>
* <button data-hook="add-items-btn">Add</button>
* <script type="text/template" data-hook="item-template">
* </script>
* </div>
*/
import $ from 'jquery'
import notie from 'notie'

import {queryByHook} from '../util'

export default class {
constructor (opts) {
const elements = {
itemTemplate: queryByHook('item-template', opts.el),
items: queryByHook('items', opts.el),
addBtn: queryByHook('add-item-btn', opts.el)
}
const ItemTemplate = elements.itemTemplate.html()
const itemLabel = opts.el.data('item-label') || 'item'

// Add button
elements.addBtn.on('click', function (e) {
elements.items.append(ItemTemplate)
})

// "Remove resource" buttons
elements.items.on('click', '[data-hook~=remove-item-btn]', (e) => {
notie.confirm(`Delete this ${itemLabel}?`, 'Yes', 'Cancel', () => {
$(e.currentTarget).closest('[data-hook~=item]').remove()
})
})
}
}

0 comments on commit b5cf1d6

Please sign in to comment.