api_maker 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/app/api_maker/api_helpers/api_maker_helpers.rb +5 -0
  3. data/app/api_maker/services/can_can/load_abilities.rb +30 -0
  4. data/app/api_maker/services/devise/sign_in.rb +64 -0
  5. data/app/api_maker/services/devise/sign_out.rb +9 -0
  6. data/app/api_maker/services/models/find_or_create_by.rb +18 -0
  7. data/app/channels/api_maker/subscriptions_channel.rb +33 -2
  8. data/app/controllers/api_maker/base_controller.rb +7 -3
  9. data/app/controllers/api_maker/commands_controller.rb +26 -4
  10. data/app/controllers/api_maker/session_statuses_controller.rb +1 -1
  11. data/app/services/api_maker/abilities_loader.rb +104 -0
  12. data/app/services/api_maker/application_service.rb +2 -1
  13. data/app/services/api_maker/base_command.rb +248 -0
  14. data/app/services/api_maker/collection_command_service.rb +29 -15
  15. data/app/services/api_maker/collection_loader.rb +124 -0
  16. data/app/services/api_maker/command_failed_error.rb +3 -0
  17. data/app/services/api_maker/command_response.rb +17 -6
  18. data/app/services/api_maker/command_service.rb +3 -3
  19. data/app/services/api_maker/create_command.rb +11 -26
  20. data/app/services/api_maker/create_command_service.rb +3 -3
  21. data/app/services/api_maker/database_type.rb +9 -0
  22. data/app/services/api_maker/deep_merge_params.rb +26 -0
  23. data/app/services/api_maker/deserializer.rb +35 -0
  24. data/app/services/api_maker/destroy_command.rb +15 -21
  25. data/app/services/api_maker/destroy_command_service.rb +3 -3
  26. data/app/services/api_maker/generate_react_native_api_service.rb +3 -19
  27. data/app/services/api_maker/include_helpers.rb +17 -0
  28. data/app/services/api_maker/index_command.rb +8 -88
  29. data/app/services/api_maker/index_command_service.rb +5 -5
  30. data/app/services/api_maker/js_method_namer_service.rb +1 -1
  31. data/app/services/api_maker/locals_from_controller.rb +14 -0
  32. data/app/services/api_maker/member_command_service.rb +15 -13
  33. data/app/services/api_maker/model_classes_java_script_generator_service.rb +37 -0
  34. data/app/services/api_maker/model_content_generator_service.rb +17 -21
  35. data/app/services/api_maker/models/save.rb +29 -0
  36. data/app/services/api_maker/models_finder_service.rb +6 -2
  37. data/app/services/api_maker/models_generator_service.rb +6 -43
  38. data/app/services/api_maker/move_components_to_routes.rb +50 -0
  39. data/app/services/api_maker/primary_id_for_model.rb +6 -0
  40. data/app/services/api_maker/reset_indexed_db_service.rb +36 -0
  41. data/app/services/api_maker/routes_file_reloader.rb +20 -0
  42. data/app/services/api_maker/select_columns_on_collection.rb +78 -0
  43. data/app/services/api_maker/select_parser.rb +32 -0
  44. data/app/services/api_maker/service_command.rb +27 -0
  45. data/app/services/api_maker/service_command_service.rb +14 -0
  46. data/app/services/api_maker/simple_model_errors.rb +52 -0
  47. data/app/services/api_maker/update_command.rb +8 -24
  48. data/app/services/api_maker/update_command_service.rb +3 -3
  49. data/app/services/api_maker/valid_command.rb +4 -13
  50. data/app/services/api_maker/valid_command_service.rb +3 -3
  51. data/app/services/api_maker/validation_errors_generator_service.rb +146 -0
  52. data/app/views/api_maker/_data.html.erb +17 -11
  53. data/config/routes.rb +0 -2
  54. data/lib/api_maker/ability.rb +22 -7
  55. data/lib/api_maker/ability_loader.rb +9 -6
  56. data/lib/api_maker/base_collection_instance.rb +15 -0
  57. data/lib/api_maker/base_resource.rb +135 -9
  58. data/lib/api_maker/base_service.rb +14 -0
  59. data/lib/api_maker/collection_serializer.rb +95 -34
  60. data/lib/api_maker/command_spec_helper.rb +41 -11
  61. data/lib/api_maker/configuration.rb +31 -4
  62. data/lib/api_maker/expect_to_able_to_helper.rb +31 -0
  63. data/lib/api_maker/individual_command.rb +24 -9
  64. data/lib/api_maker/javascript/model-template.js.erb +39 -25
  65. data/lib/api_maker/javascript/models.js.erb +6 -0
  66. data/lib/api_maker/loader.rb +1 -1
  67. data/lib/api_maker/memory_storage.rb +1 -1
  68. data/lib/api_maker/model_extensions.rb +34 -18
  69. data/lib/api_maker/permitted_params_argument.rb +5 -1
  70. data/lib/api_maker/preloader.rb +71 -32
  71. data/lib/api_maker/preloader_base.rb +108 -0
  72. data/lib/api_maker/preloader_belongs_to.rb +34 -33
  73. data/lib/api_maker/preloader_has_many.rb +45 -39
  74. data/lib/api_maker/preloader_has_one.rb +30 -47
  75. data/lib/api_maker/railtie.rb +3 -11
  76. data/lib/api_maker/relationship_preloader.rb +42 -0
  77. data/lib/api_maker/resource_routing.rb +18 -4
  78. data/lib/api_maker/result_parser.rb +34 -20
  79. data/lib/api_maker/serializer.rb +53 -22
  80. data/lib/api_maker/spec_helper/browser_logs.rb +14 -0
  81. data/lib/api_maker/spec_helper/execute_collection_command.rb +46 -0
  82. data/lib/api_maker/spec_helper/execute_member_command.rb +52 -0
  83. data/lib/api_maker/spec_helper/expect_no_browser_errors.rb +18 -0
  84. data/lib/api_maker/spec_helper/wait_for_expect.rb +20 -0
  85. data/lib/api_maker/spec_helper/wait_for_flash_message.rb +21 -0
  86. data/lib/api_maker/spec_helper.rb +112 -48
  87. data/lib/api_maker/version.rb +1 -1
  88. data/lib/api_maker.rb +7 -3
  89. metadata +108 -89
  90. data/README.md +0 -476
  91. data/app/controllers/api_maker/devise_controller.rb +0 -60
  92. data/lib/api_maker/base_command.rb +0 -81
  93. data/lib/api_maker/javascript/api.js +0 -92
  94. data/lib/api_maker/javascript/base-model.js +0 -543
  95. data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +0 -16
  96. data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +0 -47
  97. data/lib/api_maker/javascript/bootstrap/card.jsx +0 -79
  98. data/lib/api_maker/javascript/bootstrap/checkbox.jsx +0 -127
  99. data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +0 -105
  100. data/lib/api_maker/javascript/bootstrap/live-table.jsx +0 -168
  101. data/lib/api_maker/javascript/bootstrap/money-input.jsx +0 -136
  102. data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +0 -80
  103. data/lib/api_maker/javascript/bootstrap/select.jsx +0 -168
  104. data/lib/api_maker/javascript/bootstrap/string-input.jsx +0 -203
  105. data/lib/api_maker/javascript/cable-connection-pool.js +0 -169
  106. data/lib/api_maker/javascript/cable-subscription-pool.js +0 -111
  107. data/lib/api_maker/javascript/cable-subscription.js +0 -33
  108. data/lib/api_maker/javascript/collection.js +0 -186
  109. data/lib/api_maker/javascript/commands-pool.js +0 -123
  110. data/lib/api_maker/javascript/custom-error.js +0 -14
  111. data/lib/api_maker/javascript/deserializer.js +0 -35
  112. data/lib/api_maker/javascript/devise.js.erb +0 -113
  113. data/lib/api_maker/javascript/error-logger.js +0 -119
  114. data/lib/api_maker/javascript/event-connection.jsx +0 -24
  115. data/lib/api_maker/javascript/event-created.jsx +0 -26
  116. data/lib/api_maker/javascript/event-destroyed.jsx +0 -26
  117. data/lib/api_maker/javascript/event-emitter-listener.jsx +0 -32
  118. data/lib/api_maker/javascript/event-listener.jsx +0 -41
  119. data/lib/api_maker/javascript/event-updated.jsx +0 -26
  120. data/lib/api_maker/javascript/form-data-to-object.js +0 -70
  121. data/lib/api_maker/javascript/included.js +0 -39
  122. data/lib/api_maker/javascript/key-value-store.js +0 -47
  123. data/lib/api_maker/javascript/logger.js +0 -23
  124. data/lib/api_maker/javascript/model-name.js +0 -21
  125. data/lib/api_maker/javascript/models-response-reader.js +0 -43
  126. data/lib/api_maker/javascript/paginate.jsx +0 -128
  127. data/lib/api_maker/javascript/params.js +0 -68
  128. data/lib/api_maker/javascript/resource-route.jsx +0 -75
  129. data/lib/api_maker/javascript/resource-routes.jsx +0 -36
  130. data/lib/api_maker/javascript/result.js +0 -25
  131. data/lib/api_maker/javascript/session-status-updater.js +0 -113
  132. data/lib/api_maker/javascript/sort-link.jsx +0 -88
  133. data/lib/api_maker/javascript/updated-attribute.jsx +0 -60
  134. data/lib/api_maker/preloader_through.rb +0 -101
  135. data/lib/api_maker/relationship_includer.rb +0 -42
@@ -1,168 +0,0 @@
1
- import PropTypes from "prop-types"
2
- import PropTypesExact from "prop-types-exact"
3
- import React from "react"
4
-
5
- const inflection = require("inflection")
6
-
7
- export default class BootstrapSelect extends React.Component {
8
- static propTypes = PropTypesExact({
9
- attribute: PropTypes.string,
10
- children: PropTypes.node,
11
- className: PropTypes.string,
12
- "data-controller": PropTypes.string,
13
- defaultValue: PropTypes.oneOfType([PropTypes.array, PropTypes.number, PropTypes.string]),
14
- description: PropTypes.node,
15
- disabled: PropTypes.bool,
16
- id: PropTypes.string,
17
- includeBlank: PropTypes.bool,
18
- hideSearch: PropTypes.bool,
19
- hint: PropTypes.node,
20
- hintBottom: PropTypes.node,
21
- label: PropTypes.node,
22
- labelContainerClassName: PropTypes.string,
23
- model: PropTypes.object,
24
- multiple: PropTypes.bool,
25
- name: PropTypes.string,
26
- placeholder: PropTypes.string,
27
- onChange: PropTypes.func,
28
- options: PropTypes.array,
29
- select2: PropTypes.bool,
30
- wrapperClassName: PropTypes.string,
31
- })
32
-
33
- componentDidMount() {
34
- if (this.props.select2 && this.props.onChange)
35
- $(this.refs.select).on("change", this.props.onChange)
36
-
37
- // Set default value to nothing when multiple
38
- if (this.props.select2 && this.props.multiple && !this.inputDefaultValue())
39
- $(this.refs.select).val("")
40
- }
41
-
42
- componentWillUnmount() {
43
- if (this.props.select2 && this.props.onChange)
44
- $(this.refs.select).off("change", this.props.onChange)
45
- }
46
-
47
- render() {
48
- return (
49
- <div className={this.wrapperClassName()}>
50
- {this.label() &&
51
- <div className={this.props.labelContainerClassName ? this.props.labelContainerClassName : null}>
52
- <label className={this.labelClassName()} htmlFor={this.inputId()}>
53
- {this.label()}
54
- </label>
55
- </div>
56
- }
57
- {this.props.description &&
58
- <div className="mb-4">
59
- {this.props.description}
60
- </div>
61
- }
62
- {this.props.hint &&
63
- <span className="form-text text-muted font-smoothing font-xs">
64
- {this.props.hint}
65
- </span>
66
- }
67
- <select
68
- data-controller={this.dataController()}
69
- data-hide-search={this.props.hideSearch}
70
- data-placeholder={this.props.placeholder}
71
- defaultValue={this.inputDefaultValue()}
72
- className={`form-control ${this.props.className}`}
73
- disabled={this.props.disabled}
74
- id={this.inputId()}
75
- multiple={this.props.multiple}
76
- name={this.inputName()}
77
- onChange={this.props.onChange}
78
- ref="select"
79
- >
80
- {this.includeBlank() &&
81
- <option />
82
- }
83
- {this.props.options && this.props.options.map(option => (
84
- <option key={`select-option-${option[1]}`} value={option[1]}>{option[0]}</option>
85
- ))}
86
- {this.props.children}
87
- </select>
88
- {this.props.hintBottom &&
89
- <span className="form-text text-muted font-smoothing font-xs">
90
- {this.props.hintBottom}
91
- </span>
92
- }
93
- </div>
94
- )
95
- }
96
-
97
- dataController() {
98
- if ("data-controller" in this.props) {
99
- return this.props["data-controller"]
100
- } else if (this.props.select2) {
101
- return "select2--default"
102
- }
103
- }
104
-
105
- includeBlank() {
106
- if (this.props.includeBlank || (this.props.placeholder && !this.props.multiple)) {
107
- return true
108
- } else {
109
- return false
110
- }
111
- }
112
-
113
- inputDefaultValue() {
114
- if ("defaultValue" in this.props) {
115
- return this.props.defaultValue
116
- } else if (this.props.selected) {
117
- return this.props.selected
118
- } else if (this.props.model) {
119
- if (!this.props.model[this.props.attribute])
120
- throw new Error(`No attribute by that name: ${this.props.attribute}`)
121
-
122
- return this.props.model[this.props.attribute]()
123
- }
124
- }
125
-
126
- inputId() {
127
- if ("id" in this.props) {
128
- return this.props.id
129
- } else if (this.props.model) {
130
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
131
- }
132
- }
133
-
134
- inputName() {
135
- if ("name" in this.props) {
136
- return this.props.name
137
- } else if (this.props.model) {
138
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
139
- }
140
- }
141
-
142
- label() {
143
- if ("label" in this.props) {
144
- return this.props.label
145
- } else if (this.props.model) {
146
- let attributeMethodName = inflection.camelize(this.props.attribute.replace(/_id$/, ""), true)
147
- return this.props.model.modelClass().humanAttributeName(attributeMethodName)
148
- }
149
- }
150
-
151
- labelClassName() {
152
- let classNames = ["form-group-label"]
153
-
154
- if (this.props.labelClassName)
155
- classNames.push(this.props.labelClassName)
156
-
157
- return classNames.join(" ")
158
- }
159
-
160
- wrapperClassName() {
161
- let classNames = ["form-group", "component-bootstrap-select"]
162
-
163
- if (this.props.wrapperClassName)
164
- classNames.push(this.props.wrapperClassName)
165
-
166
- return classNames.join(" ")
167
- }
168
- }
@@ -1,203 +0,0 @@
1
- import MoneyInput from "./money-input"
2
- import PropTypes from "prop-types"
3
- import PropTypesExact from "prop-types-exact"
4
- import React from "react"
5
-
6
- const inflection = require("inflection")
7
-
8
- export default class BootstrapStringInput extends React.Component {
9
- static propTypes = PropTypesExact({
10
- append: PropTypes.node,
11
- attribute: PropTypes.string,
12
- autoComplete: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
13
- className: PropTypes.string,
14
- currenciesCollection: PropTypes.array,
15
- currencyName: PropTypes.string,
16
- "data-controller": PropTypes.string,
17
- defaultValue: PropTypes.node,
18
- disabled: PropTypes.bool,
19
- hint: PropTypes.node,
20
- hintBottom: PropTypes.node,
21
- id: PropTypes.string,
22
- label: PropTypes.node,
23
- labelClassName: PropTypes.string,
24
- maxLength: PropTypes.number,
25
- model: PropTypes.object,
26
- name: PropTypes.string,
27
- onChange: PropTypes.func,
28
- onKeyUp: PropTypes.func,
29
- placeholder: PropTypes.node,
30
- rows: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
31
- step: PropTypes.number,
32
- small: PropTypes.bool,
33
- type: PropTypes.string,
34
- wrapperClassName: PropTypes.string
35
- })
36
-
37
- render() {
38
- return (
39
- <div className={this.wrapperClassName()} ref="wrapper">
40
- {this.label() &&
41
- <label className={this.labelClassName()} htmlFor={this.inputId()}>
42
- {this.label()}
43
- </label>
44
- }
45
- {this.props.hint &&
46
- <span className="form-text text-muted font-smoothing font-xs">
47
- {this.props.hint}
48
- </span>
49
- }
50
- {this.inputType() == "textarea" &&
51
- <textarea
52
- className={this.inputClassName()}
53
- data-controller={this.props["data-controller"]}
54
- defaultValue={this.inputDefaultValue()}
55
- id={this.inputId()}
56
- maxLength={this.props.maxLength}
57
- name={this.inputName()}
58
- onChange={this.props.onChange}
59
- onKeyUp={this.props.onKeyUp}
60
- placeholder={this.props.placeholder}
61
- ref="input"
62
- rows={this.props.rows}
63
- />
64
- }
65
- {this.inputType() == "money" &&
66
- <MoneyInput
67
- attribute={this.props.attribute}
68
- currenciesCollection={this.props.currenciesCollection}
69
- currencyName={this.props.currencyName}
70
- model={this.props.model}
71
- name={this.props.name}
72
- className={this.inputClassName()}
73
- onChange={this.props.onChange}
74
- placeholder={this.props.placeholder}
75
- small={this.props.small}
76
- ref="money"
77
- />
78
- }
79
- {this.inputType() != "textarea" && this.inputType() != "money" &&
80
- <div className="input-group">
81
- {this.props.prepend &&
82
- <div className="input-group-prepend">
83
- <span className="input-group-text">
84
- {this.props.prepend}
85
- </span>
86
- </div>
87
- }
88
- <input
89
- autoComplete={this.props.autoComplete}
90
- className={this.inputClassName()}
91
- data-controller={this.props["data-controller"]}
92
- defaultValue={this.inputDefaultValue()}
93
- disabled={this.props.disabled}
94
- id={this.inputId()}
95
- name={this.inputName()}
96
- onChange={this.props.onChange}
97
- onKeyUp={this.props.onKeyUp}
98
- placeholder={this.props.placeholder}
99
- ref="input"
100
- step={this.props.step}
101
- type={this.inputType()}
102
- />
103
- {this.props.append &&
104
- <div className="input-group-append">
105
- <span className="input-group-text">
106
- {this.props.append}
107
- </span>
108
- </div>
109
- }
110
- </div>
111
- }
112
- {this.props.hintBottom &&
113
- <span className="form-text text-muted font-smoothing font-xs">
114
- {this.props.hintBottom}
115
- </span>
116
- }
117
- </div>
118
- )
119
- }
120
-
121
- inputClassName() {
122
- var classNames = ["form-control"]
123
-
124
- if (this.props.className)
125
- classNames.push(this.props.className)
126
-
127
- return classNames.join(" ")
128
- }
129
-
130
- inputDefaultValue() {
131
- if ("defaultValue" in this.props) {
132
- return this.formatValue(this.props.defaultValue)
133
- } else if (this.props.model) {
134
- if (!this.props.model[this.props.attribute])
135
- throw new Error(`No such attribute: ${this.props.model.modelClassData().name}#${this.props.attribute}`)
136
-
137
- return this.formatValue(this.props.model[this.props.attribute]())
138
- }
139
- }
140
-
141
- formatValue(value) {
142
- // We need to use a certain format for datetime-local
143
- if (this.inputType() == "datetime-local" && value instanceof Date) {
144
- return I18n.strftime(value, "%Y-%m-%dT%H:%M:%S")
145
- } else if (this.inputType() == "date" && value instanceof Date) {
146
- return I18n.strftime(value, "%Y-%m-%d")
147
- }
148
-
149
- return value
150
- }
151
-
152
- inputId() {
153
- if ("id" in this.props) {
154
- return this.props.id
155
- } else if (this.props.model) {
156
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
157
- }
158
- }
159
-
160
- inputName() {
161
- if ("name" in this.props) {
162
- return this.props.name
163
- } else if (this.props.model) {
164
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
165
- }
166
- }
167
-
168
- inputType() {
169
- if (this.props.type) {
170
- return this.props.type
171
- } else {
172
- return "text"
173
- }
174
- }
175
-
176
- label() {
177
- if (this.props.label === false) {
178
- return null
179
- } else if (this.props.label) {
180
- return this.props.label
181
- } else if (this.props.model) {
182
- return this.props.model.modelClass().humanAttributeName(this.props.attribute)
183
- }
184
- }
185
-
186
- labelClassName() {
187
- var classNames = []
188
-
189
- if (this.props.labelClassName)
190
- classNames.push(this.props.labelClassName)
191
-
192
- return classNames.join(" ")
193
- }
194
-
195
- wrapperClassName() {
196
- var classNames = ["form-group", "component-bootstrap-string-input"]
197
-
198
- if (this.props.wrapperClassName)
199
- classNames.push(this.props.wrapperClassName)
200
-
201
- return classNames.join(" ")
202
- }
203
- }
@@ -1,169 +0,0 @@
1
- import CableSubscriptionPool from "./cable-subscription-pool"
2
- import CableSubscription from "./cable-subscription"
3
-
4
- export default class ApiMakerCableConnectionPool {
5
- static current() {
6
- if (!window.apiMakerCableConnectionPool)
7
- window.apiMakerCableConnectionPool = new ApiMakerCableConnectionPool()
8
-
9
- return window.apiMakerCableConnectionPool
10
- }
11
-
12
- constructor() {
13
- this.connections = {}
14
- this.upcomingSubscriptionData = {}
15
- this.upcomingSubscriptions = []
16
- }
17
-
18
- connectCreated(modelName, callback) {
19
- if (!this.upcomingSubscriptionData[modelName])
20
- this.upcomingSubscriptionData[modelName] = {}
21
-
22
- if (!this.upcomingSubscriptionData[modelName]["creates"])
23
- this.upcomingSubscriptionData[modelName]["creates"] = true
24
-
25
- if (!this.upcomingSubscriptions[modelName])
26
- this.upcomingSubscriptions[modelName] = {}
27
-
28
- if (!this.upcomingSubscriptions[modelName]["creates"])
29
- this.upcomingSubscriptions[modelName]["creates"] = []
30
-
31
- var subscription = new CableSubscription({
32
- callback: callback,
33
- modelName: modelName
34
- })
35
-
36
- this.upcomingSubscriptions[modelName]["creates"].push(subscription)
37
-
38
- this.scheduleConnectUpcoming()
39
-
40
- return subscription
41
- }
42
-
43
- connectDestroyed(modelName, modelId, callback) {
44
- if (!this.upcomingSubscriptionData[modelName])
45
- this.upcomingSubscriptionData[modelName] = {}
46
-
47
- if (!this.upcomingSubscriptionData[modelName]["destroys"])
48
- this.upcomingSubscriptionData[modelName]["destroys"] = []
49
-
50
- if (!this.upcomingSubscriptionData[modelName]["destroys"].includes(modelId))
51
- this.upcomingSubscriptionData[modelName]["destroys"].push(modelId)
52
-
53
- if (!this.upcomingSubscriptions[modelName])
54
- this.upcomingSubscriptions[modelName] = {}
55
-
56
- if (!this.upcomingSubscriptions[modelName]["destroys"])
57
- this.upcomingSubscriptions[modelName]["destroys"] = {}
58
-
59
- if (!this.upcomingSubscriptions[modelName]["destroys"][modelId])
60
- this.upcomingSubscriptions[modelName]["destroys"][modelId] = []
61
-
62
- var subscription = new CableSubscription({
63
- callback: callback,
64
- modelName: modelName,
65
- modelId: modelId
66
- })
67
-
68
- this.upcomingSubscriptions[modelName]["destroys"][modelId].push(subscription)
69
-
70
- this.scheduleConnectUpcoming()
71
-
72
- return subscription
73
- }
74
-
75
- connectEvent(modelName, modelId, eventName, callback) {
76
- if (!this.upcomingSubscriptionData[modelName])
77
- this.upcomingSubscriptionData[modelName] = {}
78
-
79
- if (!this.upcomingSubscriptionData[modelName]["events"])
80
- this.upcomingSubscriptionData[modelName]["events"] = {}
81
-
82
- if (!this.upcomingSubscriptionData[modelName]["events"][eventName])
83
- this.upcomingSubscriptionData[modelName]["events"][eventName] = []
84
-
85
- if (!this.upcomingSubscriptionData[modelName]["events"][eventName].includes(modelId))
86
- this.upcomingSubscriptionData[modelName]["events"][eventName].push(modelId)
87
-
88
- if (!this.upcomingSubscriptions[modelName])
89
- this.upcomingSubscriptions[modelName] = {}
90
-
91
- if (!this.upcomingSubscriptions[modelName]["events"])
92
- this.upcomingSubscriptions[modelName]["events"] = {}
93
-
94
- if (!this.upcomingSubscriptions[modelName]["events"])
95
- this.upcomingSubscriptions[modelName]["events"] = {}
96
-
97
- if (!this.upcomingSubscriptions[modelName]["events"][modelId])
98
- this.upcomingSubscriptions[modelName]["events"][modelId] = {}
99
-
100
- if (!this.upcomingSubscriptions[modelName]["events"][modelId][eventName])
101
- this.upcomingSubscriptions[modelName]["events"][modelId][eventName] = []
102
-
103
- var subscription = new CableSubscription({
104
- callback: callback,
105
- modelName: modelName,
106
- modelId: modelId
107
- })
108
-
109
- this.upcomingSubscriptions[modelName]["events"][modelId][eventName].push(subscription)
110
-
111
- this.scheduleConnectUpcoming()
112
-
113
- return subscription
114
- }
115
-
116
- connectUpdate(modelName, modelId, callback) {
117
- if (!this.upcomingSubscriptionData[modelName])
118
- this.upcomingSubscriptionData[modelName] = {}
119
-
120
- if (!this.upcomingSubscriptionData[modelName]["updates"])
121
- this.upcomingSubscriptionData[modelName]["updates"] = []
122
-
123
- if (!this.upcomingSubscriptionData[modelName]["updates"].includes(modelId))
124
- this.upcomingSubscriptionData[modelName]["updates"].push(modelId)
125
-
126
- if (!this.upcomingSubscriptions[modelName])
127
- this.upcomingSubscriptions[modelName] = {}
128
-
129
- if (!this.upcomingSubscriptions[modelName]["updates"])
130
- this.upcomingSubscriptions[modelName]["updates"] = {}
131
-
132
- if (!this.upcomingSubscriptions[modelName]["updates"][modelId])
133
- this.upcomingSubscriptions[modelName]["updates"][modelId] = []
134
-
135
- var subscription = new CableSubscription({
136
- callback: callback,
137
- modelName: modelName,
138
- modelId: modelId
139
- })
140
-
141
- this.upcomingSubscriptions[modelName]["updates"][modelId].push(subscription)
142
-
143
- this.scheduleConnectUpcoming()
144
-
145
- return subscription
146
- }
147
-
148
- connectUpcoming() {
149
- var subscriptionData = this.upcomingSubscriptionData
150
- var subscriptions = this.upcomingSubscriptions
151
-
152
- this.upcomingSubscriptionData = {}
153
- this.upcomingSubscriptions = {}
154
-
155
- var cableSubscriptionPool = new CableSubscriptionPool({
156
- subscriptionData: subscriptionData,
157
- subscriptions: subscriptions
158
- })
159
-
160
- return cableSubscriptionPool
161
- }
162
-
163
- scheduleConnectUpcoming() {
164
- if (this.scheduleConnectUpcomingTimeout)
165
- clearTimeout(this.scheduleConnectUpcomingTimeout)
166
-
167
- this.scheduleConnectUpcomingTimeout = setTimeout(() => this.connectUpcoming(), 50)
168
- }
169
- }
@@ -1,111 +0,0 @@
1
- import CommandsPool from "./commands-pool"
2
- import Deserializer from "./deserializer"
3
- import Logger from "./logger"
4
-
5
- const inflection = require("inflection")
6
-
7
- export default class ApiMakerCableSubscriptionPool {
8
- constructor(props) {
9
- this.props = props
10
- this.activeSubscriptions = 0
11
- this.registerSubscriptions()
12
- this.connect()
13
- }
14
-
15
- connect() {
16
- var globalData = CommandsPool.current().globalRequestData
17
-
18
- this.subscription = App.cable.subscriptions.create(
19
- {channel: "ApiMaker::SubscriptionsChannel", global: globalData, subscription_data: this.props.subscriptionData},
20
- {received: (data) => this.onReceived(data)}
21
- )
22
- }
23
-
24
- onReceived(rawData) {
25
- var data = Deserializer.parse(rawData)
26
- var modelType = data.model_type
27
- var modelName = inflection.camelize(inflection.singularize(modelType.replace(/-/g, "_")))
28
- var modelId = data.model_id
29
- var modelInstance = data.model
30
- var subscriptions = this.props.subscriptions
31
-
32
- if (data.type == "update") {
33
- for(var subscription of subscriptions[modelName]["updates"][modelId]) {
34
- subscription.onReceived({model: modelInstance})
35
- }
36
- } else if (data.type == "create") {
37
- for(var subscription of subscriptions[modelName]["creates"]) {
38
- subscription.onReceived({model: modelInstance})
39
- }
40
- } else if (data.type == "destroy") {
41
- for(var subscription of subscriptions[modelName]["destroys"][modelId]) {
42
- subscription.onReceived({model: modelInstance})
43
- }
44
- } else if (data.type == "event") {
45
- for(var subscription of subscriptions[modelName]["events"][modelId][data.event_name]) {
46
- subscription.onReceived({
47
- args: data.args,
48
- eventName: data.event_name,
49
- model: modelInstance
50
- })
51
- }
52
- } else {
53
- throw new Error(`Unknown type: ${data.type}`)
54
- }
55
- }
56
-
57
- onUnsubscribe() {
58
- Logger.log(`activeSubscriptions before unsub: ${this.activeSubscriptions}`)
59
- this.activeSubscriptions -= 1
60
- Logger.log(`activeSubscriptions after unsub: ${this.activeSubscriptions}`)
61
-
62
- if (this.activeSubscriptions <= 0) {
63
- Logger.log("Unsubscribe from ActionCable subscription")
64
- this.subscription.unsubscribe()
65
- }
66
- }
67
-
68
- registerSubscriptions() {
69
- Logger.log(`registerSubscriptions: ${this.props.subscriptions.length}`)
70
- Logger.log(this.props.subscriptions)
71
-
72
- for(var modelName in this.props.subscriptions) {
73
- if (this.props.subscriptions[modelName]["creates"]) {
74
- for(var subscription of this.props.subscriptions[modelName]["creates"]) {
75
- this.connectUnsubscriptionForSubscription(subscription)
76
- }
77
- }
78
-
79
- if (this.props.subscriptions[modelName]["events"]) {
80
- for(var eventName in this.props.subscriptions[modelName]["events"]) {
81
- for(var modelId in this.props.subscriptions[modelName]["events"][eventName]) {
82
- for(var subscription of this.props.subscriptions[modelName]["events"][eventName][modelId]) {
83
- this.connectUnsubscriptionForSubscription(subscription)
84
- }
85
- }
86
- }
87
- }
88
-
89
- if (this.props.subscriptions[modelName]["updates"]) {
90
- for(var modelId in this.props.subscriptions[modelName]["updates"]) {
91
- for(var subscription of this.props.subscriptions[modelName]["updates"][modelId]) {
92
- this.connectUnsubscriptionForSubscription(subscription)
93
- }
94
- }
95
- }
96
- }
97
- }
98
-
99
- connectUnsubscriptionForSubscription(subscription) {
100
- Logger.log("Connecting to unsubscribe on subscription")
101
- Logger.log({ subscription })
102
-
103
- this.activeSubscriptions += 1
104
-
105
- subscription.onUnsubscribe(() => {
106
- Logger.log("Call onUnsubscribe on self")
107
-
108
- this.onUnsubscribe(subscription)
109
- })
110
- }
111
- }
@@ -1,33 +0,0 @@
1
- import Logger from "./logger"
2
-
3
- export default class ApiMakerCableSubscription {
4
- constructor(props) {
5
- this.props = props
6
- this.onUnsubscribeCallbacks = []
7
- this.subscribed = true
8
- }
9
-
10
- onReceived(data) {
11
- this.props.callback.apply(null, [data])
12
- }
13
-
14
- onUnsubscribe(callback) {
15
- this.onUnsubscribeCallbacks.push(callback)
16
- }
17
-
18
- unsubscribe() {
19
- if (!this.subscribed) {
20
- Logger.log("Unsubscribed already called")
21
- return
22
- }
23
-
24
- Logger.log(`Unsubscribe called: ${this.onUnsubscribeCallbacks.length}`)
25
-
26
- for(var onUnsubscribeCallback of this.onUnsubscribeCallbacks) {
27
- Logger.log("onUnsubscribe called for a callback")
28
- onUnsubscribeCallback.call()
29
- }
30
-
31
- this.subscribed = false
32
- }
33
- }