admin_it 1.0.9 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 45f2f0b918cc7598db68bfa95c9531166582e32f
4
- data.tar.gz: 20beca7ce9441e4e9daf07193b683d2cce03fdbf
3
+ metadata.gz: 2b4af7fc6796fe6d148a1d91d62449d2cca40e44
4
+ data.tar.gz: dcd1542a809878391c15ed5604e74d26b1d7572d
5
5
  SHA512:
6
- metadata.gz: f3c96628072ee5f826f3363d3f46c0d35913af0f04d63f33cdcb38162c106c533535a32cf3705bfe2dd862086cfcd9ee03c4cc7cb704adf4e115c16e7f1af931
7
- data.tar.gz: bab6e0655d1a46847110bea8721ff19ad182e8f5cf516633de1b3edf83a635be1c6ad700c8cb4360f45f384492e5ed51cc8307b2dbd78aa181636262699cd78d
6
+ metadata.gz: 70d197f764d7b3126e564d7aeaf53cc47ef999f06d00a79db152defaad223725accbc64b7000cc07e92d55e964e2c856e48237c0176df300214081fec304cb62
7
+ data.tar.gz: b8886811264b9aaef4cbed1c6404eba4a93de24361785322cc86ed8ae7d65a9665136ff3d7cbc4359cf3b50ab872eed31dee8032c4f277d329582d239891240d
data/README.md CHANGED
@@ -38,6 +38,15 @@ bundle install
38
38
 
39
39
  # Changes
40
40
 
41
+ `1.0.10`
42
+
43
+ * added: sorting indicator in table column header
44
+ * added: sections
45
+
46
+ `1.0.9`
47
+
48
+ * added: filter button in table column header
49
+
41
50
  `1.0.8`
42
51
 
43
52
  * dsl code fully refactored
data/README_RU.md CHANGED
@@ -23,19 +23,98 @@ bundle install
23
23
 
24
24
  Конфигурация производится в файле `config/initializers/admin_it.rb`. На данный момент доступны следующие переменные:
25
25
 
26
+ `config.root`: папка, содержащая определения ресурсов и другие настройки. По умолчанию: `app/admin_it`.
27
+
28
+ `config.controller`: класс контроллера, от которого наследуются все контроллеры, используемые библиотекой `admin_it`. По умолчанию для Rails: `ActionController::Base`.
29
+
30
+ Пример файла конфигурации:
31
+
32
+ ```ruby
33
+ require 'admin_it'
34
+
35
+ AdminIt.config do |config|
36
+ config.root = 'admin_it'
37
+ end
38
+ ```
26
39
 
27
40
  # Использование
28
41
 
42
+ Библиотека оперирует такими понятиями, как:
43
+
44
+ * **Ресурс (resource)** - набор данных, который можно просматривать или изменять. Как правило, ресурс соответствует таблице базы данных. Для каждого ресурса библиотека создаёт отдельный класс контроллера.
45
+ * **Контекст (context)** - представление данных, или форма отображения данных. Контекст может быть для отдельной записи (`единичный контекст`) или для набора данных (`множественный контекст`). На данный момент библиотека предоставляет следующие контексты:
46
+ - единичные:
47
+ + `show` - отображение или удаление записи
48
+ + `edit` - форма для редактирования записи
49
+ + `new` - форма для создания записи
50
+ - множественные:
51
+ + `table` - таблица данных
52
+ + `tiles` - набор плиток
53
+ + `list` - список (пока не работает)
54
+ * **Поле (field)** - представляет поле (колонку) данных. Имеет следующие атрибуты:
55
+ - readable
56
+ - writable
57
+ - visible
58
+ * **Фильтр (filter)** - фильтр данных. Пока не закончено.
59
+
60
+ Для создания интерфейса управления данными, необходимо определить ресурс. Делается это в файле с расширением `.rb` в папке, указанной в конфигурации, например:
61
+
62
+ ```ruby
63
+ AdminIt.resource :location do
64
+ icon 'globe'
65
+
66
+ use_contexts except: :list
67
+
68
+ collection do
69
+ use_fields except: %i(created_at updated_at geo_point geo_data okato
70
+ kladr_code lowcase_name short_name area_children
71
+ region_children region area)
72
+ use_filters :type_name_value, :level_value
73
+ end
74
+
75
+ context :tiles do
76
+ header :name
77
+ end
78
+
79
+ context :table do
80
+ use_fields :name, :level, :*
81
+ end
82
+ end
83
+ ```
84
+
85
+ В данном файле создается ресурс для данных класса `Location`. Ресурс использует для отображения иконку "глобус". (Все иконки можно найти [здесь](http://fortawesome.github.io/Font-Awesome/icons/) - имена необходимо указывать без суффикса `fa-`).
86
+
87
+ Далее указывается, что не нужно использовать (использовать все, кроме) контекст `:list`, посокльку его описание ещё не закончено.
88
+
89
+ Далее выполняется блок для всех множественных контекстов (поскольку `:list` исключён, то это `:table` и `:tiles`). Т.е. все множественные контексты будут использовать указанные в данном блоке настройки. В нашем случае это сокращенный список полей для удобства отображения и также, сокращённый список фильтров, имеющиё смысл в данном контексте.
90
+
91
+ Далее идет индивидуальная настройка каждого контекста (не указанные явно контексты принимают все значения по-умолчанию).
92
+
93
+ Для контекста `:tiles` указывается имя поля, служащее заголоком плитки
94
+
95
+ Для контекста `:table` указывается порядок следования полей: сначала `:name`, затем `:level`, затем все остальные в порядке по-умолчанию. Символ `:*` заменяется на все имеющиеся для данного контекста поля, не указанные в команде явно.
96
+
29
97
  # Планы
30
98
 
31
99
  * Поркытие тестами
32
100
  * Редактирование/создание записей
33
101
 
34
- ## Далёкие планы
102
+ # Изменения
35
103
 
36
- * Поддержка Sinatra
104
+ `1.0.10`
37
105
 
38
- # Изменения
106
+ * добавлен индикатор сортировки в заголовках таблиц
107
+ * добавлены вкладки для единичных контекстов
108
+
109
+ `1.0.9`
110
+
111
+ * добавлена кнопка фильтров в заголоки таблиц
112
+
113
+ `1.0.8`
114
+
115
+ * полностью переработан код DSL
116
+ * увеличено покрытие тестами
117
+ * добавлена возможность выбора набора фильтров для контекста
39
118
 
40
119
  `1.0.7`
41
120
 
@@ -23,3 +23,4 @@
23
23
  .tab-pane {
24
24
  margin-top: 10px;
25
25
  }
26
+
@@ -16,11 +16,32 @@
16
16
  - if for_context.confirm == :destroy
17
17
  p = t('admin_it.confirm.destroy.header')
18
18
 
19
- dl class="dl-horizontal"
20
- - for_context.fields.each do |f|
21
- - next if f.type == :relation
22
- dt = f.display_name
23
- = field f, tag: 'dl'
19
+ - if for_context.sections.size > 0
20
+ ul class="nav nav-tabs"
21
+ - for_context.sections.each do |section|
22
+ li class="#{section.name == for_context.section ? 'active' : ''}"
23
+ a href="##{section.name}" data-toggle="tab"
24
+ = section.display_name
25
+ div class="tab-content"
26
+ - for_context.sections.each do |section|
27
+ div class="tab-pane #{section.name == for_context.section ? 'active' : ''}" id==section.name
28
+ - if section.fields.size > 0
29
+ dl class="dl-horizontal"
30
+ - section.fields.each do |f_name|
31
+ - f = for_context.field(f_name)
32
+ - next if f.type == :relation
33
+ dt = f.display_name
34
+ - value = f.show(for_context.entity)
35
+ - value = value.nil? ? ' '.html_safe : value.to_s
36
+ = field value, tag: 'dd'
37
+ - else
38
+ dl class="dl-horizontal"
39
+ - for_context.fields.each do |f|
40
+ - next if f.type == :relation
41
+ dt = f.display_name
42
+ - value = f.show(for_context.entity)
43
+ - value = value.nil? ? ' '.html_safe : value.to_s
44
+ = field value, tag: 'dd'
24
45
  div class="clearfix"
25
46
 
26
47
  - if for_context.confirm?
@@ -10,9 +10,13 @@
10
10
  = _table.header do |header|
11
11
  - for_context.headers.each do |k, h|
12
12
  - opts = { :'data-toggle' => 'popup' }
13
- - opts[:class] = 'text-info' if for_context.sorting.any? { |s| s.index("#{k}:") == 0 }
13
+ - active_sorting = for_context.sorting.find { |s| s.index("#{k}:") == 0 }
14
+ - opts[:class] = 'text-info' unless active_sorting.nil?
14
15
  = header.cell opts do
15
16
  = h
17
+ - unless active_sorting.nil?
18
+ = ' '
19
+ i class="fa fa-caret-#{active_sorting.split(':').last == 'asc' ? 'down' : 'up'}"
16
20
  - filter_class = for_context.all_filters(scope: :value).find do |f|
17
21
  - f.field.field_name == k
18
22
  - unless filter_class.nil?
@@ -25,7 +25,7 @@ html
25
25
  div class="container"
26
26
  <!-- top-menu -->
27
27
 
28
- div class="container"
28
+ div class="container admin-it-#{context.name}"
29
29
  = render File.join(%w(admin_it shared toolbar))
30
30
  = render File.join(%w(admin_it shared filters))
31
31
  = yield
@@ -1,6 +1,6 @@
1
1
  div class="modal-header"
2
2
  h4.modal-title = yield :title
3
- div class="modal-body"
3
+ div class="modal-body admin-it-#{context.name}"
4
4
  = yield
5
5
  div class="modal-footer"
6
6
  button type="button" class="btn btn-default" data-dismiss="modal"
@@ -12,6 +12,7 @@ module AdminIt
12
12
  dsl do
13
13
  dsl_block :entities, variable: :entities_getter
14
14
  dsl_accessor :default_sorting
15
+ dsl_boolean :show_in_dialog
15
16
  end
16
17
 
17
18
  def self.before_configure
@@ -25,6 +26,10 @@ module AdminIt
25
26
  ]
26
27
  end
27
28
 
29
+ def self.show_in_dialog?
30
+ @show_in_dialog.nil? ? @show_in_dialog = true : @show_in_dialog == true
31
+ end
32
+
28
33
  def self.collection?
29
34
  true
30
35
  end
@@ -41,7 +46,7 @@ module AdminIt
41
46
  end
42
47
 
43
48
  attr_accessor :entity
44
- class_attr_reader :entities_getter, :path
49
+ class_attr_reader :entities_getter, :path, :show_in_dialog?
45
50
 
46
51
  before_load do |store: {}, params: {}|
47
52
  self.sorting = store[:sorting] || self.class.default_sorting
@@ -4,25 +4,39 @@ module AdminIt
4
4
  include ExtendIt::Dsl
5
5
  include Renderable
6
6
 
7
- attr_reader :name, :display_name
7
+ attr_reader :name, :display_name, :fields
8
8
 
9
9
  dsl do
10
10
  dsl_accessor :name, :display_name
11
11
  dsl_boolean :visible
12
+
13
+ def use_fields(*names, except: nil)
14
+ names = names.ensure_symbols
15
+ fields =
16
+ if names.nil? || names.empty?
17
+ dsl_get(:fields, default: [])
18
+ else
19
+ context = dsl_get(:context, default: nil)
20
+ names & context.fields.map(&:field_name)
21
+ end
22
+ fields -= except.ensure_symbols unless except.nil?
23
+ dsl_set(:fields, fields.uniq)
24
+ end
12
25
  end
13
26
 
14
27
  def visible?
15
28
  @visible.nil? ? @visible = true : @visible == true
16
29
  end
17
30
 
18
- def fields(*names)
19
- names.empty? ? @fields ||= [] : @fields = names
20
- end
21
-
22
- def initialize(name, *fields, display_name: nil)
31
+ def initialize(name, context, display_name: nil)
23
32
  @name = name
24
33
  @display_name = display_name || name
25
- @fields = fields
34
+ @context = context
35
+ @fields = context.fields.map(&:field_name)
36
+ context.sections.each do |section|
37
+ next if section.name == name
38
+ @fields -= section.fields
39
+ end
26
40
  end
27
41
  end
28
42
 
@@ -53,12 +67,12 @@ module AdminIt
53
67
  #general.display_name(I18n.t('admin_it.collection.no_data'))
54
68
  general = Section.new(
55
69
  :general,
56
- *fields.map(&:field_name),
70
+ self,
57
71
  display_name: 'Основные свойства'
58
72
  )
59
73
  @sections[:general] = general
60
74
  end
61
- Section.new(name)
75
+ name == :general ? @sections[:general] : Section.new(name, self)
62
76
  end
63
77
  end
64
78
 
@@ -3,6 +3,21 @@ module AdminIt
3
3
  module Resource
4
4
  protected
5
5
 
6
+ TYPE_MAPPING = {
7
+ primary_key: :integer,
8
+ string: :string,
9
+ text: :string,
10
+ integer: :integer,
11
+ float: :float,
12
+ decimal: :float,
13
+ datetime: :datetime,
14
+ timestamp: :datetime,
15
+ time: :time,
16
+ date: :date,
17
+ binary: :binary,
18
+ boolean: :boolean
19
+ }
20
+
6
21
  def default_display_name
7
22
  entity_class
8
23
  .model_name
@@ -24,7 +39,7 @@ module AdminIt
24
39
  entity_class.columns_hash.each do |name, c|
25
40
  next if exclude.include?(name)
26
41
  name = name.to_sym
27
- opts = { type: c.type }
42
+ opts = { type: TYPE_MAPPING[c.type] }
28
43
  if name == :id
29
44
  opts[:visible] = false
30
45
  opts[:writable] = false
@@ -50,7 +65,7 @@ module AdminIt
50
65
  module CollectionContext
51
66
  def entities=(value)
52
67
  super(value)
53
- @count = value.count
68
+ @count = @entities.nil? ? 0 : @entities.count
54
69
  end
55
70
 
56
71
  protected
@@ -70,7 +85,9 @@ module AdminIt
70
85
  name, order = _sort.split(':')
71
86
  sort[name.to_sym] = order.to_sym
72
87
  end
73
- collection = collection.order(sort) unless sort.empty?
88
+ unless collection.nil? || sort.empty?
89
+ collection = collection.order(sort)
90
+ end
74
91
  collection
75
92
  end
76
93
  end
@@ -15,7 +15,8 @@ module AdminIt
15
15
  extend DisplayableName
16
16
  include ExtendIt::Callbacks
17
17
 
18
- TYPES = %i(unknown integer float string date relation enum)
18
+ TYPES = %i(unknown integer float string date datetime time relation enum
19
+ binary)
19
20
 
20
21
  define_callbacks :initialize
21
22
 
@@ -29,16 +30,16 @@ module AdminIt
29
30
  dsl_block :read, :write, :render, :display
30
31
 
31
32
  def hide
32
- @visible = false
33
+ dsl_set(:visible, false)
33
34
  end
34
35
 
35
36
  def show
36
- @visible = true
37
+ dsl_set(:visible, true)
37
38
  end
38
39
  end
39
40
 
40
41
  class << self
41
- attr_reader :type, :read, :write, :render, :display
42
+ attr_reader :read, :write, :render, :display, :type
42
43
 
43
44
  protected
44
45
 
@@ -65,27 +66,29 @@ module AdminIt
65
66
 
66
67
  inherited_class_reader :field_name, :entity_class
67
68
 
68
- def self.create(name, _entity_class,
69
- type: :unknown,
70
- readable: true,
71
- writable: true,
72
- visible: true,
73
- sortable: true
74
- )
69
+ def self.create(name, _entity_class, **opts)
70
+ # type: :unknown,
71
+ # readable: true,
72
+ # writable: true,
73
+ # visible: true,
74
+ # sortable: true
75
+ # )
75
76
  base = self
77
+ # _type, _readable, _writable, _visible, _sortable =
78
+ # type, readable, writable, visible, sortable
76
79
  Class.new(base) do
77
80
  @field_name, @entity_class = name, _entity_class
78
81
  import_data_module(base)
79
- @readable = readable == true
80
- @writable = writable == true
81
- @visible = visible == true
82
- @sortable = sortable == true
83
- self.type = type
82
+ @readable = opts[:readable].nil? ? true : opts[:readable] == true
83
+ @writable = opts[:writable].nil? ? true : opts[:writable] == true
84
+ @visible = opts[:visible].nil? ? true : opts[:visible] == true
85
+ @sortable = opts[:sortable].nil? ? true : opts[:sortable] == true
86
+ self.type = opts[:type]
84
87
  end
85
88
  end
86
89
 
87
90
  def self.type=(value)
88
- TYPES.include?(value) ? value : TYPES[0]
91
+ @type = TYPES.include?(value) ? value : TYPES[0]
89
92
  end
90
93
 
91
94
  def self.placeholder
@@ -25,11 +25,18 @@ module AdminIt
25
25
  resource = parent.parent.resource
26
26
  single = resource.singles.select { |c| !(c <= NewContext) }
27
27
  buttons = single.map do |_context|
28
+ if _context <= ShowContext && context.show_in_dialog?
29
+ '<a class="btn btn-xs btn-info" ' +
30
+ %Q{data-toggle="modal" data-target="#confirm_modal" } +
31
+ %Q{href="#{_context.path(entity)}?layout=dialog">} +
32
+ %Q{<i class="fa fa-#{_context.icon}"></i></a>}
33
+ else
28
34
  cl = _context <= ShowContext ? 'info' : 'default'
29
35
  href = _context.path(entity)
30
36
  "<a class=\"btn btn-xs btn-#{cl}\" href=\"#{href}\">" \
31
37
  "<i class=\"fa fa-#{_context.icon}\"></i></a>"
32
38
  end
39
+ end
33
40
  if resource.destroyable?
34
41
  if context.confirm_destroy?
35
42
  confirm = single.find { |c| c.context_name == :confirm } ||
@@ -1,5 +1,5 @@
1
1
  #
2
2
  module AdminIt
3
3
  # Current gem version
4
- VERSION = '1.0.9'
4
+ VERSION = '1.0.10'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: admin_it
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Ovchinnikov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-16 00:00:00.000000000 Z
11
+ date: 2014-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails