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

Create import petition, import legislation pages #190

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,15 @@ module.exports = {
return require('./models/activity')(event, state)
case '/legislation/create':
case '/petitions/create':
case '/legislation/import':
case '/petitions/import':
case '/petitions/yours':
case '/legislation/yours':
case '/legislation/:shortId':
case '/nominations/:shortId':
case '/:username/:shortId':
case '/:username/:shortId/edit':
case '/:user.id/:shortId':
return require('./models/measure')(event, state)
case '/legislation/:shortId/import':
case '/nominations/:shortId/import':
Expand Down
4 changes: 4 additions & 0 deletions routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ module.exports = {
'/settings': () => import('./views/settings-page'),
'/settings/unsubscribe': () => import('./views/settings-unsubscribe-page'),
'/legislation/create': () => import('./views/edit-legislation-page'),
'/legislation/import': () => import('./views/import-legislation-page'),
'/legislation/yours': () => import('./views/user-legislation-page'),
'/petitions/create': () => import('./views/edit-petition-page'),
'/petitions/import': () => import('./views/import-petition-page'),
'/legislation/:shortId': () => import('./views/measure-details-page'),
'/nominations/:shortId': () => import('./views/measure-details-page'),
'/legislation/:shortId/import': () => import('./views/import-vote-page'),
Expand All @@ -32,7 +34,9 @@ module.exports = {
'/metrics': () => import('./views/metrics-page'),
'/:username': () => import('./views/profile-page'),
'/:username/:shortId': () => import('./views/measure-details-page'),
'/:author_id/:shortId': () => import('./views/measure-details-page'),
'/:username/:shortId/import': () => import('./views/import-vote-page'),
'/:user.id/:shortId/import': () => import('./views/import-vote-page'),
'/:username/:shortId/edit': () => import('./views/edit-legislation-page'),
'/:username/:shortId/votes/:voteId': () => import('./views/measure-details-page'),
}
2 changes: 2 additions & 0 deletions views/activity-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ module.exports = (state, dispatch) => {
<p class="menu-label">Action</p>
<ul class="menu-list">
<li><a href="/petitions/create">Start a Petition</a></li>
<li><a href="/petitions/import">Import a Petition</a></li>
<li><a href="/legislation/create">Propose a Bill</a></li>
<li><a href="/legislation/import">Import a Bill</a></li>
</ul>
</nav>
</div>
Expand Down
109 changes: 109 additions & 0 deletions views/import-legislation-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const { WWW_URL } = process.env
const { handleForm, html } = require('../helpers')
const activityIndicator = require('./activity-indicator')

module.exports = (state, dispatch) => {
const { location, measures = {}, user } = state
const measure = location.params.shortId && measures[location.params.shortId]
return html`
<section class="section">
<div class="container is-widescreen">
<h2 class="title is-5">${measure ? 'Edit Petition' : 'Import External Policy Proposal as a Bill'}</h2>
<div class="is-size-5">Once imported and approved, it will be displayed alongside other policy proposals and available for voting for or against.</div><br />
${user.username
? location.params.shortId && !measure
? activityIndicator()
: form(state, dispatch)
: publicProfileRequiredMsg(user.phone_verified)}
</div>
</section>
`
}

const publicProfileRequiredMsg = (verified) => {
return html`
<p class="notification">
You must create a public profile to import a petition.
${verified
? html`<a href="/get_started">Choose a username</a> and make a public profile.</a>`
: html`<a href="/get_started">Verify your phone number</a> to choose a username and make a public profile.</a>`
}
</p>
`
}

const form = (state, dispatch) => {
const { error, forms, legislatures = [], loading, location, user, measures = {} } = state
const measure = measures[location.params.shortId] || {}
const form = forms.editMeasure || {}
const { legislature_id, summary, title } = measure
const auto_short_id = (form.title || title || '').toLowerCase().replace(/ /g, '-').replace(/[^A-z0-9-_]/g, '').slice(0, 32)
const short_id = !forms.editMeasureShortId && !measure.short_id ? auto_short_id : (form.short_id || measure.short_id)

return html`
<form method="POST" onsubmit=${handleForm(dispatch, { type: 'measure:editFormSaved', oldShortId: measure.short_id })} onkeyup=${handleForm(dispatch, { type: 'measure:editFormChanged' })} onchange=${handleForm(dispatch, { type: 'measure:editFormChanged' })}>
${error ? html`<div class="notification is-danger">${error.message}</div>` : ''}
<input type="hidden" name="measure_type" value="bill" />
<input type="hidden" name="imported_by" value="${user.id}" />
<input type="hidden" name="approval_status" value="undefined" />
<div class="${`field ${legislatures.length === 1 ? 'is-hidden' : ''}`}">
<label for="short_id" class="label has-text-grey">Legislature</label>
<div class="control">
<div class="select">
<select name="legislature_id">
${legislatures.map(({ id, name }) => {
return html`<option value="${id}" selected=${id === legislature_id}>${name}</option>`
})}
</select>
</div>
</div>
</div>
<div class="field">
<label for="short_id" class="label has-text-grey">Bill Author's Twitter Username</label>
<div class="control">
<input name="twitter_username" required class="input" placeholder="Twitter @username" />
</div>
</div>
<div class="field">
<label for="Title" class="label has-text-grey">Title</label>
<div class="control">
<input name="title" class="input" type="text" autocomplete="off" placeholder="Eliminate Sales Tax Now!" required value="${title || ''}" />
</div>
</div>
<div class="field">
<label for="short_id" class="label has-text-grey">URL</label>
<div class="field has-addons">
<div class="control">
<a class="button is-static">${WWW_URL.replace(/https?:\/\//, '')}/[author_id]/</a>
</div>
<div class="control">
<input name="short_id" class="input" type="text" placeholder="petition" onkeyup=${editedShortId(dispatch)} onchange=${editedShortId(dispatch)} value="${short_id}" />
</div>
</div>
</div>
<div class="field">
<label for="source_url" class="label has-text-grey">Source URL</label>
<div class="control">
<input name="source_url" class="input" type="text" autocomplete="off" placeholder="Eliminate Sales Tax Now!" required value="${title || ''}" />
</div>
</div>
<div class="field">
<label for="summary" class="label has-text-grey">Summary</label>
<div class="control">
<textarea name="summary" autocomplete="off" class="textarea" rows="2" placeholder="Copy an excerpt from the policy proposal you are importing to add as a summary." required value="${summary || ''}"></textarea>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class=${`button is-primary ${loading.form === 'saving' ? 'is-loading' : ''}`} disabled="${loading.form}" type="submit">
${measure.id ? 'Save' : 'Import'}
</button>
</div>
</div>
</form>
`
}

const editedShortId = (dispatch) => (event) => {
dispatch({ type: 'measure:editFormShortIdChanged', shortId: event.currentTarget.value, event })
}
110 changes: 110 additions & 0 deletions views/import-petition-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
const { WWW_URL } = process.env
const { handleForm, html } = require('../helpers')
const activityIndicator = require('./activity-indicator')

module.exports = (state, dispatch) => {
const { location, measures = {}, user } = state
const measure = location.params.shortId && measures[location.params.shortId]
return html`
<section class="section">
<div class="container is-widescreen">
<h2 class="title is-5">${measure ? 'Edit Petition' : 'Import External Policy Proposal as Petition'}</h2>
<div class="is-size-5">Once imported and approved, it will be displayed alongside other policy proposals and voters will be able to Back it.</div><br />

${user.username
? location.params.shortId && !measure
? activityIndicator()
: form(state, dispatch)
: publicProfileRequiredMsg(user.phone_verified)}
</div>
</section>
`
}

const publicProfileRequiredMsg = (verified) => {
return html`
<p class="notification">
You must create a public profile to import a petition.
${verified
? html`<a href="/get_started">Choose a username</a> and make a public profile.</a>`
: html`<a href="/get_started">Verify your phone number</a> to choose a username and make a public profile.</a>`
}
</p>
`
}

const form = (state, dispatch) => {
const { error, forms, legislatures = [], loading, location, measures = {}, user } = state
const measure = measures[location.params.shortId] || {}
const form = forms.editMeasure || {}
const { legislature_id, summary, title } = measure
const auto_short_id = (form.title || title || '').toLowerCase().replace(/ /g, '-').replace(/[^A-z0-9-_]/g, '').slice(0, 32)
const short_id = !forms.editMeasureShortId && !measure.short_id ? auto_short_id : (form.short_id || measure.short_id)

return html`
<form method="POST" onsubmit=${handleForm(dispatch, { type: 'measure:editFormSaved', oldShortId: measure.short_id })} onkeyup=${handleForm(dispatch, { type: 'measure:editFormChanged' })} onchange=${handleForm(dispatch, { type: 'measure:editFormChanged' })}>
${error ? html`<div class="notification is-danger">${error.message}</div>` : ''}
<input type="hidden" name="measure_type" value="petition" />
<input type="hidden" name="imported_by" value="${user.id}" />
<input type="hidden" name="approval_status" value="undefined" />
<div class="${`field ${legislatures.length === 1 ? 'is-hidden' : ''}`}">
<label for="short_id" class="label has-text-grey">Who is this petition for?</label>
<div class="control">
<div class="select">
<select name="legislature_id">
${legislatures.map(({ id, name }) => {
return html`<option value="${id}" selected=${id === legislature_id}>${name}</option>`
})}
</select>
</div>
</div>
</div>
<div class="field">
<label for="short_id" class="label has-text-grey">What is the author's Twitter username?</label>
<div class="control">
<input name="twitter_username" required class="input" placeholder="@username" />
</div>
</div>
<div class="field">
<label for="Title" class="label has-text-grey">Title</label>
<div class="control">
<input name="title" class="input" type="text" autocomplete="off" placeholder="Eliminate Sales Tax Now!" required value="${title || ''}" />
</div>
</div>
<div class="field">
<label for="short_id" class="label has-text-grey">URL</label>
<div class="field has-addons">
<div class="control">
<a class="button is-static">${WWW_URL.replace(/https?:\/\//, '')}/[author_id]/</a>
</div>
<div class="control">
<input name="short_id" class="input" type="text" placeholder="petition" onkeyup=${editedShortId(dispatch)} onchange=${editedShortId(dispatch)} value="${short_id}" />
</div>
</div>
</div>
<div class="field">
<label for="source_url" class="label has-text-grey">Source URL</label>
<div class="control">
<input name="source_url" class="input" type="text" autocomplete="off" placeholder="Eliminate Sales Tax Now!" required value="${title || ''}" />
</div>
</div>
<div class="field">
<label for="summary" class="label has-text-grey">Summary</label>
<div class="control">
<textarea name="summary" autocomplete="off" class="textarea" rows="2" placeholder="Copy an excerpt from the policy proposal you are importing to add as a summary." required value="${summary || ''}"></textarea>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class=${`button is-primary ${loading.form === 'saving' ? 'is-loading' : ''}`} disabled="${loading.form}" type="submit">
${measure.id ? 'Save' : 'Import'}
</button>
</div>
</div>
</form>
`
}

const editedShortId = (dispatch) => (event) => {
dispatch({ type: 'measure:editFormShortIdChanged', shortId: event.currentTarget.value, event })
}
2 changes: 2 additions & 0 deletions views/navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ const navbarAuthed = ({ location, user }) => {
<a class=${`navbar-item ${path === '/settings' ? 'is-active' : ''}`} href="/settings">Settings</a>
<hr />
<a class=${`navbar-item ${path === `/petitions/create` ? 'is-active' : ''}`} href="/petitions/create">Start a Petition</a>
<a class=${`navbar-item ${path === `/petitions/import` ? 'is-active' : ''}`} href="/petitions/import">Import a Petition</a>
<a class=${`navbar-item ${path === `/legislation/create` ? 'is-active' : ''}`} href="/legislation/create">Propose a Bill</a>
<a class=${`navbar-item ${path === `/legislation/import` ? 'is-active' : ''}`} href="/legislation/import">Import a Bill</a>
<a class=${`navbar-item ${path === '/sign_out' ? 'is-active' : ''}`} href=${`${WWW_URL}/sign_out`}>Sign out</a>
</div>
</div>
Expand Down