Giter Site home page Giter Site logo

enciv / unpoll Goto Github PK

View Code? Open in Web Editor NEW
4.0 5.0 3.0 2.24 MB

How 1000's of voters work together productively to decide on what few questions to ask their candidates in undebates. Or - in untownhall's what to ask their representatives.

License: Other

JavaScript 98.66% Shell 1.34%
crowdsourcing democracy react

unpoll's Introduction

Unpoll

This is how 1000's of voters work together to democratically determine the best 4 (or so) questions to ask the candidates of an undebate. It's also a great way for constituents to figure out the top 4 (or so) priorities for the representatives to address. Read more at Crowdsourcing Candidate Questions

Here is the current working demo version: image

If you are interested in contributing to this project, join Open San Diego and look for the EnCiv project.

Copyright 2021 EnCiv, Inc. This work is licensed under the terms described in LICENSE.txt which is an MIT license with a Public Good License Condition

Getting Started

You will need to install the following, if you do not already have them.

  1. Git: On windows go to https://git-scm.com/download/win and install it. If you are on a Mac, install brew first, https://brew.sh/ and then brew install git
  2. Node.js: https://nodejs.org/en/download/
  3. Heroku: https://devcenter.heroku.com/articles/heroku-cli
  4. I use visual studio code, but you can use another environment, but you will need to be able to run git-bash terminal windows in your environment. https://code.visualstudio.com/

Setup

On your browser go to your github account and login

If you have just installed VSC you need to setup the bash shell. Use Control-Shift-P In the input field type "Select Default Shell" Choose "Git Bash"

Then open a git-bash shell - on VSC use Control-`

    git clone https://github.com/EnCiv/unpoll
    cd unpoll
    npm install

Storybook

After you have gotten this far, you should be able to run Storybook and see all the components:

npm run storybook

image

MongoDB

This app uses MONGODB and you will need a mongodb uri to get started. Cloud.mongodb.com has free accounts, you can go there and follow these instructions

you should end up with a .bashrc file that looks like this

#!/bin/bash
export NODE_ENV="development"
export MONGODB_URI="mongodb+srv://user-name:[email protected]/db-name?retryWrites=true&w=majority"

Note that it's confusing but user-name and db-name can be anything. You pick them when you create the database, and you use them in this URI string. That's all.

Run it

source .bashrc
npm run dev

You will now be able to go to http://localhost:3011

Run it in the cloud on heroku

Heroku now charges a fee, and it's not necessary to use it for development. Almost everything can be done and tested on the dev server, if not in storybook. But here's how to do heroku:

This assumes you have already created your heroku account at heroku.com and that you have installed the heroku command line interface (CLI) from https://devcenter.heroku.com/articles/heroku-cli

You will need to think of your own unique application name. If you get an error from this step, it may be because the name you thought of is not unique.

heroku create my-unique-app-name

First, lets do a few things to setup the enviromment

echo export EDITOR="code --wait" >> .bashrc
source .bashrc
heroku config:set MONGODB_URI=""
heroku config:edit MONGODB_URI

The last step will open up a new Visual Studio Code window, with nothing in it. Paste in the URI again, just the URI like:

mongodb+srv://any-name-you-want:[email protected]/anydbname?retryWrites=true&w=majority

    Then do Control-s Control-w to save and exit

Back in the terminal window you will see:

Fetching config... done

Config Diff:
- MONGODB_URI=
+ MONGODB_URI='mongodb+srv://any-name-you-want:[email protected]/anydbname?retryWrites=true&w=majority'

Update config on my-unique-aoo-name with these values?:

    hit 'y' and <Enter>

All of this is configuration stuff you only have to do once. You can push the code to the heroku server with

git push heroku

When that is done, you will be able to go to our new app by browsing to https://my-unique-app-name.herokuapp.com (don't click on this link - you will have to type in your own app-name yourself)

Then whenever you make changes to your code and you want to try it out on heroku you can:

git add .
git commit -m "a descriptive commit message"
git push heroku

Figma and SVG

You can export svg from figma and plaste it in to a .svg file in assets/svg for example assets/svg/trash-can.svg

<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 6.58661H5H21" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8 6.58661V4.58661C8 4.05618 8.21071 3.54747 8.58579 3.1724C8.96086 2.79732 9.46957 2.58661 10 2.58661H14C14.5304 2.58661 15.0391 2.79732 15.4142 3.1724C15.7893 3.54747 16 4.05618 16 4.58661V6.58661M19 6.58661V20.5866C19 21.117 18.7893 21.6257 18.4142 22.0008C18.0391 22.3759 17.5304 22.5866 17 22.5866H7C6.46957 22.5866 5.96086 22.3759 5.58579 22.0008C5.21071 21.6257 5 21.117 5 20.5866V6.58661H19Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 11.5866V17.5866" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 11.5866V17.5866" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

This project will automatically convert the files in assets/svg into react .js files in app/svgr on install. After you add a new file you can manually trigger the conversion with

npm run svgr

Then you can use these svg files as React components in your code like this:

import SvgTrashCan from '../svgr/trash-can'

function renderSomething(){
    return <SvgTrashCan />
}
...

unpoll's People

Contributors

bolunthompson avatar ciro1690 avatar ddfridley avatar techsolomon avatar thong-pham avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

unpoll's Issues

Card List Selector

Render a list of cards, and allow the user to select N (2 in the example) and then hit done.

Inputs

N: 2
question: "The text of the question to ask at the top"
cardObjs: [{},[{},{}],...]
selectedIds: []
onComplete: ()=>{}

See #15 for a description of cardObjs

The component will mutate the selectedIds list adding, or updates what's in the list. Note that on initial render, some items may already be selected.

https://www.figma.com/proto/sd8Sfv0mEbmwMrumbpjcPs/Unpoll?node-id=905%3A14150&scaling=scale-down&page-id=900%3A12241

image

unpoll web component for questions only

Modify app/web-components/unpoll.js for the questions only scenario.
Ideally - add a new property to iotas.json for path:/unpoll to indicate this is questions only, and let the code support both cases. But not required.

Ask Component

Create the component based on this page of figma:
https://www.figma.com/proto/sd8Sfv0mEbmwMrumbpjcPs/Unpoll?node-id=900%3A13786&scaling=scale-down&page-id=900%3A12241

The component should not render the NavBar - that will be done the parent component.

Use the InputElement to gather the inputs.

The "Next" button should always be there. It should be grayed out until all 4 inputs have been provided. Then it should be blue. Use the percent-done-button to do this, and go from 0 to 25, to 50, to 75, to 100%. This is a little different than what it shown in the figma, but it is more consistent with anther area of the UI and make the Next button visible, but gray, to let the user know that have to do stuff before than can go to the next step. When the user clicks Next, onDone(true) should be called

<Ask
  majorLine="What topics would you like to ask the candidates",
  minorLine="What questions do you have regarding the topics"
  onDone={(val)=>console.info(val)}
>/

The InputElement component is going to need to be modified so that it can accept an onComplete prop. When the user has finished entering the data (Enter, or onBlur) onComplete is called with the event object, where event.value is the value of the input.

A later step to this will be adding the code that makes the api call to writes the data to the database, when the user hits next. For now lets just focus on the UI.

When updating the InputElement, please look at how backCount is done in nav-bar.storeis.js to create a way of testing the onComplete function. (Or investigate if there is a better way to do that in Storybook)

Card List Grouper

In this view: https://www.figma.com/proto/sd8Sfv0mEbmwMrumbpjcPs/Unpoll?node-id=905%3A13059&scaling=scale-down&page-id=900%3A12241

  • A list of TopicCards or CardStacks should be shown.
  • At the bottom is a control button.
  • If you click on a card, it turns into a CardStack ( see app/components/card-stack) and moves to the top of the list by smoothly scrolling upward.
  • If you click on another card, it is removed from the list and added to the card stack.
  • The departure from the list should be an animated vertical shrinking of the card.
  • The control button at the bottom should say "no topics to combine, skip" when no CardStack is being created.
  • If a CardStack is being created, the control button should be gray, inactive, and say "Complete Group to Continue"
    Stretch goal:
  • The browser's back, and forward buttons move you back ward and forward in history. And Redux is not acceptable (long talk if requested)

consider, react-flip-move or react-flip-toolkit for animation of list, but open to other things too

Inputs

cardObjs: [
  {id: "abc123", description: "this is a topic"},
  [
    {id: "abc234", description: "this is a topic in a group"},
    {id: "abc345", description: "this is another topic in the group"}
  ]
 ]
onComplete: ()=>{function to be called when grouping is complete}

The component will mutate cardObjs as the users groups cards

image

more issues keep getting added

Using the dev server, if you fill in your issues and questions and then go to the next page you see other's issues. If you navigate back to the input page, and then go forward again, there are more items, and it keeps growing every time.

clustering algorithm evaluation

Create a standalone node program that generates test data, that is mongo document like, into an array.
Build a clustering algorithm and run it on the data.
Evaluate the results.

Mongo document like means it has an _id property that is a unique string.
import ObjectID from 'isomorphic-mongo-objectid/src/isomorphic-mongo-objectid'
use this to generate ObjectID.

const statements=[
  {  _id: ObjectID(),
     description: "3", // a random number
     userId: // an ObjectId
   },
...
]

const groups=[
  {  _id: 
    userId: //
    groupings: [
       [statementId1, statmentId2],
       [staementId7,statementId3]
    ],
    allStatements: [
      statementId1,
      statementId2,
      ....
    ]
  },
  ...
]

Stuck if navigate back to user-login

Running storybook, the Unpoll / With Nave Bar story
If you click accept the terms and move to the next page, if you then navigate back to the login page (back button or back arrow on the nav page), you get stuck.

It's supose to be saying logged in, but that is not visibile. (hidden under the nav bar).

But there is no navigation on this page, and there is no even to call onDone to cause it to move forward.

Unpoll logo

We are going to change the name of this project to Unpoll. We had too much negative feedback about unmob, and poll is a lot closer to what we are making better.

So - we need an unpoll logo

React State Management Design

Unpoll needs a state manager. Redux is not acceptable - it's a long discussion if interested - but here are the requirements for the state manager design

  • Ability to use the browser's forward/back buttons to move through state. This likely means that history.pushState and .popState are used
  • Ability to refresh the page, or go back to the current URL, and get to the current position/state - likely this means that state info is encoded in the URL and the URL is updated with each state change. Again, pushState and popState are likely
  • Components with state are reused in a hierarchy or recursively - so the key to a component instance's state needs to be relative to it's place in the hierarchy not absolute. This may imply that some prop does need to be passed from parent to child, but open to ideas.
  • URL/Routes to pages/Components are programmatic not constant. Look at the location.url to determine the path, or compute it.
  • Components will render on the server side first, then be rehydrated and continue on the browser side. Much data is fetched on the server side, and then passed to the browser on the initial load.
  • Data is obtained through API calls - likely it should be separate from state, but sometimes data can be changed asynchronously by the server (using socket.io connections not REST)
  • Related code should be in the same place, ideally the same file, or the same directory. Having to separate code for a single function or feature, into different directories should be avoided. (no Redux) Think of each new product features as a module, and try to keep all the pieces of that module together in one place.

Start Page

Create a component to represent both the first and second pages of the unpoll ui design:
https://www.figma.com/proto/sd8Sfv0mEbmwMrumbpjcPs/Unpoll?node-id=900%3A13708&scaling=scale-down&page-id=900%3A12241

Use the title-bar component, and the arrow-button component. Both should be fixed within the viewport.
The text of the page should come from the subject and description properties passed. If the text turns out to be taller than the viewport, the user should be able to scroll up and down. (but not left-right). The title bar and start button should not move when the user scrolls.

The name for the button (example start or continue) should come from a buttonName prop.

The onDone props, should be called (if it exists) with the value true when the user clicks the button.

The textSize prop, with value 'large' or 'small' should set the text size as in page 1 (large) or page 2 (small).

example

<StartPage
  subject:="Hello!"
  description="You have been invited to a short survey"
  buttonName="START"
  textSize: "large"
  onDone={(val)=>console.info(val)}
/>

Done Button with percent complete

React component for a done button that shows % complete by showing the background as grey for 0, and then the left % of it as blue for what % complete it is, and the whole button is blue when it's 100% complete.

image

Ignore the other lines in the image, just do the Done Button in the center.

Inputs:
name: default should be "done"
percentComplete: 0 - 1
onClick: action to take when user clicks on it

See figma here: https://www.figma.com/file/qHaWXR2BKhyz34N95tThgB/Unpoll-Design?node-id=1%3A721

algorithm for determining similar topics based on votes

Each user will see 2 topics that they have created, plus 2 topics from each of 9 other people. (20 total)
The user is asked to group the topics that are similar, and pick the one that is most representative in each group.
There will be 100's of users, and each user will be shown items at random, but each user's input will be seen an equal number of times.

Develop an algorithm for figuring out most representative groupings, based on the user input of what they group and what they select as most representative.

There will be a round based system, where if there are 1000 users, each user will review a group of 20, from 10 different users. Then, the most representative top 200 groups (10%) will be distributed at random in groups of 20 to users again, and they will be asked to group them. If there are 10000 people, another round will be added.

The number of topics a user creates, and the number of other people's input that will be shown to a users should be variables that we can tweak based on users experience. (Basically - is 20 items to many and users burn out?)

Grouping Topics UI

In the prototype UI, at https://unmob.herokuapp.com/pres-topics

To group topics, you need to single click on them,
image

And double click on one to make it the group heading.
image

And then Click on the Group Topics button to group them.
image

  • We need a more obvious, and easier to execute (on both desktop and mobile) method of selecting the lead topic than
    double click.
  • We need a better looking way to show the group of topics
  • A way to Add a new Topic to be the lead topic - this should be a secondary fuser low - where the primary and easiest user flow is to select an existing topic to be the lead
  • We need a method to open up the group again

New discussion flow without topics

To simplify things for users since they are not familiar with this, and to simplify things for ourselves technically, we want to eliminate the process steps that involve Topics, and focus only on questions.

  1. Provide 2 Questions
  2. View questions from 9 others
  3. Group similar questions
  4. Choose the most important 2 questions.

There is a branch I started https://github.com/EnCiv/unpoll/tree/simplifiedq that makes a variation of the "Ask" story that just asks for 2 questions (and not topics).

Start by checkout/pull that branch and work in there.

We need to modify the rest of the discussion around just doing 2 questions - you can do this in the "Unpoll" story.

Then I think we need to make some changes to the apis to support questions only.

Component List Slider

<ComponentListSlider>
  <Component1 >...</Component1>
  <Component2 >...</Component2>
  <Component3 >...</Component3>
</ComponentListSlider>
  • Renders the NavBar (app/components/nav-bar) and then one of the children ().
  • NavBar will pass an additional prop to each child - onDone which is a function.
  • When the child calls onDone(true) ComponentListSlider will advance and show the next child.
  • When the user clicks onBackButton in the NavBar, the ComponentListSlider will go back to the previous Component
  • The transition from one Component to the next will be an animated, smooth right to left/left to right pan (like a carousel)
  • Do not render components until they are moved to
  • Do not unmount/destroy components once they have been rendered. Just slide them off screen. (The user may come back to it, and we need to preserve the data)
  • will pass all of the props it receives, to the children, except any props that are specific to ComponentListSlider
  • Consider that different children will have different heights, but all children should be made to be 100% wide
  • The NavBar should be fixed at the top, but the child shown can be scrolled up and down.
  • On a smartphone, no scrollbar is required.
  • On a desktop - a small scrollbar on the right is required. Consider https://www.npmjs.com/package/react-perfect-scrollbar

Here is the figma for what we are talking about, but the figma does not show the smooth transition

https://www.figma.com/proto/sd8Sfv0mEbmwMrumbpjcPs/Unpoll?node-id=900%3A13786&scaling=scale-down&page-id=900%3A12241

I've been looking at carousel components on npm but I haven't figured out an easy way to make them work like this - but it may be worth further investigation. The issue is that it's the children and onDone that control when to move, not the dots, or left and right arrows. In our case, the users has to go through the steps in order. She can go backward, but can't go forward until the child says it's done.

There is a redo button in the nav bar. For now we will ignore it - there is a separate issue for state management and we will implement redo when we get that resolved.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.