Merge lp:~hatch/juju-gui/1130787-subapp-app-extension into lp:juju-gui/experimental
- 1130787-subapp-app-extension
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~hatch/juju-gui/1130787-subapp-app-extension |
Merge into: | lp:juju-gui/experimental |
Diff against target: |
311 lines (+243/-1) (has conflicts) 6 files modified
app/app.js (+6/-1) app/assets/javascripts/app-subapp-extension.js (+144/-0) app/modules-debug.js (+7/-0) bin/merge-files (+5/-0) test/index.html (+4/-0) test/test_subapp_app_extension.js (+77/-0) Text conflict in app/app.js Text conflict in app/modules-debug.js Text conflict in bin/merge-files Text conflict in test/index.html |
To merge this branch: | bzr merge lp:~hatch/juju-gui/1130787-subapp-app-extension |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju GUI Hackers | Pending | ||
Review via email:
|
Commit message
Description of the change
Created app subapp extension
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Benjamin Saller (bcsaller) wrote : | # |
Thanks for the branch.
I have some minor comments below but there are still things I'm not
clear about here.
At minimum it seems that the parent should be the eventTarget of the
subApp when its created? Is that going to live in another branch? I
suppose this branch presents too small view of the final picture for me
to understand how this plays out in reality.
Also is there a use case for subapp removal? I think we can pass on that
for now as well, but we might note this somewhere.
Looking forward to seeing more.
https:/
File app/assets/
https:/
app/assets/
As we don't currently support removal should this be writeOnce and/or
initOnly?
https:/
app/assets/
type -> instance, its more clear and follow the
App.views.
this.get(
occur below making things a little harder to follow than they need to
be.
https:/
app/assets/
this._augmentPa
parent seems unnecessary in the naming, _this_ is the parent.
_augmentRoutes or _mixinRoutes?
https:/
app/assets/
subApps an array of sub abb objects and configs.
s/abb/app
https:/
app/assets/
subApps.length; i += 1) {
Y.each? We usually favor iterators to native loops.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Thanks for the review - I'll make the changes and resubmit
https:/
File app/assets/
https:/
app/assets/
On 2013/02/25 20:12:13, bcsaller wrote:
> As we don't currently support removal should this be writeOnce and/or
initOnly?
I understand where you're coming from but I'm not really a fan of adding
that restriction when it doesn't gain us anything - possibly something
to investigate in the future.
https:/
app/assets/
On 2013/02/25 20:12:13, bcsaller wrote:
> type -> instance, its more clear and follow the
App.views.
Sorry yes this documentation is incorrect I will fix
The new syntax mirrors how Y.App does views { type: 'name', ... }
> model.
> this.get(
occur
> below making things a little harder to follow than they need to be.
I'll evaluate a better naming convention as your right this could likely
cause name clashes.
https:/
app/assets/
this._augmentPa
On 2013/02/25 20:12:13, bcsaller wrote:
> parent seems unnecessary in the naming, _this_ is the parent.
> _augmentRoutes or _mixinRoutes?
Agreed, will fix
https:/
app/assets/
subApps an array of sub abb objects and configs.
On 2013/02/25 20:12:13, bcsaller wrote:
> s/abb/app
will fix
https:/
app/assets/
subApps.length; i += 1) {
On 2013/02/25 20:12:13, bcsaller wrote:
> Y.each? We usually favor iterators to native loops.
Agreed, will fix
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gary Poster (gary) wrote : | # |
Hi Jeff. I like where this is going. As I said on IRC, my biggest
concern is a lack of tests. I have some small-to-medium sized issues
here as well.
Notice that, because I sat on this review for awhile, the notes are from
an earlier revision. Hopefully they are still mostly worthwhile.
Thanks!
Gary
https:/
File app/assets/
https:/
app/assets/
Please add the yuidoc @module stuff here (see the topology example, for
instance)
https:/
app/assets/
SubAppRegistrat
Please add a @class directive like the topology example one.
Note that make view-docs is a nice way to double-check that you have
made the docs you want.
https:/
app/assets/
We usually comment these with "*" marks before each line. If YUI doc
does not require this, as far as I am concerned, rejoice!!! And share
the knowledge with the rest of us. But if the doc parser is unhappy,
try adding those.
https:/
app/assets/
application and it's routes to the parent application.
typo: its
https:/
app/assets/
subApp string referance to an instantiable Y.App object.
typo: reference
I don't understand this comment. The string names a property of the
parent Y.App object that is the factory for the SubApp? No, that's not
it. You get it off of Y? Is this common? Never seen that before. If
I understand correctly that you are supposed to create an application
object hanging off of the Y (framework) object, I don't really like that
on the face of it, but I'll defer to you if you say that you are
confident that this is the YUI way. We have instead made our own
top-level objects, rather than polluting the framework namespace. That
seems safer to me.
https:/
app/assets/
refresh routes from the sub apps.
When would you need to call this?
https:/
app/assets/
index index of the subapp to refresh if undefined
typo: s/index index/index/
...to refresh. If undefined,...
https:/
app/assets/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Thanks a bunch for your comments I'll get on them right away! I only
have one follow-up for line 109 so if you could let me know if that was
your expectation that would be great!
Thanks again
https:/
File app/assets/
https:/
app/assets/
On 2013/02/25 21:20:05, gary.poster wrote:
> Please add the yuidoc @module stuff here (see the topology example,
for
> instance)
will fix
https:/
app/assets/
SubAppRegistrat
On 2013/02/25 21:20:05, gary.poster wrote:
> Please add a @class directive like the topology example one.
> Note that make view-docs is a nice way to double-check that you have
made the
> docs you want.
will fix
https:/
app/assets/
On 2013/02/25 21:20:05, gary.poster wrote:
> We usually comment these with "*" marks before each line. If YUI doc
does not
> require this, as far as I am concerned, rejoice!!! And share the
knowledge with
> the rest of us. But if the doc parser is unhappy, try adding those.
YUIdoc doesn't require them it simply requires two stars after the slash
/** docs */ but I may be using a newer version - I'll re-check once I
fix the above missing docs
https:/
app/assets/
application and it's routes to the parent application.
On 2013/02/25 21:20:05, gary.poster wrote:
> typo: its
will fix
https:/
app/assets/
subApp string referance to an instantiable Y.App object.
On 2013/02/25 21:20:05, gary.poster wrote:
> typo: reference
> I don't understand this comment. The string names a property of the
parent
> Y.App object that is the factory for the SubApp? No, that's not it.
You get it
> off of Y? Is this common? Never seen that before. If I understand
correctly
> that you are supposed to create an application object hanging off of
the Y
> (framework) object, I don't really like that on the face of it, but
I'll defer
> to you if you say that you are confident that this is the YUI way. We
have
> instead made our own top-level objects, rather than polluting the
framework
> namespace. That seems safer to me.
My thought process behind this was that I wanted to mirror the syntax of
how Y.App deals with views with the syntax { type: 'path.to.view' } to
make it more consistent.
In looking at how the codebase does modules they are almost always hung
off of the Y instance under their own namespace so this allows them to
keep with the same syntax ie) 'juju.subapps.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gary Poster (gary) wrote : | # |
Hey Jeff. I made replies to some of your comments.
https:/
File app/assets/
https:/
app/assets/
subApp string referance to an instantiable Y.App object.
On 2013/02/25 21:46:59, jeff.pihach wrote:
> On 2013/02/25 21:20:05, gary.poster wrote:
> > typo: reference
> >
> > I don't understand this comment. The string names a property of the
parent
> > Y.App object that is the factory for the SubApp? No, that's not it.
You get
> it
> > off of Y? Is this common? Never seen that before. If I understand
correctly
> > that you are supposed to create an application object hanging off of
the Y
> > (framework) object, I don't really like that on the face of it, but
I'll defer
> > to you if you say that you are confident that this is the YUI way.
We have
> > instead made our own top-level objects, rather than polluting the
framework
> > namespace. That seems safer to me.
> My thought process behind this was that I wanted to mirror the syntax
of how
> Y.App deals with views with the syntax { type: 'path.to.view' } to
make it more
> consistent.
> In looking at how the codebase does modules they are almost always
hung off of
> the Y instance under their own namespace so this allows them to keep
with the
> same syntax ie) 'juju.subapps.
Ah I thought juju was not off of Y. All's well then, thanks.
https:/
app/assets/
refresh routes from the sub apps.
On 2013/02/25 21:46:59, jeff.pihach wrote:
> On 2013/02/25 21:20:05, gary.poster wrote:
> > When would you need to call this?
> If you manipulated the routes on a subapp after instantiation you
would need to
> push those back up to the parent.
> But in all honesty I I created it while prototyping and just left it
in :-)
Heh, cool. I suggest removing it then. When you write tests, and have
to decide between testing this or removing it, I bet you will prefer
removing it too. :-)
https:/
app/assets/
On 2013/02/25 21:46:59, jeff.pihach wrote:
> On 2013/02/25 21:20:05, gary.poster wrote:
> > Is there really a use case for this? Seems like a YAGNI. If we
have a use
> > case, never mind
> The idea behind allowing the dev to specify a number was a foreshadow
into
> future platform differences - they may not want to extract all routes
on a
> mobile device for example
Huh, ok. I suggest either giving a believable example of how this would
work in a comment, or deleting it as a YAGNI for now. It looks easy to
add back it.
https:/
app/assets/
On 2013/02/25 21:46:59, jeff.pi...
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Benjamin Saller (bcsaller) wrote : | # |
https:/
File app/assets/
https:/
app/assets/
'*') {
On 2013/02/25 21:59:00, gary.poster wrote:
> On 2013/02/25 21:46:59, jeff.pihach wrote:
> > On 2013/02/25 21:20:05, gary.poster wrote:
> > > hm. I guess this is a reasonable definition of middleware. It
makes me a
> bit
> > > nervous that there will be conditional middleware of some sort,
only applied
> > to
> > > certain paths...
> > Maybe I should comment this further - what it's doing is grabbing
the parent
> > routes and adding any child routes after the 'middleware' which is
really
> > anything in the parent route with a * path
> Yeah, I understood most of that. That's not a robust definition of
middleware
> though. Middleware is really something that passes through to more
routes,
> whether the path is * or /foo/* or even simply /foo. This code
assumes the
> common case, and slams over less common cases. It makes me nervous
that it will
> be a source for rare but occasional surprising bugs.
While native Y.App.route doesn't support annotations we do, we could
simply tag routes as `middleware`: true.
Another option is simply to append namespaced routes at the end. Now
that we support qualified matches (requiring the namespace attr to
match) there is no need to place them anywhere but the end. The issue
before was that a default route at the end would match anything
preventing namespaced routes from being matched. Now the default route
would be passed over.
Unless special provision is taken such that namespace attrs on subapp
routes were preserved (rather than set by the binding to App) this
policy would work.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Benjamin Saller (bcsaller) wrote : | # |
Thanks for the continued work on this branch.
Personally I think we should switch to a namespaced, append routes
model, that would remove the need to do the placement test that I
suggest below. I think gary would agree that this is simpler and more
foolproof.
https:/
File app/assets/
https:/
app/assets/
No default still?
https:/
app/assets/
groupedRoutes;
groupedRoutes is unused.
https:/
File test/test_
https:/
test/test_
match');
With a change to middleware handling we should test that insertion
happens in the currently expected place.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gary Poster (gary) wrote : | # |
LGTM with trivials.
Hi Jeff. I have a lot of comments and suggestions and thoughts. The
only thing that's a clear "please do this" request is the trivial
grammatical change ("it's" -> "its").
Everything else is thoughts. What you've done is good and has plenty of
precedent, but I think what we talked about would have been better. If
you'd like to leave it as it is, that's fine; or land it.
Thanks
Gary
https:/
File app/assets/
https:/
app/assets/
application and it's routes to the parent application.
trivial typo, but repeated from previous feedback: you mean "its."
As a matter of policy, we are supposed to go through every comment in a
review and acknowledge the comment, so the reviewer can see that their
effort was recognized, understood, and acted on. For some of us, that
is one of those rules "more honored in the breach" :-) but it really
shouldn't be. Since you missed this (trivial) comment, it might be a
good habit to get into.
https:/
app/assets/
Y.Object.
I personally think we ought to just pass in factories directly, not
strings. <shrug>
https:/
app/assets/
That's a lot of whitespace! I think we have a "don't use lots of
whitespace unless you really really want to" kind of non-rule, but could
be wrong. Do what you want here.
https:/
app/assets/
this._augmentRo
The addSubApp function reads very nicely.
https:/
app/assets/
'*') {
I still question this, but <shrug>
https:/
File test/test_
https:/
test/test_
For this level of tests, IMO it would have been nicer to use a generic
App, with your extension mixed in.
https:/
test/test_
I thought this was explicitly what you were not going to do! I don't
mind, but IMO the plan we discussed, as driven by the concerns you
expressed, was nicer.
https:/
test/test_
assert.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Thanks for the reviews! Please see the attached comments
https:/
File app/assets/
https:/
app/assets/
application and it's routes to the parent application.
On 2013/02/26 22:07:25, gary.poster wrote:
> trivial typo, but repeated from previous feedback: you mean "its."
> As a matter of policy, we are supposed to go through every comment in
a review
> and acknowledge the comment, so the reviewer can see that their effort
was
> recognized, understood, and acted on. For some of us, that is one of
those
> rules "more honored in the breach" :-) but it really shouldn't be.
Since you
> missed this (trivial) comment, it might be a good habit to get into.
Fixed.
https:/
app/assets/
Y.Object.
On 2013/02/26 22:07:25, gary.poster wrote:
> I personally think we ought to just pass in factories directly, not
strings.
> <shrug>
No problem - consider it changed.
https:/
app/assets/
On 2013/02/26 22:07:25, gary.poster wrote:
> That's a lot of whitespace! I think we have a "don't use lots of
whitespace
> unless you really really want to" kind of non-rule, but could be
wrong. Do what
> you want here.
I collapsed them into like commands to tighten it up a bit.
https:/
app/assets/
this._augmentRo
On 2013/02/26 22:07:25, gary.poster wrote:
> The addSubApp function reads very nicely.
Thanks
https:/
app/assets/
On 2013/02/26 22:00:56, bcsaller wrote:
> No default still?
Default has now been added.
https:/
app/assets/
groupedRoutes;
On 2013/02/26 22:00:56, bcsaller wrote:
> groupedRoutes is unused.
Poof it's gone!
https:/
app/assets/
'*') {
On 2013/02/26 22:07:25, gary.poster wrote:
> I still question this, but <shrug>
I'm going to leave this insertion method in here for now - at least
until we get the namespace code separated out and a functional sub app
using the code - it's trivial to change but I know that this works for
the prototype use case :-)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gary Poster (gary) wrote : | # |
On 2013/02/27 17:04:29, jeff.pihach wrote:
> Thanks for the reviews! Please see the attached comments
:-) thanks, sounds good.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Benjamin Saller (bcsaller) wrote : | # |
LGTM
I think this is in shape to land so we can move forward with it. I still
have some reservations about how it all fits together, but I'm convinced
we will be able to make this work.
Thanks again.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Hey sorry guys I forgot to 'save' my comments on the test page - please
see those comments below.
https:/
File test/test_
https:/
test/test_
On 2013/02/26 22:07:25, gary.poster wrote:
> For this level of tests, IMO it would have been nicer to use a generic
App, with
> your extension mixed in.
Sure thing - no problem I can switch that over.
https:/
test/test_
On 2013/02/26 22:07:25, gary.poster wrote:
> I thought this was explicitly what you were not going to do! I don't
mind, but
> IMO the plan we discussed, as driven by the concerns you expressed,
was nicer.
True however in practice it ended up being another level of abstraction
which was only valuable in testing and created needless complexity
everywhere else so I decided to bench those changes.
https:/
test/test_
match');
On 2013/02/26 22:07:25, gary.poster wrote:
> Another deepEqual, this time of the trailing routes, would have been
cool. This
> is alright though, given the previous test.
Because I'm benching changing the insertion point of the routes I am
going to leave this as is in conjunction with the above test. I foresee
changes in it's future...
also I can't deep equal here because the routes are augmented with quite
a bit of meta data that I am unable to mock. I'll have to investigate a
better way to do this once we have a fleshed out subapp
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Gary Poster (gary) wrote : | # |
LGTM still--looks even better. :-)
Thanks
Gary
https:/
File app/assets/
https:/
app/assets/
SubApp string referance to an instantiable Y.App object.
No longer a string reference
https:/
File test/test_
https:/
test/test_
Cool.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
*** Submitted:
Created app subapp extension
R=bcsaller, gary.poster
CC=
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeff Pihach (hatch) wrote : | # |
Please take a look.
Unmerged revisions
- 415. By Jeff Pihach
-
calling the subapp route callback in the proper context
Preview Diff
1 | === modified file 'app/app.js' |
2 | --- app/app.js 2013-02-27 16:38:40 +0000 |
3 | +++ app/app.js 2013-02-27 17:50:27 +0000 |
4 | @@ -27,7 +27,7 @@ |
5 | * |
6 | * @class App |
7 | */ |
8 | - var JujuGUI = Y.Base.create('juju-gui', Y.App, [], { |
9 | + var JujuGUI = Y.Base.create('juju-gui', Y.App, [Y.juju.SubAppRegistration], { |
10 | |
11 | /* |
12 | * Views |
13 | @@ -1194,6 +1194,11 @@ |
14 | 'app-transitions', |
15 | 'base', |
16 | 'node', |
17 | +<<<<<<< TREE |
18 | 'model', |
19 | 'sub-app'] |
20 | +======= |
21 | + 'model', |
22 | + 'app-subapp-extension'] |
23 | +>>>>>>> MERGE-SOURCE |
24 | }); |
25 | |
26 | === added file 'app/assets/javascripts/app-subapp-extension.js' |
27 | --- app/assets/javascripts/app-subapp-extension.js 1970-01-01 00:00:00 +0000 |
28 | +++ app/assets/javascripts/app-subapp-extension.js 2013-02-27 17:50:27 +0000 |
29 | @@ -0,0 +1,144 @@ |
30 | +'use strict'; |
31 | + |
32 | +YUI.add('app-subapp-extension', function(Y) { |
33 | + |
34 | + /** |
35 | + Adds the ability to register sub applications with a parent Y.App instance by |
36 | + recording all instances in a subApps attribute and augmenting the parent |
37 | + routes with the sub applications. |
38 | + |
39 | + @class SubAppRegistration |
40 | + @extension App |
41 | + */ |
42 | + function SubAppRegistration() {} |
43 | + |
44 | + SubAppRegistration.ATTRS = { |
45 | + subApps: { |
46 | + value: {} |
47 | + } |
48 | + }; |
49 | + |
50 | + SubAppRegistration.prototype = { |
51 | + |
52 | + /** |
53 | + A list of sub applications to be instantiated after initialization |
54 | + of the parent app. |
55 | + |
56 | + [{ |
57 | + type: path.to.subapp |
58 | + config: {} |
59 | + }] |
60 | + |
61 | + @property subApplications |
62 | + @type {array} |
63 | + */ |
64 | + subApplications: [], |
65 | + |
66 | + /** |
67 | + Adds all of the sub applications listed in the subApplications property. |
68 | + |
69 | + @method addSubApplications |
70 | + */ |
71 | + addSubApplications: function() { |
72 | + this.addSubApps(this.subApplications); |
73 | + }, |
74 | + |
75 | + /** |
76 | + Adds the sub application and its routes to the parent application. |
77 | + |
78 | + @method addSubApp |
79 | + @param {string} SubApp string referance to an instantiable Y.App object. |
80 | + @param {object} config configuration properties for the subapp. |
81 | + */ |
82 | + addSubApp: function(SubApp, config) { |
83 | + var subApps = this.get('subApps'), |
84 | + routes; |
85 | + |
86 | + SubApp = new SubApp(config); |
87 | + subApps[SubApp.get('urlNamespace')] = SubApp; |
88 | + |
89 | + routes = this._extractRoutes(SubApp); |
90 | + this._augmentRoutes(routes); |
91 | + }, |
92 | + |
93 | + /** |
94 | + Wrapper for addSubApp to add multiple sub apps at once. |
95 | + |
96 | + [{ |
97 | + type: 'path.to.subapplication' |
98 | + config: {} |
99 | + }] |
100 | + |
101 | + @method addSubApps |
102 | + @param {array} subApps an array of sub app objects and configs. |
103 | + */ |
104 | + addSubApps: function(subApps) { |
105 | + Y.Array.each(subApps, function(subApp) { |
106 | + this.addSubApp(subApp.type, subApp.config); |
107 | + }, this); |
108 | + }, |
109 | + |
110 | + /** |
111 | + Extract the routes out of the sub apps. |
112 | + |
113 | + @method _extractRoutes |
114 | + @protected |
115 | + @param {object | integer | undefined} subApp will extract the routes |
116 | + out of the supplied subApp, index, or all subApps if undefined. |
117 | + @return {array} array of sub app route data. |
118 | + */ |
119 | + _extractRoutes: function(subApp) { |
120 | + var subApps = this.get('subApps'), |
121 | + routes, subRoutes, i, j; |
122 | + |
123 | + switch (typeof subApp) { |
124 | + case 'number': // If an index is passed in grab that subapp |
125 | + subApp = subApps[subApp]; |
126 | + /* falls through */ |
127 | + case 'object': // If subapp is passed in fetch it's routes |
128 | + routes = subApp.getSubAppRoutes(); |
129 | + break; |
130 | + case 'undefined': |
131 | + routes = []; |
132 | + for (i = 0; i < subApps.length; i += 1) { |
133 | + subRoutes = subApps[i].getSubAppRoutes(); |
134 | + for (j = 0; j < subRoutes.length; j += 1) { |
135 | + routes.push(subRoutes[j]); |
136 | + } |
137 | + } |
138 | + break; |
139 | + default: |
140 | + throw 'subApp valid types are integer, object, or undefined'; |
141 | + } |
142 | + return routes; |
143 | + }, |
144 | + |
145 | + /** |
146 | + Adds the sub app routes to the parent routes after the middleware |
147 | + |
148 | + @method _augmentRoutes |
149 | + @protected |
150 | + @param {array} array of route objects. |
151 | + */ |
152 | + _augmentRoutes: function(routes) { |
153 | + var parentRoutes = this.get('routes'), |
154 | + middlewareIndex; |
155 | + |
156 | + Y.Array.some(parentRoutes, function(value, index, array) { |
157 | + if (value.path !== '*') { |
158 | + middlewareIndex = index; |
159 | + return true; |
160 | + } |
161 | + }); |
162 | + |
163 | + routes.unshift(middlewareIndex, 0); |
164 | + Array.prototype.splice.apply(parentRoutes, routes); |
165 | + |
166 | + this.set('routes', parentRoutes); |
167 | + return parentRoutes; |
168 | + } |
169 | + }; |
170 | + |
171 | + Y.namespace('juju').SubAppRegistration = SubAppRegistration; |
172 | + |
173 | +}, '0.1.0'); |
174 | |
175 | === modified file 'app/modules-debug.js' |
176 | --- app/modules-debug.js 2013-02-25 19:53:33 +0000 |
177 | +++ app/modules-debug.js 2013-02-27 17:50:27 +0000 |
178 | @@ -56,10 +56,17 @@ |
179 | fullpath: '/juju-ui/assets/javascripts/routing.js' |
180 | }, |
181 | |
182 | +<<<<<<< TREE |
183 | 'sub-app': { |
184 | fullpath: '/juju-ui/assets/javascripts/sub-app.js' |
185 | }, |
186 | |
187 | +======= |
188 | + 'app-subapp-extension': { |
189 | + fullpath: '/juju-ui/assets/javascripts/app-subapp-extension.js' |
190 | + }, |
191 | + |
192 | +>>>>>>> MERGE-SOURCE |
193 | // Views |
194 | 'juju-landscape': { |
195 | fullpath: '/juju-ui/views/landscape.js' |
196 | |
197 | === modified file 'bin/merge-files' |
198 | --- bin/merge-files 2013-02-25 19:53:33 +0000 |
199 | +++ bin/merge-files 2013-02-27 17:50:27 +0000 |
200 | @@ -75,8 +75,13 @@ |
201 | 'app/assets/javascripts/routing.js', |
202 | 'app/assets/javascripts/gallery-ellipsis.js', |
203 | 'app/assets/javascripts/gallery-markdown.js', |
204 | +<<<<<<< TREE |
205 | 'app/assets/javascripts/gallery-timer.js', |
206 | 'app/assets/javascripts/sub-app.js']); |
207 | +======= |
208 | + 'app/assets/javascripts/gallery-timer.js', |
209 | + 'app/assets/javascripts/app-subapp-extension.js']); |
210 | +>>>>>>> MERGE-SOURCE |
211 | |
212 | merge.combineJs(filesToLoad.js, 'build-shared/juju-ui/assets/all-yui.js'); |
213 | |
214 | |
215 | === modified file 'test/index.html' |
216 | --- test/index.html 2013-02-26 19:29:43 +0000 |
217 | +++ test/index.html 2013-02-27 17:50:27 +0000 |
218 | @@ -56,7 +56,11 @@ |
219 | <script src="test_service_module.js"></script> |
220 | <script src="test_service_view.js"></script> |
221 | <script src="test_startup.js"></script> |
222 | +<<<<<<< TREE |
223 | <script src="test_sub_app.js"></script> |
224 | +======= |
225 | + <script src="test_subapp_app_extension.js"></script> |
226 | +>>>>>>> MERGE-SOURCE |
227 | <script src="test_templates.js"></script> |
228 | <script src="test_topology.js"></script> |
229 | <script src="test_topology_relation.js"></script> |
230 | |
231 | === added file 'test/test_subapp_app_extension.js' |
232 | --- test/test_subapp_app_extension.js 1970-01-01 00:00:00 +0000 |
233 | +++ test/test_subapp_app_extension.js 2013-02-27 17:50:27 +0000 |
234 | @@ -0,0 +1,77 @@ |
235 | +'use strict'; |
236 | + |
237 | +describe('SubApplication App Extension', function() { |
238 | + var Y, juju, app, mocks, MockApp; |
239 | + |
240 | + before(function(done) { |
241 | + Y = YUI(GlobalConfig).use(['juju-routing', |
242 | + 'juju-gui', 'app-subapp-extension'], |
243 | + function(Y) { |
244 | + juju = Y.namespace('juju'); |
245 | + MockApp = Y.Base.create('mock-app', Y.App, |
246 | + [Y.juju.SubAppRegistration], {}); |
247 | + done(); |
248 | + }); |
249 | + |
250 | + }); |
251 | + |
252 | + beforeEach(function() { |
253 | + app = new MockApp(); |
254 | + |
255 | + Y.namespace('mock'); |
256 | + |
257 | + mocks = { |
258 | + subAppRoutes: [ |
259 | + { path: '/', callbacks: 'showRootView', namespace: 'charmStore' }, |
260 | + { path: '/charm/:id', callbacks: 'showCharmDetailView', |
261 | + namespace: 'charmStore' } |
262 | + ], |
263 | + parentAppRoutes: [ |
264 | + { path: '*', callbacks: 'check_user_credentials' }, |
265 | + { path: '*', callbacks: 'show_notifications_view' }, |
266 | + { path: '/charms/', callbacks: 'show_charm_collection' }, |
267 | + { path: '/charms/*charm_store_path/', callbacks: 'show_charm' } |
268 | + ] |
269 | + }; |
270 | + |
271 | + function subAppMock() {} |
272 | + subAppMock.prototype.getSubAppRoutes = function() { |
273 | + return mocks.subAppRoutes; |
274 | + }; |
275 | + subAppMock.prototype.get = function(attribute) { |
276 | + if (attribute === 'urlNamespace') { return 'charmStore'; } |
277 | + }; |
278 | + Y.mock.subapp = subAppMock; |
279 | + |
280 | + mocks.subAppProperty = { |
281 | + type: Y.mock.subapp, |
282 | + config: {} |
283 | + }; |
284 | + }); |
285 | + |
286 | + it('should add subapps to the parent app', function() { |
287 | + app.set('routes', mocks.parentAppRoutes); |
288 | + app.addSubApp(mocks.subAppProperty.type, mocks.subAppProperty.config); |
289 | + var subapps = app.get('subApps'); |
290 | + assert(typeof subapps.charmStore === 'object'); |
291 | + }); |
292 | + |
293 | + it('should extract the routes from the subapp', function() { |
294 | + app.set('subApps', [new Y.mock.subapp()]); |
295 | + assert.deepEqual(app._extractRoutes(), mocks.subAppRoutes, |
296 | + 'Routes do not match'); |
297 | + }); |
298 | + |
299 | + it('should augment the parent routes with the subapp routes', function() { |
300 | + var augmentedRoutes, numberOfRoutes; |
301 | + |
302 | + numberOfRoutes = mocks.subAppRoutes.length + mocks.parentAppRoutes.length; |
303 | + app.set('routes', mocks.parentAppRoutes); |
304 | + |
305 | + augmentedRoutes = app._augmentRoutes(mocks.subAppRoutes), |
306 | + |
307 | + assert.equal(augmentedRoutes.length, numberOfRoutes, |
308 | + 'Number of routes does not match'); |
309 | + }); |
310 | + |
311 | +}); |
Reviewers: mp+150414_ code.launchpad. net,
Message:
Please take a look.
Description:
Created app subapp extension
https:/ /code.launchpad .net/~hatch/ juju-gui/ 1130787- subapp- app-extension/ +merge/ 150414
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/7381055/
Affected files: javascripts/ app-subapp- extension. js debug.js
A [revision details]
M app/app.js
A app/assets/
M app/modules-
M bin/merge-files