rad_common_interface 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +11 -0
- data/lib/common_interface/gems.rb +3 -0
- data/lib/common_interface/require.rb +22 -0
- data/lib/common_interface/spec.rb +27 -0
- data/lib/components/common_interface.rb +16 -0
- data/lib/face/ci_model_helper.rb +9 -0
- data/lib/face/ci_view_helper.rb +59 -0
- data/lib/face/demo/base.rb +97 -0
- data/lib/face/demo/commons.rb +7 -0
- data/lib/face/demo/dialogs.rb +23 -0
- data/lib/face/demo/helps.rb +4 -0
- data/lib/face/demo/sites.rb +6 -0
- data/lib/face/demo/view_helper.rb +29 -0
- data/readme.md +55 -0
- data/spec/commons_spec.rb +7 -0
- data/spec/helpers_spec.rb +22 -0
- data/spec/helps_spec.rb +14 -0
- data/spec/sites_spec.rb +15 -0
- data/spec/spec_helper.rb +1 -0
- metadata +76 -0
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rake_ext'
|
2
|
+
|
3
|
+
project(
|
4
|
+
name: "common_interface",
|
5
|
+
official_name: "rad_common_interface",
|
6
|
+
gem: true,
|
7
|
+
summary: "User Interface for Rad Framework",
|
8
|
+
|
9
|
+
author: "Alexey Petrushin",
|
10
|
+
homepage: "http://github.com/alexeypetrushin/rad_common_interface"
|
11
|
+
)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Defining custom form tags
|
2
|
+
Rad::Face::ThemedFormHelper.generate_form_helper_methods %w(attachments_tag)
|
3
|
+
|
4
|
+
# Libraries
|
5
|
+
%w(
|
6
|
+
ci_view_helper
|
7
|
+
ci_model_helper
|
8
|
+
).each{|f| require "face/#{f}"}
|
9
|
+
|
10
|
+
# Helpers
|
11
|
+
Rad::Controller::Context.inherit Rad::Face::CiViewHelper
|
12
|
+
Rad::Html::ModelHelper.inherit Rad::Face::CiModelHelper
|
13
|
+
|
14
|
+
# Demo
|
15
|
+
module Rad::Face::Demo
|
16
|
+
autoload :Base, 'face/demo/base'
|
17
|
+
autoload :Helps, 'face/demo/helps'
|
18
|
+
autoload :ViewHelper, 'face/demo/view_helper'
|
19
|
+
autoload :Commons, 'face/demo/commons'
|
20
|
+
autoload :Dialogs, 'face/demo/dialogs'
|
21
|
+
autoload :Sites, 'face/demo/sites'
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rspec_ext'
|
2
|
+
|
3
|
+
require 'rad_ext'
|
4
|
+
require 'rad/spec'
|
5
|
+
require 'rad/spec/xhtml'
|
6
|
+
|
7
|
+
rad.common_interface
|
8
|
+
|
9
|
+
shared_examples_for 'commons demo' do
|
10
|
+
set_controller Rad::Face::Demo::Commons
|
11
|
+
|
12
|
+
[:aspects, :basic, :forms, :style, :items].each do |action|
|
13
|
+
it action do
|
14
|
+
wcall action, theme: @theme
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
shared_examples_for 'site demo' do
|
20
|
+
set_controller Rad::Face::Demo::Sites
|
21
|
+
|
22
|
+
[:home, :style, :blog, :post].each do |action|
|
23
|
+
it action do
|
24
|
+
wcall action.to_sym, theme: @theme, layout_template: @layouts[action]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
rad.register :common_interface, depends_on: :face do
|
2
|
+
require 'common_interface/gems'
|
3
|
+
require 'common_interface/require'
|
4
|
+
|
5
|
+
# config
|
6
|
+
rad.face.available_themes << :default
|
7
|
+
|
8
|
+
rad.configure :web, "#{__FILE__}/../../.." do |c|
|
9
|
+
c.locales
|
10
|
+
c.routes
|
11
|
+
c.template_paths 'app/views'
|
12
|
+
c.asset_paths 'app/static'
|
13
|
+
end
|
14
|
+
|
15
|
+
true
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rad::Face::CiViewHelper
|
2
|
+
#
|
3
|
+
# Form Buttons
|
4
|
+
#
|
5
|
+
def ok_button text = t(:ok)
|
6
|
+
submit_tag text, class: 'm_submit_form_or_ajax_form'
|
7
|
+
end
|
8
|
+
|
9
|
+
def cancel_button text = t(:cancel)
|
10
|
+
link_to text, :back, class: 'm_redirect_back_or_close_dialog'
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Custom
|
15
|
+
#
|
16
|
+
def tag_cloud tags, classes, &block
|
17
|
+
return if tags.empty?
|
18
|
+
|
19
|
+
max_count = tags.sort{|a, b| a.count <=> b.count}.last.count.to_f
|
20
|
+
|
21
|
+
tags.sort{|a, b| a.name <=> b.name}.each do |tag|
|
22
|
+
index = ((tag.count / max_count) * (classes.size - 1)).round
|
23
|
+
block.call tag, classes[index]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
#
|
29
|
+
# Attachments
|
30
|
+
#
|
31
|
+
def attachments_tag name, value = [], options = {}
|
32
|
+
value = value.collect{|h| h.to_openobject}
|
33
|
+
render '/face/attachments_tag', object: options.merge(name: name, value: value).to_openobject
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
#
|
38
|
+
# Folder
|
39
|
+
#
|
40
|
+
# params = {
|
41
|
+
# l: I18n.locale,
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# opt = {
|
45
|
+
# upload_url: item_files_path(folder),
|
46
|
+
# view: 'folder_thumb',
|
47
|
+
# select_files: t(:select_files),
|
48
|
+
# }
|
49
|
+
# def build_files_uploader_for params, opt
|
50
|
+
# raise 'update me with rad.config and with rad.cookies'
|
51
|
+
# session_key = ActionController::Base.session_options['key']
|
52
|
+
#
|
53
|
+
# params = {
|
54
|
+
# session_key => cookies[session_key]
|
55
|
+
# }.merge(params)
|
56
|
+
#
|
57
|
+
# "new FilesUpload(#{params.to_json}, #{opt.to_json});"
|
58
|
+
# end
|
59
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class Rad::Face::Demo::Base
|
2
|
+
inherit Rad::Controller::Http
|
3
|
+
helper Rad::Face::Demo::ViewHelper
|
4
|
+
|
5
|
+
layout '/rad/face/demo/layout'
|
6
|
+
|
7
|
+
def select_menu
|
8
|
+
workspace.request.session['top_menu'] = params[:top_menu] if params[:top_menu]
|
9
|
+
workspace.request.session['side_menu'] = params[:side_menu] if params[:side_menu]
|
10
|
+
|
11
|
+
redirect_to :back
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :samples
|
15
|
+
|
16
|
+
# def title
|
17
|
+
# workspace.method_name.to_s.humanize
|
18
|
+
# end
|
19
|
+
# helper_method :title
|
20
|
+
|
21
|
+
protected
|
22
|
+
def prepare_theme
|
23
|
+
theme.name = params.theme
|
24
|
+
theme.layout_template = params.layout_template
|
25
|
+
end
|
26
|
+
before :prepare_theme
|
27
|
+
|
28
|
+
def prepare_samples
|
29
|
+
@samples = {
|
30
|
+
title: workspace.method_name.to_s.humanize,
|
31
|
+
|
32
|
+
top_menu_items: %w(Email Contacts Calendar Files),
|
33
|
+
active_top_menu: (workspace.request.session['top_menu'] || 'Email'),
|
34
|
+
|
35
|
+
side_menu_items: %w(control_caption_0 control_caption_1 control_caption_2),
|
36
|
+
active_side_menu: (workspace.request.session['side_menu'] || 'control_caption_0'),
|
37
|
+
|
38
|
+
tabs: %w(Compose Contacts Import Categories),
|
39
|
+
active_tab: 'Compose',
|
40
|
+
|
41
|
+
name: "Terminator Movie Series",
|
42
|
+
tags: ['egypt', 'photo', 'travel'].collect{|w| "<a href='#'>#{w}</a>"},
|
43
|
+
details: ["Today at 15:58", "by <a href='#'>admin</a>", "{7}"],
|
44
|
+
comment_details: ["Today at 15:58", "by <a href='#'>admin</a>"],
|
45
|
+
controls: %w{add edit delete}.collect{|w| "<a href='#'>#{w}</a>"},
|
46
|
+
|
47
|
+
attachments: [
|
48
|
+
{
|
49
|
+
name: 'img1',
|
50
|
+
url: url_for("/static/demo/images/img1.jpg"),
|
51
|
+
icon_url: url_for("/static/demo/images/img1_icon.jpg"),
|
52
|
+
thumb_url: url_for("/static/demo/images/img1_thumb.jpg")
|
53
|
+
}.to_openobject,
|
54
|
+
{
|
55
|
+
name: 'img2',
|
56
|
+
url: url_for("/static/demo/images/img2.jpg"),
|
57
|
+
icon_url: url_for("/static/demo/images/img2_icon.jpg"),
|
58
|
+
thumb_url: url_for("/static/demo/images/img2_thumb.jpg")
|
59
|
+
}.to_openobject,
|
60
|
+
{
|
61
|
+
name: 'img3',
|
62
|
+
url: url_for("/static/demo/images/img3.jpg"),
|
63
|
+
icon_url: url_for("/static/demo/images/img3_icon.jpg"),
|
64
|
+
thumb_url: url_for("/static/demo/images/img3_thumb.jpg")
|
65
|
+
}.to_openobject
|
66
|
+
],
|
67
|
+
|
68
|
+
model: {
|
69
|
+
name: "Some Name",
|
70
|
+
active: true,
|
71
|
+
body: "Some text",
|
72
|
+
errors: {
|
73
|
+
base: ["Base Error Description", "Base Error Description 2"],
|
74
|
+
name: ["Name Error Description 1", "Name Error Description 2"]
|
75
|
+
}
|
76
|
+
},
|
77
|
+
|
78
|
+
detail_text: %(
|
79
|
+
<p>The Terminator (1984) <a href='#'>More at IMDbPro</a></p>
|
80
|
+
<p>Your future is in his hands.</p>
|
81
|
+
),
|
82
|
+
|
83
|
+
text: %(
|
84
|
+
<p>The Terminator (1984) <a href='#'>More at IMDbPro</a></p>
|
85
|
+
<p>In the Year of Darkness, 2029, the rulers of this planet devised the ultimate plan. They would reshape the Future by changing the Past. The plan required something that felt no pity. No pain. No fear. Something unstoppable. They created 'THE TERMINATOR'</p>
|
86
|
+
<p>The thing that won't die, in the nightmare that won't end. A human-looking, apparently unstoppable cyborg is sent from the future to kill Sarah Connor; Kyle Reese is sent to stop it.</p>
|
87
|
+
<p>Your future is in his hands.</p>
|
88
|
+
),
|
89
|
+
|
90
|
+
comment_text: %(
|
91
|
+
<p>Although the Stack Overflow engine was always designed with a technical audience in mind, I'm intrigued to see how far we can push the boundaries of that audience.</p>
|
92
|
+
<p>We've pushed a little bit when going from programmers, to sysadmins, to power computer users - and we may try pushing a tad further this year with yet another site.</p>
|
93
|
+
)
|
94
|
+
}.to_openobject
|
95
|
+
end
|
96
|
+
before :prepare_samples
|
97
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Rad::Face::Demo::Dialogs < Rad::Face::Demo::Base
|
2
|
+
def show; end
|
3
|
+
|
4
|
+
def dialog_form; end
|
5
|
+
def dialog
|
6
|
+
logger.info "Sleeping for 1 second"
|
7
|
+
sleep 1
|
8
|
+
|
9
|
+
if params.valid
|
10
|
+
render action: :dialog
|
11
|
+
else
|
12
|
+
render action: :dialog_form
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def inplace_form; end
|
17
|
+
def inplace
|
18
|
+
logger.info "Sleeping for 1 second"
|
19
|
+
sleep 1
|
20
|
+
|
21
|
+
@text = params.text
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rad::Face::Demo::ViewHelper
|
2
|
+
def samples
|
3
|
+
@samples
|
4
|
+
end
|
5
|
+
|
6
|
+
def t key, options = {}
|
7
|
+
key.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def demo_metadata
|
11
|
+
unless @demo_metadata
|
12
|
+
logger.info "RAD complex calculation :demo_metadata called!"
|
13
|
+
@demo_metadata = {}
|
14
|
+
name = "#{template.directory_name}#{rad.face.themes_path}/#{theme.name}/demo_metadata.rb"
|
15
|
+
if rad.environment.file_exist? name, rad.template.paths
|
16
|
+
fname = rad.environment.find_file! name, rad.template.paths
|
17
|
+
code = File.read fname
|
18
|
+
@demo_metadata = eval code
|
19
|
+
@demo_metadata.must_be.a Hash
|
20
|
+
end
|
21
|
+
@demo_metadata = @demo_metadata.to_openobject
|
22
|
+
end
|
23
|
+
@demo_metadata
|
24
|
+
end
|
25
|
+
|
26
|
+
def random_attachment
|
27
|
+
samples.attachments[rand(samples.attachments.size)]
|
28
|
+
end
|
29
|
+
end
|
data/readme.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Common User Interface for the Rad framework
|
2
|
+
|
3
|
+
## Rad Face
|
4
|
+
[Rad Face][face] is a tool for **Rapid Web Interface Creation** for the Rad framework.
|
5
|
+
|
6
|
+
Instead of trying to provide one universal user interface API (like GWT) to fit all needs, the [Face][face] **provides you with tools that ease creation of your own custom interface**.
|
7
|
+
|
8
|
+
Define Your design only one time, in one place, and then reuse it, forget about HTML and CSS in your Views.
|
9
|
+
|
10
|
+
It acts like an abstraction layer, allowing you to define your custom API (or DSL if you like) to build your user interface. Key point here - it allows you build such API **very quick and easy**.
|
11
|
+
|
12
|
+
## Demo
|
13
|
+
|
14
|
+
* [Sample of HomePage][sample1], [sample of page (with another design)][sample2]
|
15
|
+
* [List of all Samples][list_of_samples]
|
16
|
+
|
17
|
+
Real-life sample - [http://company.4ire.net](http://company.4ire.net), [http://4ire.net](http://4ire.net), there's no any custom template, all pages are made with the [Face][face] plugin.
|
18
|
+
|
19
|
+
## Advantages
|
20
|
+
|
21
|
+
* **Themes support** not only CSS, you can use completelly different HTML and layouts
|
22
|
+
* **DRY**
|
23
|
+
* **Clean views**
|
24
|
+
* **Iterative development**
|
25
|
+
* **Loose coupling of Logic and Design**
|
26
|
+
* **Share the same design with many Apps**
|
27
|
+
* **Mix two complete different themes** simultaneously, in the same page
|
28
|
+
* Start with simple prototype and when App matures create professional design (with minimum changes in App)
|
29
|
+
* Theme/Skin support (not only CSS but also Templates, Images, ...)
|
30
|
+
* Outsource design without opening App code
|
31
|
+
* Designers can go ahead and create working html/css/js
|
32
|
+
* Programmers can go ahead and create working App with simple design
|
33
|
+
* Both of them can do iterative prototyping that will be updated later
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
$ sudo gem install common_interface
|
38
|
+
|
39
|
+
**Notice!** Default UI is the UI I build for my own need, it's not an universal solution (and maybe you can also use it).
|
40
|
+
But to create Your own design you need to create your own 'Default UI', using this code as a sample.
|
41
|
+
|
42
|
+
## Development
|
43
|
+
|
44
|
+
### Less CSS
|
45
|
+
|
46
|
+
$ lessc style.less > style.css
|
47
|
+
$ lessc reset.less > reset.css
|
48
|
+
|
49
|
+
Copyright (c) Alexey Petrushin [http://4ire.net](http://4ire.net), released under the MIT license.
|
50
|
+
|
51
|
+
[face]: http://github.com/alexeypetrushin/face
|
52
|
+
|
53
|
+
[sample1]: http://4ire.net/ci_sites/home?layout_template=home&theme=simple_organization
|
54
|
+
[sample2]: http://4ire.net/ci_elements/page?theme=default
|
55
|
+
[list_of_samples]: http://4ire.net/ci_demo
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Helpers" do
|
4
|
+
set_controller Rad::Face::Demo::Commons
|
5
|
+
|
6
|
+
def body
|
7
|
+
wcall(:forms)
|
8
|
+
response.body
|
9
|
+
end
|
10
|
+
|
11
|
+
it "form_tag should correctly render form (from error)" do
|
12
|
+
body.to_xhtml('#basic_form_tag').should_be_fuzzy_equal_to(
|
13
|
+
id: 'basic_form_tag', action: '/some_action', method: 'post'
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "form_for should correctly render form (from error)" do
|
18
|
+
body.to_xhtml('#basic_form_for').should_be_fuzzy_equal_to(
|
19
|
+
id: 'basic_form_for', action: '/some_action', method: 'post'
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
data/spec/helps_spec.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Help" do
|
4
|
+
set_controller Rad::Face::Demo::Helps
|
5
|
+
|
6
|
+
it "should display general help page" do
|
7
|
+
wcall :index
|
8
|
+
response.should be_ok
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should display theme help" do
|
12
|
+
wcall :help, theme: 'default'
|
13
|
+
end
|
14
|
+
end
|
data/spec/sites_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'common_interface/spec'
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rad_common_interface
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexey Petrushin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-04 00:00:00.000000000 +04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rad_face
|
17
|
+
requirement: &2956880 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2956880
|
26
|
+
description:
|
27
|
+
email:
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- Rakefile
|
33
|
+
- readme.md
|
34
|
+
- lib/common_interface/gems.rb
|
35
|
+
- lib/common_interface/require.rb
|
36
|
+
- lib/common_interface/spec.rb
|
37
|
+
- lib/components/common_interface.rb
|
38
|
+
- lib/face/ci_model_helper.rb
|
39
|
+
- lib/face/ci_view_helper.rb
|
40
|
+
- lib/face/demo/base.rb
|
41
|
+
- lib/face/demo/commons.rb
|
42
|
+
- lib/face/demo/dialogs.rb
|
43
|
+
- lib/face/demo/helps.rb
|
44
|
+
- lib/face/demo/sites.rb
|
45
|
+
- lib/face/demo/view_helper.rb
|
46
|
+
- spec/commons_spec.rb
|
47
|
+
- spec/helpers_spec.rb
|
48
|
+
- spec/helps_spec.rb
|
49
|
+
- spec/sites_spec.rb
|
50
|
+
- spec/spec_helper.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://github.com/alexeypetrushin/rad_common_interface
|
53
|
+
licenses: []
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.5.1
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: User Interface for Rad Framework
|
76
|
+
test_files: []
|