I'm developing a web-application with angular and this will be used for different customers. Each customer has his own needs (specific functionality) and style (css). A lot of the functionality is shared though.
What I'm looking for is a total solution to keep this project clean and maintainable. The code will be running on the local server of each customer and the customers shouldn't see the specific code for the other customers (with other words, something like grunt should have filtered the deployment).
What I had in mind:
Define different tasks in grunt to watch, build, etc per customer
Define parent controllers (~inheritance) and parent views to share functionality
Use a subfolder for each customer
e.g. views:
app/views/general/home.html (loads main.tpl.html)
app/views/customer1/main.tpl.html
app/views/customer2/main.tpl.html
e.g. controllers:
app/scripts/controllers/general/...
app/scripts/controllers/customer1/... (extends general controllers)
e.g. css
app/styles/general/...
app/styles/customer1/...
Grunt will select only the files relevant for the customer and should remove the customer-related paths. (e.g. both app/views/customer1/ and app/views/customer2/ should go to app/views/customer, which is loaded by app/views/general/home.html)
A big disadvantage will be that the app/views/general/home.html will have a reference to unexisting file while developing. The same goes for index.html where I need to include the controllers from the target dist folder, not from the project folder structure (while developing). Which makes everything a bit less readable and logical.
Do you think this is a good approach? Are there optimizations or alternatives coming to mind? Do you know of any grunt modules or angular modules aiding for such set-up?
Thanks in advance!
One approach you could use is to run a basic node server that will store and serve up, using a rest call, the user preferences. So you would save user specific settings such as layout, etc and update these in a simple JSON file stored on a local or remote node server.
Related
I feel like there is relatively little documentation on the "best practices" of how one should go about organizing AngularJS code. For example, in many of my web pages, i.e.
index.php
profile.php
editprofile.php
There are often many factories and methods that I need repeated. For example, profile.php,, editprofile.php, and index.php all need the factory userDropdown (to get the top navbar dropdown menu). However, some of them need "modified versions of factories". For example:
index.php needs a way to get all the users and their information
profile.php needs a way to get some users information
editProfile.php needs a way to get only one user information
What I mean is that (and the above was a poor example), is that often many .js files needs some modified "child" of a "parent" factory. I find it hard to scale my application because profile.php, index.php, and editProfile.php all refer to their own factories and methods, not a base file. Changes, improvements, errors, found in one factory and is corrected, will not propagate into other files (which I find very frustrating). I also don't want to write /copy/paste services and factories over and over again. Other issue I've had is that:
X.js file need some providers that Y.js file doesn't. However, both needs providers A and B, but X needs C and Y needs D. Is it bad for me to use the same "factory" and providers" for both of them (i.e. inject A, B, C, and D into both of them?) That's the problem I see with having a base factory of a factory to serve a lot of .js files. How much space or inefficiency is it to define providers or injectable services that you don't use?
How do I accomplish some scalable angularJS code to do this, or how do you guys go about organizing your angular code? And also, what about repeating HTML templates (i.e. repeating HTML code that needs to be used in almost every page? I've heard of some service called $templateCache but couldn't figure out how to use it.)
https://github.com/johnpapa/angular-styleguide This also has an example app but seriously read through his guidelines they seem to be exactly what you are looking for and have been a great resource for me as I've been learning to build bigger angular apps.
People mention requirejs together with marionette, backbonejs and the like.
requirejs seems an asset loader -- executing your rules on when to load what.
I know the first 'page' of my single-page-app already needs most of the files. If I don't mind loading all files in one go, can I simply ignore requirejs?
Technically yes. Only dependencies for marionette-backbone are
jQuery v1.8+
Underscore v1.4.4 - 1.6.0
Backbone v1.0.0 - 1.1.2 are preferred
Backbone.Wreqr (Comes automatically with the bundled build)
Backbone.BabySitter(Comes automatically with the bundled build)
Further require.js can manage use code structure in a manner which give your code much resource efficient code at the end. From my point of view for simple application which you need simple set of views,models and collection with manageable amount of code it ok to proceed without require.js.
But if your application have complex logic and higher number of resources it's good to go require.js. Because it not good to send 15+ like individual resource requests server at very beginning of your application load. Require can make any number of your resource in to one server resource. That's the advantage.
What I prefer is one request of all css, one for all js, one for sprite image for graphic if things are big to handle which allow to create fast performing application.
Take you decision looking at the amount of resources of the project. It's not essential have require.js form the beginning of your application development.
I am using angular seed project
https://github.com/angular/angular-seed
where should I put the services and directives ?
This is really totally up to you but there are some good recommendations on project structure here: https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
Typically my structure looks something like
app\scripts\user.js
app\scripts\todo.js
Where User.js would have a service and possibly multiple controllers in it... if the file gets too large then I break it up into parts.
The problem with grouping all services together and all controllers is that the services and controllers typically have a relationship (functionally). When you want to re-use the service/controller you are typically going to use them together, when editing one you usually need a reference to the other. This makes it easiest to find things and not have 1000 js files to include and manage in the dependencies and script inclusions.
Also when it comes time and you want to make a bower component out of one of the sections it's easier to see which parts need to be pulled out.
You can make a folder for each under app, so your project tree will look like this:
app/directives
app/services
Background
I have to migrte a existing javascript application (one page app) to extjs. The display and behavior of the application depends on the users permission.
Current design
The application is divided into plugins, which represent a feature set to which permissions are granted. Each of those plugins consists of a single javascript file. A user can have permissions for one or more plugins. Depending on the permissions, those files are loaded in the head of the page. Each of these plugins will add its entries to the main menu and expose the methods used to drive the application.
The permissions are stored in a mysql database.
ExtJs's default design
In ExtJs the source files contain each a class. During the build process, all .js files are concatenated to yield one big .js file, that contains everything.
What would be the best design approach?
I considered to use custom compilation with sencha cmd, and create that way a .js file for each plugin. Then I could load these plugins the same way I do it now. But this results in a complicated build and deployment process.
I also thought about creating one and only .js file with a standard Ext build process. I would then load the permissions from the server via ajax in order to construct the menu. All the objects and methods would exist, but only those are accessible where the user has permissions.
In my opinion, the second approach is much easier maintainable, but it seens to have a security problem, because everyone could look at the source and find out about the data interfaces exposed on the server and consumed by ajax.
Any comments, ideas or advices are welcome. Thanks !
Number two would be the way to go. If you keep your server side permissions in check (while updating data etc) you only need ExtJS to show/hide menu items based on permissions. That way, malicious users can turn certain plugins/items on or off, but they can never execute something that requires more permissions then they would normally have.
I'm creating a CakePHP 2.3 advanced installation (several apps -websites- that share one same lib folder where all of cake's core files are located). This works without any problems, I just edit the core.php file in the Config folder for each app so it knows where to find cake's files. The file system looks something like:
[root]
[cake-core-files]
[websites]
[website-1]
[app]
[plugins]
[vendors]
[website-2]
...
[website-N]
These different apps are in fact different in some things (they are different websites) but at the same time there's many things that are common to all of them (for example some models, controllers, functions...). What I would like to do, if possible, is to have those apps also share a bunch of controllers, models, etc so I can put them in one place, instead of replicating them now for each app.
I've seen the concept of vendors and plugins in CakePHP (I actually use plugins in those websites, but from the /app/plugins folder), but I'm not sure if that would work in my case, or how I would set that up. I guess the idea would be to have another folder (for example [shared_objects]) at the same level of [cake-core-files] and [websites], but I don't know how I would have to configure cake to do that or how to call those objects from each app.
Any ideas?
EDIT
Based on the comments/responses below I'm trying to do this using the App:build() function in the bootstrap.php, but I can't get it to work. This is what I've done:
Added a new folder where I want to put the stuff to share between all apps:
[root]
[cake-core-files]
[shared-stuff] --> NEW FOLDER
[Model]
[Config]
[websites]
[website-1]
etc...
Placed the model User.php inside the new folder [shared-stuff/Model]
Added this line in the bootstrap:
App::build(array('Model' => array('/path/to/shared-stuff/Model')));
Deleted the model User.php from its original location [website-1/app/Model]
After this steps, it seems to work, the model User.php is loaded correctly from the [shared-stuff] folder (I've tested that printing App::objects('Model');, the User model is listed). However, it actually doesn't work, when I call that model from the UsersController in the login() function, the login doesn't work (although I don't receive any kind of error, even with debug set to 2).
This model uses a database configuration different from the default one (the users table is located in a different database than the default one). I don't know if this matters.
One thing is for sure, if I leave the same exact User.php model in its original location ( [website-1/app/Model]) it all works fine, including the login, so it's a problem with how I try to configure all this sharing stuff, not the model itself.
Any ideas what am I doing wrong?
I think it could be useful to share some controller/model between multiple websites, and do it without a plugin: Using shared controller/model lets you to overwrite it if needed. It should happen simply copying the controller/model in the website's correct folder and the system should use it instead of the shared one!
EDIT: Wonderful, it works, but i think there is a little error in cake's official documentation: All paths should be terminated with a Directory separator! In the cakephp book there aren't trailing slash. Add it to your App::build path and everything will work perfectly!
You can have plugins in the core Plugins/ dir
[root]
[lib]
[Cake]
[Plugins]
[Available]
[To]
[All]
[website-1] // the 'app' dir -> https://github.com/cakephp/cakephp/tree/master/app
[plugins]
[vendors]
[website-2] // you can have many of them named anything, 'app' is just one.
...
[website-N]
This folder specifically will make the plugins available to any app using the cake lib
EG:
Look at this. Copy app to website-1, repeat till website-n.