api_maker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +476 -0
- data/Rakefile +27 -0
- data/app/channels/api_maker/subscriptions_channel.rb +80 -0
- data/app/controllers/api_maker/base_controller.rb +32 -0
- data/app/controllers/api_maker/commands_controller.rb +26 -0
- data/app/controllers/api_maker/devise_controller.rb +60 -0
- data/app/controllers/api_maker/session_statuses_controller.rb +33 -0
- data/app/services/api_maker/application_service.rb +7 -0
- data/app/services/api_maker/collection_command_service.rb +24 -0
- data/app/services/api_maker/command_response.rb +67 -0
- data/app/services/api_maker/command_service.rb +31 -0
- data/app/services/api_maker/create_command.rb +62 -0
- data/app/services/api_maker/create_command_service.rb +18 -0
- data/app/services/api_maker/destroy_command.rb +39 -0
- data/app/services/api_maker/destroy_command_service.rb +22 -0
- data/app/services/api_maker/generate_react_native_api_service.rb +61 -0
- data/app/services/api_maker/index_command.rb +96 -0
- data/app/services/api_maker/index_command_service.rb +22 -0
- data/app/services/api_maker/js_method_namer_service.rb +11 -0
- data/app/services/api_maker/member_command_service.rb +25 -0
- data/app/services/api_maker/model_content_generator_service.rb +108 -0
- data/app/services/api_maker/models_finder_service.rb +22 -0
- data/app/services/api_maker/models_generator_service.rb +104 -0
- data/app/services/api_maker/update_command.rb +43 -0
- data/app/services/api_maker/update_command_service.rb +21 -0
- data/app/services/api_maker/valid_command.rb +35 -0
- data/app/services/api_maker/valid_command_service.rb +21 -0
- data/app/views/api_maker/_data.html.erb +15 -0
- data/config/rails_best_practices.yml +55 -0
- data/config/routes.rb +7 -0
- data/lib/api_maker.rb +36 -0
- data/lib/api_maker/ability.rb +39 -0
- data/lib/api_maker/ability_loader.rb +21 -0
- data/lib/api_maker/action_controller_base_extensions.rb +5 -0
- data/lib/api_maker/base_command.rb +81 -0
- data/lib/api_maker/base_resource.rb +78 -0
- data/lib/api_maker/collection_serializer.rb +69 -0
- data/lib/api_maker/command_spec_helper.rb +57 -0
- data/lib/api_maker/configuration.rb +34 -0
- data/lib/api_maker/engine.rb +5 -0
- data/lib/api_maker/individual_command.rb +37 -0
- data/lib/api_maker/javascript/api.js +92 -0
- data/lib/api_maker/javascript/base-model.js +543 -0
- data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +16 -0
- data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +47 -0
- data/lib/api_maker/javascript/bootstrap/card.jsx +79 -0
- data/lib/api_maker/javascript/bootstrap/checkbox.jsx +127 -0
- data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +105 -0
- data/lib/api_maker/javascript/bootstrap/live-table.jsx +168 -0
- data/lib/api_maker/javascript/bootstrap/money-input.jsx +136 -0
- data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +80 -0
- data/lib/api_maker/javascript/bootstrap/select.jsx +168 -0
- data/lib/api_maker/javascript/bootstrap/string-input.jsx +203 -0
- data/lib/api_maker/javascript/cable-connection-pool.js +169 -0
- data/lib/api_maker/javascript/cable-subscription-pool.js +111 -0
- data/lib/api_maker/javascript/cable-subscription.js +33 -0
- data/lib/api_maker/javascript/collection.js +186 -0
- data/lib/api_maker/javascript/commands-pool.js +123 -0
- data/lib/api_maker/javascript/custom-error.js +14 -0
- data/lib/api_maker/javascript/deserializer.js +35 -0
- data/lib/api_maker/javascript/devise.js.erb +113 -0
- data/lib/api_maker/javascript/error-logger.js +119 -0
- data/lib/api_maker/javascript/event-connection.jsx +24 -0
- data/lib/api_maker/javascript/event-created.jsx +26 -0
- data/lib/api_maker/javascript/event-destroyed.jsx +26 -0
- data/lib/api_maker/javascript/event-emitter-listener.jsx +32 -0
- data/lib/api_maker/javascript/event-listener.jsx +41 -0
- data/lib/api_maker/javascript/event-updated.jsx +26 -0
- data/lib/api_maker/javascript/form-data-to-object.js +70 -0
- data/lib/api_maker/javascript/included.js +39 -0
- data/lib/api_maker/javascript/key-value-store.js +47 -0
- data/lib/api_maker/javascript/logger.js +23 -0
- data/lib/api_maker/javascript/model-name.js +21 -0
- data/lib/api_maker/javascript/model-template.js.erb +110 -0
- data/lib/api_maker/javascript/models-response-reader.js +43 -0
- data/lib/api_maker/javascript/paginate.jsx +128 -0
- data/lib/api_maker/javascript/params.js +68 -0
- data/lib/api_maker/javascript/resource-route.jsx +75 -0
- data/lib/api_maker/javascript/resource-routes.jsx +36 -0
- data/lib/api_maker/javascript/result.js +25 -0
- data/lib/api_maker/javascript/session-status-updater.js +113 -0
- data/lib/api_maker/javascript/sort-link.jsx +88 -0
- data/lib/api_maker/javascript/updated-attribute.jsx +60 -0
- data/lib/api_maker/loader.rb +14 -0
- data/lib/api_maker/memory_storage.rb +65 -0
- data/lib/api_maker/model_extensions.rb +96 -0
- data/lib/api_maker/permitted_params_argument.rb +12 -0
- data/lib/api_maker/preloader.rb +91 -0
- data/lib/api_maker/preloader_belongs_to.rb +58 -0
- data/lib/api_maker/preloader_has_many.rb +69 -0
- data/lib/api_maker/preloader_has_one.rb +70 -0
- data/lib/api_maker/preloader_through.rb +101 -0
- data/lib/api_maker/railtie.rb +14 -0
- data/lib/api_maker/relationship_includer.rb +42 -0
- data/lib/api_maker/resource_routing.rb +8 -0
- data/lib/api_maker/result_parser.rb +50 -0
- data/lib/api_maker/serializer.rb +86 -0
- data/lib/api_maker/spec_helper.rb +100 -0
- data/lib/api_maker/version.rb +3 -0
- data/lib/tasks/api_maker_tasks.rake +5 -0
- metadata +581 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
import Api from "./api"
|
2
|
+
import CustomError from "./custom-error"
|
3
|
+
import Deserializer from "./deserializer"
|
4
|
+
import FormDataToObject from "./form-data-to-object"
|
5
|
+
import objectToFormData from "object-to-formdata"
|
6
|
+
|
7
|
+
export default class ApiMakerCommandsPool {
|
8
|
+
static addCommand(data, args = {}) {
|
9
|
+
if (args.instant) {
|
10
|
+
var pool = new ApiMakerCommandsPool()
|
11
|
+
} else {
|
12
|
+
var pool = ApiMakerCommandsPool.current()
|
13
|
+
}
|
14
|
+
|
15
|
+
var promiseResult = pool.addCommand(data)
|
16
|
+
|
17
|
+
if (args.instant) {
|
18
|
+
pool.flush()
|
19
|
+
} else {
|
20
|
+
pool.setFlushTimeout()
|
21
|
+
}
|
22
|
+
|
23
|
+
return promiseResult
|
24
|
+
}
|
25
|
+
|
26
|
+
static current() {
|
27
|
+
if (!window.currentApiMakerCommandsPool)
|
28
|
+
window.currentApiMakerCommandsPool = new ApiMakerCommandsPool()
|
29
|
+
|
30
|
+
return window.currentApiMakerCommandsPool
|
31
|
+
}
|
32
|
+
|
33
|
+
static flush() {
|
34
|
+
ApiMakerCommandsPool.current().flush()
|
35
|
+
}
|
36
|
+
|
37
|
+
constructor() {
|
38
|
+
this.pool = {}
|
39
|
+
this.poolData = {}
|
40
|
+
this.currentId = 1
|
41
|
+
this.globalRequestData = null
|
42
|
+
}
|
43
|
+
|
44
|
+
addCommand(data) {
|
45
|
+
return new Promise((resolve, reject) => {
|
46
|
+
var id = this.currentId
|
47
|
+
this.currentId += 1
|
48
|
+
|
49
|
+
var commandType = data.type
|
50
|
+
var commandName = data.command
|
51
|
+
var collectionName = data.collectionName
|
52
|
+
|
53
|
+
this.pool[id] = {resolve: resolve, reject: reject}
|
54
|
+
|
55
|
+
if (!this.poolData[commandType])
|
56
|
+
this.poolData[commandType] = {}
|
57
|
+
|
58
|
+
if (!this.poolData[commandType][collectionName])
|
59
|
+
this.poolData[commandType][collectionName] = {}
|
60
|
+
|
61
|
+
if (!this.poolData[commandType][collectionName][commandName])
|
62
|
+
this.poolData[commandType][collectionName][commandName] = {}
|
63
|
+
|
64
|
+
if (data.args instanceof FormData) {
|
65
|
+
var args = FormDataToObject.toObject(data.args)
|
66
|
+
} else {
|
67
|
+
var args = data.args
|
68
|
+
}
|
69
|
+
|
70
|
+
this.poolData[commandType][collectionName][commandName][id] = {
|
71
|
+
args: args,
|
72
|
+
primary_key: data.primaryKey,
|
73
|
+
id: id
|
74
|
+
}
|
75
|
+
})
|
76
|
+
}
|
77
|
+
|
78
|
+
async flush() {
|
79
|
+
if (Object.keys(this.pool) == 0)
|
80
|
+
return
|
81
|
+
|
82
|
+
this.clearTimeout()
|
83
|
+
|
84
|
+
var currentPool = this.pool
|
85
|
+
var currentPoolData = this.poolData
|
86
|
+
|
87
|
+
this.pool = {}
|
88
|
+
this.poolData = {}
|
89
|
+
|
90
|
+
var objectForFormData = {pool: currentPoolData}
|
91
|
+
|
92
|
+
if (this.globalRequestData)
|
93
|
+
objectForFormData.global = this.globalRequestData
|
94
|
+
|
95
|
+
var formData = objectToFormData(objectForFormData)
|
96
|
+
var url = `/api_maker/commands`
|
97
|
+
var response = await Api.requestLocal({path: url, method: "POST", rawData: formData})
|
98
|
+
|
99
|
+
for(var commandId in response.responses) {
|
100
|
+
var commandResponse = response.responses[commandId]
|
101
|
+
var commandResponseData = Deserializer.parse(commandResponse.data)
|
102
|
+
var commandData = currentPool[parseInt(commandId)]
|
103
|
+
|
104
|
+
if (commandResponse.type == "success") {
|
105
|
+
commandData.resolve(commandResponseData)
|
106
|
+
} else if (commandResponse.type == "error") {
|
107
|
+
commandData.reject(new CustomError("Command error", {response: commandResponseData}))
|
108
|
+
} else {
|
109
|
+
commandData.reject(new CustomError("Command failed", {response: commandResponseData}))
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
clearTimeout() {
|
115
|
+
if (this.flushTimeout)
|
116
|
+
clearTimeout(this.flushTimeout)
|
117
|
+
}
|
118
|
+
|
119
|
+
setFlushTimeout() {
|
120
|
+
this.clearTimeout()
|
121
|
+
this.flushTimeout = setTimeout(() => this.flush(), 0)
|
122
|
+
}
|
123
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
export default class ApiMakerCustomError extends Error {
|
2
|
+
constructor(message, args = {}) {
|
3
|
+
if (args.response && args.response.errors)
|
4
|
+
message = `${message}: ${args.response.errors.join(". ")}`
|
5
|
+
|
6
|
+
super(message)
|
7
|
+
|
8
|
+
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
9
|
+
if (Error.captureStackTrace)
|
10
|
+
Error.captureStackTrace(this, ApiMakerCustomError)
|
11
|
+
|
12
|
+
this.args = args
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import Money from "js-money"
|
2
|
+
|
3
|
+
const inflection = require("inflection")
|
4
|
+
|
5
|
+
export default class ApiMakerDeserializer {
|
6
|
+
static parse(object) {
|
7
|
+
if (Array.isArray(object)) {
|
8
|
+
return object.map(value => ApiMakerDeserializer.parse(value))
|
9
|
+
} else if (object && typeof object == "object") {
|
10
|
+
if (object.api_maker_type == "money") {
|
11
|
+
var cents = object.amount
|
12
|
+
var currency = object.currency
|
13
|
+
|
14
|
+
return Money.fromInteger(cents, currency)
|
15
|
+
} else if (object.api_maker_type == "model") {
|
16
|
+
var modelClassName = inflection.singularize(object.model_name)
|
17
|
+
var modelClass = require(`api-maker/models/${modelClassName}`).default
|
18
|
+
var model = new modelClass({data: object.serialized, isNewRecord: false})
|
19
|
+
|
20
|
+
return model
|
21
|
+
} else {
|
22
|
+
var newObject = {}
|
23
|
+
|
24
|
+
for(var key in object) {
|
25
|
+
var value = object[key]
|
26
|
+
newObject[key] = ApiMakerDeserializer.parse(value)
|
27
|
+
}
|
28
|
+
|
29
|
+
return newObject
|
30
|
+
}
|
31
|
+
} else {
|
32
|
+
return object
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import Api from "./api"
|
2
|
+
import CustomError from "./custom-error"
|
3
|
+
import EventEmitter from "events"
|
4
|
+
const inflection = require("inflection")
|
5
|
+
|
6
|
+
export default class Devise {
|
7
|
+
static callSignOutEvent(args) {
|
8
|
+
Devise.events().emit("onDeviseSignOut", {args: args})
|
9
|
+
}
|
10
|
+
|
11
|
+
static current() {
|
12
|
+
if (!window.currentApiMakerDevise)
|
13
|
+
window.currentApiMakerDevise = new Devise()
|
14
|
+
|
15
|
+
return window.currentApiMakerDevise
|
16
|
+
}
|
17
|
+
|
18
|
+
static events() {
|
19
|
+
if (!window.apiMakerDeviseEvents)
|
20
|
+
window.apiMakerDeviseEvents = new EventEmitter()
|
21
|
+
|
22
|
+
return window.apiMakerDeviseEvents
|
23
|
+
}
|
24
|
+
|
25
|
+
<% Devise.mappings.each do |scope| %>
|
26
|
+
<%
|
27
|
+
klass = scope[1].class_name.safe_constantize
|
28
|
+
resource = ApiMaker::Serializer.resource_for(klass)
|
29
|
+
%>
|
30
|
+
<% if resource %>
|
31
|
+
static <%= ApiMaker::JsMethodNamerService.execute!(name: "is_#{scope[0]}_signed_in") %>() {
|
32
|
+
if (Devise.current().getCurrentScope("<%= scope[1].class_name %>"))
|
33
|
+
return true
|
34
|
+
|
35
|
+
return false
|
36
|
+
}
|
37
|
+
|
38
|
+
static current<%= scope[1].class_name %>() {
|
39
|
+
return Devise.current().getCurrentScope("<%= scope[1].class_name %>")
|
40
|
+
}
|
41
|
+
<% end %>
|
42
|
+
<% end %>
|
43
|
+
|
44
|
+
static async signIn(username, password, args = {}) {
|
45
|
+
if (!args.scope)
|
46
|
+
args.scope = "user"
|
47
|
+
|
48
|
+
var postData = {"username": username, "password": password, "args": args}
|
49
|
+
var response = await Api.post("/api_maker/devise/do_sign_in", postData)
|
50
|
+
|
51
|
+
if (response.success) {
|
52
|
+
var modelClass = require(`api-maker/models/${inflection.dasherize(args.scope)}`).default
|
53
|
+
var modelInstance = new modelClass(response.model_data)
|
54
|
+
|
55
|
+
Devise.updateSession(modelInstance)
|
56
|
+
Devise.events().emit("onDeviseSignIn", Object.assign({username: username}, args))
|
57
|
+
|
58
|
+
return {model: modelInstance, response: response}
|
59
|
+
} else {
|
60
|
+
throw new CustomError("Sign in failed", {response: response})
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
static updateSession(model) {
|
65
|
+
var scope = model.modelClassData().name
|
66
|
+
Devise.current().currents[scope] = model
|
67
|
+
}
|
68
|
+
|
69
|
+
static setSignedOut(args) {
|
70
|
+
Devise.current().currents[inflection.camelize(args.scope)] = null
|
71
|
+
}
|
72
|
+
|
73
|
+
static async signOut(args = {}) {
|
74
|
+
if (!args.scope)
|
75
|
+
args.scope = "user"
|
76
|
+
|
77
|
+
var postData = {"args": args}
|
78
|
+
var response = await Api.post("/api_maker/devise/do_sign_out", postData)
|
79
|
+
|
80
|
+
if (response.success) {
|
81
|
+
Devise.setSignedOut(args)
|
82
|
+
Devise.callSignOutEvent(args)
|
83
|
+
return response
|
84
|
+
} else {
|
85
|
+
throw new CustomError("Sign out failed", {response: response})
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
constructor() {
|
90
|
+
this.currents = {}
|
91
|
+
}
|
92
|
+
|
93
|
+
getCurrentScope(scope) {
|
94
|
+
if (!(scope in this.currents))
|
95
|
+
this.currents[scope] = this.loadCurrentScope(scope)
|
96
|
+
|
97
|
+
return this.currents[scope]
|
98
|
+
}
|
99
|
+
|
100
|
+
loadCurrentScope(scope) {
|
101
|
+
var apiMakerDataElement = document.querySelector(".api-maker-data")
|
102
|
+
var keyName = `current${inflection.camelize(scope)}`
|
103
|
+
var scopeData = apiMakerDataElement.dataset[keyName]
|
104
|
+
|
105
|
+
if (!scopeData)
|
106
|
+
return null
|
107
|
+
|
108
|
+
var modelClass = require(`api-maker/models/${inflection.dasherize(inflection.underscore(scope))}`).default
|
109
|
+
var modelInstance = new modelClass({data: JSON.parse(scopeData)})
|
110
|
+
|
111
|
+
return modelInstance
|
112
|
+
}
|
113
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
import retrace from "retrace"
|
2
|
+
|
3
|
+
export default class ErrorLogger {
|
4
|
+
constructor() {
|
5
|
+
this.errors = []
|
6
|
+
}
|
7
|
+
|
8
|
+
loadSourceMaps() {
|
9
|
+
return new Promise(resolve => {
|
10
|
+
var scripts = document.querySelectorAll("script")
|
11
|
+
var promises = []
|
12
|
+
|
13
|
+
for(var script of scripts) {
|
14
|
+
var src = script.getAttribute("src")
|
15
|
+
var type = script.getAttribute("type")
|
16
|
+
|
17
|
+
if (src && src.includes("/packs/") && (type == "text/javascript" || !type)) {
|
18
|
+
var promise = this.loadSourceMapForScript(script)
|
19
|
+
promises.push(promise)
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
Promise.all(promises).then(() => { resolve() })
|
24
|
+
})
|
25
|
+
}
|
26
|
+
|
27
|
+
loadSourceMapForScript(script) {
|
28
|
+
var src = script.getAttribute("src")
|
29
|
+
var url = this.loadUrl(src)
|
30
|
+
var originalUrl = `${url.origin}${url.pathname}`
|
31
|
+
var mapUrl = `${url.origin}${url.pathname}.map`
|
32
|
+
|
33
|
+
return new Promise(resolve => {
|
34
|
+
var xhr = new XMLHttpRequest()
|
35
|
+
xhr.open("GET", mapUrl, true)
|
36
|
+
xhr.onload = () => {
|
37
|
+
retrace.register(originalUrl, xhr.responseText)
|
38
|
+
resolve()
|
39
|
+
}
|
40
|
+
xhr.send()
|
41
|
+
})
|
42
|
+
}
|
43
|
+
|
44
|
+
loadUrl(url) {
|
45
|
+
var parser = document.createElement("a")
|
46
|
+
parser.href = url
|
47
|
+
|
48
|
+
return parser
|
49
|
+
}
|
50
|
+
|
51
|
+
enable() {
|
52
|
+
this.connectOnError()
|
53
|
+
this.connectUnhandledRejection()
|
54
|
+
}
|
55
|
+
|
56
|
+
getErrors() {
|
57
|
+
return this.errors
|
58
|
+
}
|
59
|
+
|
60
|
+
connectOnError() {
|
61
|
+
window.addEventListener("error", (event) => {
|
62
|
+
if (!this.isHandlingError) {
|
63
|
+
try {
|
64
|
+
this.isHandlingError = true
|
65
|
+
this.errors.push({
|
66
|
+
errorClass: event.error ? event.error.name : "No error class",
|
67
|
+
file: event.filename,
|
68
|
+
message: event.message || "Unknown error",
|
69
|
+
url: window.location.href,
|
70
|
+
line: event.lineno,
|
71
|
+
error: event.error
|
72
|
+
})
|
73
|
+
} finally {
|
74
|
+
this.isHandlingError = false
|
75
|
+
}
|
76
|
+
}
|
77
|
+
})
|
78
|
+
}
|
79
|
+
|
80
|
+
connectUnhandledRejection() {
|
81
|
+
window.addEventListener("unhandledrejection", (event, test) => {
|
82
|
+
if (!this.isHandlingError) {
|
83
|
+
this.isHandlingError = true
|
84
|
+
|
85
|
+
try {
|
86
|
+
if (event.reason.stack) {
|
87
|
+
retrace.map(event.reason.stack).then(mappedStackTrace => {
|
88
|
+
this.errors.push({
|
89
|
+
errorClass: "UnhandledRejection",
|
90
|
+
file: null,
|
91
|
+
message: event.reason.message || "Unhandled promise rejection",
|
92
|
+
url: window.location.href,
|
93
|
+
line: null,
|
94
|
+
backtrace: mappedStackTrace.split("\n")
|
95
|
+
})
|
96
|
+
})
|
97
|
+
} else {
|
98
|
+
this.errors.push({
|
99
|
+
errorClass: "UnhandledRejection",
|
100
|
+
file: null,
|
101
|
+
message: event.reason.message || "Unhandled promise rejection",
|
102
|
+
url: window.location.href,
|
103
|
+
line: null,
|
104
|
+
backtrace: null
|
105
|
+
})
|
106
|
+
}
|
107
|
+
} finally {
|
108
|
+
this.isHandlingError = false
|
109
|
+
}
|
110
|
+
}
|
111
|
+
})
|
112
|
+
}
|
113
|
+
|
114
|
+
testPromiseError() {
|
115
|
+
return new Promise(resolve => {
|
116
|
+
throw new Error("testPromiseError")
|
117
|
+
})
|
118
|
+
}
|
119
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import PropTypes from "prop-types"
|
2
|
+
import PropTypesExact from "prop-types-exact"
|
3
|
+
import React from "react"
|
4
|
+
|
5
|
+
export default class ApiMakerEventConnection extends React.Component {
|
6
|
+
static propTypes = PropTypesExact({
|
7
|
+
model: PropTypes.object.isRequired,
|
8
|
+
event: PropTypes.string.isRequired,
|
9
|
+
onCall: PropTypes.func.isRequired
|
10
|
+
})
|
11
|
+
|
12
|
+
componentDidMount() {
|
13
|
+
this.subscription = this.props.model.connect(this.props.event, this.props.onCall)
|
14
|
+
}
|
15
|
+
|
16
|
+
componentWillUnmount() {
|
17
|
+
if (this.subscription)
|
18
|
+
this.subscription.unsubscribe()
|
19
|
+
}
|
20
|
+
|
21
|
+
render() {
|
22
|
+
return ""
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import PropTypes from "prop-types"
|
2
|
+
import PropTypesExact from "prop-types-exact"
|
3
|
+
import React from "react"
|
4
|
+
|
5
|
+
export default class ApiMakerEventCreated extends React.Component {
|
6
|
+
static propTypes = PropTypesExact({
|
7
|
+
modelClass: PropTypes.func.isRequired,
|
8
|
+
onCreated: PropTypes.func.isRequired
|
9
|
+
})
|
10
|
+
|
11
|
+
componentDidMount() {
|
12
|
+
this.connect()
|
13
|
+
}
|
14
|
+
|
15
|
+
componentWillUnmount() {
|
16
|
+
this.connectCreated.unsubscribe()
|
17
|
+
}
|
18
|
+
|
19
|
+
connect() {
|
20
|
+
this.connectCreated = this.props.modelClass.connectCreated(this.props.onCreated)
|
21
|
+
}
|
22
|
+
|
23
|
+
render() {
|
24
|
+
return ""
|
25
|
+
}
|
26
|
+
}
|