Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | var validEnv = ['development', 'test', 'production']
3 | var currentEnv = api.env()
4 | var isDevelopmentEnv = api.env('development')
5 | var isProductionEnv = api.env('production')
6 | var isTestEnv = api.env('test')
7 |
8 | if (!validEnv.includes(currentEnv)) {
9 | throw new Error(
10 | 'Please specify a valid `NODE_ENV` or ' +
11 | '`BABEL_ENV` environment variables. Valid values are "development", ' +
12 | '"test", and "production". Instead, received: ' +
13 | JSON.stringify(currentEnv) +
14 | '.'
15 | )
16 | }
17 |
18 | return {
19 | presets: [
20 | isTestEnv && [
21 | '@babel/preset-env',
22 | {
23 | targets: {
24 | node: 'current'
25 | }
26 | }
27 | ],
28 | (isProductionEnv || isDevelopmentEnv) && [
29 | '@babel/preset-env',
30 | {
31 | forceAllTransforms: true,
32 | useBuiltIns: 'entry',
33 | corejs: 3,
34 | modules: false,
35 | exclude: ['transform-typeof-symbol']
36 | }
37 | ]
38 | ].filter(Boolean),
39 | plugins: [
40 | 'babel-plugin-macros',
41 | '@babel/plugin-syntax-dynamic-import',
42 | isTestEnv && 'babel-plugin-dynamic-import-node',
43 | '@babel/plugin-transform-destructuring',
44 | [
45 | '@babel/plugin-proposal-class-properties',
46 | {
47 | loose: true
48 | }
49 | ],
50 | [
51 | '@babel/plugin-proposal-object-rest-spread',
52 | {
53 | useBuiltIns: true
54 | }
55 | ],
56 | [
57 | '@babel/plugin-transform-runtime',
58 | {
59 | helpers: false,
60 | regenerator: true,
61 | corejs: false
62 | }
63 | ],
64 | [
65 | '@babel/plugin-transform-regenerator',
66 | {
67 | async: false
68 | }
69 | ]
70 | ].filter(Boolean)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/matestack/components/header.js:
--------------------------------------------------------------------------------
1 | MatestackUiCore.Vue.component('components-header', {
2 | mixins: [MatestackUiCore.componentMixin],
3 | data: function(){
4 | return {
5 | sidebarOpen: false,
6 | expanded: false,
7 | showHeaderShadow: false
8 | }
9 | },
10 | methods: {
11 | sidebarToggle: function() {
12 | var sidebarElement = document.getElementById("sidebar");
13 | if (sidebarElement.classList.contains("closed")) {
14 | this.openSideBar();
15 | } else {
16 | this.closeSideBar();
17 | }
18 | },
19 | openSideBar: function(){
20 | var sidebarElement = document.getElementById("sidebar");
21 | var contentElement = document.getElementsByClassName("matestack-page-root")[0];
22 | this.sidebarOpen = true;
23 | contentElement.classList.remove("sidebar-closed")
24 | sidebarElement.classList.remove("closed")
25 | sidebarElement.classList.add("open")
26 | },
27 | closeSideBar: function(){
28 | var sidebarElement = document.getElementById("sidebar");
29 | var contentElement = document.getElementsByClassName("matestack-page-root")[0];
30 | this.sidebarOpen = false;
31 | contentElement.classList.add("sidebar-closed")
32 | sidebarElement.classList.add("closed")
33 | sidebarElement.classList.remove("open")
34 | },
35 | resizeCallback: function(){
36 | if (window.innerWidth <= 768){
37 | this.closeSideBar();
38 | } else {
39 | this.openSideBar();
40 | }
41 | }
42 | },
43 | mounted: function(){
44 | if (window.innerWidth <= 768){
45 | this.sidebarOpen = true;
46 | }
47 | window.addEventListener('resize', this.resizeCallback);
48 | var self = this;
49 | MatestackUiCore.matestackEventHub.$on("page_loaded", function(){
50 | if (window.innerWidth <= 768){
51 | self.closeSideBar();
52 | }
53 | })
54 | MatestackUiCore.matestackEventHub.$on("page_loading_triggered", function(){
55 | if (window.innerWidth <= 768){
56 | self.closeSideBar();
57 | }
58 | })
59 | }
60 | });
61 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | # The test environment is used exclusively to run your application's
2 | # test suite. You never need to work with it otherwise. Remember that
3 | # your test database is "scratch space" for the test suite and is wiped
4 | # and recreated between test runs. Don't rely on the data there!
5 |
6 | Rails.application.configure do
7 | # Settings specified here will take precedence over those in config/application.rb.
8 |
9 | config.cache_classes = false
10 | config.action_view.cache_template_loading = true
11 |
12 | # Do not eager load code on boot. This avoids loading your whole application
13 | # just for the purpose of running a single test. If you are using a tool that
14 | # preloads Rails for running tests, you may have to set it to true.
15 | config.eager_load = false
16 |
17 | # Configure public file server for tests with Cache-Control for performance.
18 | config.public_file_server.enabled = true
19 | config.public_file_server.headers = {
20 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
21 | }
22 |
23 | # Show full error reports and disable caching.
24 | config.consider_all_requests_local = true
25 | config.action_controller.perform_caching = false
26 | config.cache_store = :null_store
27 |
28 | # Raise exceptions instead of rendering exception templates.
29 | config.action_dispatch.show_exceptions = false
30 |
31 | # Disable request forgery protection in test environment.
32 | config.action_controller.allow_forgery_protection = false
33 |
34 | # Store uploaded files on the local file system in a temporary directory.
35 | config.active_storage.service = :test
36 |
37 | config.action_mailer.perform_caching = false
38 |
39 | # Tell Action Mailer not to deliver emails to the real world.
40 | # The :test delivery method accumulates sent emails in the
41 | # ActionMailer::Base.deliveries array.
42 | config.action_mailer.delivery_method = :test
43 |
44 | # Print deprecation notices to the stderr.
45 | config.active_support.deprecation = :stderr
46 |
47 | # Raises error for missing translations.
48 | # config.action_view.raise_on_missing_translations = true
49 | end
50 |
--------------------------------------------------------------------------------
/config/webpacker.yml:
--------------------------------------------------------------------------------
1 | # Note: You must restart bin/webpack-dev-server for changes to take effect
2 |
3 | default: &default
4 | source_path: app/javascript
5 | source_entry_path: packs
6 | public_root_path: public
7 | public_output_path: packs
8 | cache_path: tmp/cache/webpacker
9 | check_yarn_integrity: false
10 | webpack_compile_output: true
11 |
12 | # Additional paths webpack should lookup modules
13 | # ['app/assets', 'engine/foo/app/assets']
14 | resolved_paths: []
15 |
16 | # Reload manifest.json on all requests so we reload latest compiled packs
17 | cache_manifest: false
18 |
19 | # Extract and emit a css file
20 | extract_css: false
21 |
22 | static_assets_extensions:
23 | - .jpg
24 | - .jpeg
25 | - .png
26 | - .gif
27 | - .tiff
28 | - .ico
29 | - .svg
30 | - .eot
31 | - .otf
32 | - .ttf
33 | - .woff
34 | - .woff2
35 |
36 | extensions:
37 | - .mjs
38 | - .js
39 | - .sass
40 | - .scss
41 | - .css
42 | - .module.sass
43 | - .module.scss
44 | - .module.css
45 | - .png
46 | - .svg
47 | - .gif
48 | - .jpeg
49 | - .jpg
50 |
51 | development:
52 | <<: *default
53 | compile: true
54 |
55 | # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
56 | check_yarn_integrity: true
57 |
58 | # Reference: https://webpack.js.org/configuration/dev-server/
59 | dev_server:
60 | https: false
61 | host: localhost
62 | port: 3035
63 | public: localhost:3035
64 | hmr: false
65 | # Inline should be set to true if using HMR
66 | inline: true
67 | overlay: true
68 | compress: true
69 | disable_host_check: true
70 | use_local_ip: false
71 | quiet: false
72 | pretty: false
73 | headers:
74 | 'Access-Control-Allow-Origin': '*'
75 | watch_options:
76 | ignored: '**/node_modules/**'
77 |
78 |
79 | test:
80 | <<: *default
81 | compile: true
82 |
83 | # Compile test packs to a separate directory
84 | public_output_path: packs-test
85 |
86 | production:
87 | <<: *default
88 |
89 | # Production depends on precompilation of packs prior to booting for performance.
90 | compile: false
91 |
92 | # Extract and emit a css file
93 | extract_css: true
94 |
95 | # Cache manifest.json for performance
96 | cache_manifest: true
97 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 |
4 | ruby '2.6.5'
5 |
6 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7 | gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
8 | # Use postgresql as the database for Active Record
9 | gem 'pg', '>= 0.18', '< 2.0'
10 | # Use Puma as the app server
11 | gem 'puma', '~> 4.1'
12 | # Use SCSS for stylesheets
13 | gem 'sass-rails', '>= 6'
14 | # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
15 | gem 'webpacker', '~> 4.0'
16 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
17 | # gem 'turbolinks', '~> 5'
18 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
19 | gem 'jbuilder', '~> 2.7'
20 | # Use Redis adapter to run Action Cable in production
21 | # gem 'redis', '~> 4.0'
22 | # Use Active Model has_secure_password
23 | # gem 'bcrypt', '~> 3.1.7'
24 |
25 | # Use Active Storage variant
26 | # gem 'image_processing', '~> 1.2'
27 |
28 | gem 'matestack-ui-core', '~> 1.1'
29 |
30 | # for calling Github API
31 | gem 'rest-client'
32 |
33 | # for markdown usage
34 | gem 'redcarpet'
35 |
36 | # for syntax highlighting
37 | gem 'rouge'
38 |
39 | # Reduces boot times through caching; required in config/boot.rb
40 | gem 'bootsnap', '>= 1.4.2', require: false
41 |
42 | group :development, :test do
43 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console
44 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
45 | end
46 |
47 | group :development do
48 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
49 | gem 'web-console', '>= 3.3.0'
50 | gem 'listen', '~> 3.2'
51 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
52 | gem 'spring'
53 | gem 'spring-watcher-listen', '~> 2.0.0'
54 | end
55 |
56 | group :test do
57 | # Adds support for Capybara system testing and selenium driver
58 | gem 'capybara', '>= 2.15'
59 | gem 'selenium-webdriver'
60 | # Easy installation and use of web drivers to run system tests with browsers
61 | gem 'webdrivers'
62 | end
63 |
64 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
65 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
66 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports.
13 | config.consider_all_requests_local = true
14 |
15 | # Enable/disable caching. By default caching is disabled.
16 | # Run rails dev:cache to toggle caching.
17 | if Rails.root.join('tmp', 'caching-dev.txt').exist?
18 | config.action_controller.perform_caching = true
19 | config.action_controller.enable_fragment_cache_logging = true
20 |
21 | config.cache_store = :memory_store
22 | config.public_file_server.headers = {
23 | 'Cache-Control' => "public, max-age=#{2.days.to_i}"
24 | }
25 | else
26 | config.action_controller.perform_caching = false
27 |
28 | config.cache_store = :null_store
29 | end
30 |
31 | # Store uploaded files on the local file system (see config/storage.yml for options).
32 | config.active_storage.service = :local
33 |
34 | # Don't care if the mailer can't send.
35 | config.action_mailer.raise_delivery_errors = false
36 |
37 | config.action_mailer.perform_caching = false
38 |
39 | # Print deprecation notices to the Rails logger.
40 | config.active_support.deprecation = :log
41 |
42 | # Raise an error on page load if there are pending migrations.
43 | config.active_record.migration_error = :page_load
44 |
45 | # Highlight code that triggered database queries in logs.
46 | config.active_record.verbose_query_logs = true
47 |
48 | # Debug mode disables concatenation and preprocessing of assets.
49 | # This option may cause significant delays in view rendering with a large
50 | # number of complex assets.
51 | config.assets.debug = true
52 |
53 | # Suppress logger output for asset requests.
54 | config.assets.quiet = true
55 |
56 | # Raises error for missing translations.
57 | # config.action_view.raise_on_missing_translations = true
58 |
59 | # Use an evented file watcher to asynchronously detect changes in source code,
60 | # routes, locales, etc. This feature depends on the listen gem.
61 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
62 | end
63 |
--------------------------------------------------------------------------------
/app/javascript/css/custom-bootstrap.scss:
--------------------------------------------------------------------------------
1 | // Styleguide Color Palette
2 | $m_orange: #ff3b14;
3 | $m_dark: #1b1d35;
4 | $m_dark_grey: #323349;
5 | $m_grey: #606171;
6 | $m_lighter_grey: #EE3B23;
7 | $m_light_grey: #e8e8eb;
8 | $m_bright: #f4f4f5;
9 | $m_white: #ffffff;
10 |
11 | $small_screen: 576px;
12 | $medium_screen: 768px;
13 | $big_screen: 992px;
14 |
15 | @import "~bootstrap/scss/functions";
16 | @import "~bootstrap/scss/variables";
17 |
18 | $theme-colors: (
19 | "primary": $m_orange,
20 | "dark": $m_dark
21 | );
22 |
23 | $link-color: $m_orange;
24 | $link-hover-color: darken($link-color, 15%);
25 |
26 | @import "~bootstrap/scss/bootstrap";
27 |
28 | .matestack_page_content {
29 | overflow-x: hidden;
30 | }
31 |
32 | body {
33 | background-color: $m_white;
34 | }
35 |
36 | .hero {
37 | position: absolute;
38 | width: 100%;
39 | height: 200px;
40 | background-color: $m_light_grey;
41 | }
42 |
43 | @font-face {
44 | font-family: 'Geometrica';
45 | src: url('../../assets/fonts/geometrica/3AB51B_0_0.eot');
46 | src: url('../../assets/fonts/geometrica/3AB51B_0_0.eot?#iefix') format('embedded-opentype'),
47 | url('../../assets/fonts/geometrica/3AB51B_0_0.woff2') format('woff2'),
48 | url('../../assets/fonts/geometrica/3AB51B_0_0.woff') format('woff'),
49 | url('../../assets/fonts/geometrica/3AB51B_0_0.ttf') format('truetype'),
50 | url('../../assets/fonts/geometrica/3AB51B_0_0.svg#wf') format('svg');
51 | }
52 |
53 | @import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,wght@0,300;0,400;0,700;1,900&display=swap');
54 |
55 | html, body, p {
56 | font-family: 'Nunito Sans';
57 | }
58 |
59 | .matestack-page-root{
60 | margin-left: 260px;
61 |
62 | &.sidebar-closed{
63 | margin-left: 0px;
64 | }
65 | position: relative;
66 | @media (max-width: $medium_screen) {
67 | margin-left: 0px;
68 | }
69 | }
70 |
71 | h1, h2, h3, h4, h5 {
72 | font-family: 'Geometrica';
73 | color: $m_dark;
74 | }
75 |
76 | h1 {
77 | font-size: 64px;
78 | line-height: 85px;
79 | }
80 |
81 | h2 {
82 | font-size: 38px;
83 | line-height: 68px;
84 | }
85 |
86 | h3 {
87 | font-size: 18px;
88 | line-height: 34px;
89 | }
90 |
91 | h4 {
92 | font-size: 16px;
93 | }
94 |
95 | h5 {
96 | font-size: 12px;
97 | }
98 |
99 | p {
100 | font-size: 18px;
101 | color: $m_grey;
102 | }
103 |
104 | @media (max-width: $small_screen) {
105 | h2 {
106 | font-size: 30px;
107 | line-height: 58px;
108 | }
109 | }
110 |
111 |
112 |
113 | @import "./custom-components";
114 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | stages:
2 | - release
3 | - deploy-production
4 |
5 | before_script:
6 | - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
7 |
8 | variables:
9 | CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
10 |
11 | release:
12 | stage: release
13 | script:
14 | - chmod +x create_env.sh
15 | - "sh ./create_env.sh"
16 | - docker build --pull -t $CONTAINER_RELEASE_IMAGE ./ -f ./Dockerfile.release
17 | - docker push $CONTAINER_RELEASE_IMAGE
18 | only:
19 | - develop
20 | - master
21 | tags:
22 | - build #shared runner on shared machine
23 |
24 | deploy-production-de:
25 | stage: deploy-production
26 | only:
27 | - master
28 | script:
29 | - docker pull $CONTAINER_RELEASE_IMAGE
30 | - chmod +x dbauth.sh
31 | - "sh ./dbauth.sh"
32 | - docker-compose -f docker-compose.production.yml up -d postgres
33 | - docker-compose -f docker-compose.production.yml exec -d postgres sh /usr/bin/setpw.sh
34 | - sleep 10 #make sure postgres container is ready
35 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:create
36 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:migrate
37 | - docker-compose -f docker-compose.production.yml up -d rails
38 | tags:
39 | - production-do-de-1
40 |
41 | deploy-production-us:
42 | stage: deploy-production
43 | only:
44 | - master
45 | script:
46 | - docker pull $CONTAINER_RELEASE_IMAGE
47 | - chmod +x dbauth.sh
48 | - "sh ./dbauth.sh"
49 | - docker-compose -f docker-compose.production.yml up -d postgres
50 | - docker-compose -f docker-compose.production.yml exec -d postgres sh /usr/bin/setpw.sh
51 | - sleep 10 #make sure postgres container is ready
52 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:create
53 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:migrate
54 | - docker-compose -f docker-compose.production.yml up -d rails
55 | tags:
56 | - production-do-us-1
57 |
58 | deploy-production-singapore-1:
59 | stage: deploy-production
60 | only:
61 | - master
62 | script:
63 | - docker pull $CONTAINER_RELEASE_IMAGE
64 | - chmod +x dbauth.sh
65 | - "sh ./dbauth.sh"
66 | - docker-compose -f docker-compose.production.yml up -d postgres
67 | - docker-compose -f docker-compose.production.yml exec -d postgres sh /usr/bin/setpw.sh
68 | - sleep 10 #make sure postgres container is ready
69 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:create
70 | - docker-compose -f docker-compose.production.yml run --rm rails bundle exec rake db:migrate
71 | - docker-compose -f docker-compose.production.yml up -d rails
72 | tags:
73 | - production-do-singapore-1
74 |
--------------------------------------------------------------------------------
/app/matestack/components/header.scss:
--------------------------------------------------------------------------------
1 | header {
2 | background: white;
3 | align-items: center;
4 | .hide-below-xxl{
5 | display: none;
6 | @media (min-width: 1400px) {
7 | display: inline;
8 | }
9 | }
10 | .navbar {
11 | margin: 0px;
12 | border: 0px;
13 | padding-left: 1em !important;
14 | padding-right: 1em !important;
15 |
16 | // -webkit-box-shadow: 0 6px 6px -6px #999;
17 | // -moz-box-shadow: 0 6px 6px -6px #999;
18 | // box-shadow: 0 6px 6px -6px #999;
19 | box-shadow: 0 .5rem 1rem rgba(0,0,0,.15);
20 |
21 | .navbar-toggler {
22 | border: none;
23 | &:focus{
24 | outline: none;
25 | }
26 | }
27 | }
28 | .navbar-brand {
29 | margin-right: 0;
30 | }
31 | .navbar-brand img {
32 | max-width: 170px;
33 | height: auto;
34 | margin-left: 0px;
35 | margin-bottom: 4px;
36 | }
37 | .symbol {
38 | width: 44px;
39 | }
40 | .nav-item {
41 | margin-left: 17px;
42 | }
43 | .nav-link {
44 | font-family: "Geometrica";
45 | color: $m_dark;
46 | font-size: 9px;
47 | letter-spacing: 1.14px;
48 | line-height: 28px;
49 | text-align: center;
50 | border-bottom: 4px solid transparent;
51 | border-radius: 0px;
52 | }
53 | .nav-pills .nav-link.active {
54 | background-color: transparent;
55 | color: $m_dark;
56 | border-bottom: 4px solid $m_orange;
57 | border-radius: 0px;
58 | }
59 | .nav-pills .nav-link.intro {
60 | background-color: transparent;
61 | color: black;
62 | &:hover{
63 | color: black;
64 | }
65 |
66 | }
67 | .nav-pills .nav-link.highlight {
68 | background-color: $m_orange;
69 | color: white;
70 | // border-bottom: 4px solid $m_orange;
71 | border-radius: 4px;
72 | padding-bottom: 0px;
73 | padding-top: 5px;
74 | // margin-top: -8px;
75 | @media (min-width: 1200px) {
76 | margin-top: -8px!important;
77 | margin-bottom: 0px!important;
78 | }
79 | }
80 | .navbar-toggler {
81 | box-sizing: border-box;
82 | color: $m_dark;
83 | margin-bottom: 6px;
84 | .right-closed {
85 | display: block;
86 | width: 33px;
87 | }
88 | .right-open {
89 | display: none;
90 | width: 25px;
91 | margin: 0 4px;
92 | }
93 | .left-closed {
94 | width: 15px;
95 | margin: 0 6px;
96 | }
97 | }
98 | .expanded-toggler {
99 | .left-closed {
100 | transform: rotate(180deg);
101 | }
102 | .right-closed {
103 | display: none;
104 | }
105 | .right-open {
106 | display: block;
107 | }
108 | }
109 | .navbar-nav li a:hover {
110 | color: black;
111 | }
112 | }
113 |
114 | @media (max-width: 50em) {
115 | header .nav-item {
116 | text-align: center !important;
117 | margin-left: 0;
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | #
5 | # This file was generated by Bundler.
6 | #
7 | # The application 'bundle' is installed as part of a gem, and
8 | # this file is here to facilitate running it.
9 | #
10 |
11 | require "rubygems"
12 |
13 | m = Module.new do
14 | module_function
15 |
16 | def invoked_as_script?
17 | File.expand_path($0) == File.expand_path(__FILE__)
18 | end
19 |
20 | def env_var_version
21 | ENV["BUNDLER_VERSION"]
22 | end
23 |
24 | def cli_arg_version
25 | return unless invoked_as_script? # don't want to hijack other binstubs
26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27 | bundler_version = nil
28 | update_index = nil
29 | ARGV.each_with_index do |a, i|
30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31 | bundler_version = a
32 | end
33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34 | bundler_version = $1 || ">= 0.a"
35 | update_index = i
36 | end
37 | bundler_version
38 | end
39 |
40 | def gemfile
41 | gemfile = ENV["BUNDLE_GEMFILE"]
42 | return gemfile if gemfile && !gemfile.empty?
43 |
44 | File.expand_path("../../Gemfile", __FILE__)
45 | end
46 |
47 | def lockfile
48 | lockfile =
49 | case File.basename(gemfile)
50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51 | else "#{gemfile}.lock"
52 | end
53 | File.expand_path(lockfile)
54 | end
55 |
56 | def lockfile_version
57 | return unless File.file?(lockfile)
58 | lockfile_contents = File.read(lockfile)
59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60 | Regexp.last_match(1)
61 | end
62 |
63 | def bundler_version
64 | @bundler_version ||= begin
65 | env_var_version || cli_arg_version ||
66 | lockfile_version || "#{Gem::Requirement.default}.a"
67 | end
68 | end
69 |
70 | def load_bundler!
71 | ENV["BUNDLE_GEMFILE"] ||= gemfile
72 |
73 | # must dup string for RG < 1.8 compatibility
74 | activate_bundler(bundler_version.dup)
75 | end
76 |
77 | def activate_bundler(bundler_version)
78 | if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79 | bundler_version = "< 2"
80 | end
81 | gem_error = activation_error_handling do
82 | gem "bundler", bundler_version
83 | end
84 | return if gem_error.nil?
85 | require_error = activation_error_handling do
86 | require "bundler/version"
87 | end
88 | return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89 | warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90 | exit 42
91 | end
92 |
93 | def activation_error_handling
94 | yield
95 | nil
96 | rescue StandardError, LoadError => e
97 | e
98 | end
99 | end
100 |
101 | m.load_bundler!
102 |
103 | if m.invoked_as_script?
104 | load Gem.bin_path("bundler", "bundle")
105 | end
106 |
--------------------------------------------------------------------------------
/app/matestack/components/header.rb:
--------------------------------------------------------------------------------
1 | class Components::Header < Matestack::Ui::DynamicComponent
2 |
3 | def response
4 | header do
5 | nav id: 'custom-shared-navbar', class: 'navbar navbar-expand-xl fixed-top navbar-light bg-white my-0 pb-0' do
6 | button class: 'navbar-toggler', type: 'button', attributes: {"v-bind:class": "{ \"expanded-toggler\": sidebarOpen }", "@click": "sidebarToggle"} do
7 | img path: 'menu/arrow.svg', class: 'left-closed'
8 | end
9 | link class: 'navbar-brand my-0 p-0', path: "https://matestack.io" do
10 | img alt: 'matestack high quality software, simply delivered', path: 'logo/matestack_logo_orange.png', class: 'd-none d-sm-block'
11 | img alt: 'matestack high quality software, simply delivered', path: 'logo/matestack_logo_symbol.png', class: 'symbol d-block d-sm-none'
12 | end
13 | button class: 'navbar-toggler', type: 'button', attributes: {"v-bind:class": "{ \"expanded-toggler\": expanded }", "@click": "expanded = !expanded"} do
14 | img path: 'menu/burger.svg', class: 'right-closed'
15 | img path: 'menu/close.svg', class: 'right-open'
16 | end
17 | div id: 'navbarSupportedContent', class: 'collapse navbar-collapse', attributes: {"v-bind:class": "{ \"show\": expanded }"} do
18 | ul class: 'navbar-nav nav-pills ml-auto align-items-center' do
19 | li class: 'nav-item hide-below-xxl' do
20 | span class: "nav-link intro",
21 | text: 'matestack-ui-core | UI in pure Ruby:'.upcase
22 | end
23 | li class: 'nav-item' do
24 | link class: "nav-link #{active_class(:start)}",
25 | path: :core_start_path,
26 | params: { key: 'README.md' },
27 | text: 'Start'.upcase
28 | end
29 | li class: 'nav-item' do
30 | link class: "nav-link #{active_class(:ui_components)}",
31 | path: :core_ui_components_path,
32 | params: { key: 'README.md' },
33 | text: 'UI components'.upcase
34 | end
35 | li class: 'nav-item' do
36 | link class: "nav-link #{active_class(:reactive_components)}",
37 | path: :core_reactive_components_path,
38 | params: { key: 'README.md' },
39 | text: 'Reactive components'.upcase
40 | end
41 | li class: 'nav-item' do
42 | link class: "nav-link #{active_class(:reactive_apps)}",
43 | path: :core_reactive_apps_path,
44 | params: { key: 'README.md' },
45 | text: 'Reactive Apps'.upcase
46 | end
47 | li class: 'nav-item' do
48 | link class: "nav-link #{active_class(:api)}",
49 | path: :core_api_path,
50 | params: { key: 'README.md' },
51 | text: 'API'.upcase
52 | end
53 | li class: 'nav-item' do
54 | link class: "nav-link highlight px-2 my-4 #{active_class(:components)}",
55 | path: "https://matestack.io/addons",
56 | target: "_blank",
57 | text: 'Matestack UI Addon'.upcase
58 | end
59 |
60 | # TODO: Add button links for "sponsor"/"book us"
61 | end
62 | end
63 | end
64 | end
65 | end
66 |
67 | private
68 |
69 | def active_class(param)
70 | current_path = context[:request].fullpath
71 | case param
72 | when :start
73 | return 'active' if current_path.starts_with?('/docs/start')
74 | when :ui_components
75 | return 'active' if current_path.starts_with?('/docs/ui_components')
76 | when :reactive_components
77 | return 'active' if current_path.starts_with?('/docs/reactive_components')
78 | when :reactive_apps
79 | return 'active' if current_path.starts_with?('/docs/reactive_apps')
80 | when :api
81 | return 'active' if current_path.starts_with?('/docs/api')
82 | else
83 | return nil
84 | end
85 | end
86 |
87 | end
88 |
--------------------------------------------------------------------------------
/app/matestack/components/sidebar.rb:
--------------------------------------------------------------------------------
1 | class Components::Sidebar < Matestack::Ui::StaticComponent
2 |
3 | def generate_nav_data path, type="dir"
4 | @tree = ::Rails.cache.fetch("base_remote_#{path}", expires_in: 5.minutes) do
5 | JSON.parse(RestClient.get(@github_component_docs_path).body)
6 | end
7 | if @tree
8 | @tree.each do |item|
9 | if item["type"] == type
10 | @file_doc_links << item
11 | end
12 | end
13 | end
14 | @file_doc_links.sort_by! { |item| item['name'].scan(/\d+/).first.to_i }
15 | end
16 |
17 | def prepare
18 | @file_doc_links = []
19 | @tree = nil
20 |
21 | @branch = 'master'
22 | # TODO: line below references master branch, so links below need update down the row
23 | @github_base_api_url = "https://#{ENV['GITHUB_USERNAME']}:#{ENV['GITHUB_PERSONAL_ACCESS_TOKEN']}@api.github.com/repos/basemate/matestack-ui-core/contents"
24 | @current_page = @options[:currentPage]
25 | @current_path = @current_page.gsub('.md', '').gsub('.rb', '')
26 |
27 | # TODO: Refactor below to work fine with new doc/api/guides structure! (esp. add /docs/ prefix to @github_component_docs_path)
28 | case @current_path
29 | when core_start_path
30 | @github_component_docs_path = "#{@github_base_api_url}/docs/start?ref=#{@branch}"
31 | generate_nav_data(@current_path)
32 | when core_ui_components_path
33 | @github_component_docs_path = "#{@github_base_api_url}/docs/ui_components?ref=#{@branch}"
34 | generate_nav_data(@current_path)
35 | when core_reactive_components_path
36 | @github_component_docs_path = "#{@github_base_api_url}/docs/reactive_components?ref=#{@branch}"
37 | generate_nav_data(@current_path)
38 | when core_reactive_apps_path
39 | @github_component_docs_path = "#{@github_base_api_url}/docs/reactive_apps?ref=#{@branch}"
40 | generate_nav_data(@current_path)
41 | when core_api_path
42 | @github_component_docs_path = "#{@github_base_api_url}/docs/api/100-components?ref=#{@branch}"
43 | generate_nav_data(@current_path, "file")
44 | end
45 | end
46 |
47 | def response
48 | div id: 'custom-sidebar', class: 'container-fluid' do
49 | nav id: 'sidebar', class: 'bg-dark sidebar' do
50 | div class: 'sidebar-sticky menu' do
51 | ul id: 'listGroup', class: 'list-group list-group-flush' do
52 | case @current_path
53 | when core_start_path
54 | side_title 'start'
55 | @file_doc_links.each do |item|
56 | transition_link :core_start_path, { key: "#{item['name']}" }, item['name'].split("-").last.humanize.camelcase.gsub(".md", "") unless item['name'] == 'README.md'
57 | end
58 | when core_ui_components_path
59 | side_title 'UI components'
60 | @file_doc_links.each do |item|
61 | transition_link :core_ui_components_path, { key: "#{item['name']}" }, item['name'].split("-").last.humanize.camelcase.gsub(".md", "") unless item['name'] == 'README.md'
62 | end
63 | when core_reactive_components_path
64 | side_title 'Reactive components'
65 | @file_doc_links.each do |item|
66 | transition_link :core_reactive_components_path, { key: "#{item['name']}" }, item['name'].split("-").last.humanize.camelcase.gsub(".md", "") unless item['name'] == 'README.md'
67 | end
68 | when core_reactive_apps_path
69 | side_title 'Reactive apps'
70 | @file_doc_links.each do |item|
71 | transition_link :core_reactive_apps_path, { key: "#{item['name']}" }, item['name'].split("-").last.humanize.camelcase.gsub(".md", "") unless item['name'] == 'README.md'
72 | end
73 | when core_api_path
74 | side_title 'Components API'
75 | @file_doc_links.each do |item|
76 | transition_link :core_api_path, { key: item['name'], }, item['name'].gsub(".md", "") unless item['name'] == 'README.md'
77 | end
78 | end
79 | end
80 | end
81 | end
82 | end
83 | end
84 |
85 | private
86 |
87 | def side_title text
88 | link path: "https://github.com/matestack/matestack-ui-core", target: "_blank", class: "pt-4 text-decoration-none" do
89 | small class: 'list-group-item-heading text-white ml-2 pl-3 my-3 pt-4 text-monospace font-weight-light', text: "matestack-ui-core v1.3.2"
90 | end
91 | heading size: 5, class: 'list-group-item-heading text-white ml-2 pl-3 my-3 pt-4 pb-3', text: text.upcase
92 | end
93 |
94 | def transition_link path, params, text
95 | button class: "links-btn" do
96 | transition path: path, params: params, text: text.camelcase, class: "list-group-item list-group-item-action", delay: 300
97 | end
98 | end
99 |
100 | end
101 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both threaded web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
18 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
19 | # config.require_master_key = true
20 |
21 | # Disable serving static files from the `/public` folder by default since
22 | # Apache or NGINX already handles this.
23 | config.public_file_server.enabled = true
24 |
25 | # Compress CSS using a preprocessor.
26 | # config.assets.css_compressor = :sass
27 |
28 | # Do not fallback to assets pipeline if a precompiled asset is missed.
29 | config.assets.compile = false
30 |
31 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
32 | # config.action_controller.asset_host = 'http://assets.example.com'
33 |
34 | # Specifies the header that your server uses for sending files.
35 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
36 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
37 |
38 | # Store uploaded files on the local file system (see config/storage.yml for options).
39 | config.active_storage.service = :local
40 |
41 | # Mount Action Cable outside main process or domain.
42 | # config.action_cable.mount_path = nil
43 | # config.action_cable.url = 'wss://example.com/cable'
44 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
45 |
46 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
47 | # config.force_ssl = true
48 |
49 | # Use the lowest log level to ensure availability of diagnostic information
50 | # when problems arise.
51 | config.log_level = :debug
52 |
53 | # Prepend all log lines with the following tags.
54 | config.log_tags = [ :request_id ]
55 |
56 | # Use a different cache store in production.
57 | # config.cache_store = :mem_cache_store
58 |
59 | # Use a real queuing backend for Active Job (and separate queues per environment).
60 | # config.active_job.queue_adapter = :resque
61 | # config.active_job.queue_name_prefix = "matestack_docs_production"
62 |
63 | config.action_mailer.perform_caching = false
64 |
65 | # Ignore bad email addresses and do not raise email delivery errors.
66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
67 | # config.action_mailer.raise_delivery_errors = false
68 |
69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
70 | # the I18n.default_locale when a translation cannot be found).
71 | config.i18n.fallbacks = true
72 |
73 | # Send deprecation notices to registered listeners.
74 | config.active_support.deprecation = :notify
75 |
76 | # Use default logging formatter so that PID and timestamp are not suppressed.
77 | config.log_formatter = ::Logger::Formatter.new
78 |
79 | # Use a different logger for distributed setups.
80 | # require 'syslog/logger'
81 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
82 |
83 | if ENV["RAILS_LOG_TO_STDOUT"].present?
84 | logger = ActiveSupport::Logger.new(STDOUT)
85 | logger.formatter = config.log_formatter
86 | config.logger = ActiveSupport::TaggedLogging.new(logger)
87 | end
88 |
89 | # Do not dump schema after migrations.
90 | config.active_record.dump_schema_after_migration = false
91 |
92 | # Inserts middleware to perform automatic connection switching.
93 | # The `database_selector` hash is used to pass options to the DatabaseSelector
94 | # middleware. The `delay` is used to determine how long to wait after a write
95 | # to send a subsequent read to the primary.
96 | #
97 | # The `database_resolver` class is used by the middleware to determine which
98 | # database is appropriate to use based on the time delay.
99 | #
100 | # The `database_resolver_context` class is used by the middleware to set
101 | # timestamps for the last write to the primary. The resolver uses the context
102 | # class timestamps to determine how long to wait before reading from the
103 | # replica.
104 | #
105 | # By default Rails will store a last write timestamp in the session. The
106 | # DatabaseSelector middleware is designed as such you can define your own
107 | # strategy for connection switching and pass that into the middleware through
108 | # these configuration options.
109 | # config.active_record.database_selector = { delay: 2.seconds }
110 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
111 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
112 | end
113 |
--------------------------------------------------------------------------------
/app/matestack/components/toc/toc.js:
--------------------------------------------------------------------------------
1 | import jQuery from "jquery";
2 |
3 | // https://github.com/ghiculescu/jekyll-table-of-contents
4 | (function($){
5 | $.fn.toc = function(options) {
6 | var defaults = {
7 | noBackToTopLinks: false,
8 | title: 'Jump to...',
9 | minimumHeaders: 1,
10 | headers: 'h1, h2, h3, h4, h5, h6',
11 | listType: 'ol', // values: [ol|ul]
12 | showEffect: 'show', // values: [show|slideDown|fadeIn|none]
13 | showSpeed: 'slow', // set to 0 to deactivate effect
14 | classes: { list: '',
15 | item: ''
16 | }
17 | },
18 | settings = $.extend(defaults, options);
19 |
20 | function fixedEncodeURIComponent (str) {
21 | return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
22 | return '%' + c.charCodeAt(0).toString(16);
23 | });
24 | }
25 |
26 | function createLink (header) {
27 | var innerText = (header.textContent === undefined) ? header.innerText : header.textContent;
28 | return "" + innerText + "";
29 | }
30 |
31 | var headers = $(settings.headers).filter(function() {
32 | // get all headers with an ID
33 | var previousSiblingName = $(this).prev().attr( "name" );
34 | if (!this.id && previousSiblingName) {
35 | this.id = $(this).attr( "id", previousSiblingName.replace(/\./g, "-") );
36 | }
37 | return this.id;
38 | }), output = $(this);
39 | if (!headers.length || headers.length < settings.minimumHeaders || !output.length) {
40 | $(this).hide();
41 | return;
42 | }
43 |
44 | if (0 === settings.showSpeed) {
45 | settings.showEffect = 'none';
46 | }
47 |
48 | var render = {
49 | show: function() { output.hide().html(html).show(settings.showSpeed); },
50 | slideDown: function() { output.hide().html(html).slideDown(settings.showSpeed); },
51 | fadeIn: function() { output.hide().html(html).fadeIn(settings.showSpeed); },
52 | none: function() { output.html(html); }
53 | };
54 |
55 | var get_level = function(ele) { return parseInt(ele.nodeName.replace("H", ""), 10); };
56 | var highest_level = headers.map(function(_, ele) { return get_level(ele); }).get().sort()[0];
57 | var return_to_top = '';
58 |
59 | var level = get_level(headers[0]),
60 | this_level,
61 | html = settings.title + " <" +settings.listType + " class=\"" + settings.classes.list +"\">";
62 | headers.on('click', function() {
63 | if (!settings.noBackToTopLinks) {
64 | window.location.hash = this.id;
65 | }
66 | })
67 | .addClass('clickable-header')
68 | .each(function(_, header) {
69 | this_level = get_level(header);
70 | if (!settings.noBackToTopLinks && this_level === highest_level) {
71 | $(header).addClass('top-level-header').after(return_to_top);
72 | }
73 | if (this_level === level) // same level as before; same indenting
74 | html += "
" + createLink(header);
75 | else if (this_level <= level){ // higher level than before; end parent ol
76 | for(var i = this_level; i < level; i++) {
77 | html += "
"+settings.listType+">"
78 | }
79 | html += "
" + createLink(header);
80 | }
81 | else if (this_level > level) { // lower level than before; expand the previous to contain a ol
82 | for(i = this_level; i > level; i--) {
83 | html += "<" + settings.listType + " class=\"" + settings.classes.list +"\">" +
84 | "