├── src ├── frontend │ ├── index │ │ ├── production.json │ │ ├── development.json │ │ └── index.mustache │ ├── public │ │ ├── admin │ │ │ └── events │ │ │ │ └── static │ │ │ │ ├── ckeditor │ │ │ │ ├── plugins │ │ │ │ │ ├── icons.png │ │ │ │ │ ├── icons_hidpi.png │ │ │ │ │ ├── link │ │ │ │ │ │ ├── images │ │ │ │ │ │ │ ├── anchor.png │ │ │ │ │ │ │ └── hidpi │ │ │ │ │ │ │ │ └── anchor.png │ │ │ │ │ │ └── dialogs │ │ │ │ │ │ │ └── anchor.js │ │ │ │ │ ├── about │ │ │ │ │ │ └── dialogs │ │ │ │ │ │ │ ├── logo_ckeditor.png │ │ │ │ │ │ │ ├── hidpi │ │ │ │ │ │ │ └── logo_ckeditor.png │ │ │ │ │ │ │ └── about.js │ │ │ │ │ ├── blockquote │ │ │ │ │ │ ├── icons │ │ │ │ │ │ │ ├── blockquote.png │ │ │ │ │ │ │ └── hidpi │ │ │ │ │ │ │ │ └── blockquote.png │ │ │ │ │ │ └── lang │ │ │ │ │ │ │ ├── ar.js │ │ │ │ │ │ │ ├── cs.js │ │ │ │ │ │ │ ├── eo.js │ │ │ │ │ │ │ ├── es.js │ │ │ │ │ │ │ ├── fi.js │ │ │ │ │ │ │ ├── fr.js │ │ │ │ │ │ │ ├── gl.js │ │ │ │ │ │ │ ├── ja.js │ │ │ │ │ │ │ ├── ka.js │ │ │ │ │ │ │ ├── ko.js │ │ │ │ │ │ │ ├── lt.js │ │ │ │ │ │ │ ├── pl.js │ │ │ │ │ │ │ ├── ro.js │ │ │ │ │ │ │ ├── ru.js │ │ │ │ │ │ │ ├── sk.js │ │ │ │ │ │ │ ├── sl.js │ │ │ │ │ │ │ ├── sq.js │ │ │ │ │ │ │ ├── uk.js │ │ │ │ │ │ │ ├── zh.js │ │ │ │ │ │ │ ├── af.js │ │ │ │ │ │ │ ├── bg.js │ │ │ │ │ │ │ ├── ca.js │ │ │ │ │ │ │ ├── cy.js │ │ │ │ │ │ │ ├── da.js │ │ │ │ │ │ │ ├── de.js │ │ │ │ │ │ │ ├── en.js │ │ │ │ │ │ │ ├── et.js │ │ │ │ │ │ │ ├── fa.js │ │ │ │ │ │ │ ├── fo.js │ │ │ │ │ │ │ ├── he.js │ │ │ │ │ │ │ ├── hi.js │ │ │ │ │ │ │ ├── hr.js │ │ │ │ │ │ │ ├── hu.js │ │ │ │ │ │ │ ├── id.js │ │ │ │ │ │ │ ├── is.js │ │ │ │ │ │ │ ├── it.js │ │ │ │ │ │ │ ├── lv.js │ │ │ │ │ │ │ ├── mn.js │ │ │ │ │ │ │ ├── nb.js │ │ │ │ │ │ │ ├── nl.js │ │ │ │ │ │ │ ├── no.js │ │ │ │ │ │ │ ├── pt-br.js │ │ │ │ │ │ │ ├── si.js │ │ │ │ │ │ │ ├── sv.js │ │ │ │ │ │ │ ├── th.js │ │ │ │ │ │ │ ├── tr.js │ │ │ │ │ │ │ ├── tt.js │ │ │ │ │ │ │ ├── ug.js │ │ │ │ │ │ │ ├── zh-cn.js │ │ │ │ │ │ │ ├── el.js │ │ │ │ │ │ │ ├── en-au.js │ │ │ │ │ │ │ ├── en-ca.js │ │ │ │ │ │ │ ├── en-gb.js │ │ │ │ │ │ │ ├── eu.js │ │ │ │ │ │ │ ├── fr-ca.js │ │ │ │ │ │ │ ├── km.js │ │ │ │ │ │ │ ├── pt.js │ │ │ │ │ │ │ ├── vi.js │ │ │ │ │ │ │ ├── bn.js │ │ │ │ │ │ │ ├── bs.js │ │ │ │ │ │ │ ├── gu.js │ │ │ │ │ │ │ ├── mk.js │ │ │ │ │ │ │ ├── ms.js │ │ │ │ │ │ │ ├── sr.js │ │ │ │ │ │ │ ├── ku.js │ │ │ │ │ │ │ └── sr-latn.js │ │ │ │ │ ├── dialog │ │ │ │ │ │ └── dialogDefinition.js │ │ │ │ │ └── clipboard │ │ │ │ │ │ └── dialogs │ │ │ │ │ │ └── paste.js │ │ │ │ ├── samples │ │ │ │ │ ├── img │ │ │ │ │ │ ├── logo.png │ │ │ │ │ │ ├── github-top.png │ │ │ │ │ │ ├── header-bg.png │ │ │ │ │ │ ├── navigation-tip.png │ │ │ │ │ │ └── header-separator.png │ │ │ │ │ ├── old │ │ │ │ │ │ ├── assets │ │ │ │ │ │ │ ├── sample.jpg │ │ │ │ │ │ │ ├── inlineall │ │ │ │ │ │ │ │ └── logo.png │ │ │ │ │ │ │ ├── uilanguages │ │ │ │ │ │ │ │ └── languages.js │ │ │ │ │ │ │ ├── posteddata.php │ │ │ │ │ │ │ └── outputxhtml │ │ │ │ │ │ │ │ └── outputxhtml.css │ │ │ │ │ │ ├── sample_posteddata.php │ │ │ │ │ │ ├── dialog │ │ │ │ │ │ │ └── assets │ │ │ │ │ │ │ │ └── my_dialog.js │ │ │ │ │ │ ├── sample.js │ │ │ │ │ │ ├── appendto.html │ │ │ │ │ │ ├── tabindex.html │ │ │ │ │ │ ├── uicolor.html │ │ │ │ │ │ ├── ajax.html │ │ │ │ │ │ └── readonly.html │ │ │ │ │ ├── toolbarconfigurator │ │ │ │ │ │ ├── font │ │ │ │ │ │ │ ├── fontello.eot │ │ │ │ │ │ │ ├── fontello.ttf │ │ │ │ │ │ │ ├── fontello.woff │ │ │ │ │ │ │ ├── LICENSE.txt │ │ │ │ │ │ │ ├── config.json │ │ │ │ │ │ │ └── fontello.svg │ │ │ │ │ │ ├── lib │ │ │ │ │ │ │ └── codemirror │ │ │ │ │ │ │ │ ├── show-hint.css │ │ │ │ │ │ │ │ ├── neo.css │ │ │ │ │ │ │ │ └── LICENSE │ │ │ │ │ │ ├── css │ │ │ │ │ │ │ └── fontello.css │ │ │ │ │ │ └── js │ │ │ │ │ │ │ └── fulltoolbareditor.js │ │ │ │ │ └── js │ │ │ │ │ │ └── sample.js │ │ │ │ ├── skins │ │ │ │ │ └── moono │ │ │ │ │ │ ├── icons.png │ │ │ │ │ │ ├── icons_hidpi.png │ │ │ │ │ │ ├── images │ │ │ │ │ │ ├── arrow.png │ │ │ │ │ │ ├── close.png │ │ │ │ │ │ ├── lock.png │ │ │ │ │ │ ├── refresh.png │ │ │ │ │ │ ├── spinner.gif │ │ │ │ │ │ ├── hidpi │ │ │ │ │ │ │ ├── close.png │ │ │ │ │ │ │ ├── lock.png │ │ │ │ │ │ │ ├── refresh.png │ │ │ │ │ │ │ └── lock-open.png │ │ │ │ │ │ └── lock-open.png │ │ │ │ │ │ └── readme.md │ │ │ │ ├── config.js │ │ │ │ ├── README.md │ │ │ │ ├── contents.css │ │ │ │ ├── adapters │ │ │ │ │ └── jquery.js │ │ │ │ └── build-config.js │ │ │ │ └── clndr.less │ │ └── BSDSurveyWrapper.js │ ├── components │ │ ├── InfoHeader.js │ │ ├── forms │ │ │ ├── GCFormField.js │ │ │ ├── GCSubmitButton.js │ │ │ ├── GCToggleField.js │ │ │ ├── GCTextField.js │ │ │ ├── GCPasswordField.js │ │ │ ├── GCPhoneField.js │ │ │ ├── GCDateField.js │ │ │ ├── GCTimeField.js │ │ │ ├── GCRadioButtonsField.js │ │ │ ├── GCDateTimeField.js │ │ │ ├── GCCheckboxesField.js │ │ │ ├── GCBooleanField.js │ │ │ ├── GCSelectField.js │ │ │ └── GCForm.js │ │ ├── NotFound.js │ │ ├── Unauthorized.js │ │ ├── volunteer-dashboard │ │ │ ├── EventEditor.js │ │ │ ├── EventViewer.js │ │ │ ├── VolunteerEventsDashboard.js │ │ │ └── VolunteerDashboard.js │ │ ├── data │ │ │ └── USTimeZones.js │ │ ├── styles │ │ │ ├── bernie-theme.js │ │ │ └── bernie-css.js │ │ ├── AdminCallAssignment.js │ │ ├── CallAssignmentsDashboard.js │ │ ├── survey-renderers │ │ │ └── SurveyRenderer.js │ │ ├── CallAssignmentList.js │ │ ├── AdminDashboard.js │ │ ├── SurveyRenderer.js │ │ ├── AdminCallAssignmentsSection.js │ │ ├── SideBarLayout.js │ │ ├── Dashboard.js │ │ ├── CallAssignmentsSection.js │ │ ├── MutationHandler.js │ │ ├── EventPreview.js │ │ └── TopNav.js │ ├── BSD │ │ └── BSDAdminSurveyWrapper.js │ ├── mutations │ │ ├── EditEvents.js │ │ ├── DeleteEvents.js │ │ ├── SubmitCallSurvey.js │ │ └── CreateCallAssignment.js │ └── relay-extensions │ │ └── GCNetworkLayer.js ├── backend │ ├── email-templates │ │ ├── phone-bank-instructions │ │ │ ├── style.hbs │ │ │ ├── text.hbs │ │ │ └── html.hbs │ │ ├── event-create-confirmation │ │ │ ├── style.hbs │ │ │ ├── text.hbs │ │ │ └── html.hbs │ │ ├── header.hbs │ │ └── footer.hbs │ ├── bsd-instance.js │ ├── data │ │ ├── migrations │ │ │ ├── 20151219155318_add_is_primary_index_to_phones.js │ │ │ ├── 20151222165715_add_completed_to_calls.js │ │ │ ├── 20151223084757_add_instructions_to_call_assignments.js │ │ │ ├── 20151222224835_make_ids_bigint.js │ │ │ └── 20151222230001_make_other_columns_bigint.js │ │ ├── knexfile.js │ │ ├── writeSchema.js │ │ └── knex.js │ ├── log.js │ ├── bcrypt-promise.js │ └── maestro.js └── jobs │ ├── jobs.json │ ├── README.md │ ├── jobs │ ├── bsd-assigned-calls-ttl.js │ └── refresh-group-memberships.js │ └── app.js ├── vendor └── dante │ ├── lib │ ├── libsocks.so │ ├── libsocks.so.0 │ ├── libsocks.a │ ├── libdsocks.so │ ├── libsocks.so.0.1.1 │ ├── libdsocks.la │ └── libsocks.la │ ├── bin │ └── socksify │ ├── include │ └── socks.h │ ├── share │ └── man │ │ └── man1 │ │ └── socksify.1 │ └── socks.conf.template ├── Procfile ├── run ├── .tern-project ├── webpack ├── babelRelayPlugin.js ├── schemaPlugin.js ├── config.js └── server.js ├── docker-compose.yml ├── .gitignore ├── Procfile.dev ├── .env ├── .eslintrc ├── setup-osx ├── setup-linux ├── bin └── proximo ├── docs ├── SPECS.md └── CALL_ASSIGNMENTS.md └── package.json /src/frontend/index/production.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /vendor/dante/lib/libsocks.so: -------------------------------------------------------------------------------- 1 | libsocks.so.0.1.1 -------------------------------------------------------------------------------- /vendor/dante/lib/libsocks.so.0: -------------------------------------------------------------------------------- 1 | libsocks.so.0.1.1 -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: npm start 2 | worker: ./run ./src/jobs/app.js -------------------------------------------------------------------------------- /src/backend/email-templates/phone-bank-instructions/style.hbs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('babel/register'); 3 | require(process.argv[2]); -------------------------------------------------------------------------------- /.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaVersion": 6, 3 | "libs": [ 4 | "browser", 5 | "jquery" 6 | ] 7 | } -------------------------------------------------------------------------------- /vendor/dante/bin/socksify: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/bin/socksify -------------------------------------------------------------------------------- /src/frontend/index/development.json: -------------------------------------------------------------------------------- 1 | { 2 | "extra_head": "" 3 | } -------------------------------------------------------------------------------- /vendor/dante/include/socks.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/include/socks.h -------------------------------------------------------------------------------- /vendor/dante/lib/libsocks.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/lib/libsocks.a -------------------------------------------------------------------------------- /vendor/dante/lib/libdsocks.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/lib/libdsocks.so -------------------------------------------------------------------------------- /src/backend/email-templates/event-create-confirmation/style.hbs: -------------------------------------------------------------------------------- 1 | ul { 2 | list-style-type: none; 3 | padding-left: 0; 4 | } -------------------------------------------------------------------------------- /vendor/dante/lib/libsocks.so.0.1.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/lib/libsocks.so.0.1.1 -------------------------------------------------------------------------------- /vendor/dante/share/man/man1/socksify.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/vendor/dante/share/man/man1/socksify.1 -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/icons.png -------------------------------------------------------------------------------- /src/backend/bsd-instance.js: -------------------------------------------------------------------------------- 1 | import BSD from './bsd'; 2 | 3 | const BSDClient = new BSD(process.env.BSD_HOST, process.env.BSD_API_ID, process.env.BSD_API_SECRET); 4 | 5 | export default BSDClient -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/img/logo.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/icons.png -------------------------------------------------------------------------------- /webpack/babelRelayPlugin.js: -------------------------------------------------------------------------------- 1 | var getbabelRelayPlugin = require('babel-relay-plugin'); 2 | var schema = require('/tmp/schema.json'); 3 | 4 | module.exports = getbabelRelayPlugin(schema.data); 5 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/icons_hidpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/icons_hidpi.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/img/github-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/img/github-top.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/img/header-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/img/header-bg.png -------------------------------------------------------------------------------- /vendor/dante/socks.conf.template: -------------------------------------------------------------------------------- 1 | route { 2 | from: 0.0.0.0/0 to: %PROXIMO_MASK% via: %PROXIMO_HOST% port = 1080 3 | proxyprotocol: socks_v5 4 | method: username 5 | command: connect 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/assets/sample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/old/assets/sample.jpg -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/icons_hidpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/icons_hidpi.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/arrow.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/close.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/lock.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/link/images/anchor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/link/images/anchor.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/img/navigation-tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/img/navigation-tip.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/refresh.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/spinner.gif -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/img/header-separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/img/header-separator.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/close.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/lock.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/lock-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/lock-open.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/link/images/hidpi/anchor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/link/images/hidpi/anchor.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/refresh.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/about/dialogs/logo_ckeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/about/dialogs/logo_ckeditor.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/icons/blockquote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/icons/blockquote.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/assets/inlineall/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/old/assets/inlineall/logo.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/lock-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/skins/moono/images/hidpi/lock-open.png -------------------------------------------------------------------------------- /src/frontend/components/InfoHeader.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BernieText} from './styles/bernie-css'; 3 | export default function({content}) { 4 | return ( 5 |

{content}

6 | ); 7 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/icons/hidpi/blockquote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/icons/hidpi/blockquote.png -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/dialog/dialogDefinition.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.eot -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.ttf -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/al3x/ground-control/master/src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.woff -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | db: 2 | image: mdillon/postgis 3 | environment: 4 | - POSTGRES_PASSWORD= 5 | - POSTGRES_USER=postgres 6 | - POSTGRES_DBNAME=ground_control 7 | ports: 8 | - 5432 9 | ports: 10 | - 5432:5432 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | npm-debug.log 4 | src/backend/data/schema.graphql 5 | src/backend/data/schema.json 6 | rethinkdb_data 7 | src/frontend/public/js 8 | src/frontend/public/index.html 9 | *-compiled.js 10 | *-compiled.js.map 11 | -------------------------------------------------------------------------------- /Procfile.dev: -------------------------------------------------------------------------------- 1 | graphql: nodemon -e js -w ./src/backend --exec ./run -- ./src/backend/server.js 2 | webpack: ./run ./webpack/server.js 3 | postgres: postgres -D /usr/local/var/postgres 4 | worker: nodemon -e js -w ./src/jobs --exec ./run -- ./src/jobs/app.js 5 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCFormField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export default class GCFormField extends React.Component { 3 | floatingLabelText() { 4 | return this.props.floatingLabelText === false ? null : this.props.floatingLabelText || this.props.label; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/jobs/jobs.json: -------------------------------------------------------------------------------- 1 | { 2 | "jobs": [ 3 | { 4 | "cron": "00 */10 * * * *", 5 | "job": "./jobs/bsd-assigned-calls-ttl.js" 6 | }, 7 | { 8 | "cron": "*/5 * * * * *", 9 | "job": "./jobs/refresh-group-memberships.js" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/backend/data/migrations/20151219155318_add_is_primary_index_to_phones.js: -------------------------------------------------------------------------------- 1 | 2 | exports.up = function(knex, Promise) { 3 | return knex.schema.table('bsd_phones', function(table) { 4 | table.index('is_primary') 5 | }) 6 | }; 7 | 8 | exports.down = function(knex, Promise) { 9 | 10 | }; 11 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ar.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ar', { 6 | toolbar: 'اقتباس' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/cs.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'cs', { 6 | toolbar: 'Citace' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/eo.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'eo', { 6 | toolbar: 'Citaĵo' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/es.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'es', { 6 | toolbar: 'Cita' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/fi.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'fi', { 6 | toolbar: 'Lainaus' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/fr.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'fr', { 6 | toolbar: 'Citation' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/gl.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'gl', { 6 | toolbar: 'Cita' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ja.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ja', { 6 | toolbar: 'ブロック引用文' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ka.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ka', { 6 | toolbar: 'ციტატა' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ko.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ko', { 6 | toolbar: '인용 단락' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/lt.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'lt', { 6 | toolbar: 'Citata' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/pl.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'pl', { 6 | toolbar: 'Cytat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ro.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ro', { 6 | toolbar: 'Citat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ru.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ru', { 6 | toolbar: 'Цитата' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sk.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sk', { 6 | toolbar: 'Citácia' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sl.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sl', { 6 | toolbar: 'Citat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sq.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sq', { 6 | toolbar: 'Citatet' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/uk.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'uk', { 6 | toolbar: 'Цитата' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/zh.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'zh', { 6 | toolbar: '引用段落' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/af.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'af', { 6 | toolbar: 'Sitaatblok' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/bg.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'bg', { 6 | toolbar: 'Блок за цитат' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ca.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ca', { 6 | toolbar: 'Bloc de cita' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/cy.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'cy', { 6 | toolbar: 'Dyfyniad bloc' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/da.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'da', { 6 | toolbar: 'Blokcitat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/de.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'de', { 6 | toolbar: 'Zitatblock' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/en.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'en', { 6 | toolbar: 'Block Quote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/et.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'et', { 6 | toolbar: 'Blokktsitaat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/fa.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'fa', { 6 | toolbar: 'بلوک نقل قول' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/fo.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'fo', { 6 | toolbar: 'Blockquote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/he.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'he', { 6 | toolbar: 'בלוק ציטוט' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/hi.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'hi', { 6 | toolbar: 'ब्लॉक-कोट' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/hr.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'hr', { 6 | toolbar: 'Blockquote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/hu.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'hu', { 6 | toolbar: 'Idézet blokk' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/id.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'id', { 6 | toolbar: 'Kutipan Blok' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/is.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'is', { 6 | toolbar: 'Inndráttur' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/it.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'it', { 6 | toolbar: 'Citazione' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/lv.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'lv', { 6 | toolbar: 'Bloka citāts' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/mn.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'mn', { 6 | toolbar: 'Ишлэл хэсэг' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/nb.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'nb', { 6 | toolbar: 'Blokksitat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/nl.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'nl', { 6 | toolbar: 'Citaatblok' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/no.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'no', { 6 | toolbar: 'Blokksitat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/pt-br.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'pt-br', { 6 | toolbar: 'Citação' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/si.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'si', { 6 | toolbar: 'උද්ධෘත කොටස' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sv.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sv', { 6 | toolbar: 'Blockcitat' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/th.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'th', { 6 | toolbar: 'Block Quote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/tr.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'tr', { 6 | toolbar: 'Blok Oluştur' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/tt.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'tt', { 6 | toolbar: 'Өземтә блогы' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ug.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ug', { 6 | toolbar: 'بۆلەك نەقىل' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/zh-cn.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'zh-cn', { 6 | toolbar: '块引用' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/el.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'el', { 6 | toolbar: 'Περιοχή Παράθεσης' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/en-au.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'en-au', { 6 | toolbar: 'Block Quote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/en-ca.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'en-ca', { 6 | toolbar: 'Block Quote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/en-gb.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'en-gb', { 6 | toolbar: 'Block Quote' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/eu.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'eu', { 6 | toolbar: 'Aipamen blokea' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/fr-ca.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'fr-ca', { 6 | toolbar: 'Citation' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/km.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'km', { 6 | toolbar: 'ប្លក់​ពាក្យ​សម្រង់' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/pt.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'pt', { 6 | toolbar: 'Bloco de citação' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/vi.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'vi', { 6 | toolbar: 'Khối trích dẫn' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Font license info 2 | 3 | 4 | ## Font Awesome 5 | 6 | Copyright (C) 2012 by Dave Gandy 7 | 8 | Author: Dave Gandy 9 | License: SIL () 10 | Homepage: http://fortawesome.github.com/Font-Awesome/ 11 | -------------------------------------------------------------------------------- /src/backend/log.js: -------------------------------------------------------------------------------- 1 | import Minilog from 'minilog'; 2 | 3 | Minilog.suggest.deny(/.*/, process.env.NODE_ENV === 'development' ? 'debug' : 'info') 4 | 5 | Minilog.enable() 6 | .pipe(Minilog.backends.console.formatWithStack) 7 | .pipe(Minilog.backends.console) 8 | 9 | const log = Minilog('backend'); 10 | export default log; -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/bn.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'bn', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/bs.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'bs', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/gu.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'gu', { 6 | toolbar: 'બ્લૉક-કોટ, અવતરણચિહ્નો' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/mk.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'mk', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ms.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ms', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sr.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sr', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/ku.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'ku', { 6 | toolbar: 'بەربەستکردنی ووتەی وەرگیراو' 7 | } ); 8 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/blockquote/lang/sr-latn.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.plugins.setLang( 'blockquote', 'sr-latn', { 6 | toolbar: 'Block Quote' // MISSING 7 | } ); 8 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | WEBPACK_PORT=3000 3 | WEBPACK_PROXY_PORT=8090 4 | APP_HOST=localhost 5 | PORT=8090 6 | BSD_HOST=bernietest.bsd.net 7 | BSD_API_ID=ground-control 8 | BSD_API_SECRET=0cd514daf066ddc438930f86388a42a5e5eb667d 9 | SESSION_SECRET=bigbadsecretforuseindev 10 | DATABASE_URL=postgres://ground_control:@localhost:5432/ground_control -------------------------------------------------------------------------------- /src/frontend/components/NotFound.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BernieTheme} from './styles/bernie-theme'; 3 | import {BernieColors, BernieText} from './styles/bernie-css'; 4 | 5 | export default class NotFound extends React.Component { 6 | render() { 7 | return ( 8 |
9 | Nothing to see here... 10 |
11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /src/frontend/components/Unauthorized.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BernieTheme} from './styles/bernie-theme'; 3 | import {BernieColors, BernieText} from './styles/bernie-css'; 4 | 5 | export default class Unauthorized extends React.Component { 6 | render() { 7 | return ( 8 |
9 | You don't have access to that. 10 |
11 | ) 12 | } 13 | } -------------------------------------------------------------------------------- /src/backend/data/migrations/20151222165715_add_completed_to_calls.js: -------------------------------------------------------------------------------- 1 | 2 | exports.up = function(knex, Promise) { 3 | return knex.schema.table('bsd_calls', function(table) { 4 | table.boolean('completed') 5 | }) 6 | }; 7 | 8 | exports.down = function(knex, Promise) { 9 | return knex.schema.table('bsd_calls', function(table) { 10 | table.dropColumn('completed') 11 | }) 12 | }; 13 | -------------------------------------------------------------------------------- /webpack/schemaPlugin.js: -------------------------------------------------------------------------------- 1 | function apply(options, compiler) { 2 | compiler.plugin('compile', function(params) { 3 | require('babel/register')({ 4 | optional: ['es7.asyncFunctions'] 5 | }); 6 | require('../src/backend/data/writeSchema')(); 7 | }); 8 | } 9 | 10 | module.exports = function(options) { 11 | return { 12 | apply: apply.bind(this, options) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCSubmitButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TextField} from 'material-ui'; 3 | import {RaisedButton} from 'material-ui'; 4 | 5 | export default class GCSubmitButton extends React.Component { 6 | render() { 7 | return 13 | } 14 | } -------------------------------------------------------------------------------- /src/backend/data/migrations/20151223084757_add_instructions_to_call_assignments.js: -------------------------------------------------------------------------------- 1 | 2 | exports.up = function(knex, Promise) { 3 | return knex.schema.table('bsd_call_assignments', function(table) { 4 | table.text('instructions').notNullable().defaultTo('') 5 | }) 6 | }; 7 | 8 | exports.down = function(knex, Promise) { 9 | return knex.schema.table('bsd_call_assignments', function(table) { 10 | table.dropColumn('instructions') 11 | }) 12 | }; 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "ecmaFeatures": { 4 | "jsx": true, 5 | "modules": true 6 | }, 7 | "env": { 8 | "browser": true, 9 | "node": true 10 | }, 11 | "rules": { 12 | "no-var": 1, 13 | "no-this-before-super": 2, 14 | "constructor-super": 1, 15 | "react/jsx-uses-react": 2, 16 | "react/jsx-uses-vars": 2, 17 | "react/react-in-jsx-scope": 2, 18 | "react/prefer-es6-class": 2, 19 | }, 20 | "plugins": [ 21 | "react" 22 | ] 23 | } -------------------------------------------------------------------------------- /src/frontend/components/volunteer-dashboard/EventEditor.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText} from './styles/bernie-css' 4 | import Radium from 'radium' 5 | import SideBarLayout from './SideBarLayout'; 6 | 7 | @Radium 8 | class EventEditor extends React.Component { 9 | render() { 10 | return ( 11 |
event editor
12 | ) 13 | } 14 | } 15 | 16 | export default Relay.createContainer(EventEditor, { 17 | fragments: { 18 | 19 | }, 20 | }); -------------------------------------------------------------------------------- /src/frontend/components/volunteer-dashboard/EventViewer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText} from './styles/bernie-css' 4 | import Radium from 'radium' 5 | import SideBarLayout from './SideBarLayout'; 6 | 7 | @Radium 8 | class EventViewer extends React.Component { 9 | render() { 10 | return ( 11 |
event viewer
12 | ) 13 | } 14 | } 15 | 16 | export default Relay.createContainer(EventViewer, { 17 | fragments: { 18 | 19 | }, 20 | }); -------------------------------------------------------------------------------- /src/frontend/components/forms/GCToggleField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Toggle} from 'material-ui'; 3 | import {BernieText, BernieColors} from '../styles/bernie-css' 4 | 5 | export default class GCToggleField extends React.Component { 6 | styles = { 7 | label: { 8 | ...BernieText.inputLabel 9 | }, 10 | selectedButton: { 11 | color: BernieColors.lightBlue, 12 | backgroundColor: BernieColors.blue 13 | }, 14 | } 15 | render() { 16 | return 19 | } 20 | } -------------------------------------------------------------------------------- /src/frontend/components/volunteer-dashboard/VolunteerEventsDashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText} from './styles/bernie-css' 4 | import Radium from 'radium' 5 | import SideBarLayout from './SideBarLayout'; 6 | 7 | @Radium 8 | class VolunteerEventsDashboard extends React.Component { 9 | render() { 10 | return ( 11 |
events dashboard content
12 | ) 13 | } 14 | } 15 | 16 | export default Relay.createContainer(VolunteerEventsDashboard, { 17 | fragments: { 18 | 19 | }, 20 | }); -------------------------------------------------------------------------------- /src/frontend/components/forms/GCTextField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TextField} from 'material-ui'; 3 | import {BernieText} from '../styles/bernie-css'; 4 | import GCFormField from './GCFormField'; 5 | 6 | export default class GCTextField extends GCFormField { 7 | render() { 8 | return { 14 | this.props.onChange(event.target.value) 15 | }} 16 | /> 17 | } 18 | } -------------------------------------------------------------------------------- /src/frontend/components/forms/GCPasswordField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TextField} from 'material-ui'; 3 | import {BernieText} from '../styles/bernie-css'; 4 | import GCFormField from './GCFormField'; 5 | 6 | export default class GCPasswordField extends GCFormField { 7 | render() { 8 | return {this.props.onChange(event.target.value)}} 15 | /> 16 | } 17 | } -------------------------------------------------------------------------------- /src/frontend/components/data/USTimeZones.js: -------------------------------------------------------------------------------- 1 | // modified from https://gist.github.com/ykessler/3349960#file-timezones 2 | 3 | export const USTimeZones = [ 4 | {"value":"US/Atlantic","name":"Puerto Rico (Atlantic)"}, 5 | {"value":"US/Eastern","name":"New York (Eastern)"}, 6 | {"value":"US/Central","name":"Chicago (Central)"}, 7 | {"value":"US/Mountain","name":"Denver (Mountain)"}, 8 | {"value":"US/MST","name":"Phoenix (MST)"}, 9 | {"value":"US/Pacific","name":"Los Angeles (Pacific)"}, 10 | {"value":"US/Alaska","name":"Anchorage (Alaska)"}, 11 | {"value":"Pacific/Honolulu","name":"Honolulu (Hawaii)"} 12 | ]; -------------------------------------------------------------------------------- /src/backend/bcrypt-promise.js: -------------------------------------------------------------------------------- 1 | import Promise from 'bluebird'; 2 | import bcrypt from 'bcrypt'; 3 | 4 | export function hash(password, salt) { 5 | salt = salt || 10 6 | return new Promise((resolve, reject) => { 7 | bcrypt.hash(password, salt, (err, hashedValue) => { 8 | if (err) return reject(err) 9 | resolve(hashedValue) 10 | }) 11 | }) 12 | } 13 | 14 | export function compare(expected, hashedValue) { 15 | return new Promise((resolve, reject) => { 16 | bcrypt.compare(expected, hashedValue, (err, res) => { 17 | if (err) return reject(err) 18 | resolve(res) 19 | }) 20 | }) 21 | } -------------------------------------------------------------------------------- /webpack/config.js: -------------------------------------------------------------------------------- 1 | var SchemaPlugin = require('./schemaPlugin') 2 | 3 | module.exports = { 4 | entry: './src/frontend/app.js', 5 | module: { 6 | loaders: [ 7 | { test: /\.json$/, loader: 'json'}, 8 | { test: /\.css$/, loader: "style!css" }, 9 | { 10 | exclude: /node_modules/, 11 | loader: 'babel', 12 | query: {stage: 0, plugins: ['./webpack/babelRelayPlugin']}, 13 | test: /\.js$/, 14 | } 15 | ] 16 | }, 17 | plugins: [ 18 | new SchemaPlugin() 19 | ], 20 | output: {filename: 'app.js', path: './src/frontend/public/js/'}, 21 | devtool: "#inline-source-map" 22 | } 23 | -------------------------------------------------------------------------------- /src/backend/data/knexfile.js: -------------------------------------------------------------------------------- 1 | if (typeof process.env.DATABASE_URL === 'undefined') 2 | require('dotenv').load({path: '../../../.env'}); 3 | require("babel/register"); 4 | var sharedConfig = { 5 | connection: process.env.DATABASE_URL, 6 | client: 'pg', 7 | migrations: { 8 | tableName: 'knex_migrations', 9 | directory: './migrations' 10 | } 11 | } 12 | 13 | var development = { 14 | seeds: { 15 | directory: './seeds/development' 16 | } 17 | }; 18 | 19 | var production = { 20 | seeds: { 21 | directory: './seeds/production' 22 | } 23 | }; 24 | 25 | Object.assign(development, sharedConfig); 26 | Object.assign(production, sharedConfig); 27 | 28 | module.exports = { 29 | development: development, 30 | production: production 31 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "css_prefix_text": "icon-", 4 | "css_use_suffix": false, 5 | "hinting": true, 6 | "units_per_em": 1000, 7 | "ascent": 850, 8 | "glyphs": [ 9 | { 10 | "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", 11 | "css": "trash-empty", 12 | "code": 59392, 13 | "src": "fontawesome" 14 | }, 15 | { 16 | "uid": "1c4068ed75209e21af36017df8871802", 17 | "css": "down-big", 18 | "code": 59393, 19 | "src": "fontawesome" 20 | }, 21 | { 22 | "uid": "95376bf082bfec6ce06ea1cda7bd7ead", 23 | "css": "up-big", 24 | "code": 59394, 25 | "src": "fontawesome" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /src/frontend/components/forms/GCPhoneField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TextField} from 'material-ui'; 3 | import {BernieText} from '../styles/bernie-css'; 4 | import GCFormField from './GCFormField'; 5 | 6 | export default class GCPhoneField extends GCFormField { 7 | 8 | render() { 9 | let phone = this.props.value 10 | let formattedValue = `(${phone.slice(0, 3)}) ${phone.slice(3,6)}-${phone.slice(6)}` 11 | return { 18 | let val = event.target.value.replace(/\D/g,'') 19 | this.props.onChange(val) 20 | }} 21 | /> 22 | } 23 | } -------------------------------------------------------------------------------- /src/frontend/components/styles/bernie-theme.js: -------------------------------------------------------------------------------- 1 | import {Styles, Utils} from 'material-ui'; 2 | import {BernieColors, BernieText} from './bernie-css'; 3 | 4 | export const BernieTheme = { 5 | spacing: Styles.Spacing, 6 | fontFamily: BernieText.default.fontFamily, 7 | 8 | palette: { 9 | primary1Color: BernieColors.blue, 10 | primary2Color: BernieColors.red, 11 | primary3Color: Styles.Colors.grey400, 12 | accent1Color: BernieColors.red, 13 | accent2Color: BernieColors.lightGray, 14 | accent3Color: Styles.Colors.grey500, 15 | textColor: BernieText.default.color, 16 | alternateTextColor: Styles.Colors.white, 17 | canvasColor: Styles.Colors.white, 18 | borderColor: BernieColors.lightGray, 19 | disabledColor: Utils.ColorManipulator.fade(Styles.Colors.darkBlack, 0.3), 20 | }, 21 | }; -------------------------------------------------------------------------------- /src/backend/data/migrations/20151222224835_make_ids_bigint.js: -------------------------------------------------------------------------------- 1 | 2 | exports.up = async function(knex, Promise) { 3 | await knex.schema.raw('ALTER TABLE bsd_assigned_calls ALTER id SET DATA TYPE bigint;'); 4 | await knex.schema.raw('ALTER TABLE bsd_audits ALTER id SET DATA TYPE bigint;'); 5 | await knex.schema.raw('ALTER TABLE bsd_call_assignments ALTER id SET DATA TYPE bigint;'); 6 | await knex.schema.raw('ALTER TABLE bsd_calls ALTER id SET DATA TYPE bigint;'); 7 | await knex.schema.raw('ALTER TABLE gc_bsd_groups ALTER id SET DATA TYPE bigint;'); 8 | await knex.schema.raw('ALTER TABLE gc_bsd_surveys ALTER id SET DATA TYPE bigint;'); 9 | await knex.schema.raw('ALTER TABLE users ALTER id SET DATA TYPE bigint;'); 10 | await knex.schema.raw('ALTER TABLE zip_codes ALTER id SET DATA TYPE bigint;'); 11 | }; 12 | 13 | exports.down = function(knex, Promise) { 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /src/frontend/BSD/BSDAdminSurveyWrapper.js: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCDateField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {DatePicker} from 'material-ui'; 3 | import {BernieText} from '../styles/bernie-css'; 4 | import moment from 'moment'; 5 | import GCFormField from './GCFormField' 6 | 7 | export default class GCDateField extends GCFormField { 8 | render() { 9 | let oldDate = moment(this.props.value).utcOffset(this.props.utcOffset); 10 | return { 15 | let newDate = moment(date).utcOffset(this.props.utcOffset); 16 | newDate.set('hour', oldDate.get('hour')) 17 | newDate.set('minute', oldDate.get('minute')) 18 | newDate.set('second', oldDate.get('second')) 19 | this.props.onChange(newDate.toDate()) 20 | }} 21 | /> 22 | } 23 | } -------------------------------------------------------------------------------- /src/frontend/mutations/EditEvents.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay'; 2 | 3 | export default class EditEvents extends Relay.Mutation { 4 | static fragments = { 5 | listContainer: () => Relay.QL` 6 | fragment on ListContainer { 7 | id 8 | } 9 | `, 10 | }; 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation{ editEvents } 15 | `; 16 | } 17 | 18 | getFatQuery() { 19 | return Relay.QL` 20 | fragment on EditEventsPayload { 21 | listContainer { 22 | id, 23 | events 24 | }, 25 | } 26 | `; 27 | } 28 | 29 | getConfigs() { 30 | return [{ 31 | type: 'FIELDS_CHANGE', 32 | fieldIDs: { 33 | listContainer: this.props.listContainer.id 34 | } 35 | }]; 36 | } 37 | 38 | getVariables() { 39 | return { 40 | events: this.props.events 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/backend/data/migrations/20151222230001_make_other_columns_bigint.js: -------------------------------------------------------------------------------- 1 | 2 | exports.up = async function(knex, Promise) { 3 | await knex.schema.raw('ALTER TABLE bsd_assigned_calls ALTER caller_id SET DATA TYPE bigint;'); 4 | await knex.schema.raw('ALTER TABLE bsd_assigned_calls ALTER call_assignment_id SET DATA TYPE bigint;'); 5 | await knex.schema.raw('ALTER TABLE bsd_call_assignments ALTER gc_bsd_survey_id SET DATA TYPE bigint;'); 6 | await knex.schema.raw('ALTER TABLE bsd_call_assignments ALTER gc_bsd_group_id SET DATA TYPE bigint;'); 7 | await knex.schema.raw('ALTER TABLE bsd_call_assignments ALTER gc_bsd_group_id SET DATA TYPE bigint;'); 8 | await knex.schema.raw('ALTER TABLE bsd_calls ALTER caller_id SET DATA TYPE bigint;'); 9 | await knex.schema.raw('ALTER TABLE bsd_calls ALTER call_assignment_id SET DATA TYPE bigint;'); 10 | }; 11 | 12 | exports.down = function(knex, Promise) { 13 | 14 | }; 15 | -------------------------------------------------------------------------------- /src/frontend/mutations/DeleteEvents.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay'; 2 | 3 | export default class DeleteEvents extends Relay.Mutation { 4 | static fragments = { 5 | listContainer: () => Relay.QL` 6 | fragment on ListContainer { 7 | id 8 | } 9 | `, 10 | }; 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation{ deleteEvents } 15 | `; 16 | } 17 | 18 | getFatQuery() { 19 | return Relay.QL` 20 | fragment on DeleteEventsPayload { 21 | listContainer { 22 | id, 23 | events 24 | }, 25 | } 26 | `; 27 | } 28 | 29 | getConfigs() { 30 | return [{ 31 | type: 'FIELDS_CHANGE', 32 | fieldIDs: { 33 | listContainer: this.props.listContainer.id 34 | } 35 | }]; 36 | } 37 | 38 | getVariables() { 39 | return { 40 | ids: this.props.eventIDs 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/sample_posteddata.php: -------------------------------------------------------------------------------- 1 |
 2 | 
 3 | -------------------------------------------------------------------------------------------
 4 |   CKEditor - Posted Data
 5 | 
 6 |   We are sorry, but your Web server does not support the PHP language used in this script.
 7 | 
 8 |   Please note that CKEditor can be used with any other server-side language than just PHP.
 9 |   To save the content created with CKEditor you need to read the POST data on the server
10 |   side and write it to a file or the database.
11 | 
12 |   Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
13 |   For licensing, see LICENSE.md or http://ckeditor.com/license
14 | -------------------------------------------------------------------------------------------
15 | 
16 | 
*/ include "assets/posteddata.php"; ?> 17 | -------------------------------------------------------------------------------- /src/backend/data/writeSchema.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env babel-node --optional es7.asyncFunctions 2 | 3 | import fs from 'fs'; 4 | import path from 'path'; 5 | import log from '../log'; 6 | import { Schema } from './schema'; 7 | import { graphql } from 'graphql'; 8 | import { introspectionQuery, printSchema } from 'graphql/utilities'; 9 | 10 | export default async function writeSchema() { 11 | await async function() { 12 | let result = await (graphql(Schema, introspectionQuery)); 13 | 14 | if (result.errors) { 15 | log.error( 16 | 'ERROR introspecting schema: ', 17 | JSON.stringify(result.errors, null, 2) 18 | ); 19 | } else { 20 | fs.writeFileSync( 21 | path.join('/', 'tmp', 'schema.json'), 22 | JSON.stringify(result, null, 2) 23 | ); 24 | } 25 | }(); 26 | 27 | fs.writeFileSync( 28 | path.join('/', 'tmp', 'schema.graphql'), 29 | printSchema(Schema) 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/lib/codemirror/show-hint.css: -------------------------------------------------------------------------------- 1 | .CodeMirror-hints { 2 | position: absolute; 3 | z-index: 10; 4 | overflow: hidden; 5 | list-style: none; 6 | 7 | margin: 0; 8 | padding: 2px; 9 | 10 | -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 11 | -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); 12 | box-shadow: 2px 3px 5px rgba(0,0,0,.2); 13 | border-radius: 3px; 14 | border: 1px solid silver; 15 | 16 | background: white; 17 | font-size: 90%; 18 | font-family: monospace; 19 | 20 | max-height: 20em; 21 | overflow-y: auto; 22 | } 23 | 24 | .CodeMirror-hint { 25 | margin: 0; 26 | padding: 0 4px; 27 | border-radius: 2px; 28 | max-width: 19em; 29 | overflow: hidden; 30 | white-space: pre; 31 | color: black; 32 | cursor: pointer; 33 | } 34 | 35 | li.CodeMirror-hint-active { 36 | background: #08f; 37 | color: white; 38 | } 39 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCTimeField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TimePicker} from 'material-ui'; 3 | import {BernieText} from '../styles/bernie-css'; 4 | import moment from 'moment'; 5 | import GCFormField from './GCFormField'; 6 | 7 | export default class GCTimeField extends GCFormField { 8 | render() { 9 | console.log(this.props.value) 10 | let time = moment(this.props.value).utcOffset(this.props.utcOffset).toDate() 11 | let oldDate = moment(this.props.value).utcOffset(this.props.utcOffset) 12 | return { 18 | console.log(time); 19 | let newDate = moment(time) 20 | newDate.set('year', oldDate.get('year')) 21 | newDate.set('month', oldDate.get('month')) 22 | newDate.set('date', oldDate.get('date')) 23 | this.props.onChange(newDate.toDate()) 24 | }} 25 | /> 26 | } 27 | } -------------------------------------------------------------------------------- /src/frontend/components/AdminCallAssignment.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText} from './styles/bernie-css'; 4 | import {Paper, List, ListItem} from 'material-ui'; 5 | import moment from 'moment'; 6 | 7 | export class AdminCallAssignment extends React.Component { 8 | render() { 9 | return ( 10 |
11 |
12 | {this.props.callAssignment.name} 13 |
14 |
15 |
16 | Using survey: {this.props.callAssignment.survey.fullURL}
17 | Using query: {this.props.callAssignment.query} 18 |
19 |
20 |
21 | ); 22 | } 23 | } 24 | 25 | export default Relay.createContainer(AdminCallAssignment, { 26 | fragments: { 27 | callAssignment: () => Relay.QL` 28 | fragment on CallAssignment { 29 | id 30 | name 31 | survey { 32 | fullURL 33 | } 34 | query 35 | } 36 | ` 37 | } 38 | }); -------------------------------------------------------------------------------- /webpack/server.js: -------------------------------------------------------------------------------- 1 | import WebpackDevServer from 'webpack-dev-server'; 2 | import path from 'path'; 3 | import webpack from 'webpack'; 4 | import express from 'express'; 5 | import config from './config' 6 | 7 | const port = process.env.WEBPACK_PORT 8 | config['output'] = { 9 | filename: 'app.js', 10 | path: '/' 11 | } 12 | let compiler = webpack(config); 13 | 14 | let connstring = `http://${process.env.APP_HOST||'localhost'}:${process.env.WEBPACK_PROXY_PORT}` 15 | 16 | console.log('Proxying requests to:',connstring) 17 | 18 | let app = new WebpackDevServer(compiler, { 19 | contentBase: '/js/', 20 | publicPath: '/js/', 21 | headers: { 'Access-Control-Allow-Origin': '*' }, 22 | proxy: { 23 | '*': `http://${process.env.APP_HOST}:${process.env.WEBPACK_PROXY_PORT}` 24 | }, 25 | stats: {colors: true}, 26 | }); 27 | 28 | const publicPath = path.resolve(__dirname, '../frontend/public'); 29 | app.use(express.static(publicPath)) 30 | app.listen(port, () => { 31 | console.log(`Webpack dev server is now running on http://localhost:${port}`); 32 | }); 33 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/lib/codemirror/neo.css: -------------------------------------------------------------------------------- 1 | /* neo theme for codemirror */ 2 | 3 | /* Color scheme */ 4 | 5 | .cm-s-neo.CodeMirror { 6 | background-color:#ffffff; 7 | color:#2e383c; 8 | line-height:1.4375; 9 | } 10 | .cm-s-neo .cm-comment {color:#75787b} 11 | .cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3} 12 | .cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a} 13 | .cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328} 14 | .cm-s-neo .cm-string {color:#b35e14} 15 | .cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65} 16 | 17 | 18 | /* Editor styling */ 19 | 20 | .cm-s-neo pre { 21 | padding:0; 22 | } 23 | 24 | .cm-s-neo .CodeMirror-gutters { 25 | border:none; 26 | border-right:10px solid transparent; 27 | background-color:transparent; 28 | } 29 | 30 | .cm-s-neo .CodeMirror-linenumber { 31 | padding:0; 32 | color:#e0e2e5; 33 | } 34 | 35 | .cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; } 36 | .cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; } 37 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCRadioButtonsField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {FlatButton, RadioButtonGroup, RadioButton} from 'material-ui'; 3 | import {BernieText, BernieColors} from '../styles/bernie-css' 4 | 5 | export default class GCRadioButtonsField extends React.Component { 6 | styles = { 7 | label: { 8 | paddingBottom: 10, 9 | ...BernieText.inputLabel, 10 | }, 11 | } 12 | 13 | renderChoices() { 14 | return Object.keys(this.props.choices).map((choice) => { 15 | let label = this.props.choices[choice] 16 | return ( 17 | 25 | ) 26 | }) 27 | } 28 | render() { 29 | return ( 30 |
31 |
{this.props.label}
32 | 33 | {this.renderChoices()} 34 | 35 |
36 | ) 37 | } 38 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/dialog/assets/my_dialog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | 6 | CKEDITOR.dialog.add( 'myDialog', function() { 7 | return { 8 | title: 'My Dialog', 9 | minWidth: 400, 10 | minHeight: 200, 11 | contents: [ 12 | { 13 | id: 'tab1', 14 | label: 'First Tab', 15 | title: 'First Tab', 16 | elements: [ 17 | { 18 | id: 'input1', 19 | type: 'text', 20 | label: 'Text Field' 21 | }, 22 | { 23 | id: 'select1', 24 | type: 'select', 25 | label: 'Select Field', 26 | items: [ 27 | [ 'option1', 'value1' ], 28 | [ 'option2', 'value2' ] 29 | ] 30 | } 31 | ] 32 | }, 33 | { 34 | id: 'tab2', 35 | label: 'Second Tab', 36 | title: 'Second Tab', 37 | elements: [ 38 | { 39 | id: 'button1', 40 | type: 'button', 41 | label: 'Button Field' 42 | } 43 | ] 44 | } 45 | ] 46 | }; 47 | } ); 48 | 49 | -------------------------------------------------------------------------------- /vendor/dante/lib/libdsocks.la: -------------------------------------------------------------------------------- 1 | # libdsocks.la - a libtool library file 2 | # Generated by libtool (GNU libtool) 2.4.2 3 | # 4 | # Please DO NOT delete this file! 5 | # It is necessary for linking the library. 6 | 7 | # The name that we can dlopen(3). 8 | dlname='libdsocks.so' 9 | 10 | # Names of this library. 11 | library_names='libdsocks.so libdsocks.so libdsocks.so' 12 | 13 | # The name of the static archive. 14 | old_library='' 15 | 16 | # Linker flags that can not go in dependency_libs. 17 | inherited_linker_flags='' 18 | 19 | # Libraries that this one depends upon. 20 | dependency_libs=' -L/usr/lib -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lcrypt -ldl' 21 | 22 | # Names of additional weak libraries provided by this library 23 | weak_library_names='' 24 | 25 | # Version information for libdsocks. 26 | current=0 27 | age=0 28 | revision=0 29 | 30 | # Is this an already installed library? 31 | installed=yes 32 | 33 | # Should we warn about portability when linking against -modules? 34 | shouldnotlink=no 35 | 36 | # Files to dlopen/dlpreopen 37 | dlopen='' 38 | dlpreopen='' 39 | 40 | # Directory that this library needs to be installed in: 41 | libdir='/app/vendor/lib' 42 | -------------------------------------------------------------------------------- /vendor/dante/lib/libsocks.la: -------------------------------------------------------------------------------- 1 | # libsocks.la - a libtool library file 2 | # Generated by libtool (GNU libtool) 2.4.2 3 | # 4 | # Please DO NOT delete this file! 5 | # It is necessary for linking the library. 6 | 7 | # The name that we can dlopen(3). 8 | dlname='libsocks.so.0' 9 | 10 | # Names of this library. 11 | library_names='libsocks.so.0.1.1 libsocks.so.0 libsocks.so' 12 | 13 | # The name of the static archive. 14 | old_library='libsocks.a' 15 | 16 | # Linker flags that can not go in dependency_libs. 17 | inherited_linker_flags='' 18 | 19 | # Libraries that this one depends upon. 20 | dependency_libs=' -L/usr/lib -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lcrypt -ldl' 21 | 22 | # Names of additional weak libraries provided by this library 23 | weak_library_names='' 24 | 25 | # Version information for libsocks. 26 | current=1 27 | age=1 28 | revision=1 29 | 30 | # Is this an already installed library? 31 | installed=yes 32 | 33 | # Should we warn about portability when linking against -modules? 34 | shouldnotlink=no 35 | 36 | # Files to dlopen/dlpreopen 37 | dlopen='' 38 | dlpreopen='' 39 | 40 | # Directory that this library needs to be installed in: 41 | libdir='/app/vendor/lib' 42 | -------------------------------------------------------------------------------- /src/frontend/mutations/SubmitCallSurvey.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay'; 2 | 3 | export default class SubmitCallSurvey extends Relay.Mutation { 4 | static fragments = { 5 | currentUser: () => Relay.QL` 6 | fragment on User { 7 | id 8 | } 9 | `, 10 | }; 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation{ submitCallSurvey } 15 | `; 16 | } 17 | 18 | getFatQuery() { 19 | return Relay.QL` 20 | fragment on SubmitCallSurveyPayload { 21 | currentUser { 22 | id, 23 | }, 24 | } 25 | `; 26 | } 27 | 28 | getConfigs() { 29 | return [{ 30 | type: 'FIELDS_CHANGE', 31 | fieldIDs: { 32 | currentUser: this.props.currentUser.id 33 | } 34 | }]; 35 | } 36 | 37 | getVariables() { 38 | return { 39 | completed: this.props.completed, 40 | callAssignmentId: this.props.callAssignmentId, 41 | intervieweeId: this.props.intervieweeId, 42 | leftVoicemail: this.props.leftVoicemail, 43 | sentText: this.props.sentText, 44 | reasonNotCompleted: this.props.reasonNotCompleted, 45 | surveyFieldValues: this.props.surveyFieldValues 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/backend/data/knex.js: -------------------------------------------------------------------------------- 1 | import knexFactory from 'knex'; 2 | import knexfile from './knexfile'; 3 | 4 | let knex = null; 5 | if (!process.env.NO_DB) { 6 | knex = knexFactory(knexfile[process.env.NODE_ENV]) 7 | knex.count = async function(query, col) { 8 | let results = await query.count(col).first() 9 | return results.count 10 | } 11 | 12 | knex.insertAndFetch = async function(table, values, {idField, transaction}={}) { 13 | let timestamp = new Date() 14 | if (!values.length) 15 | values = [values] 16 | values = values.map((val) => { 17 | return { 18 | modified_dt: timestamp, 19 | create_dt: timestamp, 20 | ...val 21 | } 22 | }) 23 | idField = idField || 'id' 24 | let query = knex(table).insert(values).returning(idField); 25 | if (transaction) 26 | query = query.transacting(transaction) 27 | let ids = await query 28 | 29 | query = knex(table).whereIn(idField, ids) 30 | if (transaction) 31 | query = query.transacting(transaction) 32 | 33 | let returnedObjects = await query 34 | if (returnedObjects.length === 1) 35 | return returnedObjects[0] 36 | return returnedObjects 37 | } 38 | } 39 | export default knex; -------------------------------------------------------------------------------- /src/backend/email-templates/header.hbs: -------------------------------------------------------------------------------- 1 | 2 | 41 | 42 |

Bernie Sanders for President

43 |
-------------------------------------------------------------------------------- /src/frontend/mutations/CreateCallAssignment.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay'; 2 | 3 | export default class CreateCallAssignment extends Relay.Mutation { 4 | static fragments = { 5 | listContainer: () => Relay.QL` 6 | fragment on ListContainer { 7 | id 8 | } 9 | `, 10 | }; 11 | 12 | getMutation() { 13 | return Relay.QL` 14 | mutation{ createCallAssignment } 15 | `; 16 | } 17 | 18 | getFatQuery() { 19 | return Relay.QL` 20 | fragment on CreateCallAssignmentPayload { 21 | listContainer { 22 | id, 23 | callAssignments 24 | }, 25 | } 26 | `; 27 | } 28 | 29 | getConfigs() { 30 | return [{ 31 | type: 'FIELDS_CHANGE', 32 | fieldIDs: { 33 | listContainer: this.props.listContainer.id 34 | } 35 | }]; 36 | } 37 | 38 | getVariables() { 39 | return { 40 | name: this.props.name, 41 | callerGroupId: this.props.callerGroupId, 42 | intervieweeGroup: this.props.intervieweeGroup, 43 | surveyId: this.props.surveyId, 44 | renderer: this.props.renderer, 45 | processors: this.props.processors, 46 | instructions: this.props.instructions 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /setup-osx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var childProcess = require('child_process') 4 | console.log("Installing PostgreSQL...") 5 | childProcess.execSync('brew install postgres') 6 | 7 | console.log("Starting up database...") 8 | childProcess.exec('postgres -D /usr/local/var/postgres') 9 | 10 | setTimeout(function() { 11 | try { 12 | childProcess.execSync('dropdb ground_control') 13 | } catch (ex) { 14 | console.warn("dropdb did not run. This is probably because the database does not already exist, which is fine.") 15 | } 16 | try { 17 | childProcess.execSync('createdb ground_control') 18 | } catch(ex) { 19 | console.warn("createdb did not run. This is probably because the database already exists, which is fine."); 20 | } 21 | try { 22 | childProcess.execSync('psql -c "CREATE ROLE ground_control WITH LOGIN SUPERUSER;" -d ground_control') 23 | } catch (ex) { 24 | console.warn("ground_control role not created. This is probably because the role already exists, which is fine."); 25 | } 26 | 27 | console.log("Seeding data...") 28 | childProcess.execSync('npm run migrate'); 29 | childProcess.execSync('npm run seed'); 30 | console.log("Done!") 31 | }, 2000) 32 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/lib/codemirror/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 by Marijn Haverbeke and others 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /setup-linux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var childProcess = require('child_process') 4 | var connstring = ' -h 127.0.0.1 -p 5432 -U postgres -w ' 5 | 6 | console.log("Installing PostgreSQL...") 7 | childProcess.execSync('docker-compose kill db') 8 | childProcess.execSync('docker-compose rm -f db') 9 | childProcess.execSync('docker-compose up -d db') 10 | 11 | setTimeout(function() { 12 | try { 13 | childProcess.execSync('dropdb'+connstring+'ground_control') 14 | } catch (ex) { 15 | console.warn("dropdb did not run. This is probably because the database does not already exist, which is fine.") 16 | } 17 | try { 18 | childProcess.execSync('createdb'+connstring+'ground_control') 19 | } catch(ex) { 20 | console.warn("createdb did not run. This is probably because the database already exists, which is fine."); 21 | } 22 | try { 23 | childProcess.execSync('psql'+connstring+' -c "CREATE ROLE ground_control WITH LOGIN SUPERUSER;" -d ground_control') 24 | } catch (ex) { 25 | console.warn("ground_control role not created. This is probably because the role already exists, which is fine."); 26 | } 27 | 28 | console.log("Seeding data...") 29 | childProcess.execSync('npm run seed'); 30 | console.log("Done!") 31 | }, 20000) 32 | -------------------------------------------------------------------------------- /src/frontend/components/CallAssignmentsDashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText, BernieColors} from './styles/bernie-css' 4 | import Radium from 'radium' 5 | import SideBarLayout from './SideBarLayout'; 6 | import CallAssignmentList from './CallAssignmentList'; 7 | import CallAssignment from './CallAssignment'; 8 | import TopNav from './TopNav'; 9 | 10 | @Radium 11 | class CallAssignmentsDashboard extends React.Component { 12 | render() { 13 | return ( 14 |
15 | 32 | {this.props.children} 33 |
34 | ) 35 | } 36 | } 37 | 38 | export default Relay.createContainer(CallAssignmentsDashboard, { 39 | fragments: { 40 | currentUser: () => Relay.QL` 41 | fragment on User { 42 | callsMade 43 | } 44 | ` 45 | } 46 | }) -------------------------------------------------------------------------------- /src/backend/maestro.js: -------------------------------------------------------------------------------- 1 | import requestPromise from 'request-promise'; 2 | import log from './log'; 3 | 4 | export default class Maestro { 5 | constructor(customerUID, secretToken, host, fakeCall) { 6 | this.customerUID = customerUID; 7 | this.secretToken = secretToken; 8 | this.host = host; 9 | this.fakeCall = fakeCall; 10 | } 11 | 12 | createConferenceCall(name, maxReservations, startDate, duration, {contactEmail=null, greenroom=null, recording=null, backgroundMusic=null}={}) { 13 | 14 | let postParams = {contactEmail, greenroom, recording, backgroundMusic} 15 | 16 | Object.keys(postParams).forEach((key) => typeof postParams[key] === 'undefined' ? delete postParams[key] : true); 17 | 18 | Object.assign(postParams, { 19 | customer: this.customerUID, 20 | key: this.secretToken, 21 | name: name, 22 | reservationCount: 1, 23 | estimatedCallers1: maxReservations, 24 | startDate1: startDate, 25 | duration1: duration, 26 | type: 'json' 27 | }); 28 | 29 | let options = { 30 | uri: this.host + '/createConferenceReserved', 31 | method: 'POST', 32 | form: postParams, 33 | json: true 34 | } 35 | 36 | if (this.fakeCall) { 37 | log.debug('Would have made request: ' + JSON.stringify(options)) 38 | return { value: { UID: 'test-uid' } } 39 | } 40 | return requestPromise(options); 41 | } 42 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/assets/uilanguages/languages.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | var CKEDITOR_LANGS=function(){var c={af:"Afrikaans",ar:"Arabic",bg:"Bulgarian",bn:"Bengali/Bangla",bs:"Bosnian",ca:"Catalan",cs:"Czech",cy:"Welsh",da:"Danish",de:"German",el:"Greek",en:"English","en-au":"English (Australia)","en-ca":"English (Canadian)","en-gb":"English (United Kingdom)",eo:"Esperanto",es:"Spanish",et:"Estonian",eu:"Basque",fa:"Persian",fi:"Finnish",fo:"Faroese",fr:"French","fr-ca":"French (Canada)",gl:"Galician",gu:"Gujarati",he:"Hebrew",hi:"Hindi",hr:"Croatian",hu:"Hungarian",id:"Indonesian", 6 | is:"Icelandic",it:"Italian",ja:"Japanese",ka:"Georgian",km:"Khmer",ko:"Korean",ku:"Kurdish",lt:"Lithuanian",lv:"Latvian",mk:"Macedonian",mn:"Mongolian",ms:"Malay",nb:"Norwegian Bokmal",nl:"Dutch",no:"Norwegian",pl:"Polish",pt:"Portuguese (Portugal)","pt-br":"Portuguese (Brazil)",ro:"Romanian",ru:"Russian",si:"Sinhala",sk:"Slovak",sq:"Albanian",sl:"Slovenian",sr:"Serbian (Cyrillic)","sr-latn":"Serbian (Latin)",sv:"Swedish",th:"Thai",tr:"Turkish",tt:"Tatar",ug:"Uighur",uk:"Ukrainian",vi:"Vietnamese", 7 | zh:"Chinese Traditional","zh-cn":"Chinese Simplified"},b=[],a;for(a in CKEDITOR.lang.languages)b.push({code:a,name:c[a]||a});b.sort(function(a,b){return a.name 24 | ) 25 | } 26 | } 27 | 28 | // As far as I know, there is no dynamic way to generate relay fragments, so we just need to add them here when we have new survey renderers 29 | export default Relay.createContainer(BSDSurveyRenderer, { 30 | fragments: { 31 | survey: () => Relay.QL` 32 | fragment on Survey { 33 | renderer 34 | ${BSDSurvey.getFragment('survey')} 35 | ${BSDPhonebankRSVPSurey.getFragment('survey')} 36 | } 37 | `, 38 | interviewee: () => Relay.QL` 39 | fragment on Person { 40 | ${BSDSurvey.getFragment('interviewee')} 41 | ${BSDPhonebankRSVPSurey.getFragment('interviewee')} 42 | } 43 | ` 44 | } 45 | }) -------------------------------------------------------------------------------- /bin/proximo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${PROXIMO_URL}" == "" ]; then 4 | echo "You must first install Proximo:" 5 | echo "heroku addons:add proximo:development" 6 | fi 7 | 8 | DANTE_DIR="$(dirname $(dirname $(readlink -f $0)))/vendor/dante" 9 | 10 | PROXIMO_LEADER=${PROXIMO_URL%%@*} 11 | PROXIMO_AUTH=$(echo $PROXIMO_LEADER | cut -d/ -f3) 12 | PROXIMO_USERNAME=${PROXIMO_AUTH%%:*} 13 | PROXIMO_PASSWORD=${PROXIMO_AUTH#*:} 14 | PROXIMO_HOST=${PROXIMO_URL#*@} 15 | PROXIMO_HOST=$(echo $PROXIMO_HOST | sed -e 's/proxy-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)-\([0-9]*\)\.proximo.io/\1\.\2\.\3\.\4/g') 16 | PROXIMO_MASK=${PROXIMO_MASK:-0.0.0.0/0} 17 | 18 | export SOCKS_CONF="${DANTE_DIR}/socks.conf" 19 | export SOCKS_LIBDIR="${DANTE_DIR}/lib" 20 | export SOCKS_USERNAME="${PROXIMO_USERNAME}" 21 | export SOCKS_PASSWORD="${PROXIMO_PASSWORD}" 22 | export SOCKS_LIBRARY="${DANTE_DIR}/lib/libdsocks.so" 23 | export SOCKS_USEFULLPATH="true" 24 | 25 | echo "Proxying traffic bound for ${PROXIMO_MASK} via Proximo host ${PROXIMO_HOST}:1080" 26 | 27 | OIFS=$IFS 28 | IFS="," 29 | 30 | rm -f $SOCKS_CONF 31 | 32 | for PROXIMO_MASK_PART in $PROXIMO_MASK; do 33 | PROXIMO_MASK_ESCAPED=${PROXIMO_MASK_PART/\//\\/} 34 | cat "${SOCKS_CONF}.template" | \ 35 | sed -e "s/%PROXIMO_HOST%/${PROXIMO_HOST}/g" \ 36 | -e "s/%PROXIMO_MASK%/${PROXIMO_MASK_ESCAPED}/g" \ 37 | >> $SOCKS_CONF 38 | done 39 | 40 | chmod +x ${DANTE_DIR}/bin/* 41 | 42 | exec ${DANTE_DIR}/bin/socksify $* 43 | -------------------------------------------------------------------------------- /src/backend/email-templates/event-create-confirmation/text.hbs: -------------------------------------------------------------------------------- 1 | Thank you for creating an event for the Bernie Sanders campaign! The details of the event you submitted are included below. To manage the events you have created, please visit https://secure.berniesanders.com/page/event/myevents 2 | 3 | Your username on berniesanders.com is {{event.cons_email}} 4 | {{#if user.password}} 5 | Your temporary password is {{user.password}} 6 | IMPORTANT: Please change your password the first time you log in. 7 | {{/if}} 8 | 9 | {{event.name}} 10 | 11 | Event Description 12 | {{event.event_type_name}} 13 | {{{event.description}}} 14 | 15 | Event Venue 16 | {{event.venue_name}}, capacity {{event.capacity}} 17 | 18 | {{event.venue_addr1}} {{event.venue_city}} {{event.venue_state_cd}} {{event.venue_zip}} 19 | {{event.venue_directions}} 20 | 21 | Event Time 22 | {{event.start_time.h}}:{{event.start_time.i}} {{event.start_time.a}} {{event.start_tz}}, 23 | Duration: {{event.duration_num}} 24 | {{#ifCond event.duration_unit '==' 1}}minute{{/ifCond}}{{#ifCond event.duration_unit '==' 60}}hour{{/ifCond}}{{#ifCond event.duration_unit '==' 1440}}day{{/ifCond}}{{#ifCond event.duration_num '>' 1}}s{{/ifCond}} 25 | Event Date{{#ifCond event.event_dates.length '>' 1}}s{{/ifCond}} 26 | {{#each event.event_dates}} 27 | {{this.date}} 28 | {{/each}} 29 | 30 | 31 | {{#if event.attendee_volunteer_show}} 32 | Volunteer Message 33 | {{event.attendee_volunteer_message}} 34 | {{/if}} -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | 6 | CKEDITOR.editorConfig = function( config ) { 7 | // Define changes to default configuration here. 8 | // For complete reference see: 9 | // http://docs.ckeditor.com/#!/api/CKEDITOR.config 10 | 11 | // The toolbar groups arrangement, optimized for a single toolbar row. 12 | config.toolbarGroups = [ 13 | { name: 'document', groups: [ 'mode', 'document', 'doctools' ] }, 14 | { name: 'clipboard', groups: [ 'clipboard', 'undo' ] }, 15 | { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] }, 16 | { name: 'forms' }, 17 | { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] }, 18 | { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ] }, 19 | { name: 'links' }, 20 | { name: 'insert' }, 21 | { name: 'styles' }, 22 | { name: 'colors' }, 23 | { name: 'tools' }, 24 | { name: 'others' }, 25 | { name: 'about' } 26 | ]; 27 | 28 | // The default plugins included in the basic setup define some buttons that 29 | // are not needed in a basic editor. They are removed here. 30 | config.removeButtons = 'Cut,Copy,Paste,Undo,Redo,Anchor,Subscript,Superscript'; 31 | 32 | // Dialog windows are also simplified. 33 | config.removeDialogTabs = 'link:advanced'; 34 | 35 | config.extraPlugins = 'blockquote'; 36 | }; 37 | -------------------------------------------------------------------------------- /src/frontend/components/CallAssignmentList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {List, ListItem, Styles} from 'material-ui'; 4 | import moment from 'moment'; 5 | 6 | export class CallAssignmentList extends React.Component { 7 | static propTypes = { 8 | subheader: React.PropTypes.string, 9 | onSelect: React.PropTypes.func, 10 | } 11 | 12 | renderCallAssignments() { 13 | return this.props.callAssignments.edges.map(assignment => { 14 | let node = assignment.node; 15 | let s = node.callsMade === 1 ? '' : 's' 16 | let primaryText = node.name 17 | let secondaryText = `${node.callsMade} call${s} made by everyone` 18 | return ( 19 | this.props.onSelect(node.id)}/> 24 | ) 25 | } 26 | ); 27 | } 28 | 29 | render() { 30 | return ( 31 | 32 | {this.renderCallAssignments()} 33 | 34 | ); 35 | } 36 | } 37 | 38 | export default Relay.createContainer(CallAssignmentList, { 39 | fragments: { 40 | callAssignments: () => Relay.QL` 41 | fragment on CallAssignmentConnection { 42 | edges { 43 | node { 44 | id 45 | name 46 | callsMade 47 | } 48 | } 49 | } 50 | ` 51 | } 52 | }); 53 | 54 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCDateTimeField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BernieText} from '../styles/bernie-css'; 3 | import moment from 'moment'; 4 | import GCFormField from './GCFormField'; 5 | import Kronos from 'react-kronos' 6 | 7 | export default class GCDateTimeField extends GCFormField { 8 | 9 | convertToTimezone(date, utcOffset) { 10 | return moment(moment(date).utcOffset(utcOffset).format("YYYY-MM-DD HH:mm:ss")) 11 | } 12 | 13 | convertFromTimezone(date, utcOffset) { 14 | let offsetDiff = date.utcOffset() - (moment.parseZone(utcOffset).utcOffset() - date.utcOffset()) 15 | return this.convertToTimezone(date, offsetDiff) 16 | } 17 | 18 | render() { 19 | let convertedDateTime = this.convertToTimezone(this.props.value, this.props.utcOffset) 20 | return ( 21 |
22 |
23 | { 27 | this.props.onChange(this.convertFromTimezone(newDate, this.props.utcOffset).toDate()) 28 | }} 29 | /> 30 |
31 |
32 | { 36 | this.props.onChange(this.convertFromTimezone(newDate, this.props.utcOffset).toDate()) 37 | }} 38 | /> 39 |
40 |
41 | ) 42 | } 43 | } -------------------------------------------------------------------------------- /src/frontend/components/AdminDashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {Styles} from 'material-ui'; 4 | import TopNav from './TopNav'; 5 | import {BernieTheme} from './styles/bernie-theme'; 6 | import {BernieColors} from './styles/bernie-css'; 7 | 8 | @Styles.ThemeDecorator(Styles.ThemeManager.getMuiTheme(BernieTheme)) 9 | class AdminDashboard extends React.Component { 10 | tabs = [ 11 | { 12 | value: '/admin/call-assignments', 13 | label: 'Call Assignments' 14 | }, 15 | { 16 | value: '/admin/events', 17 | label: 'Events' 18 | } 19 | ]; 20 | 21 | render() { 22 | return ( 23 |
24 | 37 | {this.props.children} 38 |
39 | ) 40 | } 41 | } 42 | 43 | // We only do this to auth protect this component. Otherwise it is unnecessary. 44 | export default Relay.createContainer(AdminDashboard, { 45 | fragments: { 46 | listContainer: () => Relay.QL` 47 | fragment on ListContainer { 48 | id 49 | } 50 | ` 51 | } 52 | }) -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/README.md: -------------------------------------------------------------------------------- 1 | CKEditor 4 2 | ========== 3 | 4 | Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. 5 | http://ckeditor.com - See LICENSE.md for license information. 6 | 7 | CKEditor is a text editor to be used inside web pages. It's not a replacement 8 | for desktop text editors like Word or OpenOffice, but a component to be used as 9 | part of web applications and websites. 10 | 11 | ## Documentation 12 | 13 | The full editor documentation is available online at the following address: 14 | http://docs.ckeditor.com 15 | 16 | ## Installation 17 | 18 | Installing CKEditor is an easy task. Just follow these simple steps: 19 | 20 | 1. **Download** the latest version from the CKEditor website: 21 | http://ckeditor.com. You should have already completed this step, but be 22 | sure you have the very latest version. 23 | 2. **Extract** (decompress) the downloaded file into the root of your website. 24 | 25 | **Note:** CKEditor is by default installed in the `ckeditor` folder. You can 26 | place the files in whichever you want though. 27 | 28 | ## Checking Your Installation 29 | 30 | The editor comes with a few sample pages that can be used to verify that 31 | installation proceeded properly. Take a look at the `samples` directory. 32 | 33 | To test your installation, just call the following page at your website: 34 | 35 | http:////samples/index.html 36 | 37 | For example: 38 | 39 | http://www.example.com/ckeditor/samples/index.html 40 | -------------------------------------------------------------------------------- /src/backend/email-templates/footer.hbs: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /src/frontend/components/SurveyRenderer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import BSDSurvey from './survey-renderers/BSDSurvey' 4 | import BSDPhonebankRSVPSurvey from './survey-renderers/BSDPhonebankRSVPSurvey' 5 | 6 | class SurveyRenderer extends React.Component { 7 | static propTypes = { 8 | onSubmitted : React.PropTypes.func, 9 | } 10 | 11 | renderers = { 12 | 'BSDSurvey': BSDSurvey, 13 | 'BSDPhonebankRSVPSurvey': BSDPhonebankRSVPSurvey 14 | } 15 | 16 | submit() { 17 | this.refs.survey.refs.component.submit() 18 | } 19 | 20 | render() { 21 | let Survey = this.renderers[this.props.survey.renderer]; 22 | return ( 23 | 29 | ) 30 | } 31 | } 32 | 33 | // As far as I know, there is no dynamic way to generate relay fragments, so we just need to add them here when we have new survey renderers 34 | export default Relay.createContainer(SurveyRenderer, { 35 | fragments: { 36 | survey: () => Relay.QL` 37 | fragment on Survey { 38 | renderer 39 | ${BSDSurvey.getFragment('survey')} 40 | ${BSDPhonebankRSVPSurvey.getFragment('survey')} 41 | } 42 | `, 43 | interviewee: () => Relay.QL` 44 | fragment on Person { 45 | ${BSDSurvey.getFragment('interviewee')} 46 | ${BSDPhonebankRSVPSurvey.getFragment('interviewee')} 47 | } 48 | ` 49 | } 50 | }) -------------------------------------------------------------------------------- /src/frontend/components/AdminCallAssignmentsSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import CallAssignmentList from './CallAssignmentList'; 4 | import SideBarLayout from './SideBarLayout'; 5 | import {RaisedButton} from 'material-ui'; 6 | import AdminCallAssignment from './AdminCallAssignment'; 7 | import AdminCallAssignmentCreationForm from './AdminCallAssignmentCreationForm'; 8 | import {BernieLayout} from './styles/bernie-css'; 9 | 10 | class AdminCallAssignmentAdmin extends React.Component { 11 | render() { 12 | let sideBar = ( 13 |
14 | this.props.history.push('/admin/call-assignments/create')} 18 | /> 19 | this.props.history.push('/admin/call-assignments/' + id)} 23 | /> 24 |
25 | ) 26 | return ( 27 | 32 | ) 33 | } 34 | } 35 | 36 | export default Relay.createContainer(AdminCallAssignmentAdmin, { 37 | fragments: { 38 | listContainer: () => Relay.QL` 39 | fragment on ListContainer { 40 | callAssignments(first:50) { 41 | ${CallAssignmentList.getFragment('callAssignments')} 42 | } 43 | } 44 | `, 45 | }, 46 | }); -------------------------------------------------------------------------------- /src/frontend/index/index.mustache: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ground Control 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 17 | 19 | 22 | 28 | 29 | 30 |
31 | 36 | {{{ extra_head }}} 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/frontend/components/SideBarLayout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Styles, Paper} from 'material-ui'; 3 | import {BernieColors} from './styles/bernie-css'; 4 | import Radium from 'radium'; 5 | 6 | @Radium 7 | export default class SideBarLayout extends React.Component { 8 | styles = { 9 | container: { 10 | display: 'flex', 11 | border: 'solid 1px ' + BernieColors.lightGray 12 | }, 13 | 14 | sideBar: { 15 | width: '12em', 16 | borderRight: 'solid 1px ' + BernieColors.lightGray 17 | }, 18 | 19 | content: { 20 | display: 'flex', 21 | flex: 1, 22 | } 23 | } 24 | 25 | render() { 26 | let sideBarPosition = this.props.sideBarPosition || 'left' 27 | let sideBar = ( 28 |
32 | {this.props.sideBar} 33 |
34 | ) 35 | 36 | let content = ( 37 |
42 | {this.props.content} 43 |
44 | ) 45 | let containerStyle = { 46 | ...this.styles.container, 47 | ...this.props.containerStyle 48 | } 49 | let body = ( 50 |
51 | {sideBar} 52 | {content} 53 |
54 | ) 55 | if (sideBarPosition === 'right') 56 | body = ( 57 |
58 | {content} 59 | {sideBar} 60 |
61 | ) 62 | return body 63 | } 64 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/link/dialogs/anchor.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.dialog.add("anchor",function(c){function d(a,b){return a.createFakeElement(a.document.createElement("a",{attributes:b}),"cke_anchor","anchor")}return{title:c.lang.link.anchor.title,minWidth:300,minHeight:60,onOk:function(){var a=CKEDITOR.tools.trim(this.getValueOf("info","txtName")),a={id:a,name:a,"data-cke-saved-name":a};if(this._.selectedElement)this._.selectedElement.data("cke-realelement")?(a=d(c,a),a.replace(this._.selectedElement),CKEDITOR.env.ie&&c.getSelection().selectElement(a)): 6 | this._.selectedElement.setAttributes(a);else{var b=c.getSelection(),b=b&&b.getRanges()[0];b.collapsed?(a=d(c,a),b.insertNode(a)):(CKEDITOR.env.ie&&9>CKEDITOR.env.version&&(a["class"]="cke_anchor"),a=new CKEDITOR.style({element:"a",attributes:a}),a.type=CKEDITOR.STYLE_INLINE,c.applyStyle(a))}},onHide:function(){delete this._.selectedElement},onShow:function(){var a=c.getSelection(),b=a.getSelectedElement(),d=b&&b.data("cke-realelement"),e=d?CKEDITOR.plugins.link.tryRestoreFakeAnchor(c,b):CKEDITOR.plugins.link.getSelectedLink(c); 7 | if(e){this._.selectedElement=e;var f=e.data("cke-saved-name");this.setValueOf("info","txtName",f||"");!d&&a.selectElement(e);b&&(this._.selectedElement=b)}this.getContentElement("info","txtName").focus()},contents:[{id:"info",label:c.lang.link.anchor.title,accessKey:"I",elements:[{type:"text",id:"txtName",label:c.lang.link.anchor.name,required:!0,validate:function(){return this.getValue()?!0:(alert(c.lang.link.anchor.errorName),!1)}}]}]}}); -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/assets/posteddata.php: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | Sample — CKEditor 12 | 13 | 14 | 15 |

16 | CKEditor — Posted Data 17 |

18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | $value ) 31 | { 32 | if ( ( !is_string($value) && !is_numeric($value) ) || !is_string($key) ) 33 | continue; 34 | 35 | if ( get_magic_quotes_gpc() ) 36 | $value = htmlspecialchars( stripslashes((string)$value) ); 37 | else 38 | $value = htmlspecialchars( (string)$value ); 39 | ?> 40 | 41 | 42 | 43 | 44 | 48 |
Field NameValue
49 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCCheckboxesField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Checkbox} from 'material-ui'; 3 | import {BernieText, BernieColors} from '../styles/bernie-css' 4 | 5 | export default class GCCheckboxesField extends React.Component { 6 | styles = { 7 | label: { 8 | paddingBottom: 10, 9 | ...BernieText.inputLabel, 10 | }, 11 | } 12 | 13 | createCheckboxes() { 14 | let value = this.props.value || [] 15 | 16 | return Object.keys(this.props.choices).map((choice) => { 17 | let selected = false; 18 | 19 | if (value.indexOf(choice) !== -1) 20 | selected = true; 21 | 22 | return ( 23 | { 29 | let newValue = value.slice() 30 | if (selected) { 31 | let index = value.indexOf(choice) 32 | newValue.splice(index, 1) 33 | } 34 | else 35 | newValue.push(event.target.value) 36 | this.props.onChange(newValue) 37 | }} 38 | /> 39 | ) 40 | }) 41 | } 42 | 43 | render() { 44 | let error =
; 45 | let labelStyle = this.styles.label 46 | if (this.props.errorText) { 47 | error =
{this.props.errorText}
48 | labelStyle = { 49 | ...labelStyle, 50 | color: BernieColors.red 51 | } 52 | } 53 | 54 | return ( 55 |
56 |
{this.props.label}
57 | {this.createCheckboxes()} 58 | {error} 59 |
60 | ) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /docs/SPECS.md: -------------------------------------------------------------------------------- 1 | Ground Control exposes a GraphQL-based API that you can explore in src/backend/data/schema.js. 2 | 3 | # Person 4 | 5 | This is a person. Very minimal data exists at a top level of a person because, as it turns out, everything can change and we want to keep track of these changes (not an absolute truth, but until we find it too hard to do so). 6 | 7 | # Field 8 | 9 | A field represents something that can be filled out for a person. E.g. email, why do you like Bernie Sanders, etc. 10 | 11 | # Note 12 | 13 | A note is simple a pairing between a field and a person. 14 | 15 | # Survey 16 | 17 | A survey is a model that has an array of different data sources and a template that points to an actual React component that knows how to render the survey given the data. Most surveys will just have Fields as their data, but you could imagine, for example, a survey that is used to sign up for one of many group calls where each group call available to that survey is also a member of the data. A survey template will generally be created using a Field abstraction (which is itself a React component) that takes these props: 18 | 19 | { 20 | label 21 | helpText 22 | baseField : { 23 | type 24 | validationFunc 25 | } 26 | cleanFunc 27 | displayFunc 28 | onChange 29 | } 30 | 31 | There is also a hook on the Survey React component for onSubmit to do any cross-field validations. Surveys will be rendered by a higher order component called SurveyRenderer that will handle data fetching and mutations for the survey. When a survey is submitted, it can be processed by a series of SurveyProcessors. These can do things from the data like add Notes to Persons, sign up the Person for a Group Call, create an event, etc. -------------------------------------------------------------------------------- /src/backend/email-templates/event-create-confirmation/html.hbs: -------------------------------------------------------------------------------- 1 | {{> header }} 2 | 3 |

Thank you for volunteering to host an event for Bernie! The details of the event you submitted are included below. To manage the events you have created, please visit secure.berniesanders.com/page/event/myevents.

4 | 5 |

6 | Your username on berniesanders.com is {{user.email}} 7 | {{#if user.password}} 8 |
9 | Your password is {{user.password}} 10 |

IMPORTANT: Please change your password the first time you log in. 11 | {{/if}} 12 |

13 | 14 |
15 | 16 |

{{event.name}}

17 | 18 |

Event Description

19 |

{{event.event_type_name}}

20 | {{{event.description}}} 21 | 22 |

Event Venue

23 | {{event.venue_name}}, capacity {{event.capacity}} 24 |
25 | {{event.venue_addr1}} {{event.venue_city}} {{event.venue_state_cd}} {{event.venue_zip}} 26 |

{{event.venue_directions}}

27 | 28 |

Event Time

29 | {{event.start_time.h}}:{{event.start_time.i}} {{event.start_time.a}} {{event.start_tz}} for {{event.duration_num}} 30 | {{#ifCond event.duration_unit '==' 1}}minute{{/ifCond}}{{#ifCond event.duration_unit '==' 60}}hour{{/ifCond}}{{#ifCond event.duration_unit '==' 1440}}day{{/ifCond}}{{#ifCond event.duration_num '>' 1}}s{{/ifCond}} 31 |

Event Date{{#ifCond event.event_dates.length '>' 1}}s{{/ifCond}}

32 |
    33 | {{#each event.event_dates}} 34 |
  • {{this.date}}
  • 35 | {{/each}} 36 |
37 | 38 | {{#if event.attendee_volunteer_show}} 39 |

Volunteer Message

40 |

{{event.attendee_volunteer_message}}

41 | {{/if}} 42 | 43 | {{> footer email=user.email }} -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/font/fontello.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (C) 2014 by original authors @ fontello.com 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/about/dialogs/about.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.dialog.add("about",function(a){a=a.lang.about;var b=CKEDITOR.getUrl(CKEDITOR.plugins.get("about").path+"dialogs/"+(CKEDITOR.env.hidpi?"hidpi/":"")+"logo_ckeditor.png");return{title:CKEDITOR.env.ie?a.dlgTitle:a.title,minWidth:390,minHeight:230,contents:[{id:"tab1",label:"",title:"",expand:!0,padding:0,elements:[{type:"html",html:'\x3cstyle type\x3d"text/css"\x3e.cke_about_container{color:#000 !important;padding:10px 10px 0;margin-top:5px}.cke_about_container p{margin: 0 0 10px;}.cke_about_container .cke_about_logo{height:81px;background-color:#fff;background-image:url('+ 6 | b+");"+(CKEDITOR.env.hidpi?"background-size:163px 58px;":"")+'background-position:center; background-repeat:no-repeat;margin-bottom:10px;}.cke_about_container a{cursor:pointer !important;color:#00B2CE !important;text-decoration:underline !important;}\x3c/style\x3e\x3cdiv class\x3d"cke_about_container"\x3e\x3cdiv class\x3d"cke_about_logo"\x3e\x3c/div\x3e\x3cp\x3eCKEditor '+CKEDITOR.version+" (revision "+CKEDITOR.revision+')\x3cbr\x3e\x3ca target\x3d"_blank" href\x3d"http://ckeditor.com/"\x3ehttp://ckeditor.com\x3c/a\x3e\x3c/p\x3e\x3cp\x3e'+ 7 | a.help.replace("$1",'\x3ca target\x3d"_blank" href\x3d"http://docs.ckeditor.com/user"\x3e'+a.userGuide+"\x3c/a\x3e")+"\x3c/p\x3e\x3cp\x3e"+a.moreInfo+'\x3cbr\x3e\x3ca target\x3d"_blank" href\x3d"http://ckeditor.com/about/license"\x3ehttp://ckeditor.com/about/license\x3c/a\x3e\x3c/p\x3e\x3cp\x3e'+a.copy.replace("$1",'\x3ca target\x3d"_blank" href\x3d"http://cksource.com/"\x3eCKSource\x3c/a\x3e - Frederico Knabben')+"\x3c/p\x3e\x3c/div\x3e"}]}],buttons:[CKEDITOR.dialog.cancelButton]}}); -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/js/sample.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | 6 | /* exported initSample */ 7 | 8 | if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 ) 9 | CKEDITOR.tools.enableHtml5Elements( document ); 10 | 11 | // The trick to keep the editor in the sample quite small 12 | // unless user specified own height. 13 | CKEDITOR.config.height = 150; 14 | CKEDITOR.config.width = 'auto'; 15 | 16 | var initSample = ( function() { 17 | var wysiwygareaAvailable = isWysiwygareaAvailable(), 18 | isBBCodeBuiltIn = !!CKEDITOR.plugins.get( 'bbcode' ); 19 | 20 | return function() { 21 | var editorElement = CKEDITOR.document.getById( 'editor' ); 22 | 23 | // :((( 24 | if ( isBBCodeBuiltIn ) { 25 | editorElement.setHtml( 26 | 'Hello world!\n\n' + 27 | 'I\'m an instance of [url=http://ckeditor.com]CKEditor[/url].' 28 | ); 29 | } 30 | 31 | // Depending on the wysiwygare plugin availability initialize classic or inline editor. 32 | if ( wysiwygareaAvailable ) { 33 | CKEDITOR.replace( 'editor' ); 34 | } else { 35 | editorElement.setAttribute( 'contenteditable', 'true' ); 36 | CKEDITOR.inline( 'editor' ); 37 | 38 | // TODO we can consider displaying some info box that 39 | // without wysiwygarea the classic editor may not work. 40 | } 41 | }; 42 | 43 | function isWysiwygareaAvailable() { 44 | // If in development mode, then the wysiwygarea must be available. 45 | // Split REV into two strings so builder does not replace it :D. 46 | if ( CKEDITOR.revision == ( '%RE' + 'V%' ) ) { 47 | return true; 48 | } 49 | 50 | return !!CKEDITOR.plugins.get( 'wysiwygarea' ); 51 | } 52 | } )(); 53 | 54 | -------------------------------------------------------------------------------- /src/frontend/components/forms/GCBooleanField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {FlatButton} from 'material-ui'; 3 | import {BernieText, BernieColors} from '../styles/bernie-css' 4 | 5 | export default class GCBooleanField extends React.Component { 6 | styles = { 7 | label: { 8 | ...BernieText.inputLabel 9 | }, 10 | selectedButton: { 11 | color: BernieColors.lightBlue, 12 | backgroundColor: BernieColors.blue 13 | }, 14 | } 15 | render() { 16 | let error =
17 | let labelStyle = this.styles.label; 18 | let value = this.props.value; 19 | 20 | if (this.props.labelStyle) 21 | labelStyle = this.props.labelStyle; 22 | if (this.props.errorText) { 23 | labelStyle = { 24 | ...labelStyle, 25 | color: BernieColors.red 26 | } 27 | error =
{this.props.errorText}
28 | } 29 | 30 | let yesButton = ( 31 | {this.props.onChange(true)}} 35 | /> 36 | ) 37 | let noButton = ( 38 | {this.props.onChange(false)}} 42 | /> 43 | ) 44 | if (value === true) { 45 | yesButton = React.cloneElement(yesButton, { 46 | style: this.styles.selectedButton 47 | }) 48 | } 49 | 50 | else if (value === false) { 51 | noButton = React.cloneElement(noButton, { 52 | style: this.styles.selectedButton 53 | }) 54 | } 55 | 56 | return ( 57 |
58 |
59 | {this.props.label} 60 |
61 |
62 | {yesButton} 63 | {noButton} 64 |
65 | {error} 66 |
67 | ) 68 | } 69 | } -------------------------------------------------------------------------------- /src/frontend/components/forms/GCSelectField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BernieText, BernieColors} from '../styles/bernie-css' 3 | import GCFormField from './GCFormField'; 4 | import Select from 'react-select'; 5 | require('react-select/dist/react-select.css'); 6 | 7 | export default class GCSelectField extends GCFormField { 8 | styles = { 9 | label: { 10 | paddingBottom: 10, 11 | ...BernieText.inputLabel, 12 | }, 13 | } 14 | 15 | createMenuItems() { 16 | return Object.keys(this.props.choices).map((choice) => { 17 | return { 18 | label: this.props.choices[choice], 19 | value: choice 20 | } 21 | }) 22 | } 23 | 24 | getMenuItemIndex(menuItems) { 25 | let menuItemIndex = 0; 26 | menuItems.forEach((item, index) => { 27 | if (item.value == this.props.value){ 28 | menuItemIndex = index; 29 | } 30 | }); 31 | return menuItemIndex 32 | } 33 | 34 | render() { 35 | let error =
; 36 | let labelStyle = this.styles.label 37 | if (this.props.errorText) { 38 | error =
{this.props.errorText}
39 | labelStyle = { 40 | ...labelStyle, 41 | color: BernieColors.red 42 | } 43 | } 44 | 45 | const menuItems = this.createMenuItems(); 46 | 47 | return ( 48 |
52 |
{this.props.label}
53 | 59 |

60 |
61 |

62 | 63 |

64 |

65 | 66 |

67 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/uicolor.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | UI Color Picker — CKEditor Sample 10 | 11 | 12 | 13 | 14 |

15 | CKEditor Samples » UI Color 16 |

17 |
18 | This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. 19 |
20 |
21 |

22 | This sample shows how to automatically replace <textarea> elements 23 | with a CKEditor instance with an option to change the color of its user interface.
24 | Note:The UI skin color feature depends on the CKEditor skin 25 | compatibility. The Moono and Kama skins are examples of skins that work with it. 26 |

27 |
28 |
29 |

30 | This editor instance has a UI color value defined in configuration to change the skin color, 31 | To specify the color of the user interface, set the uiColor property: 32 |

33 |
34 | CKEDITOR.replace( 'textarea_id', {
35 | 	uiColor: '#14B8C4'
36 | });
37 |

38 | Note that textarea_id in the code above is the id attribute of 39 | the <textarea> element to be replaced. 40 |

41 |

42 | 43 | 56 |

57 |

58 | 59 |

60 |
61 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/frontend/components/CallAssignmentsSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {BernieText, BernieColors} from './styles/bernie-css' 4 | import Radium from 'radium' 5 | import SideBarLayout from './SideBarLayout'; 6 | import CallAssignmentList from './CallAssignmentList'; 7 | import CallAssignment from './CallAssignment'; 8 | import Signup from './Signup'; 9 | 10 | class CallAssignmentsSection extends React.Component { 11 | styles = { 12 | container: { 13 | paddingLeft: 40, 14 | paddingTop: 40, 15 | paddingRight: 40, 16 | paddingBottom: 40, 17 | }, 18 | paragraph: { 19 | paddingTop: '0.5em', 20 | paddingBottom: '0.5em', 21 | paddingLeft: '0.5em', 22 | paddingRight: '0.5em', 23 | }, 24 | } 25 | 26 | render() { 27 | let sideBar = ( 28 |
29 | { 33 | this.props.history.push('/call/' + id) 34 | }} 35 | /> 36 |
37 | ) 38 | 39 | let content = ( 40 |
41 |
42 | Let them hear you loud and clear 43 |
44 |
45 |

46 | On the left, you'll find a list of calling assignments that you can start with right away. Just click one, call the number that gets shown to you, and fill out the survey. 47 |

48 |

49 | Remember that everyone you are calling are people who have signed up to help. Feel free to let them know you are a fellow volunteer -- it helps! And please be sure to follow our guidelines: 50 |

51 |
    52 |
  1. Treat everyone with respect and kindness.
  2. 53 |
  3. Do not make any statements implying that you are speaking officially on behalf of the campaign.
  4. 54 |
  5. Do not give legal advice or advice on fundraising or FEC regulations.
  6. 55 |
  7. Do not speak disparagingly about other candidates, groups or volunteers during the course of these calls.
  8. 56 |
57 |

58 | Thank you and have fun! 59 |

60 |
61 |
62 | ) 63 | 64 | return ( 65 |
66 | 71 |
72 | ) 73 | } 74 | } 75 | 76 | export default Relay.createContainer(CallAssignmentsSection, { 77 | fragments: { 78 | currentUser: () => Relay.QL` 79 | fragment on User { 80 | callAssignments(first:50) { 81 | ${CallAssignmentList.getFragment('callAssignments')} 82 | } 83 | } 84 | `, 85 | }, 86 | }); -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/ajax.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | Ajax — CKEditor Sample 10 | 11 | 12 | 40 | 41 | 42 |

43 | CKEditor Samples » Create and Destroy Editor Instances for Ajax Applications 44 |

45 |
46 | This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. 47 |
48 |
49 |

50 | This sample shows how to create and destroy CKEditor instances on the fly. After the removal of CKEditor the content created inside the editing 51 | area will be displayed in a <div> element. 52 |

53 |

54 | For details of how to create this setup check the source code of this sample page 55 | for JavaScript code responsible for the creation and destruction of a CKEditor instance. 56 |

57 |
58 |

Click the buttons to create and remove a CKEditor instance.

59 |

60 | 61 | 62 |

63 | 64 |
65 |
66 | 74 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/frontend/relay-extensions/GCNetworkLayer.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay' 2 | 3 | export default class GCNetworkLayer extends Relay.DefaultNetworkLayer { 4 | // Copy pasta from relay because they didn't put it in the class 5 | formatRequestErrors(request, errors) { 6 | var CONTEXT_BEFORE = 20; 7 | var CONTEXT_LENGTH = 60; 8 | 9 | var queryLines = request.getQueryString().split('\n'); 10 | return errors.map(function (_ref, ii) { 11 | var locations = _ref.locations; 12 | var message = _ref.message; 13 | 14 | var prefix = ii + 1 + '. '; 15 | var indent = ' '.repeat(prefix.length); 16 | 17 | //custom errors thrown in graphql-server may not have locations 18 | var locationMessage = locations ? '\n' + locations.map(function (_ref2) { 19 | var column = _ref2.column; 20 | var line = _ref2.line; 21 | 22 | var queryLine = queryLines[line - 1]; 23 | var offset = Math.min(column - 1, CONTEXT_BEFORE); 24 | return [queryLine.substr(column - 1 - offset, CONTEXT_LENGTH), ' '.repeat(offset) + '^^^'].map(function (messageLine) { 25 | return indent + messageLine; 26 | }).join('\n'); 27 | }).join('\n') : ''; 28 | 29 | return prefix + message + locationMessage; 30 | }).join('\n'); 31 | } 32 | 33 | handleStructuredError(error) { 34 | let parsedError = null; 35 | 36 | try { 37 | parsedError = JSON.parse(error.message); 38 | } catch (ex) { } 39 | 40 | if (parsedError) { 41 | log.debug(parsedError); 42 | 43 | if (parsedError.status === 401 || parsedError.status === 403) { 44 | window.location = `/signup?next=${window.location.pathname}`; 45 | } else if (parsedError.status === 404) { 46 | window.location = '/404'; 47 | } 48 | } 49 | } 50 | 51 | sendQueries(requests) { 52 | return Promise.all(requests.map((request) => { 53 | return this._sendQuery(request) 54 | .then((result) => { 55 | return result.json(); 56 | }) 57 | .then((payload) => { 58 | if (payload.hasOwnProperty('errors')) { 59 | if (payload.errors.length > 0) 60 | this.handleStructuredError(payload.errors[0]); 61 | 62 | let errorString = 'Server request for query `' + request.getDebugName() + '` ' + 'failed for the following reasons:\n\n' + this.formatRequestErrors(request, payload.errors); 63 | log.error(errorString, payload.errors); 64 | 65 | let error = new Error(errorString); 66 | error.source = payload; 67 | request.reject(error); 68 | } else if (!payload.hasOwnProperty('data')) { 69 | let errorMsg = 'Server response was missing for query `' + request.getDebugName() + '`.'; 70 | log.error(errorMsg); 71 | 72 | request.reject(new Error(errorMsg)); 73 | } else { 74 | request.resolve({ response: payload.data }); 75 | } 76 | }) 77 | .catch((error) => { 78 | log.error(error.message); 79 | return request.reject(error); 80 | }); 81 | })); 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/adapters/jquery.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | (function(a){if("undefined"==typeof a)throw Error("jQuery should be loaded before CKEditor jQuery adapter.");if("undefined"==typeof CKEDITOR)throw Error("CKEditor should be loaded before CKEditor jQuery adapter.");CKEDITOR.config.jqueryOverrideVal="undefined"==typeof CKEDITOR.config.jqueryOverrideVal?!0:CKEDITOR.config.jqueryOverrideVal;a.extend(a.fn,{ckeditorGet:function(){var a=this.eq(0).data("ckeditorInstance");if(!a)throw"CKEditor is not initialized yet, use ckeditor() with a callback.";return a}, 6 | ckeditor:function(g,d){if(!CKEDITOR.env.isCompatible)throw Error("The environment is incompatible.");if(!a.isFunction(g)){var m=d;d=g;g=m}var k=[];d=d||{};this.each(function(){var b=a(this),c=b.data("ckeditorInstance"),f=b.data("_ckeditorInstanceLock"),h=this,l=new a.Deferred;k.push(l.promise());if(c&&!f)g&&g.apply(c,[this]),l.resolve();else if(f)c.once("instanceReady",function(){setTimeout(function(){c.element?(c.element.$==h&&g&&g.apply(c,[h]),l.resolve()):setTimeout(arguments.callee,100)},0)}, 7 | null,null,9999);else{if(d.autoUpdateElement||"undefined"==typeof d.autoUpdateElement&&CKEDITOR.config.autoUpdateElement)d.autoUpdateElementJquery=!0;d.autoUpdateElement=!1;b.data("_ckeditorInstanceLock",!0);c=a(this).is("textarea")?CKEDITOR.replace(h,d):CKEDITOR.inline(h,d);b.data("ckeditorInstance",c);c.on("instanceReady",function(d){var e=d.editor;setTimeout(function(){if(e.element){d.removeListener();e.on("dataReady",function(){b.trigger("dataReady.ckeditor",[e])});e.on("setData",function(a){b.trigger("setData.ckeditor", 8 | [e,a.data])});e.on("getData",function(a){b.trigger("getData.ckeditor",[e,a.data])},999);e.on("destroy",function(){b.trigger("destroy.ckeditor",[e])});e.on("save",function(){a(h.form).submit();return!1},null,null,20);if(e.config.autoUpdateElementJquery&&b.is("textarea")&&a(h.form).length){var c=function(){b.ckeditor(function(){e.updateElement()})};a(h.form).submit(c);a(h.form).bind("form-pre-serialize",c);b.bind("destroy.ckeditor",function(){a(h.form).unbind("submit",c);a(h.form).unbind("form-pre-serialize", 9 | c)})}e.on("destroy",function(){b.removeData("ckeditorInstance")});b.removeData("_ckeditorInstanceLock");b.trigger("instanceReady.ckeditor",[e]);g&&g.apply(e,[h]);l.resolve()}else setTimeout(arguments.callee,100)},0)},null,null,9999)}});var f=new a.Deferred;this.promise=f.promise();a.when.apply(this,k).then(function(){f.resolve()});this.editor=this.eq(0).data("ckeditorInstance");return this}});CKEDITOR.config.jqueryOverrideVal&&(a.fn.val=CKEDITOR.tools.override(a.fn.val,function(g){return function(d){if(arguments.length){var m= 10 | this,k=[],f=this.each(function(){var b=a(this),c=b.data("ckeditorInstance");if(b.is("textarea")&&c){var f=new a.Deferred;c.setData(d,function(){f.resolve()});k.push(f.promise());return!0}return g.call(b,d)});if(k.length){var b=new a.Deferred;a.when.apply(this,k).done(function(){b.resolveWith(m)});return b.promise()}return f}var f=a(this).eq(0),c=f.data("ckeditorInstance");return f.is("textarea")&&c?c.getData():g.call(f)}}))})(window.jQuery); -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/readonly.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | Using the CKEditor Read-Only API — CKEditor Sample 10 | 11 | 12 | 38 | 39 | 40 |

41 | CKEditor Samples » Using the CKEditor Read-Only API 42 |

43 |
44 | This sample is not maintained anymore. Check out its brand new version in CKEditor SDK. 45 |
46 |
47 |

48 | This sample shows how to use the 49 | setReadOnly 50 | API to put editor into the read-only state that makes it impossible for users to change the editor contents. 51 |

52 |

53 | For details on how to create this setup check the source code of this sample page. 54 |

55 |
56 |
57 |

58 | 59 |

60 |

61 | 62 | 63 |

64 |
65 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/build-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | 6 | /** 7 | * This file was added automatically by CKEditor builder. 8 | * You may re-use it at any time to build CKEditor again. 9 | * 10 | * If you would like to build CKEditor online again 11 | * (for example to upgrade), visit one the following links: 12 | * 13 | * (1) http://ckeditor.com/builder 14 | * Visit online builder to build CKEditor from scratch. 15 | * 16 | * (2) http://ckeditor.com/builder/3fbd7430c5ae23bca5707ed2ab706bdf 17 | * Visit online builder to build CKEditor, starting with the same setup as before. 18 | * 19 | * (3) http://ckeditor.com/builder/download/3fbd7430c5ae23bca5707ed2ab706bdf 20 | * Straight download link to the latest version of CKEditor (Optimized) with the same setup as before. 21 | * 22 | * NOTE: 23 | * This file is not used by CKEditor, you may remove it. 24 | * Changing this file will not change your CKEditor configuration. 25 | */ 26 | 27 | var CKBUILDER_CONFIG = { 28 | skin: 'moono', 29 | preset: 'basic', 30 | ignore: [ 31 | '.bender', 32 | 'bender.js', 33 | 'bender-err.log', 34 | 'bender-out.log', 35 | 'dev', 36 | '.DS_Store', 37 | '.editorconfig', 38 | '.gitattributes', 39 | '.gitignore', 40 | 'gruntfile.js', 41 | '.idea', 42 | '.jscsrc', 43 | '.jshintignore', 44 | '.jshintrc', 45 | 'less', 46 | '.mailmap', 47 | 'node_modules', 48 | 'package.json', 49 | 'README.md', 50 | 'tests' 51 | ], 52 | plugins : { 53 | 'about' : 1, 54 | 'basicstyles' : 1, 55 | 'clipboard' : 1, 56 | 'enterkey' : 1, 57 | 'entities' : 1, 58 | 'floatingspace' : 1, 59 | 'indentlist' : 1, 60 | 'link' : 1, 61 | 'list' : 1, 62 | 'toolbar' : 1, 63 | 'undo' : 1, 64 | 'wysiwygarea' : 1 65 | }, 66 | languages : { 67 | 'af' : 1, 68 | 'ar' : 1, 69 | 'bg' : 1, 70 | 'bn' : 1, 71 | 'bs' : 1, 72 | 'ca' : 1, 73 | 'cs' : 1, 74 | 'cy' : 1, 75 | 'da' : 1, 76 | 'de' : 1, 77 | 'el' : 1, 78 | 'en' : 1, 79 | 'en-au' : 1, 80 | 'en-ca' : 1, 81 | 'en-gb' : 1, 82 | 'eo' : 1, 83 | 'es' : 1, 84 | 'et' : 1, 85 | 'eu' : 1, 86 | 'fa' : 1, 87 | 'fi' : 1, 88 | 'fo' : 1, 89 | 'fr' : 1, 90 | 'fr-ca' : 1, 91 | 'gl' : 1, 92 | 'gu' : 1, 93 | 'he' : 1, 94 | 'hi' : 1, 95 | 'hr' : 1, 96 | 'hu' : 1, 97 | 'id' : 1, 98 | 'is' : 1, 99 | 'it' : 1, 100 | 'ja' : 1, 101 | 'ka' : 1, 102 | 'km' : 1, 103 | 'ko' : 1, 104 | 'ku' : 1, 105 | 'lt' : 1, 106 | 'lv' : 1, 107 | 'mk' : 1, 108 | 'mn' : 1, 109 | 'ms' : 1, 110 | 'nb' : 1, 111 | 'nl' : 1, 112 | 'no' : 1, 113 | 'pl' : 1, 114 | 'pt' : 1, 115 | 'pt-br' : 1, 116 | 'ro' : 1, 117 | 'ru' : 1, 118 | 'si' : 1, 119 | 'sk' : 1, 120 | 'sl' : 1, 121 | 'sq' : 1, 122 | 'sr' : 1, 123 | 'sr-latn' : 1, 124 | 'sv' : 1, 125 | 'th' : 1, 126 | 'tr' : 1, 127 | 'tt' : 1, 128 | 'ug' : 1, 129 | 'uk' : 1, 130 | 'vi' : 1, 131 | 'zh' : 1, 132 | 'zh-cn' : 1 133 | } 134 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ground-control", 3 | "private": true, 4 | "description": "Every political revolution needs a launch pad.", 5 | "repository": "Bernie-2016/ground-control", 6 | "version": "0.1.0", 7 | "scripts": { 8 | "bundle": "mustache ./src/frontend/index/production.json ./src/frontend/index/index.mustache > ./src/frontend/public/index.html && mkdir -p ./src/frontend/public/js && webpack --config ./webpack/config.js", 9 | "postinstall": "NO_DB=true npm run bundle", 10 | "start": "./run ./src/backend/server.js", 11 | "predev": "mustache ./src/frontend/index/development.json ./src/frontend/index/index.mustache > ./src/frontend/public/index.html", 12 | "dev": "nf start -w --procfile Procfile.dev", 13 | "lint": "eslint src", 14 | "knex": "knex --knexfile ./src/backend/data/knexfile.js", 15 | "migrate": "knex migrate:latest --knexfile ./src/backend/data/knexfile.js", 16 | "seed": "knex seed:run --knexfile ./src/backend/data/knexfile.js" 17 | }, 18 | "dependencies": { 19 | "async": "^1.5.0", 20 | "babel": "^5.8.21", 21 | "babel-core": "^5.8.25", 22 | "babel-loader": "^5.3.2", 23 | "babel-register": "^6.2.0", 24 | "babel-relay-plugin": "^0.3.0", 25 | "bcrypt": "^0.8.5", 26 | "bluebird": "^2.10.2", 27 | "body-parser": "1.14.1", 28 | "connect-session-knex": "^1.0.17", 29 | "cron": "^1.1.0", 30 | "css-loader": "^0.23.0", 31 | "csv-load-sync": "0.0.3", 32 | "dataloader": "^1.0.0", 33 | "dotenv": "^1.2.0", 34 | "email-templates": "2.0.1", 35 | "express": "^4.13.1", 36 | "express-graphql": "^0.3.0", 37 | "express-history-api-fallback": "2.0.0", 38 | "express-rate-limit": "^2.0.2", 39 | "express-session": "^1.4.0", 40 | "faker": "^3.0.1", 41 | "fixed-data-table": "^0.6.0", 42 | "graphql": "^0.4.2", 43 | "graphql-relay": "^0.3.5", 44 | "handlebars": "^3.0.0", 45 | "history": "^1.13.1", 46 | "humps": "^1.0.0", 47 | "jquery": "^2.1.4", 48 | "json-loader": "^0.5.4", 49 | "json2csv": "^3.0.1", 50 | "knex": "^0.9.0", 51 | "mailgun-js": "0.7.6", 52 | "material-ui": "0.14.0-rc1", 53 | "minilog": "^3.0.0", 54 | "moment": "^2.10.6", 55 | "moment-timezone": "^0.4.1", 56 | "mustache": "^2.2.0", 57 | "passport": "^0.3.2", 58 | "passport-local": "^1.0.0", 59 | "pg": "^4.4.3", 60 | "radium": "^0.14.3", 61 | "react": "^0.14.2", 62 | "react-dom": "^0.14.0", 63 | "react-formal": "^0.14.2", 64 | "react-google-maps": "^4.7.0", 65 | "react-kronos": "^1.2.0", 66 | "react-relay": "^0.4.0", 67 | "react-router": "^1.0.2", 68 | "react-router-relay": "^0.7.0", 69 | "react-select": "^1.0.0-beta8", 70 | "react-tap-event-plugin": "^0.2.1", 71 | "request-promise": "^1.0.1", 72 | "retry": "^0.8.0", 73 | "stacktrace-js": "^1.0.1", 74 | "style-loader": "^0.13.0", 75 | "superagent": "^1.4.0", 76 | "tz-lookup": "^6.0.1", 77 | "webpack": "^1.10.5", 78 | "xml2js": "^0.4.15", 79 | "yup": "^0.11.0" 80 | }, 81 | "devDependencies": { 82 | "foreman": "latest", 83 | "nodemon": "latest", 84 | "eslint": "latest", 85 | "eslint-plugin-react": "latest", 86 | "babel-eslint": "latest", 87 | "webpack-dev-server": "1.10.1" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/frontend/components/MutationHandler.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import {Snackbar} from 'material-ui'; 4 | import {BernieColors} from './styles/bernie-css'; 5 | 6 | export default class MutationHandler extends React.Component { 7 | 8 | static propTypes = { 9 | mutationClass: React.PropTypes.func, 10 | onSuccess: React.PropTypes.func, 11 | onFailure: React.PropTypes.func, 12 | defaultErrorMessage: React.PropTypes.string, 13 | successMessage: React.PropTypes.string 14 | } 15 | 16 | static defaultProps = { 17 | defaultErrorMessage: 'Something went wrong! Try again in a little bit.', 18 | successMessage: null 19 | } 20 | 21 | state = { 22 | errorMessage: null, 23 | statusMessage: null 24 | } 25 | 26 | clearState() { 27 | this.setState({ 28 | errorMessage: null, 29 | statusMessage: null 30 | }) 31 | } 32 | 33 | onFailure(transaction) { 34 | this.clearState() 35 | let defaultMessage = this.props.defaultErrorMessage; 36 | let error = transaction.getError(); 37 | let errorMessage = null; 38 | if (error.source) { 39 | errorMessage = error.source.errors[0].message; 40 | try { 41 | errorMessage = JSON.parse(errorMessage) 42 | errorMessage = errorMessage.message; 43 | } catch (ex) { 44 | errorMessage = null; 45 | } 46 | } 47 | if (!errorMessage) { 48 | log.error(error); 49 | errorMessage = defaultMessage 50 | } 51 | 52 | this.setState({errorMessage: errorMessage}) 53 | 54 | if (this.props.onFailure) 55 | this.props.onFailure() 56 | } 57 | 58 | onSuccess(transaction) { 59 | this.clearState() 60 | if (this.props.successMessage) 61 | this.setState({statusMessage: this.props.successMessage}) 62 | if (this.props.onSuccess) 63 | this.props.onSuccess() 64 | } 65 | 66 | send(args) { 67 | this.clearState(); 68 | let onFailure = (trans) => this.onFailure(trans); 69 | let onSuccess = (trans) => this.onSuccess(trans); 70 | try { 71 | Relay.Store.update( 72 | new this.props.mutationClass(args), {onFailure, onSuccess} 73 | ) 74 | } catch (ex) { 75 | log.error(ex.message, ex.stack); 76 | this.setState({errorMessage: this.props.defaultErrorMessage}) 77 | } 78 | } 79 | 80 | render() { 81 | let globalSnack =
; 82 | if (this.state.errorMessage) { 83 | globalSnack = 89 | } 90 | else if (this.state.statusMessage) { 91 | globalSnack = 97 | } 98 | return ( 99 |
100 | {globalSnack} 101 |
102 | ) 103 | } 104 | } -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/old/assets/outputxhtml/outputxhtml.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | * For licensing, see LICENSE.md or http://ckeditor.com/license 4 | * 5 | * Styles used by the XHTML 1.1 sample page (xhtml.html). 6 | */ 7 | 8 | /** 9 | * Basic definitions for the editing area. 10 | */ 11 | body 12 | { 13 | font-family: Arial, Verdana, sans-serif; 14 | font-size: 80%; 15 | color: #000000; 16 | background-color: #ffffff; 17 | padding: 5px; 18 | margin: 0px; 19 | } 20 | 21 | /** 22 | * Core styles. 23 | */ 24 | 25 | .Bold 26 | { 27 | font-weight: bold; 28 | } 29 | 30 | .Italic 31 | { 32 | font-style: italic; 33 | } 34 | 35 | .Underline 36 | { 37 | text-decoration: underline; 38 | } 39 | 40 | .StrikeThrough 41 | { 42 | text-decoration: line-through; 43 | } 44 | 45 | .Subscript 46 | { 47 | vertical-align: sub; 48 | font-size: smaller; 49 | } 50 | 51 | .Superscript 52 | { 53 | vertical-align: super; 54 | font-size: smaller; 55 | } 56 | 57 | /** 58 | * Font faces. 59 | */ 60 | 61 | .FontComic 62 | { 63 | font-family: 'Comic Sans MS'; 64 | } 65 | 66 | .FontCourier 67 | { 68 | font-family: 'Courier New'; 69 | } 70 | 71 | .FontTimes 72 | { 73 | font-family: 'Times New Roman'; 74 | } 75 | 76 | /** 77 | * Font sizes. 78 | */ 79 | 80 | .FontSmaller 81 | { 82 | font-size: smaller; 83 | } 84 | 85 | .FontLarger 86 | { 87 | font-size: larger; 88 | } 89 | 90 | .FontSmall 91 | { 92 | font-size: 8pt; 93 | } 94 | 95 | .FontBig 96 | { 97 | font-size: 14pt; 98 | } 99 | 100 | .FontDouble 101 | { 102 | font-size: 200%; 103 | } 104 | 105 | /** 106 | * Font colors. 107 | */ 108 | .FontColor1 109 | { 110 | color: #ff9900; 111 | } 112 | 113 | .FontColor2 114 | { 115 | color: #0066cc; 116 | } 117 | 118 | .FontColor3 119 | { 120 | color: #ff0000; 121 | } 122 | 123 | .FontColor1BG 124 | { 125 | background-color: #ff9900; 126 | } 127 | 128 | .FontColor2BG 129 | { 130 | background-color: #0066cc; 131 | } 132 | 133 | .FontColor3BG 134 | { 135 | background-color: #ff0000; 136 | } 137 | 138 | /** 139 | * Indentation. 140 | */ 141 | 142 | .Indent1 143 | { 144 | margin-left: 40px; 145 | } 146 | 147 | .Indent2 148 | { 149 | margin-left: 80px; 150 | } 151 | 152 | .Indent3 153 | { 154 | margin-left: 120px; 155 | } 156 | 157 | /** 158 | * Alignment. 159 | */ 160 | 161 | .JustifyLeft 162 | { 163 | text-align: left; 164 | } 165 | 166 | .JustifyRight 167 | { 168 | text-align: right; 169 | } 170 | 171 | .JustifyCenter 172 | { 173 | text-align: center; 174 | } 175 | 176 | .JustifyFull 177 | { 178 | text-align: justify; 179 | } 180 | 181 | /** 182 | * Other. 183 | */ 184 | 185 | code 186 | { 187 | font-family: courier, monospace; 188 | background-color: #eeeeee; 189 | padding-left: 1px; 190 | padding-right: 1px; 191 | border: #c0c0c0 1px solid; 192 | } 193 | 194 | kbd 195 | { 196 | padding: 0px 1px 0px 1px; 197 | border-width: 1px 2px 2px 1px; 198 | border-style: solid; 199 | } 200 | 201 | blockquote 202 | { 203 | color: #808080; 204 | } 205 | -------------------------------------------------------------------------------- /src/frontend/components/volunteer-dashboard/VolunteerDashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import Signup from './Signup'; 4 | import {BernieText} from './styles/bernie-css' 5 | import Radium from 'radium'; 6 | 7 | @Radium 8 | class VolunteerDashboard extends React.Component { 9 | styles = { 10 | introContainer: { 11 | display: 'flex', 12 | flexDirection: 'row' 13 | }, 14 | introTextContainer: { 15 | flex: 1, 16 | marginRight: 40 17 | }, 18 | signupForm: { 19 | flex: 'auto', 20 | width: '12em' 21 | }, 22 | container: { 23 | paddingLeft: 40, 24 | paddingTop: 40, 25 | paddingRight: 40, 26 | paddingBottom: 40 27 | }, 28 | paragraph: { 29 | paddingTop: '0.5em', 30 | paddingBottom: '0.5em', 31 | paddingLeft: '0.5em', 32 | paddingRight: '0.5em', 33 | }, 34 | } 35 | 36 | renderIntroduction() { 37 | return ( 38 |
39 |
40 |
41 |
45 | Organize 46 |
47 |
48 | Get involved in the political revolution 49 |
50 |
51 |

52 | We must launch a political revolution which engages millions of Americans from all walks of life in the struggle for real change. This country belongs to all of us, not just the billionaire class. And that’s what this campaign is all about. 53 |

54 |

55 | To win this campaign, all of us must be deeply involved. Our movement needs people like you to help it succeed. 56 |

57 |

58 | Add your name now to volunteer for our campaign for president. 59 |

60 |

61 | Thanks for all you do, 62 |

63 | Bernie 64 |
65 |
66 |
67 | 68 |
69 |
70 |
71 | ) 72 | } 73 | 74 | name() { 75 | return this.props.currentUser.firstName + ' ' + this.props.currentUser.lastName 76 | } 77 | 78 | renderDashboard() { 79 | return ( 80 |
81 |
82 | Welcome {this.name()}! 83 |
84 |
85 | ) 86 | } 87 | 88 | render() { 89 | let contentView = this.renderIntroduction(); 90 | if (this.props.currentUser) { 91 | contentView = this.renderDashboard(); 92 | } 93 | return contentView; 94 | } 95 | } 96 | 97 | export default Relay.createContainer(VolunteerDashboard, { 98 | fragments: { 99 | currentUser: () => Relay.QL` 100 | fragment on Person { 101 | firstName 102 | lastName 103 | } 104 | `, 105 | }, 106 | }); -------------------------------------------------------------------------------- /src/frontend/components/EventPreview.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Relay from 'react-relay'; 3 | import GCForm from './forms/GCForm'; 4 | import Form from 'react-formal'; 5 | import yup from 'yup'; 6 | import moment from 'moment'; 7 | import {Card, CardActions, CardExpandable, CardTitle, CardHeader, CardText, FlatButton, TextField, DropDownMenu, SelectField, DatePicker, TimePicker, Checkbox} from 'material-ui'; 8 | import {BernieText, BernieColors} from './styles/bernie-css'; 9 | import GCSelectField from './forms/GCSelectField' 10 | import InfoHeader from './InfoHeader' 11 | 12 | export default class EventPreview extends React.Component { 13 | constructor(props) { 14 | super(props); 15 | // this.handleKeyDown = this.handleKeyDown.bind(this); 16 | // document.addEventListener('keydown', this.handleKeyDown); 17 | } 18 | 19 | handleKeyDown(event){ 20 | switch(event.keyIdentifier){ 21 | case 'Down': 22 | case 'Right': 23 | // View next event 24 | this.props.onChangeEventIndex(1); 25 | break; 26 | case 'Up': 27 | case 'Left': 28 | // View previous event 29 | this.props.onChangeEventIndex(-1); 30 | break; 31 | case 'U+0041': 32 | // 'A' was pressed; approve and move to next event 33 | this.props.onEventConfirm([this.props.eventIndex]); 34 | break; 35 | case 'U+0045': 36 | // 'E' was pressed; open edit tab 37 | this.props.onTabRequest(this.props.eventIndex, 1); 38 | break; 39 | case 'U+0050': 40 | // 'P' was pressed; open preview tab 41 | this.props.onTabRequest(this.props.eventIndex, 0); 42 | break; 43 | case 'U+0044': 44 | // 'D' was pressed; delete this event 45 | this.props.onEventDelete([this.props.eventIndex]); 46 | break; 47 | default: 48 | //Statements executed when none of the values match the value of the expression 49 | console.log(event.keyIdentifier); 50 | break; 51 | } 52 | } 53 | 54 | componentWillUnmount(){ 55 | document.removeEventListener('keydown', this.handleKeyDown); 56 | } 57 | 58 | 59 | render() { 60 | let event = this.props.event 61 | return ( 62 |
63 | 64 |

{event.name}

65 | 66 | 67 |

{event.eventType.name}

68 | 69 | 70 |

Venue Capacity: {(event.capacity) ? event.capacity : 'unlimited'}

71 |

Number of RSVPs: {event.attendeesCount}

72 | 73 | 74 |

{event.description}

75 | 76 | 77 |

{moment(event.startDate).utcOffset(event.localUTCOffset).format('LLLL')} {event.localTimezone} time

78 |

Duration: {Math.floor(event.duration / 60)} hours {event.duration % 60} minutes

79 | 80 | 81 |

{event.venueName}

82 |

{event.venueAddr1} {event.venueAddr2}

83 |

{event.venueCity} {event.venueState}, {event.venueZip} ({event.venueCountry})

84 |
85 |

Capacity: {(event.capacity == 0) ? 'Unlimited' : event.capacity}

86 |
87 |

Directions: {(event.venueDirections) ? event.venueDirections : 'None'}

88 |
89 |
90 | ) 91 | } 92 | } -------------------------------------------------------------------------------- /src/frontend/components/TopNav.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import BernieLogo from './BernieLogo'; 3 | import {BernieColors, BernieText} from './styles/bernie-css'; 4 | import {BernieTheme} from './styles/bernie-theme'; 5 | import {AppBar, Styles, Tabs, Tab} from 'material-ui'; 6 | import superagent from 'superagent'; 7 | 8 | @Styles.ThemeDecorator(Styles.ThemeManager.getMuiTheme(BernieTheme)) 9 | export default class TopNav extends React.Component { 10 | static propTypes = { 11 | logoColors: React.PropTypes.shape({ 12 | primary: React.PropTypes.string, 13 | swoosh: React.PropTypes.string 14 | }), 15 | sections: React.PropTypes.arrayOf(React.PropTypes.shape({ 16 | label: React.PropTypes.string, 17 | value: React.PropTypes.string, 18 | component: React.PropTypes.object 19 | })), 20 | barColor: React.PropTypes.string, 21 | tabColor: React.PropTypes.string, 22 | selectedTabColor: React.PropTypes.string, 23 | selectedTab: React.PropTypes.string, 24 | history: React.PropTypes.object, 25 | location: React.PropTypes.object 26 | } 27 | 28 | styles = { 29 | logo: { 30 | width: 96, 31 | height: 40 32 | }, 33 | bar: { 34 | height: 56, 35 | minHeight: 56 36 | }, 37 | tab: { 38 | ...BernieText.secondaryTitle, 39 | fontSize: '1rem', 40 | } 41 | } 42 | 43 | logoutHandler = (event) => { 44 | superagent 45 | .post('/logout') 46 | .end((err, res) => { 47 | if (!err) 48 | window.location = '/signup'; 49 | else 50 | return; 51 | }) 52 | } 53 | 54 | render() { 55 | let tabs = [] 56 | let selectedTab = this.props.tabs.filter((tab) => { 57 | return this.props.location.pathname.indexOf(tab.value) === 0 58 | })[0] 59 | 60 | if (selectedTab) 61 | selectedTab = selectedTab.value 62 | 63 | this.props.tabs.forEach((tab) => { 64 | tabs.push() 74 | }) 75 | tabs.push() 86 | 87 | return ( 88 |
89 | } 103 | iconElementRight={ 104 |
105 | {this.props.extraTop} 106 | { 109 | this.props.history.push(value) 110 | }}} 111 | > 112 | {tabs} 113 | 114 |
115 | } 116 | /> 117 |
118 | ) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/plugins/clipboard/dialogs/paste.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | CKEDITOR.dialog.add("paste",function(c){function h(a){var b=new CKEDITOR.dom.document(a.document),f=b.getBody(),d=b.getById("cke_actscrpt");d&&d.remove();f.setAttribute("contenteditable",!0);if(CKEDITOR.env.ie&&8>CKEDITOR.env.version)b.getWindow().on("blur",function(){b.$.selection.empty()});b.on("keydown",function(a){a=a.data;var b;switch(a.getKeystroke()){case 27:this.hide();b=1;break;case 9:case CKEDITOR.SHIFT+9:this.changeFocus(1),b=1}b&&a.preventDefault()},this);c.fire("ariaWidget",new CKEDITOR.dom.element(a.frameElement)); 6 | b.getWindow().getFrame().removeCustomData("pendingFocus")&&f.focus()}var e=c.lang.clipboard;c.on("pasteDialogCommit",function(a){a.data&&c.fire("paste",{type:"auto",dataValue:a.data,method:"paste",dataTransfer:CKEDITOR.plugins.clipboard.initPasteDataTransfer()})},null,null,1E3);return{title:e.title,minWidth:CKEDITOR.env.ie&&CKEDITOR.env.quirks?370:350,minHeight:CKEDITOR.env.quirks?250:245,onShow:function(){this.parts.dialog.$.offsetHeight;this.setupContent();this.parts.title.setHtml(this.customTitle|| 7 | e.title);this.customTitle=null},onLoad:function(){(CKEDITOR.env.ie7Compat||CKEDITOR.env.ie6Compat)&&"rtl"==c.lang.dir&&this.parts.contents.setStyle("overflow","hidden")},onOk:function(){this.commitContent()},contents:[{id:"general",label:c.lang.common.generalTab,elements:[{type:"html",id:"securityMsg",html:'\x3cdiv style\x3d"white-space:normal;width:340px"\x3e'+e.securityMsg+"\x3c/div\x3e"},{type:"html",id:"pasteMsg",html:'\x3cdiv style\x3d"white-space:normal;width:340px"\x3e'+e.pasteMsg+"\x3c/div\x3e"}, 8 | {type:"html",id:"editing_area",style:"width:100%;height:100%",html:"",focus:function(){var a=this.getInputElement(),b=a.getFrameDocument().getBody();!b||b.isReadOnly()?a.setCustomData("pendingFocus",1):b.focus()},setup:function(){var a=this.getDialog(),b='\x3chtml dir\x3d"'+c.config.contentsLangDirection+'" lang\x3d"'+(c.config.contentsLanguage||c.langCode)+'"\x3e\x3chead\x3e\x3cstyle\x3ebody{margin:3px;height:95%;word-break:break-all;}\x3c/style\x3e\x3c/head\x3e\x3cbody\x3e\x3cscript id\x3d"cke_actscrpt" type\x3d"text/javascript"\x3ewindow.parent.CKEDITOR.tools.callFunction('+ 9 | CKEDITOR.tools.addFunction(h,a)+",this);\x3c/script\x3e\x3c/body\x3e\x3c/html\x3e",f=CKEDITOR.env.air?"javascript:void(0)":CKEDITOR.env.ie&&!CKEDITOR.env.edge?"javascript:void((function(){"+encodeURIComponent("document.open();("+CKEDITOR.tools.fixDomain+")();document.close();")+'})())"':"",d=CKEDITOR.dom.element.createFromHtml('\x3ciframe class\x3d"cke_pasteframe" frameborder\x3d"0" allowTransparency\x3d"true" src\x3d"'+f+'" aria-label\x3d"'+e.pasteArea+'" aria-describedby\x3d"'+a.getContentElement("general", 10 | "pasteMsg").domId+'"\x3e\x3c/iframe\x3e');d.on("load",function(a){a.removeListener();a=d.getFrameDocument();a.write(b);c.focusManager.add(a.getBody());CKEDITOR.env.air&&h.call(this,a.getWindow().$)},a);d.setCustomData("dialog",a);a=this.getElement();a.setHtml("");a.append(d);if(CKEDITOR.env.ie&&!CKEDITOR.env.edge){var g=CKEDITOR.dom.element.createFromHtml('\x3cspan tabindex\x3d"-1" style\x3d"position:absolute" role\x3d"presentation"\x3e\x3c/span\x3e');g.on("focus",function(){setTimeout(function(){d.$.contentWindow.focus()})}); 11 | a.append(g);this.focus=function(){g.focus();this.fire("focus")}}this.getInputElement=function(){return d};CKEDITOR.env.ie&&(a.setStyle("display","block"),a.setStyle("height",d.$.offsetHeight+2+"px"))},commit:function(){var a=this.getDialog().getParentEditor(),b=this.getInputElement().getFrameDocument().getBody(),c=b.getBogus(),d;c&&c.remove();d=b.getHtml();setTimeout(function(){a.fire("pasteDialogCommit",d)},0)}}]}]}}); -------------------------------------------------------------------------------- /src/frontend/public/admin/events/static/ckeditor/samples/toolbarconfigurator/js/fulltoolbareditor.js: -------------------------------------------------------------------------------- 1 | window.ToolbarConfigurator={}; 2 | (function(){function e(){this.instanceid="fte"+CKEDITOR.tools.getNextId();this.textarea=new CKEDITOR.dom.element("textarea");this.textarea.setAttributes({id:this.instanceid,name:this.instanceid,contentEditable:!0});this.editorInstance=this.buttons=null}ToolbarConfigurator.FullToolbarEditor=e;e.prototype.init=function(b){var a=this;document.body.appendChild(this.textarea.$);CKEDITOR.replace(this.instanceid);this.editorInstance=CKEDITOR.instances[this.instanceid];this.editorInstance.once("configLoaded",function(d){var c= 3 | d.editor.config;delete c.removeButtons;delete c.toolbarGroups;delete c.toolbar;ToolbarConfigurator.AbstractToolbarModifier.extendPluginsConfig(c);d.editor.once("loaded",function(){a.buttons=e.toolbarToButtons(a.editorInstance.toolbar);a.buttonsByGroup=e.groupButtons(a.buttons);a.buttonNamesByGroup=a.groupButtonNamesByGroup(a.buttons);d.editor.container.hide();"function"===typeof b&&b(a.buttons)})})};e.prototype.groupButtonNamesByGroup=function(b){var a=this;b=e.groupButtons(b);for(var d in b)b[d]= 4 | e.map(b[d],function(b){return a.getCamelCasedButtonName(b.name)});return b};e.prototype.getGroupByName=function(b){for(var a=this.editorInstance.config.toolbarGroups||this.getFullToolbarGroupsConfig(),d=a.length,c=0;c