loft 0.2.9 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9cbfd6f82a45ab219e1d1e8f34a640d5bb097387
4
- data.tar.gz: 52b5b9f14e48113f6c3a20da073b5789e92a8945
3
+ metadata.gz: bfbd343f5dbe51c685e42a35545b11ba6cfc9a75
4
+ data.tar.gz: d170f5aae6bf0409f13384c08a5f681fa3b0a271
5
5
  SHA512:
6
- metadata.gz: 22af5dff677b1b59fc1c5e17fba5fe8a4096b14705ba32f74b25ba69c2f10f9cb314e1489d6c58b7cc4d1bf4d952bc697bf005f8070e61a42a0e1f44da4694e1
7
- data.tar.gz: 29c7aef7a66ae2bbccdd765dfae06aa2451917c87f4e2c1127e1d5f732ced3f122d5c37c74ac1006eadb8ff190950c085e309f660914a2f9cefffab7d6388ed0
6
+ metadata.gz: 97cbd7ec0cf1be3aa5dcfeeed783771992fc0fa9aa6ab1eec0325924be97f4936130fd9ede409c1370195cd2855156359a10246cc6e163877c51399d5e5f409c
7
+ data.tar.gz: 2ac7ed3b842e923257cb9a3dc5950b825f9f5768f7f73ca6939364477ccf3993099ca9064fcc10a024b9d794a45eca9bbf2063408e97c3c74578b815b268b5ed
@@ -7,5 +7,8 @@
7
7
  ## OPTIONAL
8
8
  # require loft/redactor-loft
9
9
 
10
+ @Icons.upload = "<i class='fa fa-cloud-upload'></i>"
11
+ @Icons.remove = "<i class='fa fa-close'></i>"
12
+
10
13
  # TODOs:
11
- # - refactor group remove action: delete a bunch first, then reload the page
14
+ # - refactor group remove action: delete a bunch first, then reload the page
@@ -1,11 +1,6 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  # Author: Alexander Kravets <alex@slatestudio.com>,
3
3
  # Slate Studio (http://www.slatestudio.com)
4
- #
5
- # Coding Guide:
6
- # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
- # -----------------------------------------------------------------------------
8
-
9
4
  # -----------------------------------------------------------------------------
10
5
  # Loft Asset Item
11
6
  # -----------------------------------------------------------------------------
@@ -14,8 +9,7 @@ class @LoftAssetItem extends Item
14
9
  @$el =$ "<div class='item asset asset-#{ @object.type }' data-id='#{ @object._id }'></div>"
15
10
  @render()
16
11
 
17
-
18
- # PRIVATE ===============================================
12
+ # PRIVATE ===================================================================
19
13
 
20
14
  _bind_name_input: ->
21
15
  @$nameInput.on 'blur', (e) => @_update_name_if_changed()
@@ -23,18 +17,15 @@ class @LoftAssetItem extends Item
23
17
  if e.keyCode == 13 then $(e.target).blur()
24
18
  if e.keyCode == 27 then @_cancel_name_change()
25
19
 
26
-
27
20
  _edit_name: (e) ->
28
21
  @$el.addClass('edit-name')
29
22
  @$nameInput.focus().select()
30
23
 
31
-
32
24
  _cancel_name_change: ->
33
25
  @$el.removeClass('edit-name')
34
26
  name = @$title.html()
35
27
  @$nameInput.val(name)
36
28
 
37
-
38
29
  _update_name_if_changed: ->
39
30
  @$el.removeClass('edit-name')
40
31
  name = @$nameInput.val()
@@ -46,8 +37,7 @@ class @LoftAssetItem extends Item
46
37
  onSuccess: (object) =>
47
38
  onError: (errors) => # process errors
48
39
 
49
-
50
- # PUBLIC ================================================
40
+ # PUBLIC ====================================================================
51
41
 
52
42
  render: ->
53
43
  @$el.html('').removeClass('item-folder has-subtitle has-thumbnail')
@@ -72,7 +62,6 @@ class @LoftAssetItem extends Item
72
62
  @$checkbox.append(@$checkboxInput)
73
63
  @$el.prepend(@$checkbox)
74
64
 
75
-
76
65
  # input for assets name
77
66
  name = @$title.text()
78
67
  @$name =$ "<div class='asset-name'></div>"
@@ -83,7 +72,3 @@ class @LoftAssetItem extends Item
83
72
 
84
73
  # handler for asset name change on title click
85
74
  @$title.on 'click', (e) => @_edit_name(e)
86
-
87
-
88
-
89
-
@@ -1,11 +1,6 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  # Author: Alexander Kravets <alex@slatestudio.com>,
3
3
  # Slate Studio (http://www.slatestudio.com)
4
- #
5
- # Coding Guide:
6
- # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
- # -----------------------------------------------------------------------------
8
-
9
4
  # -----------------------------------------------------------------------------
10
5
  # Loft Group Actions
11
6
  # -----------------------------------------------------------------------------
@@ -14,8 +9,7 @@ class @LoftGroupActions
14
9
  @_render()
15
10
  @_bind_checkboxes()
16
11
 
17
-
18
- # PRIVATE ===============================================
12
+ # PRIVATE ===================================================================
19
13
 
20
14
  _render: ->
21
15
  @$el =$ "<div class='assets-group-actions' style='display:none;'></div>"
@@ -36,7 +30,6 @@ class @LoftGroupActions
36
30
  @$unselectBtn.on 'click', (e) => e.preventDefault(); @_unselect_list_items()
37
31
  @$el.append @$unselectBtn
38
32
 
39
-
40
33
  _bind_checkboxes: ->
41
34
  @list.$el.on 'click', '.asset .asset-checkbox input', (e) =>
42
35
  # when multiple selection disabled select only one asset a time
@@ -49,22 +42,19 @@ class @LoftGroupActions
49
42
  else
50
43
  @hide()
51
44
 
52
-
53
45
  _select_single_item: ($checkbox) ->
54
46
  if $checkbox.prop('checked')
55
47
  @list.$el.find('.asset .asset-checkbox input:checked').prop('checked' , false)
56
48
  $checkbox.prop('checked', true)
57
49
 
58
-
59
50
  _selected_list_items: ->
60
- $.map @list.$el.find('.asset .asset-checkbox input:checked'), (checkbox) -> $(checkbox).parent().parent()
61
-
51
+ $.map @list.$el.find('.asset .asset-checkbox input:checked'), (checkbox) ->
52
+ $(checkbox).parent().parent()
62
53
 
63
54
  _unselect_list_items: ->
64
55
  @list.$el.find('.asset .asset-checkbox input').prop('checked', false)
65
56
  @hide()
66
57
 
67
-
68
58
  _delete_selected_list_items: ->
69
59
  if confirm("Are you sure?")
70
60
  $selectedItems = @_selected_list_items()
@@ -79,7 +69,6 @@ class @LoftGroupActions
79
69
  onError: => # error notification
80
70
  @hide()
81
71
 
82
-
83
72
  _accept_selected_items: ->
84
73
  $selectedItems = @_selected_list_items()
85
74
 
@@ -96,16 +85,10 @@ class @LoftGroupActions
96
85
  else
97
86
  @loft.onAcceptCallback(objects, => @loft.closeModal())
98
87
 
99
-
100
88
  _show: ->
101
89
  @$el.show()
102
90
 
103
-
104
- # PUBLIC ================================================
91
+ # PUBLIC ====================================================================
105
92
 
106
93
  hide: ->
107
94
  @$el.hide()
108
-
109
-
110
-
111
-
@@ -1,36 +1,41 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  # Author: Alexander Kravets <alex@slatestudio.com>,
3
3
  # Slate Studio (http://www.slatestudio.com)
4
- #
5
- # Coding Guide:
6
- # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
- # -----------------------------------------------------------------------------
8
-
9
4
  # -----------------------------------------------------------------------------
10
5
  # INPUT LOFT IMAGE
11
6
  # -----------------------------------------------------------------------------
12
7
  class @InputLoftImage extends InputString
13
8
 
14
- # PRIVATE ===============================================
9
+ # PRIVATE ===================================================================
15
10
 
16
11
  _add_input: ->
17
- @config.placeholder ?= 'Image url'
12
+ @config.placeholder ?= 'Image URL'
13
+
14
+ type = "string"
15
+ if @config.fullsizePreview
16
+ @$el.addClass "fullsize-preview"
17
+ type = "hidden"
18
18
 
19
- @$input =$ "<input type='string' name='#{ @name }' value='#{ @_safe_value() }' id='#{ @name }' />"
19
+ @$input =$ """<input type='#{type}'
20
+ name='#{ @name }'
21
+ value='#{ @_safe_value() }'
22
+ id='#{ @name }' />"""
20
23
  @$el.append @$input
21
24
  @$input.on 'change', (e) =>
22
25
  @updateValue($(e.target).val())
23
26
 
24
- @_add_image()
27
+ if @config.fullsizePreview
28
+ @_update_preview_background()
29
+ else
30
+ @_add_image()
31
+ @_update_image()
32
+
25
33
  @_add_actions()
26
34
  @_update_input_class()
27
35
 
28
-
29
36
  _add_image: ->
30
37
  @$image =$ "<a href='' target='_blank' class='image'><img src='' /></a>"
31
38
  @$el.append @$image
32
- @_update_image()
33
-
34
39
 
35
40
  _add_actions: ->
36
41
  @$actions =$ "<span class='input-actions'></span>"
@@ -39,57 +44,51 @@ class @InputLoftImage extends InputString
39
44
  @_add_choose_button()
40
45
  @_add_remove_button()
41
46
 
42
-
43
47
  _add_choose_button: ->
44
- @$chooseBtn =$ "<a href='#' class='choose'></a>"
48
+ @$chooseBtn =$ "<button class='choose'>#{Icons.upload}</button>"
45
49
  @$actions.append @$chooseBtn
46
50
 
47
- @_update_choose_button_title()
48
-
49
51
  @$chooseBtn.on 'click', (e) =>
50
- e.preventDefault()
51
52
  chr.modules.loft.showModal 'images', false, (objects) =>
52
53
  asset = objects[0]
53
54
  @updateValue(asset.file.url)
54
55
 
55
-
56
56
  _add_remove_button: ->
57
- @$removeBtn =$ "<a href='#' class='remove'>Remove</a>"
57
+ @$removeBtn =$ "<button class='remove'>#{Icons.remove}</button>"
58
58
  @$actions.append @$removeBtn
59
59
 
60
60
  @$removeBtn.on 'click', (e) =>
61
- e.preventDefault()
62
61
  if confirm('Are you sure?')
63
62
  @updateValue('')
64
63
 
64
+ _update_preview_background: ->
65
+ url = @value
66
+ @$el.css { "background-image": "url(#{url})" }
65
67
 
66
68
  _update_image: ->
67
69
  url = @value
68
- @$image.attr('href', @value).children().attr('src', @value)
69
- if @value == '' then @$image.hide() else @$image.show()
70
-
71
-
72
- _update_choose_button_title: ->
73
- title = if @value == '' then 'Choose or upload an image' else 'Choose other or upload'
74
- @$chooseBtn.html(title)
75
-
70
+ @$image.attr('href', url).children().attr('src', url)
71
+ if url == ''
72
+ @$image.hide()
73
+ else
74
+ @$image.show()
76
75
 
77
76
  _update_input_class: ->
78
- if @value == '' then @$el.removeClass('has-value') else @$el.addClass('has-value')
77
+ if @value == ''
78
+ @$el.removeClass('has-value')
79
+ else
80
+ @$el.addClass('has-value')
79
81
 
80
-
81
- # PUBLIC ================================================
82
+ # PUBLIC ====================================================================
82
83
 
83
84
  updateValue: (@value) ->
84
85
  @$input.val(@value)
85
86
 
86
- @_update_image()
87
- @_update_choose_button_title()
88
- @_update_input_class()
87
+ if @config.fullsizePreview
88
+ @_update_preview_background()
89
+ else
90
+ @_update_image()
89
91
 
92
+ @_update_input_class()
90
93
 
91
94
  chr.formInputs['loft-image'] = InputLoftImage
92
-
93
-
94
-
95
-
@@ -1,135 +1,84 @@
1
1
  # -----------------------------------------------------------------------------
2
2
  # Author: Alexander Kravets <alex@slatestudio.com>,
3
3
  # Slate Studio (http://www.slatestudio.com)
4
- #
5
- # Coding Guide:
6
- # https://github.com/thoughtbot/guides/tree/master/style/coffeescript
7
- # -----------------------------------------------------------------------------
8
-
9
4
  # -----------------------------------------------------------------------------
10
5
  # Loft
11
6
  # -----------------------------------------------------------------------------
12
- #
13
7
  # Public methods:
14
8
  # new Loft(title, resource, resourcePath)
15
9
  # showModal(assetType, @selectMultipleAssets, @onAcceptCallback, @closeOnAccept)
16
10
  # closeModal()
17
- #
18
11
  # -----------------------------------------------------------------------------
19
12
  class @Loft
20
- constructor: (title='Media', resource='asset', resourcePath='/admin/assets') ->
13
+ constructor: (title="Media", resource="asset", resourcePath="/admin/assets") ->
21
14
  @module = {}
22
15
  @store = {}
16
+ @_uploadsCounter = 0
17
+
18
+ @title = title
19
+ @menuIcon = "cloud-upload"
23
20
 
24
- @arrayStoreClass = RailsArrayStore
25
- @arrayStoreConfig =
26
- resource: resource
27
- path: resourcePath
28
- sortBy: 'created_at'
21
+ @itemClass = LoftAssetItem
22
+ @arrayStore = new RailsArrayStore
23
+ resource: resource
24
+ path: resourcePath
25
+ sortBy: "created_at"
29
26
  sortReverse: true
30
27
  searchable: true
31
28
 
32
- @_uploadsCounter = 0
33
-
34
- moduleConfig =
35
- title: title
36
- menuIcon: 'cloud-upload'
37
- showNestedListsAside: true
38
- items:
39
- loft_all: @_nested_list_config 'All'
40
- loft_images: @_nested_list_config 'Images', 'image'
41
- loft_text: @_nested_list_config 'Text', 'text'
42
- loft_archives: @_nested_list_config 'Archives', 'archive'
43
- loft_audio: @_nested_list_config 'Audio', 'audio'
44
- loft_video: @_nested_list_config 'Video', 'video'
45
- loft_other: @_nested_list_config 'Other', 'other'
29
+ @listTabs =
30
+ "All": {}
31
+ "Images": { images: true }
32
+ "Documents": { not_images: true }
46
33
 
47
- onModuleInit: (module) =>
48
- @_initialize_module(module)
34
+ @onListInit = (list) =>
35
+ @_add_upload_button(list)
36
+ @_add_group_actions(list)
37
+ @_add_mode_switch(list)
49
38
 
50
- return moduleConfig
39
+ @onListShow = (list) =>
40
+ @_clear_assets_selection(list)
51
41
 
42
+ @onModuleInit = (module) =>
43
+ @_initialize_module(module)
52
44
 
53
- # PRIVATE ===============================================
45
+ # PRIVATE ===================================================================
54
46
 
55
- _initialize_module: (module) ->
56
- @module = module
57
- @store = @module.nestedLists.loft_all.config.arrayStore
58
- @nestedLists = @module.nestedLists
59
- moduleName = @module.name
60
- firstNestedListPath = _firstNonEmptyValue(@nestedLists).path
47
+ _initialize_module: (@module) ->
48
+ @selectMultipleAssets = true
49
+ @store = @module.rootList.config.arrayStore
61
50
 
62
- # API method
63
51
  @module.showModal = (assetType, selectMultipleAssets, callback, closeOnAccept) =>
64
52
  @showModal(assetType, selectMultipleAssets, callback, closeOnAccept)
65
- @selectMultipleAssets = true
66
53
 
67
- # modal close button
54
+ @_add_close_button()
55
+ @_enable_grid_mode()
56
+
57
+ _add_close_button: ->
68
58
  @module.rootList.$modalCloseBtn =$ """<a href='#' class='modal-close'>
69
59
  <i class='fa fa-times'></i>
70
60
  </a>"""
71
61
  @module.rootList.$header.prepend @module.rootList.$modalCloseBtn
72
- @module.rootList.$modalCloseBtn.on 'click', (e) => e.preventDefault() ; @closeModal()
73
-
74
- # modal types navigation
75
- @module.rootList.$items.on 'click', 'a', (e) =>
76
- if @module.$el.hasClass 'module-modal'
77
- e.preventDefault()
78
-
79
- $item = $(e.currentTarget)
80
- listName = $item.attr('href').split('/')[2]
62
+ @module.rootList.$modalCloseBtn.on "click", (e) =>
63
+ e.preventDefault()
64
+ @closeModal()
81
65
 
82
- @module.activeList.hide()
83
- @module.showList(listName)
84
- @module.activeList.updateItems()
85
-
86
- $item.parent().children('.active').removeClass('active')
87
- $item.addClass('active')
88
-
89
- # enable grid mode as default on desktop/tablet
66
+ _enable_grid_mode: ->
90
67
  if ! chr.isMobile()
91
- @module.$el.addClass('grid-mode')
92
-
93
- @module.$el.addClass("module-categories")
94
- if chr.isDesktop()
95
- chr.$mainMenu
96
- .find(".menu-#{moduleName}")
97
- .attr("href", firstNestedListPath)
68
+ @module.$el.addClass "grid-mode"
98
69
 
99
-
100
- _nested_list_config: (moduleName, assetType) ->
101
- storeConfig = {}
102
- $.extend(storeConfig, @arrayStoreConfig)
103
-
104
- if assetType
105
- $.extend(storeConfig, { urlParams: { by_type: assetType } })
106
-
107
- config =
108
- title: moduleName
109
- showWithParent: true
110
- itemClass: LoftAssetItem
111
- arrayStore: new @arrayStoreClass(storeConfig)
112
- onListInit: (list) => @_inititialize_list(list)
113
- onListShow: (list) => @_clear_assets_selection()
114
-
115
- return config
116
-
117
-
118
- _inititialize_list: (list) ->
119
- # file input button for uploading new files
70
+ _add_upload_button: (list) ->
120
71
  list.$uploadInput =$ "<input class='asset-upload' type='file' multiple='multiple' />"
121
72
  list.$search.before list.$uploadInput
122
-
123
- # file upload handler
124
- list.$uploadInput.on 'change', (e) =>
73
+ list.$uploadInput.on "change", (e) =>
125
74
  files = e.target.files
126
75
  if files.length > 0
127
76
  @_upload(file, list) for file in files
128
77
 
129
- # group actions toolbar
78
+ _add_group_actions: (list) ->
130
79
  list.groupActions = new LoftGroupActions(list, this)
131
80
 
132
- # grid/list checkbox
81
+ _add_mode_switch: (list) ->
133
82
  list.$switchMode =$ """<a class='assets-switch-mode' href='#'>
134
83
  <i class='fa fa-fw fa-th-large'></i>
135
84
  <i class='fa fa-fw fa-th-list'></i>
@@ -137,12 +86,11 @@ class @Loft
137
86
  list.$backBtn.after list.$switchMode
138
87
  list.$switchMode.on 'click', (e) => e.preventDefault() ; @module.$el.toggleClass('grid-mode')
139
88
 
140
- # modal back for mobiles
141
- list.$header.on 'click', '.back', (e) =>
142
- if @module.$el.hasClass 'module-modal'
143
- e.preventDefault()
144
- @module.showList()
145
-
89
+ # # modal back for mobiles
90
+ # list.$header.on 'click', '.back', (e) =>
91
+ # if @module.$el.hasClass 'module-modal'
92
+ # e.preventDefault()
93
+ # @module.showList()
146
94
 
147
95
  _upload: (file, list) ->
148
96
  obj = {}
@@ -153,49 +101,35 @@ class @Loft
153
101
  onSuccess: (object) => @_finish_file_upload(list)
154
102
  onError: (errors) =>
155
103
  @_finish_file_upload(list)
156
- chr.showError('Can\'t upload file.')
157
-
104
+ chr.showError("Can't upload file.")
158
105
 
159
106
  _start_file_upload: ->
160
107
  @_uploadsCounter += 1
161
- @module.$el.addClass('assets-uploading')
162
-
108
+ @module.$el.addClass("assets-uploading")
163
109
 
164
110
  _finish_file_upload: (list) ->
165
111
  @_uploadsCounter -= 1
166
112
  if @_uploadsCounter == 0
167
- @module.$el.removeClass('assets-uploading')
113
+ @module.$el.removeClass("assets-uploading")
168
114
 
169
115
  # update data in list if it's not loft_all,
170
116
  # in loft_all new objects are added automatically
171
- if @module.activeList.name != 'loft_all'
172
- @module.activeList.updateItems()
117
+ # if @module.activeList.name != 'loft_all'
118
+ # @module.activeList.updateItems()
173
119
 
120
+ _clear_assets_selection: (list) ->
121
+ list.groupActions.hide()
122
+ list.$items.find(".asset-checkbox").prop("checked", false)
174
123
 
175
- _clear_assets_selection: ->
176
- for name, list of @module.nestedLists
177
- list.groupActions.hide()
178
- list.$items.find('.asset-checkbox').prop('checked', false)
179
-
180
-
181
- # PUBLIC ================================================
124
+ # PUBLIC ====================================================================
182
125
 
183
126
  closeModal: ->
184
127
  @selectMultipleAssets = true
185
- @_clear_assets_selection()
186
- @module.$el.removeClass('module-modal')
128
+ @_clear_assets_selection(@module.activeList)
129
+ @module.$el.removeClass("module-modal")
187
130
  @module.hide()
188
131
 
189
-
190
- # chr.modules.assets.showModal()
191
- showModal: (assetType='all', @selectMultipleAssets=false, @onAcceptCallback=$.noop, @closeOnAccept=true) ->
192
- # modal mode
193
- @module.$el.addClass('module-modal')
194
- # show module
132
+ showModal: (assetType="all", @selectMultipleAssets=false, @onAcceptCallback=$.noop, @closeOnAccept=true) ->
133
+ @module.$el.addClass("module-modal")
195
134
  @module.show()
196
- # show nested list
197
- @module.showList("loft_#{ assetType }")
198
135
  @module.activeList.updateItems()
199
- # select active item
200
- @module.rootList.$items.children().removeClass('active')
201
- @module.rootList.$items.children("[href='#/loft/loft_#{ assetType }']").addClass('active')
@@ -1,8 +1,49 @@
1
1
  .input-loft-image {
2
- input { margin-bottom: .25em; }
3
- .image img { max-height: 6em; margin: .25em .75em .25em 0; float: left; }
4
- .remove { display: none; }
5
2
 
6
- &.has-value { min-height: 11em; }
3
+ input { margin-bottom: .25em; }
4
+ .image img { max-height: 6em; margin: .25em .75em .25em 0; float: left; }
5
+ .remove { display: none; }
6
+
7
+ &.has-value { min-height: 11em; }
7
8
  &.has-value .remove { display: inline; }
8
- }
9
+ }
10
+
11
+ .input-loft-image.fullsize-preview {
12
+ @include no-bottom-border;
13
+ @include position(absolute, 3.3em null null 0.5em);
14
+ z-index: 1;
15
+ width: 5em;
16
+ height: 5em;
17
+ min-height: 5em;
18
+ background-color: $border-color;
19
+ background-size: cover;
20
+ padding: 0.15em;
21
+
22
+ input,
23
+ .label-title,
24
+ .error-message { display: none; }
25
+
26
+ button {
27
+ width: 2em;
28
+ line-height: 2;
29
+ text-align: center;
30
+ border: 0;
31
+ padding: 0;
32
+ border-radius: 1.75em;
33
+ margin: 0.15em;
34
+ }
35
+ }
36
+
37
+ /* Tablet ------------------------------------------------------------------ */
38
+ @media #{$tablet} {
39
+ .input-loft-image.fullsize-preview {
40
+ padding: 0.25em;
41
+ width: 14em;
42
+ height: 14em;
43
+
44
+ button {
45
+ width: 2.5em;
46
+ line-height: 2.5;
47
+ }
48
+ }
49
+ }
@@ -1,10 +1,11 @@
1
- // -----------------------------------------------------------------------
2
- // Basic styles for Loft Character CMS plugin, this should be included in
3
- // admin.scss (default)
4
- // -----------------------------------------------------------------------
5
1
  @import "inputs/loft-image";
6
2
 
7
3
  // MIXINS
4
+ @mixin loft-icon-base($bgSize, $width, $height) {
5
+ display: block; background-size: $bgSize; width: $width; height: $height;
6
+ background-image: image-url("loft/library@3x.png");
7
+ }
8
+
8
9
  @mixin loft-icon-label($title) {
9
10
  &:before {
10
11
  display: block; margin-top: 2.6em;
@@ -14,51 +15,9 @@
14
15
  }
15
16
  }
16
17
 
17
- @mixin loft-icon-base($bgSize, $width, $height) {
18
- display: block; background-size: $bgSize; width: $width; height: $height;
19
- background-image: image-url("loft/library@3x.png");
20
- }
21
-
22
- // ASSET TYPE ICONS
23
- .loft .list:first-child .items {
24
- .item {
25
- .item-title { margin-left: 2.05em; }
26
- &:before { @include position(absolute, null null null 1em); content: ''; display: block; }
27
- }
28
-
29
- .item {
30
- &:before { @include loft-icon-base(32px 112px, 16px, 16px); }
31
- &.active:before { background-position: 16px 0px; }
32
- }
33
- .item:nth-child(2) {
34
- &:before { background-position: 0px -16px; }
35
- &.active { &:before { background-position: 16px -16px; } }
36
- }
37
- .item:nth-child(3) {
38
- &:before { background-position: 0px -32px; }
39
- &.active { &:before { background-position: 16px -32px; } }
40
- }
41
- .item:nth-child(4) {
42
- &:before { background-position: 0px -48px; }
43
- &.active { &:before { background-position: 16px -48px; } }
44
- }
45
- .item:nth-child(5) {
46
- &:before { background-position: 0px -64px; }
47
- &.active { &:before { background-position: 16px -64px; } }
48
- }
49
- .item:nth-child(6) {
50
- &:before { background-position: 0px -80px; }
51
- &.active { &:before { background-position: 16px -80px; } }
52
- }
53
- .item:nth-child(7) {
54
- &:before { background-position: 0px -96px; }
55
- &.active { &:before { background-position: 16px -96px; } }
56
- }
57
- }
58
-
59
18
  // LIST MODE
60
- .loft .list:not(:first-child) .items .item.asset {
61
- padding-left: 6.25em; // 100px;
19
+ .list.loft .items .item.asset {
20
+ padding-left: 6.25em;
62
21
 
63
22
  // checkbox
64
23
  .asset-checkbox {
@@ -116,7 +75,7 @@
116
75
  .module-modal .assets-group-actions .delete { display: none; }
117
76
 
118
77
  // UPLOAD BUTTON
119
- .loft .list-aside .header:before {
78
+ .list.loft .header:before {
120
79
  @include position(absolute, 0px 0px null null);
121
80
  @include header-icon-base;
122
81
  display: block;
@@ -136,38 +95,80 @@
136
95
 
137
96
  .list header .asset-upload + .search { @include position(absolute, 0 40px null null); }
138
97
  .list.list-search header .asset-upload + .search { @include position(absolute, 0 0 null 0); }
139
- .loft.assets-uploading .list:not(:first-child) header .spinner { display: inline-block; }
98
+ .loft.assets-uploading .list header .spinner { visibility: visible; }
140
99
 
141
100
  // MODAL MODE
142
101
  .loft {
143
102
  .modal-close { display: none; }
144
103
  &.module-modal {
145
- @include position(absolute, 0 .5em 0 .5em); z-index: 1100;
104
+ @include position(absolute, 0 .5em 0 .5em);
105
+ z-index: 1100;
146
106
 
147
107
  &:after { display: none; }
148
108
 
149
- // dark background
150
109
  &:before {
151
- @include position(fixed, 0px 0px 0px 0px); z-index: 0;
152
- content: ''; display: block; background: rgba(0,0,0,.25);
110
+ @include position(fixed, 0px 0px 0px 0px);
111
+ z-index: 0;
112
+ content: '';
113
+ display: block;
114
+ background: rgba(0, 0, 0, 0.25);
153
115
  }
154
116
 
155
117
  .modal-close {
156
118
  @include header-icon-base;
157
- @include position(absolute, null 0 null null);
119
+ @include position(absolute, null null null 0);
158
120
  display: block;
121
+ color: $secondary-font-color;
122
+
123
+ &:hover {
124
+ color: $base-font-color;
125
+ }
159
126
  }
160
- .header { top: 0; left: .5em; right: .5em; width: auto; }
161
127
 
162
- .list:first-child .back { display: none; }
128
+ .header {
129
+ top: 0;
130
+ left: 0.5em;
131
+ right: 0.5em;
132
+ width: auto;
133
+ }
134
+
135
+ .back {
136
+ display: none;
137
+ }
163
138
  }
164
139
  }
165
140
 
166
- /* Tablet ------------------------------------------------------------------ */
141
+ /* Tablet ----------------------------------------------------------------- */
167
142
  @media #{$tablet} {
143
+ // LAYOUT
144
+ .list.loft {
145
+ width: initial;
146
+ background-color: $bg-color;
147
+
148
+ .header {
149
+ background-color: $bg-color;
150
+ }
151
+
152
+ .item {
153
+ background-color: $white-color;
154
+ }
155
+ }
156
+
168
157
  // ITEMS
169
- .loft .list:not(:first-child) .items { font-size: 1em; }
170
- .loft .list:not(:first-child) .items .item.asset {
158
+ .list.loft .items {
159
+ font-size: 1em;
160
+ padding-top: 1.5em;
161
+ }
162
+
163
+ .list.loft .item {
164
+ @include no-bottom-border;
165
+ background-color: $white-color;
166
+ box-shadow: 0 0 1px rgba(0,0,0,0.15);
167
+ margin: 0 auto;
168
+ max-width: 44em;
169
+ }
170
+
171
+ .list.loft .items .item.asset {
171
172
  padding-top: 19px; padding-bottom: 19px;
172
173
  .item-title {
173
174
  display: inline; cursor: pointer;
@@ -183,62 +184,66 @@
183
184
 
184
185
  // GRID MODE
185
186
  .assets-switch-mode {
186
- @include position(absolute, null null null 1em);
187
- display: inline; line-height: 2.5; left: 3em;
187
+ @include position(absolute, null 5.5em null null);
188
+ display: inline-block;
189
+ line-height: 2.5;
188
190
  i:first-child { color: $border-color; }
189
- i:last-child { color: rgba($base-font-color, .4); }
191
+ i:last-child { color: rgba($base-font-color, 0.4); }
190
192
  }
193
+
191
194
  .loft.grid-mode .assets-switch-mode {
192
- i:first-child { color: rgba($base-font-color, .4); }
195
+ i:first-child { color: rgba($base-font-color, 0.4); }
193
196
  i:last-child { color: $border-color; }
194
197
  }
195
198
 
196
- .loft.grid-mode {
197
- .list:not(:first-child) .items {
198
- padding: 1em .25em 5em .75em;
199
- .item.asset { margin: 0 .75em 1.5em; float: left; display: inline-block; }
200
-
201
- .item.asset {
202
- padding-left: 1em; width: 222px; height: 222px;
203
- @include no-bottom-border; border: 1px solid rgba($base-font-color, .2); border-radius: 4px;
199
+ .loft.grid-mode .list .items {
200
+ padding: 1em .25em 5em .75em;
204
201
 
205
- // checkbox: position + decoration
206
- .asset-checkbox {
207
- top: 10px; left: 10px; width: 24px; height: 24px; background: white;
208
- box-shadow: 0 1px 0 rgba(0,0,0,0.05),1px 0 0 rgba(0,0,0,0.05); border-bottom-right-radius: 4px;
209
- }
202
+ .item.asset { margin: 0 .75em 1.5em; float: left; display: inline-block; }
210
203
 
211
- // thumbnail
212
- .asset-icon {
213
- @include position(absolute, 10px null null 10px);
214
- width: 200px; height: 150px; background: white; border-radius: 0;
215
- &:after { @include position(absolute, 0px 0px 0px 0px); box-shadow: 0 0 1px rgba(0,0,0,0.2) inset; content: ''; display: block; }
216
- }
204
+ .item.asset {
205
+ padding-left: 1em; width: 222px; height: 222px;
206
+ @include no-bottom-border;
207
+ box-shadow: 0 0 1px rgba(0,0,0,0.2);
208
+ border-radius: 4px;
217
209
 
218
- .asset-thumbnail-small { display: none; }
219
- .asset-thumbnail-medium { display: block; }
210
+ // checkbox: position + decoration
211
+ .asset-checkbox {
212
+ top: 10px;
213
+ left: 10px;
214
+ width: 24px;
215
+ height: 24px;
216
+ background: $white-color;
217
+ box-shadow: 0 1px 0 rgba(0,0,0,0.05),1px 0 0 rgba(0,0,0,0.05);
218
+ border-bottom-right-radius: 4px;
219
+ }
220
220
 
221
- // name & subtitle
222
- .item-title { display: block; margin-top: 9.45em; }
223
- .item-subtitle { display: block; position: initial; margin-top: .3em; }
224
- &.edit-name .asset-name { top: inherit; bottom: 27px; left: 10px; right: 10px; }
221
+ // thumbnail
222
+ .asset-icon {
223
+ @include position(absolute, 10px null null 10px);
224
+ width: 200px; height: 150px; background: white; border-radius: 0;
225
+ &:after {
226
+ @include position(absolute, 0 0 0 0);
227
+ box-shadow: 0 0 1px rgba(0,0,0,0.2) inset;
228
+ content: '';
229
+ display: block;
230
+ }
225
231
  }
226
232
 
227
- // asset type labels
228
- .asset-text .asset-icon { @include loft-icon-label('Text'); }
229
- .asset-archive .asset-icon { @include loft-icon-label('Archive'); }
230
- .asset-audio .asset-icon { @include loft-icon-label('Audio'); }
231
- .asset-video .asset-icon { @include loft-icon-label('Video'); }
232
- .asset-other .asset-icon { @include loft-icon-label('File'); }
233
- }
234
- }
235
- }
233
+ .asset-thumbnail-small { display: none; }
234
+ .asset-thumbnail-medium { display: block; }
236
235
 
237
- /* Desktop ----------------------------------------------------------------- */
238
- @media #{$desktop} {
239
- // BACK
240
- .loft .list:not(:first-child) .back { display: none; }
236
+ // name & subtitle
237
+ .item-title { display: block; margin-top: 9.45em; }
238
+ .item-subtitle { display: block; position: initial; margin-top: .3em; }
239
+ &.edit-name .asset-name { top: inherit; bottom: 27px; left: 10px; right: 10px; }
240
+ }
241
241
 
242
- // GRID MODE
243
- .assets-switch-mode { left: 1em; }
242
+ // asset type labels
243
+ .asset-text .asset-icon { @include loft-icon-label('Text'); }
244
+ .asset-archive .asset-icon { @include loft-icon-label('Archive'); }
245
+ .asset-audio .asset-icon { @include loft-icon-label('Audio'); }
246
+ .asset-video .asset-icon { @include loft-icon-label('Video'); }
247
+ .asset-other .asset-icon { @include loft-icon-label('File'); }
248
+ }
244
249
  }
@@ -1,5 +1,9 @@
1
- class Admin::AssetsController < Admin::BaseController
2
- mongosteen
1
+ module Admin
2
+ class AssetsController < Admin::BaseController
3
+ mongosteen
3
4
 
4
- has_scope :by_type
5
+ has_scope :by_type
6
+ has_scope :images, type: :boolean
7
+ has_scope :not_images, type: :boolean
8
+ end
5
9
  end
@@ -1,20 +1,13 @@
1
- require 'autoinc'
2
-
3
1
  module LoftAsset
4
2
  extend ActiveSupport::Concern
5
-
6
3
  included do
7
-
8
4
  include Mongoid::Timestamps
9
5
  include Mongoid::Autoinc
10
6
  include Mongoid::Search
11
-
12
7
  include Ants::Id
13
-
14
8
  include ActionView::Helpers::DateHelper
15
9
  include ActionView::Helpers::NumberHelper
16
10
 
17
-
18
11
  ## Attributes
19
12
  field :name, default: ''
20
13
  field :filename, default: ''
@@ -31,43 +24,36 @@ module LoftAsset
31
24
  field :_number, type: Integer
32
25
  increments :_number
33
26
 
34
-
35
27
  ## Uploaders
36
28
  mount_uploader :file, AssetFileUploader
37
29
 
38
-
39
30
  ## Validations
40
31
  validates :file, presence: true
41
32
 
42
-
43
33
  ## Search
44
34
  search_in :name, :filename
45
35
 
46
-
47
36
  ## Scopes
48
- default_scope -> { desc(:created_at) }
37
+ default_scope -> { desc(:created_at) }
49
38
  scope :by_type, -> asset_type { where(type: asset_type) }
50
-
39
+ scope :images, -> { where(type: "image") }
40
+ scope :not_images, -> { where(:type.ne => "image" ) }
51
41
 
52
42
  ## Indexes
53
43
  index({ created_at: -1 })
54
44
 
55
-
56
45
  ## Callbacks
57
46
  before_save :update_asset_attributes
58
47
 
59
-
60
48
  ## Helpers
61
49
  def _list_item_title
62
50
  name
63
51
  end
64
52
 
65
-
66
53
  def _list_item_subtitle
67
54
  time_ago_in_words(self.created_at) + " ago"
68
55
  end
69
56
 
70
-
71
57
  def _list_item_thumbnail
72
58
  if is_image?
73
59
  { medium: file._200x150_2x.url, small: file._40x40_2x.url }
@@ -76,49 +62,41 @@ module LoftAsset
76
62
  end
77
63
  end
78
64
 
79
-
80
65
  def content_type
81
66
  @content_type ||= file.content_type
82
67
  end
83
68
 
84
-
85
69
  def is_image?
86
70
  return false unless file?
87
71
  content_type.match(/image\//) ? true : false
88
72
  end
89
73
 
90
-
91
74
  def is_text?
92
75
  return false unless file?
93
76
  content_type.match(/text\//) ? true : false
94
77
  end
95
78
 
96
-
97
79
  def is_pdf?
98
80
  return false unless file?
99
81
  content_type.match(/pdf/) ? true : false
100
82
  end
101
83
 
102
-
103
84
  def is_archive?
104
85
  return false unless file?
105
86
  # need to add more archive types: rar, gz, bz2, gzip
106
87
  content_type.match(/zip/) ? true : false
107
88
  end
108
89
 
109
-
110
90
  def is_audio?
111
91
  return false unless file?
112
92
  content_type.match(/audio\//) ? true : false
113
93
  end
114
94
 
115
-
116
95
  def is_video?
117
96
  return false unless file?
118
97
  content_type.match(/video\//) ? true : false
119
98
  end
120
99
 
121
-
122
100
  def update_asset_attributes
123
101
  if file.present? && file_changed?
124
102
 
@@ -144,6 +122,5 @@ module LoftAsset
144
122
  self.name = self.name.empty? ? self.filename : self.name
145
123
  end
146
124
  private :update_asset_attributes
147
-
148
125
  end
149
126
  end
@@ -1,13 +1,15 @@
1
- require 'chr'
2
- require 'ants'
3
- require 'mongosteen'
4
- require 'mini_magick'
5
- require 'mongoid_search'
6
- require 'mongoid-grid_fs'
7
- require 'carrierwave/mongoid'
1
+ require "chr"
2
+ require "ants"
3
+ require "mongosteen"
4
+ require "mini_magick"
5
+ require "mongoid_search"
6
+ require "mongoid-grid_fs"
7
+ require "carrierwave/mongoid"
8
+ require "autoinc"
8
9
 
9
10
  module Loft
10
11
  class Engine < ::Rails::Engine
11
- require 'loft/engine'
12
+ require "loft/engine"
13
+ require "loft/routing"
12
14
  end
13
15
  end
@@ -0,0 +1,7 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ def mount_loft_assets_crud
4
+ resources :assets, controller: 'assets'
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module Loft
2
- VERSION = "0.2.9"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Kravets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-27 00:00:00.000000000 Z
11
+ date: 2015-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chr
@@ -181,6 +181,7 @@ files:
181
181
  - app/uploaders/asset_file_uploader.rb
182
182
  - lib/loft.rb
183
183
  - lib/loft/engine.rb
184
+ - lib/loft/routing.rb
184
185
  - lib/loft/version.rb
185
186
  - loft.gemspec
186
187
  homepage: http://slatestudio.com