I've a problem with FullCalendar (FC) and it's plugin Scheduler (S).
Since some some months I use the version 1.2.0 (S) together with 2.6.0 (FC).
It's ok, but a new request from our users (enable/disable grouping of resources) would be greatly satisfied using the feature 'get / set options dynamically'. So I've downloaded the new versions of the libraries, 1.4.0 (S) and 3.0.1 (FC).
Here come the problems: with the normal scheduler day view it works great. But, when I open a new page, where I use the weekly view, no data is show.
I've tried everything:
changed the versions, using the 2.7.3 (FC) with 1.3.2 (S).
used the version of (FC) packed in the zip together with (S).
having made some changes, I've deleted them, but the fault seems to lie in the way the libraries operate together.
I would post some code, but it's a bit complex... The scheduler is encapsulated inside a "class" and is activated using events. The whole infrastructure is part of a kind of framework and I cannot simply take a part of the code. What I'm sure is that the whole works with the older version, but no way with the new.
Up to now the only working solution is to use two versions, one for each page. But, of course, this is a kind of hack, not nice and not good for maintenance.
Here is the code used to generate the scheduler. _schedulerType is used to crate a daily or weekly view. Two "containers", _schedulerOptions and _schedulerServices are created outside and used to define how the scheduler is created.
_schedulerContainer.fullCalendar({
local (or lang): _schedulerOptions.language,
allDaySlot: false,
now: _currentDay,
selectable: true,
editable: false,
aspectRatio: _schedulerOptions.aspectRatio,
scrollTime: '07:30',
slotDuration: '00:15:00',
slotLabelInterval: '01:00:00',
slotLabelFormat: _schedulerOptions.slotLabelFormat,
slotWidth: _schedulerOptions.slotWidth,
nowIndicator: true,
customButtons: (_schedulerServices.schedulerHeader !== null) ?
_schedulerServices.schedulerHeader.createCustomButtons() :
null,
header: (_schedulerServices.schedulerHeader !== null) ?
_schedulerServices.schedulerHeader.createHeader() :
false,
defaultView: _schedulerType,
-------------------REMOVE-----------------------------------------
resourceLabelText: 'Rooms',
resourceGroupField: _defaultOptions.groupBy,
resourceOrder: _defaultOptions.orderBy,
resources:
function (callback) {
if (_schedulerServices.rscCallback !== null) {
if (log) {
console.log("reload resources inside scheduler");
}
callback(_schedulerServices.rscCallback.getResources());
}
},
------------------------------------------------------------------
events:
function (start, end, timezone, callback) {
if (_schedulerServices.evtCallback !== null) {
if (log) {
console.log("reload events inside scheduler");
}
callback(_schedulerServices.evtCallback.getEvents());
}
},
-------------------REMOVE-----------------------------------------
resourceRender:
function (resourceObj, element) {
if (_schedulerServices.rscViewManager !== null) {
return _schedulerServices.rscViewManager.requestRender(resourceObj, element);
}
},
------------------------------------------------------------------
eventRender:
function (eventObj, element) {
if (_schedulerServices.evtViewManager !== null) {
return _schedulerServices.evtViewManager.requestRender(eventObj, element);
}
}
});
Any help would be appreciated!
Thanks
Solved!!!
After version 2.6.0, the unused options fields of the options should not be used. In my case, removing all the fields related to Resources solved the problem.
Related
I was trying to find a way to launch all features in Karate testing through maven using an external variable to set up the browser (with a local webdriver or using a Selenium grid).
So something like:
mvn test -Dbrowser=chrome (or firefox, safari, etc)
or using a Selenium grid:
mvn test -Dbrowser=chrome (or firefox, safari, etc) -Dgrid="grid url"
With Cucumber and Java this was quite simple using a singleton for setting up a global webdriver that was then used in all tests. In this way I could run the tests with different local or remote webdrivers.
In Karate I tried different solution, the last was to:
define the Karate config file a variable "browser"
use the variable "browser" in a single feature "X" in which I set up only the Karate driver
from all the other features with callonce to re-call the feature "X" for using that driver
but it didn't work and to be honest it doesn't seem to me to be the right approach.
Probably being able to set the Karate driver from a Javascript function inside the features is the right way but I was not able to find a solution of that.
Another problem I found with karate is differentiating the behavior using a local or a remote webdriver as in the features files they're set in different ways.
So does anyone had my same needs and how can I solve it?
With the suggestions of Peter Thomas I used this karate-config.js
function fn() {
// browser settings, if not set it takes chrome
var browser = karate.properties['browser'] || 'chrome';
karate.log('the browser set is: ' + browser + ', default: "chrome"');
// grid flag, if not set it takes false. The grid url is in this format http://localhost:4444/wd/hub
var grid_url = karate.properties['grid_url'] || false;
karate.log('the grid url set is: ' + grid_url + ', default: false');
// configurations.
var config = {
host: 'http://httpstat.us/'
};
if (browser == 'chrome') {
if (!grid_url) {
karate.configure('driver', { type: 'chromedriver', executable: 'chromedriver' });
karate.log("Selected Chrome");
} else {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Chrome in grid");
}
} else if (browser == 'firefox') {
if (!grid_url) {
karate.configure('driver', { type: 'geckodriver', executable: 'geckodriver' });
karate.log("Selected Firefox");
} else {
karate.configure('driver', { type: 'geckodriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Firefox in grid");
}
}
return config;
}
In this way I was able to call the the test suite specifying the browser to use directly from the command line (to be used in a Jenkins pipeline):
mvn clean test -Dbrowser=firefox -Dgrid_url=http://localhost:4444/wd/hub
Here are a couple of principles. Karate is responsible for starting the driver (the equivalent of the Selenium WebDriver). All you need to do is set up the configure driver as described here: https://github.com/intuit/karate/tree/master/karate-core#configure-driver
Finally, depending on your environment, just switch the driver config. This can easily be done in karate-config.js actually (globally) instead of in each feature file:
function fn() {
var config = {
baseUrl: 'https://qa.mycompany.com'
};
if (karate.env == 'chrome') {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: 'http://somehost:9515/wd/hub' });
}
return config;
}
And on the command-line:
mvn test -Dkarate.env=chrome
I suggest you get familiar with Karate's configuration: https://github.com/intuit/karate#configuration - it actually ends up being simpler than typical Java / Maven projects.
Another way is to set variables in the karate-config.js and then use them in feature files.
* configure driver = { type: '#(myVariableFromConfig)' }
Keep these principles in mind:
Any driver instances created by a "top level" feature will be available to "called" features
You can even call a "common" feature, create the driver there, and it will be set in the "calling" feature
Any driver created will be closed when the "top level" feature ends
You don't need any other patterns.
EDIT: there's some more details in the documentation: https://github.com/intuit/karate/tree/develop/karate-core#code-reuse
And for parallel execution or trying to re-use a single browser for all tests, refer: https://stackoverflow.com/a/60387907/143475
I'm just getting started with next-offline and found the section regarding workbox integration and its recipes.
According to the docs:
If you're new to workbox, I'd recommend reading this quick guide --
anything inside of workboxOpts will be passed to
workbox-webpack-plugin.
Define a workboxOpts object in your next.config.js and it will gets
passed to workbox-webpack-plugin. Workbox is what next-offline uses
under the hood to generate the service worker, you can learn more
about it here.
After digging around, I found this great section.
Essentially it gives a suggestion to use two different options:
GenerateSW or InjectManifest
I would like to use the InjectManifest, however when I try to implement that in my next.config.js file. I get this error:
"runtimeCaching" is not a supported parameter.
This is my next.config.js:
const withCSS = require('#zeit/next-css');
const withSass = require('#zeit/next-sass');
const withImages = require('next-images');
const optimizedImages = require('next-optimized-images');
const withOffline = require('next-offline');
module.exports = withOffline(
withImages(
optimizedImages(
withCSS(
withSass({
// useFileSystemPublicRoutes: false,
// generateSw: false, // this allows all your workboxOpts to be passed in injectManifest
generateInDevMode: true,
workboxOpts: {
swDest: './service-worker.js', // this is the important part,
exclude: [/.+error\.js$/, /\.map$/, /\.(?:png|jpg|jpeg|svg)$/],
runtimeCaching: [
{
urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
handler: 'CacheFirst',
options: {
cacheName: 'hillfinder-images'
}
},
{
urlPattern: /^https?.*/,
handler: 'NetworkFirst',
options: {
cacheName: 'hillfinder-https-calls',
networkTimeoutSeconds: 15,
expiration: {
maxEntries: 150,
maxAgeSeconds: 30 * 24 * 60 * 60 // 1 month
},
cacheableResponse: {
statuses: [0, 200]
}
}
}
]
},
dontAutoRegisterSw: false,
env: {
MAPBOX_ACCESS_TOKEN: process.env.MAPBOX_ACCESS_TOKEN,
useFileSystemPublicRoutes: false
},
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
target: 'serverless'
}
}
});
return config;
}
})
)
)
)
);
Also when I check the Application pane, in devTools I see this:
You'll notice what appears to me a duplication of fields i.e. https-calls and hillfinder-https-calls and images and hillfinder-images.
I thought the cacheName field in the options: {} in each was allowing one to include a custom name?
Just wondering if anyone has had experience setting this up?
Thank you in advance!
(These comments apply to the basic Workbox build tools, not specifically to the next-offline wrapper, but I think they're still accurate.)
If you're using InjectManifest mode, the idea is that you write all of your service worker logic, using the underlying pieces of Workbox that you need, following a model that's similar to what's described in the Getting Started guide. You should include a call to precacheAndRoute(self.__WB_MANIFEST) somewhere in your service worker, and then the InjectManifest build tool is responsible for swapping out self.__WB_MANIFEST with an array containing the list of URLs to precache, along with revision information for each URL.
The runtimeCaching parameter is not compatible with InjectManifest. It's a parameter that can be used in GenerateSW mode, in with the Workbox build tool creates an entire service worker for you (including runtime caching routes). The GenerateSW mode takes in a declarative configuration and spits out the code for service worker based on that configuration. If that sounds good—if you'd just like to configure some build options and get a complete service worker as a result—then using GenerateSW is the right choice.
I'm currently using Jovo for cross platform developing Alexa and Google Assistant's skills/actions.
I currently hit a roadblock in which I'm trying to get the previous intent by doing either:
this.user().context.prev[0].request.intent or
this.user().getPrevIntent(0).
But it hasn't worked. I get context is undefined and getPrevIntent doesn't exist. According to the Docs, I need to set up a table with DynamoDB (I did, and verified that it's working since Jovo is able to store the user object), and passed in the default configuration to App. But still can't seem to get it work. Any ideas?
const config = {
logging: false,
// Log incoming JSON requests.
// requestLogging: true,
/**
* You don't want AMAZON.YesIntent on Dialogflow, right?
* This will map it for you!
*/
intentMap: {
'AMAZON.YesIntent': 'YesIntent',
'AMAZON.NoIntent': 'NoIntent',
'AMAZON.HelpIntent': 'HelpIntent',
'AMAZON.RepeatIntent': 'RepeatIntent',
'AMAZON.NextIntent': 'NextIntent',
'AMAZON.StartOverIntent': 'StartOverIntent',
'AMAZON.ResumeIntent': 'ContinueIntent',
'AMAZON.CancelIntent': 'CancelIntent',
},
// Configures DynamoDB to persist data
db: {
awsConfig,
type: 'dynamodb',
tableName: 'user-data',
},
userContext: {
prev: {
size: 1,
request: {
intent: true,
state: true,
inputs: true,
timestamp: true,
},
response: {
speech: true,
reprompt: true,
state: true,
},
},
},
};
const app = new App(config);
Thanks 😊
To make use of the User Context Object of the Jovo Framework, you need to have at least v1.2.0 of the jovo-framework.
You can update the package to the latest version like this: npm install jovo-framework --save
(This used to be a comment. Just adding this as an answer so other people see it as well)
I'm using grunt-watch to re-build my less style sheets:
watch: {
less: {
files: ['media/less/**/*.less'],
tasks: ['less'],
options: {
atBegin: true,
spawn: false
}
}
}
But if there is a syntax error in any of the .less files, the task just loops, trying to re-build the .less files every second… which makes debugging fairly difficult, because the error messages scroll past very quickly.
Is there any way fix that, so grunt-watch will only re-run the task once the .less files have been changed again?
This is using:
grunt#0.4.2
grunt-contrib-less#0.8.3
grunt-contrib-watch#0.5.3
I think the issue you're describing is this one, which was fixed in master but hasn't yet been released (as of 2013/12/17).
Well, for debugging purposes you could do a simple envelope of the less task with a custom task:
grunt.registerTask('myless', 'my less task', function() {
// do whatever debugging you want and stop the loop if needed.
grunt.task.run(['less']);
});
Then use your myless task in the watch.
UPDATE:
the idea is that since any repeated call to less now goes through your code - you can do whatever needed to either provide a more concrete output or preven repeated calls if failing is "desired" outcome and should fail, but not loop.
UPDATE 2:
Something like this:
watch: {
`less`: {
files: ['**/*.less'], // or whatever the extension is
tasks: ['myless'] // your envelope task
}
}
var flag;
grunt.registerTask('myless', 'My LESS task', function() {
if(flag === true) {
// if you are here - it means watch just invoked you repeatedly
// do whatever you need to analyze the issue (includig running an additional task)
flag = false;
return; // you exit task without altering any less files again -
// that should NOT trigger watch again
} else {
flag = true;
grunt.task.run(['less']);
}
});
Yeah it's just the initial browser load or two after a cache clear. Subsequent refreshes clear the problem up.
I'm thinking the item views just aren't fully constructed in time to be used in the collection views on the first load. But then they are on a refresh? Don't know.
There must be something about the code sequence or loading or the load time itself. Not sure. I'm loading via require.js.
Have two collections - users and messages. Each renders in its own collection view. Each works, just not the first time or two the browser loads.
The first time you load after clearing browser cache the console reports, for instance:
"Uncaught ReferenceError: MessageItemView is not defined"
A simple browser refresh clears it up. Same goes for the user collection. It's collection view says it doesn't know anything about its item view. But a simple browser refresh and all is well.
My views (item and collection) are in separate files. Is that the problem? For instance, here is my message collection view in its own file:
messagelistview.js
var MessageListView = Marionette.CollectionView.extend({
itemView: MessageItemView,
el: $("#messages")
});
And the message item view is in a separate file:
messageview.js
var MessageItemView = Marionette.ItemView.extend({
tagName: "div",
template: Handlebars.compile(
'<div>{{fromUserName}}:</div>' +
'<div>{{message}}</div>' +
)
});
Then in my main module file, which references each of those files, the collection view is constructed and displayed:
main.js
//Define a model
MessageModel = Backbone.Model.extend();
//Make an instance of MessageItemView - code in separate file, messagelistview.js
MessageView = new MessageItemView();
//Define a message collection
var MessageCollection = Backbone.Collection.extend({
model: MessageModel
});
//Make an instance of MessageCollection
var collMessages = new MessageCollection();
//Make an instance of a MessageListView - code in separate file, messagelistview.js
var messageListView = new MessageListView({
collection: collMessages
});
App.messageListRegion.show(messageListView);
Do I just have things sequenced wrong? I'm thinking it's some kind of race condition only because over 3G to an iPad the item views are always undefined. They never seem to get constructed in time. PC on a hard wired connection does see success after a browser refresh or two. It's either the load times or the difference in browsers maybe? Chrome IE and Firefox on a PC all seem to exhibit the success on refresh behavior. Safari on iPad fails always.
PER COMMENT BELOW, HERE IS MY REQIRE BLOCK:
in file application.js
require.config({
paths: {
jquery: '../../jquery-1.10.1.min',
'jqueryui': '../../jquery-ui-1.10.3.min',
'jqueryuilayout': '../../jquery.layout.min-1.30.79',
underscore: '../../underscore',
backbone: '../../backbone',
marionette: '../../backbone.marionette',
handlebars: '../../handlebars',
"signalr": "../../jquery.signalR-1.1.3",
"signalr.hubs": "/xyvidpro/signalr/hubs?",
"debug": '../../debug',
"themeswitchertool": '../../themeswitchertool'
},
shim: {
'jqueryui': {
deps: ['jquery']
},
'jqueryuilayout': {
deps: ['jquery', 'jqueryui']
},
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
marionette: {
deps: ["backbone"],
exports: "Marionette"
},
"signalr": {
deps: ["jquery"],
exports: "SignalR"
},
"signalr.hubs": {
deps: ["signalr"],
exports: "SignalRHubs"
},
"debug": {
deps: ["jquery"]
},
"themeswitchertool": {
deps: ["jquery"]
}
}
});
require(["marionette", "jqueryui", "jqueryuilayout", "handlebars", "signalr.hubs", "debug", "themeswitchertool"], function (Marionette) {
window.App = new Marionette.Application();
//...more code
})
Finally, inside the module that uses creates the collection views in question, the list of external file dependencies is as follows:
var dependencies = [
"modules/chat/views/userview",
"modules/chat/views/userlistview",
"modules/chat/views/messageview",
"modules/chat/views/messagelistview"
];
Clearly the itemViews are listed before collectionViews. This seems correct to me. Not sure what accounts for the collectionViews needing itemViews before they are defined. And why is all ok after a browser refresh?
The sequence in which you load files is most likely wrong: you need to load the item view before the collection view.
Try putting all of your code in the same file in the proper order, and see if it works.
The free preview to my book on Marionette can also guide you to displaying a collection view.
Edit based on calirification:
The dependencies listed for the module are NOT loaded linearly. That is precisely what RequireJS was designed to avoid. Instead the way to get the files loaded properly (i.e. in the correct order), is by defining a "chain" of dependencies that RequireJS will compute and load.
What you need to do is define (e.g.) your userlistview to depend on userview. In this way, they will get loaded in the proper order by RequireJS. You can see an example of a RequireJS app here (from by book on RequireJS and Marionette). Take a look at how each module definition decalre which modules it depends on (and that RequireJS therefore needs to load before). Once again, listing the modules sequentially within a dependecy array does NOT make them get loaded in that sequence, you really need to use the dependency chain mechanism.