rad_kit 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +3 -2
- data/app/controllers/app.rb +5 -0
- data/app/controllers/base.rb +47 -0
- data/app/controllers/base_app.rb +18 -0
- data/app/controllers/comments.rb +49 -0
- data/app/controllers/items.rb +208 -0
- data/app/helpers/kit/authorization.rb +121 -0
- data/app/helpers/kit/captcha.rb +10 -0
- data/app/helpers/kit/controller_helper.rb +76 -0
- data/app/helpers/kit/item_helper.rb +110 -0
- data/app/helpers/kit/navigation_helper.rb +15 -0
- data/app/helpers/kit/pagination.rb +62 -0
- data/app/models/_item/attachments.rb +15 -0
- data/app/models/_item/container.rb +30 -0
- data/app/models/_item/slug.rb +28 -0
- data/app/models/attachment.rb +9 -0
- data/app/models/comment.rb +30 -0
- data/app/models/item.rb +136 -0
- data/app/models/secure_token.rb +45 -0
- data/app/models/tag.rb +71 -0
- data/app/static/kit/highlight.css +48 -0
- data/app/static/kit.css +3 -0
- data/app/static/kit.js +0 -0
- data/app/static/themes/default/objects.less +28 -0
- data/app/views/controllers/comments/_embedded.html.haml +13 -0
- data/app/views/controllers/comments/_form.html.haml +8 -0
- data/app/views/controllers/comments/actions.js.haml +22 -0
- data/app/views/controllers/comments/show.html.haml +11 -0
- data/app/views/controllers/items/_items.html.haml +2 -0
- data/app/views/controllers/items/actions.js.haml +23 -0
- data/app/views/controllers/items/all.html.haml +4 -0
- data/app/views/controllers/items/inherited_action.html.haml +1 -0
- data/app/views/kit/_bottom_panel.html.haml +9 -0
- data/app/views/kit/_debug.html.haml +13 -0
- data/app/views/kit/_messages.html.haml +4 -0
- data/app/views/kit/_navigation.html.haml +19 -0
- data/app/views/kit/_not_found.html.haml +1 -0
- data/app/views/kit/_top_panel.html.haml +19 -0
- data/app/views/kit/_web_analytics.html.erb +14 -0
- data/app/views/kit/aspects/_comments.html.haml +8 -0
- data/app/views/kit/captcha/_action.js.haml +2 -0
- data/app/views/kit/captcha/_form.html.haml +10 -0
- data/app/views/kit/layout.html.haml +22 -0
- data/app/views/kit/layout.js.haml +15 -0
- data/app/views/previews/_line.html.haml +8 -0
- data/app/views/previews/_thumb.html.haml +5 -0
- data/app/views/themes/default/file.html.haml +19 -0
- data/app/views/themes/default/folder.html.haml +15 -0
- data/app/views/themes/default/layout_definitions/default.yml +27 -0
- data/app/views/themes/default/list.html.haml +21 -0
- data/app/views/themes/default/list_item.html.haml +14 -0
- data/app/views/themes/default/page.html.haml +23 -0
- data/app/views/tools/_access.html.haml +12 -0
- data/app/views/tools/_buttons.html.haml +11 -0
- data/app/views/tools/_context_menu.html.haml +12 -0
- data/app/views/tools/_search.html.haml +5 -0
- data/app/views/tools/_tags.html.haml +10 -0
- data/config/locales/en.yml +136 -0
- data/config/locales/ru.yml +142 -0
- data/config/routes.rb +44 -0
- metadata +82 -23
@@ -0,0 +1,62 @@
|
|
1
|
+
module Pagination
|
2
|
+
def paginator_for page, entries_count, per_page, &to_link
|
3
|
+
page.must_be >= 1
|
4
|
+
return if page == 1 and entries_count < per_page
|
5
|
+
|
6
|
+
opt = {
|
7
|
+
current_page: page,
|
8
|
+
pages: [], #(go_prev + [current] + go_next),
|
9
|
+
to_link: to_link
|
10
|
+
}
|
11
|
+
|
12
|
+
opt[:prev] = to_link.call(t(:go_prev), page - 1) if page > 1
|
13
|
+
opt[:next] = to_link.call(t(:go_next), page + 1)
|
14
|
+
|
15
|
+
b.paginator opt
|
16
|
+
end
|
17
|
+
|
18
|
+
# PAGINATOR_HALF_SIZE = 3
|
19
|
+
#
|
20
|
+
# def paginator_for current, total_entries, per_page, &to_link
|
21
|
+
# return "" if total_entries <= per_page
|
22
|
+
# total = (total_entries / (1.0 * per_page)).ceil
|
23
|
+
#
|
24
|
+
# from = current
|
25
|
+
# if current > 1
|
26
|
+
# from = current - PAGINATOR_HALF_SIZE
|
27
|
+
# if (right_size = total - current) < PAGINATOR_HALF_SIZE
|
28
|
+
# from -= (PAGINATOR_HALF_SIZE - right_size)
|
29
|
+
# end
|
30
|
+
# from = 1 if from < 0
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# to = current
|
34
|
+
# if current < total_entries
|
35
|
+
# to = current + PAGINATOR_HALF_SIZE
|
36
|
+
# if (left_size = current - 1) < PAGINATOR_HALF_SIZE
|
37
|
+
# to += (PAGINATOR_HALF_SIZE - left_size)
|
38
|
+
# end
|
39
|
+
# to = total if to > total
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# go_prev, go_next = [], []
|
43
|
+
# (from..to).each do |n|
|
44
|
+
# if n < current
|
45
|
+
# go_prev << to_link.call(n.to_s, n)
|
46
|
+
# elsif n > current
|
47
|
+
# go_next << to_link.call(n.to_s, n)
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# opt = {
|
52
|
+
# current_page: current,
|
53
|
+
# pages: (go_prev + [current] + go_next),
|
54
|
+
# to_link: to_link
|
55
|
+
# }
|
56
|
+
#
|
57
|
+
# opt[:prev] = to_link.call(t(:go_prev), current - 1) if current > 1
|
58
|
+
# opt[:next] = to_link.call(t(:go_next), current + 1) if current < total
|
59
|
+
#
|
60
|
+
# b.paginator opt
|
61
|
+
# end
|
62
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Models::Item
|
2
|
+
def attachments
|
3
|
+
@attachments ||= []
|
4
|
+
end
|
5
|
+
mount_attachments(:attachments, :file){Models::Attachment.new}
|
6
|
+
|
7
|
+
assign :attachments_as_attachments, true
|
8
|
+
|
9
|
+
def attachments_as_images
|
10
|
+
# TODO3 remove sorting, use order defined in database
|
11
|
+
_cache[:attachments_as_images] ||= attachments.
|
12
|
+
sort{|a, b| a.file.name <=> b.file.name}.
|
13
|
+
collect{|o| {name: o.file.name, url: o.file.url, thumb_url: o.file.thumb.url, icon_url: o.file.icon.url}.to_openobject}
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Models::Item
|
2
|
+
attr_accessor :dependent
|
3
|
+
def dependent?; !!dependent end
|
4
|
+
def independent?; !dependent? end
|
5
|
+
def independent!; remove_instance_variable :@dependent end
|
6
|
+
def dependent!; self.dependent = true end
|
7
|
+
|
8
|
+
|
9
|
+
# field :dependent, type: Boolean, default: false # Indicates wheter or not Item depends on Container
|
10
|
+
# has_many :containers, class_name: 'Models::Item', foreign_key: :item_ids
|
11
|
+
#
|
12
|
+
# CONTAINER_INHERITABLE_ATTRIBUTES = %w{owner_name viewers collaborators}
|
13
|
+
# def inherit_container_attributes container, attributes = CONTAINER_INHERITABLE_ATTRIBUTES
|
14
|
+
# attributes.each{|attr| send "#{attr}=", container.send(attr)}
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # serches independent container for this item (used in search)
|
18
|
+
# def independent_container
|
19
|
+
# unless independent_container = cache[:independent_container]
|
20
|
+
# if independent?
|
21
|
+
# independent_container = self
|
22
|
+
# else
|
23
|
+
# independent_container = containers.first
|
24
|
+
# raise "this dependent item dosn't have container!" unless independent_container
|
25
|
+
# end
|
26
|
+
# cache[:independent_container] = independent_container
|
27
|
+
# end
|
28
|
+
# independent_container
|
29
|
+
# end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Models::Item
|
2
|
+
attr_writer :slug
|
3
|
+
def slug
|
4
|
+
@slug ||= generate_slug
|
5
|
+
end
|
6
|
+
before_create :slug
|
7
|
+
assign :slug, String, true
|
8
|
+
|
9
|
+
rad.extension :item_slug, self do
|
10
|
+
validates_uniqueness_of :slug
|
11
|
+
end
|
12
|
+
|
13
|
+
validates_format_of :slug, with: /^[0-9a-z\-]+$/
|
14
|
+
validates_presence_of :slug
|
15
|
+
|
16
|
+
def self.by_param! param
|
17
|
+
by_param(param) || raise(Mongo::NotFound, "object with slug #{param} not found!")
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.by_param param
|
21
|
+
self.by_slug(param) || (BSON::ObjectId.legal?(param) && self.by_id(param))
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
def generate_slug
|
26
|
+
"#{name.blank? ? String.random(6) : name.to_url[0..50]}-#{String.random}" #UUIDTools::UUID.random_create.hexdigest[0,6]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Comment < Item
|
2
|
+
|
3
|
+
attr_accessor :item_id
|
4
|
+
validates_presence_of :item_id
|
5
|
+
def item= item
|
6
|
+
self.item_id = item._id
|
7
|
+
_cache[:item] = item
|
8
|
+
end
|
9
|
+
def item
|
10
|
+
_cache[:item] ||= Item.by_id item_id
|
11
|
+
end
|
12
|
+
|
13
|
+
after_create do |m|
|
14
|
+
Item.update({_id: m.item_id}, {_inc: {comments_count: 1}})
|
15
|
+
end
|
16
|
+
after_destroy do |m|
|
17
|
+
Item.update({_id: m.item_id}, {_inc: {comments_count: -1}})
|
18
|
+
end
|
19
|
+
|
20
|
+
available_as_markup :text
|
21
|
+
assign :original_text, String, true
|
22
|
+
validates_presence_of :text
|
23
|
+
|
24
|
+
before_save{|m| m.dependent!}
|
25
|
+
|
26
|
+
# TODO3 search
|
27
|
+
# searchable do
|
28
|
+
# text :text, using: :text_as_text
|
29
|
+
# end
|
30
|
+
end
|
data/app/models/item.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
class Item
|
2
|
+
inherit Mongo::Model
|
3
|
+
collection :items
|
4
|
+
|
5
|
+
rad.extension :item_model, self
|
6
|
+
|
7
|
+
# key :_id, String
|
8
|
+
# field :_type, String
|
9
|
+
|
10
|
+
#
|
11
|
+
# General Attributes
|
12
|
+
#
|
13
|
+
attr_accessor :name, :text
|
14
|
+
assign do
|
15
|
+
name String, true
|
16
|
+
text String, true
|
17
|
+
end
|
18
|
+
|
19
|
+
timestamps!
|
20
|
+
|
21
|
+
|
22
|
+
#
|
23
|
+
# Aspects
|
24
|
+
#
|
25
|
+
# TODO1 add support for security inheritance for comments
|
26
|
+
def comments
|
27
|
+
Comment.query({item_id: _id}, {sort: [[:created_at, -1]]})
|
28
|
+
end
|
29
|
+
after_destroy{|m| m.comments.each(&:destroy!)}
|
30
|
+
|
31
|
+
attr_writer :comments_count
|
32
|
+
def comments_count; @comments_count ||= 0 end
|
33
|
+
|
34
|
+
|
35
|
+
#
|
36
|
+
# Tags
|
37
|
+
#
|
38
|
+
inherit Models::TagsMixin
|
39
|
+
|
40
|
+
#
|
41
|
+
# Authorized Object
|
42
|
+
#
|
43
|
+
inherit Models::AuthorizedObject
|
44
|
+
|
45
|
+
|
46
|
+
#
|
47
|
+
# TextProcessor
|
48
|
+
#
|
49
|
+
inherit Mongo::Model::TextProcessor
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
# Identity
|
54
|
+
#
|
55
|
+
def to_param; slug end
|
56
|
+
|
57
|
+
|
58
|
+
#
|
59
|
+
# Teaser
|
60
|
+
#
|
61
|
+
TEASER_LENGTH = 350
|
62
|
+
def teaser
|
63
|
+
generate_teaser! unless @teaser
|
64
|
+
@teaser
|
65
|
+
end
|
66
|
+
attr_writer :teaser
|
67
|
+
|
68
|
+
def generate_teaser!
|
69
|
+
self.teaser = TextUtils.truncate text, TEASER_LENGTH if text # if new_record? or teaser_changed?
|
70
|
+
end
|
71
|
+
before_save :generate_teaser!
|
72
|
+
|
73
|
+
|
74
|
+
#
|
75
|
+
# Indexing
|
76
|
+
#
|
77
|
+
# TODO3 search
|
78
|
+
# include Sunspot::MongoMapper::Searchable
|
79
|
+
# searchable do
|
80
|
+
# text :name, stored: true, boost: 2.0
|
81
|
+
# text :teaser, stored: true
|
82
|
+
#
|
83
|
+
# string :tags, multiple: true
|
84
|
+
# string :dependent
|
85
|
+
# # string :model_name
|
86
|
+
# string :viewers, multiple: true
|
87
|
+
# time :created_at
|
88
|
+
# time :updated_at
|
89
|
+
#
|
90
|
+
# string(:space_id){space_id.to_s}
|
91
|
+
# string(:account_id){account_id.to_s}
|
92
|
+
# end
|
93
|
+
|
94
|
+
|
95
|
+
#
|
96
|
+
# Theme layout support
|
97
|
+
#
|
98
|
+
attr_accessor :layout
|
99
|
+
assign :layout, String, true
|
100
|
+
|
101
|
+
|
102
|
+
#
|
103
|
+
# Other
|
104
|
+
#
|
105
|
+
PER_PAGE = 14
|
106
|
+
|
107
|
+
# def inspect
|
108
|
+
# %{#<#{self.class.name} name: "#{name}", #{"slug: #{slug}, " unless slug.blank?}_id: #{_id}>}
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# def to_s
|
112
|
+
# inspect
|
113
|
+
# end
|
114
|
+
|
115
|
+
ALLOWED_KEYS = %w{
|
116
|
+
id _type slug
|
117
|
+
name text tags dependent
|
118
|
+
owner_name viewers
|
119
|
+
created_at updated_at
|
120
|
+
}
|
121
|
+
def to_json options = {}
|
122
|
+
options = options.symbolize_keys
|
123
|
+
options[:only] = ((options[:only] || []) + ALLOWED_KEYS).uniq
|
124
|
+
|
125
|
+
# TODO3 files
|
126
|
+
# options[:methods] = ((options[:methods] || []) + [:icon_url]).uniq
|
127
|
+
|
128
|
+
super options
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
#
|
134
|
+
# Helpers
|
135
|
+
#
|
136
|
+
Dir.glob("#{__FILE__.dirname}/_item/*.rb").each{|path| load path}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class SecureToken
|
2
|
+
inherit Mongo::Model
|
3
|
+
# TODO3 rename to :tokens
|
4
|
+
collection :secure_tokens
|
5
|
+
|
6
|
+
EXPIRES_IN = 30
|
7
|
+
|
8
|
+
rad.extension :secure_token, self
|
9
|
+
|
10
|
+
# attr_writer :values
|
11
|
+
# def values; @values ||= {} end
|
12
|
+
def [] k
|
13
|
+
instance_variable_get :"@#{k}"
|
14
|
+
end
|
15
|
+
def []= k, v
|
16
|
+
instance_variable_set :"@#{k}", v
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_writer :token
|
20
|
+
def token; @token ||= String.secure_token end
|
21
|
+
validates_presence_of :token
|
22
|
+
|
23
|
+
attr_writer :expires_at
|
24
|
+
def expires_at; @expires_at ||= EXPIRES_IN.minutes.from_now end
|
25
|
+
validates_presence_of :expires_at
|
26
|
+
|
27
|
+
timestamps!
|
28
|
+
|
29
|
+
def expired?
|
30
|
+
expires_at >= Time.now.utc
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def by_token token
|
35
|
+
return nil if token.blank?
|
36
|
+
first token: token, expires_at: {_gte: Time.now.utc}
|
37
|
+
end
|
38
|
+
alias_method :first_by_token, :by_token
|
39
|
+
|
40
|
+
def by_token! token
|
41
|
+
return by_token(token) || raise(Mongo::NotFound, "token #{token} not found!")
|
42
|
+
end
|
43
|
+
alias_method :first_by_token!, :by_token!
|
44
|
+
end
|
45
|
+
end
|
data/app/models/tag.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
class Tag
|
2
|
+
inherit Mongo::Model
|
3
|
+
collection :tags
|
4
|
+
|
5
|
+
rad.extension :tag_model, self
|
6
|
+
|
7
|
+
FORBIDDEN_CHARACTERS = /<>,/
|
8
|
+
TAG_LIST_DELIMITER = ','
|
9
|
+
|
10
|
+
attr_accessor :name, :count
|
11
|
+
assign :name, String, true
|
12
|
+
validates_presence_of :name, :count
|
13
|
+
validate :validate_name
|
14
|
+
|
15
|
+
attr_reader :context
|
16
|
+
def context
|
17
|
+
if name.to_s =~ /:/
|
18
|
+
@context = name.split(/:/).first
|
19
|
+
else
|
20
|
+
remove_instance_variable :@context if instance_variable_defined? :@context
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
before_save :context
|
25
|
+
|
26
|
+
def update_count!
|
27
|
+
new_count = Item.count tags: {_in: [name]}
|
28
|
+
unless count == new_count
|
29
|
+
self.count = new_count
|
30
|
+
self.save!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def valid_name? name
|
36
|
+
name.present? and name !~ FORBIDDEN_CHARACTERS
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_tags! tags
|
40
|
+
tags.each do |name|
|
41
|
+
if tag = Tag.by_name(name)
|
42
|
+
# TODO3 preformance lost
|
43
|
+
tag.update_count!
|
44
|
+
else
|
45
|
+
tag = Tag.new name: name
|
46
|
+
tag.count = 1
|
47
|
+
tag.save!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_tags! before, after
|
53
|
+
create_tags! after - before
|
54
|
+
delete_tags! before - after
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete_tags! tags
|
58
|
+
tags.each do |name|
|
59
|
+
if tag = Tag.by_name(name)
|
60
|
+
tag.update_count!
|
61
|
+
tag.destroy if tag.count == 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
def validate_name
|
69
|
+
errors.add :name, t(:invalid_tag_name) unless Tag.valid_name?(name)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
.hl_highlight * {font-family: courier, monospace !important;}
|
2
|
+
|
3
|
+
.hl_hll { background-color: #ffffcc }
|
4
|
+
.hl_c { color: #008800; font-style: italic } /* Comment */
|
5
|
+
.hl_err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
6
|
+
.hl_k { color: #000080; font-weight: bold } /* Keyword */
|
7
|
+
.hl_cm { color: #008800; font-style: italic } /* Comment.hl_Multiline */
|
8
|
+
.hl_cp { color: #008080 } /* Comment.hl_Preproc */
|
9
|
+
.hl_c1 { color: #008800; font-style: italic } /* Comment.hl_Single */
|
10
|
+
.hl_cs { color: #008800; font-weight: bold } /* Comment.hl_Special */
|
11
|
+
.hl_gd { color: #000000; background-color: #ffdddd } /* Generic.hl_Deleted */
|
12
|
+
.hl_ge { font-style: italic } /* Generic.hl_Emph */
|
13
|
+
.hl_gr { color: #aa0000 } /* Generic.hl_Error */
|
14
|
+
.hl_gh { color: #999999 } /* Generic.hl_Heading */
|
15
|
+
.hl_gi { color: #000000; background-color: #ddffdd } /* Generic.hl_Inserted */
|
16
|
+
.hl_go { color: #888888 } /* Generic.hl_Output */
|
17
|
+
.hl_gp { color: #555555 } /* Generic.hl_Prompt */
|
18
|
+
.hl_gs { font-weight: bold } /* Generic.hl_Strong */
|
19
|
+
.hl_gu { color: #aaaaaa } /* Generic.hl_Subheading */
|
20
|
+
.hl_gt { color: #aa0000 } /* Generic.hl_Traceback */
|
21
|
+
.hl_kc { color: #000080; font-weight: bold } /* Keyword.hl_Constant */
|
22
|
+
.hl_kd { color: #000080; font-weight: bold } /* Keyword.hl_Declaration */
|
23
|
+
.hl_kn { color: #000080; font-weight: bold } /* Keyword.hl_Namespace */
|
24
|
+
.hl_kp { color: #000080; font-weight: bold } /* Keyword.hl_Pseudo */
|
25
|
+
.hl_kr { color: #000080; font-weight: bold } /* Keyword.hl_Reserved */
|
26
|
+
.hl_kt { color: #000080; font-weight: bold } /* Keyword.hl_Type */
|
27
|
+
.hl_m { color: #0000FF } /* Literal.hl_Number */
|
28
|
+
.hl_s { color: #0000FF } /* Literal.hl_String */
|
29
|
+
.hl_na { color: #FF0000 } /* Name.hl_Attribute */
|
30
|
+
.hl_nt { color: #000080; font-weight: bold } /* Name.hl_Tag */
|
31
|
+
.hl_ow { font-weight: bold } /* Operator.hl_Word */
|
32
|
+
.hl_w { color: #bbbbbb } /* Text.hl_Whitespace */
|
33
|
+
.hl_mf { color: #0000FF } /* Literal.hl_Number.hl_Float */
|
34
|
+
.hl_mh { color: #0000FF } /* Literal.hl_Number.hl_Hex */
|
35
|
+
.hl_mi { color: #0000FF } /* Literal.hl_Number.hl_Integer */
|
36
|
+
.hl_mo { color: #0000FF } /* Literal.hl_Number.hl_Oct */
|
37
|
+
.hl_sb { color: #0000FF } /* Literal.hl_String.hl_Backtick */
|
38
|
+
.hl_sc { color: #800080 } /* Literal.hl_String.hl_Char */
|
39
|
+
.hl_sd { color: #0000FF } /* Literal.hl_String.hl_Doc */
|
40
|
+
.hl_s2 { color: #0000FF } /* Literal.hl_String.hl_Double */
|
41
|
+
.hl_se { color: #0000FF } /* Literal.hl_String.hl_Escape */
|
42
|
+
.hl_sh { color: #0000FF } /* Literal.hl_String.hl_Heredoc */
|
43
|
+
.hl_si { color: #0000FF } /* Literal.hl_String.hl_Interpol */
|
44
|
+
.hl_sx { color: #0000FF } /* Literal.hl_String.hl_Other */
|
45
|
+
.hl_sr { color: #0000FF } /* Literal.hl_String.hl_Regex */
|
46
|
+
.hl_s1 { color: #0000FF } /* Literal.hl_String.hl_Single */
|
47
|
+
.hl_ss { color: #0000FF } /* Literal.hl_String.hl_Symbol */
|
48
|
+
.hl_il { color: #0000FF } /* Literal.hl_Number.hl_Integer.hl_Long */
|
data/app/static/kit.css
ADDED
data/app/static/kit.js
ADDED
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.the_list {.t_list; .s_list; .s_box; .s_round;
|
2
|
+
.l_controls {.s_controls; .s_small_text;}
|
3
|
+
.l_item {
|
4
|
+
.l_content {}}
|
5
|
+
.l_list_item {}
|
6
|
+
.l_finished {
|
7
|
+
div, a {.s_small_text;}
|
8
|
+
.content {text-decoration: line-through;}}}
|
9
|
+
|
10
|
+
|
11
|
+
.the_file_t () {
|
12
|
+
> table.css_table {
|
13
|
+
> tbody {
|
14
|
+
> tr {
|
15
|
+
> td.css_td1 {width: @icon_size1;}
|
16
|
+
> td.css_td2 {}}}}}
|
17
|
+
.the_file {.the_file_t; .s_box; .s_round;
|
18
|
+
.l_image {width: @icon_size1; margin-right: @normal;}
|
19
|
+
.l_title {.s_a_link; font-weight: bold;}}
|
20
|
+
|
21
|
+
|
22
|
+
.the_page {.s_box; .s_round;
|
23
|
+
> .l_text {}
|
24
|
+
> .l_content {
|
25
|
+
> .m_title {.s_normal_text;}}}
|
26
|
+
|
27
|
+
|
28
|
+
.the_folder {.s_box; .s_round;}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- b.comment id: object.dom_id do |o|
|
2
|
+
- o.user link_to(object.owner_name, user_path(object.owner_name))
|
3
|
+
|
4
|
+
- avatar_img = image_tag(Models::User.avatar_url(object.owner_name), onerror: "this.style.display = 'none'")
|
5
|
+
- o.avatar link_to(avatar_img, user_path(object.owner_name))
|
6
|
+
|
7
|
+
- o.owner link_to(object.owner_name, user_path(object.owner_name))
|
8
|
+
- o.details render_item_details(object, skip: [:comments, :owner])
|
9
|
+
- o.text object.text
|
10
|
+
- o.controls do |a|
|
11
|
+
- a.add link_to(t(:edit), edit_path(object, format: :js)) if can? :update, object
|
12
|
+
- a.add link_to(t(:delete), destroy_path(object, format: :js), method: :post, confirm: t(:are_you_shure)) if can? :destroy, object
|
13
|
+
/ - a.add link_to(t(:go), path(object))
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- case action_name
|
2
|
+
- when :destroy
|
3
|
+
rad.discussion().comment('##{@model.dom_id}').destroy();
|
4
|
+
|
5
|
+
- when :edit
|
6
|
+
- form = js render('form', object: @model, locals: {form_action: update_path(@model, format: :js)})
|
7
|
+
rad.discussion().comment('##{@model.dom_id}').edit('#{form}');
|
8
|
+
|
9
|
+
- when :new
|
10
|
+
- form = js render('form', object: @model, locals: {form_action: create_comment_path(format: :js)})
|
11
|
+
rad.discussion().anew('#{form}');
|
12
|
+
|
13
|
+
- when :create
|
14
|
+
- html = js render('embedded', object: @model)
|
15
|
+
rad.discussion().create("#{html}");
|
16
|
+
|
17
|
+
- when :update
|
18
|
+
- html = js render('embedded', object: @model)
|
19
|
+
rad.discussion().comment('##{@model.dom_id}').update('#{html}');
|
20
|
+
|
21
|
+
- else
|
22
|
+
- must_be.never_called
|
@@ -0,0 +1,11 @@
|
|
1
|
+
- b.comment id: @model.dom_id do |o|
|
2
|
+
- o.user link_to(@model.owner_name, user_path(@model.owner_name))
|
3
|
+
|
4
|
+
- avatar_img = image_tag(Models::User.avatar_url(@model.owner_name), onerror: "this.style.display = 'none'")
|
5
|
+
- o.avatar link_to(avatar_img, user_path(@model.owner_name))
|
6
|
+
|
7
|
+
- o.details render_item_details(@model, skip: :comments)
|
8
|
+
- o.text @model.text
|
9
|
+
- o.controls do |a|
|
10
|
+
- a.add link_to(t(:edit), edit_path(@model, format: :js)) if can? :update, @model
|
11
|
+
- a.add link_to(t(:delete), destroy_path(@model, format: :js), method: :post, confirm: t(:are_you_shure)) if can? :destroy, @model
|
@@ -0,0 +1,23 @@
|
|
1
|
+
- case action_name
|
2
|
+
- when :new
|
3
|
+
- form = js render('form', locals: {form_action: url_for(:create, format: :js)})
|
4
|
+
rad.dialog().show('#{form}');
|
5
|
+
|
6
|
+
- when :edit
|
7
|
+
- form = js render('form', locals: {form_action: update_path(@model, format: :js)})
|
8
|
+
rad.inplace('##{@model.dom_id}').edit('#{form}');
|
9
|
+
|
10
|
+
- when :update
|
11
|
+
- html = js render('show', object: @model)
|
12
|
+
rad.inplace('##{@model.dom_id}').update('#{html}');
|
13
|
+
|
14
|
+
- when :access
|
15
|
+
- html = js render('/tools/access')
|
16
|
+
$("access_tool").replaceWith("#{html}");
|
17
|
+
|
18
|
+
- else
|
19
|
+
- must_be.never_called
|
20
|
+
|
21
|
+
/ - when :context_menu
|
22
|
+
/ - html = js render('/bag/slots/context_menu')
|
23
|
+
/ $("#_context_menu").replaceWith("#{html}");
|
@@ -0,0 +1 @@
|
|
1
|
+
= b.title "Inherited Action"
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- bottom_text, powered_by = rad.config.bottom_text, rad.config.powered_by
|
2
|
+
- if bottom_text or powered_by or rad.development? or @debug
|
3
|
+
- b.bottom_panel do |o|
|
4
|
+
- if bottom_text or rad.development? or @debug
|
5
|
+
- o.left do
|
6
|
+
= bottom_text if bottom_text
|
7
|
+
= render '/kit/debug' if rad.development?
|
8
|
+
- if powered_by
|
9
|
+
- o.right t(:powered_by, company: powered_by)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Params: #{params.inspect}
|
2
|
+
- permissions = Models::User.current.effective_permissions.select{|op, perm| perm}.collect{|op, perm| op}.join(', ')
|
3
|
+
- if permissions.present?
|
4
|
+
%br
|
5
|
+
Permissions: #{permissions}
|
6
|
+
- if @model and Models::User.current.owner?(@model)
|
7
|
+
- opermissions = Models::User.current.effective_permissions_as_owner.to_a.select{|op, perm| perm}.collect{|op, perm| op}.join(', ')
|
8
|
+
- if opermissions.present?
|
9
|
+
%br
|
10
|
+
Permissions as Owner: #{}
|
11
|
+
|
12
|
+
- if @debug
|
13
|
+
%p= @debug
|
@@ -0,0 +1,19 @@
|
|
1
|
+
- menu, additional_menu = rad.config.menu, rad.config.additional_menu
|
2
|
+
- if menu or additional_menu
|
3
|
+
- b.navigation do |o|
|
4
|
+
/ - o.items do ||
|
5
|
+
- if menu
|
6
|
+
- o.left do |a|
|
7
|
+
- menu.each do |name, link|
|
8
|
+
- if request.path.include? link
|
9
|
+
- a.add content: h(name), active: true
|
10
|
+
- else
|
11
|
+
- a.add link_to(h(name), h(link))
|
12
|
+
|
13
|
+
- if additional_menu
|
14
|
+
- o.right do |a|
|
15
|
+
- additional_menu.each do |name, link|
|
16
|
+
- if request.path.include? link
|
17
|
+
- a.add content: h(name), active: true
|
18
|
+
- else
|
19
|
+
- a.add link_to(h(name), h(link))
|
@@ -0,0 +1 @@
|
|
1
|
+
= b.title t(:page_not_found)
|