Plugin npm - link css files

Need help with NPM plugin

I need to " link” two css files.

My Main.js =:

// – code generation, React web –

this.getReactWebPackages = function() {
return {
“fullcalendar”: “^4.0.0-alpha.4”,
“fullcalendar-scheduler”: “^4.0.0-alpha.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ varName: “calendar”, path: “fullcalendar” },
{ varName: “”, path: “fullcalendar-scheduler” }
// ??? need to include Fullcalendar’s “fullcalendar.css” and Schedulers " scheduler.css" ???
// ??? manually with a <link> tage via webpacks css-loader ???
];

Many Thanks
Steve Radford

Hi,

you should be able to write something along the lines of:

this.getReactWebImports = function(exporter) {
return [
{ varName: “FullCalendarStyle”, path: “./fullcalendar.css” }
];
}

Just make sure you have proper file path in the ‘path’ property.

BR,
Juha

1 Like

Hi juha

am getting lost in this
I need to minimise inspector UI input ( just one input " TimeLine" view) and just run calendar with no data feed to start with.-- manual resource and event as coded below in “this.getReactWebJSXCode”.
I will then try to implement the data connection my self and add the rest of the schedulers options myself.
will you be able to help me??

Steve Radford

Main.js

/*
React Studio wrapper for the ‘Fullcalendat-Scheduler400A4’ npm package.

  • 2019.01.27 / Steve Radford / sradd@mail.com / copyright 2019 Steve Radford
    */

// – plugin info requested by host app –

this.describePlugin = function(id, lang) {
switch (id) {
case ‘displayName’:
return “FullSched400A4”;

case 'shortDisplayText':
  return "Sheduler by Resources vertical .";

case 'defaultNameForNewInstance':
  return "FullSched400A4";

}
}

// – private variables –

this._data = {
readonly: false,
minValue: 0,
maxValue: 5,
iconType: 0,
color: [1, 1, 0, 1],
customComponent_full: ‘’,
customComponent_empty: ‘’,
};

// – persistence, i.e. saving and loading –

this.persist = function() {
return this._data;
}

this.unpersist = function(data) {
if ( !Array.isArray(data.color))
data.color = [1, 1, 0, 1];

if ( !data.readonly)
  data.readonly = false;

this._data = data;

}

// – inspector UI –

this.inspectorUIDefinition = [
{
“type”: “checkbox”,
“id”: “readonly”,
“label”: “Read only (user can’t modify)”,
“actionBinding”: “this.onUIChange”
},
{
“type”: “label”,
“text”: “Min/max values determine the scale:”,
“paddingTop”: 20,
},
{
“type”: “numberinput”,
“id”: “minValue”,
“label”: “Min value”,
“min”: 0,
“max”: 19,
“increment”: 1,
“actionBinding”: “this.onUIChange”
},
{
“type”: “numberinput”,
“id”: “maxValue”,
“label”: “Max value”,
“min”: 1,
“max”: 20,
“increment”: 1,
“actionBinding”: “this.onUIChange”
},

{
“type”: “label”,
“text”: “You can choose components to use as the icons.\nE.g. you could use a star as the rating icon\nand an empty component as the ‘empty rating’ icon.”,
“height”: 40,
“paddingTop”: 20,
},
{
“type”: “label”,
“text”: “Custom rating icon:”
},
{
“type”: “component-picker”,
“id”: “customComponent_full”,
“actionBinding”: “this.onUIChange”
},
{
“type”: “label”,
“text”: “Custom icon for empty rating:”
},
{
“type”: “component-picker”,
“id”: “customComponent_empty”,
“actionBinding”: “this.onUIChange”
}
];

this._uiTextFields = [];
this._uiCheckboxes = [ ‘readonly’ ];
this._uiNumberFields = [ ‘minValue’, ‘maxValue’, ‘iconType’ ];
this._uiColorPickers = [ ‘color’ ];
this._uiComponentPickers = [ ‘customComponent_full’, ‘customComponent_empty’ ];

this._accessorForDataKey = function(key) {
if (this._uiTextFields.includes(key)) return ‘text’;
else if (this._uiCheckboxes.includes(key)) return ‘checked’;
else if (this._uiNumberFields.includes(key)) return ‘numberValue’;
else if (this._uiColorPickers.includes(key)) return ‘rgbaArrayValue’;
else if (this._uiComponentPickers.includes(key)) return ‘componentName’;
return null;
}

this.onCreateUI = function() {
var ui = this.getUI();
for (var controlId in this._data) {
var prop = this._accessorForDataKey(controlId);
if (prop) {
try {
ui.getChildById(controlId)[prop] = this._data[controlId];
} catch (e) {
console.log("** can’t set ui value for key “+controlId+”, prop "+prop);
}
}
}
}

this.onUIChange = function(controlId) {
var ui = this.getUI();
var prop = this._accessorForDataKey(controlId);
if (prop) {
this._data[controlId] = ui.getChildById(controlId)[prop];
} else {
console.log("** no data property found for controlId "+controlId);
}
}

// – plugin preview –

this.renderIcon = function(canvas) {
this._renderPreview(canvas, null, true, 5);
};

this.renderEditingCanvasPreview = function(canvas, controller) {
this._renderPreview(canvas, controller, false, this._data.maxValue - this._data.minValue);
}

this._renderPreview = function(canvas, controller, fitToWidth, numIcons) {
var ctx = canvas.getContext(‘2d’);
var w = canvas.width;
var h = canvas.height;
ctx.save();

var scale = 1;
if (controller && controller.renderPixelsPerWebPixel) {
scale = controller.renderPixelsPerWebPixel;
ctx.scale(scale, scale);
}

// var customIcon_full = this.getComponentPreviewImage(this._data.customComponent_full);
// var customIcon_empty = this.getComponentPreviewImage(this._data.customComponent_empty);
//
// var color = “rgba(0, 0, 0, 0.75)”;
// ctx.fillStyle = color;
// ctx.strokeStyle = color;
//
// ctx.strokeWidth = scale * 0.7;
//
// var xMargin = 1;
// var yMargin = 2;
// var spacing = 3;
// var r;
// if (fitToWidth) {
// r = (w - 2xMargin - (numIcons-1)spacing) / numIcons / 2;
// yMargin = h/2 - r;
// } else {
// r = 9;
// }
//
// var x = xMargin + r;
// var y = yMargin + r;
// for (var i = 0; i < numIcons; i++) {
// var w = r
2 + spacing;
// var icon = null;
// if (numIcons > 1 && i === numIcons - 1) {
// icon = customIcon_empty;
// }
// if ( !icon) {
// icon = customIcon_full;
// }
// if (icon) {
// var iconW = icon.width/scale;
// var iconH = icon.height/scale;
// ctx.drawImage(icon, x-r, y-r, iconW, iconH);
//
// if ( !fitToWidth)
// w = iconW;
// } else {
// /

// // draw filled circle with outline
// ctx.beginPath();
// ctx.arc(x, y, r, 0, Math.PI2, false);
// ctx.stroke();
// ctx.beginPath();
// ctx.arc(x, y, r - 2, 0, Math.PI
2, false);
// ctx.fill();
// /
// // draw star
// ctx.beginPath();
// ctx.moveTo(x, y - r);
// for (var k = 1; k < 10; k++) {
// var t = -Math.PI/2 + (k/5 * Math.PI);
// var rp = (k % 2 == 1) ? r
0.4 : r;
// ctx.lineTo(x + rpMath.cos(t), y + rpMath.sin(t));
// }
// if (i < numIcons - 1) {
// ctx.fill();
// }
// ctx.closePath();
// ctx.stroke();
// }
//
// x += w;
// }
//
ctx.restore();
// }

// – code generation, React web –

this.getReactWebPackages = function() {
return {
“fullcalendar”: “^4.0.0-alpha.4”,
“fullcalendar-scheduler”: “^4.0.0-alpha.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ varName: “calendar”, path: “fullcalendar” },
{ varName: “”, path: “fullcalendar-scheduler” }
{ varName: “FullCalendarStyle”, path: “…/fullcalendar/dist/fullcalendar.css” }
{ varName: “SchedulerStyle”, path: “…/fullcalendar-scheduler/dist/scheduler.css” }
//{ varName: “FullCalendarStyle”, path: “./node_modules/fullcalendar/dist/fullcalendar.css” }
//{ varName: “SchedulerStyle”, path: “./node_modules/fullcalendar-scheduler/dist/scheduler.css” }
];

// var customComp_full = exporter.classNameForComponentByName(this._data.customComponent_full);
// if (customComp_full) {
//	arr.push({ varName: customComp_full, path: `./${customComp_full}` });

arr.push({ varName: calendar, path: ./${customComp_full} });
// }
// var customComp_empty = exporter.classNameForComponentByName(this._data.customComponent_empty);
// if (customComp_empty && customComp_empty != customComp_full) {
// arr.push({ varName: customComp_empty, path: ./${customComp_empty} });
// }

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template
this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {

document.addEventListener(‘DOMContentLoaded’, function() {
var calendarEl = document.getElementById(‘calendar’);
var calendar = new Calendar(calendarEl, {
// options
now: ‘2019-01-31’,
editable: true, // enable draggable events
aspectRatio: 1.8,
scrollTime: ‘00:00’, // undo default 6am scrollTime
header: {
left: ‘today prev,next’,
center: ‘title’,
right: ‘timelineDay,timelineThreeDays,agendaWeek,month,listWeek’
},
defaultView: ‘timelineDay’,
views: {
timelineThreeDays: {
type: ‘timeline’,
duration: { days: 3 },
buttonText: ‘3 days’
}
},
resourceLabelText: ‘Stylists’,
resources: [
{ id: ‘a’, title: ‘John Hi-lights’ },
{ id: ‘b’, title: ‘John Tint’, eventColor: ‘green’ },

  ],
  events: [
    { id: '1', resourceId: 'a', start: '2019-01-31T02:00:00', end: '2019-01-31T02:30:00', title: 'High Light Medium with cut' },
    { id: '2', resourceId: 'b', start: '2019-01-31T05:00:00', end: '2019-01-31T05:30:00', title: 'event 2' },
    { id: '4', resourceId: 'a', start: '2019-01-31T03:00:00', end: '2019-01-31T03:30:00', title: 'event 4' },
    { id: '5', resourceId: 'a', start: '2019-01-31T09:00:00', end: '2019-01-31T09:30:00', title: 'event 5' }
  ]


});
calendar.render();

});

// var jsx = <Rating readonly={${readonly}} start={${min}} stop={${max}};
//
// jsx += />;
// return jsx;
}

Hi Steve,

please make sure you return a string value from getReactWebJSXCode method. React Studio doesn’t execute the code itself but just writes it as a plain string to the exported project. getReactWebJSXCode writes code that is responsible for the HTML output of the project so you should implement it something like this:

this.getReactWebJSXCode = function (exporter) {
return “<calendar now: ‘2019-01-31’ editable: true etc. />”;
}

Also it might be a good idea to move some of the initialization code to getReactWebRenderMethodSetupCode method. Here’s an example how the method works:

this.getReactWebRenderMethodSetupCode = function(exporter, elementName) {
return “let example_var_for_”+elementName+";\n";
}

Checking how the code looks when you export the project should give better understanding how the code generation of the plugins work.

BR,
Juha

Hi
Juha

I’ve minimised the main.js as below.
But it doesn’t do anything
Please help
Steve

// – plugin info requested by host app –
this.__pluginHostId = “FulSched4A4”;
this.__pluginPackageId = “com.neonto.plugin.reactstudio.FullShed4A4”;

this.describePlugin = function(id, lang) {
switch (id) {
case ‘displayName’:
return “FullSched400A4”;

case 'shortDisplayText':
  return "Sheduler by Resources vertical .";

case 'defaultNameForNewInstance':
  return "fullsched400a4";

}
}

// – private variables –

this._data = {

};

// – persistence, i.e. saving and loading –

this.persist = function() {
return this._data;
}

this.unpersist = function(data) {

this._data = data;

}

// – inspector UI –

this.onCreateUI = function() {

}

this.onUIChange = function(controlId) {

}

// – plugin preview –

this.renderIcon = function(canvas) {
var ctx = canvas.getContext(‘2d’);
var w = canvas.width;
var h = canvas.height;
ctx.save();
if (this.icon == null) {
var path = Plugin.getPathForResource(“fullcalendarsqs180180.png”);
this.icon = Plugin.loadImage(path);
}
var iconW = this.icon.width;
var iconH = this.icon.height;
var aspectScale = Math.min(w/iconW, h/iconH);
var scale = 0.9 * aspectScale; // add some margin around icon
iconW *= scale;
iconH *= scale;
ctx.drawImage(this.icon, (w-iconW)*0.5, (h-iconH)*0.5, iconW, iconH);

ctx.restore();
}

// – code generation, React web –

this.getReactWebPackages = function() {
return {
“fullcalendar”: “^4.0.0-alpha.4”;
“fullcalendar-scheduler”: “^4.0.0-alpha.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ varName: “FullCalendarStyle”, path: “…/fullcalendar/dist/fullcalendar.css” }
{ varName: “SchedulerStyle”, path: “…/fullcalendar-scheduler/dist/scheduler.css” }
{ varName: { calendar }, path: “fullcalendar” }
{ varName: “”, path: “fullcalendar-scheduler” }
];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {
return "<calendar
now: ‘2019-01-31’;
slotDuration: ‘00:15:00’; // 15 minutes slots
minTime: ‘05:00:00’; //
maxTime: ‘19:00:00’;
editable: true; // enable draggable events
aspectRatio: 1.8;
scrollTime: ‘07:00:00’; // undo default 6am scrollTime
weekends: true;
header: {
left: ‘today prev,next’;
center: ‘title’;
right: ‘agendaDay,basicDay,timelineThreeDays’
};
defaultView: ‘agendaDay’;
views: {
timelineThreeDays: {
type: ‘timeline’;
duration: { days: 3 };
buttonText: ‘3 days’
}
};
resourceLabelText: ‘Stylists’;
resources: [
{ id: ‘a’, title: ‘John Hi-lights’ };
{ id: ‘b’, title: ‘John Tint’, eventColor: ‘green’ }

  ],
  events: [
    { id: '1', resourceId: 'a', start: '2019-01-31T02:00:00', end: '2019-01-31T02:30:00', title: 'High Light Medium with cut' };
    { id: '2', resourceId: 'b', start: '2019-01-31T05:00:00', end: '2019-01-31T05:30:00', title: 'event 2' };
    { id: '4', resourceId: 'a', start: '2019-01-31T03:00:00', end: '2019-01-31T03:30:00', title: 'event 4' };
    { id: '5', resourceId: 'a', start: '2019-01-31T09:00:00', end: '2019-01-31T09:30:00', title: 'event 5' }
  ]

/>";

}

Hi Steve,

there seems to be few syntax errors, e.g. there’s a semicolon in the middle of the dictionary returned by the getReactWebPackages method. React Studio prints plugin errors to Project Command Line window (Plugins -> Developer Extras -> Show Project-Level Command Line) and Mac’s Console app. Also code editors such as VS Code is very useful for catching syntax errors.

BR,
Juha

Hi Juha
Thanks for the plugin errors find - have sorted them but am struggling with —

https://fullcalendar.io/docs/v4/scheduler requirement of " import ‘Fullcalendar-scheduler’;
== importing with no varName: “” ,path: “Fullcalendar-scheduler”

import { Calendar } from ‘fullcalendar’;
import ‘fullcalendar-scheduler’;

how do I write the above line in getReactWebImports function

my Main.js follows below:

// – plugin info requested by host app –
this.__pluginHostId = “com.neonto.studio.element”;
this.__pluginPackageId = “com.neonto.plugin.reactstudio.fullshed4a4”;

this.describePlugin = function(id, lang) {
switch (id) {
case ‘displayName’:
return “FullSched400A4”;

case 'shortDisplayText':
  return "Sheduler by Resources vertical .";

case 'defaultNameForNewInstance':
  return "fullsched400a4";

}
}

// – private variables –

this._data = {
//nowDate: “2019-01-31”,
// slotDuration: “00:15:00”, // 15 minutes slots
// defaultView: “agendaDay”
};

// – persistence, i.e. saving and loading –

this.persist = function() {
return this._data;
}

this.unpersist = function(data) {

this._data = data;

}

// – inspector UI –

this.onCreateUI = function() {

}

this.onUIChange = function(controlId) {

}

// – plugin preview –

this.renderIcon = function(canvas) {
var ctx = canvas.getContext(‘2d’);
var w = canvas.width;
var h = canvas.height;
ctx.save();
if (this.icon == null) {
var path = Plugin.getPathForResource(“fullcalendarsqs180180.png”);
this.icon = Plugin.loadImage(path);
}
var iconW = this.icon.width;
var iconH = this.icon.height;
var aspectScale = Math.min(w/iconW, h/iconH);
var scale = 0.9 * aspectScale; // add some margin around icon
iconW *= scale;
iconH *= scale;
ctx.drawImage(this.icon, (w-iconW)*0.5, (h-iconH)*0.5, iconW, iconH);

ctx.restore();
}

// – code generation, React web –

this.getReactWebPackages = function() {
return {
“fullcalendar”: “^4.0.0-alpha.4”,
“fullcalendar-scheduler”: “^4.0.0-alpha.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ varName: “FullCalendarStyle”, path: “…/node_modules/fullcalendar/dist/fullcalendar.css” },
{ varName: “SchedulerStyle”, path: “…/node_modules/fullcalendar-scheduler/dist/scheduler.css” },
{ varName: “calendar”, path: “fullcalendar” },
{ varName: “calendar1”, path: “fullcalendar-scheduler” }
//{ varName: " ", path: “fullcalendar-scheduler” }
];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {
// var nowdates = this._data.nowDate;
// var slotDurations = this._data.slotDuration;
// var defaultViews = this._data.defaultView;
var jsx = <calendar
jsx += defaultView : 'agendaDay',
jsx += defaultDate : '2019-02-07',
jsx += slotDuration : '00:15:00',
jsx += weekends : true,
jsx += editable : true,
jsx += selectable : true,
jsx += eventLimit : true,
jsx += header : {
jsx += left : 'prev,next today',
jsx += center : 'title',
jsx += right : 'agendaDay,basicDay,agendaTwoDay'
jsx += },
jsx += views : {
jsx += agendaTwoDay : { type : 'agenda', duration : { days : 2 },
jsx += }
jsx += },
jsx += allDaySlot : false,
jsx += resourceLabelText: 'Stylists',
jsx += resources: [
jsx += { id: 'a', title: 'John Hi-lights' },
jsx += { id: 'b', title: 'John Tint', eventColor: 'green' }
jsx += ],
jsx += events: [
jsx += { id: '1', resourceId: 'a', start: '2019-02-07T02:00:00', end: '2019-02-07T02:30:00', title: 'High Light Medium with cut' },
jsx += { id: '2', resourceId: 'b', start: '2019-02-07T05:00:00', end: '2019-02-07T05:30:00', title: 'event 2' },
jsx += { id: '4', resourceId: 'a', start: '2019-02-07T03:00:00', end: '2019-02-07T03:30:00', title: 'event 4' },
jsx += { id: '5', resourceId: 'a', start: '2019-02-07T09:00:00', end: '2019-02-07T09:30:00', title: 'event 5' }
jsx += ]
jsx += />;
return jsx;

}

many thanks Steve

I need to –
syntax===
import “module-name”;
===syntax

I’ve used all sorts of variations to no avail

even
{ varName: " ", path: “fullcalendar-scheduler” }
and
{ varName: “*”, path: “fullcalendar-scheduler” }
and
{ path: “fullcalendar-scheduler” }
but none of these work?

Steve

Yes, unfortunately it’s true that you can’t have just plain import statement without from syntax at the moment. It can be added to the next version which we are aiming to release pretty soon. Is it so that meanwhile you can’t use something like:

{ varName: “Scheduler”, path: “fullcalendar-scheduler” }

-Juha

Thanks
will get hold of Fullcalendar and ask them what to use

many thanks in replying
Steve

Can you please write this into your next version.

No joy from Fullcalendar.io.

I am busy on 3 projects that revolve around this Fullcalendar-Scheduler import.
(Fullcalendar is currently downloaded 78000 times weekly and Fullcalendar-Scheduler = 9000 times @ “npmjs.com”.)
I code alone – have done since Cobol 1984 and VS-VB 1987. And really need and enjoy your React-Studio linked with firestore noSQL system to pump out my Projects.

Would you have any idea on the expected date I can receive this Import without “from” amendment.

Most appreciated
Steve

Hi Steve,

we’ll make the release this week if nothing goes wrong.

-Juha

Most appreciated
Steve

The update is now live! (build 349). You should see the update dialog in React Studio.

You can now write entries with just path property to getReactWebImports method to write plain import statements to exported project. I.e. this:

this.getReactWebImports = function(exporter) { return [{path: “Test”}]; }

Produces this:

import ‘Test’;

-Juha

1 Like

many thanks
appreciate
Steve

1 Like

Hi

Thanks for the Import change — But as Murphy would have it ??!! —

Fullcalendar has gone to beta and changed imports chopped up there system

into smaller specific plugins — ( much faster and better)

I however have lost the react studio plugin name -says “Untitled Plugin”

And there’s no Fullcalendar code showing up in the “Code Glance” window?

“A” section hereunder is the new Fullcalendar Docs/Vertical Resource View implementation.

And

“B” is my attempt at Plugin Main.js in my plugin.

Help would be most appreciated

Steve

—A—

Docs Vertical Resource View v4

>>>>>>>>>>>>>>>>>>>>

TimeGrid day resource view can be initialized in an ES6 setup like so:

npm install --save @fullcalendar/core @fullcalendar/resource-timegrid

import { Calendar } from ‘@fullcalendar/core’;

import resourceTimeGridPlugin from ‘@fullcalendar/resource-timegrid’;

let calendar = new Calendar(calendarEl, {

plugins: [ resourceTimeGridPlugin ],

defaultView: ‘resourceTimeGridDay’,

resources: [

// your list of resources

]

});

Then you’ll need to ensure the correct stylesheets are loaded:

<link href=‘node_modules/@fullcalendar/core/main.css’ rel=‘stylesheet’ />

<link href=‘node_modules/@fullcalendar/timegrid/main.css’ rel=‘stylesheet’ />

<link href=‘node_modules/@fullcalendar/resource-timegrid/main.css’ rel=‘stylesheet’ />

>>>>>>>>>>>>>>>>>

—B—

>>>>>>>>>>>>> =Main.js

// – plugin info requested by host app –

this.__pluginHostId = “com.neonto.studio.element”;

this.__pluginPackageId = “com.neonto.plugin.reactstudio.fullshed4b4”;

this.describePlugin = function(id, lang) {

switch (id) {

case ‘displayName’:

return “fullshed4b4”;

case ‘shortDisplayText’:

return “Sheduler by Resources vertical .”;

case ‘defaultNameForNewInstance’:

return “fullsched400b4”;

}

}

// – private variables –

this._data = {

//nowDate: “2019-01-31”,

// slotDuration: “00:15:00”, // 15 minutes slots

// defaultView: “agendaDay”

};

// – persistence, i.e. saving and loading –

this.persist = function() {

return this._data;

}

this.unpersist = function(data) {

this._data = data;

}

// – inspector UI –

this.onCreateUI = function() {

}

this.onUIChange = function(controlId) {

}

// – plugin preview –

this.renderIcon = function(canvas) {

var ctx = canvas.getContext(‘2d’);

var w = canvas.width;

var h = canvas.height;

ctx.save();

if (this.icon == null) {

var path = Plugin.getPathForResource(“fullcalendarsqs180180.png”);

this.icon = Plugin.loadImage(path);

}

var iconW = this.icon.width;

var iconH = this.icon.height;

var aspectScale = Math.min(w/iconW, h/iconH);

var scale = 0.9 * aspectScale; // add some margin around icon

iconW *= scale;

iconH *= scale;

ctx.drawImage(this.icon, (w-iconW)*0.9, (h-iconH)*0.9, iconW, iconH);

ctx.restore();

}

// – code generation, React web –

this.getReactWebPackages = function() {

return {

@fullcalendar/core”: “^4.0.0-beta.4”,

@fullcalendar/resource-timegrid”: “^4.0.0-beta.4”

@fullcalendar/interaction”: “^4.0.0-beta.4”

};

}

this.getReactWebImports = function(exporter) {

var arr = [

{ varName: “stylesheet”, path: “…/node_modules/@fullcalendar/core/main.css” },

{ varName: “stylesheet”, path: “…/node_modules/@fullcalendar/timegrid/main.css” },

{ varName: “stylesheet”, path: “…/node_modules/@fullcalendar/resource-timegrid/main.css” },

{ varName: “{ Calendar }”, path: “@fullcalendar/core” },

{ varName: “resourceTimeGridPlugin”, path: “@fullcalendar/resource-timegrid” },

{ varName: “interaction”, path: “@fullcalendar/interaction” },

];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [

“value”

];

this.reactWebInteractions = [

“valueChange” // This is the id for the default interaction available to plugins in React Studio

];

this.describeReactWebInteraction = function(exporter, interactionId) {

switch (interactionId) {

case ‘valueChange’:

return {

actionMethod: {

// arguments: [‘rating’],

// getDataExpression: ‘rating’

}

};

}

return null;

}

this.getReactWebJSXCode = function(exporter) {

var jsx = &lt;calendar

jsx += plugins: [ resourceTimeGridPlugin ],

jsx += defaultView: 'resourceTimeGridDay',

jsx += resources: [

jsx += { id: 'a', title: 'John Hi-lights' },

jsx += { id: 'b', title: 'John Tint', eventColor: 'green' }

jsx += ],

jsx += events: [

jsx += { id: '1', resourceId: 'a', start: '2019-02-07T02:00:00', end: '2019-02-07T02:30:00', title: 'High Light Medium with cut' },

jsx += { id: '2', resourceId: 'b', start: '2019-02-07T05:00:00', end: '2019-02-07T05:30:00', title: 'event 2' },

jsx += { id: '4', resourceId: 'a', start: '2019-02-07T03:00:00', end: '2019-02-07T03:30:00', title: 'event 4' },

jsx += { id: '5', resourceId: 'a', start: '2019-02-07T09:00:00', end: '2019-02-07T09:30:00', title: 'event 5' }

jsx += ]

jsx += /&gt;; calendar.render();

return jsx;

}

>>>>>>>>>>>>>

—C—

>>>>> info.plist

<?xml version=“1.0” encoding=“UTF-8”?>

<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>

<plist version=“1.0”>

<dict>

<key>CFBundleName</key>

<string>fullshed4b4</string>

<key>CFBundleIdentifier</key>

<string>com.neonto.plugin.reactstudio.fullshed4b4</string>

<key>CFBundleVersion</key>

<string>8</string>

<key>CFBundlePackageType</key>

<string>BNDL</string>

<key>CFBundleSignature</key>

<string>???</string>

<key>SPXPluginTypeId</key>

<string>exchange.spx.plugin.element</string>

<key>SPXPluginDependencies</key>

<array>

<string>js/mustache.js</string>

</array>

</dict>

</plist>

>>>>>>info.plist

Hi

Have edited my main.js but am stopping on line 55 c 63 see screenshot.

hereunder my main.js file.
Fullcalendar use the same stylesheet varName for all threee sheets
RS only brings in the first one --I had to change the varNames on the 2nd and 3rd sty sheets
but am not sure how to load them in the plugin.

// – plugin info requested by host app –
this.__pluginHostId = “com.neonto.studio.element”;
this.__pluginPackageId = “com.neonto.plugin.reactstudio.fullshed4b4”;

this.describePlugin = function(id, lang) {
switch (id) {
case ‘displayName’:
return “fullshed4b4”;

case 'shortDisplayText':
  return "Sheduler by Resources vertical .";

case 'defaultNameForNewInstance':
  return "fullsched400b4";

}
}

// – private variables –

this._data = {
//nowDate: “2019-01-31”,
// slotDuration: “00:15:00”, // 15 minutes slots
// defaultView: “agendaDay”
};

// – persistence, i.e. saving and loading –

this.persist = function() {
return this._data;
}

this.unpersist = function(data) {

this._data = data;

}

// – inspector UI –

this.onCreateUI = function() {

}

this.onUIChange = function(controlId) {

}

// – plugin preview –

this.renderIcon = function(canvas) {
var ctx = canvas.getContext(‘2d’);
var w = canvas.width;
var h = canvas.height;
ctx.save();
if (this.icon == null) {
var path = Plugin.getPathForResource(“512-30.png”);
this.icon = Plugin.loadImage(path);
}
var iconW = this.icon.width;
var iconH = this.icon.height;
var aspectScale = Math.min(w/iconW, h/iconH);
var scale = 0.9 * aspectScale; // add some margin around icon
iconW *= scale;
iconH *= scale;
ctx.drawImage(this.icon, (w-iconW)*0.5, (h-iconH)*0.5, iconW, iconH);
ctx.drawImage(this.icon, 10, 10);
ctx.restore();
}

// – code generation, React web –

this.getReactWebPackages = function() {
return {
@fullcalendar/core”: “^4.0.0-beta.4”,
@fullcalendar/resource-timegrid”: “^4.0.0-beta.4”
//"@fullcalendar/interaction": “^4.0.0-beta.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ varName: “stylesheet”, path: “…/node_modules/@fullcalendar/core/main.css” },
{ varName: “stylesheettg”, path: “…/node_modules/@fullcalendar/timegrid/main.css” },
{ varName: “stylesheetrtg”, path: “…/node_modules/@fullcalendar/resource-timegrid/main.css” },
{ varName: “{ Calendar }”, path: “@fullcalendar/core” },
{ varName: “resourceTimeGridPlugin”, path: “@fullcalendar/resource-timegrid” },
//{ varName: “interaction”, path: “@fullcalendar/interaction” },
];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {

var jsx = `let calendar = new Calendar(calendarEl, {`;
jsx += ` plugins: [ resourceTimeGridPlugin ],`;
jsx += ` defaultView: 'resourceTimeGridDay',`;
jsx += ` resources: [`;
jsx += ` { id: 'a', title: 'John Hi-lights' },`;
jsx += ` { id: 'b', title: 'John Tint', eventColor: 'green' }`;
jsx += ` ],`;
jsx += ` events: [`;
jsx += ` { id: '1', resourceId: 'a', start: '2019-02-07T02:00:00', end: '2019-02-07T02:30:00', title: 'High Light Medium with cut' },`;
jsx += ` { id: '2', resourceId: 'b', start: '2019-02-07T05:00:00', end: '2019-02-07T05:30:00', title: 'event 2' },`;
jsx += ` { id: '4', resourceId: 'a', start: '2019-02-07T03:00:00', end: '2019-02-07T03:30:00', title: 'event 4' },`;
jsx += ` { id: '5', resourceId: 'a', start: '2019-02-07T09:00:00', end: '2019-02-07T09:30:00', title: 'event 5' }`;
jsx += ` ]`;
jsx += ` }); calendar.render(); `;

return jsx;

}

many thanks
Steve

Hi Steve,

you can now import css files with just path property in getReactWebImports. They don’t really need varName but it was required by React Studio up until the previous update.

getReactWebJSXCode method can’t export JS code directly but it should write HTML elements instead. Something like:

this.getReactWebJSXCode = function(exporter) {
var jsx = <Calendar;
jsx += plugins=[ resourceTimeGridPlugin ];
// other properties
jsx += />;
return jsx;
}

-Juha

hi Juha

can you see what wrong with my main.js attached
I don’t see any Fullcalendar code in code glance and my icon and plugin name have gone back to
“untitled plugin” with no icon

this.getReactWebPackages = function() {
return {
@fullcalendar/core”: “^4.0.0-beta.4”,
@fullcalendar/resource-timegrid”: “^4.0.0-beta.4”
//"@fullcalendar/interaction": “^4.0.0-beta.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ path: “…/node_modules/@fullcalendar/core/main.css” },
{ path: “…/node_modules/@fullcalendar/timegrid/main.css” },
{ path: “…/node_modules/@fullcalendar/resource-timegrid/main.css” },
{ varName: “{ Calendar }”, path: “@fullcalendar/core” },
{ varName: “resourceTimeGridPlugin”, path: “@fullcalendar/resource-timegrid” },
//{ varName: “interaction”, path: “@fullcalendar/interaction” },
];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {

var jsx = <Calendar(calendarEl, {;
jsx +=  plugins= [ resourceTimeGridPlugin ];
jsx +=  defaultView= 'resourceTimeGridDay';
jsx +=  resources= [
jsx +=  { id: 'a', title: 'John Hi-lights' },
jsx +=  { id: 'b', title: 'John Tint', eventColor: 'green' }
jsx +=  ];
jsx +=  events= [
jsx +=  { id: '1', resourceId: 'a', start: '2019-02-07T02:00:00', end: '2019-02-07T02:30:00', title: 'High Light Medium with cut' },
jsx +=  { id: '2', resourceId: 'b', start: '2019-02-07T05:00:00', end: '2019-02-07T05:30:00', title: 'event 2' },
jsx +=  { id: '4', resourceId: 'a', start: '2019-02-07T03:00:00', end: '2019-02-07T03:30:00', title: 'event 4' },
jsx +=  { id: '5', resourceId: 'a', start: '2019-02-07T09:00:00', end: '2019-02-07T09:30:00', title: 'event 5' }
jsx +=  ]
jsx +=  }); Calendar.render();
jsx += />;

return jsx;
}

I placed the back ticks into the jsx string and the name of plugin and its icon reappeared but gave "
unexpected token at in JSX string line at Calendar; position see attached screenshot

Steve

// – code generation, React web –

this.getReactWebPackages = function() {
return {
@fullcalendar/core”: “^4.0.0-beta.4”,
@fullcalendar/resource-timegrid”: “^4.0.0-beta.4”
//"@fullcalendar/interaction": “^4.0.0-beta.4”
};
}

this.getReactWebImports = function(exporter) {
var arr = [
{ path: “…/node_modules/@fullcalendar/core/main.css” },
{ path: “…/node_modules/@fullcalendar/timegrid/main.css” },
{ path: “…/node_modules/@fullcalendar/resource-timegrid/main.css” },
{ varName: “{ Calendar }”, path: “@fullcalendar/core” },
{ varName: “resourceTimeGridPlugin”, path: “@fullcalendar/resource-timegrid” },
//{ varName: “interaction”, path: “@fullcalendar/interaction” },
];

return arr;

}

this.writesCustomReactWebComponent = false; // change to true if use component template

this.reactWebDataLinkKeys = [
“value”
];

this.reactWebInteractions = [
“valueChange” // This is the id for the default interaction available to plugins in React Studio
];

this.describeReactWebInteraction = function(exporter, interactionId) {
switch (interactionId) {
case ‘valueChange’:
return {
actionMethod: {
// arguments: [‘rating’],
// getDataExpression: ‘rating’
}
};
}
return null;
}

this.getReactWebJSXCode = function(exporter) {

var jsx = `<Calendar;`
jsx +=  ` plugins= [ resourceTimeGridPlugin ];`
jsx +=  ` defaultView= 'resourceTimeGridDay';`
jsx +=  ` resources= [`
jsx +=  `{ id: 'a', title: 'John Hi-lights' },`
jsx +=  ` { id: 'b', title: 'John Tint', eventColor: 'green' }`
jsx +=  `];`
jsx +=  ` events= [`
jsx +=  ` { id: '1', resourceId: 'a', start: '2019-02-07T02:00:00', end: '2019-02-07T02:30:00', title: 'High Light Medium with cut' },`
jsx +=  ` { id: '2', resourceId: 'b', start: '2019-02-07T05:00:00', end: '2019-02-07T05:30:00', title: 'event 2' },`
jsx +=  ` { id: '4', resourceId: 'a', start: '2019-02-07T03:00:00', end: '2019-02-07T03:30:00', title: 'event 4' },`
jsx +=  ` { id: '5', resourceId: 'a', start: '2019-02-07T09:00:00', end: '2019-02-07T09:30:00', title: 'event 5' }`
jsx +=  `]`
jsx +=  ` />;`
jsx +=  ` Calendar.render();`

return jsx;
}