fluentd-ui 0.3.8 → 0.3.9

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.

Potentially problematic release.


This version of fluentd-ui might be problematic. Click here for more details.

Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +9 -0
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +4 -1
  5. data/app/assets/javascripts/vue/fluent_log.js +4 -4
  6. data/app/assets/javascripts/vue/in_tail_format.js +43 -49
  7. data/app/assets/javascripts/{alert.js → vue/notification.js} +21 -7
  8. data/app/assets/javascripts/vue/settings.js +121 -0
  9. data/app/assets/javascripts/vue/treeview.js +3 -3
  10. data/app/assets/stylesheets/common.css.scss +7 -1
  11. data/app/controllers/api/settings_controller.rb +55 -0
  12. data/app/controllers/api_controller.rb +6 -2
  13. data/app/controllers/concerns/setting_concern.rb +2 -2
  14. data/app/controllers/fluentd/settings_controller.rb +17 -2
  15. data/app/models/fluentd/setting/config.rb +39 -0
  16. data/app/views/api/settings/_element.json.jbuilder +6 -0
  17. data/app/views/api/settings/index.json.jbuilder +3 -0
  18. data/app/views/api/settings/show.json.jbuilder +1 -0
  19. data/app/views/fluentd/settings/edit.html.haml +3 -0
  20. data/app/views/fluentd/settings/source_and_output.html.haml +19 -2
  21. data/app/views/layouts/application.html.erb +1 -30
  22. data/app/views/shared/vue/_in_tail_format.html.erb +11 -36
  23. data/app/views/shared/vue/_notification.html.erb +31 -0
  24. data/app/views/shared/vue/_setting.html.erb +23 -0
  25. data/app/views/shared/vue/_treeview.html.erb +2 -2
  26. data/bower.json +1 -1
  27. data/config/application.rb +1 -0
  28. data/config/locales/translation_en.yml +11 -7
  29. data/config/locales/translation_ja.yml +4 -0
  30. data/config/routes.rb +2 -0
  31. data/lib/fluentd-ui/version.rb +1 -1
  32. data/spec/features/fluentd/setting/source_and_output_spec.rb +157 -0
  33. data/spec/spec_helper.rb +1 -0
  34. data/spec/support/javascript_macro.rb +21 -0
  35. data/vendor/assets/javascripts/bower/vue/.bower.json +7 -7
  36. data/vendor/assets/javascripts/bower/vue/LICENSE +1 -1
  37. data/vendor/assets/javascripts/bower/vue/dist/vue.js +7822 -4768
  38. data/vendor/assets/javascripts/bower/vue/dist/vue.min.js +7 -7
  39. data/vendor/assets/javascripts/bower/vue/src/api/child.js +53 -0
  40. data/vendor/assets/javascripts/bower/vue/src/api/data.js +161 -0
  41. data/vendor/assets/javascripts/bower/vue/src/api/dom.js +211 -0
  42. data/vendor/assets/javascripts/bower/vue/src/api/events.js +176 -0
  43. data/vendor/assets/javascripts/bower/vue/src/api/global.js +146 -0
  44. data/vendor/assets/javascripts/bower/vue/src/api/lifecycle.js +144 -0
  45. data/vendor/assets/javascripts/bower/vue/src/batcher.js +52 -32
  46. data/vendor/assets/javascripts/bower/vue/src/cache.js +112 -0
  47. data/vendor/assets/javascripts/bower/vue/src/compiler/compile.js +549 -0
  48. data/vendor/assets/javascripts/bower/vue/src/compiler/transclude.js +163 -0
  49. data/vendor/assets/javascripts/bower/vue/src/config.js +74 -14
  50. data/vendor/assets/javascripts/bower/vue/src/directive.js +179 -219
  51. data/vendor/assets/javascripts/bower/vue/src/directives/attr.js +32 -0
  52. data/vendor/assets/javascripts/bower/vue/src/directives/class.js +18 -0
  53. data/vendor/assets/javascripts/bower/vue/src/directives/cloak.js +12 -0
  54. data/vendor/assets/javascripts/bower/vue/src/directives/component.js +214 -0
  55. data/vendor/assets/javascripts/bower/vue/src/directives/el.js +13 -0
  56. data/vendor/assets/javascripts/bower/vue/src/directives/html.js +30 -34
  57. data/vendor/assets/javascripts/bower/vue/src/directives/if.js +77 -46
  58. data/vendor/assets/javascripts/bower/vue/src/directives/index.js +22 -129
  59. data/vendor/assets/javascripts/bower/vue/src/directives/model/checkbox.js +25 -0
  60. data/vendor/assets/javascripts/bower/vue/src/directives/model/default.js +123 -0
  61. data/vendor/assets/javascripts/bower/vue/src/directives/model/index.js +56 -0
  62. data/vendor/assets/javascripts/bower/vue/src/directives/model/radio.js +26 -0
  63. data/vendor/assets/javascripts/bower/vue/src/directives/model/select.js +166 -0
  64. data/vendor/assets/javascripts/bower/vue/src/directives/on.js +51 -50
  65. data/vendor/assets/javascripts/bower/vue/src/directives/partial.js +36 -42
  66. data/vendor/assets/javascripts/bower/vue/src/directives/ref.js +24 -0
  67. data/vendor/assets/javascripts/bower/vue/src/directives/repeat.js +477 -226
  68. data/vendor/assets/javascripts/bower/vue/src/directives/show.js +8 -0
  69. data/vendor/assets/javascripts/bower/vue/src/directives/style.js +49 -37
  70. data/vendor/assets/javascripts/bower/vue/src/directives/text.js +15 -0
  71. data/vendor/assets/javascripts/bower/vue/src/directives/transition.js +12 -0
  72. data/vendor/assets/javascripts/bower/vue/src/directives/with.js +38 -41
  73. data/vendor/assets/javascripts/bower/vue/src/filters/array-filters.js +87 -0
  74. data/vendor/assets/javascripts/bower/vue/src/filters/index.js +135 -0
  75. data/vendor/assets/javascripts/bower/vue/src/instance/compile.js +71 -0
  76. data/vendor/assets/javascripts/bower/vue/src/instance/events.js +122 -0
  77. data/vendor/assets/javascripts/bower/vue/src/instance/init.js +76 -0
  78. data/vendor/assets/javascripts/bower/vue/src/instance/scope.js +217 -0
  79. data/vendor/assets/javascripts/bower/vue/src/observer/array.js +90 -0
  80. data/vendor/assets/javascripts/bower/vue/src/observer/dep.js +50 -0
  81. data/vendor/assets/javascripts/bower/vue/src/observer/index.js +235 -0
  82. data/vendor/assets/javascripts/bower/vue/src/observer/object.js +75 -0
  83. data/vendor/assets/javascripts/bower/vue/src/parsers/directive.js +159 -0
  84. data/vendor/assets/javascripts/bower/vue/src/parsers/expression.js +226 -0
  85. data/vendor/assets/javascripts/bower/vue/src/parsers/path.js +300 -0
  86. data/vendor/assets/javascripts/bower/vue/src/parsers/template.js +246 -0
  87. data/vendor/assets/javascripts/bower/vue/src/parsers/text.js +178 -0
  88. data/vendor/assets/javascripts/bower/vue/src/transition/css.js +189 -0
  89. data/vendor/assets/javascripts/bower/vue/src/transition/index.js +151 -0
  90. data/vendor/assets/javascripts/bower/vue/src/transition/js.js +43 -0
  91. data/vendor/assets/javascripts/bower/vue/src/util/debug.js +50 -0
  92. data/vendor/assets/javascripts/bower/vue/src/util/dom.js +176 -0
  93. data/vendor/assets/javascripts/bower/vue/src/util/env.js +74 -0
  94. data/vendor/assets/javascripts/bower/vue/src/util/filter.js +72 -0
  95. data/vendor/assets/javascripts/bower/vue/src/util/index.js +8 -0
  96. data/vendor/assets/javascripts/bower/vue/src/util/lang.js +175 -0
  97. data/vendor/assets/javascripts/bower/vue/src/util/merge-option.js +258 -0
  98. data/vendor/assets/javascripts/bower/vue/src/vue.js +84 -0
  99. data/vendor/assets/javascripts/bower/vue/src/watcher.js +240 -0
  100. metadata +65 -20
  101. data/app/assets/javascripts/setting_format.js +0 -15
  102. data/vendor/assets/javascripts/bower/vue/src/binding.js +0 -103
  103. data/vendor/assets/javascripts/bower/vue/src/compiler.js +0 -1037
  104. data/vendor/assets/javascripts/bower/vue/src/deps-parser.js +0 -65
  105. data/vendor/assets/javascripts/bower/vue/src/directives/model.js +0 -174
  106. data/vendor/assets/javascripts/bower/vue/src/directives/view.js +0 -56
  107. data/vendor/assets/javascripts/bower/vue/src/emitter.js +0 -97
  108. data/vendor/assets/javascripts/bower/vue/src/exp-parser.js +0 -190
  109. data/vendor/assets/javascripts/bower/vue/src/filters.js +0 -191
  110. data/vendor/assets/javascripts/bower/vue/src/fragment.js +0 -67
  111. data/vendor/assets/javascripts/bower/vue/src/main.js +0 -188
  112. data/vendor/assets/javascripts/bower/vue/src/observer.js +0 -446
  113. data/vendor/assets/javascripts/bower/vue/src/template-parser.js +0 -46
  114. data/vendor/assets/javascripts/bower/vue/src/text-parser.js +0 -96
  115. data/vendor/assets/javascripts/bower/vue/src/transition.js +0 -228
  116. data/vendor/assets/javascripts/bower/vue/src/utils.js +0 -326
  117. data/vendor/assets/javascripts/bower/vue/src/viewmodel.js +0 -190
@@ -0,0 +1,32 @@
1
+ // xlink
2
+ var xlinkNS = 'http://www.w3.org/1999/xlink'
3
+ var xlinkRE = /^xlink:/
4
+
5
+ module.exports = {
6
+
7
+ priority: 850,
8
+
9
+ bind: function () {
10
+ var name = this.arg
11
+ this.update = xlinkRE.test(name)
12
+ ? xlinkHandler
13
+ : defaultHandler
14
+ }
15
+
16
+ }
17
+
18
+ function defaultHandler (value) {
19
+ if (value || value === 0) {
20
+ this.el.setAttribute(this.arg, value)
21
+ } else {
22
+ this.el.removeAttribute(this.arg)
23
+ }
24
+ }
25
+
26
+ function xlinkHandler (value) {
27
+ if (value != null) {
28
+ this.el.setAttributeNS(xlinkNS, this.arg, value)
29
+ } else {
30
+ this.el.removeAttributeNS(xlinkNS, 'href')
31
+ }
32
+ }
@@ -0,0 +1,18 @@
1
+ var _ = require('../util')
2
+ var addClass = _.addClass
3
+ var removeClass = _.removeClass
4
+
5
+ module.exports = function (value) {
6
+ if (this.arg) {
7
+ var method = value ? addClass : removeClass
8
+ method(this.el, this.arg)
9
+ } else {
10
+ if (this.lastVal) {
11
+ removeClass(this.el, this.lastVal)
12
+ }
13
+ if (value) {
14
+ addClass(this.el, value)
15
+ this.lastVal = value
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,12 @@
1
+ var config = require('../config')
2
+
3
+ module.exports = {
4
+
5
+ bind: function () {
6
+ var el = this.el
7
+ this.vm.$once('hook:compiled', function () {
8
+ el.removeAttribute(config.prefix + 'cloak')
9
+ })
10
+ }
11
+
12
+ }
@@ -0,0 +1,214 @@
1
+ var _ = require('../util')
2
+ var compile = require('../compiler/compile')
3
+ var templateParser = require('../parsers/template')
4
+
5
+ module.exports = {
6
+
7
+ isLiteral: true,
8
+
9
+ /**
10
+ * Setup. Two possible usages:
11
+ *
12
+ * - static:
13
+ * v-component="comp"
14
+ *
15
+ * - dynamic:
16
+ * v-component="{{currentView}}"
17
+ */
18
+
19
+ bind: function () {
20
+ if (!this.el.__vue__) {
21
+ // create a ref anchor
22
+ this.ref = document.createComment('v-component')
23
+ _.replace(this.el, this.ref)
24
+ // check keep-alive options.
25
+ // If yes, instead of destroying the active vm when
26
+ // hiding (v-if) or switching (dynamic literal) it,
27
+ // we simply remove it from the DOM and save it in a
28
+ // cache object, with its constructor id as the key.
29
+ this.keepAlive = this._checkParam('keep-alive') != null
30
+ if (this.keepAlive) {
31
+ this.cache = {}
32
+ }
33
+ // compile parent scope content
34
+ this.parentLinkFn = compile(
35
+ this.el, this.vm.$options,
36
+ true, // partial
37
+ true // asParent
38
+ )
39
+ // if static, build right now.
40
+ if (!this._isDynamicLiteral) {
41
+ this.resolveCtor(this.expression)
42
+ this.childVM = this.build()
43
+ this.childVM.$before(this.ref)
44
+ } else {
45
+ // check dynamic component params
46
+ this.readyEvent = this._checkParam('wait-for')
47
+ this.transMode = this._checkParam('transition-mode')
48
+ }
49
+ } else {
50
+ _.warn(
51
+ 'v-component="' + this.expression + '" cannot be ' +
52
+ 'used on an already mounted instance.'
53
+ )
54
+ }
55
+ },
56
+
57
+ /**
58
+ * Resolve the component constructor to use when creating
59
+ * the child vm.
60
+ */
61
+
62
+ resolveCtor: function (id) {
63
+ this.ctorId = id
64
+ this.Ctor = this.vm.$options.components[id]
65
+ _.assertAsset(this.Ctor, 'component', id)
66
+ },
67
+
68
+ /**
69
+ * Instantiate/insert a new child vm.
70
+ * If keep alive and has cached instance, insert that
71
+ * instance; otherwise build a new one and cache it.
72
+ *
73
+ * @return {Vue} - the created instance
74
+ */
75
+
76
+ build: function () {
77
+ if (this.keepAlive) {
78
+ var cached = this.cache[this.ctorId]
79
+ if (cached) {
80
+ return cached
81
+ }
82
+ }
83
+ var vm = this.vm
84
+ var el = templateParser.clone(this.el)
85
+ if (this.Ctor) {
86
+ var parentUnlinkFn
87
+ if (this.parentLinkFn) {
88
+ parentUnlinkFn = this.parentLinkFn(vm, el)
89
+ }
90
+ var child = vm.$addChild({
91
+ el: el
92
+ }, this.Ctor)
93
+ child._parentUnlinkFn = parentUnlinkFn
94
+ if (this.keepAlive) {
95
+ this.cache[this.ctorId] = child
96
+ }
97
+ return child
98
+ }
99
+ },
100
+
101
+ /**
102
+ * Teardown the current child, but defers cleanup so
103
+ * that we can separate the destroy and removal steps.
104
+ */
105
+
106
+ unbuild: function () {
107
+ var child = this.childVM
108
+ if (!child || this.keepAlive) {
109
+ return
110
+ }
111
+ if (child._parentUnlinkFn) {
112
+ child._parentUnlinkFn()
113
+ }
114
+ // the sole purpose of `deferCleanup` is so that we can
115
+ // "deactivate" the vm right now and perform DOM removal
116
+ // later.
117
+ child.$destroy(false, true)
118
+ },
119
+
120
+ /**
121
+ * Remove current destroyed child and manually do
122
+ * the cleanup after removal.
123
+ *
124
+ * @param {Function} cb
125
+ */
126
+
127
+ removeCurrent: function (cb) {
128
+ var child = this.childVM
129
+ var keepAlive = this.keepAlive
130
+ if (child) {
131
+ child.$remove(function () {
132
+ if (!keepAlive) child._cleanup()
133
+ if (cb) cb()
134
+ })
135
+ } else if (cb) {
136
+ cb()
137
+ }
138
+ },
139
+
140
+ /**
141
+ * Update callback for the dynamic literal scenario,
142
+ * e.g. v-component="{{view}}"
143
+ */
144
+
145
+ update: function (value) {
146
+ if (!value) {
147
+ // just destroy and remove current
148
+ this.unbuild()
149
+ this.removeCurrent()
150
+ this.childVM = null
151
+ } else {
152
+ this.resolveCtor(value)
153
+ this.unbuild()
154
+ var newComponent = this.build()
155
+ var self = this
156
+ if (this.readyEvent) {
157
+ newComponent.$once(this.readyEvent, function () {
158
+ self.swapTo(newComponent)
159
+ })
160
+ } else {
161
+ this.swapTo(newComponent)
162
+ }
163
+ }
164
+ },
165
+
166
+ /**
167
+ * Actually swap the components, depending on the
168
+ * transition mode. Defaults to simultaneous.
169
+ *
170
+ * @param {Vue} target
171
+ */
172
+
173
+ swapTo: function (target) {
174
+ var self = this
175
+ switch (self.transMode) {
176
+ case 'in-out':
177
+ target.$before(self.ref, function () {
178
+ self.removeCurrent()
179
+ self.childVM = target
180
+ })
181
+ break
182
+ case 'out-in':
183
+ self.removeCurrent(function () {
184
+ target.$before(self.ref)
185
+ self.childVM = target
186
+ })
187
+ break
188
+ default:
189
+ self.removeCurrent()
190
+ target.$before(self.ref)
191
+ self.childVM = target
192
+ }
193
+ },
194
+
195
+ /**
196
+ * Unbind.
197
+ */
198
+
199
+ unbind: function () {
200
+ this.unbuild()
201
+ // destroy all keep-alive cached instances
202
+ if (this.cache) {
203
+ for (var key in this.cache) {
204
+ var child = this.cache[key]
205
+ if (child._parentUnlinkFn) {
206
+ child._parentUnlinkFn()
207
+ }
208
+ child.$destroy()
209
+ }
210
+ this.cache = null
211
+ }
212
+ }
213
+
214
+ }
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+
3
+ isLiteral: true,
4
+
5
+ bind: function () {
6
+ this.vm.$$[this.expression] = this.el
7
+ },
8
+
9
+ unbind: function () {
10
+ delete this.vm.$$[this.expression]
11
+ }
12
+
13
+ }
@@ -1,41 +1,37 @@
1
- var utils = require('../utils'),
2
- slice = [].slice
1
+ var _ = require('../util')
2
+ var templateParser = require('../parsers/template')
3
3
 
4
- /**
5
- * Binding for innerHTML
6
- */
7
4
  module.exports = {
8
5
 
9
- bind: function () {
10
- // a comment node means this is a binding for
11
- // {{{ inline unescaped html }}}
12
- if (this.el.nodeType === 8) {
13
- // hold nodes
14
- this.nodes = []
15
- }
16
- },
6
+ bind: function () {
7
+ // a comment node means this is a binding for
8
+ // {{{ inline unescaped html }}}
9
+ if (this.el.nodeType === 8) {
10
+ // hold nodes
11
+ this.nodes = []
12
+ }
13
+ },
17
14
 
18
- update: function (value) {
19
- value = utils.guard(value)
20
- if (this.nodes) {
21
- this.swap(value)
22
- } else {
23
- this.el.innerHTML = value
24
- }
25
- },
15
+ update: function (value) {
16
+ value = _.toString(value)
17
+ if (this.nodes) {
18
+ this.swap(value)
19
+ } else {
20
+ this.el.innerHTML = value
21
+ }
22
+ },
26
23
 
27
- swap: function (value) {
28
- var parent = this.el.parentNode,
29
- nodes = this.nodes,
30
- i = nodes.length
31
- // remove old nodes
32
- while (i--) {
33
- parent.removeChild(nodes[i])
34
- }
35
- // convert new value to a fragment
36
- var frag = utils.toFragment(value)
37
- // save a reference to these nodes so we can remove later
38
- this.nodes = slice.call(frag.childNodes)
39
- parent.insertBefore(frag, this.el)
24
+ swap: function (value) {
25
+ // remove old nodes
26
+ var i = this.nodes.length
27
+ while (i--) {
28
+ _.remove(this.nodes[i])
40
29
  }
30
+ // convert new value to a fragment
31
+ var frag = templateParser.parse(value, true)
32
+ // save a reference to these nodes so we can remove later
33
+ this.nodes = _.toArray(frag.childNodes)
34
+ _.before(frag, this.el)
35
+ }
36
+
41
37
  }
@@ -1,56 +1,87 @@
1
- var utils = require('../utils')
1
+ var _ = require('../util')
2
+ var compile = require('../compiler/compile')
3
+ var templateParser = require('../parsers/template')
4
+ var transition = require('../transition')
2
5
 
3
- /**
4
- * Manages a conditional child VM
5
- */
6
6
  module.exports = {
7
7
 
8
- bind: function () {
9
-
10
- this.parent = this.el.parentNode
11
- this.ref = document.createComment('vue-if')
12
- this.Ctor = this.compiler.resolveComponent(this.el)
13
-
14
- // insert ref
15
- this.parent.insertBefore(this.ref, this.el)
16
- this.parent.removeChild(this.el)
8
+ bind: function () {
9
+ var el = this.el
10
+ if (!el.__vue__) {
11
+ this.start = document.createComment('v-if-start')
12
+ this.end = document.createComment('v-if-end')
13
+ _.replace(el, this.end)
14
+ _.before(this.start, this.end)
15
+ if (el.tagName === 'TEMPLATE') {
16
+ this.template = templateParser.parse(el, true)
17
+ } else {
18
+ this.template = document.createDocumentFragment()
19
+ this.template.appendChild(el)
20
+ }
21
+ // compile the nested partial
22
+ this.linker = compile(
23
+ this.template,
24
+ this.vm.$options,
25
+ true
26
+ )
27
+ } else {
28
+ this.invalid = true
29
+ _.warn(
30
+ 'v-if="' + this.expression + '" cannot be ' +
31
+ 'used on an already mounted instance.'
32
+ )
33
+ }
34
+ },
17
35
 
18
- if (utils.attr(this.el, 'view')) {
19
- utils.warn(
20
- 'Conflict: v-if cannot be used together with v-view. ' +
21
- 'Just set v-view\'s binding value to empty string to empty it.'
22
- )
23
- }
24
- if (utils.attr(this.el, 'repeat')) {
25
- utils.warn(
26
- 'Conflict: v-if cannot be used together with v-repeat. ' +
27
- 'Use `v-show` or the `filterBy` filter instead.'
28
- )
29
- }
30
- },
36
+ update: function (value) {
37
+ if (this.invalid) return
38
+ if (value) {
39
+ this.insert()
40
+ } else {
41
+ this.teardown()
42
+ }
43
+ },
31
44
 
32
- update: function (value) {
45
+ insert: function () {
46
+ // avoid duplicate inserts, since update() can be
47
+ // called with different truthy values
48
+ if (!this.unlink) {
49
+ this.compile(this.template)
50
+ }
51
+ },
33
52
 
34
- if (!value) {
35
- this.unbind()
36
- } else if (!this.childVM) {
37
- this.childVM = new this.Ctor({
38
- el: this.el.cloneNode(true),
39
- parent: this.vm
40
- })
41
- if (this.compiler.init) {
42
- this.parent.insertBefore(this.childVM.$el, this.ref)
43
- } else {
44
- this.childVM.$before(this.ref)
45
- }
46
- }
47
-
48
- },
53
+ compile: function (template) {
54
+ var vm = this.vm
55
+ var frag = templateParser.clone(template)
56
+ var originalChildLength = vm._children
57
+ ? vm._children.length
58
+ : 0
59
+ this.unlink = this.linker
60
+ ? this.linker(vm, frag)
61
+ : vm.$compile(frag)
62
+ transition.blockAppend(frag, this.end, vm)
63
+ this.children = vm._children
64
+ ? vm._children.slice(originalChildLength)
65
+ : null
66
+ if (this.children && _.inDoc(vm.$el)) {
67
+ this.children.forEach(function (child) {
68
+ child._callHook('attached')
69
+ })
70
+ }
71
+ },
49
72
 
50
- unbind: function () {
51
- if (this.childVM) {
52
- this.childVM.$destroy()
53
- this.childVM = null
73
+ teardown: function () {
74
+ if (!this.unlink) return
75
+ transition.blockRemove(this.start, this.end, this.vm)
76
+ if (this.children && _.inDoc(this.vm.$el)) {
77
+ this.children.forEach(function (child) {
78
+ if (!child._isDestroyed) {
79
+ child._callHook('detached')
54
80
  }
81
+ })
55
82
  }
83
+ this.unlink()
84
+ this.unlink = null
85
+ }
86
+
56
87
  }