js-kompo-utils 1.0.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/README.md +1 -0
- package/app.js +22 -0
- package/components/VlApexChart.vue +89 -0
- package/components/VlCKEditorTemplate.vue +52 -0
- package/components/VlCKEditorWithVars.vue +80 -0
- package/components/VlCollapsible.vue +91 -0
- package/components/VlCopyBox.vue +61 -0
- package/components/VlCreditCardInput.vue +104 -0
- package/components/VlDateMonthDay.vue +327 -0
- package/components/VlDateTextInput.vue +151 -0
- package/components/VlInternationalPhoneInput.vue +902 -0
- package/components/VlPartialDate.vue +283 -0
- package/components/VlPasswordInput.vue +358 -0
- package/components/VlQrCodeScanner.vue +91 -0
- package/components/VlSwipeableTab.vue +35 -0
- package/components/VlSwipeableTabs.vue +325 -0
- package/components/VlText.vue +72 -0
- package/components/VlTutorialStepBuilder.vue +671 -0
- package/components/VlValidatedInput.vue +262 -0
- package/components/data/countries.js +253 -0
- package/components/getAllDefaultComponents.js +12 -0
- package/docs/architecture.md +71 -0
- package/docs/tutorials.md +247 -0
- package/docs/usage.md +128 -0
- package/functions/index.js +7 -0
- package/functions/inputs.js +64 -0
- package/functions/loading.js +20 -0
- package/kompo-ckeditor-1.0.17/index.js +5 -0
- package/kompo-ckeditor-1.0.17/komponents/CKEditor.vue +36 -0
- package/kompo-ckeditor-1.0.17/komponents/CKEditorExtended.vue +66 -0
- package/kompo-ckeditor-1.0.17/komponents/EditableCKEditor.vue +42 -0
- package/kompo-ckeditor-1.0.17/komponents/TranslatableEditor.vue +28 -0
- package/kompo-ckeditor-1.0.17/mixins/CKEditor.js +291 -0
- package/kompo-ckeditor-1.0.17/mixins/CKEditorUtilities.js +52 -0
- package/kompo-ckeditor-1.0.17/mixins/CkUploadAdapter.js +95 -0
- package/kompo-ckeditor-1.0.17/mixins/translations/en.js +1 -0
- package/kompo-ckeditor-1.0.17/mixins/translations/fr.js +1 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockCommand.js +100 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockEditing.js +225 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockUi.js +21 -0
- package/kompo-ckeditor-1.0.17/plugins/MentionPlugin.js +118 -0
- package/orchestrator/KompoJsBuilder.js +333 -0
- package/package.json +25 -0
- package/raw_animations/count-up-animation.js +220 -0
- package/raw_animations/magic-poof.js +210 -0
- package/tutorials/TutorialConfig.js +34 -0
- package/tutorials/TutorialEngine.js +448 -0
- package/tutorials/index.js +2 -0
- package/tutorials/modules/AutoNext.js +86 -0
- package/tutorials/modules/Avatar.js +94 -0
- package/tutorials/modules/Bubble.js +617 -0
- package/tutorials/modules/Cursor.js +315 -0
- package/tutorials/modules/Highlight.js +282 -0
- package/tutorials/modules/HoverForcer.js +250 -0
- package/tutorials/modules/Mobile.js +148 -0
- package/tutorials/modules/Options.js +98 -0
- package/tutorials/modules/Overlay.js +142 -0
- package/tutorials/modules/Scroll.js +37 -0
- package/tutorials/modules/Typewriter.js +132 -0
- package/tutorials/step-builder/step-builder-bridge.js +436 -0
- package/tutorials/step-builder/utils/bezier-editor.js +379 -0
- package/tutorials/step-builder/utils/code-generator.js +127 -0
- package/tutorials/step-builder/utils/element-picker.js +125 -0
- package/tutorials/tutorial.scss +816 -0
- package/tutorials/utils/selectors.js +225 -0
- package/tutorials/utils/stability.js +76 -0
- package/tutorials/utils/svg.js +46 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Tutorial System
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The tutorial system provides guided walkthroughs for users. Tutorials are defined as JSON files, processed server-side by PHP (translations, conditions, user variables), and rendered client-side by the TutorialEngine.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
resources/tutorials/dashboard-view.json ← You author this (pure data)
|
|
11
|
+
↓
|
|
12
|
+
PHP: TutorialProcessor ← Translates, filters, replaces variables
|
|
13
|
+
↓
|
|
14
|
+
GET /api/tutorials/dashboard-view ← Serves processed JSON
|
|
15
|
+
↓
|
|
16
|
+
JS: TutorialEngine ← Renders overlay, bubble, cursor, highlights
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Key components
|
|
20
|
+
|
|
21
|
+
| Component | Role |
|
|
22
|
+
|-----------|------|
|
|
23
|
+
| **TutorialEngine** (JS) | Orchestrates modules: Overlay, Bubble, Cursor, Highlight, etc. |
|
|
24
|
+
| **TutorialProcessor** (PHP) | Loads JSON, translates strings, evaluates conditions, replaces `{{variables}}` |
|
|
25
|
+
| **TutorialConditionEvaluator** (PHP) | Safe expression parser for `showIf` conditions |
|
|
26
|
+
| **HasTutorial** (PHP plugin) | Auto-detects tutorials for Kompo components, triggers on first visit |
|
|
27
|
+
| **TutorialStepBuilder** (PHP + JS) | Dev-only visual editor for editing steps live |
|
|
28
|
+
|
|
29
|
+
## Creating a Tutorial
|
|
30
|
+
|
|
31
|
+
### 1. Create the JSON file
|
|
32
|
+
|
|
33
|
+
Place it in `resources/tutorials/{component-slug}.json`. The slug matches the Kompo component name (e.g., `DashboardView` → `dashboard-view`).
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"steps": [
|
|
38
|
+
{
|
|
39
|
+
"html": "tutorial.welcome"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"html": "tutorial.click-here",
|
|
43
|
+
"highlight": { "groups": [{ "elements": ["#my-button"] }] },
|
|
44
|
+
"position": "right"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"html": "tutorial.fill-form",
|
|
48
|
+
"highlight": { "groups": [{ "elements": [".form-field", ".submit-btn"] }] },
|
|
49
|
+
"cursor": {
|
|
50
|
+
"from": ".form-field",
|
|
51
|
+
"to": ".submit-btn",
|
|
52
|
+
"click": true,
|
|
53
|
+
"duration": 1.5
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Add translations
|
|
61
|
+
|
|
62
|
+
In your translation files (`resources/lang/en/tutorial.php`):
|
|
63
|
+
|
|
64
|
+
```php
|
|
65
|
+
return [
|
|
66
|
+
'welcome' => 'Welcome, {{user_first_name}}! Let me show you around.',
|
|
67
|
+
'click-here' => 'Click this button to get started.',
|
|
68
|
+
'fill-form' => 'Fill in the form and hit submit.',
|
|
69
|
+
];
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The PHP processor translates keys and replaces `{{user_first_name}}`, `{{user_last_name}}`, `{{user_name}}` automatically.
|
|
73
|
+
|
|
74
|
+
### 3. That's it
|
|
75
|
+
|
|
76
|
+
The `HasTutorial` plugin auto-detects the JSON file based on the component slug and starts the tutorial on first visit. A replay button in the navbar lets users re-watch it anytime.
|
|
77
|
+
|
|
78
|
+
## Step Configuration
|
|
79
|
+
|
|
80
|
+
Each step supports these properties:
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"html": "translation.key",
|
|
85
|
+
|
|
86
|
+
"position": "left | right | top | bottom",
|
|
87
|
+
"align": "left | center | right",
|
|
88
|
+
"overlay": true,
|
|
89
|
+
|
|
90
|
+
"highlight": {
|
|
91
|
+
"groups": [{ "elements": [".selector1", ".selector2"] }],
|
|
92
|
+
"padding": 8,
|
|
93
|
+
"borderRadius": 8
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
"cursor": {
|
|
97
|
+
"from": ".start-element",
|
|
98
|
+
"to": ".end-element",
|
|
99
|
+
"click": true,
|
|
100
|
+
"duration": 1.5,
|
|
101
|
+
"loop": true
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
"hover": ".element-to-force-hover",
|
|
105
|
+
|
|
106
|
+
"scrollTo": ".element-to-scroll-into-view",
|
|
107
|
+
"scrollInside": { "selector": ".container", "by": 200, "duration": 1 },
|
|
108
|
+
|
|
109
|
+
"options": [
|
|
110
|
+
{ "label": "tutorial.option-a", "goToStep": 4 },
|
|
111
|
+
{ "label": "tutorial.option-b", "done": true },
|
|
112
|
+
{ "label": "tutorial.option-c", "redirect": "/other-page" }
|
|
113
|
+
],
|
|
114
|
+
|
|
115
|
+
"autoNext": 3,
|
|
116
|
+
"advance": "click | afterAnimation",
|
|
117
|
+
"silentClick": ".element-to-auto-click",
|
|
118
|
+
"showBack": true,
|
|
119
|
+
"chatMode": true,
|
|
120
|
+
|
|
121
|
+
"showIf": "permission:ManageTeam && !setting:hide_tutorial",
|
|
122
|
+
|
|
123
|
+
"redirect": "/next-page"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Triggering Tutorials
|
|
128
|
+
|
|
129
|
+
### Automatic (first visit)
|
|
130
|
+
|
|
131
|
+
The `HasTutorial` plugin handles this. If `resources/tutorials/{component-slug}.json` exists, the tutorial starts on first visit and is marked as viewed.
|
|
132
|
+
|
|
133
|
+
### Button click (replay)
|
|
134
|
+
|
|
135
|
+
```php
|
|
136
|
+
// Uses 'default' — auto-resolves to current page's tutorial
|
|
137
|
+
_Button('Help')->initTutorial();
|
|
138
|
+
|
|
139
|
+
// Or specify a tutorial explicitly
|
|
140
|
+
_Button('Start Tour')->initTutorial('campaign-settings');
|
|
141
|
+
|
|
142
|
+
// Start at a specific step
|
|
143
|
+
_Button('Show Step 3')->initTutorial('campaign-settings', stepNumber: 2);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### On page load (cross-page redirect)
|
|
147
|
+
|
|
148
|
+
Use `_Tutorial()` in a component's `render()` method:
|
|
149
|
+
|
|
150
|
+
```php
|
|
151
|
+
function render()
|
|
152
|
+
{
|
|
153
|
+
return _Rows(
|
|
154
|
+
_Tutorial('onboarding-step-2'),
|
|
155
|
+
// ... rest of component
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This supports cross-page chaining — when a tutorial redirects to another page with `?tutorial=name&fromStep=N`, the `_Tutorial()` helper picks it up and starts automatically.
|
|
161
|
+
|
|
162
|
+
## Conditional Steps
|
|
163
|
+
|
|
164
|
+
Use `showIf` to conditionally show steps based on user permissions, settings, or DOM elements:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{ "showIf": "permission:ManageTeam" }
|
|
168
|
+
{ "showIf": "permission:EditCampaign && !setting:onboarding_done" }
|
|
169
|
+
{ "showIf": "(role:admin || role:manager) && permission:ViewFinances" }
|
|
170
|
+
{ "showIf": "selector:.optional-feature-panel" }
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Built-in condition types:**
|
|
174
|
+
- `permission:X` — checks `user->hasPermission(X)`
|
|
175
|
+
- `setting:X` — checks `user->getSettingValue(X)`
|
|
176
|
+
- `role:X` — checks `user->hasRole(X)`
|
|
177
|
+
- `selector:X` — checks if DOM element exists (evaluated client-side)
|
|
178
|
+
|
|
179
|
+
**Custom conditions** — register in a service provider:
|
|
180
|
+
|
|
181
|
+
```php
|
|
182
|
+
TutorialConditionEvaluator::register('hasActiveSubscription',
|
|
183
|
+
fn() => auth()->user()->subscription?->isActive() ?? false
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Then use: `"showIf": "hasActiveSubscription && permission:ManageBilling"`
|
|
188
|
+
|
|
189
|
+
## Cross-Page Tutorials
|
|
190
|
+
|
|
191
|
+
When a step needs to redirect to another page and continue:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"html": "tutorial.go-to-settings",
|
|
196
|
+
"options": [
|
|
197
|
+
{
|
|
198
|
+
"label": "tutorial.lets-go",
|
|
199
|
+
"redirect": "/campaign/settings",
|
|
200
|
+
"startTutorial": "campaign-settings"
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The target page should have `_Tutorial('campaign-settings')` in its render method to pick up the redirect.
|
|
207
|
+
|
|
208
|
+
## Dev Mode: Step Builder
|
|
209
|
+
|
|
210
|
+
In debug mode (`APP_DEBUG=true`):
|
|
211
|
+
- A step builder panel is available in the navbar
|
|
212
|
+
- Clicking the replay button also opens the visual editor
|
|
213
|
+
- Edit step properties, pick elements, preview live changes
|
|
214
|
+
- Copy the JSON output to update your tutorial file
|
|
215
|
+
|
|
216
|
+
## File Structure
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
js-kompo-utils/tutorials/
|
|
220
|
+
├── TutorialEngine.js # Main orchestrator
|
|
221
|
+
├── TutorialConfig.js # Defaults + config
|
|
222
|
+
├── tutorial.scss # All tutorial styles
|
|
223
|
+
├── modules/
|
|
224
|
+
│ ├── Avatar.js # Container + avatar image
|
|
225
|
+
│ ├── Overlay.js # Full-screen overlay
|
|
226
|
+
│ ├── Bubble.js # Speech bubble + positioning
|
|
227
|
+
│ ├── Typewriter.js # Character-by-character text
|
|
228
|
+
│ ├── Cursor.js # Animated cursor + click pulse
|
|
229
|
+
│ ├── Highlight.js # SVG cutout overlay
|
|
230
|
+
│ ├── HoverForcer.js # Force :hover styles
|
|
231
|
+
│ ├── Scroll.js # Scroll helpers
|
|
232
|
+
│ ├── Options.js # Choice buttons
|
|
233
|
+
│ ├── AutoNext.js # Timed progress bar
|
|
234
|
+
│ └── Mobile.js # Mobile detection + tab handling
|
|
235
|
+
├── utils/
|
|
236
|
+
│ ├── selectors.js # CSS selector utilities
|
|
237
|
+
│ ├── svg.js # SVG element helpers
|
|
238
|
+
│ └── stability.js # Element position polling
|
|
239
|
+
└── step-builder/ # Dev-only visual editor
|
|
240
|
+
├── step-builder-bridge.js
|
|
241
|
+
└── utils/
|
|
242
|
+
|
|
243
|
+
utils/src/Tutorials/
|
|
244
|
+
├── TutorialProcessor.php # JSON loading + translation + conditions
|
|
245
|
+
├── TutorialConditionEvaluator.php # Safe expression parser
|
|
246
|
+
└── TutorialStepBuilder.php # Kompo Form for visual editor
|
|
247
|
+
```
|
package/docs/usage.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# js-kompo-utils - Usage Guide
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
In your Laravel app's `app.js`:
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { defaultConfig, KompoJsInitializer } from 'js-kompo-utils';
|
|
9
|
+
|
|
10
|
+
const config = defaultConfig
|
|
11
|
+
.bootstrap(() => require('./bootstrap'));
|
|
12
|
+
|
|
13
|
+
new KompoJsInitializer(config, window).initialize();
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This gives you: jQuery, Vue + vue-kompo, CKEditor, Google Maps, QR code reader, all default components, window utilities, and animations.
|
|
17
|
+
|
|
18
|
+
## What's included by default
|
|
19
|
+
|
|
20
|
+
| Feature | Default | Toggle off |
|
|
21
|
+
|---------|---------|------------|
|
|
22
|
+
| jQuery | on | `.withoutJquery()` |
|
|
23
|
+
| CKEditor | on | `.withoutCkEditor()` |
|
|
24
|
+
| Google Maps | on | `.withoutKompoMaps()` |
|
|
25
|
+
| Tutorial Engine | on | `.withoutTutorialEngine()` |
|
|
26
|
+
| QR Code Reader | on (Vue plugin) | - |
|
|
27
|
+
| Default components | all `./components/*.vue` | `.excludeComponent('Name')` |
|
|
28
|
+
| Window utils | input + loading functions | - |
|
|
29
|
+
| Animations | count-up, magic-poof | - |
|
|
30
|
+
|
|
31
|
+
## Adding and removing components
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
// Add an app-specific component
|
|
35
|
+
config.addComponent('MyComponent', require('./components/MyComponent.vue').default);
|
|
36
|
+
|
|
37
|
+
// Add multiple
|
|
38
|
+
config.addComponents({
|
|
39
|
+
'CompA': require('./components/CompA.vue').default,
|
|
40
|
+
'CompB': require('./components/CompB.vue').default,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Remove a default component you don't need
|
|
44
|
+
config.excludeComponent('VlApexChart');
|
|
45
|
+
config.excludeComponents(['VlCKEditorTemplate', 'VlCKEditorWithVars']);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Adding Vue plugins
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
import SomePlugin from 'some-vue-plugin';
|
|
52
|
+
|
|
53
|
+
config.addVuePlugin(SomePlugin);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Adding files to import
|
|
57
|
+
|
|
58
|
+
Pass callbacks — webpack resolves the path at build time:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
config.addFilesToImport([
|
|
62
|
+
() => require('./my-custom-script.js'),
|
|
63
|
+
() => require('./another-script.js'),
|
|
64
|
+
]);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Window utilities
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
// Add individual functions to window
|
|
71
|
+
config.addWindowUtilsItem('myHelper', () => { /* ... */ });
|
|
72
|
+
|
|
73
|
+
// Merge an object of functions
|
|
74
|
+
config.mergeWindowUtils({
|
|
75
|
+
helperA: () => { /* ... */ },
|
|
76
|
+
helperB: () => { /* ... */ },
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Add a decorator that receives window and does custom setup
|
|
80
|
+
config.addWindowDecorator((window) => {
|
|
81
|
+
// custom window setup
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Lifecycle hooks
|
|
86
|
+
|
|
87
|
+
Hook into any initialization step with before/after callbacks:
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
config.addAfterStepCallback('bootstrapExecution', () => {
|
|
91
|
+
// runs after bootstrap, e.g. add axios interceptors
|
|
92
|
+
window.axios.interceptors.request.use(config => {
|
|
93
|
+
config.headers['X-Custom'] = 'value';
|
|
94
|
+
return config;
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
config.addBeforeStepCallback('instanceApp', () => {
|
|
99
|
+
// runs right before Vue mounts
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Available step names:** `bootstrapExecution`, `requireFilesToImport`, `bootJqueryIfRequired`, `bootVue`, `decorateWindow`, `bootCkEditorIfRequired`, `bootMapsIfRequired`, `instanceApp`
|
|
104
|
+
|
|
105
|
+
## Changing the mount selector
|
|
106
|
+
|
|
107
|
+
Default is `#app` (matches kompo's `vue_app_id` config). Override if needed:
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
config.setAppSelector('#my-app');
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Starting from scratch
|
|
114
|
+
|
|
115
|
+
If `defaultConfig` includes too much, build your own:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
import { KompoJsConfigBuilder, KompoJsInitializer } from 'js-kompo-utils';
|
|
119
|
+
|
|
120
|
+
const config = new KompoJsConfigBuilder()
|
|
121
|
+
.bootstrap(() => require('./bootstrap'))
|
|
122
|
+
.withJquery()
|
|
123
|
+
.withoutCkEditor()
|
|
124
|
+
.withoutKompoMaps()
|
|
125
|
+
.addComponent('MyOnly', require('./components/MyOnly.vue').default);
|
|
126
|
+
|
|
127
|
+
new KompoJsInitializer(config, window).initialize();
|
|
128
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function getYesNoValue(id)
|
|
2
|
+
{
|
|
3
|
+
const group = $('#' + id);
|
|
4
|
+
|
|
5
|
+
const rawValue = group.find('.selected').find('*[data-value]').data('value');
|
|
6
|
+
|
|
7
|
+
if (rawValue == undefined) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const value = rawValue == 'yes' ? 1 : 0;
|
|
12
|
+
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getToggle(name)
|
|
17
|
+
{
|
|
18
|
+
return $('input[type=checkbox][name="' + name + '"]');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getToggleValue(name)
|
|
22
|
+
{
|
|
23
|
+
const toggleCheckbox = getToggle(name);
|
|
24
|
+
const checked = toggleCheckbox.attr('aria-checked') == "true";
|
|
25
|
+
|
|
26
|
+
return checked ? 1 : 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function toggleYesNo(name) {
|
|
30
|
+
const groupId = 'temp_' + name;
|
|
31
|
+
const toggleName = name + '_toggle';
|
|
32
|
+
|
|
33
|
+
const groupValue = getYesNoValue(groupId);
|
|
34
|
+
const toggleValue = getToggleValue(toggleName);
|
|
35
|
+
|
|
36
|
+
// This want to fix the first "no" select when the default is null
|
|
37
|
+
if(groupValue == null) {
|
|
38
|
+
$('#' + name + '-off-input').hide();
|
|
39
|
+
$('#' + name + '-on-input').hide();
|
|
40
|
+
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (groupValue != toggleValue) {
|
|
45
|
+
console.log(getToggle(toggleName));
|
|
46
|
+
getToggle(toggleName).each(function(key, toggle) {
|
|
47
|
+
const evt = new Event( 'click', { bubbles: true } );
|
|
48
|
+
toggle.nextElementSibling.dispatchEvent(evt);
|
|
49
|
+
});
|
|
50
|
+
} else if (groupValue == 1) {
|
|
51
|
+
$('#' + name + '-off-input').hide();
|
|
52
|
+
$('#' + name + '-on-input').show();
|
|
53
|
+
} else if(groupValue == 0) {
|
|
54
|
+
$('#' + name + '-off-input').show();
|
|
55
|
+
$('#' + name + '-on-input').hide();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
getYesNoValue,
|
|
61
|
+
getToggle,
|
|
62
|
+
getToggleValue,
|
|
63
|
+
toggleYesNo
|
|
64
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function setLoadingScreen()
|
|
2
|
+
{
|
|
3
|
+
const loadingInnerHtml = `
|
|
4
|
+
<div class="loading-screen">
|
|
5
|
+
<i id="vl-spinner" class="icon-spinner" style="display: block;"></i>
|
|
6
|
+
</div>
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
$('body').append(loadingInnerHtml);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function removeLoadingScreen()
|
|
13
|
+
{
|
|
14
|
+
$('.loading-screen').remove();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
setLoadingScreen,
|
|
19
|
+
removeLoadingScreen
|
|
20
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<vl-form-field v-bind="$_wrapperAttributes" @labelclick="focus">
|
|
3
|
+
<ckeditor
|
|
4
|
+
class="vlFormControl"
|
|
5
|
+
ref="content"
|
|
6
|
+
v-model="component.value"
|
|
7
|
+
v-bind="$_attributes"
|
|
8
|
+
v-on="$_events"
|
|
9
|
+
@keydown.stop
|
|
10
|
+
@ready="onReady"
|
|
11
|
+
|
|
12
|
+
:editor="editor"
|
|
13
|
+
:config="editorConfig" />
|
|
14
|
+
<div
|
|
15
|
+
v-if="mentions.length"
|
|
16
|
+
class="mention-triggers border-t border-gray-200 p-2 flex">
|
|
17
|
+
<div
|
|
18
|
+
v-for="(mention, index) in mentions"
|
|
19
|
+
v-html="getButtonHtml(mention)"
|
|
20
|
+
@click="activateMention(mention)"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
<a v-if="customTextInsertion"
|
|
24
|
+
@click="insertCustomText"
|
|
25
|
+
class="cursor-pointer absolute bottom-2 right-2 text-sm"
|
|
26
|
+
v-html="customTextInsertLabel" />
|
|
27
|
+
</vl-form-field>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
import CKEditor from '../mixins/CKEditor'
|
|
32
|
+
|
|
33
|
+
export default {
|
|
34
|
+
mixins: [CKEditor]
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<vl-form-field v-bind="$_wrapperAttributes" @labelclick="focus">
|
|
3
|
+
<ckeditor
|
|
4
|
+
class="vlFormControl"
|
|
5
|
+
ref="content"
|
|
6
|
+
v-model="component.value"
|
|
7
|
+
v-bind="$_attributes"
|
|
8
|
+
v-on="$_events"
|
|
9
|
+
@keydown.stop
|
|
10
|
+
|
|
11
|
+
:editor="editor"
|
|
12
|
+
:config="editorConfig" />
|
|
13
|
+
<div
|
|
14
|
+
v-if="mentions.length"
|
|
15
|
+
class="mention-triggers border-t border-gray-200 p-2 flex">
|
|
16
|
+
<div
|
|
17
|
+
v-for="(mention, index) in mentions"
|
|
18
|
+
:key="index"
|
|
19
|
+
v-html="getButtonHtml(mention)"
|
|
20
|
+
@click="activateMention(mention)"
|
|
21
|
+
/>
|
|
22
|
+
<VlDate
|
|
23
|
+
:vkompo="$_config('date-component')"
|
|
24
|
+
@open="onOpen"
|
|
25
|
+
@change="onChange"
|
|
26
|
+
@close="onClose"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
</vl-form-field>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
import CKEditor from '../mixins/CKEditor'
|
|
34
|
+
import DoesAxiosRequests from 'vue-kompo/js/form/mixins/DoesAxiosRequests'
|
|
35
|
+
import EmitsEvents from 'vue-kompo/js/element/mixins/EmitsEvents'
|
|
36
|
+
import HasId from 'vue-kompo/js/element/mixins/HasId'
|
|
37
|
+
import HasConfig from 'vue-kompo/js/element/mixins/HasConfig'
|
|
38
|
+
import CKEditorUtilities from '../mixins/CKEditorUtilities'
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
mixins: [CKEditor, DoesAxiosRequests, CKEditorUtilities, EmitsEvents, HasId, HasConfig],
|
|
42
|
+
data(){
|
|
43
|
+
return {
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
methods: {
|
|
48
|
+
onOpen(value, event){ //not used anymore
|
|
49
|
+
return
|
|
50
|
+
},
|
|
51
|
+
onChange(value, event){ //not used anymore
|
|
52
|
+
return
|
|
53
|
+
},
|
|
54
|
+
onClose(value, event){
|
|
55
|
+
value = value.substr(0, 16)
|
|
56
|
+
var html = '<span class="mention ckeditor-mention icon-calendar" data-mention="icon-calendar|'+value+'">'+value+'</span>'
|
|
57
|
+
this.insertHtml(html)
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
created(){
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="vlEditableWrapper">
|
|
3
|
+
<div
|
|
4
|
+
class="vlEditableContent cursor-pointer"
|
|
5
|
+
v-if="!editing"
|
|
6
|
+
v-html="$_value || $_label"
|
|
7
|
+
@click.stop="startEditing"/>
|
|
8
|
+
|
|
9
|
+
<VlCKEditor
|
|
10
|
+
v-if="editing"
|
|
11
|
+
:vkompo="component"
|
|
12
|
+
v-click-out="close"
|
|
13
|
+
@change="change"/>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
import CKEditor from '../mixins/CKEditor'
|
|
19
|
+
export default {
|
|
20
|
+
mixins: [CKEditor],
|
|
21
|
+
data(){
|
|
22
|
+
return {
|
|
23
|
+
editing: false
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
computed: {
|
|
27
|
+
|
|
28
|
+
},
|
|
29
|
+
methods: {
|
|
30
|
+
startEditing(){
|
|
31
|
+
this.editing = true
|
|
32
|
+
},
|
|
33
|
+
close(){
|
|
34
|
+
this.editing = !this.editing
|
|
35
|
+
},
|
|
36
|
+
change(value){
|
|
37
|
+
this.component.value = value
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<vl-form-field v-bind="$_wrapperAttributes">
|
|
3
|
+
<vlLocaleTabs
|
|
4
|
+
:locales="locales"
|
|
5
|
+
:activeLocale="activeLocale"
|
|
6
|
+
@changeLocale="changeTab"/>
|
|
7
|
+
<ckeditor
|
|
8
|
+
class="vlFormControl"
|
|
9
|
+
ref="content"
|
|
10
|
+
v-model="currentTranslation"
|
|
11
|
+
v-bind="$_attributes"
|
|
12
|
+
v-on="$_events"
|
|
13
|
+
@keydown.stop
|
|
14
|
+
|
|
15
|
+
:editor="editor"
|
|
16
|
+
:config="editorConfig" />
|
|
17
|
+
</vl-form-field>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import CKEditor from '../mixins/CKEditor'
|
|
22
|
+
import Translatable from 'vue-kompo/js/form/mixins/Translatable'
|
|
23
|
+
|
|
24
|
+
export default {
|
|
25
|
+
mixins: [CKEditor, Translatable],
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|