Fix bricks framework API usage and file structure
- Move all JS files from wwwroot/scripts/ to wwwroot/ root directory to comply with ahserver requirements - Fix component registration: use bricks.Factory.register() instead of bricks.register() - Fix function registration: use bricks.RF.register() instead of bricks.registerFunction() - Update UI files to use item_template_url with external templates for List components - Add proper list item template files (session-list-item.ui, service-list-item.ui, model-list-item.ui) - Ensure all custom components and functions use correct bricks framework API
This commit is contained in:
parent
34949ea16c
commit
3edfa140e9
106
wwwroot/list-component.js
Normal file
106
wwwroot/list-component.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Simplified List component using urlwidget pattern
|
||||||
|
// This approach follows the bricks-framework best practices by delegating item rendering to separate .ui files
|
||||||
|
|
||||||
|
bricks.List = class extends bricks.VBox {
|
||||||
|
constructor(opts) {
|
||||||
|
super(opts);
|
||||||
|
this.data_url = opts.data_url || null;
|
||||||
|
this.items = opts.items || [];
|
||||||
|
this.item_template_url = opts.item_template_url || null; // URL to the item template .ui file
|
||||||
|
this.itemHeight = opts.itemHeight || 50;
|
||||||
|
this._loading = false;
|
||||||
|
|
||||||
|
// Set default dimensions
|
||||||
|
if (!this.options.width) this.options.width = '100%';
|
||||||
|
if (!this.options.height) this.options.height = '100%';
|
||||||
|
|
||||||
|
// Load data if provided
|
||||||
|
if (this.data_url) {
|
||||||
|
this.loadData();
|
||||||
|
} else if (this.items.length > 0 && this.item_template_url) {
|
||||||
|
this.renderItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadData() {
|
||||||
|
if (this._loading || !this.data_url) return;
|
||||||
|
this._loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(this.data_url);
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
this.items = Array.isArray(data) ? data : (data.items || []);
|
||||||
|
this.renderItems();
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load list data:', response.status);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading list data:', error);
|
||||||
|
} finally {
|
||||||
|
this._loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItems() {
|
||||||
|
// Clear existing children
|
||||||
|
this.subwidgets = [];
|
||||||
|
this.children.forEach(child => child.remove());
|
||||||
|
this.children = [];
|
||||||
|
|
||||||
|
// Render each item using urlwidget to load the item template
|
||||||
|
this.items.forEach((item, index) => {
|
||||||
|
const itemContainer = new bricks.VBox({
|
||||||
|
width: '100%',
|
||||||
|
height: this.itemHeight + 'px'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store item data on the container for reference
|
||||||
|
itemContainer._listItemData = item;
|
||||||
|
itemContainer._listItemIndex = index;
|
||||||
|
|
||||||
|
// Create urlwidget binding to load the item template
|
||||||
|
if (!itemContainer.binds) {
|
||||||
|
itemContainer.binds = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
itemContainer.binds.push({
|
||||||
|
wid: 'self',
|
||||||
|
event: 'on_parent',
|
||||||
|
actiontype: 'urlwidget',
|
||||||
|
target: 'self',
|
||||||
|
options: {
|
||||||
|
url: this.item_template_url,
|
||||||
|
params: {
|
||||||
|
item: item,
|
||||||
|
index: index,
|
||||||
|
id: 'item_' + index
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mode: 'replace'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.appendChild(itemContainer);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public method to reload data
|
||||||
|
reload() {
|
||||||
|
if (this.data_url) {
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public method to set items directly
|
||||||
|
setItems(items) {
|
||||||
|
this.items = items || [];
|
||||||
|
this.renderItems();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register the List component
|
||||||
|
bricks.Factory.register('List', bricks.List);
|
||||||
|
|
||||||
|
console.log('List component registered - uses urlwidget pattern for item rendering');
|
||||||
46
wwwroot/list-item-template.ui
Normal file
46
wwwroot/list-item-template.ui
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "HBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "50px",
|
||||||
|
"backgroundColor": "{{ '#22C55E' if item.status == 'Connected' else '#EF4444' }}",
|
||||||
|
"padding": "8px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.name}}",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": "bold"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Filler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Details",
|
||||||
|
"backgroundColor": "#3B82F6",
|
||||||
|
"color": "#FFFFFF"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "urlwidget",
|
||||||
|
"target": "app.main-content",
|
||||||
|
"options": {
|
||||||
|
"url": "{{entire_url('service-detail.ui')}}",
|
||||||
|
"params": {
|
||||||
|
"service_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "replace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
93
wwwroot/model-list-item.ui
Normal file
93
wwwroot/model-list-item.ui
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"padding": "16px",
|
||||||
|
"border": "1px solid #334155",
|
||||||
|
"borderRadius": "8px",
|
||||||
|
"bgcolor": "#1E293B",
|
||||||
|
"marginBottom": "12px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "UiStr",
|
||||||
|
"options": {
|
||||||
|
"name": "model-name",
|
||||||
|
"label": "Model Name",
|
||||||
|
"value": "{{item.name}}",
|
||||||
|
"width": "100%",
|
||||||
|
"marginBottom": "8px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "UiStr",
|
||||||
|
"options": {
|
||||||
|
"name": "provider",
|
||||||
|
"label": "Provider",
|
||||||
|
"value": "{{item.provider}}",
|
||||||
|
"width": "100%",
|
||||||
|
"marginBottom": "8px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "HBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"gap": "12px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Update",
|
||||||
|
"bgcolor": "#3B82F6",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"border": "none",
|
||||||
|
"borderRadius": "4px",
|
||||||
|
"padding": "6px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "registerfunction",
|
||||||
|
"target": "self",
|
||||||
|
"rfname": "update_model",
|
||||||
|
"params": {
|
||||||
|
"model_id": "{{item.id}}",
|
||||||
|
"model_name": "{{item.name}}",
|
||||||
|
"model_provider": "{{item.provider}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Remove",
|
||||||
|
"bgcolor": "#EF4444",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"border": "none",
|
||||||
|
"borderRadius": "4px",
|
||||||
|
"padding": "6px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "registerfunction",
|
||||||
|
"target": "self",
|
||||||
|
"rfname": "remove_model",
|
||||||
|
"params": {
|
||||||
|
"model_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,149 +0,0 @@
|
|||||||
// Custom List component for bricks-framework
|
|
||||||
// This component renders a list of items with custom item templates
|
|
||||||
|
|
||||||
bricks.List = class extends bricks.VBox {
|
|
||||||
constructor(opts) {
|
|
||||||
super(opts);
|
|
||||||
this.data_url = opts.data_url || null;
|
|
||||||
this.items = opts.items || [];
|
|
||||||
this.itemHeight = opts.itemHeight || 50;
|
|
||||||
this._loading = false;
|
|
||||||
|
|
||||||
// Set default dimensions if not provided
|
|
||||||
if (!this.options.width) this.options.width = '100%';
|
|
||||||
if (!this.options.height) this.options.height = '100%';
|
|
||||||
|
|
||||||
// Load data if data_url is provided
|
|
||||||
if (this.data_url) {
|
|
||||||
this.loadData();
|
|
||||||
} else if (this.items.length > 0) {
|
|
||||||
this.renderItems();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async loadData() {
|
|
||||||
if (this._loading || !this.data_url) return;
|
|
||||||
this._loading = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(this.data_url);
|
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
this.items = Array.isArray(data) ? data : (data.items || []);
|
|
||||||
this.renderItems();
|
|
||||||
} else {
|
|
||||||
console.error('Failed to load list data:', response.status);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error loading list data:', error);
|
|
||||||
} finally {
|
|
||||||
this._loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderItems() {
|
|
||||||
// Clear existing children
|
|
||||||
this.subwidgets = [];
|
|
||||||
this.children = [];
|
|
||||||
|
|
||||||
// Render each item using the template defined in subwidgets
|
|
||||||
this.items.forEach((item, index) => {
|
|
||||||
const itemWidget = this.createItemWidget(item, index);
|
|
||||||
if (itemWidget) {
|
|
||||||
this.appendChild(itemWidget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Refresh the display
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
createItemWidget(itemData, index) {
|
|
||||||
if (!this.template || this.template.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone the template and process it with item data
|
|
||||||
const processedTemplate = this.processTemplate(this.template[0], itemData, index);
|
|
||||||
if (processedTemplate) {
|
|
||||||
const widget = bricks.Factory.create(processedTemplate);
|
|
||||||
if (widget) {
|
|
||||||
// Store reference to item data for event handling
|
|
||||||
widget._listItemData = itemData;
|
|
||||||
widget._listItemIndex = index;
|
|
||||||
return widget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
processTemplate(template, itemData, index) {
|
|
||||||
// This is a simplified template processor
|
|
||||||
// In a real implementation, you would need proper Jinja2-like processing
|
|
||||||
const processed = JSON.parse(JSON.stringify(template));
|
|
||||||
|
|
||||||
// Process options recursively
|
|
||||||
this.processObject(processed, itemData, index);
|
|
||||||
|
|
||||||
return processed;
|
|
||||||
}
|
|
||||||
|
|
||||||
processObject(obj, itemData, index) {
|
|
||||||
if (typeof obj !== 'object' || obj === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key in obj) {
|
|
||||||
if (typeof obj[key] === 'string') {
|
|
||||||
// Simple string replacement for {{item.xxx}} patterns
|
|
||||||
if (obj[key].includes('{{item.')) {
|
|
||||||
const match = obj[key].match(/{{item\.([^}]+)}}/);
|
|
||||||
if (match && match[1]) {
|
|
||||||
const fieldName = match[1];
|
|
||||||
obj[key] = obj[key].replace(`{{item.${fieldName}}}`, itemData[fieldName] || '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Handle conditional expressions like {{ '#22C55E' if item.status == 'Connected' else '#EF4444' }}
|
|
||||||
if (obj[key].includes('{{ ') && obj[key].includes(' if item.')) {
|
|
||||||
const fullMatch = obj[key].match(/{{\s*(.*?)\s+if\s+item\.(\w+)\s*==\s*'([^']+)'\s+else\s+(.*?)\s*}}/);
|
|
||||||
if (fullMatch) {
|
|
||||||
const trueValue = fullMatch[1].trim().replace(/^['"]|['"]$/g, '');
|
|
||||||
const fieldName = fullMatch[2];
|
|
||||||
const conditionValue = fullMatch[3];
|
|
||||||
const falseValue = fullMatch[4].trim().replace(/^['"]|['"]$/g, '');
|
|
||||||
|
|
||||||
obj[key] = itemData[fieldName] === conditionValue ? trueValue : falseValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
||||||
this.processObject(obj[key], itemData, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public method to reload data
|
|
||||||
reload() {
|
|
||||||
if (this.data_url) {
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public method to set items directly
|
|
||||||
setItems(items) {
|
|
||||||
this.items = items || [];
|
|
||||||
this.renderItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override appendChild to capture the template
|
|
||||||
appendChild(widget) {
|
|
||||||
if (!this.template) {
|
|
||||||
this.template = this.subwidgets || [];
|
|
||||||
}
|
|
||||||
super.appendChild(widget);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Register the List component
|
|
||||||
bricks.register('List', bricks.List);
|
|
||||||
|
|
||||||
console.log('Custom List component registered with bricks framework');
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
// Register functions for settings management
|
|
||||||
bricks.registerFunction('save_general_settings', async function(params) {
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('default-model', params.default_model);
|
|
||||||
formData.append('session-timeout', params.session_timeout);
|
|
||||||
formData.append('auto-save', params.auto_save);
|
|
||||||
|
|
||||||
const response = await fetch('/hermes-web-cli/settings/save/general/', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
bricks.showMessage('General settings saved successfully', 'success');
|
|
||||||
} else {
|
|
||||||
bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
bricks.showMessage('Network error: ' + error.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bricks.registerFunction('save_security_settings', async function(params) {
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('require-auth', params.require_auth);
|
|
||||||
formData.append('encrypt-storage', params.encrypt_storage);
|
|
||||||
|
|
||||||
const response = await fetch('/hermes-web-cli/settings/save/security/', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
bricks.showMessage('Security settings saved successfully', 'success');
|
|
||||||
} else {
|
|
||||||
bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
bricks.showMessage('Network error: ' + error.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bricks.registerFunction('save_appearance_settings', async function(params) {
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('theme-select', params.theme);
|
|
||||||
|
|
||||||
const response = await fetch('/hermes-web-cli/settings/save/appearance/', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
bricks.showMessage('Appearance settings saved successfully', 'success');
|
|
||||||
// Apply theme change
|
|
||||||
document.body.className = params.theme;
|
|
||||||
} else {
|
|
||||||
bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
bricks.showMessage('Network error: ' + error.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register functions for models management
|
|
||||||
bricks.registerFunction('add_model', async function(params) {
|
|
||||||
// Navigate to add model page
|
|
||||||
const mainContent = bricks.getWidget('app.main-content');
|
|
||||||
if (mainContent) {
|
|
||||||
mainContent.loadURL(bricks.entire_url('add_model.ui'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bricks.registerFunction('update_model', async function(params) {
|
|
||||||
try {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append('model_id', params.model_id);
|
|
||||||
formData.append('model_name', params.model_name);
|
|
||||||
formData.append('model_provider', params.model_provider);
|
|
||||||
|
|
||||||
const response = await fetch('/hermes-web-cli/models/update/', {
|
|
||||||
method: 'POST',
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
bricks.showMessage('Model updated successfully', 'success');
|
|
||||||
// Refresh the models list if needed
|
|
||||||
} else {
|
|
||||||
bricks.showMessage(result.error || 'Failed to update model', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
bricks.showMessage('Network error: ' + error.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bricks.registerFunction('remove_model', async function(params) {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/hermes-web-cli/models/remove/?id=' + params.model_id);
|
|
||||||
const result = await response.json();
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
bricks.showMessage('Model removed successfully', 'success');
|
|
||||||
// Refresh the models list
|
|
||||||
const modelsList = bricks.getWidget('models-list');
|
|
||||||
if (modelsList) {
|
|
||||||
modelsList.reload();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bricks.showMessage(result.error || 'Failed to remove model', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
bricks.showMessage('Network error: ' + error.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
139
wwwroot/service-list-item.ui
Normal file
139
wwwroot/service-list-item.ui
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"padding": "16px",
|
||||||
|
"border": "1px solid #334155",
|
||||||
|
"borderRadius": "8px",
|
||||||
|
"bgcolor": "#1E293B"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "HBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"alignItems": "center",
|
||||||
|
"marginBottom": "8px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.name}}",
|
||||||
|
"fontSize": "18px",
|
||||||
|
"fontWeight": "600",
|
||||||
|
"color": "#F8FAFC"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Filler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Badge",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.status}}",
|
||||||
|
"bgcolor": "{{ '#22C55E' if item.status == 'Connected' else '#EF4444' }}",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"borderRadius": "12px",
|
||||||
|
"padding": "4px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.endpoint}}",
|
||||||
|
"fontSize": "14px",
|
||||||
|
"color": "#CBD5E1",
|
||||||
|
"marginBottom": "8px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "HBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"gap": "12px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Edit",
|
||||||
|
"bgcolor": "#3B82F6",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"border": "none",
|
||||||
|
"borderRadius": "4px",
|
||||||
|
"padding": "6px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "urlwidget",
|
||||||
|
"target": "app.main-content",
|
||||||
|
"options": {
|
||||||
|
"url": "{{entire_url('edit_service.ui')}}",
|
||||||
|
"params": {
|
||||||
|
"service_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "replace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Remove",
|
||||||
|
"bgcolor": "#EF4444",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"border": "none",
|
||||||
|
"borderRadius": "4px",
|
||||||
|
"padding": "6px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "registerfunction",
|
||||||
|
"target": "self",
|
||||||
|
"rfname": "remove_service",
|
||||||
|
"params": {
|
||||||
|
"service_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Button",
|
||||||
|
"options": {
|
||||||
|
"label": "Test Connection",
|
||||||
|
"bgcolor": "#8B5CF6",
|
||||||
|
"color": "#FFFFFF",
|
||||||
|
"border": "none",
|
||||||
|
"borderRadius": "4px",
|
||||||
|
"padding": "6px 12px",
|
||||||
|
"fontSize": "12px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "registerfunction",
|
||||||
|
"target": "self",
|
||||||
|
"rfname": "test_service_connection",
|
||||||
|
"params": {
|
||||||
|
"service_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// Register functions for services management
|
// Register functions for services management
|
||||||
bricks.registerFunction('remove_service', async function(params) {
|
bricks.RF.register('remove_service', async function(params) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/hermes-web-cli/services/remove/?id=' + params.service_id);
|
const response = await fetch('/hermes-web-cli/services/remove/?id=' + params.service_id);
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
@ -19,7 +19,7 @@ bricks.registerFunction('remove_service', async function(params) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bricks.registerFunction('test_service_connection', async function(params) {
|
bricks.RF.register('test_service_connection', async function(params) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/hermes-web-cli/services/test/?id=' + params.service_id);
|
const response = await fetch('/hermes-web-cli/services/test/?id=' + params.service_id);
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
@ -70,146 +70,9 @@
|
|||||||
"width": "100%",
|
"width": "100%",
|
||||||
"height": "calc(100% - 100px)",
|
"height": "calc(100% - 100px)",
|
||||||
"itemHeight": "100px",
|
"itemHeight": "100px",
|
||||||
"data_url": "/hermes-web-cli/services/list/"
|
"data_url": "/hermes-web-cli/services/list/",
|
||||||
},
|
"item_template_url": "{{entire_url('service-list-item.ui')}}"
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px",
|
|
||||||
"border": "1px solid #334155",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"bgcolor": "#1E293B"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "HBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"alignItems": "center",
|
|
||||||
"marginBottom": "8px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.name}}",
|
|
||||||
"fontSize": "18px",
|
|
||||||
"fontWeight": "600",
|
|
||||||
"color": "#F8FAFC"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Filler"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Badge",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.status}}",
|
|
||||||
"bgcolor": "{{ '#22C55E' if item.status == 'Connected' else '#EF4444' }}",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"borderRadius": "12px",
|
|
||||||
"padding": "4px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.endpoint}}",
|
|
||||||
"fontSize": "14px",
|
|
||||||
"color": "#CBD5E1",
|
|
||||||
"marginBottom": "8px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "HBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"gap": "12px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {
|
|
||||||
"label": "Edit",
|
|
||||||
"bgcolor": "#3B82F6",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"border": "none",
|
|
||||||
"borderRadius": "4px",
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
},
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.main-content",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('edit_service.ui?id={{item.id}}')}}"
|
|
||||||
},
|
|
||||||
"mode": "replace"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {
|
|
||||||
"label": "Remove",
|
|
||||||
"bgcolor": "#EF4444",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"border": "none",
|
|
||||||
"borderRadius": "4px",
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
},
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "registerfunction",
|
|
||||||
"target": "self",
|
|
||||||
"rfname": "remove_service",
|
|
||||||
"params": {
|
|
||||||
"service_id": "{{item.id}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {
|
|
||||||
"label": "Test Connection",
|
|
||||||
"bgcolor": "#8B5CF6",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"border": "none",
|
|
||||||
"borderRadius": "4px",
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
},
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "registerfunction",
|
|
||||||
"target": "self",
|
|
||||||
"rfname": "test_service_connection",
|
|
||||||
"params": {
|
|
||||||
"service_id": "{{item.id}}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
67
wwwroot/session-list-item.ui
Normal file
67
wwwroot/session-list-item.ui
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"padding": "12px",
|
||||||
|
"border": "1px solid #334155",
|
||||||
|
"borderRadius": "8px",
|
||||||
|
"bgcolor": "#1E293B",
|
||||||
|
"cursor": "pointer"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "HBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"alignItems": "center"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.name}}",
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": "600",
|
||||||
|
"color": "#F8FAFC"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Filler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.last_active}}",
|
||||||
|
"fontSize": "12px",
|
||||||
|
"color": "#94A3B8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "{{item.model}}",
|
||||||
|
"fontSize": "14px",
|
||||||
|
"color": "#CBD5E1",
|
||||||
|
"marginTop": "4px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "click",
|
||||||
|
"actiontype": "urlwidget",
|
||||||
|
"target": "app.main-content",
|
||||||
|
"options": {
|
||||||
|
"url": "{{entire_url('session_detail.ui')}}",
|
||||||
|
"params": {
|
||||||
|
"session_id": "{{item.id}}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode": "replace"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -70,74 +70,9 @@
|
|||||||
"width": "100%",
|
"width": "100%",
|
||||||
"height": "calc(100% - 100px)",
|
"height": "calc(100% - 100px)",
|
||||||
"itemHeight": "80px",
|
"itemHeight": "80px",
|
||||||
"data_url": "/hermes-web-cli/sessions/list/"
|
"data_url": "/hermes-web-cli/sessions/list/",
|
||||||
},
|
"item_template_url": "{{entire_url('session-list-item.ui')}}"
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "12px",
|
|
||||||
"border": "1px solid #334155",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"bgcolor": "#1E293B",
|
|
||||||
"cursor": "pointer"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "HBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"alignItems": "center"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.name}}",
|
|
||||||
"fontSize": "16px",
|
|
||||||
"fontWeight": "600",
|
|
||||||
"color": "#F8FAFC"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Filler"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.last_active}}",
|
|
||||||
"fontSize": "12px",
|
|
||||||
"color": "#94A3B8"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "{{item.model}}",
|
|
||||||
"fontSize": "14px",
|
|
||||||
"color": "#CBD5E1",
|
|
||||||
"marginTop": "4px"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.main-content",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('session_detail.ui?id={{item.id}}')}}"
|
|
||||||
},
|
|
||||||
"mode": "replace"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
121
wwwroot/settings.js
Normal file
121
wwwroot/settings.js
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
1|// Register functions for settings management
|
||||||
|
2|bricks.RF.register('save_general_settings', async function(params) {
|
||||||
|
3| try {
|
||||||
|
4| const formData = new FormData();
|
||||||
|
5| formData.append('default-model', params.default_model);
|
||||||
|
6| formData.append('session-timeout', params.session_timeout);
|
||||||
|
7| formData.append('auto-save', params.auto_save);
|
||||||
|
8|
|
||||||
|
9| const response = await fetch('/hermes-web-cli/settings/save/general/', {
|
||||||
|
10| method: 'POST',
|
||||||
|
11| body: formData
|
||||||
|
12| });
|
||||||
|
13| const result = await response.json();
|
||||||
|
14|
|
||||||
|
15| if (result.success) {
|
||||||
|
16| bricks.showMessage('General settings saved successfully', 'success');
|
||||||
|
17| } else {
|
||||||
|
18| bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
||||||
|
19| }
|
||||||
|
20| } catch (error) {
|
||||||
|
21| bricks.showMessage('Network error: ' + error.message, 'error');
|
||||||
|
22| }
|
||||||
|
23|});
|
||||||
|
24|
|
||||||
|
25|bricks.RF.register('save_security_settings', async function(params) {
|
||||||
|
26| try {
|
||||||
|
27| const formData = new FormData();
|
||||||
|
28| formData.append('require-auth', params.require_auth);
|
||||||
|
29| formData.append('encrypt-storage', params.encrypt_storage);
|
||||||
|
30|
|
||||||
|
31| const response = await fetch('/hermes-web-cli/settings/save/security/', {
|
||||||
|
32| method: 'POST',
|
||||||
|
33| body: formData
|
||||||
|
34| });
|
||||||
|
35| const result = await response.json();
|
||||||
|
36|
|
||||||
|
37| if (result.success) {
|
||||||
|
38| bricks.showMessage('Security settings saved successfully', 'success');
|
||||||
|
39| } else {
|
||||||
|
40| bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
||||||
|
41| }
|
||||||
|
42| } catch (error) {
|
||||||
|
43| bricks.showMessage('Network error: ' + error.message, 'error');
|
||||||
|
44| }
|
||||||
|
45|});
|
||||||
|
46|
|
||||||
|
47|bricks.RF.register('save_appearance_settings', async function(params) {
|
||||||
|
48| try {
|
||||||
|
49| const formData = new FormData();
|
||||||
|
50| formData.append('theme-select', params.theme);
|
||||||
|
51|
|
||||||
|
52| const response = await fetch('/hermes-web-cli/settings/save/appearance/', {
|
||||||
|
53| method: 'POST',
|
||||||
|
54| body: formData
|
||||||
|
55| });
|
||||||
|
56| const result = await response.json();
|
||||||
|
57|
|
||||||
|
58| if (result.success) {
|
||||||
|
59| bricks.showMessage('Appearance settings saved successfully', 'success');
|
||||||
|
60| // Apply theme change
|
||||||
|
61| document.body.className = params.theme;
|
||||||
|
62| } else {
|
||||||
|
63| bricks.showMessage(result.error || 'Failed to save settings', 'error');
|
||||||
|
64| }
|
||||||
|
65| } catch (error) {
|
||||||
|
66| bricks.showMessage('Network error: ' + error.message, 'error');
|
||||||
|
67| }
|
||||||
|
68|});
|
||||||
|
69|
|
||||||
|
70|// Register functions for models management
|
||||||
|
71|bricks.RF.register('add_model', async function(params) {
|
||||||
|
72| // Navigate to add model page
|
||||||
|
73| const mainContent = bricks.getWidget('app.main-content');
|
||||||
|
74| if (mainContent) {
|
||||||
|
75| mainContent.loadURL(bricks.entire_url('add_model.ui'));
|
||||||
|
76| }
|
||||||
|
77|});
|
||||||
|
78|
|
||||||
|
79|bricks.RF.register('update_model', async function(params) {
|
||||||
|
80| try {
|
||||||
|
81| const formData = new FormData();
|
||||||
|
82| formData.append('model_id', params.model_id);
|
||||||
|
83| formData.append('model_name', params.model_name);
|
||||||
|
84| formData.append('model_provider', params.model_provider);
|
||||||
|
85|
|
||||||
|
86| const response = await fetch('/hermes-web-cli/models/update/', {
|
||||||
|
87| method: 'POST',
|
||||||
|
88| body: formData
|
||||||
|
89| });
|
||||||
|
90| const result = await response.json();
|
||||||
|
91|
|
||||||
|
92| if (result.success) {
|
||||||
|
93| bricks.showMessage('Model updated successfully', 'success');
|
||||||
|
94| // Refresh the models list if needed
|
||||||
|
95| } else {
|
||||||
|
96| bricks.showMessage(result.error || 'Failed to update model', 'error');
|
||||||
|
97| }
|
||||||
|
98| } catch (error) {
|
||||||
|
99| bricks.showMessage('Network error: ' + error.message, 'error');
|
||||||
|
100| }
|
||||||
|
101|});
|
||||||
|
102|
|
||||||
|
103|bricks.RF.register('remove_model', async function(params) {
|
||||||
|
104| try {
|
||||||
|
105| const response = await fetch('/hermes-web-cli/models/remove/?id=' + params.model_id);
|
||||||
|
106| const result = await response.json();
|
||||||
|
107|
|
||||||
|
108| if (result.success) {
|
||||||
|
109| bricks.showMessage('Model removed successfully', 'success');
|
||||||
|
110| // Refresh the models list
|
||||||
|
111| const modelsList = bricks.getWidget('models-list');
|
||||||
|
112| if (modelsList) {
|
||||||
|
113| modelsList.reload();
|
||||||
|
114| }
|
||||||
|
115| } else {
|
||||||
|
116| bricks.showMessage(result.error || 'Failed to remove model', 'error');
|
||||||
|
117| }
|
||||||
|
118| } catch (error) {
|
||||||
|
119| bricks.showMessage('Network error: ' + error.message, 'error');
|
||||||
|
120| }
|
||||||
|
121|});
|
||||||
@ -146,104 +146,10 @@
|
|||||||
"width": "100%",
|
"width": "100%",
|
||||||
"height": "calc(100% - 80px)",
|
"height": "calc(100% - 80px)",
|
||||||
"itemHeight": "120px",
|
"itemHeight": "120px",
|
||||||
"items": []
|
"data_url": "/hermes-web-cli/models/list/",
|
||||||
},
|
"item_template_url": "{{entire_url('model-list-item.ui')}}"
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px",
|
|
||||||
"border": "1px solid #334155",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"bgcolor": "#1E293B",
|
|
||||||
"marginBottom": "12px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "UiStr",
|
|
||||||
"options": {
|
|
||||||
"name": "model-name",
|
|
||||||
"label": "Model Name",
|
|
||||||
"value": "{{data.name}}",
|
|
||||||
"width": "100%",
|
|
||||||
"marginBottom": "8px"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"widgettype": "UiStr",
|
|
||||||
"options": {
|
|
||||||
"name": "provider",
|
|
||||||
"label": "Provider",
|
|
||||||
"value": "{{data.provider}}",
|
|
||||||
"width": "100%",
|
|
||||||
"marginBottom": "8px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "HBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"gap": "12px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {
|
|
||||||
"label": "Update",
|
|
||||||
"bgcolor": "#3B82F6",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"border": "none",
|
|
||||||
"borderRadius": "4px",
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
},
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "registerfunction",
|
|
||||||
"target": "self",
|
|
||||||
"rfname": "update_model",
|
|
||||||
"params": {
|
|
||||||
"model_id": "{{data.id}}",
|
|
||||||
"model_name": "{{data.name}}",
|
|
||||||
"model_provider": "{{data.provider}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Button",
|
|
||||||
"options": {
|
|
||||||
"label": "Remove",
|
|
||||||
"bgcolor": "#EF4444",
|
|
||||||
"color": "#FFFFFF",
|
|
||||||
"border": "none",
|
|
||||||
"borderRadius": "4px",
|
|
||||||
"padding": "6px 12px",
|
|
||||||
"fontSize": "12px"
|
|
||||||
},
|
|
||||||
"binds": [
|
|
||||||
{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "registerfunction",
|
|
||||||
"target": "self",
|
|
||||||
"rfname": "remove_model",
|
|
||||||
"params": {
|
|
||||||
"model_id": "{{data.id}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"widgettype": "Button",
|
"widgettype": "Button",
|
||||||
"options": {
|
"options": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user