basemate-ui-core 0.3.0 → 0.4.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
  SHA256:
3
- metadata.gz: 9fca01ad9a69d5ad7714be6303266507651f75ec205812a7a7c4771fc2e7255d
4
- data.tar.gz: 0b0d45ba477ba7c4693565cf3ef2e151081892ec0676746c8629682be08554f5
3
+ metadata.gz: dff05e3fe084c36ce2fbd5c1812f87da7682563e314f3cb354e797cfed814b19
4
+ data.tar.gz: dfcc244c148cc0a38adcdcb363cadc6cd211a692a88a3295737b7cc47b5a1abb
5
5
  SHA512:
6
- metadata.gz: 2de5fa9c6e02bb29f16748c16c52c4e3847428348e83299146cbb6c9e8a3a80cd0d2e7d39b380475c6db810f4b60d9778d96005eb5c6df06d2c852816bf90ae0
7
- data.tar.gz: 8f2e45bc1e48ddd2f095728afcfbd6c8522cdc45a1a6e7c856fdf81d4ed01f00da31beb6850dd28d1be8dd4f3d240edc561455d77e34b3148bd676108182adb2
6
+ metadata.gz: 34047d5f4853321fccb736f091840deb4cd77602aafe060be4e1826300cf80eba36424f2604502ec00fd5829dd0cbcb02142b55950972d49329ff6f64d559599
7
+ data.tar.gz: aa2d3034364c8e1c7f060d9f61977734a0353afc3a23148f2c894718d7c8683d8800ea5c5a044c639506d9f2b38874fcd7e4b4efe51f8e4f961d344989ab1a58
data/README.md CHANGED
@@ -1,16 +1,21 @@
1
- # Basemate::Ui::Core
1
+ # Basemate UI Core
2
2
 
3
- Create component based, object oriented views. Get dynamic SPA-like behaviour
4
- through integrated vue.js with zero effort.
3
+ ## What is basemate?
5
4
 
6
- ## Why basemate?
5
+ basemate is a "Rails Engine", turning the MVC-Framework "Ruby on Rails" into a
6
+ Fullstack Web-Development Framework. With basemate you are able to write dynamic
7
+ Web-Apps in pure Ruby. Javascript/HTML/CSS is only used for adding special, custom
8
+ UI-Behaviour.
9
+
10
+ basemate is designed to write maintainable, dynamic Web-UIs on top of Rails and Vue.js with
11
+ minimum effort. In order to increase development speed, basemate's architecture
12
+ moves back- and frontend development closer together. In other words: basemate
13
+ melts Rails and Vue.js down to one holistic Web App Development Framework.
14
+
15
+ basemate progressively replaces the classic Rails-View-Layer. You are able to use
16
+ it alongside your classic views and incrementally turn your Rails-App into a
17
+ dynamic, more maintainable Web-App.
7
18
 
8
- ### Our why:
9
- Frontend development has gotten unnecessarily complex, messy and expensive. Implementing responsive, basic user interfaces often keeps us from creating the really valuable juice (= business logic).
10
- ### Our how:
11
- We're replacing the original view-layer of Ruby on Rails, the most productive MVC framework we know, with our technology. By introducing basemate we get dynamic, fast and simple user interfaces without the need to touch HTML/HAML/ERB/JS/CSS. Plus, it feels like a single page application, but there's no need for all the API hustle SPAs usually bring with them.
12
- ### Our what:
13
- basemate. Declarative frontend solutions.
14
19
 
15
20
  ## Current State
16
21
  This repo is currently under heavy development and should not be used until the
@@ -5,6 +5,9 @@ module Action::Cell
5
5
  @component_config[:action_path] = action_path
6
6
  @component_config[:method] = options[:method]
7
7
  @component_config[:success] = options[:success]
8
+ if options[:notify].nil?
9
+ @component_config[:notify] = true
10
+ end
8
11
  end
9
12
 
10
13
  def action_path
@@ -2,6 +2,8 @@ import Vue from 'vue/dist/vue.esm'
2
2
  import Vuex from 'vuex'
3
3
  import axios from 'axios'
4
4
 
5
+ import basemateEventHub from 'core/js/event-hub'
6
+
5
7
  import componentMixin from 'component/js/component'
6
8
 
7
9
  const componentDef = {
@@ -15,21 +17,26 @@ const componentDef = {
15
17
  axios({
16
18
  method: self.componentConfig["method"],
17
19
  url: self.componentConfig["action_path"],
20
+ data: self.componentConfig["data"],
18
21
  headers: {
19
22
  'X-CSRF-Token': document.getElementsByName("csrf-token")[0].getAttribute('content')
20
23
  }
21
24
  })
22
25
  .then(function(response){
23
26
  for (let key in self.componentConfig["success"]) {
24
- self.$root.$refs[key][self.componentConfig["success"][key]]()
27
+ basemateEventHub.$emit(self.componentConfig["success"][key], key);
25
28
  }
26
- if (typeof basemateUiCoreActionSuccess !== 'undefined') {
27
- basemateUiCoreActionSuccess(response);
29
+ if (self.componentConfig["notify"] === true) {
30
+ if (typeof basemateUiCoreActionSuccess !== 'undefined') {
31
+ basemateUiCoreActionSuccess(response);
32
+ }
28
33
  }
29
34
  })
30
- .catch(function(response){
31
- if (typeof basemateUiCoreActionError !== 'undefined') {
32
- basemateUiCoreActionError(response);
35
+ .catch(function(error){
36
+ if (self.componentConfig["notify"] === true) {
37
+ if (typeof basemateUiCoreActionError !== 'undefined') {
38
+ basemateUiCoreActionError(error);
39
+ }
33
40
  }
34
41
  })
35
42
  }
@@ -1,9 +1,3 @@
1
- - if options[:type] == :button || options[:type] == "button"
2
-
3
- %button{"@click.prevent": "perform"}
4
- = options[:text]
5
-
6
- - if options[:type] == :link || options[:type] == "link"
7
-
8
- %a{href: "#", "@click.prevent": "perform"}
9
- = options[:text]
1
+ %span{"@click.prevent": "perform"}
2
+ - if block_given?
3
+ = yield
@@ -1,4 +1,4 @@
1
- module Navigation::Cell
1
+ module Button::Cell
2
2
  class Button < Component::Cell::Static
3
3
 
4
4
  end
@@ -0,0 +1,7 @@
1
+ - if options[:text].nil?
2
+ %button{"class": options[:class], "id": component_id}
3
+ - if block_given?
4
+ = yield
5
+ - else
6
+ %button{"class": options[:class], "id": component_id}
7
+ = options[:text]
@@ -42,21 +42,31 @@ module Component::Cell
42
42
  @controller_context = context[:controller_context]
43
43
  @argument = model
44
44
  @static = false
45
+ @nodes = {}
46
+ @cells = {}
45
47
  generate_component_name
46
48
  generate_children_cells
47
49
  setup
48
50
  end
49
51
 
50
- def self.static
51
- @static = true
52
- end
53
-
54
52
  def setup
55
53
  true
56
54
  end
57
55
 
58
56
  def show(&block)
59
- render(view: :dynamic, &block)
57
+ if respond_to? :prepare
58
+ prepare
59
+ end
60
+ if respond_to? :response
61
+ response &block
62
+ render :response
63
+ else
64
+ if @static
65
+ render(view: :static, &block)
66
+ else
67
+ render(view: :dynamic, &block)
68
+ end
69
+ end
60
70
  end
61
71
 
62
72
  def render_children
@@ -70,7 +80,7 @@ module Component::Cell
70
80
  end
71
81
 
72
82
  def component_id
73
- options[:id] ||= @component_key
83
+ options[:id] ||= nil
74
84
  end
75
85
 
76
86
  def js_action name, arguments
@@ -83,6 +93,18 @@ module Component::Cell
83
93
  js_action("navigateTo", [path])
84
94
  end
85
95
 
96
+ def components(&block)
97
+ @nodes = ::Component::Utils::ComponentNode.build(self, &block)
98
+
99
+ @nodes.each do |key, node|
100
+ @cells[key] = to_cell(key, node["component_name"], node["config"], node["argument"], node["components"])
101
+ end
102
+ end
103
+
104
+ def partial(&block)
105
+ ::Component::Utils::ComponentNode.build(self, &block)
106
+ end
107
+
86
108
  private
87
109
 
88
110
  def generate_children_cells
@@ -11,13 +11,5 @@ module Component::Cell
11
11
  end
12
12
  end
13
13
 
14
- def show(&block)
15
- if @static
16
- render(view: :static, &block)
17
- else
18
- render(view: :dynamic, &block)
19
- end
20
- end
21
-
22
14
  end
23
15
  end
@@ -2,6 +2,8 @@ import Vue from 'vue/dist/vue.esm'
2
2
  import axios from 'axios'
3
3
  import VRuntimeTemplate from "v-runtime-template"
4
4
 
5
+ import basemateEventHub from 'core/js/event-hub'
6
+
5
7
  const componentMixin = {
6
8
  props: ['componentConfig', 'params'],
7
9
  data: function(){
@@ -10,6 +12,11 @@ const componentMixin = {
10
12
  }
11
13
  },
12
14
  methods: {
15
+ onRerender: function(event){
16
+ if (this.$el.id === event){
17
+ this.rerender()
18
+ }
19
+ },
13
20
  rerender: function(){
14
21
  var self = this;
15
22
  self.params["component_key"] = self.componentConfig["component_key"]
@@ -30,6 +37,14 @@ const componentMixin = {
30
37
  this.rerender()
31
38
  }
32
39
  },
40
+ created: function () {
41
+ const self = this
42
+ basemateEventHub.$on('rerender', self.onRerender)
43
+ },
44
+ beforeDestroy: function() {
45
+ const self = this
46
+ basemateEventHub.$off('rerender', self.onRerender);
47
+ },
33
48
  components: {
34
49
  VRuntimeTemplate: VRuntimeTemplate
35
50
  }
@@ -0,0 +1,51 @@
1
+ module Component::Utils
2
+ class ComponentNode
3
+
4
+ def self.build(component_instance, &block)
5
+ node = ComponentNode.new(component_instance)
6
+ node.instance_eval(&block)
7
+ node.hash
8
+ end
9
+
10
+ attr_reader :hash
11
+
12
+ def initialize(component_instance)
13
+ @hash = {}
14
+ @node_start_id = 0
15
+ @component_instance = component_instance
16
+ component_instance.instance_variables.each do |component_instance_var_key|
17
+ self.instance_variable_set(component_instance_var_key, component_instance.instance_variable_get(component_instance_var_key))
18
+ end
19
+ end
20
+
21
+ def method_missing meth, *args, &block
22
+ begin
23
+ @component_instance.send(meth, *args, &block)
24
+ rescue
25
+ node_id = @node_start_id + 1
26
+ @node_start_id = node_id
27
+ current_node = "#{meth}_#{@node_start_id}"
28
+ @hash[current_node] = {}
29
+ @hash[current_node]["component_name"] = meth.to_s
30
+ @hash[current_node]["config"] = {}
31
+ @hash[current_node]["argument"] = nil
32
+
33
+ if meth == :partial
34
+ @hash[current_node]["components"] = @component_instance.send(args.first, *args.drop(1))
35
+ else
36
+ if args.first.is_a?(Hash)
37
+ @hash[current_node]["config"] = args.first
38
+ else
39
+ @hash[current_node]["argument"] = args.first
40
+ end
41
+
42
+ if block_given?
43
+ @hash[current_node]["components"] = ComponentNode.build(@component_instance, &block)
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,2 @@
1
+ - @cells.each do |key, cell|
2
+ = cell.call(:show)
@@ -7,12 +7,13 @@ import anonymDynamicComponent from 'component/js/anonym-dynamic-component'
7
7
  import html from 'html/js/html'
8
8
  import transition from 'transition/js/transition'
9
9
  import action from 'action/js/action'
10
+ import form from 'form/js/form'
10
11
 
11
-
12
+ let basemateUiApp = undefined
12
13
 
13
14
  document.addEventListener('DOMContentLoaded', () => {
14
15
 
15
- const basemateUiApp = new Vue({
16
+ basemateUiApp = new Vue({
16
17
  el: "#basemate_ui",
17
18
  store: store
18
19
  })
@@ -0,0 +1,5 @@
1
+ import Vue from 'vue/dist/vue.esm'
2
+
3
+ const basemateEventHub = new Vue();
4
+
5
+ export default basemateEventHub
@@ -0,0 +1,23 @@
1
+ module Form::Cell
2
+ class Form < Component::Cell::Dynamic
3
+
4
+ def setup
5
+ @component_config[:submit_path] = submit_path
6
+ @component_config[:method] = options[:method]
7
+ @component_config[:success] = options[:success]
8
+ if options[:notify].nil?
9
+ @component_config[:notify] = true
10
+ end
11
+ end
12
+
13
+ def submit_path
14
+ begin
15
+ return ::Rails.application.routes.url_helpers.send(options[:path], options[:params])
16
+ rescue
17
+ "path_not_found"
18
+ end
19
+ end
20
+
21
+
22
+ end
23
+ end
@@ -0,0 +1,76 @@
1
+ import Vue from 'vue/dist/vue.esm'
2
+ import Vuex from 'vuex'
3
+ import axios from 'axios'
4
+
5
+ import basemateEventHub from 'core/js/event-hub'
6
+
7
+ import componentMixin from 'component/js/component'
8
+
9
+ const componentDef = {
10
+ mixins: [componentMixin],
11
+ data: function(){
12
+ return {
13
+ data: {},
14
+ showInlineForm: false
15
+ }
16
+ },
17
+ methods: {
18
+ launchInlineForm: function(key, value){
19
+ this.showInlineForm = true;
20
+ this.data[key] = value;
21
+ const self = this;
22
+ setTimeout(function () {
23
+ self.$refs.inlineinput.focus();
24
+ }, 300);
25
+ },
26
+ closeInlineForm: function(){
27
+ this.showInlineForm = false;
28
+ },
29
+ setProps: function(flat, newVal){
30
+ for(var i in flat){
31
+ if((typeof flat[i] === "object") && !(flat[i] instanceof Array)){
32
+ setProps(flat[i], newVal);
33
+ return;
34
+ } else {
35
+ flat[i] = newVal;
36
+ }
37
+ }
38
+ },
39
+ perform: function(){
40
+ const self = this
41
+ let payload = {}
42
+ payload[self.componentConfig["for"]] = self.data
43
+ axios({
44
+ method: self.componentConfig["method"],
45
+ url: self.componentConfig["submit_path"],
46
+ data: payload,
47
+ headers: {
48
+ 'X-CSRF-Token': document.getElementsByName("csrf-token")[0].getAttribute('content')
49
+ }
50
+ })
51
+ .then(function(response){
52
+ for (let key in self.componentConfig["success"]) {
53
+ basemateEventHub.$emit(self.componentConfig["success"][key], key);
54
+ }
55
+ if (self.componentConfig["notify"] === true) {
56
+ if (typeof basemateUiCoreActionSuccess !== 'undefined') {
57
+ basemateUiCoreActionSuccess(response);
58
+ }
59
+ }
60
+ self.setProps(self.data, null);
61
+ self.showInlineForm = false;
62
+ })
63
+ .catch(function(error){
64
+ if (self.componentConfig["notify"] === true) {
65
+ if (typeof basemateUiCoreActionError !== 'undefined') {
66
+ basemateUiCoreActionError(error);
67
+ }
68
+ }
69
+ })
70
+ }
71
+ }
72
+ }
73
+
74
+ let component = Vue.component('form-cell', componentDef)
75
+
76
+ export default componentDef
@@ -0,0 +1,2 @@
1
+ %form{"@submit.prevent": true}
2
+ = yield
@@ -0,0 +1,9 @@
1
+ module Input::Cell
2
+ class Inline < Component::Cell::Static
3
+
4
+
5
+ def input_key
6
+ 'data["' + options[:key].to_s + '"]'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Input::Cell
2
+ class Input < Component::Cell::Static
3
+
4
+
5
+ def input_key
6
+ 'data["' + options[:key].to_s + '"]'
7
+ end
8
+ end
9
+ end