starproxima_library 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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +69 -0
  4. data/diagrams/add_uthor_seq.png +0 -0
  5. data/diagrams/add_uthor_seq.puml +42 -0
  6. data/diagrams/author.png +0 -0
  7. data/diagrams/author.puml +118 -0
  8. data/diagrams/core.png +0 -0
  9. data/diagrams/core.puml +103 -0
  10. data/diagrams/delete_author.png +0 -0
  11. data/diagrams/delete_author.puml +25 -0
  12. data/diagrams/edit_author.png +0 -0
  13. data/diagrams/edit_author.puml +48 -0
  14. data/diagrams/er.png +0 -0
  15. data/diagrams/er.puml +30 -0
  16. data/diagrams/publisher.png +0 -0
  17. data/diagrams/publisher.puml +118 -0
  18. data/diagrams/requirements.docx +0 -0
  19. data/diagrams/start.png +0 -0
  20. data/diagrams/start.puml +74 -0
  21. data/lib/author/author_db_data_source.rb +90 -0
  22. data/lib/author/controllers/author_controller.rb +57 -0
  23. data/lib/author/controllers/author_input_form_controller_create.rb +44 -0
  24. data/lib/author/controllers/author_input_form_controller_edit.rb +53 -0
  25. data/lib/author/controllers/author_list_controller.rb +107 -0
  26. data/lib/author/ui/author_input_form.rb +69 -0
  27. data/lib/author/ui/author_list_view.rb +170 -0
  28. data/lib/controllers/tab_students_controller.rb +43 -0
  29. data/lib/data_sources/book_db_data_source.rb +43 -0
  30. data/lib/data_sources/db_client.rb +34 -0
  31. data/lib/db_config/config.yaml +5 -0
  32. data/lib/db_config/library_config.yaml +5 -0
  33. data/lib/db_config/migrations/create_db.sql +3 -0
  34. data/lib/db_config/migrations/create_tables.sql +27 -0
  35. data/lib/db_config/mock_data/mock_data.sql +49 -0
  36. data/lib/logger.rb +27 -0
  37. data/lib/main.rb +6 -0
  38. data/lib/models/author.rb +32 -0
  39. data/lib/models/book.rb +31 -0
  40. data/lib/models/publisher.rb +37 -0
  41. data/lib/models/student.rb +102 -0
  42. data/lib/models/student_base.rb +100 -0
  43. data/lib/models/student_short.rb +50 -0
  44. data/lib/publisher/controllers/publisher_input_form_controller_create.rb +44 -0
  45. data/lib/publisher/controllers/publisher_input_form_controller_edit.rb +52 -0
  46. data/lib/publisher/controllers/publisher_list_controller.rb +99 -0
  47. data/lib/publisher/publisher_db_data_source.rb +63 -0
  48. data/lib/publisher/ui/publisher_input_form.rb +69 -0
  49. data/lib/publisher/ui/publisher_list_view.rb +168 -0
  50. data/lib/repositories/adapters/db_source_adapter.rb +54 -0
  51. data/lib/repositories/adapters/file_source_adapter.rb +37 -0
  52. data/lib/repositories/containers/data_list.rb +74 -0
  53. data/lib/repositories/containers/data_list_student_short.rb +18 -0
  54. data/lib/repositories/containers/data_table.rb +35 -0
  55. data/lib/repositories/data_sources/db_data_source.rb +32 -0
  56. data/lib/repositories/data_sources/file_data_source.rb +75 -0
  57. data/lib/repositories/data_sources/transformers/data_transformer_base.rb +15 -0
  58. data/lib/repositories/data_sources/transformers/data_transformer_json.rb +16 -0
  59. data/lib/repositories/data_sources/transformers/data_transformer_yaml.rb +16 -0
  60. data/lib/repositories/student_repository.rb +32 -0
  61. data/lib/state_holders/list_state_notifier.rb +60 -0
  62. data/lib/views/main_window.rb +32 -0
  63. data/lib/views/tab_students.rb +148 -0
  64. data/starproxima_library.gemspec +15 -0
  65. data/test/author_test.rb +51 -0
  66. data/test/book_test.rb +33 -0
  67. data/test/publisher_test.rb +39 -0
  68. data/test/state_notifier_test.rb +80 -0
  69. metadata +123 -0
@@ -0,0 +1,90 @@
1
+ require 'mysql2'
2
+ require_relative '../data_sources/db_client'
3
+
4
+ class AuthorDBDataSource
5
+ def initialize
6
+ @client = DBClient.instance
7
+ end
8
+
9
+ # def add(author)
10
+ # query = "INSERT INTO Author (FirstName, LastName, FatherName) VALUES ('#{author.first_name}', '#{author.last_name}', #{author.father_name.nil? ? 'NULL' : "'#{author.father_name}'"})"
11
+ # @client.query(query)
12
+ # end
13
+
14
+
15
+
16
+ # добавляет нового автора в базу данных, возвращает созданную запись.
17
+ def add(author)
18
+ query = "INSERT INTO Author (FirstName, LastName, FatherName) VALUES ('#{author.first_name}', '#{author.last_name}', #{author.father_name.nil? ? 'NULL' : "'#{author.father_name}'"})"
19
+ @client.query(query)
20
+ author_id = @client.last_id
21
+ get(author_id)
22
+ end
23
+
24
+ # изменяет данные об авторе в базе данных, возвращает измененную запись.
25
+ def change(author)
26
+ query = "UPDATE Author SET FirstName='#{author.first_name}', LastName='#{author.last_name}', FatherName=#{author.father_name.nil? ? 'NULL' : "'#{author.father_name}'"} WHERE AuthorID=#{author.author_id}"
27
+ @client.query(query)
28
+ get(author.author_id)
29
+ end
30
+
31
+ # удаляет запись об авторе из базы данных.
32
+ def delete(id)
33
+ query = "DELETE FROM Author WHERE AuthorID=#{id}"
34
+ @client.query(query)
35
+ end
36
+
37
+ # возвращает запись об авторе по заданному id.
38
+ def get(id)
39
+ query = "SELECT * FROM Author WHERE AuthorID=#{id}"
40
+ result = @client.query(query).first
41
+ if result
42
+ Author.new(result[:'AuthorID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
43
+ else
44
+ nil
45
+ end
46
+ end
47
+
48
+ # def get_list(page_size, page_num, sort_field, sort_direction)
49
+ # offset = (page_num - 1) * page_size
50
+ # query = "SELECT * FROM Author ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
51
+ # results = @client.query(query)
52
+ #
53
+ # authors = []
54
+ # results.each do |result|
55
+ # authors << Author.new(result[:'AuthorID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
56
+ # end
57
+ #
58
+ # authors
59
+ # end
60
+
61
+ # возвращает список авторов с учетом фильтра по наличию отчества и сортировки, позволяет задавать количество элементов на странице и номер страницы.
62
+ def get_list(page_size, page_num, sort_field, sort_direction, has_father_name = nil)
63
+ offset = (page_num - 1) * page_size
64
+ query = "SELECT * FROM Author"
65
+
66
+ if has_father_name == true
67
+ query += " WHERE FatherName IS NOT NULL"
68
+ elsif has_father_name == false
69
+ query += " WHERE FatherName IS NULL"
70
+ end
71
+
72
+ query += " ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
73
+ results = @client.query(query)
74
+
75
+ authors = []
76
+ results.each do |result|
77
+ authors << Author.new(result[:'AuthorID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
78
+ end
79
+
80
+ authors
81
+ end
82
+
83
+ # возвращает количество записей об авторах в базе данных.
84
+ def count
85
+ query = "SELECT COUNT(*) FROM Author"
86
+ result = @client.query(query).first
87
+
88
+ result[:'COUNT(*)']
89
+ end
90
+ end
@@ -0,0 +1,57 @@
1
+ # # frozen_string_literal: true
2
+ #
3
+ # require './lib/views/main_window'
4
+ # require './lib/repositories/student_repository'
5
+ # require './lib/repositories/adapters/db_source_adapter'
6
+ # require './lib/repositories/containers/data_list_student_short'
7
+ # require './lib/state_holders/list_state_notifier'
8
+ # require_relative '../author_db_data_source'
9
+ # require 'win32api'
10
+ #
11
+ # class AuthorController
12
+ #
13
+ #
14
+ # def initialize(view)
15
+ # @view = view
16
+ # @state_notifier = ListStateNotifier.new
17
+ # @state_notifier.add_listener(@view)
18
+ # @author_rep = AuthorDBDataSource.new
19
+ # end
20
+ #
21
+ # def edit (number)
22
+ # author = @state_notifier.get(number)
23
+ # puts author.id
24
+ # # @view.show_edit_dialog(author)
25
+ # end
26
+ #
27
+ # def add (number)
28
+ # author = @state_notifier.get(number)
29
+ # puts author
30
+ # # @view.show_add_dialog(author)
31
+ # end
32
+ #
33
+ #
34
+ # def remove (number)
35
+ # author = @state_notifier.get(number)
36
+ # puts author
37
+ # # @view.show_remove_dialog(author)
38
+ # end
39
+ #
40
+ # def refresh_data(page, per_page)
41
+ # items = @author_rep.get_list(per_page, page, 'FirstName', 'ASC' )
42
+ # @state_notifier.set_all(items)
43
+ # @view.update_student_count(@author_rep.count)
44
+ # end
45
+ #
46
+ # def refresh()
47
+ # items = @author_rep.get_list(per_page, page, 'FirstName', 'ASC' )
48
+ # @state_notifier.set_all(items)
49
+ # @view.update_student_count(@author_rep.count)
50
+ # end
51
+ #
52
+ # def on_db_conn_error
53
+ # api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
54
+ # api.call(0, "No connection to DB", "Error", 0)
55
+ # exit(false)
56
+ # end
57
+ # end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'win32api'
4
+
5
+ class AuthorInputFormControllerCreate
6
+ def initialize(parent_controller)
7
+ @parent_controller = parent_controller
8
+ @author_rep = AuthorDBDataSource.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
+ puts fields
26
+ item = Author.new(-1, *fields.values)
27
+ puts item
28
+ item = @author_rep.add(item)
29
+ @parent_controller.state_notifier.add(item)
30
+ @view.close
31
+ rescue ArgumentError => e
32
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
33
+ api.call(0, e.message, 'Error', 0)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def on_db_conn_error
40
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
41
+ api.call(0, "No connection to DB", "Error", 0)
42
+ @view.close
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'win32api'
4
+
5
+ class AuthorInputFormControllerEdit
6
+ def initialize(parent_controller, item)
7
+ @parent_controller = parent_controller
8
+ @item = item
9
+ @author_rep = AuthorDBDataSource.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 = Author.new(@item.author_id, *fields.values)
37
+ item = @author_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,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/state_holders/list_state_notifier'
4
+ require_relative '../ui/author_input_form'
5
+ require_relative 'author_input_form_controller_create'
6
+ require_relative 'author_input_form_controller_edit'
7
+ require_relative '../author_db_data_source'
8
+ require 'win32api'
9
+
10
+ # Класс AuthorListController отвечает за управление списком
11
+ # авторов, используя различные методы для обновления данных и
12
+ # взаимодействия с пользовательским интерфейсом.
13
+ class AuthorListController
14
+
15
+ attr_reader :state_notifier;
16
+
17
+ def initialize(view)
18
+ LoggerHolder.instance.debug('AuthorListController: initialize')
19
+ @view = view
20
+ @state_notifier = ListStateNotifier.new
21
+ @state_notifier.add_listener(@view)
22
+ @author_rep = AuthorDBDataSource.new
23
+
24
+ @sort_columns = %w[AuthorID 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('AuthorListController: show_modal_add')
45
+ controller = AuthorInputFormControllerCreate.new(self)
46
+ view = AuthorInputForm.new(controller)
47
+ controller.set_view(view)
48
+ view.create.show
49
+ end
50
+
51
+ # метод, который создает контроллер AuthorInputFormControllerEdit, представление AuthorInputForm, устанавливает связи между ними и показывает модальное окно.
52
+ def show_modal_edit(current_page, per_page, selected_row)
53
+ LoggerHolder.instance.debug('AuthorListController: show_modal_edit')
54
+ # item_num = (current_page - 1) * per_page + selected_row
55
+
56
+ item = @state_notifier.get(selected_row)
57
+
58
+ controller = AuthorInputFormControllerEdit.new(self, item)
59
+ view = AuthorInputForm.new(controller)
60
+ controller.set_view(view)
61
+ view.create.show
62
+ end
63
+
64
+ # метод, который получает выбранный элемент из state_notifier, удаляет его из базы данных и из state_notifier
65
+ def delete_selected(current_page, per_page, selected_row)
66
+ LoggerHolder.instance.debug('AuthorListController: delete_selected')
67
+ begin
68
+ item = @state_notifier.get(selected_row)
69
+ @author_rep.delete(item.author_id)
70
+ @state_notifier.delete(item)
71
+ rescue
72
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
73
+ api.call(0, "You cannot delete the author because he is associated with some book", "Error", 0)
74
+ end
75
+ end
76
+
77
+ # етод, который получает список авторов из базы данных, устанавливает их в state_notifier и обновляет пользовательский интерфейс
78
+ def refresh_data(page, per_page)
79
+ # begin
80
+ # @data_list = @student_rep.paginated_short_students(page, per_page, @data_list)
81
+ # @view.update_student_count(@student_rep.student_count)
82
+ # rescue
83
+ # on_db_conn_error
84
+ # end
85
+ items = @author_rep.get_list(per_page, page, @sort_by, 'ASC', @father_name_filter)
86
+ @state_notifier.set_all(items)
87
+ @view.update_student_count(@author_rep.count)
88
+ end
89
+
90
+ def sort(page, per_page, sort_index)
91
+ @sort_by = @sort_columns[sort_index]
92
+ refresh_data(page, per_page)
93
+ end
94
+
95
+ def filter_father_name(page, per_page, filter_index)
96
+ @father_name_filter = @father_name_filter_columns[filter_index]
97
+ refresh_data(page, per_page)
98
+ end
99
+
100
+ private
101
+
102
+ def on_db_conn_error
103
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
104
+ api.call(0, "No connection to DB", "Error", 0)
105
+ exit(false)
106
+ end
107
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+ require_relative '../controllers/author_input_form_controller_create'
5
+ require './lib/models/author'
6
+ require 'win32api'
7
+
8
+ class AuthorInputForm
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
+
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/author_list_controller'
5
+ require_relative '../controllers/author_controller'
6
+ require_relative 'author_input_form'
7
+
8
+ class AuthorListView
9
+ include Glimmer
10
+
11
+ PAGE_SIZE = 20
12
+
13
+ def initialize
14
+ @controller = AuthorListController.new(self)
15
+ @current_page = 1
16
+ @total_count = 0
17
+ end
18
+
19
+ def on_create
20
+ @controller.on_view_created
21
+ @controller.refresh_data(@current_page, PAGE_SIZE)
22
+ end
23
+
24
+ # Метод наблюдателя datalist
25
+ # def on_datalist_changed(new_table)
26
+ # arr = new_table.to_2d_array
27
+ # arr.map do |row|
28
+ # row[3] = [row[3][:value], contact_color(row[3][:type])] unless row[3].nil?
29
+ # end
30
+ # @table.model_array = arr
31
+ # end
32
+
33
+ def update(authors)
34
+ @items = []
35
+
36
+ i = 0
37
+ item_num = 0
38
+ authors.each do |author|
39
+ i += 1
40
+ item_num = ((@current_page - 1) * PAGE_SIZE) + i
41
+ @items << Struct.new(:№, :id, :имя_автора, :фамилия_автора, :отчество_автора).new(item_num, author.author_id, author.first_name, author.last_name, author.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
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/views/main_window'
4
+ require './lib/repositories/student_repository'
5
+ require './lib/repositories/adapters/db_source_adapter'
6
+ require './lib/repositories/containers/data_list_student_short'
7
+ require 'win32api'
8
+
9
+ class TabStudentsController
10
+ def initialize(view)
11
+ @view = view
12
+ @data_list = DataListStudentShort.new([])
13
+ @data_list.add_listener(@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
+ end
23
+
24
+ def show_view
25
+ @view.create.show
26
+ end
27
+
28
+ def refresh_data(page, per_page)
29
+ begin
30
+ @data_list = @student_rep.paginated_short_students(page, per_page, @data_list)
31
+ @view.update_student_count(@student_rep.student_count)
32
+ rescue
33
+ on_db_conn_error
34
+ end
35
+ end
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
+ # TODO: Возможность переключения на JSON помимо exit
41
+ exit(false)
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ require 'mysql2'
2
+ require_relative 'db_client'
3
+ class BookDBDataSource
4
+ def initialize
5
+ @client = DBClient.instance
6
+ end
7
+
8
+ def add(book)
9
+ query = "INSERT INTO Book (BookID, Title, AuthorID, PublisherID) VALUES (#{book.id}, '#{book.title}', #{book.author_id}, #{book.publisher_id})"
10
+ @client.query(query)
11
+ end
12
+
13
+ def change(book)
14
+ query = "UPDATE Book SET Title='#{book.title}', AuthorID=#{book.author_id}, PublisherID=#{book.publisher_id} WHERE BookID=#{book.id}"
15
+ @client.query(query)
16
+ end
17
+
18
+ def delete(id)
19
+ query = "DELETE FROM Book WHERE BookID=#{id}"
20
+ @client.query(query)
21
+ end
22
+
23
+ def get(id)
24
+ query = "SELECT * FROM Book WHERE BookID=#{id}"
25
+ result = @client.query(query).first
26
+ if result
27
+ Book.new(result['BookID'], result['Title'], result['AuthorID'], result['PublisherID'])
28
+ else
29
+ nil
30
+ end
31
+ end
32
+
33
+ def get_list(page_size, page_num, sort_field, sort_direction)
34
+ offset = (page_num - 1) * page_size
35
+ query = "SELECT * FROM Book ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
36
+ results = @client.query(query)
37
+ books = []
38
+ results.each do |result|
39
+ books << Book.new(result['BookID'], result['Title'], result['AuthorID'], result['PublisherID'])
40
+ end
41
+ books
42
+ end
43
+ end