lanes 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/client/lanes/Config.coffee +3 -1
  4. data/client/lanes/access/screens/user-management/UserManagement.cjsx +2 -2
  5. data/client/lanes/components/grid/Body.cjsx +8 -1
  6. data/client/lanes/components/grid/EditingMixin.cjsx +5 -2
  7. data/client/lanes/components/grid/Grid.cjsx +1 -1
  8. data/client/lanes/components/grid/PopOverMixin.cjsx +1 -1
  9. data/client/lanes/components/grid/row-editor.scss +6 -0
  10. data/client/lanes/components/grid/styles.scss +1 -1
  11. data/client/lanes/components/record-finder/RecordFinder.cjsx +22 -16
  12. data/client/lanes/components/select-field/SelectField.cjsx +20 -27
  13. data/client/lanes/components/shared/DateTime.cjsx +12 -23
  14. data/client/lanes/components/shared/DisplayValue.cjsx +5 -10
  15. data/client/lanes/components/shared/FieldMixin.cjsx +107 -56
  16. data/client/lanes/components/shared/FieldWrapper.cjsx +59 -6
  17. data/client/lanes/components/shared/FormGroup.cjsx +3 -8
  18. data/client/lanes/components/shared/Helpers.coffee +1 -1
  19. data/client/lanes/components/shared/Icon.cjsx +1 -1
  20. data/client/lanes/components/shared/ImageAsset.cjsx +46 -0
  21. data/client/lanes/components/shared/Input.cjsx +5 -1
  22. data/client/lanes/components/shared/InputFieldMixin.cjsx +8 -27
  23. data/client/lanes/components/shared/NumberInput.cjsx +11 -4
  24. data/client/lanes/components/shared/RadioField.cjsx +18 -8
  25. data/client/lanes/components/shared/ScreenWrapper.cjsx +1 -1
  26. data/client/lanes/components/shared/TextArea.cjsx +15 -0
  27. data/client/lanes/components/shared/ToggleField.cjsx +11 -19
  28. data/client/lanes/components/shared/fields.scss +22 -76
  29. data/client/lanes/components/shared/{image-saver.scss → image-asset.scss} +1 -1
  30. data/client/lanes/components/shared/styles.scss +1 -1
  31. data/client/lanes/components/toolbar/RemoteChangeSets.cjsx +13 -10
  32. data/client/lanes/components/toolbar/changes-notification.scss +14 -1
  33. data/client/lanes/extension/Base.coffee +5 -1
  34. data/client/lanes/models/Asset.coffee +81 -0
  35. data/client/lanes/models/AssociationMap.coffee +14 -5
  36. data/client/lanes/models/AssociationProxy.coffee +9 -6
  37. data/client/lanes/models/Base.coffee +6 -3
  38. data/client/lanes/models/Collection.coffee +1 -3
  39. data/client/lanes/models/JobStatus.coffee +3 -0
  40. data/client/lanes/models/Query.coffee +3 -2
  41. data/client/lanes/models/Sync.coffee +6 -4
  42. data/client/lanes/react/mixins/Access.coffee +1 -1
  43. data/client/lanes/react/mixins/Data.coffee +33 -31
  44. data/client/lanes/screens/Commands.coffee +0 -1
  45. data/client/lanes/screens/Definitions.coffee +1 -1
  46. data/client/lanes/screens/SystemSettings.cjsx +23 -11
  47. data/client/lanes/screens/UserPreferences.cjsx +3 -2
  48. data/client/lanes/styles/bootstrap-custom-grid.scss +6 -4
  49. data/client/lanes/styles/fonts.scss +9 -0
  50. data/client/lanes/styles/global/styles.scss +1 -0
  51. data/client/lanes/styles/variables.scss +1 -1
  52. data/client/lanes/testing/Helpers.coffee +5 -3
  53. data/client/lanes/vendor/development/base.js +17206 -19211
  54. data/client/lanes/vendor/development/calendar.js +67 -471
  55. data/client/lanes/vendor/development/commons.js +21680 -19814
  56. data/client/lanes/vendor/development/helpers.js +40 -29
  57. data/client/lanes/vendor/development/toggle.js +22 -19
  58. data/client/lanes/vendor/development/widgets.js +2476 -2625
  59. data/client/lanes/vendor/production/base.js +19034 -21038
  60. data/client/lanes/vendor/production/calendar.js +67 -471
  61. data/client/lanes/vendor/production/commons.js +21369 -19136
  62. data/client/lanes/vendor/production/toggle.js +22 -19
  63. data/client/lanes/vendor/production/widgets.js +2476 -2625
  64. data/client/lanes/vendor/styles/widgets.scss +2 -0
  65. data/client/lanes/workspace/FirstRun.cjsx +69 -0
  66. data/client/lanes/workspace/Navbar.cjsx +4 -2
  67. data/client/lanes/workspace/ScreenView.cjsx +9 -1
  68. data/client/lanes/workspace/index.js +1 -0
  69. data/client/lanes/workspace/styles/screens.scss +11 -0
  70. data/config/database.yml +2 -2
  71. data/db/migrate/01_create_system_settings.rb +0 -1
  72. data/db/migrate/02_create_assets.rb +15 -0
  73. data/lanes.gemspec +25 -28
  74. data/lib/lanes/access/authentication_provider.rb +20 -7
  75. data/lib/lanes/access/role_collection.rb +9 -2
  76. data/lib/lanes/api/default_routes.rb +4 -4
  77. data/lib/lanes/api/formatted_reply.rb +15 -11
  78. data/lib/lanes/api/handlers/asset.rb +37 -0
  79. data/lib/lanes/api/request_wrapper.rb +18 -4
  80. data/lib/lanes/api/routing.rb +17 -6
  81. data/lib/lanes/api/updates.rb +1 -1
  82. data/lib/lanes/api.rb +1 -1
  83. data/lib/lanes/asset.rb +38 -0
  84. data/lib/lanes/concerns/all.rb +1 -1
  85. data/lib/lanes/concerns/asset_uploader.rb +60 -0
  86. data/lib/lanes/configuration.rb +1 -2
  87. data/lib/lanes/extension.rb +1 -1
  88. data/lib/lanes/logger.rb +26 -16
  89. data/lib/lanes/system_settings.rb +13 -8
  90. data/lib/lanes/version.rb +1 -1
  91. data/lib/lanes.rb +1 -0
  92. data/npm-build/base.js +1 -1
  93. data/npm-build/package.json +9 -9
  94. data/spec/command-reference-files/initial/Gemfile +1 -1
  95. data/spec/fixtures/logo.png +0 -0
  96. data/spec/lanes/components/grid/PopoverEditorSpec.coffee +48 -0
  97. data/spec/server/asset_spec.rb +34 -0
  98. data/spec/server/spec_helper.rb +14 -2
  99. metadata +118 -127
  100. data/client/lanes/components/shared/ControlLabel.cjsx +0 -45
  101. data/client/lanes/components/shared/ImageSaver.cjsx +0 -33
  102. data/client/lanes/models/SystemSettings.coffee +0 -0
  103. data/client/lanes/models/mixins/FileSupport.coffee +0 -60
  104. data/lib/lanes/api/handlers/file.rb +0 -26
  105. data/lib/lanes/concerns/image_uploader.rb +0 -42
@@ -1,45 +0,0 @@
1
- class InvalidTag extends Lanes.React.BaseComponent
2
-
3
- mixins: [
4
- Lanes.React.Mixins.ReadEditingState
5
- Lanes.React.Mixins.FieldErrors
6
- Lanes.React.Mixins.Viewport
7
- ]
8
-
9
- render: ->
10
- return null unless (invalidMsg = @fieldInvalidValueMessage())
11
- tooltip =
12
- <BS.Tooltip id="error-tooltip">{invalidMsg}</BS.Tooltip>
13
- <BS.OverlayTrigger
14
- delayShow={300} delayHide={150} container={@context.viewport.lanes}
15
- placement="top" overlay={tooltip}
16
- >
17
- <span ref='target'>
18
- <LC.Icon ref='target' type='exclamation-triangle' className='error' />
19
- </span>
20
- </BS.OverlayTrigger>
21
-
22
- class Lanes.Components.ControlLabel extends Lanes.React.Component
23
-
24
- mixins: [
25
- Lanes.React.Mixins.ReadEditingState
26
- Lanes.React.Mixins.FieldErrors
27
- ]
28
-
29
- propTypes:
30
- model: Lanes.PropTypes.State
31
- invalidMsg: React.PropTypes.string
32
- focusInput: (ev) ->
33
- _.dom(ev.target).closest('.form-group')
34
- .qs('input', raise: false).focusAndSelect()
35
- render: ->
36
- if @props.titleOnly
37
- <span className="label-title-only">
38
- {@props.label}
39
- <InvalidTag {...@props} />
40
- </span>
41
- else
42
- <label className="control-label" onClick={@focusInput}>
43
- <span className="label-title">{@props.label}</span>
44
- <InvalidTag {...@props} />
45
- </label>
@@ -1,33 +0,0 @@
1
- class Lanes.Components.ImageSaver extends Lanes.React.Component
2
-
3
- propTypes:
4
- model: Lanes.PropTypes.Model
5
- name: React.PropTypes.string.isRequired
6
-
7
- listenNetworkEvents: true
8
- bindDataEvents: ->
9
- model: "change:#{@props.name} change:#{@props.name}_data"
10
-
11
- uploadImage: ->
12
- imageFormData = new FormData()
13
- imageFormData.append('imageFile', imageFile)
14
-
15
- handleImageChange: (ev) ->
16
- ev.preventDefault()
17
- @model.set("#{@props.name}_file", ev.target.files[0])
18
-
19
- renderImage: ->
20
- <img className="preview" src={@model.imageUrlFor('logo', 'thumb')} />
21
-
22
- render: ->
23
- value = if @model.hasImage(@props.name) then @renderImage() else null
24
- className = _.classnames(@props.className, 'image-saver', {'with-image': @model.hasImage(@props.name)})
25
- <LC.FieldWrapper {...@props} className={className} value={value}>
26
- {value}
27
- <form>
28
- <label className="selector">
29
- {if value then 'Update' else 'Choose'}
30
- <input id='file' className="file" type="file" onChange={@handleImageChange} />
31
- </label>
32
- </form>
33
- </LC.FieldWrapper>
File without changes
@@ -1,60 +0,0 @@
1
- isFileDefinition = (def) ->
2
- (_.isString(def) and def is 'file') or (_.isObject(def) and def.type is 'file')
3
-
4
- Lanes.Models.Mixins.FileSupport = {
5
-
6
- included: (klass) ->
7
- files = _.pickBy klass::props, (def, name) -> isFileDefinition(def)
8
- return if _.isEmpty(files)
9
- session = {}
10
- for name, def of files
11
- session["#{name}_data"] = 'any'
12
- session["#{name}_file"] = 'any'
13
- _.extend( klass::session ||= {}, session)
14
-
15
- initialize: ->
16
- @on('save', @_uploadFileAfterSave)
17
- for name, def of @_definition when isFileDefinition(def)
18
- @on("change:#{name}_file", _.partial(@readPossibleImage, name))
19
-
20
- hasImage: (attr) ->
21
- this[attr] || this["#{attr}_data"]
22
-
23
- imageUrlFor: (attr, type = '') ->
24
- if this["#{attr}_data"]
25
- this["#{attr}_data"]
26
- else if (file = this[attr])
27
- if type then file[type].url else file.url
28
- else
29
- ''
30
-
31
- readPossibleImage: (name) ->
32
- return unless (file = this["#{name}_file"])
33
- reader = new FileReader()
34
- reader.onloadend = =>
35
- @["#{name}_data"] = reader.result
36
- reader.readAsDataURL(file)
37
-
38
-
39
- _uploadFileAfterSave: ->
40
- files = _.pickBy @_definition, (def, name) =>
41
- isFileDefinition(def) and @["#{name}_file"]
42
- return if _.isEmpty(files)
43
-
44
- form = new FormData()
45
- for name, def of files
46
- form.append("files[#{name}]", this["#{name}_file"], this["#{name}_file"].name)
47
- form.append("type", @modelTypeIdentifier())
48
- form.append("id", @getId())
49
- form.append("extension_id", @FILE.extension.identifier)
50
- url = Lanes.config.api_path + '/save-file-attribute'
51
-
52
- Lanes.Vendor.xhr.post(url, {body: form}, (err, resp, body) =>
53
- if err
54
- @errors = { http: err.message }
55
- else
56
- model = JSON.parse(body)?.data?.model
57
- @set(model)
58
- this["#{name}_data"] = this["#{name}_file"] = null for name, def of files
59
- )
60
- }
@@ -1,26 +0,0 @@
1
- module Lanes::API::Handlers
2
-
3
- class File
4
-
5
- def self.saver
6
- lambda do
7
- Lanes.logger.debug "Saving File. Root=#{CarrierWave.root}"
8
- path = "#{params['extension_id']}/#{params['type']}"
9
- model = path.underscore.camelize.constantize
10
- record = model.find(params['id'])
11
- params['files'].each do |attr, data|
12
- record.send(attr).store!( data )
13
- end
14
- record.save!
15
-
16
- json_reply std_api_reply :create, { model: record }, success: true
17
- end
18
- end
19
-
20
- def self.getter
21
- lambda do
22
- send_file CarrierWave::Uploader::Base.root.call + '/' + params['splat'].first
23
- end
24
- end
25
- end
26
- end
@@ -1,42 +0,0 @@
1
- require 'mini_magick'
2
- require 'carrierwave'
3
- require 'fastimage'
4
-
5
- module Lanes::Concerns
6
-
7
- class ImageUploader < CarrierWave::Uploader::Base
8
-
9
- include CarrierWave::MiniMagick
10
-
11
- version :medium do
12
- process :resize_to_fit => [800, 800]
13
- end
14
-
15
- version :thumb do
16
- process :resize_to_fit => [200,200]
17
- end
18
-
19
- def cache_dir
20
- '/tmp'
21
- end
22
-
23
- def store_dir
24
- "images/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
25
- end
26
-
27
- def filename
28
- if original_filename.present?
29
- ext = FastImage.type(file.file)
30
- "#{secure_token}.#{ext}"
31
- end
32
- end
33
-
34
- protected
35
-
36
- def secure_token
37
- var = :"@#{mounted_as}_secure_token"
38
- model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.hex(6))
39
- end
40
- end
41
-
42
- end