api_maker 0.0.1 → 0.0.2

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 (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,127 +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 BootstrapCheckbox extends React.Component {
8
- static propTypes = PropTypesExact({
9
- attribute: PropTypes.string,
10
- className: PropTypes.string,
11
- "data-action": PropTypes.string,
12
- "data-target": PropTypes.string,
13
- defaultChecked: PropTypes.bool,
14
- defaultValue: PropTypes.node,
15
- hint: PropTypes.node,
16
- id: PropTypes.string,
17
- label: PropTypes.node,
18
- labelClassName: PropTypes.string,
19
- model: PropTypes.object,
20
- name: PropTypes.string,
21
- onChange: PropTypes.func,
22
- wrapperClassName: PropTypes.string
23
- })
24
-
25
- render() {
26
- let id = this.inputId()
27
-
28
- return (
29
- <div className={this.wrapperClassName()}>
30
- <div className="form-check">
31
- <input defaultValue="0" name={this.inputName()} type="hidden" type="hidden" />
32
- <input
33
- data-target={this.props["data-target"]}
34
- defaultChecked={this.inputDefaultChecked()}
35
- className={this.className()}
36
- data-action={this.props["data-action"]}
37
- defaultValue="1"
38
- id={id}
39
- name={this.inputName()}
40
- onChange={this.props.onChange}
41
- ref="input"
42
- type="checkbox"
43
- />
44
-
45
- {this.label() &&
46
- <label className={this.labelClassName()} htmlFor={id}>
47
- {this.label()}
48
- </label>
49
- }
50
- </div>
51
- {this.props.hint &&
52
- <p className="text-muted">
53
- {this.props.hint}
54
- </p>
55
- }
56
- </div>
57
- )
58
- }
59
-
60
- className() {
61
- var classNames = ["form-check-input"]
62
-
63
- if (this.props.className)
64
- classNames.push(this.props.className)
65
-
66
- return classNames.join(" ")
67
- }
68
-
69
- generatedId() {
70
- return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
71
- }
72
-
73
- inputDefaultChecked() {
74
- if ("defaultChecked" in this.props) {
75
- return this.props.defaultChecked
76
- } else if (this.props.model) {
77
- if (!this.props.model[this.props.attribute])
78
- throw new Error(`No such attribute: ${this.props.attribute}`)
79
-
80
- return this.props.model[this.props.attribute]()
81
- }
82
- }
83
-
84
- inputId() {
85
- if (this.props.id) {
86
- return this.props.id
87
- } else if (this.props.model) {
88
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
89
- } else {
90
- return this.generatedId()
91
- }
92
- }
93
-
94
- inputName() {
95
- if (this.props.name) {
96
- return this.props.name
97
- } else if (this.props.model) {
98
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
99
- }
100
- }
101
-
102
- wrapperClassName() {
103
- let classNames = ["component-bootstrap-checkbox"]
104
-
105
- if (this.props.wrapperClassName)
106
- classNames.push(this.props.wrapperClassName)
107
-
108
- return classNames.join(" ")
109
- }
110
-
111
- label() {
112
- if (this.props.label) {
113
- return this.props.label
114
- } else if (this.props.model) {
115
- return this.props.model.modelClass().humanAttributeName(this.props.attribute)
116
- }
117
- }
118
-
119
- labelClassName() {
120
- let classNames = ["form-check-label"]
121
-
122
- if (this.props.labelClassName)
123
- classNames.push(this.props.labelClassName)
124
-
125
- return classNames.join(" ")
126
- }
127
- }
@@ -1,105 +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 BootstrapCheckboxes extends React.Component {
8
- static propTypes = PropTypesExact({
9
- attribute: PropTypes.string,
10
- defaultValue: PropTypes.array,
11
- label: PropTypes.string,
12
- labelClassName: PropTypes.string,
13
- model: PropTypes.object,
14
- name: PropTypes.string,
15
- options: PropTypes.array.isRequired
16
- })
17
-
18
- render() {
19
- return (
20
- <div className="component-bootstrap-checkboxes form-group">
21
- <label className={this.labelClassName()}>
22
- {this.label()}
23
- </label>
24
-
25
- <input name={this.inputName()} type="hidden" value="" />
26
- {this.props.options.map((option, index) => this.optionElement(option, index))}
27
- </div>
28
- )
29
- }
30
-
31
- inputDefaultValue() {
32
- if (this.props.defaultValue) {
33
- return this.props.defaultValue
34
- } else if (this.props.model) {
35
- if (!this.props.model[this.props.attribute])
36
- throw `No such attribute: ${this.props.attribute}`
37
-
38
- return this.props.model[this.props.attribute]()
39
- }
40
- }
41
-
42
- inputName() {
43
- if (this.props.name) {
44
- return `${this.props.name}[]`
45
- } else if (this.props.model) {
46
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
47
- }
48
- }
49
-
50
- isDefaultSelected(option) {
51
- let defaultValue = this.inputDefaultValue()
52
-
53
- if (!defaultValue)
54
- return false
55
-
56
- if (defaultValue.constructor === Array) {
57
- return defaultValue.includes(option)
58
- } else {
59
- return defaultValue == option
60
- }
61
- }
62
-
63
- label() {
64
- if (this.props.label === false) {
65
- return null
66
- } else if (this.props.label) {
67
- return this.props.label
68
- } else if (this.props.model) {
69
- return this.props.model.modelClass().humanAttributeName(this.props.attribute)
70
- }
71
- }
72
-
73
- labelClassName() {
74
- let classNames = []
75
-
76
- if (this.props.labelClassName)
77
- classNames.push(this.props.labelClassName)
78
-
79
- return classNames.join(" ")
80
- }
81
-
82
- generatedId() {
83
- return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
84
- }
85
-
86
- optionElement(option) {
87
- var id = this.generatedId()
88
-
89
- return (
90
- <div className="checkboxes-option" key={`option-${option[1]}`}>
91
- <input
92
- data-option-value={option[1]}
93
- defaultChecked={this.isDefaultSelected(option[1])}
94
- id={id}
95
- name={this.inputName()}
96
- type="checkbox"
97
- value={option[1]} />
98
-
99
- <label className="ml-1" htmlFor={id}>
100
- {option[0]}
101
- </label>
102
- </div>
103
- )
104
- }
105
- }
@@ -1,168 +0,0 @@
1
- import Collection from "api-maker/collection"
2
- import EventCreated from "api-maker/event-created"
3
- import EventDestroyed from "api-maker/event-destroyed"
4
- import Paginate from "api-maker/paginate"
5
- import Params from "api-maker/params"
6
-
7
- const inflection = require("inflection")
8
-
9
- export default class LiveTable extends React.Component {
10
- static defaultProps = {
11
- preloads: [],
12
- select: {}
13
- }
14
-
15
- static propTypes = PropTypesExact({
16
- className: PropTypes.string,
17
- collection: PropTypes.instanceOf(Collection),
18
- columnsContent: PropTypes.func.isRequired,
19
- defaultParams: PropTypes.object,
20
- destroyMessage: PropTypes.string,
21
- filterContent: PropTypes.func,
22
- filterSubmitLabel: PropTypes.node,
23
- headersContent: PropTypes.func.isRequired,
24
- modelClass: PropTypes.func.isRequired,
25
- preloads: PropTypes.array.isRequired,
26
- queryName: PropTypes.string.isRequired,
27
- select: PropTypes.object
28
- })
29
-
30
- constructor(props) {
31
- super(props)
32
- this.state = {
33
- currentHref: location.href,
34
- queryQName: `${this.props.queryName}_q`,
35
- queryPageName: `${this.props.queryName}_page`
36
- }
37
- }
38
-
39
- componentDidMount() {
40
- this.loadQParams().then(() => this.loadModels())
41
- }
42
-
43
- componentDidUpdate() {
44
- if (this.state.currentHref != location.href) {
45
- var { queryQName } = this.state
46
- var params = Params.parse()
47
- var qParams = params[queryQName] || {}
48
- Params.setCachedParams(queryQName, qParams)
49
- this.setState({currentHref: location.href, qParams}, () => this.loadModels())
50
- }
51
- }
52
-
53
- async loadQParams() {
54
- var { queryQName } = this.state
55
- var qParams = await Params.getCachedParams(queryQName, {default: this.props.defaultParams || {}})
56
- return this.setState({qParams})
57
- }
58
-
59
- async loadModels() {
60
- var params = Params.parse()
61
- var { modelClass, preloads, select } = this.props
62
- var { qParams, queryPageName, queryQName } = this.state
63
- var query
64
-
65
- if (this.props.collection) {
66
- query = this.props.collection
67
- } else {
68
- query = modelClass
69
- }
70
-
71
- query = query
72
- .ransack(qParams)
73
- .searchKey(queryQName)
74
- .page(params[queryPageName])
75
- .pageKey(queryPageName)
76
- .preload(preloads)
77
- .select(select)
78
-
79
- var result = await query.result()
80
-
81
- this.setState({query, result, models: result.models()})
82
- }
83
-
84
- render() {
85
- var { qParams, query, result, models } = this.state
86
-
87
- return (
88
- <div className={this.className()}>
89
- {qParams && query && result && models && this.content()}
90
- </div>
91
- )
92
- }
93
-
94
- content() {
95
- var { filterContent, filterSubmitLabel, modelClass } = this.props
96
- var { qParams, query, result, models } = this.state
97
-
98
- return (
99
- <div className="content-container">
100
- <EventCreated modelClass={modelClass} onCreated={() => this.onModelCreated()} />
101
-
102
- {filterContent &&
103
- <Card className="mb-4">
104
- <form onSubmit={(e) => this.onFilterFormSubmit(e)} ref="filterForm">
105
- {filterContent({qParams})}
106
- <input className="btn btn-primary" label={filterSubmitLabel} type="submit" />
107
- </form>
108
- </Card>
109
- }
110
-
111
- {models.map(model =>
112
- <EventDestroyed key={`event-destroyed-${model.cacheKey()}`} model={model} onDestroyed={(args) => this.onModelDestroyed(args)} />
113
- )}
114
-
115
- <Card className="mb-4" striped table>
116
- <thead>
117
- <tr>
118
- {this.props.headersContent({query})}
119
- </tr>
120
- </thead>
121
- <tbody>
122
- {models.map(model =>
123
- <tr className={`${inflection.singularize(modelClass.modelClassData().collectionName)}-row`} data-model-id={model.id()} key={model.cacheKey()}>
124
- {this.props.columnsContent({model})}
125
- </tr>
126
- )}
127
- </tbody>
128
- </Card>
129
-
130
- <Paginate result={result} />
131
- </div>
132
- )
133
- }
134
-
135
- className() {
136
- var classNames = ["component-api-maker-live-table"]
137
-
138
- if (this.props.className)
139
- classNames.push(this.props.className)
140
-
141
- return classNames.join(" ")
142
- }
143
-
144
- onFilterFormSubmit(e) {
145
- e.preventDefault()
146
-
147
- var qParams = Params.serializeForm(this.refs.filterForm)
148
- var { queryQName } = this.state
149
-
150
- var changeParamsParams = {}
151
- changeParamsParams[queryQName] = qParams
152
-
153
- Params.changeParams(changeParamsParams)
154
- Params.setCachedParams(queryQName, qParams)
155
-
156
- this.setState({currentHref: location.href, qParams}, () => this.loadModels())
157
- }
158
-
159
- onModelCreated() {
160
- this.loadModels()
161
- }
162
-
163
- onModelDestroyed(args) {
164
- this.setState({
165
- models: this.state.models.filter(model => model.id() != args.model.id())
166
- })
167
- }
168
- }
@@ -1,136 +0,0 @@
1
- import Api from "api-maker/api"
2
- import formatNumber from "format-number"
3
- import PropTypes from "prop-types"
4
- import React from "react"
5
-
6
- const inflection = require("inflection")
7
-
8
- export default class BootstrapMoneyInput extends React.Component {
9
- constructor(props) {
10
- super(props)
11
- this.state = {}
12
-
13
- let formatOptions = {
14
- decimal: I18n.t("number.currency.format.separator"),
15
- integerSeparator: I18n.t("number.currency.format.delimiter")
16
- }
17
- this.formatter = formatNumber(formatOptions)
18
- }
19
-
20
- render() {
21
- return (
22
- <div className="component-api-maker-bootstrap-money-input">
23
- <input defaultValue={this.inputDefaultCentsValue()} id={this.inputCentsId()} name={this.inputCentsName()} ref="input" type="hidden" />
24
-
25
- <div className="input-group">
26
- <input
27
- className={this.props.className}
28
- defaultValue={this.inputDefaultValue()}
29
- id={this.inputId()}
30
- onBlur={() => this.setAmount()}
31
- onChange={() => this.setCents()}
32
- onKeyUp={() => this.setCents()}
33
- placeholder={this.props.placeholder}
34
- ref="whole"
35
- type="text"
36
- />
37
- <select className="component-bootstrap-money-input" defaultValue={this.inputCurrencyValue()} id={this.inputCurrencyId()} name={this.inputCurrencyName()} onChange={() => { this.onCurrencyChanged() }} ref="currency">
38
- <option></option>
39
- {this.props.currenciesCollection.map(option => (
40
- <option key={`select-option-${option[1]}`} value={option[1]}>
41
- {this.props.small && option[1]}
42
- {!this.props.small && option[0]}
43
- </option>
44
- ))}
45
- </select>
46
- </div>
47
- </div>
48
- )
49
- }
50
-
51
- inputCurrencyId() {
52
- return `${this.inputId()}_currency`
53
- }
54
-
55
- inputCurrencyName() {
56
- if (this.props.currencyName)
57
- return this.props.currencyName
58
-
59
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}_currency]`
60
- }
61
-
62
- inputCurrencyValue() {
63
- let value = this.props.model[this.props.attribute]()
64
-
65
- if (value) {
66
- return MoneyFormatter.currencyFromMoney(value).code
67
- } else {
68
- return "DKK"
69
- }
70
- }
71
-
72
- inputDefaultValue() {
73
- let value = this.props.model[this.props.attribute]()
74
-
75
- if (value) {
76
- return MoneyFormatter.fromMoney({amount: value.amount, currency: this.inputCurrencyValue()}, {decimals: 2, excludeCurrency: true}).toString()
77
- } else {
78
- return ""
79
- }
80
- }
81
-
82
- inputDefaultCentsValue() {
83
- let value = this.props.model[this.props.attribute]()
84
-
85
- if (this.refs.input)
86
- return this.refs.input.value
87
-
88
- if (value)
89
- return MoneyFormatter.amountFromMoney(value)
90
- }
91
-
92
- inputCentsId() {
93
- return `${this.inputId()}_cents`
94
- }
95
-
96
- inputCentsName() {
97
- if (this.props.name)
98
- return this.props.name
99
-
100
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}_cents]`
101
- }
102
-
103
- inputId() {
104
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
105
- }
106
-
107
- onCurrencyChanged() {
108
- if (this.props.onChange)
109
- this.props.onChange()
110
- }
111
-
112
- setAmount() {
113
- if (!this.refs.input.value && this.refs.input.value == "") {
114
- this.refs.whole.value = ""
115
- } else {
116
- let cents = parseFloat(this.refs.input.value)
117
- let formatted = MoneyFormatter.fromMoney({amount: cents, currency: this.inputCurrencyValue()}, {decimals: 2, excludeCurrency: true}).toString()
118
-
119
- this.refs.whole.value = formatted
120
- }
121
- }
122
-
123
- setCents() {
124
- let whole = MoneyFormatter.stringToFloat(this.refs.whole.value)
125
- let cents = parseInt(whole * 100)
126
- let oldCents = parseInt(this.refs.input.value)
127
- this.refs.input.value = cents
128
-
129
- if (this.props.onChange && oldCents != cents)
130
- this.props.onChange()
131
- }
132
- }
133
-
134
- BootstrapMoneyInput.propTypes = {
135
- currenciesCollection: PropTypes.array.isRequired
136
- }
@@ -1,80 +0,0 @@
1
- import PropTypesExact from "prop-types-exact"
2
- import React from "react"
3
-
4
- const inflection = require("inflection")
5
-
6
- export default class BootstrapRadioButtons extends React.Component {
7
- static propTypes = PropTypesExact({
8
- attribute: PropTypes.string,
9
- collection: PropTypes.array.isRequired,
10
- defaultValue: PropTypes.oneOfType([
11
- PropTypes.number,
12
- PropTypes.string
13
- ]),
14
- id: PropTypes.string,
15
- name: PropTypes.string,
16
- model: PropTypes.object,
17
- wrapperClassName: PropTypes.string
18
- })
19
-
20
- render() {
21
- return (
22
- <div className={this.wrapperClassName()}>
23
- <input name={this.inputName()} type="hidden" value="" />
24
- {this.props.collection.map(option => this.optionElement(option))}
25
- </div>
26
- )
27
- }
28
-
29
- inputDefaultValue() {
30
- if (this.props.defaultValue) {
31
- return this.props.defaultValue
32
- } else if (this.props.model) {
33
- if (!this.props.model[this.props.attribute])
34
- throw new Error(`No such attribute: ${this.props.attribute}`)
35
-
36
- return this.props.model[this.props.attribute]()
37
- }
38
- }
39
-
40
- inputName() {
41
- if (this.props.name) {
42
- return this.props.name
43
- } else if (this.props.model) {
44
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
45
- }
46
- }
47
-
48
- generatedId() {
49
- return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
50
- }
51
-
52
- optionElement(option) {
53
- let id = this.generatedId()
54
-
55
- return (
56
- <div key={`option-${option[1]}`}>
57
- <input
58
- data-option-value={option[1]}
59
- defaultChecked={option[1] == this.inputDefaultValue()}
60
- id={id}
61
- name={this.inputName()}
62
- type="radio"
63
- value={option[1]} />
64
-
65
- <label className="ml-1" htmlFor={id}>
66
- {option[0]}
67
- </label>
68
- </div>
69
- )
70
- }
71
-
72
- wrapperClassName() {
73
- var classNames = ["component-bootstrap-radio-buttons"]
74
-
75
- if (this.props.wrapperClassName)
76
- classNames.push(this.props.wrapperClassName)
77
-
78
- return classNames.join(" ")
79
- }
80
- }