Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions js-src/00-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const SF = (function () {
.replace(/"/g, '"');
};

sf.assert = function (cond, message) {
if (!cond) throw new Error('[SolverForge] ' + message);
};

sf.el = function (tag, attrs) {
var children = Array.prototype.slice.call(arguments, 2);
var el = document.createElement(tag);
Expand Down
4 changes: 4 additions & 0 deletions js-src/03-buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
'use strict';

sf.createButton = function (config) {
sf.assert(config, 'createButton(config) requires a configuration object');

var classes = ['sf-btn'];

if (config.variant) classes.push('sf-btn--' + config.variant);
Expand All @@ -23,6 +25,8 @@

if (config.disabled) btn.disabled = true;

sf.assert(!config.onClick || typeof config.onClick === 'function', 'createButton(onClick) must be a function');

if (config.icon) {
var icon = sf.el('i', { className: 'fa-solid ' + config.icon });
btn.appendChild(icon);
Expand Down
11 changes: 11 additions & 0 deletions js-src/04-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
'use strict';

sf.createHeader = function (config) {
sf.assert(config, 'createHeader(config) requires a configuration object');

var header = sf.el('header', { className: 'sf-header' });
var controls = {
actions: null,
Expand Down Expand Up @@ -38,9 +40,12 @@

// Nav tabs
if (config.tabs && config.tabs.length > 0) {
sf.assert(Array.isArray(config.tabs), 'createHeader(config.tabs) expects an array');
var nav = sf.el('nav', { className: 'sf-header-nav' });
controls.nav = nav;
config.tabs.forEach(function (tab) {
sf.assert(tab && tab.id, 'createHeader tab entries require an id');
sf.assert(typeof tab.label === 'string', 'createHeader tab entries require a label');
var btn = sf.el('button', {
className: 'sf-nav-btn' + (tab.active ? ' active' : ''),
dataset: { tab: tab.id },
Expand All @@ -61,6 +66,12 @@

// Action buttons
if (config.actions) {
sf.assert(typeof config.actions === 'object', 'createHeader(config.actions) expects an object');
sf.assert(!config.actions.onSolve || typeof config.actions.onSolve === 'function', 'createHeader(config.actions.onSolve) must be a function');
sf.assert(!config.actions.onStop || typeof config.actions.onStop === 'function', 'createHeader(config.actions.onStop) must be a function');
sf.assert(!config.actions.onAnalyze || typeof config.actions.onAnalyze === 'function', 'createHeader(config.actions.onAnalyze) must be a function');
sf.assert(!config.onTabChange || typeof config.onTabChange === 'function', 'createHeader(config.onTabChange) must be a function');

var actions = sf.el('div', { className: 'sf-header-actions' });
controls.actions = actions;

Expand Down
3 changes: 3 additions & 0 deletions js-src/06-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
'use strict';

sf.createModal = function (config) {
sf.assert(config, 'createModal(config) requires a configuration object');
sf.assert(!config.footer || Array.isArray(config.footer), 'createModal(config.footer) must be an array');

var overlay = sf.el('div', { className: 'sf-modal-overlay' });
var dialog = sf.el('div', { className: 'sf-modal' });
var body = sf.el('div', { className: 'sf-modal-body' });
Expand Down
3 changes: 3 additions & 0 deletions js-src/07-tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
};

sf.createTabs = function (config) {
sf.assert(config, 'createTabs(config) requires a configuration object');
sf.assert(Array.isArray(config.tabs), 'createTabs(config.tabs) must be an array');

var container = sf.el('div', { className: 'sf-tabs-container' });
var tabsId = sf.uid('sf-tabs');

Expand Down
4 changes: 4 additions & 0 deletions js-src/08-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
'use strict';

sf.createTable = function (config) {
sf.assert(config, 'createTable(config) requires a configuration object');
sf.assert(!config.columns || Array.isArray(config.columns), 'createTable(config.columns) must be an array');
sf.assert(!config.rows || Array.isArray(config.rows), 'createTable(config.rows) must be an array');

var wrapper = sf.el('div', { className: 'sf-table-container' });
var table = sf.el('table', { className: 'sf-table' });

Expand Down
2 changes: 2 additions & 0 deletions js-src/09-toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
}

sf.showToast = function (config) {
sf.assert(config, 'showToast(config) requires a configuration object');

ensureContainer();

var variant = config.variant || 'danger';
Expand Down
5 changes: 5 additions & 0 deletions js-src/10-backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
'use strict';

sf.createBackend = function (config) {
config = config || {};
var type = config.type || 'axum';
if (type === 'tauri') return createTauriBackend(config);
return createHttpBackend(config);
Expand Down Expand Up @@ -97,6 +98,10 @@
/* ── Tauri IPC backend ── */

function createTauriBackend(config) {
sf.assert(typeof config === 'object', 'createBackend({}) is required for Tauri adapter');
sf.assert(typeof config.invoke === 'function', 'Tauri backend requires config.invoke');
sf.assert(typeof config.listen === 'function', 'Tauri backend requires config.listen');

var invoke = config.invoke;
var listen = config.listen;
var commands = config.commands || {};
Expand Down
10 changes: 10 additions & 0 deletions js-src/11-solver.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
'use strict';

sf.createSolver = function (config) {
sf.assert(config, 'createSolver(config) requires a configuration object');
sf.assert(config.backend, 'createSolver(config.backend) is required');
sf.assert(config.backend.createSchedule && typeof config.backend.createSchedule === 'function', 'createSolver(config.backend.createSchedule) must be a function');
sf.assert(config.backend.streamEvents && typeof config.backend.streamEvents === 'function', 'createSolver(config.backend.streamEvents) must be a function');
sf.assert(config.backend.getSchedule && typeof config.backend.getSchedule === 'function', 'createSolver(config.backend.getSchedule) must be a function');
sf.assert(!config.onUpdate || typeof config.onUpdate === 'function', 'createSolver(config.onUpdate) must be a function');
sf.assert(!config.onComplete || typeof config.onComplete === 'function', 'createSolver(config.onComplete) must be a function');
sf.assert(!config.onAnalysis || typeof config.onAnalysis === 'function', 'createSolver(config.onAnalysis) must be a function');
sf.assert(!config.onError || typeof config.onError === 'function', 'createSolver(config.onError) must be a function');

var backend = config.backend;
var statusBar = config.statusBar;
var closeStream = null;
Expand Down
7 changes: 6 additions & 1 deletion js-src/12-api-guide.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
'use strict';

sf.createApiGuide = function (config) {
sf.assert(config, 'createApiGuide(config) requires a configuration object');
sf.assert(Array.isArray(config.endpoints), 'createApiGuide(config.endpoints) must be an array');

var guide = sf.el('div', { className: 'sf-api-guide' });
var endpoints = config.endpoints || [];
var endpoints = config.endpoints;

endpoints.forEach(function (ep) {
var section = sf.el('div', { className: 'sf-api-section' });
Expand Down Expand Up @@ -40,6 +43,8 @@
};

sf.createFooter = function (config) {
sf.assert(config, 'createFooter(config) requires a configuration object');

var footer = sf.el('footer', { className: 'sf-footer' });
if (config.links) {
config.links.forEach(function (link, i) {
Expand Down
13 changes: 13 additions & 0 deletions js-src/13-rail.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
sf.rail = {};

sf.rail.createHeader = function (config) {
sf.assert(config, 'createHeader(config) requires a configuration object');
sf.assert(!config.columns || Array.isArray(config.columns), 'createHeader(config.columns) expects an array');

var labelWidth = config.labelWidth || 200;
var columns = config.columns || [];

Expand All @@ -32,6 +35,8 @@
};

sf.rail.createCard = function (config) {
sf.assert(config, 'createCard(config) requires a configuration object');

var labelWidth = config.labelWidth || 200;
var card = sf.el('div', { className: 'sf-resource-card' });

Expand Down Expand Up @@ -136,6 +141,10 @@
};

sf.rail.addBlock = function (rail, config) {
sf.assert(rail, 'addBlock(rail) requires a rail element');
sf.assert(config && config.horizon != null, 'addBlock(config.horizon) is required');
sf.assert(config.start != null && config.end != null, 'addBlock(config.start/config.end) are required');

var horizon = config.horizon || 1;
var startPct = (config.start / horizon) * 100;
var widthPct = ((config.end - config.start) / horizon) * 100;
Expand Down Expand Up @@ -175,6 +184,10 @@
};

sf.rail.addChangeover = function (rail, config) {
sf.assert(rail, 'addChangeover(rail) requires a rail element');
sf.assert(config && config.horizon != null, 'addChangeover(config.horizon) is required');
sf.assert(config.start != null && config.end != null, 'addChangeover(config.start/config.end) are required');

var horizon = config.horizon || 1;
var startPct = (config.start / horizon) * 100;
var widthPct = ((config.end - config.start) / horizon) * 100;
Expand Down
4 changes: 4 additions & 0 deletions js-src/14-gantt.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
sf.gantt = {};

sf.gantt.create = function (config) {
config = config || {};
var instanceId = sf.uid('sf-gantt');
var chartPaneId = config.chartPane || (instanceId + '-chart-pane');
var gridPaneId = config.gridPane || (instanceId + '-grid-pane');
Expand Down Expand Up @@ -78,12 +79,15 @@
var ctrl = { el: wrapper };

ctrl.mount = function (parent) {
sf.assert(parent, 'gantt.mount(parent) requires a mount target');
var target = typeof parent === 'string' ? document.getElementById(parent) : parent;
sf.assert(target, 'gantt.mount(parent) target not found: ' + parent);
target.appendChild(wrapper);
initSplit();
};

ctrl.setTasks = function (newTasks) {
sf.assert(Array.isArray(newTasks), 'gantt.setTasks(tasks) expects an array');
tasks = newTasks;
renderGrid(newTasks);
renderChart(newTasks);
Expand Down
Loading
Loading