papaSquidLib 0.1.0
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 +7 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +69 -0
- data/lib/controllers/tab_students_controller.rb +43 -0
- data/lib/data_sources/db_client.rb +35 -0
- data/lib/db_config/config.yaml +5 -0
- data/lib/db_config/library_config.yaml +5 -0
- data/lib/db_config/migrations/create_db.sql +3 -0
- data/lib/db_config/migrations/create_tables.sql +29 -0
- data/lib/db_config/mock_data/mock_data.sql +72 -0
- data/lib/logger.rb +27 -0
- data/lib/main.rb +6 -0
- data/lib/manager/controllers/manager_input_form_controller_create.rb +44 -0
- data/lib/manager/controllers/manager_input_form_controller_edit.rb +54 -0
- data/lib/manager/controllers/manager_list_controller.rb +99 -0
- data/lib/manager/manager_db_data_source.rb +63 -0
- data/lib/manager/ui/manager_input_form.rb +69 -0
- data/lib/manager/ui/manager_list_view.rb +168 -0
- data/lib/models/manager.rb +41 -0
- data/lib/models/student.rb +102 -0
- data/lib/models/student_base.rb +100 -0
- data/lib/models/student_short.rb +50 -0
- data/lib/models/task.rb +49 -0
- data/lib/models/user.rb +32 -0
- data/lib/papaSquidLib/version.rb +5 -0
- data/lib/papa_squid_lib.rb +6 -0
- data/lib/repositories/adapters/db_source_adapter.rb +54 -0
- data/lib/repositories/adapters/file_source_adapter.rb +37 -0
- data/lib/repositories/containers/data_list.rb +74 -0
- data/lib/repositories/containers/data_list_student_short.rb +18 -0
- data/lib/repositories/containers/data_table.rb +35 -0
- data/lib/repositories/data_sources/db_data_source.rb +32 -0
- data/lib/repositories/data_sources/file_data_source.rb +75 -0
- data/lib/repositories/data_sources/transformers/data_transformer_base.rb +15 -0
- data/lib/repositories/data_sources/transformers/data_transformer_json.rb +16 -0
- data/lib/repositories/data_sources/transformers/data_transformer_yaml.rb +16 -0
- data/lib/repositories/student_repository.rb +32 -0
- data/lib/state_holders/list_state_notifier.rb +60 -0
- data/lib/task/controllers/task_input_form_controller_create.rb +43 -0
- data/lib/task/controllers/task_input_form_controller_edit.rb +57 -0
- data/lib/task/controllers/task_list_controller.rb +93 -0
- data/lib/task/task_db_data_source.rb +85 -0
- data/lib/task/ui/task_input_form.rb +67 -0
- data/lib/task/ui/task_input_form_factory.rb +26 -0
- data/lib/task/ui/task_list_view.rb +163 -0
- data/lib/user/controllers/user_input_form_controller_create.rb +42 -0
- data/lib/user/controllers/user_input_form_controller_edit.rb +53 -0
- data/lib/user/controllers/user_list_controller.rb +99 -0
- data/lib/user/ui/user_input_form.rb +69 -0
- data/lib/user/ui/user_list_view.rb +170 -0
- data/lib/user/user_db_data_source.rb +71 -0
- data/lib/views/main_window.rb +32 -0
- data/lib/views/tab_students.rb +148 -0
- data/papaSquidLib.gemspec +15 -0
- data/test/manager_test.rb +27 -0
- data/test/state_notifier_test.rb +82 -0
- data/test/task_test.rb +51 -0
- data/test/user_test.rb +39 -0
- metadata +113 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'glimmer-dsl-libui'
|
3
|
+
require_relative '../controllers/task_input_form_controller_create.rb'
|
4
|
+
require './lib/models/task'
|
5
|
+
require 'win32api'
|
6
|
+
|
7
|
+
class TaskInputForm
|
8
|
+
include Glimmer
|
9
|
+
|
10
|
+
def initialize(controller, fields_to_create, existing_student = nil)
|
11
|
+
@fields_to_create=fields_to_create
|
12
|
+
@item = existing_student.to_hash unless existing_student.nil?
|
13
|
+
@controller = controller
|
14
|
+
@entries = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_create
|
18
|
+
@controller.on_view_created
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@root_container = window('Задание', 300, 70) {
|
23
|
+
resizable false
|
24
|
+
|
25
|
+
vertical_box {
|
26
|
+
@student_form = form {
|
27
|
+
stretchy false
|
28
|
+
|
29
|
+
fields = @fields_to_create
|
30
|
+
|
31
|
+
fields.each do |field|
|
32
|
+
@entries[field[0]] = entry {
|
33
|
+
label field[1]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
button('Сохранить') {
|
39
|
+
stretchy false
|
40
|
+
|
41
|
+
on_clicked {
|
42
|
+
values = @entries.transform_values { |v| v.text.force_encoding("utf-8").strip }
|
43
|
+
values.transform_values! { |v| v.empty? ? nil : v}
|
44
|
+
@controller.process_fields(values)
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
on_create
|
50
|
+
@root_container
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_value(field, value)
|
54
|
+
return unless @entries.include?(field)
|
55
|
+
@entries[field].text = value
|
56
|
+
end
|
57
|
+
|
58
|
+
def make_readonly(*fields)
|
59
|
+
fields.each do |field|
|
60
|
+
@entries[field].read_only = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def close
|
65
|
+
@root_container.destroy
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TaskInputFormFactory
|
4
|
+
def self.create_create_form(controller)
|
5
|
+
TaskInputForm.new(controller, fields_for_create)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create_edit_form(controller, existing_task)
|
9
|
+
TaskInputForm.new(controller, fields_for_edit(existing_task), existing_task)
|
10
|
+
end
|
11
|
+
|
12
|
+
private_class_method def self.fields_for_create
|
13
|
+
[
|
14
|
+
[:user_id, 'ID пользователя'],
|
15
|
+
[:manager_id, 'ID менеджера'],
|
16
|
+
[:description, 'Описание']
|
17
|
+
]
|
18
|
+
end
|
19
|
+
|
20
|
+
private_class_method def self.fields_for_edit(task)
|
21
|
+
[
|
22
|
+
[:description, 'Описание', task.description],
|
23
|
+
[:completed, 'Завершено', task.completed]
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative '../controllers/task_list_controller'
|
3
|
+
require_relative 'task_input_form'
|
4
|
+
|
5
|
+
class TaskListView
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
PAGE_SIZE = 20
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@controller = TaskListController.new(self)
|
12
|
+
@current_page = 1
|
13
|
+
@total_count = 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_create
|
17
|
+
@controller.on_view_created
|
18
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
19
|
+
end
|
20
|
+
|
21
|
+
def update(tasks)
|
22
|
+
@items = []
|
23
|
+
i = 0
|
24
|
+
item_num = 0
|
25
|
+
tasks.each do |task|
|
26
|
+
i += 1
|
27
|
+
item_num = ((@current_page - 1) * PAGE_SIZE) + i
|
28
|
+
@items << Struct.new(:№, :id, :id_пользователя, :id_менеджера, :дата_создания, :описание, :статус).new(item_num, task.task_id, task.user_id, task.manager_id, task.date, task.description, task.completed)
|
29
|
+
end
|
30
|
+
|
31
|
+
@table.model_array = @items
|
32
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_student_count(new_cnt)
|
36
|
+
@total_count = new_cnt
|
37
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def create
|
41
|
+
|
42
|
+
root_container = horizontal_box {
|
43
|
+
# Секция 1
|
44
|
+
vertical_box {
|
45
|
+
stretchy false
|
46
|
+
|
47
|
+
vertical_box {
|
48
|
+
stretchy false
|
49
|
+
|
50
|
+
label {
|
51
|
+
text 'Завершено'
|
52
|
+
}
|
53
|
+
combobox { |c|
|
54
|
+
items ['Не важно','Сделано','Не сделано']
|
55
|
+
selected 0
|
56
|
+
on_selected do
|
57
|
+
@controller.filter_completed(@current_page, PAGE_SIZE, c.selected)
|
58
|
+
end
|
59
|
+
}
|
60
|
+
|
61
|
+
label {
|
62
|
+
text 'Сортировка'
|
63
|
+
}
|
64
|
+
combobox { |c|
|
65
|
+
items ['ID',
|
66
|
+
'ID пользователя',
|
67
|
+
'ID менеджера',
|
68
|
+
'Дата создания',
|
69
|
+
'Описание',
|
70
|
+
'Статус'
|
71
|
+
]
|
72
|
+
selected 0
|
73
|
+
on_selected do
|
74
|
+
@controller.sort(@current_page, PAGE_SIZE, c.selected)
|
75
|
+
end
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
# Секция 2
|
81
|
+
vertical_box {
|
82
|
+
@table = refined_table(
|
83
|
+
table_editable: false,
|
84
|
+
filter: lambda do |row_hash, query|
|
85
|
+
utf8_query = query.force_encoding("utf-8")
|
86
|
+
row_hash['Имя пользователя'].include?(utf8_query)
|
87
|
+
end,
|
88
|
+
table_columns: {
|
89
|
+
'№' => :text,
|
90
|
+
'ID' => :text,
|
91
|
+
'ID пользователя' => :text,
|
92
|
+
'ID менеджера' => :text,
|
93
|
+
'Дата создания' => :text,
|
94
|
+
'Описание' => :text,
|
95
|
+
'Статус' => :text
|
96
|
+
},
|
97
|
+
per_page: PAGE_SIZE,
|
98
|
+
|
99
|
+
)
|
100
|
+
|
101
|
+
@pages = horizontal_box {
|
102
|
+
stretchy false
|
103
|
+
|
104
|
+
button("<") {
|
105
|
+
stretchy true
|
106
|
+
|
107
|
+
on_clicked do
|
108
|
+
@current_page = [@current_page - 1, 1].max
|
109
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
110
|
+
end
|
111
|
+
|
112
|
+
}
|
113
|
+
@page_label = label("...") { stretchy false }
|
114
|
+
button(">") {
|
115
|
+
stretchy true
|
116
|
+
|
117
|
+
on_clicked do
|
118
|
+
@current_page = [@current_page + 1, (@total_count / PAGE_SIZE.to_f).ceil].min
|
119
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
120
|
+
end
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
# Секция 3
|
126
|
+
vertical_box {
|
127
|
+
stretchy false
|
128
|
+
|
129
|
+
button('Добавить') {
|
130
|
+
stretchy false
|
131
|
+
|
132
|
+
on_clicked {
|
133
|
+
@controller.show_modal_add
|
134
|
+
}
|
135
|
+
}
|
136
|
+
button('Изменить') {
|
137
|
+
stretchy false
|
138
|
+
|
139
|
+
on_clicked {
|
140
|
+
@controller.show_modal_edit(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
141
|
+
}
|
142
|
+
}
|
143
|
+
button('Удалить') {
|
144
|
+
stretchy false
|
145
|
+
|
146
|
+
on_clicked {
|
147
|
+
@controller.delete_selected(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
148
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
149
|
+
}
|
150
|
+
}
|
151
|
+
button('Обновить') {
|
152
|
+
stretchy false
|
153
|
+
|
154
|
+
on_clicked {
|
155
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
on_create
|
161
|
+
root_container
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
|
5
|
+
class UserInputFormControllerCreate
|
6
|
+
def initialize(parent_controller)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@user_rep = UserDbDataSource.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_view(view)
|
12
|
+
@view = view
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_view_created
|
16
|
+
# begin
|
17
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
18
|
+
# rescue Mysql2::Error::ConnectionError
|
19
|
+
# on_db_conn_error
|
20
|
+
# end
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_fields(fields)
|
24
|
+
begin
|
25
|
+
item = User.new(-1, *fields.values)
|
26
|
+
item = @user_rep.add(item)
|
27
|
+
@parent_controller.state_notifier.add(item)
|
28
|
+
@view.close
|
29
|
+
rescue ArgumentError => e
|
30
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
31
|
+
api.call(0, e.message, 'Error', 0)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def on_db_conn_error
|
38
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
39
|
+
api.call(0, "No connection to DB", "Error", 0)
|
40
|
+
@view.close
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
|
5
|
+
class UserInputFormControllerEdit
|
6
|
+
def initialize(parent_controller, item)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@item = item
|
9
|
+
@user_rep = UserDbDataSource.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_view(view)
|
13
|
+
@view = view
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_view_created
|
17
|
+
# begin
|
18
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
19
|
+
# rescue Mysql2::Error::ConnectionError
|
20
|
+
# on_db_conn_error
|
21
|
+
# end
|
22
|
+
|
23
|
+
# @item = @author_rep.get(@item_id)
|
24
|
+
# @view.make_readonly(:git, :telegram, :email, :phone)
|
25
|
+
populate_fields(@item)
|
26
|
+
end
|
27
|
+
|
28
|
+
def populate_fields(item)
|
29
|
+
@view.set_value(:first_name, item.first_name)
|
30
|
+
@view.set_value(:last_name, item.last_name)
|
31
|
+
@view.set_value(:father_name, item.father_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_fields(fields)
|
35
|
+
begin
|
36
|
+
item = User.new(@item.user_id, *fields.values)
|
37
|
+
item = @user_rep.change(item)
|
38
|
+
@parent_controller.state_notifier.replace(@item, item)
|
39
|
+
@view.close
|
40
|
+
rescue ArgumentError => e
|
41
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
42
|
+
api.call(0, e.message, 'Error', 0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def on_db_conn_error
|
49
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
50
|
+
api.call(0, "No connection to DB", "Error", 0)
|
51
|
+
@view.close
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './lib/state_holders/list_state_notifier'
|
4
|
+
require_relative '../ui/user_input_form'
|
5
|
+
require_relative 'user_input_form_controller_create'
|
6
|
+
require_relative 'user_input_form_controller_edit'
|
7
|
+
require_relative '../user_db_data_source'
|
8
|
+
require 'win32api'
|
9
|
+
|
10
|
+
# Класс UserListController отвечает за управление списком
|
11
|
+
# авторов, используя различные методы для обновления данных и
|
12
|
+
# взаимодействия с пользовательским интерфейсом.
|
13
|
+
class UserListController
|
14
|
+
|
15
|
+
attr_reader :state_notifier;
|
16
|
+
|
17
|
+
def initialize(view)
|
18
|
+
LoggerHolder.instance.debug('UserListController: initialize')
|
19
|
+
@view = view
|
20
|
+
@state_notifier = ListStateNotifier.new
|
21
|
+
@state_notifier.add_listener(@view)
|
22
|
+
@user_rep = UserDbDataSource.new
|
23
|
+
|
24
|
+
@sort_columns = %w[UserID FirstName LastName FatherName]
|
25
|
+
@sort_by = @sort_columns.first
|
26
|
+
|
27
|
+
@father_name_filter_columns = [nil, true, false]
|
28
|
+
@father_name_filter = @father_name_filter_columns.first
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_view_created
|
32
|
+
# begin
|
33
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
34
|
+
# rescue Mysql2::Error::ConnectionError
|
35
|
+
# on_db_conn_error
|
36
|
+
# end
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_view
|
40
|
+
@view.create.show
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_modal_add
|
44
|
+
LoggerHolder.instance.debug('UserListController: show_modal_add')
|
45
|
+
controller = UserInputFormControllerCreate.new(self)
|
46
|
+
view = UserInputForm.new(controller)
|
47
|
+
controller.set_view(view)
|
48
|
+
view.create.show
|
49
|
+
end
|
50
|
+
|
51
|
+
# метод, который создает контроллер UserInputFormControllerEdit, представление UserInputForm, устанавливает связи между ними и показывает модальное окно.
|
52
|
+
def show_modal_edit(current_page, per_page, selected_row)
|
53
|
+
LoggerHolder.instance.debug('UserListController: show_modal_edit')
|
54
|
+
# item_num = (current_page - 1) * per_page + selected_row
|
55
|
+
item = @state_notifier.get(selected_row)
|
56
|
+
controller = UserInputFormControllerEdit.new(self, item)
|
57
|
+
view = UserInputForm.new(controller)
|
58
|
+
controller.set_view(view)
|
59
|
+
view.create.show
|
60
|
+
end
|
61
|
+
|
62
|
+
# метод, который получает выбранный элемент из state_notifier, удаляет его из базы данных и из state_notifier
|
63
|
+
def delete_selected(current_page, per_page, selected_row)
|
64
|
+
LoggerHolder.instance.debug('UserListController: delete_selected')
|
65
|
+
begin
|
66
|
+
item = @state_notifier.get(selected_row)
|
67
|
+
@user_rep.delete(item.user_id)
|
68
|
+
@state_notifier.delete(item)
|
69
|
+
rescue
|
70
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
71
|
+
api.call(0, "You cannot delete the user because he is associated with some book", "Error", 0)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# етод, который получает список авторов из базы данных, устанавливает их в state_notifier и обновляет пользовательский интерфейс
|
76
|
+
def refresh_data(page, per_page)
|
77
|
+
items = @user_rep.get_list(per_page, page, @sort_by, 'ASC', @father_name_filter)
|
78
|
+
@state_notifier.set_all(items)
|
79
|
+
@view.update_student_count(@user_rep.count)
|
80
|
+
end
|
81
|
+
|
82
|
+
def sort(page, per_page, sort_index)
|
83
|
+
@sort_by = @sort_columns[sort_index]
|
84
|
+
refresh_data(page, per_page)
|
85
|
+
end
|
86
|
+
|
87
|
+
def filter_father_name(page, per_page, filter_index)
|
88
|
+
@father_name_filter = @father_name_filter_columns[filter_index]
|
89
|
+
refresh_data(page, per_page)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def on_db_conn_error
|
95
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
96
|
+
api.call(0, "No connection to DB", "Error", 0)
|
97
|
+
exit(false)
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative '../controllers/user_input_form_controller_create'
|
5
|
+
require './lib/models/user'
|
6
|
+
require 'win32api'
|
7
|
+
|
8
|
+
class UserInputForm
|
9
|
+
include Glimmer
|
10
|
+
|
11
|
+
def initialize(controller, existing_student = nil)
|
12
|
+
@item = existing_student.to_hash unless existing_student.nil?
|
13
|
+
@controller = controller
|
14
|
+
@entries = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_create
|
18
|
+
@controller.on_view_created
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@root_container = window('Пользователь', 300, 70) {
|
23
|
+
resizable false
|
24
|
+
|
25
|
+
vertical_box {
|
26
|
+
@student_form = form {
|
27
|
+
stretchy false
|
28
|
+
|
29
|
+
fields = [[:first_name, 'Имя Пользователя'], [:last_name, 'Фамилия Пользователя'], [:father_name, 'Отчество пользователя']]
|
30
|
+
|
31
|
+
fields.each do |field|
|
32
|
+
@entries[field[0]] = entry {
|
33
|
+
label field[1]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
button('Сохранить') {
|
39
|
+
stretchy false
|
40
|
+
|
41
|
+
on_clicked {
|
42
|
+
values = @entries.transform_values { |v| v.text.force_encoding("utf-8").strip }
|
43
|
+
values.transform_values! { |v| v.empty? ? nil : v}
|
44
|
+
|
45
|
+
@controller.process_fields(values)
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
on_create
|
51
|
+
@root_container
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_value(field, value)
|
55
|
+
return unless @entries.include?(field)
|
56
|
+
print value.class
|
57
|
+
@entries[field].text = value
|
58
|
+
end
|
59
|
+
|
60
|
+
def make_readonly(*fields)
|
61
|
+
fields.each do |field|
|
62
|
+
@entries[field].read_only = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def close
|
67
|
+
@root_container.destroy
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative '../controllers/user_list_controller'
|
5
|
+
require_relative 'user_input_form'
|
6
|
+
|
7
|
+
class UserListView
|
8
|
+
include Glimmer
|
9
|
+
|
10
|
+
PAGE_SIZE = 20
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@controller = UserListController.new(self)
|
14
|
+
@current_page = 1
|
15
|
+
@total_count = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_create
|
19
|
+
@controller.on_view_created
|
20
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Метод наблюдателя datalist
|
24
|
+
# def on_datalist_changed(new_table)
|
25
|
+
# arr = new_table.to_2d_array
|
26
|
+
# arr.map do |row|
|
27
|
+
# row[3] = [row[3][:value], contact_color(row[3][:type])] unless row[3].nil?
|
28
|
+
# end
|
29
|
+
# @table.model_array = arr
|
30
|
+
# end
|
31
|
+
|
32
|
+
def update(users)
|
33
|
+
@items = []
|
34
|
+
|
35
|
+
i = 0
|
36
|
+
item_num = 0
|
37
|
+
users.each do |user|
|
38
|
+
i += 1
|
39
|
+
item_num = ((@current_page - 1) * PAGE_SIZE) + i
|
40
|
+
print("USERid=#{user.user_id}")
|
41
|
+
@items << Struct.new(:№, :id, :имя_пользователя, :фамилия_пользователя, :отчество_пользователя).new(item_num, user.user_id, user.first_name, user.last_name, user.father_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
@table.model_array = @items
|
45
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def update_student_count(new_cnt)
|
49
|
+
@total_count = new_cnt
|
50
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def create
|
54
|
+
|
55
|
+
root_container = horizontal_box {
|
56
|
+
# Секция 1
|
57
|
+
vertical_box {
|
58
|
+
stretchy false
|
59
|
+
|
60
|
+
vertical_box {
|
61
|
+
stretchy false
|
62
|
+
|
63
|
+
label {
|
64
|
+
text 'Отчество'
|
65
|
+
}
|
66
|
+
combobox { |c|
|
67
|
+
items ['Не важно','Есть','Нет']
|
68
|
+
selected 0
|
69
|
+
on_selected do
|
70
|
+
@controller.filter_father_name(@current_page, PAGE_SIZE, c.selected)
|
71
|
+
end
|
72
|
+
}
|
73
|
+
|
74
|
+
label {
|
75
|
+
text 'Сортировка'
|
76
|
+
}
|
77
|
+
combobox { |c|
|
78
|
+
items ['ID', 'Имя пользователя', 'Фамилия пользователя', 'Отчество пользователя']
|
79
|
+
selected 0
|
80
|
+
on_selected do
|
81
|
+
@controller.sort(@current_page, PAGE_SIZE, c.selected)
|
82
|
+
end
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
}
|
88
|
+
|
89
|
+
# Секция 2
|
90
|
+
vertical_box {
|
91
|
+
@table = refined_table(
|
92
|
+
table_editable: false,
|
93
|
+
filter: lambda do |row_hash, query|
|
94
|
+
utf8_query = query.force_encoding("utf-8")
|
95
|
+
row_hash['Имя пользователя'].include?(utf8_query)
|
96
|
+
end,
|
97
|
+
table_columns: {
|
98
|
+
'№' => :text,
|
99
|
+
'ID' => :text,
|
100
|
+
'Имя пользователя' => :text,
|
101
|
+
'Фамилия пользователя' => :text,
|
102
|
+
'Отчество пользователя' => :text,
|
103
|
+
},
|
104
|
+
per_page: PAGE_SIZE,
|
105
|
+
|
106
|
+
)
|
107
|
+
|
108
|
+
@pages = horizontal_box {
|
109
|
+
stretchy false
|
110
|
+
|
111
|
+
button("<") {
|
112
|
+
stretchy true
|
113
|
+
|
114
|
+
on_clicked do
|
115
|
+
@current_page = [@current_page - 1, 1].max
|
116
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
117
|
+
end
|
118
|
+
|
119
|
+
}
|
120
|
+
@page_label = label("...") { stretchy false }
|
121
|
+
button(">") {
|
122
|
+
stretchy true
|
123
|
+
|
124
|
+
on_clicked do
|
125
|
+
@current_page = [@current_page + 1, (@total_count / PAGE_SIZE.to_f).ceil].min
|
126
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
127
|
+
end
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
# Секция 3
|
133
|
+
vertical_box {
|
134
|
+
stretchy false
|
135
|
+
|
136
|
+
button('Добавить') {
|
137
|
+
stretchy false
|
138
|
+
|
139
|
+
on_clicked {
|
140
|
+
@controller.show_modal_add
|
141
|
+
}
|
142
|
+
}
|
143
|
+
button('Изменить') {
|
144
|
+
stretchy false
|
145
|
+
|
146
|
+
on_clicked {
|
147
|
+
@controller.show_modal_edit(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
148
|
+
}
|
149
|
+
}
|
150
|
+
button('Удалить') {
|
151
|
+
stretchy false
|
152
|
+
|
153
|
+
on_clicked {
|
154
|
+
@controller.delete_selected(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
155
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
156
|
+
}
|
157
|
+
}
|
158
|
+
button('Обновить') {
|
159
|
+
stretchy false
|
160
|
+
|
161
|
+
on_clicked {
|
162
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
on_create
|
168
|
+
root_container
|
169
|
+
end
|
170
|
+
end
|