ecrire 0.22.1 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +5 -0
  4. data/Gemfile +19 -0
  5. data/README.md +2 -0
  6. data/Rakefile +1 -1
  7. data/lib/ecrire/app/assets/javascripts/admin/editor/content.coffee +46 -76
  8. data/lib/ecrire/app/assets/javascripts/admin/editor/ext.coffee +3 -0
  9. data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/clipboard.coffee +2 -1
  10. data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/code.coffee +1 -2
  11. data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/image.coffee +73 -1
  12. data/lib/ecrire/app/assets/javascripts/admin/editor/parsers/image.coffee +6 -115
  13. data/lib/ecrire/app/assets/javascripts/admin/editor.coffee +1 -0
  14. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/delete.js.coffee +1 -2
  15. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/draft.js.coffee +1 -3
  16. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/help.js.coffee +1 -1
  17. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/save.js.coffee +2 -2
  18. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/sticky.js.coffee +1 -2
  19. data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/toggle.js.coffee +1 -2
  20. data/lib/ecrire/app/assets/javascripts/admin/posts/header.coffee +96 -40
  21. data/lib/ecrire/app/assets/javascripts/admin/posts/new.js.coffee +1 -2
  22. data/lib/ecrire/app/assets/javascripts/admin/posts/tag.js.coffee +7 -0
  23. data/lib/ecrire/app/assets/javascripts/admin/posts/tags.js.coffee +15 -0
  24. data/lib/ecrire/app/assets/javascripts/admin/posts/title.coffee +38 -9
  25. data/lib/ecrire/app/assets/javascripts/admin/tags/list.js.coffee +34 -0
  26. data/lib/ecrire/app/assets/javascripts/admin.js +1 -1
  27. data/lib/ecrire/app/assets/javascripts/application.js +2 -3
  28. data/lib/ecrire/app/assets/javascripts/shared/overlay.js.coffee +1 -2
  29. data/lib/ecrire/app/assets/javascripts/shared/popup.js.coffee +1 -2
  30. data/lib/ecrire/app/assets/stylesheets/admin/base.css.scss +1 -2
  31. data/lib/ecrire/app/assets/stylesheets/admin/editor/base.css.scss +0 -7
  32. data/lib/ecrire/app/assets/stylesheets/admin/editor/content.css.scss +30 -12
  33. data/lib/ecrire/app/assets/stylesheets/admin/editor/header.css.scss +154 -32
  34. data/lib/ecrire/app/assets/stylesheets/admin/posts.css.scss +8 -1
  35. data/lib/ecrire/app/assets/stylesheets/admin/tags.css.scss +78 -0
  36. data/lib/ecrire/app/assets/stylesheets/admin/title.css.scss +51 -0
  37. data/lib/ecrire/app/assets/stylesheets/admin/variables.css.scss +3 -0
  38. data/lib/ecrire/app/assets/stylesheets/shared/popup.css.scss +2 -0
  39. data/lib/ecrire/app/controllers/admin/application_controller.rb +6 -0
  40. data/lib/ecrire/app/controllers/admin/images_controller.rb +5 -6
  41. data/lib/ecrire/app/controllers/admin/posts/tags_controller.rb +35 -0
  42. data/lib/ecrire/app/controllers/admin/posts_controller.rb +13 -12
  43. data/lib/ecrire/app/controllers/admin/tags_controller.rb +4 -0
  44. data/lib/ecrire/app/controllers/admin/titles_controller.rb +39 -0
  45. data/lib/ecrire/app/controllers/application_controller.rb +13 -3
  46. data/lib/ecrire/app/controllers/ecrire/posts_controller.rb +6 -5
  47. data/lib/ecrire/app/helpers/posts_helper.rb +0 -12
  48. data/lib/ecrire/app/models/admin/image.rb +4 -7
  49. data/lib/ecrire/app/models/admin/post.rb +2 -7
  50. data/lib/ecrire/app/models/admin/tag.rb +4 -0
  51. data/lib/ecrire/app/models/admin/title.rb +4 -0
  52. data/lib/ecrire/app/models/post.rb +30 -22
  53. data/lib/ecrire/app/models/tag.rb +5 -0
  54. data/lib/ecrire/app/models/title.rb +62 -0
  55. data/lib/ecrire/app/views/admin/images/errors.json.jbuilder +1 -0
  56. data/lib/ecrire/app/views/admin/posts/edit.html.erb +61 -21
  57. data/lib/ecrire/app/views/admin/posts/header/_dropping.html.erb +12 -0
  58. data/lib/ecrire/app/views/admin/posts/header/_error.html.erb +18 -0
  59. data/lib/ecrire/app/views/admin/posts/header/_uploading.html.erb +21 -0
  60. data/lib/ecrire/app/views/admin/posts/new.html.erb +23 -0
  61. data/lib/ecrire/app/views/admin/posts/tags/_tag.html.erb +10 -0
  62. data/lib/ecrire/app/views/admin/posts/tags/create.js.erb +1 -0
  63. data/lib/ecrire/app/views/admin/posts/tags/dialog/_tag.html.erb +3 -0
  64. data/lib/ecrire/app/views/admin/posts/tags/dialog/_tags.html.erb +12 -0
  65. data/lib/ecrire/app/views/admin/posts/tags/index.js.erb +1 -0
  66. data/lib/ecrire/app/views/admin/posts/tags/update.js.erb +2 -0
  67. data/lib/ecrire/app/views/admin/titles/_title.html.erb +11 -0
  68. data/lib/ecrire/app/views/admin/titles/_titles.html.erb +22 -0
  69. data/lib/ecrire/app/views/admin/titles/create.js.erb +1 -0
  70. data/lib/ecrire/app/views/admin/titles/edit.js.erb +1 -0
  71. data/lib/ecrire/app/views/admin/titles/errors.js.erb +5 -0
  72. data/lib/ecrire/app/views/admin/titles/index.js.erb +1 -0
  73. data/lib/ecrire/app/views/admin/titles/update.js.erb +1 -0
  74. data/lib/ecrire/app/views/layouts/admin/application.html.erb +1 -1
  75. data/lib/ecrire/app/views/sessions/_navigation.html.erb +1 -1
  76. data/lib/ecrire/application.rb +1 -1
  77. data/lib/ecrire/config/routes.rb +2 -2
  78. data/lib/ecrire/db/migrate/20150305123321_move_labels_to_titles.rb +27 -0
  79. data/lib/ecrire/db/migrate/20150318549479_create_tags.rb +13 -0
  80. data/lib/ecrire/db/schema.rb +25 -22
  81. data/lib/ecrire/onboarding/assets/javascripts/base.js +1 -1
  82. data/lib/ecrire/onboarding/assets/javascripts/databases/information.js.coffee +1 -1
  83. data/lib/ecrire/onboarding/assets/javascripts/message.js.coffee +1 -1
  84. data/lib/ecrire/template/Gemfile +4 -3
  85. data/lib/ecrire/template/assets/javascripts/base.js.coffee +1 -0
  86. data/lib/ecrire/version.rb +1 -1
  87. data/test/editor/controllers/base_controller_test.rb +1 -0
  88. data/test/editor/models/post_test.rb +26 -56
  89. data/test/editor/models/title_test.rb +31 -0
  90. data/test/editor/test_helper.rb +2 -0
  91. data/test/fixtures/posts.yml +0 -4
  92. data/test/fixtures/tags.yml +2 -0
  93. data/test/fixtures/titles.yml +11 -0
  94. data/test/initializations/railtie_test.rb +2 -2
  95. data/test/themes/template/secrets.yml +6 -0
  96. metadata +49 -24
  97. data/lib/ecrire/app/assets/stylesheets/admin/editor/image.css.scss +0 -58
  98. data/lib/ecrire/app/controllers/admin/labels_controller.rb +0 -18
  99. data/lib/ecrire/app/models/label.rb +0 -3
  100. data/lib/ecrire/app/views/admin/images/errors.js.erb +0 -1
  101. data/lib/ecrire/app/views/admin/posts/title.html.erb +0 -10
  102. data/test/editor/controllers/admin/images_controller_test.rb +0 -6
  103. data/test/editor/controllers/admin/posts_controller_test.rb +0 -90
  104. data/test/editor/controllers/images_controller_test.rb +0 -2
  105. data/test/editor/controllers/partials_controller_test.rb +0 -2
  106. data/test/editor/controllers/posts_controller_test.rb +0 -21
  107. data/test/editor/helpers/posts_helper_test.rb +0 -3
  108. data/test/editor/models/partial_test.rb +0 -4
  109. data/test/fixtures/partials.yml +0 -9
  110. /data/lib/ecrire/app/views/admin/images/{update.js.erb → create.js.erb} +0 -0
  111. /data/{lib/ecrire/template/assets/javascripts/post.js.coffee → test/themes/onboarding/.keep} +0 -0
@@ -1,69 +1,125 @@
1
- Joint.bind 'Post.Header', class
1
+ ObserveJS.bind 'Post.Header', class
2
2
  loaded: =>
3
+ @on 'click', @element().querySelector('p.browse'), @open
4
+ @on 'click', @element().querySelector('svg.clear'), @remove
5
+ @on 'change', @element().querySelector('input[type=file]'), @submit
3
6
  @on 'dragover', @over
4
7
  @on 'dragleave', @cancel
5
8
  @on 'drop', @drop
6
- @on 'click', @element().querySelector('div'), @open
7
- @on 'submit', @element().querySelector('form.clear'), @loading
8
- input = @element().querySelector('input[type=file]')
9
- @on 'change', input, @submit
10
9
 
11
- @on 'images:update', @update
12
- @on 'images:destroy', @clear
13
- @refresh()
10
+ @on 'ObserveJS:XHR:Failed', @failed
11
+
12
+ @on 'click', @retrieve('div.error.status').querySelector('button'), @clear
13
+
14
+ @on 'images:create', @refresh
15
+ @on 'images:destroy', @refresh
16
+ @on 'titles:index', @popup
17
+ @on 'titles:update', document, @updateTitle
18
+ @on 'titles:create', document, @updateTitle
19
+
20
+ popup: (e) =>
21
+ document.body.appendChild(e.HTML)
22
+
23
+ show: (el) =>
24
+ @show.container ||= @element().querySelector('div.drop')
25
+ unless el.parentElement?
26
+ @element().querySelector('div.drop').appendChild(el)
27
+
28
+ for child in @show.container.children
29
+ child.classList.add 'hidden'
30
+
31
+ el.classList.remove('hidden')
32
+
33
+ hide: (el) =>
34
+ el.classList.add('hidden')
35
+
36
+ outside: (e, rect) ->
37
+ e.x >= (rect.left + rect.width) ||
38
+ e.x <= rect.left ||
39
+ e.y >= (rect.top + rect.height) ||
40
+ e.y <= rect.top
41
+
42
+ progress: (e) =>
43
+ return unless e.lengthComputable
44
+ percentComplete = e.loaded / e.total * 100.0;
45
+ progressBar = @retrieve('div.status.uploading').querySelector('.progressbar')
46
+ progressBar.firstElementChild.style.width = "#{percentComplete}%";
47
+
48
+ failed: (e) =>
49
+ errors = JSON.parse(e.response.target.responseText)
50
+ @hide(@retrieve('div.status.uploading'))
51
+ @show(@retrieve('div.error.status'))
52
+ ul = @retrieve('div.error.status').querySelector('ul')
53
+ for error in errors
54
+ ul.insertAdjacentHTML('beforeend', "<li>#{error}</li>")
14
55
 
15
56
  open: (e) =>
16
57
  @element().querySelector('input[type=file]').click()
17
58
 
59
+ remove: (e) =>
60
+ xhr = new ObserveJS.XHR(e.currentTarget)
61
+ xhr.request.upload.onprogress = @progress
62
+ xhr.send()
63
+
18
64
  over: (e) =>
19
65
  e.preventDefault()
20
- @element().classList.add 'dropping'
66
+ if !@element().classList.contains('image')
67
+ @element().classList.add 'image'
68
+ @show(@retrieve('div.dropping.status'))
21
69
 
22
70
  cancel: (e) =>
23
71
  e.preventDefault()
24
- @element().classList.remove 'dropping'
72
+ rect = @element().getBoundingClientRect()
73
+ if @outside(e, rect)
74
+ @clear(e)
25
75
 
26
76
  drop: (e) =>
27
- @element().classList.remove 'dropping'
28
- @loading()
29
77
  e.preventDefault()
30
- form = @element().querySelector('form.update')
31
- xhr = new Joint.XHR(form)
32
- xhr.data.set 'image[file]', e.dataTransfer.files[0]
33
- xhr.send()
78
+ if e.dataTransfer.files.length > 0
79
+ @upload(e.dataTransfer.files[0])
34
80
 
35
81
  submit: (e) =>
36
- @loading()
37
- Joint.XHR.send(e.target.form)
82
+ if e.target.files.length > 0
83
+ @upload(e.target.files[0])
84
+
85
+ e.target.value = ''
86
+
87
+ upload: (file) =>
88
+ if !@element().classList.contains('image')
89
+ @element().classList.add 'image'
90
+
91
+ @show(@retrieve('div.status.uploading'))
92
+ @retrieve('div.status.uploading').querySelector('.progressbar > span').style.width = '0%';
93
+ xhr = new ObserveJS.XHR(@element())
94
+ xhr.data.set 'image[file]', file
95
+ xhr.request.upload.onprogress = @progress
96
+ xhr.send()
38
97
 
39
98
  loading: =>
40
- @element().classList.add 'loading'
99
+ @element().firstElementChild.appendChild(@retrieve('div.status.uploading'))
41
100
 
42
101
  clear: (e) =>
43
- @element().style.backgroundImage = null
44
- @element().classList.remove 'loading'
45
- @refresh()
102
+ @element().classList.remove 'image'
103
+ for li in @retrieve('div.error.status').querySelectorAll('li')
104
+ li.remove()
46
105
 
47
- update: (e) =>
48
- @element().classList.remove 'loading'
106
+ for status of @statuses
107
+ @statuses[status].classList.add 'hidden'
49
108
 
50
- if e.ErrorHTML
51
- document.body.appendChild(e.ErrorHTML)
52
- return
109
+ if @element().style.backgroundImage.length == 0
110
+ @element().querySelector('svg.clear').classList.add('hidden')
111
+ else
112
+ @element().querySelector('svg.clear').classList.remove('hidden')
53
113
 
54
- @element().style.backgroundImage = "url(#{e.headerURL})"
55
- @refresh()
56
114
 
115
+ refresh: (e) =>
116
+ if e.headerURL?
117
+ @element().style.backgroundImage = "url(#{e.headerURL})"
118
+ else
119
+ @element().style.backgroundImage = null
57
120
 
58
- refresh: =>
59
- clearForm = @element().querySelector('form.clear')
60
- p = @element().querySelector('p')
61
- @refresh = =>
62
- if @element().style.backgroundImage.length > 0
63
- p.style.visibility = 'hidden'
64
- clearForm.style.visibility = 'visible'
65
- else
66
- clearForm.style.visibility = 'hidden'
67
- p.style.visibility = 'visible'
121
+ @clear()
68
122
 
69
- @refresh()
123
+ updateTitle: (e) =>
124
+ unless e.Errors?
125
+ @element().querySelector('a.title').textContent = e.Title
@@ -1,7 +1,6 @@
1
- Joint.bind 'Posts.New', class
1
+ ObserveJS.bind 'Posts.New', class
2
2
  loaded: =>
3
3
  for el in @element().querySelectorAll('.transparent')
4
4
  el.classList.remove('transparent')
5
5
 
6
6
  @element().querySelector('input[type=text]').focus()
7
-
@@ -0,0 +1,7 @@
1
+ ObserveJS.bind 'Post.Tag', class
2
+ loaded: =>
3
+ @on 'click', @submit
4
+
5
+ submit: (e) =>
6
+ @on 'tags:update', @remove
7
+ ObserveJS.XHR.send(@element())
@@ -0,0 +1,15 @@
1
+ ObserveJS.bind 'Post.Tags', class
2
+ loaded: =>
3
+ @on 'tags:index', @show
4
+ @on 'tags:update', document, @update
5
+
6
+ show: (e) =>
7
+ document.body.appendChild(e.HTML)
8
+ e.HTML.querySelector('input').focus()
9
+
10
+ update: (e) =>
11
+ target = @element().querySelector("[oid='#{e.HTML.getAttribute('oid')}']")
12
+ if target?
13
+ target.remove()
14
+ else
15
+ @element().insertBefore(e.HTML, @element().lastElementChild)
@@ -1,15 +1,44 @@
1
- Joint.bind 'Posts.Title', class
1
+ ObserveJS.bind 'Post.Title', class
2
2
  loaded: =>
3
- @title = @element().querySelector('input.title')
4
- @on 'posts:update', @update
3
+ @on 'keydown', @enter
4
+ @observer = new MutationObserver(@modified)
5
+ @observer.settings = {
6
+ childList: true,
7
+ subtree: true,
8
+ }
9
+ @input = @element().querySelector('div.input')
10
+ @errors = @element().querySelector('ul.errors')
11
+ @observe()
12
+ @on 'titles:update', @update
13
+ @on 'titles:create', @update
14
+ @input.focus()
15
+
16
+ dismiss: =>
17
+ @element().parentElement.remove()
5
18
 
6
19
  update: (e) =>
7
- @title.value = e.HTML
8
- @title.blur()
20
+ if e.Errors
21
+ @errors.appendChild(error) for error in e.Errors
22
+ else
23
+ @dismiss()
24
+
25
+ enter: (e) =>
26
+ if e.keyCode == 13
27
+ @errors.innerHTML = ''
28
+ e.stopPropagation()
29
+ e.preventDefault()
30
+ @save()
31
+ return
9
32
 
10
- if e.MessageHTML
11
- event = new CustomEvent('Editor:message', { bubbles: true})
12
- event.MessageHTML = e.MessageHTML
13
- @element().dispatchEvent(event)
33
+ modified: (observedMutations) =>
34
+ @observer.disconnect()
35
+ @input.innerHTML = @input.textContent
36
+ @observe()
14
37
 
38
+ observe: =>
39
+ @observer.observe @input, @observer.settings
15
40
 
41
+ save: =>
42
+ xhr = new ObserveJS.XHR(@element())
43
+ xhr.data.set '[title]name', @input.textContent
44
+ xhr.send()
@@ -0,0 +1,34 @@
1
+ ObserveJS.bind 'Tags.List', class
2
+ loaded: =>
3
+ @on 'keypress', @element().querySelector('input'), @submit
4
+ @on 'click', @element().querySelector('ul'), @update
5
+ @on 'tags:update', @toggle
6
+ @on 'tags:create', @add
7
+
8
+ submit: (e) =>
9
+ if e.keyCode != 13
10
+ return
11
+
12
+ xhr = new ObserveJS.XHR(e.target)
13
+ xhr.method = 'POST'
14
+ xhr.data.set '[tag]name', e.target.value
15
+ xhr.send()
16
+
17
+ update: (e) =>
18
+ return unless e.target instanceof HTMLLIElement
19
+ xhr = new ObserveJS.XHR(e.target)
20
+ xhr.send()
21
+
22
+ toggle: (e) =>
23
+ li = @element().querySelector("[oid='#{e.ObjectID}']")
24
+ li.remove()
25
+
26
+ add: (e) =>
27
+ @element().querySelector('input').value = ''
28
+ target = @element().querySelector("[oid='#{e.HTML.getAttribute('oid')}']")
29
+ if target?
30
+ target.classList.add('highlight')
31
+ else
32
+ ul = @element().querySelector('ul')
33
+ ul.insertBefore(e.HTML, ul.firstElementChild)
34
+ e.HTML.classList.add('highlight')
@@ -1,5 +1,5 @@
1
1
  //= require turbolinks
2
- //= require joint
2
+ //= require observejs
3
3
  //= require_tree ./admin
4
4
  //= require_tree ./vendor
5
5
  //= require_tree ./shared
@@ -1,10 +1,10 @@
1
1
  //= require turbolinks
2
- //= require joint
2
+ //= require observejs
3
3
  //= require_tree ./vendor
4
4
  //= require_tree ./shared
5
5
  //
6
6
 
7
- // Not loading this with JointJS cuz the layout
7
+ // Not loading this with ObserveJS cuz the layout
8
8
  // would require to declare a class for it to load.
9
9
  var script = document.getElementsByTagName('script');
10
10
 
@@ -18,4 +18,3 @@ if (script) {
18
18
  document.addEventListener('page:load', Prism.highlightAll);
19
19
  }
20
20
  }
21
-
@@ -1,4 +1,4 @@
1
- Joint.bind 'Overlay', class
1
+ ObserveJS.bind 'Overlay', class
2
2
  loaded: =>
3
3
  @on 'click', @clicked
4
4
  @on 'keyup', document, @escaped
@@ -26,4 +26,3 @@ Joint.bind 'Overlay', class
26
26
  window.scrollTo(0, @y)
27
27
  main.style.top = null
28
28
  @scrollTop = null
29
-
@@ -1,7 +1,6 @@
1
- Joint.bind 'Posts.Popup', class
1
+ ObserveJS.bind 'Posts.Popup', class
2
2
  loaded: =>
3
3
  @on 'posts:index', @show
4
4
 
5
5
  show: (e) =>
6
6
  document.body.appendChild(e.HTML)
7
-
@@ -24,7 +24,7 @@ body {
24
24
  }
25
25
 
26
26
  a {
27
- color: rgb(114, 153, 204);
27
+ color: $link-color;
28
28
  }
29
29
 
30
30
  ol.list {
@@ -95,4 +95,3 @@ main {
95
95
  box-shadow: inset 0px 0px 3px 1px rgba(76, 120, 155, 1);
96
96
  color: #FEFEFE;
97
97
  }
98
-
@@ -7,13 +7,6 @@ body.posts > main {
7
7
  @include flex-direction(column);
8
8
  }
9
9
 
10
-
11
- body.posts > main > header {
12
- @include flex(0 auto);
13
- padding: 1em 0;
14
-
15
- }
16
-
17
10
  body.posts > main > section {
18
11
  @include flex(1);
19
12
  @include display(flex);
@@ -46,36 +46,54 @@ body.edit.posts > main > section {
46
46
  background: rgba(0,0,0, 0.1);
47
47
  }
48
48
 
49
- & > div.image {
49
+ & > figure {
50
50
  @include display(flex);
51
51
  @include flex-direction(column);
52
52
  @include transition(background-color 0.3s);
53
- height: 480px;
54
53
  background-color: #EEE;
54
+ overflow: hidden;
55
55
 
56
- &:hover {
57
- background-color: #CCC;
58
- }
59
56
 
60
- &.dropping {
61
- background-color: #CCC;
57
+ &.dropping div[contenteditable] {
58
+ background-color: rgb(122, 199, 122);
62
59
  }
63
60
 
64
- & > em {
65
- background-color: #EEE;
61
+ figcaption {
66
62
  padding: 1em;
67
63
  }
68
64
 
69
- & > div {
65
+ & > div[contenteditable] {
70
66
  @include display(flex);
71
67
  @include align-items(center);
72
- @include justify-content(center);
68
+ @include justify-content(flex-end);
69
+ @include flex-direction(column);
73
70
  @include flex(1);
74
71
  cursor: pointer;
75
72
  width: 100%;
76
- background-size: cover;
73
+ box-shadow: 0 0 3px 0 #aaa;
74
+
75
+ &:hover {
76
+ background-color: #CCC;
77
+ }
78
+
79
+ & > .progressbar {
80
+ @include flex(0 auto);
81
+ width: 100%;
82
+ & > span.progress {
83
+ @include transition(width 0.3s ease-out);
84
+ display: block;
85
+ height: 2px;
86
+ width: 0%;
87
+ background: #B9C8BA;
88
+ }
89
+ }
90
+
91
+ & > img {
92
+ max-width: 100%;
93
+ }
77
94
 
78
95
  & > p {
96
+ padding: 2em 0;
79
97
  text-align: center;
80
98
  }
81
99
 
@@ -1,45 +1,167 @@
1
1
  body.edit.posts > main > header {
2
2
  @include display(flex);
3
- @include flex-direction(column);
3
+ @include flex(0 auto);
4
4
  }
5
5
 
6
- body.edit.posts > main > header form.title {
6
+ body.edit.posts > main > header > div.title {
7
7
  @include display(flex);
8
- @include flex(0 auto);
9
- position: relative;
10
- margin: auto 0;
8
+ @include flex-direction(column);
9
+ @include transition(opacity 0.2s linear);
10
+ text-align: center;
11
+ width: 100%;
12
+ z-index: 5;
13
+ & > p.browse {
14
+ @include transition(color 0.3s);
15
+ font-size: 0.7em;
16
+ cursor: pointer;
17
+ &:hover {
18
+ color: rgb(114, 153, 204);
19
+ }
20
+ }
11
21
 
12
- &:after {
22
+ svg.clear {
23
+ @include transition(fill 0.3s);
24
+ width: 30px;
13
25
  position: absolute;
14
- width: 1em;
15
- content: '↵';
16
26
  right: 1em;
17
- top: 1.1em;
18
- color: #FAFAFA;
19
- font-size: 1.4em;
27
+ top: 1em;
28
+ fill: #D8ABAB;
29
+ cursor: pointer;
30
+ &:hover {
31
+ fill: #C23131;
32
+ }
20
33
  }
34
+ }
21
35
 
22
- input.title {
23
- width: 100%;
24
- min-height: 60px;
25
- font-size: 2em;
26
- cursor: pointer;
27
- text-decoration: underline;
28
- text-align: center;
29
- background: none;
30
- border-color: transparent;
31
- border-style: solid;
32
- border-width: 1px;
33
- resize: none;
34
- outline: none;
35
- color: inherit;
36
-
37
- &:focus {
38
- cursor: text;
39
- text-decoration: none;
40
- background: rgb(239, 239, 239);
41
- box-shadow: 0 0 2px #FFF;
36
+ [as='Post.Header'] a.title {
37
+ @include flex(0 auto);
38
+ @include transition(box-shadow 0.3s ease, background 0.3s ease, color 0.3s ease);
39
+
40
+ font-size: 2.3em;
41
+ line-height: 1.4em;
42
+ padding: 0.3em 1em;
43
+ margin: 0.5em 0 0 0;
44
+ cursor: pointer;
45
+ text-decoration: none;
46
+ color: inherit;
47
+
48
+ &:hover {
49
+ color: $link-color;
50
+ }
51
+
52
+ }
53
+
54
+ [as='Post.Header'] {
55
+ @include display(flex);
56
+ @include flex-direction(column);
57
+ @include align-items(center);
58
+ @include justify-content(flex-start);
59
+ @include transition(background-color 0.3s ease);
60
+
61
+ background-size: cover;
62
+ position: relative;
63
+ padding-bottom: 0.5em;
64
+ border-bottom: 1px solid #E8E8E8;
65
+
66
+ &.image {
67
+
68
+ & > div.drop {
69
+ background-color: rgb(122, 199, 122);
70
+ opacity: 1;
71
+ z-index: 6;
72
+ }
73
+
74
+ & > div.title {
75
+ opacity: 0;
76
+ }
77
+ }
78
+
79
+ input[type='file'] {
80
+ visibility: hidden;
81
+ }
82
+
83
+ }
84
+
85
+ [as='Post.Header'] div.drop {
86
+ @include transition(opacity 0.3s ease);
87
+ @include display(flex);
88
+ @include flex-direction(column);
89
+ @include align-items(center);
90
+ @include justify-content(center);
91
+ position: absolute;
92
+ opacity: 0;
93
+ left: 0;
94
+ right: 0;
95
+ top: 0;
96
+ bottom: 0;
97
+ font-size: 1em;
98
+ text-align: center;
99
+ margin: 0;
100
+
101
+ svg {
102
+ width: 40px;
103
+ fill: rgb(66, 152, 66);
104
+ }
105
+
106
+ p {
107
+ color: rgb(66, 152, 66);
108
+ text-shadow: 0 1px 0 rgb(143, 213, 143);
109
+ }
110
+ }
111
+
112
+ [as='Post.Header'] div.progressbar {
113
+ position: absolute;
114
+ bottom: 0;
115
+ left: 0;
116
+ right: 0;
117
+ height: 4px;
118
+
119
+ & > span.progress {
120
+ @include transition(width 0.3s ease-out);
121
+ display: block;
122
+ height: 100%;
123
+ width: 0%;
124
+ background: #5FFF6A;
125
+ }
126
+ }
127
+
128
+ [as='Post.Header'] div.drop > div.status.error {
129
+ @include flex-direction(column);
130
+ @include align-items(center);
131
+ @include justify-content(center);
132
+ width: 100%;
133
+ height: 100%;
134
+
135
+ background: $red-color;
136
+ color: $dark-red-color;
137
+
138
+ &:not(.hidden) {
139
+ @include display(flex);
140
+ }
141
+
142
+ svg {
143
+ fill: rgb(89, 18, 18);
144
+ }
145
+
146
+ ul {
147
+ color: $dark-red-color;
148
+ text-shadow: 0 1px 0 #BD4141;
149
+ font-weight: bolder;
150
+ }
151
+
152
+ button {
153
+ @include transition(box-shadow 0.2s ease);
154
+ border: 1px solid #8B0B0B;
155
+ border-radius: 2px;
156
+ box-shadow: inset 0 0px 1px 0 #D85D5D;
157
+ padding: 6px 1em;
158
+
159
+ &:hover {
160
+ box-shadow: inset 0 0px 3px 0 #D85D5D;
161
+ }
42
162
 
163
+ &:active {
164
+ box-shadow: inset 0 0px 2px 0 #813131;
43
165
  }
44
166
  }
45
167
  }
@@ -51,7 +173,7 @@ body.posts > main [as='Navigation.Toggle'] {
51
173
  height: auto;
52
174
  cursor: pointer;
53
175
  fill: rgba(212, 228, 237, 1);
54
- margin: 0 auto;
176
+ margin: 8px auto;
55
177
  &:hover {
56
178
  fill: #73CDFF;
57
179
  }
@@ -38,9 +38,16 @@ form.post.new.title {
38
38
  color: #BABABA;
39
39
  font-size: 1.4em;
40
40
  }
41
+
42
+ &.errors {
43
+ border-color: $red-color;
44
+ }
41
45
  }
42
46
 
43
- p {
47
+ p, ul {
44
48
  text-align: center;
49
+ &.errors {
50
+ color: $red-color;
51
+ }
45
52
  }
46
53
  }