alchemy-chimera 1.3.0-alpha.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/CLAUDE.md +297 -0
- package/assets/scripts/chimera/chimera.js +12 -0
- package/assets/stylesheets/chimera/chimera.scss +308 -0
- package/config/routes.js +38 -0
- package/controller/00-chimera_controller.js +36 -6
- package/controller/chimera_editor_controller.js +53 -9
- package/controller/chimera_settings_controller.js +1 -0
- package/controller/chimera_static_controller.js +163 -2
- package/controller/system_task_controller.js +224 -0
- package/element/chimera_dashboard_button.js +100 -0
- package/element/chimera_run_task_button.js +93 -0
- package/element/chimera_task_monitor.js +672 -0
- package/lib/chimera_config.js +94 -0
- package/lib/toolbar_buttons.js +78 -0
- package/model/00_chimera_model.js +11 -0
- package/model/chimera_dashboard_config_model.js +44 -0
- package/package.json +4 -4
- package/view/chimera/dashboard.hwk +4 -3
- package/view/chimera/editor/task_monitor.hwk +32 -0
- package/view/chimera/sidebar.hwk +0 -0
- package/view/chimera/toolbar/customize_dashboard_button.hwk +26 -0
- package/view/chimera/toolbar/monitor_button.hwk +8 -0
- package/view/chimera/toolbar/reset_dashboard_button.hwk +26 -0
- package/view/chimera/toolbar/run_task_button.hwk +25 -0
- package/view/elements/chimera_task_monitor.hwk +80 -0
- package/view/layouts/chimera_body.hwk +46 -4
package/lib/chimera_config.js
CHANGED
|
@@ -23,6 +23,100 @@ const Config = Function.inherits('Alchemy.Base', 'Alchemy.Chimera', function Con
|
|
|
23
23
|
this.record_preview = null;
|
|
24
24
|
this.record_preview_controller = null;
|
|
25
25
|
this.record_preview_action = null;
|
|
26
|
+
|
|
27
|
+
// Custom row actions for this model
|
|
28
|
+
this.row_actions = [];
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Add a custom row action for this model.
|
|
33
|
+
* Actions appear in the index table and context menu.
|
|
34
|
+
*
|
|
35
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
36
|
+
* @since 1.3.0
|
|
37
|
+
* @version 1.3.0
|
|
38
|
+
*
|
|
39
|
+
* @param {Object} config
|
|
40
|
+
* @param {String} config.name Machine name for the action
|
|
41
|
+
* @param {String} config.icon Icon name (FontAwesome)
|
|
42
|
+
* @param {String} config.title Display title
|
|
43
|
+
* @param {Array} config.placement Where to show: ['row', 'context']
|
|
44
|
+
* @param {String} config.route Route name (e.g., 'Controller#action')
|
|
45
|
+
* @param {Object} config.route_params Route parameters (use $pk for record primary key)
|
|
46
|
+
*
|
|
47
|
+
* @return {Object} The action config
|
|
48
|
+
*/
|
|
49
|
+
Config.setMethod(function addRowAction(config) {
|
|
50
|
+
|
|
51
|
+
if (!config || !config.name) {
|
|
52
|
+
throw new Error('Row action requires at least a name');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Set defaults
|
|
56
|
+
if (!config.placement) {
|
|
57
|
+
config.placement = ['row', 'context'];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.row_actions.push(config);
|
|
61
|
+
|
|
62
|
+
return config;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get all configured row actions for a specific record.
|
|
67
|
+
* This resolves route URLs using the record's primary key.
|
|
68
|
+
*
|
|
69
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
70
|
+
* @since 1.3.0
|
|
71
|
+
* @version 1.3.0
|
|
72
|
+
*
|
|
73
|
+
* @param {Document} record The record to create actions for
|
|
74
|
+
*
|
|
75
|
+
* @return {Array} Array of Form.Action instances
|
|
76
|
+
*/
|
|
77
|
+
Config.setMethod(function getRowActionsFor(record) {
|
|
78
|
+
|
|
79
|
+
let result = [];
|
|
80
|
+
|
|
81
|
+
for (let config of this.row_actions) {
|
|
82
|
+
let url;
|
|
83
|
+
|
|
84
|
+
if (config.route) {
|
|
85
|
+
// Build route parameters, replacing $pk with actual primary key
|
|
86
|
+
let params = {};
|
|
87
|
+
|
|
88
|
+
if (config.route_params) {
|
|
89
|
+
for (let key in config.route_params) {
|
|
90
|
+
let value = config.route_params[key];
|
|
91
|
+
|
|
92
|
+
if (value === '$pk') {
|
|
93
|
+
value = record.$pk;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
params[key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
url = alchemy.routeUrl(config.route, params);
|
|
101
|
+
|
|
102
|
+
if (!url) {
|
|
103
|
+
log.warn('Failed to generate URL for row action', config.name, 'with route', config.route);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let action = new Classes.Alchemy.Form.Action.Url({
|
|
109
|
+
name : config.name,
|
|
110
|
+
icon : config.icon,
|
|
111
|
+
title : config.title,
|
|
112
|
+
placement : config.placement,
|
|
113
|
+
url : url,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
result.push(action);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result;
|
|
26
120
|
});
|
|
27
121
|
|
|
28
122
|
/**
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register Chimera's toolbar buttons
|
|
3
|
+
*
|
|
4
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
* @version 0.3.0
|
|
7
|
+
*/
|
|
8
|
+
const EditorToolbarManager = Classes.Alchemy.Widget.EditorToolbarManager;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Register model-level buttons for Chimera
|
|
12
|
+
*
|
|
13
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
14
|
+
* @since 0.3.0
|
|
15
|
+
* @version 0.3.0
|
|
16
|
+
*
|
|
17
|
+
* @param {Alchemy.Widget.EditorToolbarManager} manager
|
|
18
|
+
* @param {string} model_name
|
|
19
|
+
*/
|
|
20
|
+
EditorToolbarManager.registerModelButtonProvider(function addChimeraModelButtons(manager, model_name) {
|
|
21
|
+
|
|
22
|
+
// Only add buttons in chimera scenario
|
|
23
|
+
if (manager.scenario != 'chimera') {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Add create button for all models
|
|
28
|
+
manager.addTemplateToRender('buttons', 'chimera/toolbar/create_button', {
|
|
29
|
+
model_name: model_name,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Register document-level buttons for Chimera
|
|
35
|
+
*
|
|
36
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
37
|
+
* @since 0.3.0
|
|
38
|
+
* @version 0.3.0
|
|
39
|
+
*
|
|
40
|
+
* @param {Alchemy.Widget.EditorToolbarManager} manager
|
|
41
|
+
* @param {Alchemy.Document} doc
|
|
42
|
+
* @param {Alchemy.Model} model
|
|
43
|
+
* @param {string} model_name
|
|
44
|
+
* @param {*} pk_val
|
|
45
|
+
*/
|
|
46
|
+
EditorToolbarManager.registerDocumentButtonProvider(function addChimeraDocumentButtons(manager, doc, model, model_name, pk_val) {
|
|
47
|
+
|
|
48
|
+
// Edit in Chimera button (for non-chimera scenarios)
|
|
49
|
+
if (manager.scenario != 'chimera') {
|
|
50
|
+
manager.addTemplateToRender('buttons', 'chimera/toolbar/edit_in_chimera_button', {
|
|
51
|
+
model_name: model_name.underscore(),
|
|
52
|
+
record_pk: pk_val,
|
|
53
|
+
});
|
|
54
|
+
return; // No other buttons for non-chimera
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Preview button (chimera scenario only)
|
|
58
|
+
if (model.chimera?.record_preview) {
|
|
59
|
+
manager.addTemplateToRender('buttons', 'chimera/toolbar/preview_button', {
|
|
60
|
+
model_name: model_name.underscore(),
|
|
61
|
+
record_pk: pk_val,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Run Task button for System.Task
|
|
66
|
+
if (model_name == 'System_Task' && doc.enabled && doc.type) {
|
|
67
|
+
manager.addTemplateToRender('buttons', 'chimera/toolbar/run_task_button', {
|
|
68
|
+
record_pk: pk_val,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Monitor button for System.TaskHistory
|
|
73
|
+
if (model_name == 'System_TaskHistory') {
|
|
74
|
+
manager.addTemplateToRender('buttons', 'chimera/toolbar/monitor_button', {
|
|
75
|
+
record_pk: pk_val,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base Chimera Model class
|
|
3
|
+
* Creates the Chimera model namespace
|
|
4
|
+
*
|
|
5
|
+
* @constructor
|
|
6
|
+
*
|
|
7
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
8
|
+
* @since 1.4.0
|
|
9
|
+
* @version 1.4.0
|
|
10
|
+
*/
|
|
11
|
+
const Chimera = Function.inherits('Alchemy.Model.App', 'Alchemy.Model.Chimera', 'Chimera');
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Chimera DashboardConfig Model
|
|
3
|
+
* Stores widget configurations for the Chimera dashboard
|
|
4
|
+
*
|
|
5
|
+
* @constructor
|
|
6
|
+
*
|
|
7
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
8
|
+
* @since 1.3.0
|
|
9
|
+
* @version 1.3.0
|
|
10
|
+
*/
|
|
11
|
+
const DashboardConfig = Function.inherits('Alchemy.Model.Chimera', 'DashboardConfig');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configure the schema
|
|
15
|
+
*
|
|
16
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
17
|
+
* @since 1.3.0
|
|
18
|
+
* @version 1.3.0
|
|
19
|
+
*/
|
|
20
|
+
DashboardConfig.constitute(function addFields() {
|
|
21
|
+
|
|
22
|
+
// Name of this dashboard configuration
|
|
23
|
+
this.addField('name', 'String', {
|
|
24
|
+
title: 'Name',
|
|
25
|
+
required: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// The widget configuration
|
|
29
|
+
this.addField('widgets', 'Widgets', {
|
|
30
|
+
title: 'Widgets',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Is this the default dashboard?
|
|
34
|
+
this.addField('is_default', 'Boolean', {
|
|
35
|
+
title: 'Default',
|
|
36
|
+
default: false,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Optional: belongs to a specific user for per-user dashboards
|
|
40
|
+
this.belongsTo('User', {
|
|
41
|
+
title: 'User',
|
|
42
|
+
description: 'If set, this is a user-specific dashboard',
|
|
43
|
+
});
|
|
44
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "alchemy-chimera",
|
|
3
3
|
"description": "Chimera plugin for Alchemy MVC",
|
|
4
|
-
"version": "1.3.0
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"author": "Jelle De Loecker <jelle@elevenways.be>",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"alchemy",
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
],
|
|
12
12
|
"repository": "11ways/alchemy-chimera",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"alchemy-acl" : "
|
|
14
|
+
"alchemy-acl" : ">=0.9.0||>=0.9.0-alpha",
|
|
15
15
|
"alchemymvc" : ">=1.4.0||>=1.4.0-alpha",
|
|
16
|
-
"alchemy-form" : "
|
|
17
|
-
"alchemy-widget" : "
|
|
16
|
+
"alchemy-form" : ">=0.3.0||>=0.3.0-alpha",
|
|
17
|
+
"alchemy-widget" : ">=0.3.0||>=0.3.0-alpha",
|
|
18
18
|
"alchemy-styleboost" : ">=0.5.0||>=0.5.0-alpha"
|
|
19
19
|
},
|
|
20
20
|
"license": "MIT",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{% include "layouts/chimera_basics" %}
|
|
2
|
+
|
|
3
|
+
{% block "page-actions" %}
|
|
4
|
+
{% if system_task %}
|
|
5
|
+
<a
|
|
6
|
+
!Route="Chimera.Editor#edit"
|
|
7
|
+
+model="System_Task"
|
|
8
|
+
+pk={% system_task.$pk %}
|
|
9
|
+
class="btn"
|
|
10
|
+
>
|
|
11
|
+
<al-icon icon-name="pencil"></al-icon>
|
|
12
|
+
{%t "edit-task" %}
|
|
13
|
+
</a>
|
|
14
|
+
{% /if %}
|
|
15
|
+
|
|
16
|
+
<a
|
|
17
|
+
!Route="Chimera.Editor#index"
|
|
18
|
+
+model="System_TaskHistory"
|
|
19
|
+
class="btn"
|
|
20
|
+
>
|
|
21
|
+
<al-icon icon-name="list"></al-icon>
|
|
22
|
+
{%t "task-history" %}
|
|
23
|
+
</a>
|
|
24
|
+
{% /block %}
|
|
25
|
+
|
|
26
|
+
{% block "main" %}
|
|
27
|
+
<chimera-task-monitor
|
|
28
|
+
task-history-id={% task_history_id %}
|
|
29
|
+
#history_doc={% history_doc %}
|
|
30
|
+
#system_task={% system_task %}
|
|
31
|
+
></chimera-task-monitor>
|
|
32
|
+
{% /block %}
|
package/view/chimera/sidebar.hwk
CHANGED
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<chimera-dashboard-button
|
|
2
|
+
class="btn btn-toolbar"
|
|
3
|
+
action="customize"
|
|
4
|
+
title="Create your personal dashboard"
|
|
5
|
+
state="default"
|
|
6
|
+
>
|
|
7
|
+
<al-state state-name="default">
|
|
8
|
+
<al-icon icon-name="user-pen"></al-icon>
|
|
9
|
+
{%t "customize" %}
|
|
10
|
+
</al-state>
|
|
11
|
+
|
|
12
|
+
<al-state state-name="busy">
|
|
13
|
+
<al-icon icon-name="spinner" icon-flags="spin"></al-icon>
|
|
14
|
+
{%t "working" %}
|
|
15
|
+
</al-state>
|
|
16
|
+
|
|
17
|
+
<al-state state-name="done">
|
|
18
|
+
<al-icon icon-name="badge-check" icon-flags="beat"></al-icon>
|
|
19
|
+
{%t "done" %}
|
|
20
|
+
</al-state>
|
|
21
|
+
|
|
22
|
+
<al-state state-name="error">
|
|
23
|
+
<al-icon icon-name="skull" icon-flags="shake"></al-icon>
|
|
24
|
+
{%t "error" %}
|
|
25
|
+
</al-state>
|
|
26
|
+
</chimera-dashboard-button>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<chimera-dashboard-button
|
|
2
|
+
class="btn btn-toolbar"
|
|
3
|
+
action="reset"
|
|
4
|
+
title="Reset to default dashboard"
|
|
5
|
+
state="default"
|
|
6
|
+
>
|
|
7
|
+
<al-state state-name="default">
|
|
8
|
+
<al-icon icon-name="rotate-left"></al-icon>
|
|
9
|
+
{%t "reset" %}
|
|
10
|
+
</al-state>
|
|
11
|
+
|
|
12
|
+
<al-state state-name="busy">
|
|
13
|
+
<al-icon icon-name="spinner" icon-flags="spin"></al-icon>
|
|
14
|
+
{%t "working" %}
|
|
15
|
+
</al-state>
|
|
16
|
+
|
|
17
|
+
<al-state state-name="done">
|
|
18
|
+
<al-icon icon-name="badge-check" icon-flags="beat"></al-icon>
|
|
19
|
+
{%t "done" %}
|
|
20
|
+
</al-state>
|
|
21
|
+
|
|
22
|
+
<al-state state-name="error">
|
|
23
|
+
<al-icon icon-name="skull" icon-flags="shake"></al-icon>
|
|
24
|
+
{%t "error" %}
|
|
25
|
+
</al-state>
|
|
26
|
+
</chimera-dashboard-button>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<chimera-run-task-button
|
|
2
|
+
class="btn btn-run-task"
|
|
3
|
+
task-id={% record_pk %}
|
|
4
|
+
state="default"
|
|
5
|
+
>
|
|
6
|
+
<al-state state-name="default">
|
|
7
|
+
<al-icon icon-style="duotone" icon-name="play"></al-icon>
|
|
8
|
+
{%t "run-task" %}
|
|
9
|
+
</al-state>
|
|
10
|
+
|
|
11
|
+
<al-state state-name="busy">
|
|
12
|
+
<al-icon icon-style="duotone" icon-name="spinner" icon-flags="spin"></al-icon>
|
|
13
|
+
{%t "starting" %}
|
|
14
|
+
</al-state>
|
|
15
|
+
|
|
16
|
+
<al-state state-name="done">
|
|
17
|
+
<al-icon icon-style="duotone" icon-name="badge-check" icon-flags="beat"></al-icon>
|
|
18
|
+
{%t "started" %}
|
|
19
|
+
</al-state>
|
|
20
|
+
|
|
21
|
+
<al-state state-name="error">
|
|
22
|
+
<al-icon icon-style="duotone" icon-name="skull" icon-flags="shake"></al-icon>
|
|
23
|
+
{%t "error" %}
|
|
24
|
+
</al-state>
|
|
25
|
+
</chimera-run-task-button>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<div class="task-monitor-container">
|
|
2
|
+
<div class="task-monitor-header">
|
|
3
|
+
<div class="task-info">
|
|
4
|
+
<h2 class="task-title">
|
|
5
|
+
{% if self.system_task %}
|
|
6
|
+
{{ self.system_task.title || self.history_doc.type }}
|
|
7
|
+
{% else %}
|
|
8
|
+
{{ self.history_doc.type }}
|
|
9
|
+
{% /if %}
|
|
10
|
+
</h2>
|
|
11
|
+
<div class="task-type">{{ self.history_doc.type }}</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="task-meta">
|
|
15
|
+
<div class="meta-item">
|
|
16
|
+
<span class="meta-label">{%t "status" %}</span>
|
|
17
|
+
<span class="task-status status-pending">{%t "task-status-pending" %}</span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="meta-item">
|
|
20
|
+
<span class="meta-label">{%t "elapsed" %}</span>
|
|
21
|
+
<span class="elapsed-time">-</span>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="meta-item">
|
|
24
|
+
<span class="meta-label">{%t "progress" %}</span>
|
|
25
|
+
<span class="progress-text">-</span>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="task-error" style="display: none;"></div>
|
|
31
|
+
|
|
32
|
+
<div class="progress-container">
|
|
33
|
+
<div class="progress-track">
|
|
34
|
+
<div class="progress-bar" style="width: 0%;"></div>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="task-controls">
|
|
39
|
+
<button class="btn btn-pause" type="button" style="display: none;">
|
|
40
|
+
<al-icon icon-name="pause"></al-icon>
|
|
41
|
+
{%t "pause" %}
|
|
42
|
+
</button>
|
|
43
|
+
<button class="btn btn-resume" type="button" style="display: none;">
|
|
44
|
+
<al-icon icon-name="play"></al-icon>
|
|
45
|
+
{%t "resume" %}
|
|
46
|
+
</button>
|
|
47
|
+
<button class="btn btn-stop btn-danger" type="button" style="display: none;">
|
|
48
|
+
<al-icon icon-name="stop"></al-icon>
|
|
49
|
+
{%t "stop" %}
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<div class="task-logs">
|
|
54
|
+
<h3 class="logs-title">{%t "output" %}</h3>
|
|
55
|
+
<div class="log-output"></div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="task-timestamps">
|
|
59
|
+
<div class="timestamp-item">
|
|
60
|
+
<span class="timestamp-label">{%t "started-at" %}</span>
|
|
61
|
+
<span class="timestamp-value">
|
|
62
|
+
{% if self.history_doc.started_at %}
|
|
63
|
+
{{ self.history_doc.started_at.format('Y-m-d H:i:s') }}
|
|
64
|
+
{% else %}
|
|
65
|
+
-
|
|
66
|
+
{% /if %}
|
|
67
|
+
</span>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="timestamp-item">
|
|
70
|
+
<span class="timestamp-label">{%t "ended-at" %}</span>
|
|
71
|
+
<span class="timestamp-value ended-at-value">
|
|
72
|
+
{% if self.history_doc.ended_at %}
|
|
73
|
+
{{ self.history_doc.ended_at.format('Y-m-d H:i:s') }}
|
|
74
|
+
{% else %}
|
|
75
|
+
-
|
|
76
|
+
{% /if %}
|
|
77
|
+
</span>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
@@ -34,11 +34,53 @@
|
|
|
34
34
|
></al-user-avatar-group>
|
|
35
35
|
</div>
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
<div slot="right">
|
|
38
|
+
<al-button class="start-edit" state="ready">
|
|
39
|
+
<al-icon icon-name="pencil"></al-icon>
|
|
40
|
+
{%t "start-editing" %}
|
|
41
|
+
</al-button>
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
<al-button class="stop-and-save" state="ready">
|
|
44
|
+
<al-state state-name="saving">
|
|
45
|
+
<al-icon icon-name="spinner" icon-flags="spin"></al-icon>
|
|
46
|
+
{%t "saving" %}
|
|
47
|
+
</al-state>
|
|
48
|
+
<al-state state-name="saving-before-stop">
|
|
49
|
+
<al-icon icon-name="spinner" icon-flags="spin"></al-icon>
|
|
50
|
+
{%t "saving" %}
|
|
51
|
+
</al-state>
|
|
52
|
+
<al-state state-name="saved">
|
|
53
|
+
<al-icon icon-name="badge-check" icon-flags="beat"></al-icon>
|
|
54
|
+
{%t "saved" %}
|
|
55
|
+
</al-state>
|
|
56
|
+
<al-state state-name="ready">
|
|
57
|
+
<al-icon icon-name="floppy-disk-circle-arrow-right"></al-icon>
|
|
58
|
+
{%t "save-and-stop-editing" %}
|
|
59
|
+
</al-state>
|
|
60
|
+
</al-button>
|
|
61
|
+
|
|
62
|
+
<al-button class="stop-edit" state="ready">
|
|
63
|
+
<al-icon icon-name="pencil-slash"></al-icon>
|
|
64
|
+
{%t "stop-editing" %}
|
|
65
|
+
</al-button>
|
|
66
|
+
|
|
67
|
+
<al-button class="save-all" state="ready">
|
|
68
|
+
<al-state state-name="saving">
|
|
69
|
+
<al-icon icon-name="spinner" icon-flags="spin"></al-icon>
|
|
70
|
+
{%t "saving" %}
|
|
71
|
+
</al-state>
|
|
72
|
+
<al-state state-name="saved">
|
|
73
|
+
<al-icon icon-name="badge-check" icon-flags="beat"></al-icon>
|
|
74
|
+
{%t "saved" %}
|
|
75
|
+
</al-state>
|
|
76
|
+
<al-state state-name="ready">
|
|
77
|
+
<al-icon icon-name="floppy-disk"></al-icon>
|
|
78
|
+
{%t "save-all" %}
|
|
79
|
+
</al-state>
|
|
80
|
+
</al-button>
|
|
81
|
+
|
|
82
|
+
<div data-area="buttons"></div>
|
|
83
|
+
</div>
|
|
42
84
|
</al-editor-toolbar>
|
|
43
85
|
|
|
44
86
|
{#
|