netzke-workspace 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +58 -0
- data/Rakefile +1 -0
- data/lib/netzke-workspace.rb +7 -0
- data/lib/netzke/workspace.rb +8 -0
- data/lib/netzke/workspace/tab_panel.rb +61 -0
- data/lib/netzke/workspace/tab_panel/javascripts/tab_panel.js +108 -0
- data/lib/netzke/workspace/version.rb +5 -0
- data/netzke-workspace.gemspec +31 -0
- data/spec/features/javascripts/secure_tab_panel_spec.js.coffee +6 -0
- data/spec/features/javascripts/some_tab_panel_spec.js.coffee +15 -0
- data/spec/features/javascripts/tab_panel_with_dashboard_spec.js.coffee +9 -0
- data/spec/features/netzke_mocha_spec.rb +20 -0
- data/spec/features/workspace_spec.rb +5 -0
- data/spec/integration +0 -0
- data/spec/rails_app/README.rdoc +28 -0
- data/spec/rails_app/Rakefile +6 -0
- data/spec/rails_app/app/assets/images/.keep +0 -0
- data/spec/rails_app/app/assets/javascripts/application.js +13 -0
- data/spec/rails_app/app/assets/stylesheets/application.css +13 -0
- data/spec/rails_app/app/components/hello_user.rb +29 -0
- data/spec/rails_app/app/components/secure_tab_panel.rb +12 -0
- data/spec/rails_app/app/components/some_tab_panel.rb +37 -0
- data/spec/rails_app/app/components/tab_panel_with_dashboard.rb +12 -0
- data/spec/rails_app/app/controllers/application_controller.rb +5 -0
- data/spec/rails_app/app/controllers/concerns/.keep +0 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/mailers/.keep +0 -0
- data/spec/rails_app/app/models/.keep +0 -0
- data/spec/rails_app/app/models/concerns/.keep +0 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
- data/spec/rails_app/bin/bundle +3 -0
- data/spec/rails_app/bin/rails +4 -0
- data/spec/rails_app/bin/rake +4 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +31 -0
- data/spec/rails_app/config/boot.rb +4 -0
- data/spec/rails_app/config/database.yml +25 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/development.rb +29 -0
- data/spec/rails_app/config/environments/production.rb +80 -0
- data/spec/rails_app/config/environments/test.rb +36 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails_app/config/initializers/inflections.rb +16 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/initializers/netzke_testing.rb +3 -0
- data/spec/rails_app/config/initializers/secret_token.rb +12 -0
- data/spec/rails_app/config/initializers/session_store.rb +3 -0
- data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_app/config/locales/en.yml +2 -0
- data/spec/rails_app/config/locales/es.yml +19 -0
- data/spec/rails_app/config/routes.rb +3 -0
- data/spec/rails_app/db/development.sqlite3 +0 -0
- data/spec/rails_app/db/development_structure.sql +88 -0
- data/spec/rails_app/db/migrate/20100914104207_create_users.rb +15 -0
- data/spec/rails_app/db/migrate/20100914104236_create_roles.rb +13 -0
- data/spec/rails_app/db/migrate/20101026185816_create_authors.rb +14 -0
- data/spec/rails_app/db/migrate/20101026190021_create_books.rb +22 -0
- data/spec/rails_app/db/migrate/20110101143818_create_addresses.rb +17 -0
- data/spec/rails_app/db/migrate/20110701070052_create_book_with_custom_primary_keys.rb +15 -0
- data/spec/rails_app/db/migrate/20110901114016_add_last_read_at_to_books.rb +9 -0
- data/spec/rails_app/db/migrate/20110909071740_add_published_on_to_books.rb +5 -0
- data/spec/rails_app/db/migrate/20130105145110_create_issues.rb +12 -0
- data/spec/rails_app/db/migrate/20130105145156_create_projects.rb +9 -0
- data/spec/rails_app/db/migrate/20130105145231_create_developers.rb +8 -0
- data/spec/rails_app/db/migrate/20130105145239_create_statuses.rb +8 -0
- data/spec/rails_app/db/schema.rb +97 -0
- data/spec/rails_app/db/seeds.rb +7 -0
- data/spec/rails_app/db/test.sqlite3 +0 -0
- data/spec/rails_app/lib/assets/.keep +0 -0
- data/spec/rails_app/lib/tasks/.keep +0 -0
- data/spec/rails_app/log/.keep +0 -0
- data/spec/rails_app/public/404.html +58 -0
- data/spec/rails_app/public/422.html +58 -0
- data/spec/rails_app/public/500.html +57 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/robots.txt +5 -0
- data/spec/rails_app/public/uploads/foo.png +0 -0
- data/spec/rails_app/vendor/assets/javascripts/.keep +0 -0
- data/spec/rails_app/vendor/assets/stylesheets/.keep +0 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/database_cleaner.rb +21 -0
- data/spec/support/helpers.rb +44 -0
- metadata +318 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: aa1fe8d5e2a2563b8a95c4107b7efef98069ec54
|
4
|
+
data.tar.gz: be7cf1c3dccc760b0950b94a2033b6c7a3454b86
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4812acfcd3d8e4858d7d09780d4884495bc711e02ec03939540186f0052313d0f24ff9e6f0f0e2e213371f6769a2ce0f52e9823ce45ee12da728c10ea5d58d23
|
7
|
+
data.tar.gz: 7603a2043a5417b0bca1088b143e1db3d381295f2da4ed687df122a7721ce045a278f60f886e0277e22649bad0eeae4ed42a93df6aa702fb07fb7e6ac96dca48
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Max Gorin
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Netzke::Workspace
|
2
|
+
|
3
|
+
Provides a tab-panel-based Netzke component that:
|
4
|
+
|
5
|
+
* allows dynamic loading of arbitrary Netzke components in (new or currently active tab)
|
6
|
+
|
7
|
+
* handles persistence of open tabs
|
8
|
+
|
9
|
+
* provides a method that unloads all tabs at once
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'netzke-workspace'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install netzke-workspace
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Inherit your workspace component from Netzke::Workspace::TabPanel. Then on the client side call the `loadTab` method to dynamically load components, e.g. (the `HelloWorld` component is supposed to be defined elsewhere):
|
28
|
+
|
29
|
+
class MyTabPanel < Netzke::Workspace::TabPanel
|
30
|
+
action :load_component
|
31
|
+
|
32
|
+
js_configure do |c|
|
33
|
+
c.on_load_component = <<-JS
|
34
|
+
function() {
|
35
|
+
this.loadTab("HelloWorld", newTab: true});
|
36
|
+
}
|
37
|
+
JS
|
38
|
+
end
|
39
|
+
|
40
|
+
def configure(c)
|
41
|
+
super
|
42
|
+
c.bbar = [:load_component]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
See `spec/rails_app/app/components` for more examples.
|
47
|
+
|
48
|
+
## Running tests
|
49
|
+
|
50
|
+
$ rspec spec
|
51
|
+
|
52
|
+
## Contributing
|
53
|
+
|
54
|
+
1. Fork it ( http://github.com/<my-github-username>/netzke-workspace/fork )
|
55
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
56
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
57
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
58
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Workspace
|
3
|
+
# A component that allows for dynamical loading/unloading of other Netzke components in tabs.
|
4
|
+
#
|
5
|
+
# Call the +loadTab+ method on the client to dynamically load a component:
|
6
|
+
#
|
7
|
+
# workspaceTabPanel.loadTab("UserGrid", {newTab: true})
|
8
|
+
#
|
9
|
+
# - will load a UserGrid component from the server in a new tab.
|
10
|
+
#
|
11
|
+
# == Client-side methods:
|
12
|
+
#
|
13
|
+
# +loadTab(componentClassName, options)+ - loads a component in a (new or currently active) tab
|
14
|
+
#
|
15
|
+
# * +options+ is an object that may contain the following keys:
|
16
|
+
# * +newTab+ (boolean) - whether to load a component in a newly created tab
|
17
|
+
# * +clientConfig+ (object) - config for the loaded Netzke component
|
18
|
+
#
|
19
|
+
# +closeAllTabs+ - closes all open tabs
|
20
|
+
#
|
21
|
+
# == Security
|
22
|
+
#
|
23
|
+
# By default, this component allows loading any Netzke component as requested from the client (component
|
24
|
+
# class has been sent as a paremeter for the deliver_component endpoint), which may not be secury enough for you.
|
25
|
+
# Override the :tab component to do any proper checks (see an example in the specs app).
|
26
|
+
#
|
27
|
+
class TabPanel < Netzke::Base
|
28
|
+
js_configure do |c|
|
29
|
+
c.extend = "Ext.tab.Panel"
|
30
|
+
c.header = false
|
31
|
+
c.mixin
|
32
|
+
end
|
33
|
+
|
34
|
+
def configure(c)
|
35
|
+
c.tabs = state[:tabs].presence
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
component :tab do |c|
|
40
|
+
# this hack is needed because of Netzke::Core's imperfection: it eagerly evaluates all components (even if those
|
41
|
+
# would never be loaded) - and thus, a valid +klass+ is required.
|
42
|
+
if c.client_config.empty?
|
43
|
+
c.klass = Netzke::Core::Panel
|
44
|
+
else
|
45
|
+
c.klass = c.client_config[:klass].constantize
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_tab_session_config(c)
|
50
|
+
tabs = state[:tabs] ||= {}
|
51
|
+
if tab_index = c.delete(:tabIndex)
|
52
|
+
tabs[tab_index] = c
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
endpoint :server_save_tabs do |params, this|
|
57
|
+
state[:tabs] = params
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
{
|
2
|
+
/**
|
3
|
+
* Loads a component.
|
4
|
+
*/
|
5
|
+
loadTab: function(cmp, options) {
|
6
|
+
var receivingTab;
|
7
|
+
|
8
|
+
options = options || {};
|
9
|
+
|
10
|
+
if (options.newTab) {
|
11
|
+
receivingTab = this.add({layout: 'fit', closable: true});
|
12
|
+
} else {
|
13
|
+
receivingTab = this.getActiveTab();
|
14
|
+
if (!this.isDynamic(receivingTab)) return;
|
15
|
+
}
|
16
|
+
|
17
|
+
this.suspendEvents();
|
18
|
+
this.setActiveTab(receivingTab);
|
19
|
+
this.resumeEvents();
|
20
|
+
|
21
|
+
receivingTab.setTitle('Loading...');
|
22
|
+
|
23
|
+
receivingTab.removeAll();
|
24
|
+
|
25
|
+
var clientConfig = Ext.apply(options.clientConfig, {
|
26
|
+
klass: cmp
|
27
|
+
});
|
28
|
+
|
29
|
+
this.netzkeLoadComponent("tab", {
|
30
|
+
clientConfig: clientConfig,
|
31
|
+
container: receivingTab,
|
32
|
+
clone: true,
|
33
|
+
scope: this,
|
34
|
+
callback: function(c) {
|
35
|
+
receivingTab.setTitle(c.title);
|
36
|
+
receivingTab.componentConfig = clientConfig;
|
37
|
+
this.saveTabs();
|
38
|
+
}
|
39
|
+
});
|
40
|
+
},
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Closes all tabs
|
44
|
+
*/
|
45
|
+
closeAllTabs: function() {
|
46
|
+
this.items.each(function(tab, i) {
|
47
|
+
if (this.isDynamic(tab)) {
|
48
|
+
this.remove(tab);
|
49
|
+
}
|
50
|
+
}, this)
|
51
|
+
this.saveTabs();
|
52
|
+
},
|
53
|
+
|
54
|
+
/**
|
55
|
+
* private methods
|
56
|
+
*/
|
57
|
+
|
58
|
+
initComponent: function() {
|
59
|
+
this.callParent();
|
60
|
+
|
61
|
+
this.on('tabchange', this.onTabChange, this);
|
62
|
+
|
63
|
+
this.on('remove', function(me, tab) {
|
64
|
+
this.saveTabs();
|
65
|
+
}, this);
|
66
|
+
|
67
|
+
this.addInitialTabs();
|
68
|
+
},
|
69
|
+
|
70
|
+
addInitialTabs: function(){
|
71
|
+
if (this.tabs) {
|
72
|
+
this.tabs.forEach(function(c) {
|
73
|
+
var tab = this.add({layout: 'fit', closable: true, title: c.title, active: c.active, componentConfig: c});
|
74
|
+
if (c.active) this.setActiveTab(tab);
|
75
|
+
}, this);
|
76
|
+
}
|
77
|
+
},
|
78
|
+
|
79
|
+
onTabChange: function(panel, tab){
|
80
|
+
if (tab.items.getCount() == 0 && this.isDynamic(tab)) {
|
81
|
+
// this tab is nesting no component yet
|
82
|
+
this.netzkeLoadComponent("tab", {container: tab, clientConfig: tab.componentConfig, clone: true});
|
83
|
+
}
|
84
|
+
|
85
|
+
this.saveTabs();
|
86
|
+
},
|
87
|
+
|
88
|
+
// Returns true if given tab was dynamically loaded (as opposed to tabs that could be there initially)
|
89
|
+
isDynamic: function(tab){
|
90
|
+
return !!tab.componentConfig;
|
91
|
+
},
|
92
|
+
|
93
|
+
// Saves current tab configs to server
|
94
|
+
saveTabs: function() {
|
95
|
+
var activeTab = this.getActiveTab();
|
96
|
+
var configs = [];
|
97
|
+
this.items.each(function(tab, i){
|
98
|
+
if (this.isDynamic(tab)) {
|
99
|
+
var tabConfig = tab.componentConfig || {};
|
100
|
+
tabConfig.title = tab.title;
|
101
|
+
tabConfig.active = activeTab == tab;
|
102
|
+
configs.push(tabConfig);
|
103
|
+
}
|
104
|
+
}, this);
|
105
|
+
|
106
|
+
this.serverSaveTabs(configs);
|
107
|
+
}
|
108
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'netzke/workspace/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "netzke-workspace"
|
8
|
+
spec.version = Netzke::Workspace::VERSION
|
9
|
+
spec.authors = ["Max Gorin"]
|
10
|
+
spec.email = ["gorinme@gmail.com"]
|
11
|
+
spec.summary = %q{Netzke Workspace component}
|
12
|
+
spec.description = %q{Dynamically loads components in persisted tabs}
|
13
|
+
spec.homepage = "http://netzke.org"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency 'netzke-core', '0.10.0'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'rails', '~> 4.0.0'
|
23
|
+
spec.add_development_dependency 'sqlite3'
|
24
|
+
spec.add_development_dependency 'yard'
|
25
|
+
spec.add_development_dependency 'coffee-script'
|
26
|
+
# spec.add_development_dependency 'netzke-testing', '0.10.0.rc1'
|
27
|
+
spec.add_development_dependency 'rspec-rails'
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
30
|
+
spec.add_development_dependency "rake"
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe 'SomeTabPanel component', ->
|
2
|
+
it 'loads component in new tab', (done) ->
|
3
|
+
click button "New tab"
|
4
|
+
wait ->
|
5
|
+
expectToSee tab "User 1"
|
6
|
+
click button "Ping server"
|
7
|
+
wait ->
|
8
|
+
expectToSee header "Server says Hello User 1"
|
9
|
+
click button "New tab"
|
10
|
+
wait ->
|
11
|
+
expectToSee tab "User 2"
|
12
|
+
click button "Ping server"
|
13
|
+
wait ->
|
14
|
+
expectToSee header "Server says Hello User 2"
|
15
|
+
done()
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature "Mocha specs", js: true do
|
4
|
+
# if a spec path is provided, create a single spec for it
|
5
|
+
if path = ENV["S"]
|
6
|
+
it "pass for '#{path}'" do
|
7
|
+
run_mocha_spec(path)
|
8
|
+
end
|
9
|
+
else
|
10
|
+
# create a spec for each file spec dir that ends on "_spec.js.coffee"
|
11
|
+
dir = File.join File.dirname(__FILE__), "javascripts"
|
12
|
+
Dir[File.join(dir, "**/*_spec.js.coffee")].each do |f|
|
13
|
+
spec_path = f.sub(dir, '')[1..-1].sub(/_spec\..*$/, '')
|
14
|
+
|
15
|
+
it "pass for '#{spec_path.underscore}'" do
|
16
|
+
run_mocha_spec spec_path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/spec/integration
ADDED
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|