basemate-ui-core 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +495 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/basemate_ui_core_manifest.js +2 -0
  6. data/app/assets/javascripts/basemate/ui/core/application.js +15 -0
  7. data/app/assets/stylesheets/basemate/ui/core/application.css +15 -0
  8. data/app/concepts/app/cell/app.rb +75 -0
  9. data/app/concepts/app/js/app.js +27 -0
  10. data/app/concepts/app/js/store.js +66 -0
  11. data/app/concepts/app/utils/app_node.rb +53 -0
  12. data/app/concepts/app/view/app.haml +4 -0
  13. data/app/concepts/component/cell/dynamic.rb +110 -0
  14. data/app/concepts/component/cell/static.rb +14 -0
  15. data/app/concepts/component/js/component.js +38 -0
  16. data/app/concepts/component/view/children.haml +2 -0
  17. data/app/concepts/component/view/dynamic.haml +6 -0
  18. data/app/concepts/component/view/static.haml +1 -0
  19. data/app/concepts/core/js/core.js +20 -0
  20. data/app/concepts/div/cell/div.rb +5 -0
  21. data/app/concepts/div/view/div.haml +3 -0
  22. data/app/concepts/header/cell/header.rb +5 -0
  23. data/app/concepts/header/view/header.haml +3 -0
  24. data/app/concepts/heading/cell/heading.rb +5 -0
  25. data/app/concepts/heading/view/heading.haml +50 -0
  26. data/app/concepts/html/cell/html.rb +17 -0
  27. data/app/concepts/html/js/html.js +10 -0
  28. data/app/concepts/html/view/html.haml +3 -0
  29. data/app/concepts/img/cell/img.rb +5 -0
  30. data/app/concepts/img/view/img.haml +1 -0
  31. data/app/concepts/link/cell/link.rb +14 -0
  32. data/app/concepts/link/view/link.haml +6 -0
  33. data/app/concepts/main/cell/main.rb +5 -0
  34. data/app/concepts/main/view/main.haml +3 -0
  35. data/app/concepts/nav/cell/nav.rb +5 -0
  36. data/app/concepts/nav/view/nav.haml +3 -0
  37. data/app/concepts/navigation/cell/button.rb +5 -0
  38. data/app/concepts/navigation/view/button.haml +3 -0
  39. data/app/concepts/page/cell/content.rb +5 -0
  40. data/app/concepts/page/cell/page.rb +110 -0
  41. data/app/concepts/page/utils/page_node.rb +51 -0
  42. data/app/concepts/page/view/content.haml +7 -0
  43. data/app/concepts/page/view/page.haml +3 -0
  44. data/app/concepts/partial/cell/partial.rb +5 -0
  45. data/app/concepts/partial/view/partial.haml +3 -0
  46. data/app/concepts/plain/cell/plain.rb +10 -0
  47. data/app/concepts/section/cell/section.rb +5 -0
  48. data/app/concepts/section/view/section.haml +3 -0
  49. data/app/concepts/shared/utils/to_cell.rb +27 -0
  50. data/app/concepts/span/cell/span.rb +5 -0
  51. data/app/concepts/span/view/span.haml +3 -0
  52. data/app/concepts/transition/cell/transition.rb +18 -0
  53. data/app/concepts/transition/js/transition.js +26 -0
  54. data/app/concepts/transition/view/transition.haml +6 -0
  55. data/app/controllers/basemate/ui/core/application_controller.rb +9 -0
  56. data/app/helpers/basemate/ui/core/application_helper.rb +35 -0
  57. data/config/routes.rb +2 -0
  58. data/lib/basemate/ui/core.rb +14 -0
  59. data/lib/basemate/ui/core/engine.rb +19 -0
  60. data/lib/basemate/ui/core/version.rb +7 -0
  61. data/lib/tasks/basemate/ui/core_tasks.rake +4 -0
  62. metadata +190 -0
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Basemate::Ui::Core'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ load 'rails/tasks/statistics.rake'
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/basemate/ui/core .js
2
+ //= link_directory ../stylesheets/basemate/ui/core .css
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require rails-ujs
14
+ //= require activestorage
15
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,75 @@
1
+ module App::Cell
2
+ class App < Trailblazer::Cell
3
+ include ActionView::Helpers::ActiveModelHelper
4
+ include ActionView::Helpers::ActiveModelInstanceTag
5
+ include ActionView::Helpers::AssetTagHelper
6
+ include ActionView::Helpers::AssetUrlHelper
7
+ include ActionView::Helpers::AtomFeedHelper
8
+ include ActionView::Helpers::CacheHelper
9
+ include ActionView::Helpers::CaptureHelper
10
+ include ActionView::Helpers::CspHelper
11
+ include ActionView::Helpers::CsrfHelper
12
+ include ActionView::Helpers::DateHelper
13
+ include ActionView::Helpers::DebugHelper
14
+ include ActionView::Helpers::FormHelper
15
+ include ActionView::Helpers::FormOptionsHelper
16
+ include ActionView::Helpers::FormTagHelper
17
+ include ActionView::Helpers::JavaScriptHelper
18
+ include ActionView::Helpers::NumberHelper
19
+ include ActionView::Helpers::OutputSafetyHelper
20
+ include ActionView::Helpers::RecordTagHelper
21
+ # include ActionView::Helpers::RenderingHelper
22
+ include ActionView::Helpers::SanitizeHelper
23
+ include ActionView::Helpers::TagHelper
24
+ include ActionView::Helpers::TextHelper
25
+ include ActionView::Helpers::TranslationHelper
26
+ include ActionView::Helpers::UrlHelper
27
+ include ::Cell::Haml
28
+ include ::Basemate::Ui::Core::ApplicationHelper
29
+ include Shared::Utils::ToCell
30
+ # include ::Rails.application.routes.url_helpers
31
+
32
+ view_paths << "#{Basemate::Ui::Core::Engine.root}/app/concepts"
33
+
34
+ def initialize(model=nil, options={})
35
+ super
36
+ @nodes = {}
37
+ @cells = {}
38
+ @page_block = nil
39
+ setup
40
+ end
41
+
42
+ def setup
43
+ true
44
+ end
45
+
46
+ def prepare
47
+ true
48
+ end
49
+
50
+
51
+ def show(page_nodes, &block)
52
+ @page_nodes = page_nodes
53
+ prepare
54
+ response
55
+ render(view: :app, &block)
56
+ end
57
+
58
+ def page_nodes
59
+ @page_nodes
60
+ end
61
+
62
+ def components(&block)
63
+ @nodes = ::App::Utils::AppNode.build(self, &block)
64
+
65
+ @nodes.each do |key, node|
66
+ @cells[key] = to_cell(key, node["component_name"], node["config"], node["argument"], node["components"])
67
+ end
68
+ end
69
+
70
+ def partial(&block)
71
+ ::App::Utils::AppNode.build(self, &block)
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ import Vue from 'vue/dist/vue.esm'
2
+ import axios from 'axios'
3
+ import VRuntimeTemplate from "v-runtime-template"
4
+ import Vuex from 'vuex'
5
+
6
+ const componentDef = {
7
+ props: ['appConfig', 'params'],
8
+ data: function(){
9
+ return {}
10
+ },
11
+ computed: Vuex.mapState({
12
+ asyncTemplate: state => state.pageTemplate,
13
+ }),
14
+ mounted: function(){
15
+ const self = this;
16
+ window.onpopstate = function(event) {
17
+ self.$store.dispatch("navigateTo", {url: document.location.pathname, backwards: true} );
18
+ }
19
+ },
20
+ components: {
21
+ VRuntimeTemplate: VRuntimeTemplate
22
+ }
23
+ }
24
+
25
+ let component = Vue.component('app', componentDef)
26
+
27
+ export default componentDef
@@ -0,0 +1,66 @@
1
+ import Vue from 'vue/dist/vue.esm'
2
+ import Vuex from 'vuex'
3
+ import axios from 'axios'
4
+
5
+ Vue.use(Vuex)
6
+
7
+ const store = new Vuex.Store({
8
+ state: {
9
+ pageTemplate: null,
10
+ currentPath: document.location.pathname
11
+ },
12
+ mutations: {
13
+ setPageTemplate (state, serverResponse){
14
+ state.pageTemplate = serverResponse
15
+ },
16
+ setCurrentPath (state, path){
17
+ state.currentPath = path
18
+ }
19
+ },
20
+ actions: {
21
+ navigateTo ({ commit, state }, { url, backwards }) {
22
+ if (typeof basemateUiCoreTransitionStart !== 'undefined') {
23
+ basemateUiCoreTransitionStart(url);
24
+ }
25
+ if (!window.history.pushState) {
26
+ document.location.href = url;
27
+ return;
28
+ }
29
+ return new Promise((resolve, reject) => {
30
+ axios({
31
+ method: "get",
32
+ url: url,
33
+ headers: {
34
+ 'X-CSRF-Token': document.getElementsByName("csrf-token")[0].getAttribute('content')
35
+ },
36
+ params: {"only_page": true}
37
+ })
38
+ .then(function(response){
39
+ if (backwards){
40
+ window.history.replaceState({basemateApp: true, url: url}, null, url);
41
+ } else {
42
+ window.history.pushState({basemateApp: true, url: url}, null, url);
43
+ }
44
+ setTimeout(function () {
45
+ resolve(response["data"])
46
+ commit('setPageTemplate', response["data"])
47
+ commit('setCurrentPath', url)
48
+ if (typeof basemateUiCoreTransitionSuccess !== 'undefined') {
49
+ basemateUiCoreTransitionSuccess(url);
50
+ }
51
+ }, 300);
52
+ })
53
+ .catch(function(response){
54
+ setTimeout(function () {
55
+ resolve(response["data"])
56
+ if (typeof basemateUiCoreTransitionError !== 'undefined') {
57
+ basemateUiCoreTransitionError(url);
58
+ }
59
+ }, 300);
60
+ })
61
+ })
62
+ }
63
+ }
64
+ })
65
+
66
+ export default store
@@ -0,0 +1,53 @@
1
+ module App::Utils
2
+ class AppNode
3
+
4
+ def self.build(app_instance, &block)
5
+ node = AppNode.new(app_instance)
6
+ node.instance_eval(&block)
7
+ node.hash
8
+ end
9
+
10
+ attr_reader :hash
11
+
12
+ def initialize(app_instance)
13
+ @hash = {}
14
+ @node_start_id = 0
15
+ @app_instance = app_instance
16
+ app_instance.instance_variables.each do |app_instance_var_key|
17
+ self.instance_variable_set(app_instance_var_key, app_instance.instance_variable_get(app_instance_var_key))
18
+ end
19
+ end
20
+
21
+ def method_missing meth, *args, &block
22
+ begin
23
+ @app_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 == :page_content
34
+ @hash[current_node]["components"] = @app_instance.send(:page_nodes)
35
+ elsif meth == :partial
36
+ @hash[current_node]["components"] = @app_instance.send(args.first, *args.drop(1))
37
+ else
38
+ if args.first.is_a?(Hash)
39
+ @hash[current_node]["config"] = args.first
40
+ else
41
+ @hash[current_node]["argument"] = args.first
42
+ end
43
+
44
+ if block_given?
45
+ @hash[current_node]["components"] = AppNode.build(@app_instance, &block)
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,4 @@
1
+ %component{"is": "app", "inline-template": true}
2
+ %div
3
+ - @cells.each do |key, cell|
4
+ = cell.call(:show)
@@ -0,0 +1,110 @@
1
+ module Component::Cell
2
+ class Dynamic < Trailblazer::Cell
3
+ include ActionView::Helpers::ActiveModelHelper
4
+ include ActionView::Helpers::ActiveModelInstanceTag
5
+ include ActionView::Helpers::AssetTagHelper
6
+ include ActionView::Helpers::AssetUrlHelper
7
+ include ActionView::Helpers::AtomFeedHelper
8
+ include ActionView::Helpers::CacheHelper
9
+ include ActionView::Helpers::CaptureHelper
10
+ include ActionView::Helpers::CspHelper
11
+ include ActionView::Helpers::CsrfHelper
12
+ include ActionView::Helpers::DateHelper
13
+ include ActionView::Helpers::DebugHelper
14
+ include ActionView::Helpers::FormHelper
15
+ include ActionView::Helpers::FormOptionsHelper
16
+ include ActionView::Helpers::FormTagHelper
17
+ include ActionView::Helpers::JavaScriptHelper
18
+ include ActionView::Helpers::NumberHelper
19
+ include ActionView::Helpers::OutputSafetyHelper
20
+ include ActionView::Helpers::RecordTagHelper
21
+ # include ActionView::Helpers::RenderingHelper
22
+ include ActionView::Helpers::SanitizeHelper
23
+ include ActionView::Helpers::TagHelper
24
+ include ActionView::Helpers::TextHelper
25
+ include ActionView::Helpers::TranslationHelper
26
+ include ActionView::Helpers::UrlHelper
27
+ # include ActionView::Helpers::UrlHelper
28
+ # include ActionView::Helpers::TranslationHelper
29
+ include ::Cell::Haml
30
+ include ::Basemate::Ui::Core::ApplicationHelper
31
+ include Shared::Utils::ToCell
32
+
33
+ view_paths << "#{Basemate::Ui::Core::Engine.root}/app/concepts"
34
+ view_paths << "#{::Rails.root}/app/basemate"
35
+
36
+ def initialize(model=nil, options={})
37
+ super
38
+ @component_config = options.except(:context, :children, :url_params)
39
+ @url_params = options[:url_params].except(:action, :controller, :component_key)
40
+ @component_key = options[:component_key]
41
+ @children_cells = {}
42
+ @controller_context = context[:controller_context]
43
+ @argument = model
44
+ @static = false
45
+ generate_component_name
46
+ generate_children_cells
47
+ setup
48
+ end
49
+
50
+ def self.static
51
+ @static = true
52
+ end
53
+
54
+ def setup
55
+ true
56
+ end
57
+
58
+ def show(&block)
59
+ render(view: :dynamic, &block)
60
+ end
61
+
62
+ def render_children
63
+ render(view: :children)
64
+ end
65
+
66
+ def render_content(&block)
67
+ render do
68
+ render_children
69
+ end
70
+ end
71
+
72
+ def component_id
73
+ options[:id] ||= @component_key
74
+ end
75
+
76
+ def js_action name, arguments
77
+ argumentString = arguments.join('", "')
78
+ argumentString = '"' + argumentString + '"'
79
+ [name, '(', argumentString, ')'].join("")
80
+ end
81
+
82
+ def navigate_to path
83
+ js_action("navigateTo", [path])
84
+ end
85
+
86
+ private
87
+
88
+ def generate_children_cells
89
+ unless options[:children].nil?
90
+ options[:children].each do |key, node|
91
+ @children_cells[key] = to_cell("#{@component_key}__#{key}", node["component_name"], node["config"], node["argument"], node["components"])
92
+ end
93
+ end
94
+ end
95
+
96
+ def generate_component_name
97
+ name_parts = self.class.name.split("::")
98
+ name = name_parts[0] + name_parts[1]
99
+ if name_parts[0] == name_parts[2]
100
+ name = name_parts[0] + name_parts[1]
101
+ @component_class = name.underscore.gsub("_", "-")
102
+ else
103
+ name = name_parts[0] + name_parts[2] + name_parts[1]
104
+ @component_class = name.underscore.gsub("_", "-")
105
+ end
106
+ @component_name = @component_class.gsub("-cell", "")
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,14 @@
1
+ module Component::Cell
2
+ class Static < Component::Cell::Dynamic
3
+
4
+ def initialize(model=nil, options={})
5
+ super
6
+ @static = true
7
+ end
8
+
9
+ def show(&block)
10
+ render(view: :static, &block)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ import Vue from 'vue/dist/vue.esm'
2
+ import axios from 'axios'
3
+ import VRuntimeTemplate from "v-runtime-template"
4
+
5
+ const componentMixin = {
6
+ props: ['componentConfig', 'params'],
7
+ data: function(){
8
+ return {
9
+ asyncTemplate: null
10
+ }
11
+ },
12
+ methods: {
13
+ rerender: function(){
14
+ var self = this;
15
+ self.params["component_key"] = self.componentConfig["component_key"]
16
+ axios({
17
+ method: "get",
18
+ url: self.componentConfig["origin_url"],
19
+ headers: {
20
+ 'X-CSRF-Token': document.getElementsByName("csrf-token")[0].getAttribute('content')
21
+ },
22
+ params: self.params
23
+ })
24
+ .then(function(response){
25
+ self.asyncTemplate = response["data"];
26
+ })
27
+ },
28
+ rerenderWith: function(newParams){
29
+ Object.assign(this.params, newParams);
30
+ this.rerender()
31
+ }
32
+ },
33
+ components: {
34
+ VRuntimeTemplate: VRuntimeTemplate
35
+ }
36
+ }
37
+
38
+ export default componentMixin