serviceworker-rails gem not intergrating with solidus eCommerce gem - ruby-on-rails

I am using the serviceworker-rails gem to make my eCommerce application a progressive web app. Here is a gem file snippet from the project;
# progressive web application gem
gem 'serviceworker-rails'
# eCommerce gems
gem 'solidus'
gem 'solidus_auth_devise'
#base gems
gem 'rails', '~> 5.2.0'
ruby '2.5.1'
the serviceworker-rails gem in turn generates the manifest files needed to make the app a progressive web application;
app/assets/javascripts/serviceworker.js.erb
var CACHE_VERSION = 'v1';
var CACHE_NAME = CACHE_VERSION + ':sw-cache-';
function onInstall(event) {
console.log('[Serviceworker]', "Installing!", event);
event.waitUntil(
caches.open(CACHE_NAME).then(function prefill(cache) {
return cache.addAll([
// make sure serviceworker.js is not required by application.js
// if you want to reference application.js from here
'<%#= asset_path "application.js" %>',
'<%= asset_path "application.css" %>',
'/offline.html',
]);
})
);
}
function onActivate(event) {
console.log('[Serviceworker]', "Activating!", event);
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(cacheName) {
// Return true if you want to remove this cache,
// but remember that caches are shared across
// the whole origin
return cacheName.indexOf(CACHE_VERSION) !== 0;
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
}
// Borrowed from https://github.com/TalAter/UpUp
function onFetch(event) {
event.respondWith(
// try to return untouched request from network first
fetch(event.request).catch(function() {
// if it fails, try to return request from the cache
return caches.match(event.request).then(function(response) {
if (response) {
return response;
}
// if not found in cache, return default offline content for navigate requests
if (event.request.mode === 'navigate' ||
(event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
console.log('[Serviceworker]', "Fetching offline content", event);
return caches.match('/offline.html');
}
})
})
);
}
self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);
app/assets/javascripts/serviceworker-companion.js
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js', { scope: './' })
.then(function(reg) {
console.log('[Companion]', 'Service worker registered!');
});
}
The application does not raise up any errors; just that I happen to notice that the service worker is not being registered. Here is the manifest in use;
app/assets/javascripts/manifest.json.erb
{
"name": "My Progressive Rails App",
"short_name": "Progressive",
"start_url": "/"
}
...and finally;
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Istore</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<link rel="manifest" href="/manifest.json" />
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
<%= yield %>
</body>
</html>
To be fair; I have used this set up before and it worked good. Something breaks when I use it with solidus_gem. So far; my efforts to debug the issue has only zeroed me in on a set of probabilities. The strongest being; lack of a root directive.
(the gem also doesn't work for the default rails starter page)
But upon setting a custom root page; the gem works. So I did some monkey patching and added the solidus' root page to my project then appended the application routes to include the solidus home page.
config/routes.rb
Rails.application.routes.draw do
root to: 'spree/home#index'
mount Spree::Core::Engine, at: '/'
end
This has proven unsuccessful. I am using lighthouse to audit the application and the error signifies that the serviceworker is not being registered.
What am I missing? Is something out of scope?

I finally got it to work :) . The gem supplying the application layout is solidus but the problem is that the manifest is in the local application within which solidus is a gem.
To make it visible to the gem; I removed the tags from
app/views/layouts/application.html.erb
and then put them in the gems layout file. You have to download it locally to make changes. The layout file as of writing this is at
app/views/spree/layouts/
but the head section contains a render of a _head partial at
app/views/spree/shared/_head.html.erb
from where it is more efficient to place these tags inside to resolve the issue.
<%= javascript_include_tag "application" %>
<link rel="manifest" href="/manifest.json" />
<meta name="apple-mobile-web-app-capable" content="yes">

Related

Excel Add In - Javascript only working after reload

I am developing an Excel Add-In using the Office-JS Library.
When some pages are loaded, the JS is not loaded properly.
The Javascript only works after reloading the page.
I disabled turbolink as suggested in another question.
But my problem still appears.
My office_connect.js contains the following:
//= require jquery3
//= require jquery_ujs
//= require_self
//= require select2-full
//= require select2_locale_de
And the head of my layout file:
<%= yield :head_top %>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<%= stylesheet_link_tag "office_connect"%>
<%= javascript_include_tag "office_connect_app"%>
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
<%= javascript_include_tag "oc_function"%>
<%= javascript_include_tag "office_excel"%>
<title><%=t('layouts.head.text_immodatacockpit')%></title>
<%= csrf_meta_tag %>
<%= yield :head %>
The oc_function file starts Office JS:
// The initialize function must be run each time a new page is loaded.
(function () {
Office.initialize = function (reason) {
// If you need to initialize something you can do so here.
};
})();
A shortened version of my excel.js:
(function () {
"use strict";
var cellToHighlight;
var messageBanner;
var config;
var sheetData;
let housing_output_template_new;
let housing_output_template_edit;
// The initialize function must be run each time a new page is loaded.
Office.initialize = function (reason) {
$(document).ready(function () {
$(".spinner").hide();
// If not using Excel 2016, use fallback logic.
if (!Office.context.requirements.isSetSupported('ExcelApi', '1.1')) {
$('#subtitle').text("Opps!");
$("#template-description").text("Sorry, this sample requires Word 2016 or later. The button will not open a dialog.");
$('#button-text').text("Button");
$('#button-desc').text("Button that opens dialog only on Word 2016 or later.");
return;
}
$("#select1").select2({placeholder: 'Please choose' , language:'<%= I18n.locale %>',dropdownAutoWidth:true});
$(".select4").select2({placeholder: 'Please choose' , language:'<%= I18n.locale %>',dropdownAutoWidth:true});
});
}
})();
I think it has something to do with the order I load the JS libraries.
Could you point me in the direction of what I am missing?
It looks like you are assigning Office.initialize in two places. If these calls are on two different pages, then that's OK. But you shouldn't be doing this twice on the same page.

Ckeditor not displayed after installation

After install CKedit dont work. I used the guides - https://github.com/galetahub/ckeditor
I've tried everything but it does not work
config/initializers/assets.rb
`Rails.application.config.assets.precompile += %w(ckeditor/config.js)`
config/initializers/assets.rb
//= require ckeditor/init
routes.rb
mount Ckeditor::Engine => '/ckeditor'
ActiveRecord + carrierwave
gem 'carrierwave'
gem 'mini_magick'
rails generate ckeditor:install --orm=active_record --backend=carrierwave
everything tried, but anyway dont work, help
Here is simple code try this .No need any gems
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<title>Full page editing with Document Properties plugin</title>
<script src="https://cdn.ckeditor.com/4.11.2/standard-all/ckeditor.js"></script>
</head>
<body>
<div class="container">
<textarea cols="80" id="editor1" name="editor1" rows="10">
</textarea>
</div>
<script>
CKEDITOR.replace('editor1', {
fullPage: true,
extraPlugins: 'docprops',
// Disable content filtering because if you use full page mode, you probably
// want to freely enter any HTML content in source mode without any limitations.
allowedContent: true,
height: 320
});
</script>
</body>
</html>

Angular ui-router templates are not loading, Rails backend

I'm following along with the Angular/Rails tutorial at Thinkster and I've run into an issue which seems to be most likely be Angular-related. Everything works just fine until I get to the Angular Routing section. Simply put, the inline templates within the <script> tags do not load in the <ui-view></ui-view> element. I originally thought this may be due to having opened the page locally as a file rather than having it loaded from a server, but the same problem persists even after integrating Rails (using an older version of Sprockets, as pointed out in this similar but unrelated issue).
When I load the index page in either the browser as a file or as a URL when running the Rails server, I've inspected the HTML and, sure enough, the only thing it shows in the code are the divs and an empty <ui-view> element, indicating something just isn't adding up correctly. I've tried various things, including:
Using the newest version of ui-router (0.2.15 at this writing) rather than the version in the tutorial
Using <div ui-view></div> instead of <ui-view></ui-view>
Changing the value of 'url' in the home state to 'index.html', including using the full path to the file (file:///...)
Putting the contents of the inline <script> templates into their own files (without the <script> tags, of course) and specifying the 'templateUrl' field using both relative and full paths
Trying both Chrome and Firefox just to be extra certain
None of these things have worked, even when accessing http://localhost:3000/#/home when the Rails server is running after having integrated Angular into the asset pipeline in the Integrating the Front-end with the Asset Pipeline section of the tutorial. Indeed, the route loads but does not show anything more than a completely blank page with a lonesome and empty <ui-view> element when inspecting the HTML using Chrome's dev tools.
Given that the issue seems to occur even before the Rails portion, it does seem like something to do with Angular itself, but I've got no clue what's going on, especially since I've followed along to the letter.
I'm using Bower to manage the Angular dependencies and the HTML does show that the Angular javascript files in both the app/assets/javascripts directory and in the vendor/assets/bower_components directory are being loaded properly in the <head> section, so everything seems to be okay on the asset pipeline integration.
Versios I'm using:
Rails: 4.2.3
Ruby: 2.2.1p85
Angular: 1.4.3
ui-router: 0.2.15
The code I've got for the major moving parts is below:
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Test App</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<body ng-app="testApp">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
</body>
</html>
app/assets/javascripts/app.js
angular.module('testApp', ['ui.router', 'templates']).config(['$stateProvider', '$urlRouteProvider', function($stateProvider, $urlRouteProvider) {
$stateProvider
.state('home', {
'url': '/home',
'templateUrl': 'home/_home.html',
'controller': 'MainCtrl'
})
.state('posts', {
'url': '/posts/{id}',
'templateUrl': 'posts/_posts.html',
'controller': 'PostsCtrl'
});
$urlRouteProvider.otherwise('home');
}]);
app/assets/javascripts/application.js
//= require angular
//= require angular-rails-templates
//= require angular-ui-router
//= require_tree .
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
respond_to :json
def angular
render 'layouts/application'
end
end
config/routes.rb
Rails.application.routes.draw do
root to: 'application#angular'
end
app/assets/javascripts/home/mainCtrl.js
angular.module('testApp').controller('MainCtrl', ['$scope', 'posts', function($scope, posts) {
$scope.posts = posts.posts;
$scope.addPost = function() {
if (!$scope.title || $scope.title === "")
return;
$scope.posts.push({
'title': $scope.title,
'link': $scope.link,
'upvotes': 0,
'comments': [
{'author': 'Some Person', 'body': 'This is a comment.', 'upvotes': 0},
{'author': 'Another Person', 'body': 'This is also a comment.', 'upvotes': 0}
]
});
$scope.title = "";
$scope.link = "";
};
$scope.incrementUpvotes = function(post) {
post.upvotes++;
};
}]);
app/assets/javascripts/posts/postsCtrl.js
angular.module('testApp').controller('PostsCtrl', ['$scope', '$stateParams', 'posts', function($scope, $stateParams, posts) {
$scope.post = posts.posts[$stateParams.id];
$scope.addComment = function() {
if($scope.body === '')
return;
$scope.post.comments.push({
'body': $scope.body,
'author': 'user',
'upvotes': 0
});
$scope.body = '';
};
}]);
app/assets/javascripts/posts/posts.js
angular.module('testApp').factory('posts', ['$http', function($http) {
var o = {
'posts': []
};
o.getAll = function() {
return $http.get('/posts.json').success(function(data) {
angular.copy(data, o.posts);
});
};
return o;
}]);
If any other code is required to help uncover the problem, please let me know and I'll supply anything requested.
it seems that the angular-ui-router is incompatible with the new Rails sprockets. To fix this, add this earlier version of sprockets to your gemfile:
gem 'sprockets', '2.12.3'
And then run bundle update sprockets.
This was answered a few times in other similar questions, like the one below:
Angular Rails Templates just not working
$urlRouteProvider in my code should've been $urlRouterProvider. Be sure to double-check everything, folks, and make good use of the console!

Getting Dojo to Work with Ruby on Rails 4

I'm porting my symfony app to Ruby on Rails 4.2.0. My setup works fine in symfony. There is this old post on how to use dojo with RoR, but it uses deprecated code.
In my application.html.erb I have
<script>dojoConfig = {async: true}</script>
<%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js'%>
I replaced the symfony wrappers with Rails ones. I also changed the dojo version. I was using 1.9.1. Rails generates this html:
<script>
dojoConfig = {async: true}
</script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js">
The last line is followed by a bunch of compressed javascript and the close script tag in Firebug.
I didn't make any changes in my home/index.html.erb where I'm testing this code. In app/assets/javaascipts/home.js, I have:
//require(["dojo/dom", "dojo/ready", "dijit/Tooltip"], function(dom, ready, Tooltip)
define(["dojo/dom", "dojo/ready", "dijit/Tooltip"], function(dom, ready, Tooltip)
{
ready(function()
{
var head = "<div class='footnote-text'>";
var tail = "</div>";
var fnt1 = head + dom.byId("fnb1").innerHTML + tail;
var fnt2 = head + dom.byId("fnb2").innerHTML + tail;
var fnt4 = head + dom.byId("fnb4").innerHTML + tail;
new Tooltip({ connectId: ["footnote1"],position:["after","above","below"],label: fnt1 });
new Tooltip({ connectId: ["footnote2"],position:["after","above","below"],label: fnt2 });
new Tooltip({ connectId: ["footnote4"],position:["after","above","below"],label: fnt4 });
new Tooltip({ connectId: ["footnote5"],position:["after","above","below"],label: fnt4 });
});
});
//require(["dojo/dom", "dojo/ready", "dijit/Dialog"], function(dom, ready, Dialog){
define(["dojo/dom", "dojo/ready", "dijit/Dialog"], function(dom, ready, Dialog){
ready(function(){
var fnt3 = dom.byId("fnb3").innerHTML;
myDialog = new Dialog({
title: "Contact Me",
content: fnt3,
style: "width: 300px"
});
});
});
The commented out require lines are what I use in my symfony app. As you can see, I replaced them with define as described on the dojo site. When I run it, I get the following error on the Firebug console:
ReferenceError: define is not defined
...define(["dojo/dom", "dojo/ready", "dijit/Tooltip"], function(dom, ready, Tooltip
If I used require instead of define, I get require is not defined.
Update
I tried installing dojo into the app and made some progress. I copied the download from dojo to vendor/assets/javascript/dojo. The dojo directory contains the subdirectories dojo, dojox, and digit
I then added
//= require dojo/dojo/dojo.js
to app/assets/javascript/application.js. I also changed the define back to require in the home.js file. When I reloaded the page, I got an error complaining that it couldn't find Tooltip. I then added:
//= require dojo/dijit/Tooltip.js
On reload it complained about a bunch of other missing js files. This is the same problem I had using symfony, which is why I went to the google image. How can I get to rails to search for the files in the vendor directories? This is one of the errors:
"NetworkError: 404 Not Found - http://amcolan.loc/dijit/_base/manager.js"
Update 2
Since require_tree worked for app assets, I thought it might work to vendor as well. I added
//= require_tree ../../../vendor/assets/javascripts/dojo
to my application.js file. When I reloaded the page, it took about a minute. My guess is that it's loading everything in the dojo directory tree, which is not surprising. The page load completed without any errors. When I hovered over a tooltip item (the purpose of the code is to show tooltips), Firebug cranked out about two thousand errors and quit. All the errors appear to be "ReferenceError: define is not defined"
Update 3
I went back to using the googleapi. My application.html.erb header looks like this
<head>
<meta charset="UTF-8">
<title><%= content_for?(:title) ? yield(:title) : "American Colonial Ancestors" %></title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<script>dojoConfig = {async: true}</script>
<%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js'%>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
I reversed the order of the javascript includes. The page reloaded without errors. The tooltip doesn't work, but it doesn't generate any errors when I hover over an item. I put a bad statement in the home.js code and it came up on the console so I know the code is being parsed. I may just have a bug in my page setup.
There may be more than one way to get Dojo toolkit to work with Ruby on Rails. This is the easiest if not the most efficient way. This works in Rails 4.2.0. I would imagine it would work in other versions as well.
In views/layouts/application.html.erb add the following prior to the inclusion of the site scripts:
<script>dojoConfig = {async: true}</script>
<%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js'%>
Change the version to the latest or to which ever one you want to use. Here I'm using version 1.10.3. The dojo site says there are other CDN's (Content Delivery Network) for the source code. I'm using google as it was in their example. Here are the pertinent parts of my head section:
<head>
<meta charset="UTF-8">
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= stylesheet_link_tag "http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dijit/themes/claro/claro.css" %>
<script>dojoConfig = {async: true}</script>
<%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dojo/dojo.js'%>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= content_for :page_script %>
<%= csrf_meta_tags %>
</head>
If you are going to use any of the toolkit's dialog boxes, tooltips, etc, you will need to include a stytlesheet by adding something like this:
<%= stylesheet_link_tag "http://ajax.googleapis.com/ajax/libs/dojo/1.10.3/dijit/themes/claro/claro.css" %>
Change the version and the theme to your own requirements. Here I'm using the claro theme. You can see it in my head section above. I don't think placement is critical. You also need to declare your theme class in the body statement. Here's mine:
<body class="claro">
An older post on the subject had different javascript formatting. I don't think anything special is needed. Here's an example of a working script:
require(["dojo/dom", "dojo/ready", "dijit/Tooltip"], function(dom, ready, Tooltip)
{
ready(function()
{
var head = "<div class='footnote-text'>";
var tail = "</div>";
var fnt1 = head + dom.byId("fnb1").innerHTML + tail;
var fnt2 = head + dom.byId("fnb2").innerHTML + tail;
new Tooltip({connectId: ["footnote1"], position:["after","above","below"], label: fnt1 });
new Tooltip({connectId: ["footnote2"], position:["after","above","below"], label: fnt2 });
});
});
As mentioned in my question, I tried placing the Dojo Toolkit source in vendor/assets/javascript. Starting with with version 1.7, dojo started using Asynchronous Module Definition (AMD). It may be the case that the AMD loader is incompatible with the Rails pre-compile feature. I don't know enough about it to say for sure.

Dynamically set value in Rails javascript asset based on Rails environment

I have a js file used for Recurly:
(function() {
// Required
Recurly.config({
subdomain: 'MYSUBDOMAIN',
currency: 'USD'
});
})();
I'd like to be able to switch the subdomain attribute based on my Rails environment but keep this javascript available to the asset pipeline. Is this possible within asset pipeline or what is the best way to achieve the equivalent functionality?
It's a disappointingly hacky solution but you could set a global variable in the <head> of your document before your asset pipelined JS is included and then use that variable later, e.g.:
In your application.html.erb:
<head>
...
<%= javascript_tag "var subdomain = '#{request.subdomains.join(".")}';" %>
<%= javascript_include_tag "application" %>
...
</head>
And in your JS:
(function() {
// Required
Recurly.config({
subdomain: subdomain,
currency: 'USD'
});
})();

Resources