removes tutorial docs and irrelavent readme and todo files, updates docs build to exclude tutorials header

This commit is contained in:
Shannon
2015-06-17 11:56:20 +02:00
parent 2751a4a02d
commit d77f95f29b
29 changed files with 7 additions and 2893 deletions

View File

@@ -1,168 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Test-driven developement flow for Umbraco 7</h1>
<p><em>This document tries to outline what is required to have a test-driven setup for
angular developement in Umbraco 7. It goes through the setup process as well as how
to add new services that requires mocking as well as how to use grunt to run tests automaticly.</em></p>
<h2>Setup</h2>
<p>Make sure to have all the node dependencies in order when you start, these are updated regularly in case we need to go to a new version of a dependency, or new dependencies are added.</p>
<p>Simply run open a terminal / cmd in the Umbraco.Web.Ui.Client folder and run:</p>
<pre><code>npm install</code></pre>
<p>This should setup the entire grunt,karma and jsint setup we use for tests and pruning.</p>
<h2>Automated testing</h2>
<p>To start working on the client files, and have them automaticly built and merged into the client project, as well as the VS project, simply run the command</p>
<pre><code>grunt dev</code></pre>
<p>This will start a webserver on :8080 and tell karma to run tests every time a .js or .less file is changed.
After linting and tests have passed, all the client files are copied to umrbaco.web.ui/umbraco folder, so it also keeps the server project uptodate on any client changes. This should all happen in the background.</p>
<h2>Adding a new service</h2>
<p>The process for adding or modifying a service should always be based on passed tests. So if we need to change the footprint of the contentservice, and the way any controller calls this service, we need to make sure the tests passes with our mocked services.</p>
<p>This ensures 3 things:
- we test our controllers
- we test our services
- we always have mocked data available, if you want to run the client without IIS</p>
<h3>Example:</h3>
<p>We add a service for fetching macros from the database, the initial implementation should happen of this service should happen in <code>/src/common/resources/macro.resource.js</code></p>
<p>The macro.resource.js calls <code>$http</code> as normal, but no server implementation should be needed at this point.</p>
<p>Next, we describe how the rest service should return data, this is done in /common/mocks/umbraco.httpbackend.js, where we can define what data a certain url
would return. </p>
<p>So in the case of getting tree items we define:</p>
<pre><code>$httpBackend
.whenGET( urlRegex(&#39;/umbraco/UmbracoTrees/ApplicationTreeApi/GetApplicationTrees&#39;) )
.respond(returnApplicationTrees);</code></pre>
<p>The <code>returnApplicationTrees</code> function then looks like this: </p>
<pre><code>function returnApplicationTrees(status, data, headers){
var app = getParameterByName(data, &quot;application&quot;);
var tree = _backendData.tree.getApplication(app);
return [200, tree, null];
}</code></pre>
<p>It returns an array of 3 items, the http status code, the expected data, and finally it can return a collection of http headers.</p>
<pre><code>_backendData.tree.getApplication(app);</code></pre>
<p>Refers to a helper method in <code>umbraco.httpbackend.helper.js</code> which contains all the helper methods we
use to return static json. </p>
<h3>In short</h3>
<p>So to add a service, which requires data from the server we should:</p>
<ul>
<li>add the .service.js as normal</li>
<li>add the .resource.js as normal</li>
<li>call $http as normal</li>
<li>define the response data in umbraco.httpbackend.helper.js</li>
<li>define the url in umbraco.httpbackend.js</li>
</ul>
<h3>ServerVariables</h3>
<p>There is a static servervariables file in /mocks which describes the urls used by the rest service, this is currently needed as we dont have this set as a angular service, and no real conventions for these urls yet. Longer-term it would be great to have a urlBuilder which could do</p>
<pre><code>urlService.url(&quot;contentTypes&quot;, &quot;GetAllowedChildren&quot;);
//would return /&lt;umbracodir&gt;/&lt;apibaseDir&gt;/contentyTypes/getAllowedChildren</code></pre>
<p>But for now, they are set in the servervariables file. </p>
</body>
</html>

View File

@@ -1,159 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Belle Lab Tasks</h1>
<h2>Applcation Structure</h2>
<ul>
<li>Work on dialogs, plenty to choose from</li>
<li>A reuseable tree component for pickers</li>
<li>migrate all the navigation stuff into a navigation service</li>
<li>a scriptloading service to replace requireJs, with labJs, $script or similiar</li>
<li>reusable modal component (show in left side, right side, generic closing events etc)</li>
</ul>
<h2>Components</h2>
<ul>
<li>tabs directive</li>
<li>date picker</li>
<li>tabs property editor</li>
<li>localization strategy?<ul>
<li>localize filter: {{This is my default english value,content.area.key | localize}}</li>
<li>So, it will use the default value if there is none found for the key, and register this
value in the localize service, keys should not contain commas</li>
</ul>
</li>
</ul>
<h2>Chores</h2>
<ul>
<li>Write a test</li>
<li>Write docs</li>
<li>Automate something<ul>
<li>OSX:<ul>
<li>start webserver</li>
<li>start grunt watch</li>
<li>improve test output?</li>
<li>phantomJs?</li>
</ul>
</li>
<li>windows<ul>
<li>start webserver</li>
<li>start grunt</li>
<li>install node stuff?</li>
<li>register chrome_bin in path</li>
<li>or register phantomJS?</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
</html>

View File

@@ -1,198 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Codereview with Peter Bacon Darwin</h1>
<h2>Office at cogworks:</h2>
<p>71-75 Shelton Street
London
WC2H 9JQ</p>
<p>Meeting room 11 - 17</p>
<h2>Issues to go through:</h2>
<h3>Structure, dependencies and external libraries</h3>
<ul>
<li>review of modules structure and suggestions on how to handle loading things when needed.</li>
<li><p>replace requireJs for dependency loading, so we dont have to load tinyMCE, googlemaps, etc
on app start $script, yepNope, labjs?</p>
</li>
<li><p>get the app to load .aspx pages in an iframe instead of a &quot;normal&quot; view</p>
<ul>
<li>write directive for loading templates to replace ng-include</li>
<li>if .aspx, load in iframe, </li>
<li>if not found try default, finally load error msg </li>
</ul>
</li>
<li>Javascript as resources from dlls? - add a scriptService to load these? - yes
merge those resources into the umbraco.app.js file </li>
</ul>
<p><a href="http://briantford.com/blog/huuuuuge-angular-apps.html">http://briantford.com/blog/huuuuuge-angular-apps.html</a></p>
<h3>Refactoring</h3>
<ul>
<li><p>Convert tree into directive, recursive, lazy-load</p>
<ul>
<li>$watchCollection $watch on the entire tree model</li>
<li>reuse the old tree plugin to inject into dom instead of into angular</li>
<li>10 levels of digest limit</li>
<li>fine for CG, bad for release</li>
</ul>
</li>
<li><p>best practices for directives, what should we convert?</p>
</li>
<li>other areas to convert?<ul>
<li>for guidelines, look at angular/bootstrap-ui</li>
<li>replace our components with ng-bootstrap or angular-strap</li>
</ul>
</li>
</ul>
<h3>Application logic</h3>
<ul>
<li>Authentication, force login, authenticate user against acccess to sections?</li>
<li>whats the best way to handle urls, routes and state management,
so the tree, sections etc, syncs with urls and the state of the application</li>
<li>tinyMCE directive angular-ui </li>
<li>How to handle file-uploads<ul>
<li>through a service?</li>
<li>ng-upload? or jquery-upload-plugin thingy?</li>
</ul>
</li>
<li>validation, ng-form $valid and directives should be enough<ul>
<li>add remote directive: angular-app/admin/users/user-edit.js for directive code</li>
</ul>
</li>
</ul>
<h3>Dev experience</h3>
<ul>
<li><p>H Way to handle templates with missing controller? -&gt; replace ng-include? &lt;- yup
angular-app/samples/directives/fielddirective for code</p>
<ul>
<li>H generel exception handling with feedback to log or notifications service</li>
<li>L jslint code on the server?<br> <a href="http://madskristensen.net/post/Verify-JavaScript-syntax-using-C.aspx">http://madskristensen.net/post/Verify-JavaScript-syntax-using-C.aspx</a></li>
<li>L automated setup of node, grunt, jasmine and karma, powershell and .sh? </li>
</ul>
</li>
</ul>
<h3>Testing</h3>
<ul>
<li>Best way to test against service data, simply mock data in memory, or better way?</li>
<li>Testing dom manipulating components, like modals</li>
<li>e2e testing</li>
<li>teamcity intergration</li>
<li>testing templates</li>
</ul>
<h1>Notes</h1>
<ul>
<li>Javascript as resources? - add a scriptService to load these? nope, they will compile into umbraco.app.js</li>
<li>capture errors with javascript code, to not load it into the combined files
(serverside jsLint) - mads blogpost for compiling js</li>
</ul>
</body>
</html>

View File

@@ -1,178 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Naming conventions</h1>
<h2>modules handle namespacing,</h2>
<p>Naming: last one wins
but to do this automaticly, we would need
to auto-register all modules needed on app-start.
This gives us a couple of complications for handling 3rd party applications.
As it would be a pain to scan every file for modules to load on app start.</p>
<p>Proposed structure:
<a href="http://briantford.com/blog/huuuuuge-angular-apps.html">http://briantford.com/blog/huuuuuge-angular-apps.html</a></p>
<p>Register all modules in app.js
Root module: Umbraco
- contains the core services: notifications,dialogs,etc
- contains the core resources: content,media etc
- contains the core directives</p>
<p>1 module pr file princible</p>
<p>1st level modules:
Umbraco (for misc system-level stuff, dialogs, notifications, etc)
Umbraco.PropertyEditors (for all editors, as they are shared between all modules)
- how would a 3rd party property editor access a 3rd party service in the Ucommerce module, when its loaded in the content editor? (which is inside the the content module?)
Umbraco.Content (registers that it needs umbraco module, for access to core services )
Umbraco.Media
Umbraco.Settings
Ucommerce
TeaCommerce
Etc</p>
<p>Should all (core + 3rd party) services, filters and directives just be dependencies in the global umbraco module?</p>
<p>Each section namespace knows what modules to initially have loaded:
Umbraco.Content
- EditController
- SortController</p>
<p>Inside the EditController module, it references the needed services:
- DialogService
- ContentFactory
- Etc</p>
<p>So things are only loaded when needed, due to the modules, and our application, really only needs to know about the root modules, Content,Media,Settings, Ucommerce etc.</p>
<h2>Directives</h2>
<p>If more directives have the same name, they will all be run</p>
<h2>Controllers</h2>
<p>Last one wins, so you can override core controllers
Can be namedspaced, but shouldnt, the module is the namespace?
Module: Umbraco.Section.Area.Page
Name: PageNameController</p>
<p>Filename: /umbraco/section/area/pagename.controller.js
Ex: /umbraco/content/document/edit.controller.js
Ex: /umbraco/settings/documenttype/edit.controller.js</p>
<p>There is a need to have an extra level in the content tree urls due to all
other sections have this as well, and we dont want to confuse the routing.</p>
<p>The ctrl acronym is horrible and should not be used IMO.</p>
<h2>Services</h2>
<p>typeService ? - cant be namespaced
Module: Umbraco.Services.Type
Name: TypeService?</p>
<p>Ex: Umbraco.Services.Notifications.NotificationsService
Filename: /umbraco/common/services/notifcations.service.js</p>
<h2>Resources</h2>
<ul>
<li>Content, media, etc, cant be namespaced:
Module: Umbraco.Resources.Type
Name: TypeFactory?</li>
</ul>
<p>Ex: Umbraco.Resources.Content.ContentFactory?
filename: /umbraco/common/resources/content.resources.js ? or
/umbraco/common/resoures/content.factory.js ?</p>
</body>
</html>

View File

@@ -1,147 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Getting up and running with Belle</h1>
<p><em>The super fast introduction to getting belle running on your local machine, both as a pre-built environment, and with the full setup with unit-tests, grunt-tasks and node.</em></p>
<h2>Running the prebuilt site</h2>
<h3>Windows</h3>
<p>Right-click the <code>/build</code> folder and choose &quot;open in webmatrix&quot;, run the website in webmatrix and browse to <code>localhost:9999/Belle/</code>, this should display the Belle login screen</p>
<p><em>Port 9999 should be used because that is the target site that the grunt build command mentioned below will launch</em></p>
<h3>OSX</h3>
<p>Open a terminal inside the &quot;/build&quot; folder and run the command:</p>
<pre><code>python -m SimpleHTTPServer 9999</code></pre>
<p>This will start a local webserver, hosting the site on <code>localhost:9999</code> browse to localhost:9999/Belle/ which should display the belle login screen.</p>
<h2>Uing the dev environment</h2>
<p><em>The dev environment is tad more tricky to get running, since it depends on a number of unit tests and automated tools, to produce the contents of the /build folder</em></p>
<p><em>The dev environment is cross platform, so will work on both osx and windows, and do not currently have any dependencies to .net</em></p>
<h3>Install node.js</h3>
<p>We need node to run tests and automated less compiling and other automated tasks. go to <a href="http://nodejs.org">http://nodejs.org</a>. Node.js is a powerfull javascript engine, which allows us to run all our tests and tasks written in javascript locally.</p>
<p><em>note:</em> On windows you might need to restart explorer.exe to register node.</p>
<h3>Install dependencies</h3>
<p>Next we need to install all the required packages. This is done with the package tool, included with node.js, open /Umbraco.Belle.Client in cmd.exe or osx terminal and run the command:</p>
<pre><code>npm install</code></pre>
<p>this will fetch all needed packages to your local machine.</p>
<h3>Install grunt globally</h3>
<p>Grunt is a task runner for node.js, and we use it for all automated tasks in the build process. For convenience we need to install it globally on your machine, so it can be used directly in cmd.exe or the terminal.</p>
<p>So run the command:</p>
<pre><code>npm install grunt-cli -g</code></pre>
<p><em>note:</em> On windows you might need to restart explorer.exe to register the grunt cmd.</p>
<p><em>note:</em> On OSX you might need to run:</p>
<pre><code>sudo npm install grunt-cli -g</code></pre>
<p>Now that you have node and grunt installed, you can open <code>/Umbraco.Belle.Client</code> in either <code>cmd.exe</code> or terminal and run: </p>
<pre><code>grunt dev</code></pre>
<p>This will build the site, merge less files, run tests and create the /Build folder, launch the web browser and monitor changes.</p>
<h3>Automated builds and tests</h3>
<p>grunt dev will continue to run in the background monitoring changes to files. When changes are detected it will rebuild the JS and also run the unit tests.</p>
</body>
</html>

View File

@@ -1,176 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Things to do</h1>
<h2>Structure</h2>
<ul>
<li>One module pr file idea, instead of registering everything on app.js</li>
<li><p>Have core services, resources and other common items under umbraco</p>
</li>
<li><p>third party modules outside of the root umbraco module, but registered in app.js</p>
</li>
<li><p>to access 3rd party service:
ecomEditor.controller.js
angular.module(&quot;umbraco.myeditor&quot;, [&quot;ecommerce.services&quot;]).controller(&quot;ecom.editor&quot;, </p>
<pre><code> function(&quot;inventoryFactory&quot;){
do things...
});</code></pre>
</li>
<li><p>best way to setup services and controllers are:
.controller(&quot;name&quot;,[
&quot;service&quot;,
&quot;dependency&quot;,
function(s, d){</p>
<p> }
]);</p>
</li>
<li><p>move logic from controllers to services, especcially around navigation</p>
<ul>
<li>easier for testing</li>
<li>only keep view interactions, everything into a service</li>
<li>looser testing on controllers</li>
<li>for testing the dialogs, look in angular source or angular bootstrap projects</li>
</ul>
</li>
</ul>
<h2>Routing</h2>
<p>Change /section/page/id to /section/area/page/id to support all section scenarios
Have a fallback to defaults?</p>
<h2>Legacy</h2>
<ul>
<li>for UmbClientTools we can access the services in angular from
angular.element(&quot;body&quot;).injector().get(&quot;notifications&quot;);</li>
<li>rootscope available in same location</li>
<li>the bootstrap method returns the injector</li>
</ul>
<h2>ScriptLoaderService</h2>
<pre><code>- Service to load required scripts for a controller using $script
- remove requirejs dependency as it makes things muddy</code></pre>
<h2>Authentication</h2>
<p>Angular-app: common/security/interceptor.js , intercept http requests</p>
<h2>Promises</h2>
<pre><code>Use promises pattern for all our services
$http.get(url)
.then(function(response){
return response.data;
}, function(response){
return $q.reject(&quot;http failed&quot;);
}).then(function(data){
alert(&quot;our data:&quot; + data);
})</code></pre>
<h2>Think about rest services and authentication</h2>
<p>Usecase: member picker editor, which fetches member-data</p>
<h2>Avoid $resource and instead use $http</h2>
<p>Sublime linter</p>
</body>
</html>

View File

@@ -1,193 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>doc</title>
<style>
/*github.com style (c) Vasily Polovnyov <vast@whiteants.net>*/
pre code {
display: block; padding: 0.5em;
color: #333;
background: #f8f8ff
}
pre .comment,
pre .template_comment,
pre .diff .header,
pre .javadoc {
color: #998;
font-style: italic
}
pre .keyword,
pre .css .rule .keyword,
pre .winutils,
pre .javascript .title,
pre .nginx .title,
pre .subst,
pre .request,
pre .status {
color: #333;
font-weight: bold
}
pre .number,
pre .hexcolor,
pre .ruby .constant {
color: #099;
}
pre .string,
pre .tag .value,
pre .phpdoc,
pre .tex .formula {
color: #d14
}
pre .title,
pre .id {
color: #900;
font-weight: bold
}
pre .javascript .title,
pre .lisp .title,
pre .clojure .title,
pre .subst {
font-weight: normal
}
pre .class .title,
pre .haskell .type,
pre .vhdl .literal,
pre .tex .command {
color: #458;
font-weight: bold
}
pre .tag,
pre .tag .title,
pre .rules .property,
pre .django .tag .keyword {
color: #000080;
font-weight: normal
}
pre .attribute,
pre .variable,
pre .lisp .body {
color: #008080
}
pre .regexp {
color: #009926
}
pre .class {
color: #458;
font-weight: bold
}
pre .symbol,
pre .ruby .symbol .string,
pre .lisp .keyword,
pre .tex .special,
pre .prompt {
color: #990073
}
pre .built_in,
pre .lisp .title,
pre .clojure .built_in {
color: #0086b3
}
pre .preprocessor,
pre .pi,
pre .doctype,
pre .shebang,
pre .cdata {
color: #999;
font-weight: bold
}
pre .deletion {
background: #fdd
}
pre .addition {
background: #dfd
}
pre .diff .change {
background: #0086b3
}
pre .chunk {
color: #aaa
}
</style>
</head>
<body>
<h1>Using AngularJS Promises and Umbraco Resources</h1>
<h2>Promises in Umbraco Resources</h2>
<p>All Umbraco resource methods utilize a helper method:</p>
<pre><code>umbRequestHelper.resourcePromise</code></pre>
<p>This method accepts 2 arguments:</p>
<ul>
<li>The angular HttpPromise which is created with a call to $http.get (post, etc..)</li>
<li>The error message that is bubbled to the UI when the http call fails</li>
</ul>
<p>Here&#39;s an example of the usage in an Umbraco resource. This example is the method of the treeResource that fetches data to display the menu for a tree node:</p>
<pre><code>/** Loads in the data to display the nodes menu */
loadMenu: function (node) {
return umbRequestHelper.resourcePromise(
$http.get(getTreeMenuUrl(node)),
&quot;Failed to retrieve data for a node&#39;s menu &quot; + node.id);
}</code></pre>
<p>HTTP error handling is performed automatically inside of the <code>umbRequestHelper.resourcePromise</code> and inside of Umbraco&#39;s response interceptors.</p>
<h2>Consuming Umbraco resources</h2>
<p>When consuming Umbraco resources, a normal angular promise will be returned based on the above <code>umbRequestHelper.resourcePromise</code>. The success callback will always receive the RAW json data from the server and the error callback will always receive an object containing these properties:</p>
<ul>
<li>erroMsg = the error message that can be used to show in the UI</li>
<li>data = the original data object used to create the promise</li>
</ul>
<p>Error handling will be done automatically in the Umbraco resource. Http error handling should not be done during the consumption of an Umbraco resource.</p>
<h3>Simple example</h3>
<p>An simple example of consuming an Umbraco resource:</p>
<pre><code>treeResource.loadMenu(treeItem.node)
.then(function(data) {
scope.menu = data;
});</code></pre>
<h3>Transforming result data</h3>
<p>Sometimes the consumption of an Umbraco resource needs to return a promise itself. This is required in some circumstances such as:</p>
<p>The data from a result of an http resource might need to be transformed into something usable in the UI so a Service may need to call a resource, transform the result and continue to return it&#39;s own promise (since everything happens async).</p>
<p>This is actually very simple to do, the Service (or whatever is consuming the resource) just returns the result of their &#39;then&#39; call. Example - this example is the <code>getActions</code> method of the <code>treeService</code> that consumes the treeResource, transforms the result and continues to return it&#39;s own promise:</p>
<pre><code>getActions: function(treeItem, section) {
return treeResource.loadMenu(treeItem.node)
.then(function(data) {
//need to convert the icons to new ones
for (var i = 0; i &lt; data.length; i++) {
data[i].cssclass = iconHelper.convertFromLegacyIcon(data[i].cssclass);
}
return data;
});
} </code></pre>
<p>Notice that this is just returning the call to &#39;then&#39; which will return a promise that resolves the data from it&#39;s return statement.</p>
<h3>Error hanlding</h3>
<p>Ok, what about error handling ? This is really simple as well, we just add an additional method to the .then call. A simple example:</p>
<pre><code>treeResource.loadMenu(treeItem.node)
.then(function(data) {
scope.menu = data;
}, function(err) {
//display the error
notificationsService.error(err.errorMsg);
});</code></pre>
<h3>Error handling when transforming result data</h3>
<p>This is one of those things that is important to note! If you need to return a custom promise based on the result of an Umbraco resource (like the example above in Transforming result data) then you will need to &#39;throw&#39; an error if you want to &#39;bubble&#39; the error to the handler of your custom promise.</p>
<p>The good news is, this is very simple to do, example:</p>
<pre><code>getActions: function(treeItem, section) {
return treeResource.loadMenu(treeItem.node)
.then(function(data) {
//need to convert the icons to new ones
for (var i = 0; i &lt; data.length; i++) {
data[i].cssclass = iconHelper.convertFromLegacyIcon(data[i].cssclass);
}
return data;
}, function(err) {
//display the error
notificationsService.error(err.errorMsg);
//since we want the handler of this promise to be notified of this error
// we just need to rethrow it:
throw err;
});
}</code></pre>
<p>The next thing that is important to note is that <strong>you don&#39;t have to do anything</strong> if you don&#39;t want to do anything with the error but still want the error bubbled up to your promises handlers. So for example, if you are expecting the handler of this promise to handle the error and display something in the UI, just leave out the function(err) callback which would look exactly the same as the example for &#39;Transforming result data&#39;</p>
</body>
</html>

View File

@@ -1,35 +0,0 @@
#Belle Lab Tasks
##Applcation Structure
- Work on dialogs, plenty to choose from
- A reuseable tree component for pickers
- migrate all the navigation stuff into a navigation service
- a scriptloading service to replace requireJs, with labJs, $script or similiar
- reusable modal component (show in left side, right side, generic closing events etc)
##Components
- tabs directive
- date picker
- tabs property editor
- localization strategy?
- localize filter: {{This is my default english value,content.area.key | localize}}
- So, it will use the default value if there is none found for the key, and register this
value in the localize service, keys should not contain commas
##Chores
- Write a test
- Write docs
- Automate something
- OSX:
- start webserver
- start grunt watch
- improve test output?
- phantomJs?
- windows
- start webserver
- start grunt
- install node stuff?
- register chrome_bin in path
- or register phantomJS?

View File

@@ -1,10 +0,0 @@
#Belle Lab in Aarhus, May 28th
*Today was the first day with an open belle lab event, kindly hosted by the great people at Illumi in Aarhus. It was the first time the Belle prototype really got into the hands of developers, with the primary goal of getting people up and running and contributing*
The day kicked off with a fast and condensed introduction to belle and AngularJS, the JS framework we've decided to build belle on, afterwards, the event split into 2 tracks.
- 1 group focused on working on the conceptual level in regards to user experience
- the other focused on diving into the codebase and getting familiar with the new approach to extending the backoffice.

View File

@@ -1,73 +0,0 @@
#Codereview with Peter Bacon Darwin
##Office at cogworks:
71-75 Shelton Street
London
WC2H 9JQ
Meeting room 11 - 17
##Issues to go through:
###Structure, dependencies and external libraries
* review of modules structure and suggestions on how to handle loading things when needed.
* replace requireJs for dependency loading, so we dont have to load tinyMCE, googlemaps, etc
on app start $script, yepNope, labjs?
* get the app to load .aspx pages in an iframe instead of a "normal" view
- write directive for loading templates to replace ng-include
- if .aspx, load in iframe,
- if not found try default, finally load error msg
* Javascript as resources from dlls? - add a scriptService to load these? - yes
merge those resources into the umbraco.app.js file
http://briantford.com/blog/huuuuuge-angular-apps.html
###Refactoring
* Convert tree into directive, recursive, lazy-load
- $watchCollection $watch on the entire tree model
- reuse the old tree plugin to inject into dom instead of into angular
- 10 levels of digest limit
- fine for CG, bad for release
* best practices for directives, what should we convert?
* other areas to convert?
- for guidelines, look at angular/bootstrap-ui
- replace our components with ng-bootstrap or angular-strap
###Application logic
* Authentication, force login, authenticate user against acccess to sections?
* whats the best way to handle urls, routes and state management,
so the tree, sections etc, syncs with urls and the state of the application
* tinyMCE directive angular-ui
* How to handle file-uploads
- through a service?
- ng-upload? or jquery-upload-plugin thingy?
* validation, ng-form $valid and directives should be enough
- add remote directive: angular-app/admin/users/user-edit.js for directive code
###Dev experience
* H Way to handle templates with missing controller? -> replace ng-include? <- yup
angular-app/samples/directives/fielddirective for code
* H generel exception handling with feedback to log or notifications service
* L jslint code on the server?
http://madskristensen.net/post/Verify-JavaScript-syntax-using-C.aspx
- L automated setup of node, grunt, jasmine and karma, powershell and .sh?
###Testing
* Best way to test against service data, simply mock data in memory, or better way?
* Testing dom manipulating components, like modals
* e2e testing
- teamcity intergration
- testing templates
#Notes
- Javascript as resources? - add a scriptService to load these? nope, they will compile into umbraco.app.js
- capture errors with javascript code, to not load it into the combined files
(serverside jsLint) - mads blogpost for compiling js

View File

@@ -1,65 +0,0 @@
#Getting up and running with Belle
_The super fast introduction to getting belle running on your local machine, both as a pre-built environment, and with the full setup with unit-tests, grunt-tasks and node._
##Running the prebuilt site
###Windows
Right-click the `/build` folder and choose "open in webmatrix", run the website in webmatrix and browse to `localhost:9999/Belle/`, this should display the Belle login screen
*Port 9999 should be used because that is the target site that the grunt build command mentioned below will launch*
###OSX
Open a terminal inside the "/build" folder and run the command:
python -m SimpleHTTPServer 9999
This will start a local webserver, hosting the site on `localhost:9999` browse to localhost:9999/Belle/ which should display the belle login screen.
##Uing the dev environment
_The dev environment is tad more tricky to get running, since it depends on a number of unit tests and automated tools, to produce the contents of the /build folder_
_The dev environment is cross platform, so will work on both osx and windows, and do not currently have any dependencies to .net_
###Install node.js
We need node to run tests and automated less compiling and other automated tasks. go to http://nodejs.org. Node.js is a powerfull javascript engine, which allows us to run all our tests and tasks written in javascript locally.
*note:* On windows you might need to restart explorer.exe to register node.
###Install dependencies
Next we need to install all the required packages. This is done with the package tool, included with node.js, open /Umbraco.Belle.Client in cmd.exe or osx terminal and run the command:
npm install
this will fetch all needed packages to your local machine.
###Install grunt globally
Grunt is a task runner for node.js, and we use it for all automated tasks in the build process. For convenience we need to install it globally on your machine, so it can be used directly in cmd.exe or the terminal.
So run the command:
npm install grunt-cli -g
*note:* On windows you might need to restart explorer.exe to register the grunt cmd.
*note:* On OSX you might need to run:
sudo npm install grunt-cli -g
Now that you have node and grunt installed, you can open `/Umbraco.Belle.Client` in either `cmd.exe` or terminal and run:
grunt dev
This will build the site, merge less files, run tests and create the /Build folder, launch the web browser and monitor changes.
###Automated builds and tests
grunt dev will continue to run in the background monitoring changes to files. When changes are detected it will rebuild the JS and also run the unit tests.

View File

@@ -1,65 +0,0 @@
#Things to do
##Structure
- One module pr file idea, instead of registering everything on app.js
- Have core services, resources and other common items under umbraco
- third party modules outside of the root umbraco module, but registered in app.js
- to access 3rd party service:
ecomEditor.controller.js
angular.module("umbraco.myeditor", ["ecommerce.services"]).controller("ecom.editor",
function("inventoryFactory"){
do things...
});
- best way to setup services and controllers are:
.controller("name",[
"service",
"dependency",
function(s, d){
}
]);
- move logic from controllers to services, especcially around navigation
- easier for testing
- only keep view interactions, everything into a service
- looser testing on controllers
- for testing the dialogs, look in angular source or angular bootstrap projects
##Routing
Change /section/page/id to /section/area/page/id to support all section scenarios
Have a fallback to defaults?
##Legacy
- for UmbClientTools we can access the services in angular from
angular.element("body").injector().get("notifications");
- rootscope available in same location
- the bootstrap method returns the injector
##ScriptLoaderService
- Service to load required scripts for a controller using $script
- remove requirejs dependency as it makes things muddy
##Authentication
Angular-app: common/security/interceptor.js , intercept http requests
##Promises
Use promises pattern for all our services
$http.get(url)
.then(function(response){
return response.data;
}, function(response){
return $q.reject("http failed");
}).then(function(data){
alert("our data:" + data);
})
##Think about rest services and authentication
Usecase: member picker editor, which fetches member-data
##Avoid $resource and instead use $http
Sublime linter

View File

@@ -1,157 +0,0 @@
@ngdoc overview
@name Adding serverside data to a property editor
@description
##Overview
In this tutorial we will add a serverside API controller, which will query a custom table in the umbraco database, and then return the data to a simple angular controller + view.
The end result will be a person-list, populated from a custom table, when clicked it will store the ID of the selected person.
##Setup the database
First thing we need is some data, below is a simple SQL Script for create a `people` table with some random data in. You could also use [http://generatedata.com] for larger amounts of data:
CREATE TABLE people (
id INTEGER NOT NULL IDENTITY(1, 1),
name VARCHAR(255) NULL,
town VARCHAR(255) NULL,
country VARCHAR(100) NULL,
PRIMARY KEY (id)
);
GO
INSERT INTO people(name,town,country) VALUES('Myles A. Pearson','Tailles','United Kingdom');
INSERT INTO people(name,town,country) VALUES('Cora Y. Kelly','Froidchapelle','Latvia');
INSERT INTO people(name,town,country) VALUES('Brooke Baxter','Mogi das Cruzes','Grenada');
INSERT INTO people(name,town,country) VALUES('Illiana T. Strong','Bevel','Bhutan');
INSERT INTO people(name,town,country) VALUES('Kaye Frederick','Rothesay','Turkmenistan');
INSERT INTO people(name,town,country) VALUES('Erasmus Camacho','Sint-Pieters-Kapelle','Saint Vincent and The Grenadines');
INSERT INTO people(name,town,country) VALUES('Aimee Sampson','Hawera','Antigua and Barbuda');
##Setup ApiController routes
Next we need to defined a `ApiController` to expose a server side route which our application will use to fetch the data.
For this, we will create a file at: `/app_code/PersonApiController.cs` It must be in app_code since we want our app to compile it on start, alternatively, you can just add it to a normal .net project and compile into a dll as normal.
In the PersonApiController.cs file, add:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Web.WebApi;
using Umbraco.Web.Editors;
using Umbraco.Core.Persistence;
namespace My.Controllers
{
[Umbraco.Web.Mvc.PluginController("My")]
public class PersonApiController : UmbracoAuthorizedJsonController
{
//we will add a method here later
}
}
This is a very basic Api controller which inherits from `UmbracoAuthorizedJsonController` this specific class will only return json data, and only to requests which are authorized to access the backoffice
##Setup the GetAll() method
Now that we have a controller, we need to create a method, which can return a collection of people, which our editor will use.
So first of all, we add a `Person` class to the `My.Controllers` namespace:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Town { get; set; }
public string Country { get; set; }
}
We will use this class to map our table data to an c# class, which we can return as json later.
Now we need the `GetAll()` method which returns a collection of people, insert this inside the PersonApiController class:
public IEnumerable<Person> GetAll()
{
}
Inside the GetAll() method, we now write a bit of code, that connects to the database, creates a query and returns the data, mapped to the `Person` class above:
//get the database
var db = UmbracoContext.Application.DatabaseContext.Database;
//build a query to select everything the people table
var query = new Sql().Select("*").From("people");
//fetch data from DB with the query and map to Person object
return db.Fetch<Person>(query);
We are now done with the server side of things, with the file saved in app_code you can now open the Url: /umbraco/My/PersonApi/GetAll
This will return our json code.
##Create a Person Resource
Now that we have the serverside in place, and a Url to call, we will setup a service to retrieve our data. As an Umbraco specific convention, we call these services a *resource, so we always have an indication what services fetch data from the DB.
Create a new file as `person.resource.js` and add:
//adds the resource to umbraco.resources module:
angular.module('umbraco.resources').factory('personResource',
function($q, $http) {
//the factory object returned
return {
//this cals the Api Controller we setup earlier
getAll: function () {
return $http.get("My/PersonApi/GetAll");
}
};
}
);
This uses the standard angular factory pattern, so we can now inject this into any of our controllers under the name `personResource`.
the getAll method just returns a $http.get call, which handles calling the url, and will return the data when its ready.
##Create the view and controller
We will now finally setup a new view and controller, which follows previous tutorials, so have refer to those for more details:
####the view:
<div ng-controller="My.PersonPickerController">
<ul>
<li ng-repeat="person in people">
<a href ng-click="model.value = person.Name">{{person.Name}}</a>
</li>
</ul>
</div>
####The controller:
angular.module("umbraco")
.controller("My.PersonPickerController", function($scope, personResource){
personResource.getAll().then(function(response){
$scope.people = response.data;
});
});
##The flow
So with all these bits in place, all you need to do is register the property editor in a package.manifest - have a look at the first tutorial in this series. You will need to tell the package to load both your personpicker.controller.js and the person.resource.js file on app start.
With this, the entire flow is:
1. the view renders a list of people with a controller
2. the controller asks the personResource for data
3. the personResource returns a promise and asks the /my/PersonAPI api controller
4. The apicontroller queries the database, which returns the data as strongly typed Person objects
5. the api controller returns those `Person` objects as json to the resource
6. the resource resolve the promise
7. the controller populates the view
Easy huh? - honestly tho, there is a good amount of things to keep track of, but each component is tiny and flexible.
##Wrap-up
The important part of the above is the way you create an `ApiController` call the database for your own data, and finally expose the data to angular as a service using $http.
For simplicity, you could also have skipped the service part, and just called $http directly in your controller, but by having your data in a service, it becomes a reusable resource for your entire application.

View File

@@ -1,67 +0,0 @@
@ngdoc overview
@name Adding configuration to a property editor
@description
##Overview
This is step 2 in our guid to building a property editor. This step continues work on the markdown editor we build in step 1, but goes further to show you how you can add configuration options to the editor.
##Configuration?
So, an important part of building good property editors, are to build something relatively flexible, so you can reuse it many many times, for different things. Like the rich text editor in Umbraco, that allows you to choose which buttons and stylesheets you want to use on each instance of the editor.
So an editor can be used several times, with different configurations, and that is what we will be working on now.
##package.manifest
So to add configuration options to our markdown editor, open the package.manifest file. rigth below the editor definition, paste in the following:
prevalues: {
fields: [
{
label: "Preview",
description: "Display a live preview",
key: "preview",
view: "boolean"
},
{
label: "Default value",
description: "If value is blank, the editor will show this",
key: "defaultValue",
view: "textarea"
}
]
}
**Remember to: ** separate the editor element and prevalue editor definition with a comma, or you will get a json error.
So what did we just add? We added a prevalue editor, with a `fields` collection. This collection contains infomation about the UI we will render on the data type configuration for this editor.
So the first gets the label "Preview" and uses the view "boolean", so this will allow us to turn preview on/off and will provide the user with a simple checkbox. The name "boolean" comes from the convention that all preview editors are stored in /umbraco/views/prevalueeditors/ and then found via `<name>.html`
Same with the next one, only that it will provide the user with a textarea to input a default value for the editor.
Save the manifest **restart the app pool** and have a look at the markdown datatype in Umbraco now. You should now see that you have 2 configuration options.
##Using the configuration
The next step is to gain access to our new configuration options. For this, open the `markdowneditor.controller.js` file
Lets first add the default value functionality. So basicly when the ´$scope.model.value` is empty or undefined, we want to use the default value, to do that, we add the following to the very beginning of the controller:
if($scope.model.value === null || $scope.model.value === ""){
$scope.model.value = $scope.model.config.defaultValue;
}
You see whats new? - the `$scope.model.config` object is. And the other thing you will notice is that because of our configuration, we now have access to `$scope.model.config.defaultValue` which contains the configiration value for that key, its that easy to setup and use configuration values from code.
However, you can also use these values without any javascript, so open the `markdowneditor.html` file instead.
Because we can also use the configuration directly in our html like here, where we use it to toggle the preview `<div>`, using the ng-hide attribute:
<div ng-show="model.config.preview" class="wmd-panel wmd-preview"></div>
##Get the codes
The latest update to the markdowneditor project is on github where you can see all the files and the manifest [here](https://github.com/umbraco/Umbraco-CMS/tree/7.0.0/src/Umbraco.Web.UI.Client/src/packages/MarkdownEditor).

View File

@@ -1,105 +0,0 @@
@ngdoc overview
@name Building Umbraco 7 from source
@description
##Overview
Umbraco 7 has a slightly unorthodox project structure, compared to a normal asp.net project. This is by design, and a choice from the beginning to embrace a mucher larger group then "just" the developers who know how to use Visual Studio.
As a result of that, the Umbraco UI is not a visual studio project, but simply a collection of folders and files, following certain conventions, and a small configuration file called `gruntfile` - we will get to the grunt part in a moment.
This means that anyone with a text editor can open the UI source, make changes and run the project, without having Visual Studio installed - we will get into how to do that in a moment as well.
But bottom line is that the UI project has zero dependencies on asp.net or windows, but you will need node.js installed, but don't worry we will get into that in a second.
##Prerequisites
Umbraco 7 needs a couple of things to run:
###Node.js
To compile and run the UI project you need node.js installed, you can get that at [http://nodejs.org](nodejs.org) for both windows and osx.
###Grunt
When you have node.js installed, you need to install grunt. Grunt is a simple javascript task runner, basicly like Nant, Msbuild or any traditional build system [http://gruntjs.com](more about grunt here).
To install, open a terminal and run:
npm install -g grunt-cli
For OSX users, you will most likely need to do:
sudo npm install -g grunt-cli
This installs a `grunt` command into your terminal so you can run grunt scripts with simple commands. That migth sound scary, but really isn't, for working with Umbraco 7, you will become really good friends with `grunt` and your terminal.
###Project dependencies
Now its time to install all the dependencies that the project requires to compile, debug, test, minify and so on. Luckily this is all automatic, and is done wiht the node.js package manager (which you already have installed with node)
In your terminal, browse to the `Umbraco.Web.Ui.Client` folder and run the command:
npm install
This will output a ton of feedback in your terminal, when it stops, your project is ready to run.
This might seem like a lot of stuff to do, but think of it this way, every time you setup this environment, all you have to do is run `npm install` and everything will be running smoothly.
##Running from source without Visual studio or IIS
The Umbraco 7 project includes a complete mocked data model and an embedded webserver to run off.
So to get the project up and running in a browser as fast as possible, open a terminal and browse to `Umbraco.Web.Ui.Client` folder, and run the command:
grunt dev
this will do the following:
- Compile the project files and merge them
- Compile less files to one .css file
- Lint js files for syntax and style errors
- run unit tests
- Setup a watcher to monitor for ongoing changes.
- Start a webserver on port 9999
- Open a browser to display localhost:9999/belle
This is all grunt doing that for us, and notice that it sets up a watcher, which means that every time you make a change, it will automaticly recompile and test your code, if something is wrong the terminal will tell you why.
You can now login (no user/pass) and browse the UI with dummy data, this setup is perfect for fast css and js changes that does not require any *real* data.
##Running from Visual Studio
**Note:** we will make this even easier to so the steps with node and grunt wont be required for .net developers in visual studio, but for now the below is needed:
To run from Visual Studio, simply open the solution and run the `Umbraco.Web.UI` project as a normal website project. But to get the latest Umbraco 7 files into this site you still need to open a terminal at `Umbraco.Web.Ui.Client` and run either:
grunt dev
or for a one-time build:
grunt build
This will compile all files and copy them into the appropriate folder in the VS project, if you run `grunt dev` it will also automaticly update the VS project files as you edit them.
You should never edit the /umbraco/js/umbraco.*.js files directly, these will be overwritten on each build.
##using build.bat
The Umbraco source comes with a build.bat file that runs the full build process, which is the one we use on our nightly builds, it produces a complete zip file with a ready to use distribution.
The same rules apply as with running from Visual Studio, you need to run
grunt build
Before running build.bat, then the latest UI files will be included.
##Conclusion
Having Umbraco 7 UI as a separate project does indeed give us a bit more complexity when building and running from visual studio, since 2 build systems are in play: grunt and msbuild.
However, the alternative would be to shove everything into the msbuil process, making the entire thing inaccesible to a large number of frontend developers and with a clunkier and less uptodate system.
So see it as an additional powerfull tool in your arsenal, once you see the power, you don't want to go back.

View File

@@ -1,165 +0,0 @@
@ngdoc overview
@name Creating a custom tree with an editor and dialog
@description
##Overview
This guide will explain how to create a simple custom tree an angular editor & dialog using standard conventions. This guide does not go into detail about how to persist data in your editors, it is a simple tutorial defining how routing interacts with your views and where your views need to be stored.
So all the steps we will go through:
- Creating a tree with a menu item
- Create an editor
- Create a dialog for the menu item
##Create a tree
First you need to define a tree class that inherits from `Umbraco.Web.Trees.TreeController`
public class MyCustomTreeController : TreeController
{
}
The name of your tree must be suffixed with the term 'Controller'.
Next we need to add some attributes to the tree. The first one defines the section it belongs to, the tree alias and it's name. Ensure your tree alias is unique, tree aliases cannot overlap.
[Tree("settings", "myTree", "My Tree")]
The 2nd attribute does 2 things - Tells Umbraco how to route the tree and tells Umbraco where to find the view files. This attribute is not required but if you do not specify it then the view location conventions will not work.
[PluginController("MyPackage")]
There are 2 methods that need to be overriden from the TreeController class: `GetTreeNodes` & `GetMenuForNode`. This example will create 3 nodes underneath the root node:
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
{
//check if we're rendering the root node's children
if (id == Constants.System.Root.ToInvariantString())
{
var tree = new TreeNodeCollection
{
CreateTreeNode("1", queryStrings, "My Node 1"),
CreateTreeNode("2", queryStrings, "My Node 2"),
CreateTreeNode("3", queryStrings, "My Node 3")
};
return tree;
}
//this tree doesn't suport rendering more than 1 level
throw new NotSupportedException();
}
Next we'll create a menu item for each node, in this case its a 'Create' menu item
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
menu.AddMenuItem(new MenuItem("create", "Create"));
return menu;
}
That's it, the whole tree looks like this:
[Tree("settings", "myTree", "My Tree")]
[PluginController("MyPackage")]
public class MyCustomTreeController : TreeController
{
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
{
//check if we're rendering the root node's children
if (id == Constants.System.Root.ToInvariantString())
{
var tree = new TreeNodeCollection
{
CreateTreeNode("1", queryStrings, "My Node 1"),
CreateTreeNode("2", queryStrings, "My Node 2"),
CreateTreeNode("3", queryStrings, "My Node 3")
};
return tree;
}
//this tree doesn't suport rendering more than 1 level
throw new NotSupportedException();
}
protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
menu.AddMenuItem(new MenuItem("create", "Create"));
return menu;
}
}
##View path conventions
Now that we've created our tree it is important to understand Umbraco conventions and where it will look for your views for editors and dialogs.
###Angular editor routes
The main angular route to load in editors is */:section/:tree/:method/:id*
Umbraco will load in views for this route based on these conventions:
* If it is a core tree - views will be loaded from: */umbraco/views/{treetype}/{method}.html*
* If it is a custom (package) tree - views will be loaded from: */App_Plugins/{mypackage}/BackOffice/{treetype}/{method}.html*
###Editor locations
By default each tree node's 'method' is assigned as 'edit' therefore these are the view paths for an editor when a tree node is clicked:
* If it is a core tree - views will be loaded from: */umbraco/views/{treetype}/edit.html*
* If it is a custom (package) tree - views will be loaded from: */App_Plugins/{mypackage}/BackOffice/{treetype}/edit.html*
Developers can specify a custom `RoutePath` for any tree node which will cause umbraco to route to that specific location.
###Dialog locations
Dialog view path locations are similar to editors:
* If it is a core tree - views will be loaded from: umbraco/views/{treetype}/{action}.html
* If it is a custom (package) tree - views will be loaded from: /App_Plugins/{mypackage}/BackOffice/{treetype}/{action}.html
'action' is the alias of your menu item, for example in the menu item in the example above this would be 'create'.
##Create an editor
An editor is simply an angular view (html file) so you can really do whatever you'd like! This tutorial will simply create a hello world editor showing the id of the item being edited.
###Create a controller
First thing we'll do is create an angular controller for the editor, this controller will be contained in a file found beside the view - *the file naming conventions are based on the controller file naming conventions in the Umbraco core*.
/App_Plugins/MyPackage/BackOffice/MyTree/mypackage.mytree.edit.controller.js
The controller is super simple, at it is going to do is assign a property to the $scope which shows the current item id being edited:
'use strict';
(function () {
//create the controller
function myTreeEditController($scope, $routeParams) {
//set a property on the scope equal to the current route id
$scope.id = $routeParams.id;
};
//register the controller
angular.module("umbraco").controller('MyPackage.MyTree.EditController', myTreeEditController);
})();
###Create a view
As per the conventions above our editor view will need to be located at:
/App_Plugins/MyPackage/BackOffice/MyTree/edit.html
The view is simple, it is just going to show the current id being edited
<div ng-controller="MyPackage.MyTree.EditController">
<h1>Hello world!</h1>
<p>
You are current editing an item with id {{id}}
</p>
</div>
##Create a dialog
This is the same principle as an editor, you just need to follow conventions. Based on the above conventions the 'create' dialog view will be located here:
/App_Plugins/MyPackage/BackOffice/MyTree/create.html

View File

@@ -1,158 +0,0 @@
@ngdoc overview
@name Creating a property editor
@description
##Overview
This guide explains how to setup a simple property editor, how to hook it into Umbraco's datatypes
how to hook it into angulars modules and its injector, and finally how you can test your property editor.
So all the steps we will go through:
- Setting up a plugin
- Write some basic hello world html + js
- Register the data type in Umbraco
- Add external dependencies
- Complete the markdown editor
##Prerequisites
This is about how to use AngularJS with umbraco, so it does not cover AngularJS itself, as there are tons of resources on that already here:
- [egghead.io](http://www.egghead.io/)
- [angularjs.org/tutorial](http://docs.angularjs.org/tutorial)
- [Tekpub](http://tekpub.com/products/angular)
##The end result
By the end of this guide, we will have a simple markdown editor running inside of Umbraco
registered as a data type in the backoffice, assigned to a document type, and the editor can
create and modify data.
##Setting up a plugin
The first thing we must do is create a new folder inside `/App_Plugins` folder. We will call it
`MarkDownEditor`
Next We will create a simple manifest file to describe what this plugin does. This manifest will tell Umbraco about our new property editor and allows us to inject any needed files into the application, so we create the file `/App_Plugins/MarkDownEditor/package.manifest`
Inside this package manifest we add a bit of json to describe the property editor, have a look at the inline comments in the json below for details on each bit:
{
//you can define multiple editors
propertyEditors: [
{
/*this must be a unique alias*/
alias: "My.MarkdownEditor",
/*the name*/
name: "Markdown editor",
/*the html file we will load for the editor*/
editor: {
view: "~/App_Plugins/MarkDownEditor/markdowneditor.html"
}
}
]
,
//array of files we want to inject into the application on app_start
javascript: [
'~/App_Plugins/MarkDownEditor/markdowneditor.controller.js'
]
}
##Writing some basic html + js
Then we add 2 files to the /app_plugins/markdowneditor/ folder:
- ´markdowneditor.html`
- `markdowneditor.controller.js`
These will be our main files for the editor, with the .html file handling the view and the .js
part handling the functionality.
In the .js file I will add a basic angularJS controller declaration
angular.module("umbraco")
.controller("My.MarkdownEditorController",
function () {
alert("The controller has landed");
});
And in the .html file I'll add:
<div ng-controller="My.MarkdownEditorController">
<textarea ng-model="model.value"></textarea>
</div>
Now our basic parts of the editor is done namely:
- The package manifest, telling umbraco what to lod
- The html view for the editor
- The controller for wiring up the editor with angular.
##Register the datatype in umbraco
After the above edits are done, restart your application. Go to developer section, click the 3 dots next to the datatypes folder and create a new data type called "markdown". In the editor you can now select a property editor, where your newly added "markdown editor" will appear.
Save the datatype, and add it to a document type of your choice, open a document of that type, and you will be greated with an alert message saying "The controller has landed", which means all is well, and you can now edit the assigned property's value with your editor.
##Add external dependencies
Lets go a bit further, and load in a markdown editor javascript library, I've chosen pagedown, but you can use whatever you want.
First of, I'll add some external files to our package folder, in /app_plugins/markdowneditor/lib folder, these files comes from the pagedown editor project found here:
[Pagedown-bootstrap on github.com](https://github.com/samwillis/pagedown-bootstrap)
Then open the `markdowneditor.controller.js` file and edit it so it looks like this:
angular.module("umbraco")
.controller("My.MarkdownEditorController",
//inject umbracos assetsService
function ($scope,assetsService) {
//tell the assetsService to load the markdown.editor libs from the markdown editors
//plugin folder
assetsService
.load([
"/App_Plugins/MarkDownEditor/lib/markdown.converter.js",
"/App_Plugins/MarkDownEditor/lib/markdown.sanitizer.js",
"/App_Plugins/MarkDownEditor/lib/markdown.editor.js"
])
.then(function () {
//this function will execute when all dependencies have loaded
alert("editor dependencies loaded");
});
//load the seperat css for the editor to avoid it blocking our js loading
assetsService.loadCss("/App_Plugins/MarkDownEditor/lib/markdown.css");
});
This loads in our external dependency, but only when its needed by the editor.
Now lets replace that `alert()` with some code that can instantiate the pagedown editor:
var converter2 = new Markdown.Converter();
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
editor2.run();
and add that id to the text area in the html, for more info on the html structure, see the pagedown demo [here](https://github.com/samwillis/pagedown-bootstrap/blob/master/demo/browser/demo.html):
<div ng-controller="My.MarkdownEditorController" class="wmd-panel">
<div id="wmd-button-bar-{{model.alias}}"></div>
<textarea ng-model="model.value" class="wmd-input" id="wmd-input-{{model.alias}}">
your content
</textarea>
<div id="wmd-preview-{{model.alias}}" class="wmd-panel wmd-preview"></div>
</div>
Now, clear the cache, reload the document and see the pagedown editor running.
When you save or publish the value of the editor is automaticly synced to the current content object and sent to the server, all through the power of angular and the `ng-model`attribute.
##Get the source
The full source, including manifest and dependencies, can be found on the umbraco-cms project
[here](https://github.com/umbraco/Umbraco-CMS/tree/7.0.0/src/Umbraco.Web.UI.Client/src/packages/MarkdownEditor)
Simply copy the MarkdownEditor folder to /app_plugins and restart your website, and it will be up and running.

View File

@@ -1,87 +0,0 @@
@ngdoc overview
@name Integrating services with a property editor
@description
##Overview
This is step 3 in the property editor tutorial. In this part we will intergrate one of the built-in
umbraco services. For this sample we will use the dialog service to hook into the media picker and return image data to the markdown editor.
##Injecting the service.
First up, we need to get access to the service, this is done in the constructor of the controller, where we add it as a parameter:
angular.module("umbraco")
.controller("My.MarkdownEditorController",
//inject umbracos assetsServce and dialog service
function ($scope,assetsService, dialogService) { ... }
this works the same way as with the assetsService we added in step 1.
##Hooking into pagedown
The pagedown editor we are using, has a nice event system inplace, so we can easily hook into the events triggered by the media chooser, by adding a hook, after the editor has started:
//Start the editor
var converter2 = new Markdown.Converter();
var editor2 = new Markdown.Editor(converter2, "-" + $scope.model.alias);
editor2.run();
//subscribe to the image dialog clicks
editor2.hooks.set("insertImageDialog", function (callback) {
//here we can intercept our own dialog handling
return true; // tell the editor that we'll take care of getting the image url
});
});
Notice the callback, this callback is used to return whatever data we want to editor.
So now that we have access to the editor events, we will trigger a media picker dialog, by using the `dialogService`. You can inject whatever html you want with this service, but it also has a number of shorthands for things like a media picker:
//the callback is called when the use selects images
dialogService.mediaPicker({callback: function(data){
//data.selection contains an array of images
$(data.selection).each(function(i, item){
//try using $log.log(item) to see what this data contains
});
}});
##Getting to the image data
Because of Umbraco's generic nature, you don't always know where your image is, as a media object's data is basicly an array of properies, so how do you pick the right one? - you cannot always be sure the property is called `umbracoFile` for instance.
For cases like this, a helper service is available: `imageHelper`. This utillity has usefull methods for getting to images embedded in property data, as well as associated thumbnails. **Remember to** inject this imageHelper in the controller constructor as well (same place as dialogService and assetsService).
So we get the image page from the selected media item, and return it through the callback:
var imagePropVal = imageHelper.getImagePropertyValue({ imageModel: item, scope: $scope });
callback(imagePropVal);
Now when we run the markdown editor and click the image button, we are presented with a native umbraco dialog, listing the standard media archive.
Clicking an image and choosing select returns the image to the editor which then renders it as:
![Koala picture][1]
[1]: /media/1005/Koala.jpg
The above is correct markdown code, representing the image, and if preview is turned on, you will see the image below the editor.
##Wrap up
So over the 3 previous steps, we've:
- created a plugin
- defined an editor
- injected our own javascript libraries and 3rd party ones
- made the editor configurable
- connected the editor with native dialogs and services
- looked at koala pictures.
The complete project can be found [here](https://github.com/umbraco/Umbraco-CMS/tree/7.0.0/src/Umbraco.Web.UI.Client/src/packages/MarkdownEditor).

View File

@@ -1,31 +0,0 @@
@ngdoc overview
@name Running Umbraco 7
@description
##Overview
This document explains how you can run Umbraco from one of our nightly builds on Windows.
You must have either IIS, IISExpress and/or WebMatrix installed
##Getting the build
Our buildserver runs every morning at 9 danish time, and each day it produces 3 zip files with the latest changes compiled and ready to run.
The umbraco 7 nightly builds can be downloaded from [http://nightly.umbraco.org/umbraco%207.0.0/](nightly.umbraco.org)
As you can see, there are different types of builds:
- UmbracoCms.7.0.0-build.##.zip
- UmbracoCms.AllBinaries.7.0.0.build.##.zip
- UmbracoCms.WebPi.7.0.0.build.##.zip
The first one contains the full website, ready to run in IIS, the AllBinaries one only contains the comiled .dll's and finally WebPi is for installing through microsoft platform installer.
You should download the latest of the first kind.
##Unzipping and installing
When downloaded, *Remember* to right-click the file, choose properties and select *Unblock file*
UnZip and setup IIS/IISExpress to run the site from this folder, or if you have webmatrix installed, right click it and choose "run as website from webmatrix"
During install, you can choose between Sql Server and Sql CE, both versions work, with CE being perfectly fine for local developement on machines where you dont want to bother with SQL Server.

View File

@@ -1,78 +0,0 @@
@ngdoc overview
@name Source code structure
@description
##Overview
This document outlines where the different files in the Umbraco 7 source code is.
The Client-side part of Umbraco 7 is located in the project folder: `Umbraco.Web.Ui.Client
##Root folders
The folders found in the root of the client-side project and what they contain:
*/Assets*
This folder contains various client-side assets, most of them are obsolete by now and will over time be merged into the source
*/Build*
The folder containing the compiled and minified bits outputted by grunt
*/Docs*
Automated documentation files by ngdoc project from inline comments in source files as well as from .ngdoc files in /docs/src/
*/Lib*
Folder containing all 3rd party dependencies used by the Umbraco web application
*/node_modules*
Dependencies used by node and grunt to build the project
*/src*
The source code of Umbraco 7 UI
*/test*
Test configuration and test files used by the karma testrunner to unit-test the project.
##Source folders
Inside the /src folder, the Umbraco 7 source code is devided into 3 groups of code:
- Less files
- Common / shared javascript
- Views
###Less files
Everything is loaded into the belle.less which specifies what files to include, the variables.less contains global variabls
###/Views
The Views folder contains all the html for the application as well as the Controllers used on those views. The convention for views and controllers are:
- /views/section/Viewname.html
- /views/section/section.viewname.controller.js
So if you are looking for the html and javascript used by the content editor look in /src/views/content/edit.html and `/src/vies/content/content.edit.controller.js`
###/Common
The Common folder contains all the items that are share between multiple parts of the application, such as Services, Directives and Filters.
So if you want to access the navigationService look in `/src/common/services/navigation.service.js`
For the Umbraco 7 application, we also have introduce the concept of a `Resource`, this term is used for a shared service which primarily is used to access data from the database and perform crud operations on this data.
Example resources could be:
- /src/common/resources/media.resource.js
- /src/common/resources/entity.resource.js
All resources returns a promise when data is fetched, they use the same pattern for errors and generally require a http backend to work.
On our serverless setup, we use a mocked http backend to simulate data.
###Packages
Folder containing various sample projects on how to use the external api, good for referencing how the package.manifest and property editors work.
###App.js and app.dev.js
The central application script, which handles what modules to inject, app.js is for production, app.dev.js is for testing
###loader.js
lazyload.js based loader for async loading javascript files, this file specifies what files to load on application start
###routes.js
Routing setup for /umbraco/ pages, by default it contains a mvc-like convention based pattern, which means that we not very often need to modify this.

View File

@@ -1,52 +0,0 @@
@ngdoc overview
@name Adding tag support to property editors
@description
##What is tag support?
This document will explain how to add tagging support to property editors and what tagging support means. A property editor that has tag support enabled means
that any time a document is published (or saved in the case of media/members) that has a property editor with tagging support, the tags the are exposed
by these property editors will be saved into the tag table in the database and associated with the corresponding document property. This then allows you
to query or render content based on tags on the front-end.
*NOTE: The documentation for querying tag data is coming soon....*
##Enabling tag support
This will explain both ways to enable tag support for property editors: both in c# or by the manifest.
### CSharp
Like creating a normal c# property editor you start by declaring a class with the PropertyEditor attribute:
[PropertyEditor("tags", "Tags", "tags")]
public class TagsPropertyEditor : PropertyEditor
{
}
To add tag support, we simply add the SupportsTags attribute:
[SupportTags]
[PropertyEditor(Constants.PropertyEditors.TagsAlias, "Tags", "readonlyvalue")]
public class TagsPropertyEditor : PropertyEditor
{
}
There are a few options for the `SupportsTag` attribute but normally the default options will suffice.
The default options are:
* Requires that the property editor value is a comma delimited string value
* Will replace the current property's tags in the tags database table with the ones in the value
* Will add all tags as part of the 'default' tag group in the database table
These options can all be changed on the attribute, you can specify a different delimiter, you can specify whether to replace or append the tags associated with the property and you can specify a different tag group.
There is one last option that can be set which is the `TagValueType` enum, the values can be:
* `FromDelimitedValue` - this is the default
* `CustomTagList` - if this is used then it is expected that the property editor's value (returned from the method `ConvertEditorToDb`) is an `IEnumerable<string>`
* This setting might be handy if you need to dynamically (in c#) generate the tags list
### Manifest
*Coming soon!*

View File

@@ -1,84 +0,0 @@
@ngdoc overview
@name Test-driven developement flow
@description
##Overview
_This document tries to outline what is required to have a test-driven setup for
angular developement in Umbraco 7. It goes through the setup process as well as how
to add new services that requires mocking as well as how to use grunt to run tests automaticly._
##Setup
Make sure to have all the node dependencies in order when you start, these are updated regularly in case we need to go to a new version of a dependency, or new dependencies are added.
Simply run open a terminal / cmd in the Umbraco.Web.Ui.Client folder and run:
npm install
This should setup the entire grunt,karma and jsint setup we use for tests and pruning.
##Automated testing
To start working on the client files, and have them automaticly built and merged into the client project, as well as the VS project, simply run the command
grunt dev
This will start a webserver on :8080 and tell karma to run tests every time a .js or .less file is changed.
After linting and tests have passed, all the client files are copied to umrbaco.web.ui/umbraco folder, so it also keeps the server project uptodate on any client changes. This should all happen in the background.
##Adding a new service
The process for adding or modifying a service should always be based on passed tests. So if we need to change the footprint of the contentservice, and the way any controller calls this service, we need to make sure the tests passes with our mocked services.
This ensures 3 things:
- we test our controllers
- we test our services
- we always have mocked data available, if you want to run the client without IIS
###Example:
We add a service for fetching macros from the database, the initial implementation should happen of this service should happen in `/src/common/resources/macro.resource.js`
The macro.resource.js calls `$http` as normal, but no server implementation should be needed at this point.
Next, we describe how the rest service should return data, this is done in /common/mocks/umbraco.httpbackend.js, where we can define what data a certain url
would return.
So in the case of getting tree items we define:
$httpBackend
.whenGET( urlRegex('/umbraco/UmbracoTrees/ApplicationTreeApi/GetApplicationTrees') )
.respond(returnApplicationTrees);
The `returnApplicationTrees` function then looks like this:
function returnApplicationTrees(status, data, headers){
var app = getParameterByName(data, "application");
var tree = _backendData.tree.getApplication(app);
return [200, tree, null];
}
It returns an array of 3 items, the http status code, the expected data, and finally it can return a collection of http headers.
_backendData.tree.getApplication(app);
Refers to a helper method in `umbraco.httpbackend.helper.js` which contains all the helper methods we
use to return static json.
###In short
So to add a service, which requires data from the server we should:
- add the .service.js as normal
- add the .resource.js as normal
- call $http as normal
- define the response data in umbraco.httpbackend.helper.js
- define the url in umbraco.httpbackend.js
###ServerVariables
There is a static servervariables file in /mocks which describes the urls used by the rest service, this is currently needed as we dont have this set as a angular service, and no real conventions for these urls yet. Longer-term it would be great to have a urlBuilder which could do
urlService.url("contentTypes", "GetAllowedChildren");
//would return /<umbracodir>/<apibaseDir>/contentyTypes/getAllowedChildren
But for now, they are set in the servervariables file.

View File

@@ -1,7 +0,0 @@
@ngdoc overview
@name Creating a property editor
@description
##Overview
TODO: SD: Write this article! :)

View File

@@ -1,65 +0,0 @@
@ngdoc overview
@name Tutorials
@description
##Tutorials
This section contains longer written tutorials on how to perform certain tasks with the new angular-based UI.
Our initial focus is getting developers up and running with their own property editors, and secondly we will focus on how to use the serverside support methods to hook into the clientside code from asp.net.
##Getting up and running
There are 2 ways to get umbraco 7 running, either from source, or from one of the nightly builds.
###{@link Running Running a nightly build}
This only works on windows with IIS or IISExpress
###{@link Building Building from source}
You can run the client bits on osx and windows, or simple run the source from Visual Studio
##Create your own editor
One of the big breaking changes in Umbraco 7 is the new format for property editors / data types. Get ahead by reading through our series on how to build your own:
###{@link CreatingAPropertyEditor Create an editor}
The initial setup of the plugin, the manifest and files
###{@link Adding-Configuration-To-Property-Editor Adding configuration}
How we make the editor configurable so it becomes flexible and reusable
###{@link Intergrating-Services-With-PropertyEditor Intergrating services}
How you can get access to all the standard services inside of Umbraco from your editor
###{@link Add-ServerSide-Data Adding serverside data}
How you can return your own custom data from the server to a property editor
through a ApiController
##Start developing
###{@link Source-Code-Structure how the source code is structured}
An overview of the different folders and files in the Umbraco 7 client project
##Recommended reading
It is always recommended to have a clear understanding of the underlying framework, before you start building on top of it.
###Html and css
For our html, css and various widgets, we use twitter bootstrap 2
- [getbootstrap.com](http://getbootstrap.com/)
###Javascript application framework
For the underlying application framework we use AngularJS, there are plenty of really good ressources for learning but these are our preffered ones:
- [egghead.io](http://www.egghead.io/)
- [angularjs.org/tutorial](http://docs.angularjs.org/tutorial)
- [Tekpub](http://tekpub.com/products/angular)
###Environment
We use various tools to built the client-side code. This is to ensure that our javascript is automatically tested, our .less files are compiled, and that files are minified and linted.
For all these automated tasks, we use [gruntjs](http://gruntjs.com) which is a javascript based task-runner for [node.js](http://nodejs.com)
it is highly recommended to read and understand the basics of grunt, and have a closer look at our gruntfile.js in the source, since this ties the entire application together.

View File

@@ -1,169 +0,0 @@
@ngdoc overview
@name Manifest overview
@description
This is a sample manifest, it is always stored in a folder in /app_plugins/{YourPackageName}, with the name package.manifest:
{
propertyEditors: [
{
alias: "Sir.Trevor",
name: "Sir Trevor",
editor: {
view: "~/App_Plugins/SirTrevor/SirTrevor.html",
hideLabel: true,
valueType: "JSON"
}
],
javascript: [
'~/App_Plugins/SirTrevor/SirTrevor.controller.js'
]
}
##Root elements
The manifest can contain 4 root colllections, none of them are mandatory
{
propertyEditors: [],
parameterEditors:[],
javascript: [],
css: []
}
##propertyEditors
Returns an array of editor objects, each object specifies an editor to make available to data types as an editor component. These editors are primarily property editors for content, media and members, but can also be made available as a macro parameter editor.
The basic values on any editor is `alias`, `name`, and `editor` these 3 must be set. Furthermore, the `editor` value is an object with additional configuration options on, but must contain a `view` value.
{
alias: "my.editor.alias",
name: "My friendly editor name",
editor: {
view: "~/App_Plugins/SirTrevor/view.html"
},
prevalues:{
fields: []
}
}
- **alias** The alias of the editor, this must be unique, its recommended to prefix with your own "namespace"
- **name** the name visible to the user in the ui, should also be unique.
- **editor** object containing editor configuration (see below)
- **isParameterEditor** enables the property editor as a macro parameter editor can be true/false
- **prevalues** configuration of editor prevalues (see below)
- **defaultConfig** default configation values (see below)
###Editor
Besides setting a view, the editor can also contain additinal information.
editor: {
view: "~/App_Plugins/SirTrevor/view.html",
hideLabel: true,
valueType: "TEXT",
validation: {},
isReadOnly: false
}
- **view**:path to the html file to use for rendering the editor
- **hideLabel**: turn the label on/off
- **valueType**: sets the DB type the value is stored as, by default its string
- **validation**: object describing required validators on the editor
- **isReadOnly**: disables editing the value
####valueType
Sets what kind of data the editor will save in the database. by default this is set to "string".
editor: {
view: "~/App_Plugins/SirTrevor/view.html",
valueType: "TEXT"
}
**The available options are**
- **STRING** : stores the value as an nvarchar in the database
- **DATETIME**: stores the value as datetime in the database
- **TEXT**: stores the value as ntext in the database
- **INT** stores the value as a bigint in the database
- **JSON** stored as ntext, but automatically serialized to dynamic object
###prevalues
Collection of prevalue editors, used for configurating the property editor, the prevalues object must return an array of editors, called "fields".
prevalues: {
fields:[
{
label: "Enable something",
description: "This is a describtion",
key: "enableStuff",
view: "boolean"
}
]
}
Each field contains a number of configuration values:
- **label**: the label shown on the data type configuration screen
- **description**: help text displayed underneath the label
- **key**: the key the prevalue is stored under (see below)
- **view**: path to the editor used to configure this prevalue (see below)
####key
The key on a prevalue, determines where its stored in the database, so if you give your prevalue the key "wolf" - then this key will be used in the prevalue table.
But it also means that when this property editor is used on a propety, then this prevalue will be exposed on the models configuration object like below, inside the property editors controller:
//this is the property value
$scope.model.value = "hello";
///this is the configration on the property editor:
$scope.model.config
//this is our specific prevalue with the alias wolf
$scope.model.config.wolf
####view
The `view` config value points the prevalue editor to an editor to use. This follows the same concept as any other editor in umbraco, but with prevalue editors there are a couple of conventions.
If you just specify a name like "boolean" then umbraco will look at `/umbraco/views/prevalueeditors/boolean/boolean.html` for the editor view - if you wish to use your own, you specify the path like `~/app_data/package/prevalue-editor.html`.
###defaultConfig
The defaultConfig object, provides a collection of default configuration values, in cases the property editor is not configured or is used a parameter editor, which doesnt allow configuration. The object is a key/value collection and must match the prevalue fields keys.
defaultConfig: {
wolf: "nope",
editor: "hello",
random: 1234
}
##parameterEditors
Returns an array of editor objects, each object specifies an editor to make available to macro parameters as an editor component. These editors work solely as parameter editors, and will not show up on the property editors list.
The parameter editors array follows the same format as the property editors described above, however, it cannot contain prevalues since there are no configuration options for macro parameter editors.
##javascript
Returns a string[] of javascript files to load on application start
javascript: [
'~/App_Plugins/SirTrevor/SirTrevor.controller.js',
'~/App_Plugins/SirTrevor/service.js'
]
##css
Returns a string[] of css files to load on application start
css: [
'~/App_Plugins/SirTrevor/SirTrevor.css',
'~/App_Plugins/SirTrevor/hibba.css'
]

View File

@@ -1,91 +0,0 @@
@ngdoc overview
@name Naming conventions
@description
##Overview
This document is loosely connected notes and thoughts on naming conventions on all application components for the Umbraco 7 UI.
##modules handle namespacing,
Naming: last one wins
but to do this automaticly, we would need
to auto-register all modules needed on app-start.
This gives us a couple of complications for handling 3rd party applications.
As it would be a pain to scan every file for modules to load on app start.
Proposed structure:
http://briantford.com/blog/huuuuuge-angular-apps.html
Register all modules in app.js
Root module: Umbraco
- contains the core services: notifications,dialogs,etc
- contains the core resources: content,media etc
- contains the core directives
1 module pr file princible
1st level modules:
Umbraco (for misc system-level stuff, dialogs, notifications, etc)
Umbraco.PropertyEditors (for all editors, as they are shared between all modules)
- how would a 3rd party property editor access a 3rd party service in the Ucommerce module, when its loaded in the content editor? (which is inside the the content module?)
Umbraco.Content (registers that it needs umbraco module, for access to core services )
Umbraco.Media
Umbraco.Settings
Ucommerce
TeaCommerce
Etc
Should all (core + 3rd party) services, filters and directives just be dependencies in the global umbraco module?
Each section namespace knows what modules to initially have loaded:
Umbraco.Content
- EditController
- SortController
Inside the EditController module, it references the needed services:
- DialogService
- ContentFactory
- Etc
So things are only loaded when needed, due to the modules, and our application, really only needs to know about the root modules, Content,Media,Settings, Ucommerce etc.
##Directives
If more directives have the same name, they will all be run
##Controllers
Last one wins, so you can override core controllers
Can be namedspaced, but shouldnt, the module is the namespace?
Module: Umbraco.Section.Area.Page
Name: PageNameController
Filename: /umbraco/section/area/pagename.controller.js
Ex: /umbraco/content/document/edit.controller.js
Ex: /umbraco/settings/documenttype/edit.controller.js
There is a need to have an extra level in the content tree urls due to all
other sections have this as well, and we dont want to confuse the routing.
The ctrl acronym is horrible and should not be used IMO.
##Services
typeService ? - cant be namespaced
Module: Umbraco.Services.Type
Name: TypeService?
Ex: Umbraco.Services.Notifications.NotificationsService
Filename: /umbraco/common/services/notifcations.service.js
##Resources
- Content, media, etc, cant be namespaced:
Module: Umbraco.Resources.Type
Name: TypeFactory?
Ex: Umbraco.Resources.Content.ContentFactory?
filename: /umbraco/common/resources/content.resources.js ? or
/umbraco/common/resoures/content.factory.js ?

View File

@@ -1,108 +0,0 @@
@ngdoc overview
@name Using AngularJS Promises and Umbraco Resources
@description
##Overview
Document to outline the way we work with data from the Umbraco rest API which is always returned as a promise, so we in an async way can resolve our data.
##Promises in Umbraco Resources
All Umbraco resource methods utilize a helper method:
umbRequestHelper.resourcePromise
This method accepts 2 arguments:
* The angular HttpPromise which is created with a call to $http.get (post, etc..)
* The error message that is bubbled to the UI when the http call fails
Here's an example of the usage in an Umbraco resource. This example is the method of the treeResource that fetches data to display the menu for a tree node:
/** Loads in the data to display the nodes menu */
loadMenu: function (node) {
return umbRequestHelper.resourcePromise(
$http.get(getTreeMenuUrl(node)),
"Failed to retrieve data for a node's menu " + node.id);
}
HTTP error handling is performed automatically inside of the `umbRequestHelper.resourcePromise` and inside of Umbraco's response interceptors.
##Consuming Umbraco resources
When consuming Umbraco resources, a normal angular promise will be returned based on the above `umbRequestHelper.resourcePromise`. The success callback will always receive the RAW json data from the server and the error callback will always receive an object containing these properties:
* erroMsg = the error message that can be used to show in the UI
* data = the original data object used to create the promise
Error handling will be done automatically in the Umbraco resource. Http error handling should not be done during the consumption of an Umbraco resource.
###Simple example
An simple example of consuming an Umbraco resource:
treeResource.loadMenu(treeItem.node)
.then(function(data) {
scope.menu = data;
});
###Transforming result data
Sometimes the consumption of an Umbraco resource needs to return a promise itself. This is required in some circumstances such as:
The data from a result of an http resource might need to be transformed into something usable in the UI so a Service may need to call a resource, transform the result and continue to return it's own promise (since everything happens async).
This is actually very simple to do, the Service (or whatever is consuming the resource) just returns the result of their 'then' call. Example - this example is the `getActions` method of the `treeService` that consumes the treeResource, transforms the result and continues to return it's own promise:
getActions: function(treeItem, section) {
return treeResource.loadMenu(treeItem.node)
.then(function(data) {
//need to convert the icons to new ones
for (var i = 0; i < data.length; i++) {
data[i].cssclass = iconHelper.convertFromLegacyIcon(data[i].cssclass);
}
return data;
});
}
Notice that this is just returning the call to 'then' which will return a promise that resolves the data from it's return statement.
###Error hanlding
Ok, what about error handling ? This is really simple as well, we just add an additional method to the .then call. A simple example:
treeResource.loadMenu(treeItem.node)
.then(function(data) {
scope.menu = data;
}, function(err) {
//display the error
notificationsService.error(err.errorMsg);
});
###Error handling when transforming result data
This is one of those things that is important to note! If you need to return a custom promise based on the result of an Umbraco resource (like the example above in Transforming result data) then you will need to 'throw' an error if you want to 'bubble' the error to the handler of your custom promise.
The good news is, this is very simple to do, example:
getActions: function(treeItem, section) {
return treeResource.loadMenu(treeItem.node)
.then(function(data) {
//need to convert the icons to new ones
for (var i = 0; i < data.length; i++) {
data[i].cssclass = iconHelper.convertFromLegacyIcon(data[i].cssclass);
}
return data;
}, function(err) {
//display the error
notificationsService.error(err.errorMsg);
//since we want the handler of this promise to be notified of this error
// we just need to rethrow it:
throw err;
});
}
The next thing that is important to note is that **you don't have to do anything** if you don't want to do anything with the error but still want the error bubbled up to your promises handlers. So for example, if you are expecting the handler of this promise to handle the error and display something in the UI, just leave out the function(err) callback which would look exactly the same as the example for 'Transforming result data'

View File

@@ -305,6 +305,10 @@ module.exports = function (grunt) {
watch: {
docs: {
files: ['docs/src/**/*.md'],
tasks: ['watch-docs', 'timestamp']
},
css: {
files: 'src/**/*.less',
tasks: ['watch-less', 'timestamp'],
@@ -347,8 +351,8 @@ module.exports = function (grunt) {
title: 'API Documentation'
},
tutorials: {
src: ['docs/src/tutorials/**/*.ngdoc'],
title: 'Tutorials'
src: [],
title: ''
}
},

View File

@@ -9,6 +9,7 @@
"name": "Image",
"alias": "media",
"view": "media",
"render": "eatme",
"icon": "icon-picture"
},
{