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.
- checksums.yaml +4 -4
- data/app/api_maker/api_helpers/api_maker_helpers.rb +5 -0
- data/app/api_maker/services/can_can/load_abilities.rb +30 -0
- data/app/api_maker/services/devise/sign_in.rb +64 -0
- data/app/api_maker/services/devise/sign_out.rb +9 -0
- data/app/api_maker/services/models/find_or_create_by.rb +18 -0
- data/app/channels/api_maker/subscriptions_channel.rb +33 -2
- data/app/controllers/api_maker/base_controller.rb +7 -3
- data/app/controllers/api_maker/commands_controller.rb +26 -4
- data/app/controllers/api_maker/session_statuses_controller.rb +1 -1
- data/app/services/api_maker/abilities_loader.rb +104 -0
- data/app/services/api_maker/application_service.rb +2 -1
- data/app/services/api_maker/base_command.rb +248 -0
- data/app/services/api_maker/collection_command_service.rb +29 -15
- data/app/services/api_maker/collection_loader.rb +124 -0
- data/app/services/api_maker/command_failed_error.rb +3 -0
- data/app/services/api_maker/command_response.rb +17 -6
- data/app/services/api_maker/command_service.rb +3 -3
- data/app/services/api_maker/create_command.rb +11 -26
- data/app/services/api_maker/create_command_service.rb +3 -3
- data/app/services/api_maker/database_type.rb +9 -0
- data/app/services/api_maker/deep_merge_params.rb +26 -0
- data/app/services/api_maker/deserializer.rb +35 -0
- data/app/services/api_maker/destroy_command.rb +15 -21
- data/app/services/api_maker/destroy_command_service.rb +3 -3
- data/app/services/api_maker/generate_react_native_api_service.rb +3 -19
- data/app/services/api_maker/include_helpers.rb +17 -0
- data/app/services/api_maker/index_command.rb +8 -88
- data/app/services/api_maker/index_command_service.rb +5 -5
- data/app/services/api_maker/js_method_namer_service.rb +1 -1
- data/app/services/api_maker/locals_from_controller.rb +14 -0
- data/app/services/api_maker/member_command_service.rb +15 -13
- data/app/services/api_maker/model_classes_java_script_generator_service.rb +37 -0
- data/app/services/api_maker/model_content_generator_service.rb +17 -21
- data/app/services/api_maker/models/save.rb +29 -0
- data/app/services/api_maker/models_finder_service.rb +6 -2
- data/app/services/api_maker/models_generator_service.rb +6 -43
- data/app/services/api_maker/move_components_to_routes.rb +50 -0
- data/app/services/api_maker/primary_id_for_model.rb +6 -0
- data/app/services/api_maker/reset_indexed_db_service.rb +36 -0
- data/app/services/api_maker/routes_file_reloader.rb +20 -0
- data/app/services/api_maker/select_columns_on_collection.rb +78 -0
- data/app/services/api_maker/select_parser.rb +32 -0
- data/app/services/api_maker/service_command.rb +27 -0
- data/app/services/api_maker/service_command_service.rb +14 -0
- data/app/services/api_maker/simple_model_errors.rb +52 -0
- data/app/services/api_maker/update_command.rb +8 -24
- data/app/services/api_maker/update_command_service.rb +3 -3
- data/app/services/api_maker/valid_command.rb +4 -13
- data/app/services/api_maker/valid_command_service.rb +3 -3
- data/app/services/api_maker/validation_errors_generator_service.rb +146 -0
- data/app/views/api_maker/_data.html.erb +17 -11
- data/config/routes.rb +0 -2
- data/lib/api_maker/ability.rb +22 -7
- data/lib/api_maker/ability_loader.rb +9 -6
- data/lib/api_maker/base_collection_instance.rb +15 -0
- data/lib/api_maker/base_resource.rb +135 -9
- data/lib/api_maker/base_service.rb +14 -0
- data/lib/api_maker/collection_serializer.rb +95 -34
- data/lib/api_maker/command_spec_helper.rb +41 -11
- data/lib/api_maker/configuration.rb +31 -4
- data/lib/api_maker/expect_to_able_to_helper.rb +31 -0
- data/lib/api_maker/individual_command.rb +24 -9
- data/lib/api_maker/javascript/model-template.js.erb +39 -25
- data/lib/api_maker/javascript/models.js.erb +6 -0
- data/lib/api_maker/loader.rb +1 -1
- data/lib/api_maker/memory_storage.rb +1 -1
- data/lib/api_maker/model_extensions.rb +34 -18
- data/lib/api_maker/permitted_params_argument.rb +5 -1
- data/lib/api_maker/preloader.rb +71 -32
- data/lib/api_maker/preloader_base.rb +108 -0
- data/lib/api_maker/preloader_belongs_to.rb +34 -33
- data/lib/api_maker/preloader_has_many.rb +45 -39
- data/lib/api_maker/preloader_has_one.rb +30 -47
- data/lib/api_maker/railtie.rb +3 -11
- data/lib/api_maker/relationship_preloader.rb +42 -0
- data/lib/api_maker/resource_routing.rb +18 -4
- data/lib/api_maker/result_parser.rb +34 -20
- data/lib/api_maker/serializer.rb +53 -22
- data/lib/api_maker/spec_helper/browser_logs.rb +14 -0
- data/lib/api_maker/spec_helper/execute_collection_command.rb +46 -0
- data/lib/api_maker/spec_helper/execute_member_command.rb +52 -0
- data/lib/api_maker/spec_helper/expect_no_browser_errors.rb +18 -0
- data/lib/api_maker/spec_helper/wait_for_expect.rb +20 -0
- data/lib/api_maker/spec_helper/wait_for_flash_message.rb +21 -0
- data/lib/api_maker/spec_helper.rb +112 -48
- data/lib/api_maker/version.rb +1 -1
- data/lib/api_maker.rb +7 -3
- metadata +108 -89
- data/README.md +0 -476
- data/app/controllers/api_maker/devise_controller.rb +0 -60
- data/lib/api_maker/base_command.rb +0 -81
- data/lib/api_maker/javascript/api.js +0 -92
- data/lib/api_maker/javascript/base-model.js +0 -543
- data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +0 -16
- data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +0 -47
- data/lib/api_maker/javascript/bootstrap/card.jsx +0 -79
- data/lib/api_maker/javascript/bootstrap/checkbox.jsx +0 -127
- data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +0 -105
- data/lib/api_maker/javascript/bootstrap/live-table.jsx +0 -168
- data/lib/api_maker/javascript/bootstrap/money-input.jsx +0 -136
- data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +0 -80
- data/lib/api_maker/javascript/bootstrap/select.jsx +0 -168
- data/lib/api_maker/javascript/bootstrap/string-input.jsx +0 -203
- data/lib/api_maker/javascript/cable-connection-pool.js +0 -169
- data/lib/api_maker/javascript/cable-subscription-pool.js +0 -111
- data/lib/api_maker/javascript/cable-subscription.js +0 -33
- data/lib/api_maker/javascript/collection.js +0 -186
- data/lib/api_maker/javascript/commands-pool.js +0 -123
- data/lib/api_maker/javascript/custom-error.js +0 -14
- data/lib/api_maker/javascript/deserializer.js +0 -35
- data/lib/api_maker/javascript/devise.js.erb +0 -113
- data/lib/api_maker/javascript/error-logger.js +0 -119
- data/lib/api_maker/javascript/event-connection.jsx +0 -24
- data/lib/api_maker/javascript/event-created.jsx +0 -26
- data/lib/api_maker/javascript/event-destroyed.jsx +0 -26
- data/lib/api_maker/javascript/event-emitter-listener.jsx +0 -32
- data/lib/api_maker/javascript/event-listener.jsx +0 -41
- data/lib/api_maker/javascript/event-updated.jsx +0 -26
- data/lib/api_maker/javascript/form-data-to-object.js +0 -70
- data/lib/api_maker/javascript/included.js +0 -39
- data/lib/api_maker/javascript/key-value-store.js +0 -47
- data/lib/api_maker/javascript/logger.js +0 -23
- data/lib/api_maker/javascript/model-name.js +0 -21
- data/lib/api_maker/javascript/models-response-reader.js +0 -43
- data/lib/api_maker/javascript/paginate.jsx +0 -128
- data/lib/api_maker/javascript/params.js +0 -68
- data/lib/api_maker/javascript/resource-route.jsx +0 -75
- data/lib/api_maker/javascript/resource-routes.jsx +0 -36
- data/lib/api_maker/javascript/result.js +0 -25
- data/lib/api_maker/javascript/session-status-updater.js +0 -113
- data/lib/api_maker/javascript/sort-link.jsx +0 -88
- data/lib/api_maker/javascript/updated-attribute.jsx +0 -60
- data/lib/api_maker/preloader_through.rb +0 -101
- 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
|
-
}
|