Skip to content

Commit abcf11d

Browse files
authored
Merge pull request #468 from matestack/next-release
1.1.0 Release
2 parents 682d7d4 + b244c50 commit abcf11d

File tree

71 files changed

+1316
-17625
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1316
-17625
lines changed

Diff for: CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v1.1.0 Release
4+
5+
### Improvements
6+
7+
* added the `cable` component in order to use ActionCable to update the DOM
8+
39
## v1.0.1 Release
410

511
This release contains bugfixes.

Diff for: Gemfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
matestack-ui-core (1.0.0)
4+
matestack-ui-core (1.0.1)
55
cells-haml
66
cells-rails
77
haml

Diff for: app/concepts/matestack/ui/core/async/async.js

+6-28
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,9 @@ const componentDef = {
7676
},
7777
created: function () {
7878
const self = this
79-
if(this.componentConfig["show_on"] != undefined){
80-
this.showing = false
81-
var show_events = this.componentConfig["show_on"].split(",")
82-
show_events.forEach(show_event => matestackEventHub.$on(show_event.trim(), self.show));
83-
}
84-
if(this.componentConfig["hide_on"] != undefined){
85-
var hide_events = this.componentConfig["hide_on"].split(",")
86-
hide_events.forEach(hide_event => matestackEventHub.$on(hide_event.trim(), self.hide));
87-
}
88-
if(this.componentConfig["rerender_on"] != undefined){
89-
var rerender_events = this.componentConfig["rerender_on"].split(",")
90-
rerender_events.forEach(rerender_event => matestackEventHub.$on(rerender_event.trim(), self.rerender));
91-
}
79+
self.registerEvents(this.componentConfig['show_on'], self.show)
80+
self.registerEvents(this.componentConfig['hide_on'], self.hide)
81+
self.registerEvents(this.componentConfig['rerender_on'], self.rerender)
9282
if(this.componentConfig["show_on"] != undefined){
9383
this.showing = false
9484
}
@@ -106,21 +96,9 @@ const componentDef = {
10696
beforeDestroy: function() {
10797
const self = this
10898
clearTimeout(self.hideAfterTimeout)
109-
matestackEventHub.$off(this.componentConfig["rerender_on"], self.rerender);
110-
matestackEventHub.$off(this.componentConfig["show_on"], self.show);
111-
matestackEventHub.$off(this.componentConfig["hide_on"], self.hide);
112-
if(this.componentConfig["show_on"] != undefined){
113-
var shown_events = this.componentConfig["show_on"].split(",")
114-
shown_events.forEach(show_event => matestackEventHub.$off(show_event.trim(), self.show));
115-
}
116-
if(this.componentConfig["hide_on"] != undefined){
117-
var hiden_events = this.componentConfig["hide_on"].split(",")
118-
hiden_events.forEach(hide_event => matestackEventHub.$off(hide_event.trim(), self.hide));
119-
}
120-
if(this.componentConfig["rerender_on"] != undefined){
121-
var rerender_events = this.componentConfig["rerender_on"].split(",")
122-
rerender_events.forEach(rerender_event => matestackEventHub.$off(rerender_event.trim(), self.rerender));
123-
}
99+
self.removeEvents(this.componentConfig["show_on"], self.show)
100+
self.removeEvents(this.componentConfig["hide_on"], self.hide)
101+
self.removeEvents(this.componentConfig["rerender_on"], self.rerender)
124102
},
125103
components: {
126104
VRuntimeTemplate: VRuntimeTemplate

Diff for: app/concepts/matestack/ui/core/async/async.rb

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
module Matestack::Ui::Core::Async
2-
class Async < Matestack::Ui::Core::Component::Rerender
2+
class Async < Matestack::Ui::Core::Component::Dynamic
33
vue_js_component_name "matestack-ui-core-async"
44

5-
optional :id # will be required in 1.0.0
5+
requires :id # required since 1.1.0
66

77
def initialize(*args)
88
super
9-
ActiveSupport::Deprecation.warn(
10-
'Calling async components without id is deprecated. Instead provide a unique id for async components.'
11-
) if id.blank?
12-
@component_config[:component_key] = id || "async_#{Digest::SHA256.hexdigest(caller[3])}"
13-
if @included_config.present? && @included_config[:isolated_parent_class].present?
14-
@component_config[:parent_class] = @included_config[:isolated_parent_class]
9+
component_config[:component_key] = id
10+
if included_config.present? && included_config[:isolated_parent_class].present?
11+
component_config[:parent_class] = included_config[:isolated_parent_class]
1512
end
1613
end
1714

1815
def children_wrapper_attributes
1916
html_attributes.merge({
2017
"v-if": "showing",
21-
id: @component_config[:component_key]
18+
id: component_config[:component_key]
2219
})
2320
end
2421

@@ -33,7 +30,7 @@ def render_content
3330
end
3431

3532
def get_component_key
36-
@component_config[:component_key]
33+
component_config[:component_key]
3734
end
3835

3936
end

Diff for: app/concepts/matestack/ui/core/cable/cable.haml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
%component{dynamic_tag_attributes.merge('initial-template': "#{render_content}")}
2+
%div{class: "matestack-cable-component-container", "v-bind:class": "{ 'loading': loading === true }"}
3+
%div{class: "matestack-cable-component-wrapper", "v-if": "cableTemplate != null", "v-bind:class": "{ 'loading': loading === true }"}
4+
%v-runtime-template{":template":"cableTemplate"}

Diff for: app/concepts/matestack/ui/core/cable/cable.js

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import Vue from 'vue/dist/vue.esm'
2+
import VRuntimeTemplate from "v-runtime-template"
3+
import matestackEventHub from '../js/event-hub'
4+
import componentMixin from '../component/component'
5+
6+
const componentDef = {
7+
mixins: [componentMixin],
8+
props: {
9+
initialTemplate: String,
10+
},
11+
data: function(){
12+
return {
13+
cableTemplate: null,
14+
cableTemplateDomElement: null,
15+
loading: false,
16+
event: {
17+
data: {}
18+
}
19+
}
20+
},
21+
methods: {
22+
append: function(payload){
23+
var html = this.formatPayload(payload)
24+
this.cableTemplateDomElement.insertAdjacentHTML(
25+
'beforeend',
26+
html.join('')
27+
)
28+
this.updateCableTemplate()
29+
},
30+
prepend: function(payload){
31+
var html = this.formatPayload(payload)
32+
this.cableTemplateDomElement.insertAdjacentHTML(
33+
'afterbegin',
34+
html.join('')
35+
)
36+
this.updateCableTemplate()
37+
},
38+
delete: function(payload){
39+
var ids = this.formatPayload(payload)
40+
ids.forEach(id =>
41+
this.cableTemplateDomElement.querySelector('#' + id).remove()
42+
)
43+
this.updateCableTemplate()
44+
},
45+
update: function(payload){
46+
const self = this
47+
var html = this.formatPayload(payload)
48+
html.forEach(function(elem){
49+
var dom_elem = document.createElement('div')
50+
dom_elem.innerHTML = elem
51+
var id = dom_elem.firstChild.id
52+
var old_elem = self.cableTemplateDomElement.querySelector('#' + id)
53+
old_elem.parentNode.replaceChild(dom_elem.firstChild, old_elem)
54+
})
55+
this.updateCableTemplate()
56+
},
57+
replace: function(payload){
58+
var html = this.formatPayload(payload)
59+
this.cableTemplateDomElement.innerHTML = html.join('')
60+
this.updateCableTemplate()
61+
},
62+
updateCableTemplate: function(){
63+
this.cableTemplate = this.cableTemplateDomElement.outerHTML
64+
},
65+
formatPayload: function(payload){
66+
if(!Array.isArray(payload.data)){
67+
return [payload.data]
68+
}
69+
return payload.data
70+
},
71+
},
72+
mounted: function() {
73+
const self = this
74+
var dom_elem = document.createElement('div')
75+
dom_elem.innerHTML = this.initialTemplate
76+
this.cableTemplateDomElement = dom_elem.querySelector("#" + this.componentConfig["id"])
77+
this.cableTemplate = this.cableTemplateDomElement.outerHTML
78+
this.registerEvents(this.componentConfig['append_on'], self.append)
79+
this.registerEvents(this.componentConfig['prepend_on'], self.prepend)
80+
this.registerEvents(this.componentConfig['delete_on'], self.delete)
81+
this.registerEvents(this.componentConfig['update_on'], self.update)
82+
this.registerEvents(this.componentConfig['replace_on'], self.replace)
83+
},
84+
beforeDestroy: function() {
85+
const self = this
86+
this.cableTemplate = null
87+
this.removeEvents(this.componentConfig['append_on'], self.append)
88+
this.removeEvents(this.componentConfig['prepend_on'], self.prepend)
89+
this.removeEvents(this.componentConfig['delete_on'], self.delete)
90+
this.removeEvents(this.componentConfig['update_on'], self.update)
91+
this.removeEvents(this.componentConfig['replace_on'], self.replace)
92+
},
93+
components: {
94+
VRuntimeTemplate: VRuntimeTemplate
95+
}
96+
}
97+
98+
let component = Vue.component('matestack-ui-core-cable', componentDef)
99+
100+
export default componentDef

Diff for: app/concepts/matestack/ui/core/cable/cable.rb

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module Matestack::Ui::Core::Cable
2+
class Cable < Matestack::Ui::Core::Component::Dynamic
3+
vue_js_component_name 'matestack-ui-core-cable'
4+
5+
requires :id
6+
7+
def setup
8+
component_config[:component_key] = id
9+
end
10+
11+
def show
12+
render :cable
13+
end
14+
15+
def render_content
16+
render :children_wrapper do
17+
render :children
18+
end
19+
end
20+
21+
def children_wrapper_attributes
22+
html_attributes.merge({
23+
id: component_config[:component_key]
24+
})
25+
end
26+
27+
end
28+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
%div{ children_wrapper_attributes.merge(class: "matestack-cable-component-root") }
2+
=yield

Diff for: app/concepts/matestack/ui/core/collection/content/content.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import Vue from 'vue/dist/vue.esm'
22
import matestackEventHub from '../../js/event-hub'
33
import queryParamsHelper from '../../js/helpers/query-params-helper'
44
import componentMixin from '../../component/component'
5-
import asyncMixin from '../../async/async'
5+
// import asyncMixin from '../../async/async'
66

77
const componentDef = {
8-
mixins: [componentMixin, asyncMixin],
8+
mixins: [componentMixin],
99
data: function(){
1010
return {
1111
currentLimit: null,

Diff for: app/concepts/matestack/ui/core/collection/content/content.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Matestack::Ui::Core::Collection::Content
2-
class Content < Matestack::Ui::Core::Component::Rerender
2+
class Content < Matestack::Ui::Core::Component::Dynamic
33
vue_js_component_name 'matestack-ui-core-collection-content'
44

55
def setup

Diff for: app/concepts/matestack/ui/core/component/base.rb

+9-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ class Base < Trailblazer::Cell
44
include Matestack::Ui::Core::HasViewContext
55
include Matestack::Ui::Core::HtmlAttributes
66
include Matestack::Ui::Core::Properties
7+
include Matestack::Ui::Core::DSL
78

89
# define html global attributes
910
html_attributes *HTML_GLOBAL_ATTRIBUTES, *HTML_EVENT_ATTRIBUTES
1011

11-
# probably need to remove for other tests to be green again
12-
include Matestack::Ui::Core::DSL
1312

1413
view_paths << "#{Matestack::Ui::Core::Engine.root}/app/concepts"
1514
view_paths << "#{::Rails.root}#{'/' unless ::Rails.root.nil?}app/matestack"
@@ -99,6 +98,11 @@ def set_included_config config
9998
def get_included_config
10099
@included_config
101100
end
101+
alias :included_config :get_included_config
102+
103+
def component_config
104+
@component_config
105+
end
102106

103107
# TODO: modifies/recreates view lookup paths on every invocation?!
104108
# At least memoize it I guess...
@@ -161,8 +165,10 @@ def prepare
161165
def params
162166
if @matestack_context.present? && @matestack_context[:controller].present?
163167
@matestack_context[:controller].params
164-
else
168+
elsif context.present? && context[:params]
165169
context[:params]
170+
else
171+
ActionController::Parameters.new({})
166172
end
167173
end
168174

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1+
import matestackEventHub from '../js/event-hub'
2+
13
const componentMixin = {
2-
props: ['componentConfig', 'params']
4+
props: ['componentConfig', 'params'],
5+
methods: {
6+
registerEvents: function(events, callback){
7+
if(events != undefined){
8+
var event_names = events.split(",")
9+
event_names.forEach(event_name => matestackEventHub.$on(event_name.trim(), callback));
10+
}
11+
},
12+
removeEvents: function(events, callback){
13+
if(events != undefined){
14+
var event_names = events.split(",")
15+
event_names.forEach(event_name => matestackEventHub.$off(event_name.trim(), callback));
16+
}
17+
}
18+
}
19+
320
}
421

522
export default componentMixin

Diff for: app/concepts/matestack/ui/core/component/dynamic.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def dynamic_tag_attributes
1616
"is": get_vue_js_name,
1717
"ref": component_id,
1818
":params": params.except(:controller, :action).to_json,
19-
":component-config": @component_config.to_json,
19+
":component-config": component_config.to_json,
2020
"inline-template": true,
2121
}
2222
attrs.merge!(options[:attributes]) unless options[:attributes].nil?

Diff for: app/concepts/matestack/ui/core/component/rerender.rb

-8
This file was deleted.

Diff for: app/concepts/matestack/ui/core/js/core.js

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { turbolinksAdapterMixin } from 'vue-turbolinks';
44
// Import from app/concepts/matestack/ui/core:
55
import app from '../app/app'
66
import async from '../async/async'
7+
import cable from '../cable/cable'
78
import pageContent from '../page/content/content'
89
import toggle from '../toggle/toggle'
910
import store from '../app/store'

Diff for: app/helpers/matestack/ui/core/application_helper.rb

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module ApplicationHelper
1414
def self.included(base)
1515
base.extend(ClassMethods)
1616
end
17-
17+
1818
module ClassMethods
1919
def matestack_app _class
2020
@matestack_app_class = _class
@@ -99,8 +99,11 @@ def responder_for(*args)
9999
end
100100

101101
def matestack_component(component, options = {}, &block)
102-
context = (options[:matestack_context] ||= {}).merge(controller: @_controller)
103-
Matestack::Ui::Core::Component::Base.new(options.merge(matestack_context: context)).send(component, options.merge(matestack_context: context), &block)
102+
controller = (self.class <= ActionController::Base) ? self : @_controller
103+
context = (options[:matestack_context] ||= {}).merge(controller: controller)
104+
Matestack::Ui::Core::Component::Base
105+
.new(options.merge(matestack_context: context))
106+
.send(component, options.merge(matestack_context: context), &block).to_s
104107
end
105108
end
106109
end

Diff for: docker-compose.yml

+1-12
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,7 @@ services:
7171
POSTGRES_DB: test
7272
volumes:
7373
- test-data-volume:/var/lib/postgresql/data
74-
75-
postgres_dummy:
76-
image: postgres
77-
expose:
78-
- 5432
79-
environment:
80-
POSTGRES_USER: postgres
81-
POSTGRES_PASSWORD: postgres
82-
POSTGRES_DB: dummy
83-
volumes:
84-
- test-data-volume:/var/lib/postgresql/data
85-
74+
8675
volumes:
8776
test-data-volume:
8877
dummy-data-volume:

0 commit comments

Comments
 (0)