diff --git a/book/processes/00index.adoc b/book/processes/00index.adoc index e3997a3..78e3fac 100644 --- a/book/processes/00index.adoc +++ b/book/processes/00index.adoc @@ -2,5 +2,5 @@ include::code-merging.adoc[] include::github-create-pr.adoc[] -include::github-pr-merge-squash.adoc[] +include::github-squash-commit.adoc[] include::quality-engineering.adoc[] diff --git a/book/processes/branch_history.png b/book/processes/branch_history.png new file mode 100644 index 0000000..170bf81 Binary files /dev/null and b/book/processes/branch_history.png differ diff --git a/book/processes/commit1.png b/book/processes/commit1.png new file mode 100644 index 0000000..641b27e Binary files /dev/null and b/book/processes/commit1.png differ diff --git a/book/processes/commit2.png b/book/processes/commit2.png new file mode 100644 index 0000000..8048f30 Binary files /dev/null and b/book/processes/commit2.png differ diff --git a/book/processes/commit3.png b/book/processes/commit3.png new file mode 100644 index 0000000..d650ef8 Binary files /dev/null and b/book/processes/commit3.png differ diff --git a/book/processes/commit4.png b/book/processes/commit4.png new file mode 100644 index 0000000..8bc85fe Binary files /dev/null and b/book/processes/commit4.png differ diff --git a/book/processes/github-pr-merge-squash.adoc b/book/processes/github-pr-merge-squash.adoc index 550b72c..b16a93d 100644 --- a/book/processes/github-pr-merge-squash.adoc +++ b/book/processes/github-pr-merge-squash.adoc @@ -1,6 +1,6 @@ == GitHub PR-merge-squash Workflow -When using GitHub there are a variety of possible workflows. Each has their +When using GitHub there are a variety of possible workflows. Each has their own merits, but for a large, long-running project with a number of committers it is worth considering taking the extra time to follow a fork, merge-squash strategy. @@ -10,14 +10,14 @@ roles may not necessarily filled by different people, but for the sake of clarit step is assigned to one of them. Product Management:: - Product Management tasked with understanding the long term goals of the project and - measuring progress towards them. These people are also responsible for outlining the work + Product Management tasked with understanding the long term goals of the project and + measuring progress towards them. These people are also responsible for outlining the work to be done and verifying that changes made work as expected. Maintainers:: Maintainers are the technical staff responsible for maintaining the repository. They are responsible for approving the code and keeping it moving through the pipeline. Contributor:: - Contributors are the technical staff responsible for implementing features. + Contributors are the technical staff responsible for implementing features. === Steps @@ -26,14 +26,13 @@ a. If necessary, the project management team creates Milestones and perhaps Issu representing the work to be completed. .Contributor -1. fork the master repository to their own local repositories. -2. clone their personal fork to their local workstation -3. create branches for each line of work on their local repository -4. write code, committing it to their branch frequently -5. push their local feature-branch to their personal fork on github -6. use GitHub's "Compare and Pull Request" feature to open a pull request against +1. create a branch from the master branch in the wisertogether repository. +2. clone their branch to their local workstation +3. write code, committing it to their branch frequently +4. push their local feature-branch to the wisertogether repository +5. use GitHub's "Compare and Pull Request" feature to open a pull request against the master repository -7. update the pull request's description field with an accurate description of the +6. update the pull request's description field with an accurate description of the change, conforming to the commit message guidelines * the first line of the message shoul be 58 char or less and contain the milestone number * the 3rd and subsequent lines should contain the text "fixes #xxx" where xxx is the @@ -50,54 +49,7 @@ a. If necessary, the project management team creates Milestones and perhaps Issu 2. provide updated commits to their branch as needed. Once the pull request meets the feature requirements, code review, and is otherwise -deemed to be complete, the Maintainer will squash-merge the commit and close the associated -issues and the pull request itself. - -In order to facilitate this, the maintainer should edit their ".git/config" file and add the -following line to the `[origin]` section: `fetch = +refs/pull/*/head:refs/remotes/origin/pr/*`. -Doing that will allow you to run `git remote update --prune && git fetch` and then `git branch -r`. - -Your `git branch -r` output should look like the following, with a new "branch" for each pull request. - ----- - - * [new ref] refs/pull/10/head -> origin/pr/10 - * [new ref] refs/pull/11/head -> origin/pr/11 - ----- - -You can use `git log origin/pr/10` to view the changelog for the PR, `git diff origin/pr/10` to see the changes. - -To merge the change, use `git merge --squash origin/pr/10 -m 'COMMIT MESSAGE'` - -For the commit messge, copy the description from the pull request. It should look something like this: - ----- - - M1 - implement new frob-nizz feature - - - lint all the files, fixes #1 - - add some huge dependencies, fixes #2 - - implement new frobb-nizz features, fixes #10 - ----- - -In particular, you'll need to add the last line, (fixes #10) to mark the pull request as closed. - -Once the Maintainer is happy with the commit and commit message, simply push it back to the origin repo -with `git push origin master`. When GitHub sees the commit and the fixes #xxx lines in the commit message, -it will automatically close out all the associated issues. - -There is also a short script to help with handling this. Copy the following script to someplace on your path, -for instance `$HOME/bin/git-mergepr` and mark it as executable. Then you can simple execute `git mergepr 10` or -`git mergepr` to see a list of the available pull requests. - -[source,ruby] ----- -include::git-mergepr.rb[] ----- - -Once the Contributor sees their pull request has been closed, they can simply delete their branch with the -"delete branch" button in the GitHub UI, and pull the updated master branch to their local repository to base -future work upon. +deemed to be complete, the Maintainer will merge the pullrequest and close the associated +issues and the pull request itself by including `fixes #000` in the pull request. +The maintainer, upon merging the pull request, should also delete the feature branch that the pull request was created from. diff --git a/book/processes/github-squash-commit.adoc b/book/processes/github-squash-commit.adoc new file mode 100644 index 0000000..ebe759a --- /dev/null +++ b/book/processes/github-squash-commit.adoc @@ -0,0 +1,53 @@ +== GitHub Develop-Squash-Commit Workflow + +This is an alternative workflow to allow easier merging for PR merge masters. + +The follow steps outline how to do this: + +We assume origin is the remote repo you are working on + +open a git command window and first do a: + +git checkout master + +git pull origin master + +image::commit1.png[Commit1] + +You may need to update the archery sub-module folder. + +To do this you can delete the archery folder in your project + +then do a: + +git submodule update + +This will re-point and checkout archery with the current latest version. + +Now finally you should rebase to master and apply your work on top of it +and squash-commit any commit messages which you don't want to belong. + +git checkout + +git rebase -i master + +image::commit2.png[Commit2] + +It is recommended to do your first commit as the commit message you want +to use. In our example we use fixup to discard the commit message but squash +the changes into the previous commit. Hence the reason why the first commit +message should be the sensible one you want to use + +image::commit3.png[Commit3] + +You should exit the editor and execute the rebase by doing :wq (in windows) + +You should see a screen like this if everything is successful. + +image::commit4.png[Commit4] + +Finally you can double check the branch history has squashed or fixed all commits +into one by visualisaing the branch history you should see just one commit line +like this: + +image::branch_history.png[BranchHistory] diff --git a/book/standards/css/00index.adoc b/book/standards/css/00index.adoc index e69de29..fd68bee 100644 --- a/book/standards/css/00index.adoc +++ b/book/standards/css/00index.adoc @@ -0,0 +1,151 @@ +== CSS & Less Guide + +The new site for Wiser Health is going to contain many services and applications built by many teams; we will need a set of fundamental goals and constraints to ensure long term success. Our five topics will be: + +. How do we handle core and/or external CSS frameworks versus custom work? +. How do we manage cross-browser compatibility? +. What is the relationship between our markup and our styling? +. What are the considerations for modularity, hierarchies, and best practices? +. How do we design to be device-agnostic? + +The quantifiable benchmarks are: + +. The CSS or LESS will be manageable, instead of being too large, cumbersome, or undocumented. +. There will be few if any instances of redundant work or cross-contamination. +. Uniformity of styling will be such that authorship is anonymous and irrelevant. +. Developers can enter or leave the project at any time with minimal on-boarding or knowledge sharing. +. The visual presentation of the site maintains a consistent and cohesive design aesthetic. + +=== CSS & LESS Rules and Principles + +==== I. Frameworks Versus Custom Styling + +Our core framework will be Twitter Bootstrap (currently in v.3.0.2). As we may be using newer versions of Boostrap, the component itself will go untouched. Any work that is developed must be done to build upon or complement Boostrap, or any other framework. For example, Bootstrap's grid system is defined in grids.less and mixins.less. We can create a new breakpoint that can add to the current list of breakpoints, without having to completely rewrite grids.less. + +There will be one main.less file that each page calls. Inside main.less, we will import the parts of Bootstrap as needed, along with any other custom styling. Custom styling will live in a static directory independent from external components. + +==== II. Cross-Browser Compatibility and Fallbacks + +We will design for a fictionally ideal browser that is completely standards-compliant. Obviously, this cannot work in practice. *_Any other styling used as a fallback must be placed in a separate file._* Such a file can be named something like ie_navbar.less to contrast with the ideal navbar.less file. We are doing this because there will come a day when we no longer have to support any number of older browsers, and it must be easy to remove styling for unsupported browsers. Redundant work today, easy of transitition tomorrow. + +*_We will not be using IE conditional comments at top of any file_*, as they pollute the declaration. IE conditional comments are allowable to include JS files, or at the declaration. The current implementation of conditional commenting is: + +---- + + + + + + + +---- + +CSS to capture only IE7 + +---- +.ie7 {} +---- + +CSS to capture only IE8 + +---- +.ie8 {} +---- + +CSS to capture only IE9 + +---- +.ie9 {} +---- + +CSS to capture both IE7 and IE8 (The majority of fallback CSS should come from this class) + +---- +.ie7_8 {} +---- + +CSS to capture IE7, IE8, and IE9 +---- +.ie {} +---- + +==== III. HTML Markup and Styling + +Structured Outline:: Using a combination of appropriate and semantic HTML5 tags and heading hierarchies, *_the page must maintain structured outline._* There will be no untitled sections, and the outlining structure must make semantic sense. See http://html5doctor.com/outlines/ or http://coding.smashingmagazine.com/2011/08/16/html5-and-the-document-outlining-algorithm/ for reference. + * The essential test for structured outline is available via http://gsnedders.html5.org/outliner/ It will show a visual representation of the page's sectioned content and the names of each part. Sections that have been improperly defined will be listed as _"Untitled Section."_ + * The steps to correct improper sectioning are prioritized as: + ** Reduce the amount of HTML nesting and hierarchy + ** Reduce the amount of CSS nesting and hierarchy, and define attributes based on classes and names + ** Determine whether a block element is for actual sectioning or just for visual presentation and alignment. Convert sectioning elements to DIVs, or vice versa. + ** create header elements that are set to display:none; in CSS + * The metric for properly structured HTML is a much leaner amount of templating needed to generate page features. Likewise, the amount of CSS needed to style the features will be significantly reduced as well. + +Respect ARIA Roles:: Pages will have landmark roles (banner, contentinfo, search, main) and we ought to develop CSS around those roles. Additionally, define CSS around widget and document roles where applicable. See http://www.w3.org/TR/wai-aria/roles. + +==== IV. Best Practices: Modularity, Hierarchies, Naming Conventions, Etc. + +Modularity Based shared components and layout pieces:: Since the compiler will combine all the CSS into one file, we have an opportunity to make as many stylesheets as we need, each serving a singular purpose. There will be three kinds of CSS files. + . Global resets and variables such as a normalize, typography and/or utilities + . component parts like the styling for buttons, forms, or tables + . Page or application features like a navigation menu, data table, or footers + +Include description in every file:: The risk of moving to pre-process CSS changes such that instead of worrying about giant bloated files, we now have to worry about too many files, of which we may lose track. *_All LESS files must contain a summary of purpose at the top._* + +Naming Conventions:: Even though LESS allows for deep nesting, we will *_avoid nesting too deep_*, as it taxes resources and creates cumbersome styling. Take advantage of uniquely occurring (once per page) #IDs to keep nesting as shallow as possible. Currently we will say that nesting should not go past 5 layers. + +* If a feature on a page exists only once, then identify that feature with an #id {} and nest all properties of elements of that feature within. +* If the feature requires classes, prefix the class names with the id name or nest them under the id. +** For example, if there is sidebar for blog links, all elements for that sidebar will be under #blog_links_sidebar {} which can contain nested classes such as .primary_link {}. In such a manner, the class .primary_link {} will not interfere with anything else on the page that may coincidentally share the same class name. On the hand if we don't want to nest this class and have out of #blog_links_sidebar {} then the class must be named .blog_links_sidebar_primary_link {}. + +Sizing:: With the exception of global resets for font sizing, legacy browser support, and defining breakpoints, *_do not define anything using pixels._* Use EMs or REMs, depending on context or relevancy. + +==== V. Device-Agnostic and Responsive Design + +The styling for all pages and applications will assume that we do not have control over the browser, viewport, or device being used. Breakpoints must be defined such that there is coherent presentation and behavior regardless of screen size or available user interaction (e.g. touch screens versus mouse control). + +*Responsiveness is going to use breakpoints that go from smallest to largest,* not largest to smallest. The definitions are as follows: + +* Browser widths *below 768 pixels*: currently out of scope + +* Browser widths at *768 to 991 pixels* + ** Covers screen resolutions of 768 and 960 (tablet space) + ** Content width fixed at 768: 12 columns of 64 pixels + +* Browser widths at *992 to 1199 pixels* + ** Covers screen resolutions of 1014 and 1152 (landscape tablets and small monitors) + ** Content width fixed at 960 pixels: 12 columns of 80 pixels + +* Browser widths at *1200 to 1329 pixels* + ** Covers screen resolution of 1280 (standard desktop monitors) + ** Content width fixed at 1152 pixels: 12 columns of 96 pixels + +* Browser widths at *1300 pixels and higher* + ** Covers screen resolutions of 1366, 1440, and up (standard laptop screens, Macbook screens, and large monitors) + ** Content width fixed at 1296 pixels: 12 columns of 108 pixels + +Consequently, the width of the content of the site will never exceed 1296 pixels. + +=== Benchmarks for Success + +==== I. Managable, Well-Documented CSS and Styling + +How do I change the font size of the menu items in the global navigation? How do I add styling for error messages on the membership form? These questions should be solvable without excessive hunting or asking for help from previous developers. + +Our living KSS style guide will reflect what the site looks like. + +==== II. Concurrent Work without Overlapping + +Work submitted from one project will not interfere with work from another project, now or in the future (This is where proper naming conventions becomes highly relevant). If there is commonly shared component across multiple pages or applications, there, only one CSS file is generating that visual presentation. + +==== III. Anonymous and Uniform Authorship + +The mark of good coding or scripting is nobody determine who wrote it. To achieve this, all developers entering into the various projects of WiserHealth will have agreed on best practices, and all peer reviews will take measures to enforce such practices. We do not ownership of parts of the code. We do not want information silos. + +==== IV. Flexible Entry and Exit for Developers + +We will be using contractors depending on projects, and WiserTogether will have developers coming in and out of projects, or leaving or being hired. New people should not have spend weeks familiarizing themselves with the CSS and LESS frameworks, and people leaving should have to devote too much time explaining or training replacements. + +==== V. Consistent Visual Design Implementation and Aesthetic + +What separates a passable site from a professionally done site is attention to detail. The typography cannot look a certain way on one page and be slightly off on another page. Transitions and interactions will behave the same way, every time. In other words the true measure of success is achieving a singular, identifiable "look and feel." + diff --git a/book/standards/javascript/00index.adoc b/book/standards/javascript/00index.adoc index b46c144..cac58bd 100644 --- a/book/standards/javascript/00index.adoc +++ b/book/standards/javascript/00index.adoc @@ -163,3 +163,58 @@ This is recommended jsformat settings when using Sublime Text 2 ---- include::jsformat_recommend.js[] ---- + +[[Backbone Patterns]] + +Here is a list of good patterns and pratices while developing and +building Backbone applications. + +File structure: + +In most projects in wiser it is recommended to follow this type of structure: + +/... + + /collections + /handlebars + /models + /templates + /views + app.js + router.js + views.js + +Views: + +The /views folder should be seperated by module name in larger projects + +e.g. + +/views + /header + /nav + /module1 + /module2 + base.js + mixins.js + +Following best practices it is better to not do any rendering code within the +view class unless there is good reason. + +---- +include::views.js[] +---- + +For view cleanup because this is not handled automatically by backbone you should +make sure that view.remove() gets called before you render or navigate to a different +page. This will allow objects/bindings/events to cleanup before you render the new +view Please see below for example of how to do this. This code would be used in +the router for example by all views which will render the view. + +Also render should only be called by this structure ALWAYS: + + $("#page-layout").html(view.render().el); // there is numerous reasons for this. + +---- +include::router.js[] +---- diff --git a/book/standards/javascript/jshintrc.json b/book/standards/javascript/jshintrc.json index 170342f..6649df0 100644 --- a/book/standards/javascript/jshintrc.json +++ b/book/standards/javascript/jshintrc.json @@ -8,6 +8,7 @@ "jquery": true, "latedef": true, "newcap": true, + "camelcase": false, "noarg": true, "node": true, "nonew": true, diff --git a/book/standards/javascript/router.js b/book/standards/javascript/router.js new file mode 100644 index 0000000..1ba98c5 --- /dev/null +++ b/book/standards/javascript/router.js @@ -0,0 +1,16 @@ + // Navigates to a page and adds the view to be removed later + navigatePage: function (view) { + that.closeViews(); + that.views.push(view); + $("#page-layout").html(view.render().el); + + }, + closeViews: function () { + // Call remove on the views currently loaded to clean up + if (this.views.length > 0) { + _(this.views).each(function (view) { + view.remove(); + }); + this.views = []; + } + } \ No newline at end of file diff --git a/book/standards/javascript/views.js b/book/standards/javascript/views.js new file mode 100644 index 0000000..cb6dc5f --- /dev/null +++ b/book/standards/javascript/views.js @@ -0,0 +1,53 @@ +// Good example + +/*global define*/ +define(function (require) { + 'use strict'; + + var Template = require('hbs!../../templates/static/contact_us'), + Base = require("nagini/views/base"), + _ = require('underscore'); + + return Base.extend({ + template: Template, + events: { + 'click button': 'sendQuestion' + }, + initialize: function () { + var args = _.clone(arguments); + this.listenTo(this, 'sendZendeskTicket', this.sendZendeskTicket); + Base.prototype.initialize.apply(this, arguments); + }, + sendQuestion: function (e) { + var ticketParams = this.getZendeskParams(); + ticketParams.tag = 'contact-us'; + e.preventDefault(); + this.trigger('sendZendeskTicket', ticketParams); + } + }); +}); + +// Bad example + +/*global define*/ +define(function (require) { +'use strict'; + +var Template = require('hbs!../../templates/static/contact_us'), + Base = require("nagini/views/base"), + _ = require('underscore'); + + return Base.extend({ + el: $('body'), // Don't reference the el object in a view like this + tagName: 'header', + initialize: function () { + this.render(); // Don't call render within initialize if you have to do this the view is setup wrong. + }, + render: function () { + // Don't add a require statement within render and any function which overrides a base class + // needs to make sure it calls its parent class always. + // Base.prototype.render.apply(this, arguments); + this.$el.append(require('hbs!templates/header')); + } + }); +});