loft 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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