--- a/static/css/custom.css Fri Nov 08 14:43:16 2013 +0900
+++ b/static/css/custom.css Fri Nov 08 18:25:36 2013 +0900
--- a/static/js/framework/collections.js Fri Nov 08 14:43:16 2013 +0900
+++ b/static/js/framework/collections.js Fri Nov 08 18:25:36 2013 +0900
+var Workspaces = Backbone.Collection.extend({
+ localStorage: new Backbone.LocalStorage('workspaces'),
var Projects = Backbone.Collection.extend({
--- a/static/js/framework/models.js Fri Nov 08 14:43:16 2013 +0900
+++ b/static/js/framework/models.js Fri Nov 08 18:25:36 2013 +0900
+var Workspace = Backbone.Model.extend({
var Project = Model.extend({
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/js/framework/views/workspaces.js Fri Nov 08 18:25:36 2013 +0900
+var WorkspaceTabsView = CollectionView.extend({
+ initialize: function(options) {
+ this.compileTemplates(options.templates);
+ renderItem: function(workspace) {
+ return $(this.templates.tab(workspace.toJSON()));
+ appendItem: function(workspace) {
+ var $item = this.renderItem(workspace);
+ this.$el.append($item);
+ activate: function(workspace) {
+ this.$el.find('[data-workspace]').removeClass('active');
+ this.$el.find('[data-workspace="' + workspace + '"]').addClass('active');
--- a/static/js/ui.js Fri Nov 08 14:43:16 2013 +0900
+++ b/static/js/ui.js Fri Nov 08 18:25:36 2013 +0900
window.fruitbar = new Backbone.View();
+ fruitbar.workspaces = new Workspaces();
fruitbar.tasks = new Tasks();
fruitbar.projects = new Projects();
fruitbar.router = new Router();
el: $('.workspace-title')
+ fruitbar.workspaceTabs = new WorkspaceTabsView({
+ el: $('.workspace-tabs'),
+ collection: fruitbar.workspaces,
+ tab: $.trim($('#workspace-tab-template').html())
fruitbar.projectCounter = new CollectionCounterView({
el: $('.project-counter'),
collection: fruitbar.projects,
this.workspace = workspace;
+ this.workspaces.create({name: workspace});
this.tasks.url = '/' + encodeURIComponent(workspace) + '/tasks/';
this.projects.url = '/' + encodeURIComponent(workspace) + '/projects/';
fruitbar.workspaceTitleDisplayer.render(workspace);
+ fruitbar.workspaceTabs.activate(workspace);
$('body').stop().animate({opacity: 1});
fruitbar.xhrs.push(fruitbar.fetchAll('/' + encodeURIComponent(fruitbar.workspace) + '/all/'));
+ fruitbar.workspaces.fetch();
Backbone.history.start();
--- a/templates/index.html Fri Nov 08 14:43:16 2013 +0900
+++ b/templates/index.html Fri Nov 08 18:25:36 2013 +0900
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
+ <script src="//cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.0/backbone.localStorage-min.js"></script>
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
{% assets filters='jsmin', output='bundles/fruitbar.%(version)s.js',
'js/framework/collections.js',
'js/framework/views/base.js',
'js/framework/views/inline.js',
+ 'js/framework/views/workspaces.js',
'js/framework/views/projects.js',
'js/framework/views/tasks.js',
'js/framework/router.js',
<body style="opacity: 0;">
- <h3 class="align-right">
- <button class="btn btn-mini btn-success btn-new-project">New project</button>
+ <div class="span2 ui-sidebar align-right">
+ <button class="btn btn-mini btn-success btn-new-project">New project</button>
+ <div class="span2 ui-sidebar">
+ <ul class="nav nav-tabs nav-stacked workspace-tabs">
+ <script id="workspace-tab-template" type="text/template">
+ <li data-workspace="<%- data.name %>">
+ <a href="#<%- data.name %>">#<%- data.name %></a>
<section class="projects">