Giter Site home page Giter Site logo

newspring / holtzman Goto Github PK

View Code? Open in Web Editor NEW
24.0 24.0 10.0 71.13 MB

The main NewSpring namespace and utilities for all newspring packages.

Home Page: http://holtzman.newspring.io/

License: Other

JavaScript 91.45% CSS 8.15% HTML 0.12% Shell 0.03% Ruby 0.25%
javascript jest meteor react

holtzman's People

Contributors

briankalwat avatar cdanwards avatar dcs619 avatar delianides avatar edolyne avatar isaachardy avatar jakedawkins avatar johnthepink avatar meredithrouse avatar richarddubay avatar samclaridge avatar timarney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

holtzman's Issues

Verify inActive schedule workflow

Whoever does this, please take screenshots along the way so @samclaridge can verify it is a great experience. There are some technical limitations (for instance scheduling multiple gifts as once) that required a UI change.

To verify:

  • create a schedule
  • make it inactive with a PATCH in Rock
  • login to your account

Create application id file

This should allow setting of App Name (i.e. NewSpring, NewSpring App), and application settings needed from other systems.

Giving 1.0

Giving through Apollos

this issue should act as an easy way to check off / view scope of the giving 1.0 MVP

Apollos giving is configured to use Network Merchants to process transactions and Rock to pull financial accounts, store transaction details, giving history, and schedules. The feature set required for launch is the following.

  • Give as a guest
    • Create a person record in Rock
    • Allow user to create account after gift
    • Email receipt to guest
  • Give with an account
    • Allow login to give
    • Prefill all known information in forms
    • Allow saving of payment for future gifts
    • Save gift to associated user account
    • Email receipt to user
  • Give using a saved account
    • Give in under 10 seconds
  • Set up a recurring gift
    • Create schedule in Rock
    • Create schedule in NMI
    • Alert finance of new schedule
  • Cancel a recurring gift
    • Delete it in Rock
    • Prompt user to verify they want to delete
    • Cancel plan in NMI
  • Recover a recurring gift
    • Pull in active gifts from Rock
    • Prompt to reactivate gift using payment detail
    • Set gift as active in Rock
  • View schedules
  • View giving history
    • Allow for detailed view of history
  • View saved accounts
  • Remove saved accounts
    • Removes them in Rock
    • Removes them in NMI

Most of these are already done as of Feb 24. We need to test and verify like crazy though and fix any bugs

Remaining features to build (in order of priority)

  • Prompt user to verify they want to delete scheduled gift

Priority to test

  • Give as guest
  • Give as user
  • Schedule a gift
  • Recover a schedule
  • Save a payment
  • View history
  • Cancel schedule
  • Everything else

All in all I think give is very very close. There are some bug fixes (schedule times, first payment date, and alerting finance, saving payments, and a few more) but its pretty close. We did a test with staff last Wednesday (Feb 17, 2016) and it went over pretty well. I'd like to do another test this coming week if possible.

cc @johnthepink @samclaridge

Verify CVV match requirement with NMI

This may be a setting we are missing. We need to verify a mismatch will fail a transaction. That way a successful gift can also mean a successful saved account if checked

Profile 1.0

NewSpring Account

this issue should act as an easy way to check off / view scope of the profile 1.0 MVP

The initial scope of the NewSpring account is focused around data integrity and existing account merging. It is critical that this part of the site / app be excellent as it is the easiest way to loose the trust of our users. The initial scope of profile is as follows:

  • Signup for an account
    • Creates user in Rock
    • Logs in user
    • Displays welcome to your NewSpring account message
  • Signin to your account
    • Syncs PersonId and PersonAliasId with Rock
  • Reset your password
    • Sends email through Rock with link to reset
    • Allows you to reset password
  • Update your information
  • Change your password
  • Update your address
  • Update your profile photo

Most of these are already done as of Feb 24. We need to test and verify like crazy though and fix any bugs

Remaining features to build (in order of priority)

  • Reset password workflow
  • Upload photo

Priority to test

Same order as scope

Profile is close already. I don't love the navigation on desktop of settings but its okay for launch probably. We need to test with staff accounts, infellowship accounts, and database accounts. This needs to be easy to use and reliable. I do think it is in a good place though

cc @johnthepink @samclaridge

Will not run on docker within circle ci

You can recreate the issue easily by SSHing into a circle ci build and executing these commands.

docker run -a stdin -a stdout -a stderr -i -t ubuntu /bin/bash
apt-get install curl
curl https://install.meteor.com/ | sh
apt-get install vim
cd /home/
meteor create app
cd app/
vim .meteor/packages

Once in VI, append a newline with velocityjs:velocityjs. Then exit VIM and run this command to execute the installation:

meteor update

You will get this error:

Error: EINVAL, chown '/tmp/<random dir>/<package you added>'

Running this in docker on my machine (Mac OS X) works correctly, but in CI, it always throws the error.

Questions I am trying to answer:

  • Why does it happens on a circle box, even though it's all within a docker container?
  • Why do certain packages (like velocityjs:velocityjs) trigger the error? bjwiley2:server-watch does as well.

What I've tried with no success:

  • Switching the directories that the meteor app is created in
  • Using sudo to try and fix the chown issue
  • chown nobody:nogroup /tmp
  • Cloning bjwiley2:server-watch into my projects packages directory to see if it would run locally (it did)
  • Installing package dependencies directly (like http and jquery) to see if one of those was the problem
  • Tried to recreate problem on Ubuntu Server to see if it was working locally only because I was on OS X. It worked. the problem is still only on circle boxes.

Paginate Groups

Ideally lets return 10 at a time. The GQL server can return back the total results if wanted.

Apollos state management

Apollos States

Applications built on Apollos can expose two types of client side views: pages and cards.

Pages exists only via hitting a specific route and are meant to be the more traditional style view (think server side rendered). The subscription of data for pages happens entirely within the Apollos.Router route for the given page. Ideally these are set or configured) only on the top level application view (i.e. the site or app that is using the Apollos framework). The template for the page includes markup, components and cards (among other things).

Cards are patterned usages of components and subscription of data to supply components with cached data. This is important because when a component is destroyed, the client side data is jettisoned prior to the next template render. In order to cache the dataset between components, a card should specify what data will / can be shared by components to prevent over subscription. The goal of a card is it can be included (and optionally configured) on any page in an apollos application. Cards can also change the url of the application and read from the url to set the state of the card. This is useful for page reload or sharing links.

In order for cards to be used as pages (so that state can be bubbled up to the router and visited at a url), the state management of cards should be extendable to routes. For example:

  1. A user starts filling out data for a form
  2. Halfway through they lose internet connection or encounter an error
  3. The user reloads the page as learned behavior from the web
  4. User should right where they were with as much data
    preserved as possible

The form is a card that can be used inline on any page. The top level application (view) should be able to configure routes of cards to customize the application. (e.g. all giving shouldn't have to be at /give//add-to-fund).

State management is helpful to preserve temporary data between components as well without a write to the minimongo or server side db. This can be done with card level reactive variables that all child components can read from or write to.

Setting a state should be done within each card component and should relate to a top level card.

In order to best explain this API and structuring, lets look at a sample card and its corresponding components and pages. For this example we will look at a card representing an account / item that money can be given towards.

Below are the files we will be working with for the sample fund card.
Note that the file system shown below is abbreviated and is not meant for large scale projects

- client
  - components
    - fund.add-to-fund.coffee
    - fund.add-to-fund.html
    - fund.summary.coffee
    - fund.summary.html
    - fund.vision.coffee
    - fund.vision.html
  - give.fund.coffee
  - give.fund.html
  - give.html
- lib
  - collections.coffee
  - router.coffee
- server
  - publications.coffee

The first thing we will need to do is set up a collection and publish it to
the client

# lib/collections.coffee
Apollos.Funds = new Mongo.Collection "funds"

fund = Apollos.generateSchema
  name:
    type: String
  imageUrl:
    type: String
    optional: true
  description:
    type: String
    optional: true

Apollos.Funds.attachSchema fund
# server/publications.coffee

# all funds, all fields
Meteor.publish "funds", ->
  Apollos.Funds.find()

# one fund, all fields
Meteor.publish "fund", (fundId) ->
  Apollos.Funds.find(fundId)

Now that we have our collection and publications setup we can start to look at the client side application. The first thing to do is set up a layout template to render our page into. Then we will set up the give page.

<!-- client/give.html -->
<template name="layout">
  {{! simple layout to include templates using Apollos.Layout}}
  {{> Template.dynamic template=layout data=currentData}}
</template>

<template name="give">

  {{#each funds}}
    {{> give.fund name=name}}
  {{/each}}

  {{! Any other presentation data here}}

</template>

This template includes a head and body which would normally be abstracted to layouts. It also loops through all funds {{funds}} and includes a give card for each using the name as the identifier {{> give.fund name=name}}

In order to get the data to /give we have two choices. One is to create a give component and subscribe to the data that way. The other is to use Apollos.Router to set up a route at /give and subscribe to the data there.

For pages it is preferable if the data is managed in the router that way the data can be server side loaded.

# lib/router.coffee
Give = Apollos.Router.group({
  prefix: "/give"
  subscriptions: ->
    # subscribe to all funds for any page within /give
    @.register("funds", Meteor.subscribe("funds"))
})

# /give
Give.route("/", {
  action: ->
    # render home page of give
    Apollos.Layout.render("layout", {template: "give"})
})

Give.route("/:fund", {
  action: (params, queryParams)->
    # render page of a single fund
    Apollos.Layout.render("layout", {
      template: "give.fund"
      name: params.fund
    })
})

Alright, at this point we have our data published to the client, a route set up at /give to show all funds, and the client has subscribed to the data for funds so we shouldn't have to worry about missing data. Now time to set up the actual fund card. This is the part that could be used on any page and should just work.

First thing we will do is make the template to show a simple card.

<!-- client/give.fund.html -->
<template name="give.fund">
  {{#if subscriptionsReady}}
    {{#with fund}}
      <img src="{{imageUrl}}"/>
      <h1>{{name}}</h1>

      <a href="#">
        Information
      </a>

      <a href="#">
        Give now
      </a>

    {{/with}}
  {{else}}

    {{! show loading state here}}

  {{/if}}
</template>

The only problem at this point is our {{#with fund}} doesn't have any data for {{fund}}. We could have handled this in our /give page by wrapping each render in {{#with}} {{/with}} blocks BUT then in order to use the card elsewhere, we would have to do the subscription and lookup instead of the fund card handling its own data. In order to get data to the card we create an give.fund component and can populate the fund loading here. because of our router, if a fund is used within a /give/* page, all data that it needs will already be stored client side

# give.fund.coffee
class give.fund extends Apollos.component
  @register "give.fund"


  # subscribe to fund publication with filter on fund specified
  subscriptions: -> [

    "fund":
      args: [
        @.data()?.name
      ]

  ]

  # populate helpers within template to show fund data
  fund: ->

    name = @.data()?.name
    return Apollos.Funds.findOne({name: name})

Now we should have pictures and names for any funds in our database! With a little setup, you can render pages with Apollos.Router and Apollos.Layout. Now we need to setup the internal workings of the give.fund card.

The makeup of this card is as follows:

  1. Summary (default)
  2. Vision
  3. Add to Fund

Still in progress

Things we need to figure out:

  1. should a template be registered as a card? (✓)
    • as of right now I don't think that it should need to be registered. The data settings on it + documentation should highlight it as a card
  2. how do you set defaults for templates? required? (✓)
    • the first element to register a card is the default
    • a card can specify a default at the card level
  3. should siblings know about each other? (✓)
    • ideally no (seperation of concerns ftw)
  4. how is data shared between elements of a card? (✓)
    • I think we can use reactive var although the list may get long in some applications, we need to test reactive var objects. So we could use the card level component as the storage provider. Within nested components how could you easily do ..get() instead of traversing parent components to find the card? Could all children inherit the reactive vars of the card or their parent? Can we persist this info between hot-code reloads if use use reactive dict? Right now reactive-dict has memory leaks which will prevent us from using it :(
    • the best solution for right now will be on a per template level decision to copy vars from the parent card to itself for the child card to use. In a way this will be setting up a reactive var tree
  5. how are cards within cards maintained?
    • it should be registered like a regular component. Access to states could be tricky for sure. The component that registered or included the child card should handle the life-cycleing of it and the state relationships
    • however card states will need to be change state of the parent card
  6. how can a card express its state in the url? (✓)
    • this one will be really tricky. Although urls are becoming less prevalent and have no meaning (kindof) in the app world. it still is a reality in the web one and can be helpful to load a specific state of an app. The state management system could allow for hooks to update the url schema.
    • I think that reading from the url on load is going to be the harder part to set. We have a few options with this. If each component state updates the url (via state change) then double loading of the url and app logic could be avoided. The loading of state should be done by the card level component which would make since that it would also handle the reading of the url.
    • in short:
      • card handles state maintenance
      • card handles reading of the url to render
      • card handles setting of the url
      • components can update the state of the card and thus the url
      • pages can configure the segments leading up to the card
      • pages can configure if a card updates the url
    • any component that registers as a card @card true will try to bind urls if the @.data().bindUrls is true (should this be default?)
  7. what are conventions for template types (pages, cards, components, etc) (✓)
    • this one will take a little more time to figure out. We are nearing thing point of confusion between the components as well as when are items capitalized and when are they not?
    • I lean towards libraries and collections being Cap case
    • templates and methods being camelCase
    • private items prefixed with _
    • no snake case
    • Globals being all caps?
  8. how can links be set in template for states? (✓)
    • this should be as simple as IR's {{pathFor 'name' data=foo}} if at all possible
    • this should read through the cards state settings to create a url that is either a normal url or a param / query string based url.
    • either way, these should create valid links for seo following and semantic markup. href="#" is to be avoided at all costs
    • {{Apollos.stateFor 'fund.vision' name=name}} (if in the parent card)
    • {{Apollos.stateFor 'fund.vision' from 'Apollos.give.fund' name=name}} (if outside the card)
  9. where are states managed? (✓)
    • on the card level component

A card has a 1 to many relation ship with its card elements. Each element has the option to register a state and url of the parent card. An element can only register with ONE card. Cards are the outer bounds of card elements and they act as the controller and data storage for the elements. When a component is registered they set what card they belong to and their stateful name. Unless specified on the card, the first to register is the default state. Pages are ultimately responsible for the initial rendering of cards. A card will parse the url onRender to decide which state to render. Cards also have no knowledge about what page they are on or what layout they are using.

Card elements can sometimes become pages? How do they do this? Sermon entry, give fund, sign-in page, etc...

Possible state getters

<a href="{{Apollos.state 'fund.summary'}}"></a>
<a href="{{Apollos.state 'fund.summary' from 'give.fund'}}"></a>

Possible registration methods for cards / card components

# give.fund.coffee
class give.fund extends Apollos.component
  @register "give.fund"
  @card true # sets this component as a card


  vars: -> [
    state: "fund.summary"
  ]

  # subscribe to fund publication with filter on fund specified
  subscriptions: -> [

    "fund":
      args: [
        @.data()?.name
      ]

  ]

  # populate helpers within template to show fund data
  fund: ->

    name = @.data()?.named
    return Apollos.Funds.findOne({name: name})

# fund.summary.coffee
class fund.summary extends Apollos.component
  @register "fund.summary"
  @card "give.fund" # set this component to belong to "give.fund" card
# fund.vision.coffee
class fund.vision extends Apollos.component
  @register "fund.vision"
  @card "give.fund" # set this component to belong to "give.fund" card
  url: "#{@.data()?.name}" # set url to update on render / read

# fund.addToFund.coffee
class fund.addToFund extends Apollos.component
  @register "fund.addToFund"
  @card "give.fund" # set this component to belong to "give.fund" card
  url: "#{@.data()?.name}/add-to-fund" # set url to update on render / read
<!-- client/give.fund.html -->
<!--

  What a normal card would look out just from a data standpoint

-->
<template name="give.fund">
  {{#if subscriptionsReady}}
    {{#with fund}}
      {{> Template.dynamic template=state.get data=currentData}}
    {{/with}}
  {{else}}

    {{! show loading state here}}

  {{/if}}
</template>

Existing card implementation (markup)

<!-- from this -->
<template name="Apollos.profile.onBoard">


  {{!-- Spacebars does not have else if statements :( --}}
  {{! Need to extend so we can have else if statements}}
  {{#if resetPasswordToken}}
    {{> resetPassword
      email=email.get
    }}
  {{else}}
    {{#if passwordForget.get}}
      {{> forgotPassword
        email=email.get
      }}
    {{else}}

      {{#if Template.contentBlock}}

        {{#signin
          email=email.get
        }}
          {{> Template.contentBlock}}

        {{/signin}}

      {{else}}

        {{>signin
          email=email.get
        }}

      {{/if}}
    {{/if}}
  {{/if}}

</template>

<!-- to this -->
<template name="Apollos.profile.onBoard">

  {{> Template.dynamic template=state.get data=currentData}}

</template>

can not create user

Trying to create a new apollos user in production results in an error:

[45.55.213.136] Exception while invoking method 'createUser' TypeError: Object.keys called on non-object
    at Function.keys (native)
    at Apollos.user.create.Accounts.createUser.email (packages/newspring:apollos-core/lib/lib/apollos.js:100:1)
    at Object.Accounts.insertUserDoc (packages/accounts-base/accounts_server.js:999:1)
[45.55.213.136]     at createUser (packages/accounts-password/password_server.js:718:1)
    at packages/accounts-password/password_server.js:738:1
    at tryLoginMethod (packages/accounts-base/accounts_server.js:161:1)
    at Object.Accounts._loginMethod (packages/accounts-base/accounts_server.js:277:1)
    at [object Object].Meteor.methods.createUser (packages/accounts-password/password_server.js:724:1)
    at maybeAuditArgumentChecks (packages/ddp/livedata_server.js:1617:1)
[45.55.213.136]     at packages/ddp/livedata_server.js:648:1

I think the issue is here:
https://github.com/NewSpring/apollos-core/blob/master/_source/lib/apollos.coffee#L92

Community 0.5

Community in Apollos

this issue should act as an easy way to check off / view scope of the community 0.5 MVP

The initial launch of community section of apollos sites and apps is focused around finding a community by location and / or know filters of a group. The data is fetched from Rock using Rock's api/Groups/ByLatLng method which is already mapped in heighliner. The initial scope of community is as follows:

  • Find groups by location
    • enter address
    • see list of groups
  • View group detail
    • see leaders
    • see location (not address)
    • see topics / age / more details
  • Request to join group
    • requires an account
    • adds person to group in Rock as pending member
    • sends email to leader with included note from the person

Most of these are already done as of Feb 24. We need to test and verify like crazy though and fix any bugs

Remaining features to build (in order of priority)

  • Request to join group
  • Paginate groups

Priority to test

  • find by location
  • request to join
  • leader is notified

Community needs the most work of all the features. The client side data management is kinda gross, the api call takes too long, and our textarea input isn't excellent. Pagination is setup in heighliner using first: 10, after: 11 arguments so its more the UI / data side we need to do. Everything should be in place to add a person to a group and send the email but we need to test it. Also, we need to add additional merge fields to the email template to include the note from the user. I also think we can remove the name field fwiw.

cc @johnthepink @samclaridge

Coordinated Game Plan

Thoughts on how we can make this happen in a week.

Focus

We all have our area's of speciality and I think we stick with those in this case to be the most efficient. Instead of owning features, I think we should own technology.

@samclaridge I think you should be in charge of final UI decisions, UI cleanup / polish, UI copy, and asset generation. This will probably amount to a lot of small PRs. The more the better.

@johnthepink you have the best expertise with React and MySQL. I think you should handle client side functionality and interactions with server side methods as well as any additional GQL mapping needed to function with EE (navee for instance).

@delianides infrastructure is your heart. Lets make it great (again). Take care of the protected branches, Circle integration, alerts / monitoring / dashboards. If there is time, lets look at the redis integration with GQL to see if we can do it better. I think we can.

I have the most experience with Rock, NMI, and the GQL server in general. I'll take those interactions and improvements.

Communication / Git

This needs to be a fluid week with minimal overlap. To do this we need to over communicate. The room #systems room in slack is a good place for real time feedback. Also, assign yourself when working on an issue and mention people as needed. @delianides I'm going to need you to keep me up to date often on deployments and alerts / dashboards so we can make sure we have somewhere to launch too.

For git, do as best as possible as 1 issue : 1 PR. This helps us review, merge, and revert if necessary.

Go team go.

cc @delianides @johnthepink @samclaridge

Rock Sync Validation

During a sync from Rock to Apollos, I received an email address like this: "[email protected]". Our email regex says this is invalid. I found Rock's email validation regex, which says that email is valid.

We could deal with this by:

  1. Switch to Rock's regex
  2. Reject emails from Rock that don't match our regex
  3. Don't validate emails on sync from Rock
  4. Use Rock's regex on sync from Rock

I've run in to a few issues like this when validating data received from Rock. For instance, we had a validation on birth year that it could not be less than 1900, but apparently there are people in Rock with birth years before 1900. I've dealt with those temporarily by turning off that validation.

Form Validation

Form validations are acting strange. It looks like the Apollos.profile.information disabled variable is getting set to false incorrectly. This allows you to move through the forms without providing the correct information. I tried to track it down, but filing the issue so we can come back to it later.

Finalize reset password workflow

  • reset password form
  • url to reset password with token
  • email setup in Rock (use ResetUrl, UserLogin, and Person as the data passed to the {{Lava}} template

Send welcome email on account generation

Should be setup in Rock. Will need the Person and UserLogin model passed into it and used in the {{Lava}} template. Check with @jonhorton, he's got plans.

I'd like to loop moleman in on this. I think he would do a great job. Would he be open to doing it as a favor?

Use SSL for GQL Server

@delianides there is an open PR on Heighliner for the application modifications for this. We need the cert installed (should be already on Rancher yes?)

Release 1.0

Apollos 1.0

this issue should act as an easy way to check off / view scope of the general apollos framework for 1.0 MVP

The initial scope of apollos is shared between my.newspring.cc (newwwwspring.cc repo) and the newspring-app. It handles communication with the GraphQL server and with Rock, and sets the base for future work done by the Systems team. This issue is a catch all for misc features needed by launch:

  • Discover section
    • search using google site search
    • discover using promotions_newspring low reorder set
  • Navigation from EE
    • use navee to pull data
    • open app links in app, site links in site
  • Stable infrastructure
    • Containerized env
    • CD / CI
    • alerts / monitoring

cc @johnthepink @samclaridge

Apollos style guide

All in all we need to set a style guide for things in Apollos. At this point I think we have worked enough to see some pain points and what is helpful. Leh go!

In no order:

  1. client side pages should be grouped under a pages folder
  2. each page should have its own folder named <top-level-segment>.group (eg. give.group contains all pages that are found at /give)
  3. files should be named in dash-case (e.g. fund.add-to-fund )
  4. global libraries should be capitalized (e.g. Rock, Apollos, Ldap)
  5. Collections and reusable methods should be capitalized and attached to a parent object if possible (e.g. Apollos.Component, Apollos.Router, Apollos.People)
  6. Templates should be grouped to keep the global namespace clean
  7. When declaring a new group or a shared variable between files, do it in a _vars.js file at the top of the folder containing the files using it.

(more to come)

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.