diff --git a/.gitignore b/.gitignore
index d31efa22..3ce6fe7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,13 @@ build-iPhoneSimulator/
/gemfiles/vendor/bundle
/lib/bundler/man/
+# Ignore webpacker files
+/spec/rails_app/node_modules
+/spec/rails_app/yarn.lock
+/spec/rails_app/yarn-error.log
+/spec/rails_app/public/packs
+/spec/rails_app/public/packs-test
+
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
diff --git a/Gemfile b/Gemfile
index 72c1cfad..0c60f2d2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -25,5 +25,6 @@ group :test do
gem 'coveralls', require: false
end
+gem 'webpacker', groups: [:production, :development]
gem 'rack-cors', groups: [:production, :development]
gem 'dotenv-rails', groups: [:development, :test]
diff --git a/README.md b/README.md
index c42f0fd5..b87632fa 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,10 @@ The deployed demo application is included in this gem's source code as a test ap
REST API reference as OpenAPI Specification is published in SwaggerHub here:
* **https://app.swaggerhub.com/apis/simukappu/activity-notification/**
+You can see sample single page application using [Vue.js](https://vuejs.org) as a part of example Rails application here:
+* **https://activity-notification-example.herokuapp.com/spa/**
+This sample application works with *activity_notification* REST API backend.
+
## Table of Contents
diff --git a/bin/deploy_on_heroku.sh b/bin/deploy_on_heroku.sh
index 234e0bfd..c4651f33 100755
--- a/bin/deploy_on_heroku.sh
+++ b/bin/deploy_on_heroku.sh
@@ -6,9 +6,11 @@ CURRENT_BRANCH=`git symbolic-ref --short HEAD`
git checkout -b $HEROKU_DEPLOYMENT_BRANCH
bundle install
sed -i "" -e "s/^\/Gemfile.lock/# \/Gemfile.lock/g" .gitignore
+cp spec/rails_app/bin/webpack* bin/
git add .gitignore
git add Gemfile.lock
-git commit -m "Add Gemfile.lock"
+git add bin/webpack*
+git commit -m "Add Gemfile.lock and webpack"
git push heroku ${HEROKU_DEPLOYMENT_BRANCH}:master --force
git checkout $CURRENT_BRANCH
git branch -D $HEROKU_DEPLOYMENT_BRANCH
diff --git a/docs/Functions.md b/docs/Functions.md
index 6038b23b..9b821e5c 100644
--- a/docs/Functions.md
+++ b/docs/Functions.md
@@ -385,6 +385,8 @@ Then, *activity_notification* uses *[ActivityNotification::SubscriptionsApiContr
When you want to use REST API backend integrated with Devise authentication, see [REST API backend with Devise Token Auth](#rest-api-backend-with-devise-token-auth).
+You can see [sample single page application](/spec/rails_app/app/javascript/) using [Vue.js](https://vuejs.org) as a part of example Rails application. This sample application works with *activity_notification* REST API backend.
+
#### API reference as OpenAPI Specification
*activity_notification* provides API reference as [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification).
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..3d44be60
--- /dev/null
+++ b/package.json
@@ -0,0 +1,8 @@
+{
+ "engines": {
+ "yarn": "1.x"
+ },
+ "scripts": {
+ "postinstall": "cd ./spec/rails_app && yarn && yarn install --check-files"
+ }
+}
diff --git a/spec/rails_app/app/controllers/admins_controller.rb b/spec/rails_app/app/controllers/admins_controller.rb
new file mode 100644
index 00000000..463775b8
--- /dev/null
+++ b/spec/rails_app/app/controllers/admins_controller.rb
@@ -0,0 +1,21 @@
+class AdminsController < ApplicationController
+ before_action :set_admin, only: [:show]
+
+ # GET /users
+ def index
+ render json: {
+ users: Admin.all.as_json(include: :user)
+ }
+ end
+
+ # GET /users/:id
+ def show
+ render json: @admin.as_json(include: :user)
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_admin
+ @admin = Admin.find(params[:id])
+ end
+end
diff --git a/spec/rails_app/app/controllers/spa_controller.rb b/spec/rails_app/app/controllers/spa_controller.rb
new file mode 100644
index 00000000..baab0d0b
--- /dev/null
+++ b/spec/rails_app/app/controllers/spa_controller.rb
@@ -0,0 +1,7 @@
+class SpaController < ApplicationController
+
+ # GET /spa
+ def index
+ end
+
+end
\ No newline at end of file
diff --git a/spec/rails_app/app/controllers/users_controller.rb b/spec/rails_app/app/controllers/users_controller.rb
new file mode 100644
index 00000000..5d1801b3
--- /dev/null
+++ b/spec/rails_app/app/controllers/users_controller.rb
@@ -0,0 +1,21 @@
+class UsersController < ApplicationController
+ before_action :set_user, only: [:show]
+
+ # GET /users
+ def index
+ render json: {
+ users: User.all
+ }
+ end
+
+ # GET /users/:id
+ def show
+ render json: @user
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_user
+ @user = User.find(params[:id])
+ end
+end
diff --git a/spec/rails_app/app/javascript/App.vue b/spec/rails_app/app/javascript/App.vue
new file mode 100644
index 00000000..65dc0551
--- /dev/null
+++ b/spec/rails_app/app/javascript/App.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue b/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue
new file mode 100644
index 00000000..06e1a9b3
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/Top.vue b/spec/rails_app/app/javascript/components/Top.vue
new file mode 100644
index 00000000..0e48f3bf
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/Top.vue
@@ -0,0 +1,101 @@
+
+
+
+ Authentecated User
+
+
+
+
+
+ {{ currentUser.name }} · {{ currentUser.email }} · Logout
+
+
+ Not logged in · Login
+
+
Notifications /
+
Subscriptions
+
+
+
+
+
+
+ Listing Users
+
+
+
+
+ {{ user.name }} · {{ user.email }}
+ Notifications /
+ Subscriptions
+
+
+
+
+
+
+ Authentecated User as Admin
+
+
+
+
+
+ {{ currentUser.name }} · {{ currentUser.email }} · (admin)(not admin)
+
+
+ Not logged in · Login
+
+
Notifications /
+
Subscriptions
+
+
+
+
+
+
+ Listing Admins
+
+
+
+
+
+ {{ admin.user.name }} · {{ admin.user.email }}
+ Notifications /
+ Subscriptions
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/notifications/Index.vue b/spec/rails_app/app/javascript/components/notifications/Index.vue
new file mode 100644
index 00000000..2ceafb0b
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/notifications/Index.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/notifications/Notification.vue b/spec/rails_app/app/javascript/components/notifications/Notification.vue
new file mode 100644
index 00000000..55b21ed9
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/notifications/Notification.vue
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue b/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue
new file mode 100644
index 00000000..9116ef8f
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+ {{ notification.notifier.name }} updated his or her article "{{ notification.notifiable.title }}".
+
+ {{ new Date(notification.created_at) | moment('timezone', 'UTC', "MMM DD HH:mm") }}
+
+
+
+ {{ notification.notifier.printable_notifier_name }}
+ Someone
+
+ and {{ notification.group_member_notifier_count }} other
+ {{ notification.notifier.printable_type.toLowerCase() | pluralize(notification.group_member_notifier_count) }}
+ people
+
+ notified you of
+
+
+ {{ notification.group_notification_count }} {{notification.notifiable_type.toLowerCase() | pluralize(notification.group_notification_count) }} including
+
+ {{ notification.printable_notifiable_name }}
+ in {{ notification.group.printable_group_name }}
+
+
+
+ {{ notification.group_notification_count }} {{notification.notifiable_type.toLowerCase() | pluralize(notification.group_notification_count) }}
+
+
+ a {{ notification.notifiable_typetoLowerCase() | pluralize(0) }}
+
+ in {{ notification.group.printable_group_name }}
+ but the notifiable is not found. It may have been deleted.
+
+
+ {{ new Date(notification.created_at) | moment('timezone', 'UTC', "MMM DD hh:mm") }}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/subscriptions/Index.vue b/spec/rails_app/app/javascript/components/subscriptions/Index.vue
new file mode 100644
index 00000000..f33991cb
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/subscriptions/Index.vue
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+ No subscriptions are available.
+
+
+
+
+
+
+
+
+
+
+
+ No notification keys are available.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue b/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue
new file mode 100644
index 00000000..ac72b957
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue b/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue
new file mode 100644
index 00000000..6e6199f6
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue b/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue
new file mode 100644
index 00000000..8f9c3631
--- /dev/null
+++ b/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spec/rails_app/app/javascript/packs/application.js b/spec/rails_app/app/javascript/packs/application.js
new file mode 100644
index 00000000..7c3021d7
--- /dev/null
+++ b/spec/rails_app/app/javascript/packs/application.js
@@ -0,0 +1,18 @@
+/* eslint no-console:0 */
+// This file is automatically compiled by Webpack, along with any other files
+// present in this directory. You're encouraged to place your actual application logic in
+// a relevant structure within app/javascript and only use these pack files to reference
+// that code so it'll be compiled.
+//
+// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
+// layout file, like app/views/layouts/application.html.erb
+
+
+// Uncomment to copy all static images under ../images to the output folder and reference
+// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
+// or the `imagePath` JavaScript helper below.
+//
+// const images = require.context('../images', true)
+// const imagePath = (name) => images(name, true)
+
+console.log('Hello World from Webpacker')
diff --git a/spec/rails_app/app/javascript/packs/spa.js b/spec/rails_app/app/javascript/packs/spa.js
new file mode 100644
index 00000000..b664310c
--- /dev/null
+++ b/spec/rails_app/app/javascript/packs/spa.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import axios from 'axios'
+import App from '../App.vue'
+
+axios.defaults.baseURL = "/api/v2"
+
+document.addEventListener('DOMContentLoaded', () => {
+ const app = new Vue({
+ render: h => h(App)
+ }).$mount('#spa')
+})
diff --git a/spec/rails_app/app/javascript/store/auth.js b/spec/rails_app/app/javascript/store/auth.js
new file mode 100644
index 00000000..9fcfaafe
--- /dev/null
+++ b/spec/rails_app/app/javascript/store/auth.js
@@ -0,0 +1,37 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import createPersistedState from "vuex-persistedstate"
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+ state: {
+ signedInStatus: false,
+ currentUser: null,
+ authHeaders: {}
+ },
+ mutations: {
+ signIn(state, { user, authHeaders }) {
+ state.currentUser = user;
+ state.authHeaders = authHeaders;
+ state.signedInStatus = true;
+ },
+ signOut(state) {
+ state.signedInStatus = false;
+ state.currentUser = null;
+ state.authHeaders = {};
+ }
+ },
+ getters: {
+ userSignedIn(state) {
+ return state.signedInStatus;
+ },
+ currentUser(state) {
+ return state.currentUser;
+ },
+ authHeaders(state) {
+ return state.authHeaders;
+ }
+ },
+ plugins: [createPersistedState({storage: window.sessionStorage})]
+});
\ No newline at end of file
diff --git a/spec/rails_app/app/models/user.rb b/spec/rails_app/app/models/user.rb
index 6638e104..521152c6 100644
--- a/spec/rails_app/app/models/user.rb
+++ b/spec/rails_app/app/models/user.rb
@@ -19,6 +19,12 @@ module UserModel
def admin?
admin.present?
end
+
+ def as_json(options = {})
+ options[:include] = (options[:include] || {}).merge(admin: { methods: [:printable_target_name] })
+ options[:methods] = (options[:methods] || []).push(:printable_target_name)
+ super(options)
+ end
end
unless ENV['AN_TEST_DB'] == 'mongodb'
diff --git a/spec/rails_app/app/views/spa/index.html.erb b/spec/rails_app/app/views/spa/index.html.erb
new file mode 100644
index 00000000..38f1af7b
--- /dev/null
+++ b/spec/rails_app/app/views/spa/index.html.erb
@@ -0,0 +1,2 @@
+
+<%= javascript_pack_tag 'spa' %>
\ No newline at end of file
diff --git a/spec/rails_app/babel.config.js b/spec/rails_app/babel.config.js
new file mode 100644
index 00000000..12f98da5
--- /dev/null
+++ b/spec/rails_app/babel.config.js
@@ -0,0 +1,72 @@
+module.exports = function(api) {
+ var validEnv = ['development', 'test', 'production']
+ var currentEnv = api.env()
+ var isDevelopmentEnv = api.env('development')
+ var isProductionEnv = api.env('production')
+ var isTestEnv = api.env('test')
+
+ if (!validEnv.includes(currentEnv)) {
+ throw new Error(
+ 'Please specify a valid `NODE_ENV` or ' +
+ '`BABEL_ENV` environment variables. Valid values are "development", ' +
+ '"test", and "production". Instead, received: ' +
+ JSON.stringify(currentEnv) +
+ '.'
+ )
+ }
+
+ return {
+ presets: [
+ isTestEnv && [
+ '@babel/preset-env',
+ {
+ targets: {
+ node: 'current'
+ }
+ }
+ ],
+ (isProductionEnv || isDevelopmentEnv) && [
+ '@babel/preset-env',
+ {
+ forceAllTransforms: true,
+ useBuiltIns: 'entry',
+ corejs: 3,
+ modules: false,
+ exclude: ['transform-typeof-symbol']
+ }
+ ]
+ ].filter(Boolean),
+ plugins: [
+ 'babel-plugin-macros',
+ '@babel/plugin-syntax-dynamic-import',
+ isTestEnv && 'babel-plugin-dynamic-import-node',
+ '@babel/plugin-transform-destructuring',
+ [
+ '@babel/plugin-proposal-class-properties',
+ {
+ loose: true
+ }
+ ],
+ [
+ '@babel/plugin-proposal-object-rest-spread',
+ {
+ useBuiltIns: true
+ }
+ ],
+ [
+ '@babel/plugin-transform-runtime',
+ {
+ helpers: false,
+ regenerator: true,
+ corejs: false
+ }
+ ],
+ [
+ '@babel/plugin-transform-regenerator',
+ {
+ async: false
+ }
+ ]
+ ].filter(Boolean)
+ }
+}
diff --git a/spec/rails_app/bin/webpack b/spec/rails_app/bin/webpack
new file mode 100755
index 00000000..1031168d
--- /dev/null
+++ b/spec/rails_app/bin/webpack
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+
+ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
+ENV["NODE_ENV"] ||= "development"
+
+require "pathname"
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
+ Pathname.new(__FILE__).realpath)
+
+require "bundler/setup"
+
+require "webpacker"
+require "webpacker/webpack_runner"
+
+APP_ROOT = File.expand_path("..", __dir__)
+Dir.chdir(APP_ROOT) do
+ Webpacker::WebpackRunner.run(ARGV)
+end
diff --git a/spec/rails_app/bin/webpack-dev-server b/spec/rails_app/bin/webpack-dev-server
new file mode 100755
index 00000000..dd966273
--- /dev/null
+++ b/spec/rails_app/bin/webpack-dev-server
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+
+ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
+ENV["NODE_ENV"] ||= "development"
+
+require "pathname"
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
+ Pathname.new(__FILE__).realpath)
+
+require "bundler/setup"
+
+require "webpacker"
+require "webpacker/dev_server_runner"
+
+APP_ROOT = File.expand_path("..", __dir__)
+Dir.chdir(APP_ROOT) do
+ Webpacker::DevServerRunner.run(ARGV)
+end
diff --git a/spec/rails_app/config/initializers/devise_token_auth.rb b/spec/rails_app/config/initializers/devise_token_auth.rb
index 72b13c1b..caff2272 100644
--- a/spec/rails_app/config/initializers/devise_token_auth.rb
+++ b/spec/rails_app/config/initializers/devise_token_auth.rb
@@ -5,11 +5,11 @@
# client is responsible for keeping track of the changing tokens. Change
# this to false to prevent the Authorization header from changing after
# each request.
- # config.change_headers_on_each_request = true
+ config.change_headers_on_each_request = false
# By default, users will need to re-authenticate after 2 weeks. This setting
# determines how long tokens will remain valid after they are issued.
- # config.token_lifespan = 2.weeks
+ config.token_lifespan = 1.hour
# Limiting the token_cost to just 4 in testing will increase the performance of
# your test suite dramatically. The possible cost value is within range from 4
diff --git a/spec/rails_app/config/routes.rb b/spec/rails_app/config/routes.rb
index 6fa3ec19..dc301891 100644
--- a/spec/rails_app/config/routes.rb
+++ b/spec/rails_app/config/routes.rb
@@ -1,36 +1,46 @@
Rails.application.routes.draw do
+ # Routes for example Rails application
root to: 'articles#index'
devise_for :users
resources :articles, except: [:destroy]
resources :comments, only: [:create, :destroy]
+ # activity_notification routes for users
notify_to :users, with_subscription: true
notify_to :users, with_devise: :users, devise_default_routes: true, with_subscription: true
+ # activity_notification routes for admins
+ notify_to :admins, with_devise: :users, with_subscription: true
+ scope :admins, as: :admins do
+ notify_to :admins, with_devise: :users, devise_default_routes: true, with_subscription: true, routing_scope: :admins
+ end
+
+ # Routes for single page application working with activity_notification REST API backend
+ resources :spa, only: [:index]
namespace :api do
scope :"v#{ActivityNotification::GEM_VERSION::MAJOR}" do
mount_devise_token_auth_for 'User', at: 'auth'
end
end
+
+ # Routes of activity_notification REST API backend for users
scope :api do
scope :"v#{ActivityNotification::GEM_VERSION::MAJOR}" do
notify_to :users, api_mode: true, with_subscription: true
notify_to :users, api_mode: true, with_devise: :users, devise_default_routes: true, with_subscription: true
resources :apidocs, only: [:index], controller: 'activity_notification/apidocs'
+ resources :users, only: [:index, :show]
end
end
- notify_to :admins, with_devise: :users, with_subscription: true
- scope :admins, as: :admins do
- notify_to :admins, with_devise: :users, devise_default_routes: true, with_subscription: true, routing_scope: :admins
- end
-
+ # Routes of activity_notification REST API backend for admins
scope :api do
scope :"v#{ActivityNotification::GEM_VERSION::MAJOR}" do
notify_to :admins, api_mode: true, with_devise: :users, with_subscription: true
scope :admins, as: :admins do
notify_to :admins, api_mode: true, with_devise: :users, devise_default_routes: true, with_subscription: true
end
+ resources :admins, only: [:index, :show]
end
end
end
diff --git a/spec/rails_app/config/webpack/development.js b/spec/rails_app/config/webpack/development.js
new file mode 100644
index 00000000..c5edff94
--- /dev/null
+++ b/spec/rails_app/config/webpack/development.js
@@ -0,0 +1,5 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'development'
+
+const environment = require('./environment')
+
+module.exports = environment.toWebpackConfig()
diff --git a/spec/rails_app/config/webpack/environment.js b/spec/rails_app/config/webpack/environment.js
new file mode 100644
index 00000000..6ef014b0
--- /dev/null
+++ b/spec/rails_app/config/webpack/environment.js
@@ -0,0 +1,7 @@
+const { environment } = require('@rails/webpacker')
+const { VueLoaderPlugin } = require('vue-loader')
+const vue = require('./loaders/vue')
+
+environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
+environment.loaders.prepend('vue', vue)
+module.exports = environment
diff --git a/spec/rails_app/config/webpack/loaders/vue.js b/spec/rails_app/config/webpack/loaders/vue.js
new file mode 100644
index 00000000..509c742b
--- /dev/null
+++ b/spec/rails_app/config/webpack/loaders/vue.js
@@ -0,0 +1,6 @@
+module.exports = {
+ test: /\.vue(\.erb)?$/,
+ use: [{
+ loader: 'vue-loader'
+ }]
+}
diff --git a/spec/rails_app/config/webpack/production.js b/spec/rails_app/config/webpack/production.js
new file mode 100644
index 00000000..be0f53aa
--- /dev/null
+++ b/spec/rails_app/config/webpack/production.js
@@ -0,0 +1,5 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'production'
+
+const environment = require('./environment')
+
+module.exports = environment.toWebpackConfig()
diff --git a/spec/rails_app/config/webpack/test.js b/spec/rails_app/config/webpack/test.js
new file mode 100644
index 00000000..c5edff94
--- /dev/null
+++ b/spec/rails_app/config/webpack/test.js
@@ -0,0 +1,5 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'development'
+
+const environment = require('./environment')
+
+module.exports = environment.toWebpackConfig()
diff --git a/spec/rails_app/config/webpacker.yml b/spec/rails_app/config/webpacker.yml
new file mode 100644
index 00000000..79217f35
--- /dev/null
+++ b/spec/rails_app/config/webpacker.yml
@@ -0,0 +1,97 @@
+# Note: You must restart bin/webpack-dev-server for changes to take effect
+
+default: &default
+ source_path: app/javascript
+ source_entry_path: packs
+ public_root_path: public
+ public_output_path: packs
+ cache_path: tmp/cache/webpacker
+ check_yarn_integrity: false
+ webpack_compile_output: true
+
+ # Additional paths webpack should lookup modules
+ # ['app/assets', 'engine/foo/app/assets']
+ resolved_paths: []
+
+ # Reload manifest.json on all requests so we reload latest compiled packs
+ cache_manifest: false
+
+ # Extract and emit a css file
+ extract_css: false
+
+ static_assets_extensions:
+ - .jpg
+ - .jpeg
+ - .png
+ - .gif
+ - .tiff
+ - .ico
+ - .svg
+ - .eot
+ - .otf
+ - .ttf
+ - .woff
+ - .woff2
+
+ extensions:
+ - .vue
+ - .mjs
+ - .js
+ - .sass
+ - .scss
+ - .css
+ - .module.sass
+ - .module.scss
+ - .module.css
+ - .png
+ - .svg
+ - .gif
+ - .jpeg
+ - .jpg
+
+development:
+ <<: *default
+ compile: true
+
+ # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
+ check_yarn_integrity: true
+
+ # Reference: https://webpack.js.org/configuration/dev-server/
+ dev_server:
+ https: false
+ host: localhost
+ port: 3035
+ public: localhost:3035
+ hmr: false
+ # Inline should be set to true if using HMR
+ inline: true
+ overlay: true
+ compress: true
+ disable_host_check: true
+ use_local_ip: false
+ quiet: false
+ pretty: false
+ headers:
+ 'Access-Control-Allow-Origin': '*'
+ watch_options:
+ ignored: '**/node_modules/**'
+
+
+test:
+ <<: *default
+ compile: true
+
+ # Compile test packs to a separate directory
+ public_output_path: packs-test
+
+production:
+ <<: *default
+
+ # Production depends on precompilation of packs prior to booting for performance.
+ compile: false
+
+ # Extract and emit a css file
+ extract_css: false
+
+ # Cache manifest.json for performance
+ cache_manifest: true
diff --git a/spec/rails_app/package.json b/spec/rails_app/package.json
new file mode 100644
index 00000000..8f19c223
--- /dev/null
+++ b/spec/rails_app/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "activity_notification",
+ "description": "Sample single page application for activity_notification using Vue.js",
+ "dependencies": {
+ "@rails/webpacker": "^4.2.0",
+ "axios": "^0.19.0",
+ "vue": "^2.6.10",
+ "vuex": "^3.1.2",
+ "vuex-persistedstate": "^2.7.0",
+ "vue-loader": "^15.7.2",
+ "vue-router": "^3.1.3",
+ "vue-template-compiler": "^2.6.10",
+ "vue-moment": "^4.1.0",
+ "vue-moment-tz": "^2.1.1",
+ "vue-pluralize": "^0.0.2"
+ },
+ "devDependencies": {
+ "webpack-dev-server": "^3.9.0"
+ },
+ "license": "MIT"
+}
diff --git a/spec/rails_app/postcss.config.js b/spec/rails_app/postcss.config.js
new file mode 100644
index 00000000..aa5998a8
--- /dev/null
+++ b/spec/rails_app/postcss.config.js
@@ -0,0 +1,12 @@
+module.exports = {
+ plugins: [
+ require('postcss-import'),
+ require('postcss-flexbugs-fixes'),
+ require('postcss-preset-env')({
+ autoprefixer: {
+ flexbox: 'no-2009'
+ },
+ stage: 3
+ })
+ ]
+}