slicejs-web-framework 1.0.9 → 1.0.12
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/package.json +1 -1
- package/src/Components/AppComponents/DocumentationPage/DocumentationPage.js +2 -2
- package/src/Components/AppComponents/ServiceDocumentation/ServiceDocumentation.css +82 -0
- package/src/Components/AppComponents/ServiceDocumentation/ServiceDocumentation.html +74 -0
- package/src/Components/AppComponents/ServiceDocumentation/ServiceDocumentation.js +416 -0
- package/src/Components/AppComponents/SliceStylesDocumentation/SliceStylesDocumentation.css +56 -0
- package/src/Components/AppComponents/SliceStylesDocumentation/SliceStylesDocumentation.html +28 -0
- package/src/Components/AppComponents/SliceStylesDocumentation/SliceStylesDocumentation.js +134 -0
- package/src/Components/AppComponents/StructuralDocumentation/StructuralDocumentation.css +72 -0
- package/src/Components/AppComponents/StructuralDocumentation/StructuralDocumentation.html +98 -0
- package/src/Components/AppComponents/StructuralDocumentation/StructuralDocumentation.js +219 -0
- package/src/Components/AppComponents/ThemesDocumentation/ThemesDocumentation.css +61 -0
- package/src/Components/AppComponents/ThemesDocumentation/ThemesDocumentation.html +80 -0
- package/src/Components/AppComponents/ThemesDocumentation/ThemesDocumentation.js +149 -0
- package/src/Components/AppComponents/VisualDocumentation/VisualDocumentation.css +70 -0
- package/src/Components/AppComponents/VisualDocumentation/VisualDocumentation.html +67 -0
- package/src/Components/AppComponents/VisualDocumentation/VisualDocumentation.js +193 -0
- package/src/Components/components.js +3 -0
- package/src/routes.js +21 -0
package/package.json
CHANGED
|
@@ -48,8 +48,8 @@ export default class DocumentationPage extends HTMLElement {
|
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
title: 'Services',
|
|
51
|
-
path: '/Documentation/
|
|
52
|
-
component: '
|
|
51
|
+
path: '/Documentation/Service',
|
|
52
|
+
component: 'ServiceDocumentation'
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
title: 'Lifecycle methods',
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
slice-servicedocumentation {
|
|
2
|
+
color: var(--font-primary-color);
|
|
3
|
+
font-family: var(--font-family);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
slice-servicedocumentation h1,
|
|
7
|
+
slice-servicedocumentation h2,
|
|
8
|
+
slice-servicedocumentation h3 {
|
|
9
|
+
margin-top: 1.5em;
|
|
10
|
+
margin-bottom: 0.5em;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
slice-servicedocumentation p {
|
|
14
|
+
line-height: 1.6;
|
|
15
|
+
margin: 1em 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
slice-servicedocumentation ul,
|
|
19
|
+
slice-servicedocumentation ol {
|
|
20
|
+
margin: 1em 0;
|
|
21
|
+
padding-left: 2em;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
slice-servicedocumentation li {
|
|
25
|
+
margin-bottom: 0.5em;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
slice-servicedocumentation code {
|
|
29
|
+
font-family: monospace;
|
|
30
|
+
background-color: var(--secondary-background-color);
|
|
31
|
+
padding: 0.2em 0.4em;
|
|
32
|
+
border-radius: 3px;
|
|
33
|
+
font-size: 0.9em;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
slice-servicedocumentation .service-example,
|
|
37
|
+
slice-servicedocumentation .service-usage-example,
|
|
38
|
+
slice-servicedocumentation .fetch-manager-example,
|
|
39
|
+
slice-servicedocumentation .local-storage-example,
|
|
40
|
+
slice-servicedocumentation .indexed-db-example,
|
|
41
|
+
slice-servicedocumentation .translator-example,
|
|
42
|
+
slice-servicedocumentation .custom-service-example {
|
|
43
|
+
margin: 1.5em 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
slice-servicedocumentation strong {
|
|
47
|
+
color: var(--primary-color);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
slice-servicedocumentation .faq-section {
|
|
51
|
+
margin: 2em 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
slice-servicedocumentation .faq-section slice-details {
|
|
55
|
+
margin-bottom: 1em;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
slice-servicedocumentation table {
|
|
59
|
+
width: 100%;
|
|
60
|
+
border-collapse: collapse;
|
|
61
|
+
margin: 1.5em 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
slice-servicedocumentation th,
|
|
65
|
+
slice-servicedocumentation td {
|
|
66
|
+
padding: 0.75em;
|
|
67
|
+
text-align: left;
|
|
68
|
+
border-bottom: 1px solid var(--primary-color-shade);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
slice-servicedocumentation th {
|
|
72
|
+
background-color: var(--primary-color);
|
|
73
|
+
color: var(--primary-color-contrast);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
slice-servicedocumentation .service-section {
|
|
77
|
+
padding: 1em;
|
|
78
|
+
margin: 1em 0;
|
|
79
|
+
border-left: 3px solid var(--primary-color);
|
|
80
|
+
background-color: var(--secondary-background-color);
|
|
81
|
+
border-radius: 0 var(--border-radius-slice) var(--border-radius-slice) 0;
|
|
82
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<h1 id="serviceComponents">Service Components</h1>
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
Service components in Slice.js handle business logic and data operations without a visual representation. They provide reusable functionality that can be shared across visual components, serving as the backbone of your application's data layer and business logic.
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h2 id="serviceComponentOverview">What are Service Components?</h2>
|
|
8
|
+
<p>
|
|
9
|
+
Service components in Slice.js:
|
|
10
|
+
</p>
|
|
11
|
+
<ul>
|
|
12
|
+
<li>Handle data operations, API communication, and business logic</li>
|
|
13
|
+
<li>Don't have visual representation or DOM elements</li>
|
|
14
|
+
<li>Can be shared across multiple visual components</li>
|
|
15
|
+
<li>Often follow the singleton pattern (one instance shared throughout the application)</li>
|
|
16
|
+
<li>Provide a clean separation between UI and business logic</li>
|
|
17
|
+
</ul>
|
|
18
|
+
|
|
19
|
+
<h2 id="buildingServiceComponents">Creating Service Components</h2>
|
|
20
|
+
<p>
|
|
21
|
+
Here's a basic example of a service component that fetches and caches data from an API:
|
|
22
|
+
</p>
|
|
23
|
+
<div class="service-example"></div>
|
|
24
|
+
|
|
25
|
+
<h2 id="usingServiceComponents">Using Service Components</h2>
|
|
26
|
+
<p>
|
|
27
|
+
Services are built using <code>slice.build()</code> just like visual components, but they interact differently with the application:
|
|
28
|
+
</p>
|
|
29
|
+
<div class="service-usage-example"></div>
|
|
30
|
+
|
|
31
|
+
<h2 id="builtInServices">Built-in Service Components</h2>
|
|
32
|
+
|
|
33
|
+
<h3 id="fetchManager">FetchManager</h3>
|
|
34
|
+
<p>
|
|
35
|
+
The FetchManager service simplifies API communication with features like automatic loading indicators, timeout handling, error management, and response caching:
|
|
36
|
+
</p>
|
|
37
|
+
<div class="fetch-manager-example"></div>
|
|
38
|
+
|
|
39
|
+
<h3 id="localStorageManager">LocalStorageManager</h3>
|
|
40
|
+
<p>
|
|
41
|
+
The LocalStorageManager service provides a simplified interface for working with browser localStorage, including automatic JSON serialization and error handling:
|
|
42
|
+
</p>
|
|
43
|
+
<div class="local-storage-example"></div>
|
|
44
|
+
|
|
45
|
+
<h3 id="indexedDbManager">IndexedDbManager</h3>
|
|
46
|
+
<p>
|
|
47
|
+
The IndexedDbManager service offers a simplified API for working with IndexedDB, providing methods for CRUD operations on object stores:
|
|
48
|
+
</p>
|
|
49
|
+
<div class="indexed-db-example"></div>
|
|
50
|
+
|
|
51
|
+
<h3 id="translator">Translator</h3>
|
|
52
|
+
<p>
|
|
53
|
+
The Translator service enables internationalization in your application, allowing you to support multiple languages:
|
|
54
|
+
</p>
|
|
55
|
+
<div class="translator-example"></div>
|
|
56
|
+
|
|
57
|
+
<h2 id="customServices">Creating Custom Service Components</h2>
|
|
58
|
+
<p>
|
|
59
|
+
You can create custom service components for specific application needs. Here's an example of a custom authentication service:
|
|
60
|
+
</p>
|
|
61
|
+
<div class="custom-service-example"></div>
|
|
62
|
+
|
|
63
|
+
<h2 id="serviceComponentBestPractices">Best Practices</h2>
|
|
64
|
+
<ul>
|
|
65
|
+
<li><strong>Single Responsibility</strong>: Each service should focus on a specific domain or functionality</li>
|
|
66
|
+
<li><strong>Error Handling</strong>: Implement robust error handling and logging within services</li>
|
|
67
|
+
<li><strong>Caching Strategy</strong>: Use appropriate caching strategies to improve performance</li>
|
|
68
|
+
<li><strong>Service Composition</strong>: Compose complex services by combining simpler services</li>
|
|
69
|
+
<li><strong>Dependency Injection</strong>: Pass dependencies to services through their constructors</li>
|
|
70
|
+
<li><strong>Consistent API</strong>: Design service APIs with consistent naming and behavior patterns</li>
|
|
71
|
+
</ul>
|
|
72
|
+
|
|
73
|
+
<h2 id="serviceComponentsFaq">Frequently Asked Questions</h2>
|
|
74
|
+
<div class="faq-section"></div>
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
export default class ServiceDocumentation extends HTMLElement {
|
|
2
|
+
constructor(props) {
|
|
3
|
+
super();
|
|
4
|
+
slice.attachTemplate(this);
|
|
5
|
+
|
|
6
|
+
slice.controller.setComponentProps(this, props);
|
|
7
|
+
this.debuggerProps = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async init() {
|
|
11
|
+
// Create simple service example
|
|
12
|
+
const serviceExample = await slice.build('CodeVisualizer', {
|
|
13
|
+
value: `// Example: Basic Service Component
|
|
14
|
+
export default class DataService {
|
|
15
|
+
constructor(props = {}) {
|
|
16
|
+
// Initialize state and config
|
|
17
|
+
this.baseUrl = props.baseUrl || 'https://api.example.com';
|
|
18
|
+
this.cache = new Map();
|
|
19
|
+
|
|
20
|
+
// Register with controller if needed
|
|
21
|
+
if (props.sliceId) {
|
|
22
|
+
slice.controller.registerComponent(this);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async fetchData(endpoint) {
|
|
27
|
+
// Check cache first
|
|
28
|
+
if (this.cache.has(endpoint)) {
|
|
29
|
+
return this.cache.get(endpoint);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Show loading indicator
|
|
33
|
+
slice.loading.start();
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Fetch data from API
|
|
37
|
+
const response = await fetch(\`\${this.baseUrl}/\${endpoint}\`);
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
|
|
40
|
+
// Cache the response
|
|
41
|
+
this.cache.set(endpoint, data);
|
|
42
|
+
return data;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// Log error
|
|
45
|
+
slice.logger.logError('DataService', \`Error fetching \${endpoint}\`, error);
|
|
46
|
+
throw error;
|
|
47
|
+
} finally {
|
|
48
|
+
// Hide loading indicator
|
|
49
|
+
slice.loading.stop();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
clearCache() {
|
|
54
|
+
this.cache.clear();
|
|
55
|
+
}
|
|
56
|
+
}`,
|
|
57
|
+
language: 'javascript'
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
this.querySelector('.service-example').appendChild(serviceExample);
|
|
61
|
+
|
|
62
|
+
// Create service usage example
|
|
63
|
+
const serviceUsageExample = await slice.build('CodeVisualizer', {
|
|
64
|
+
value: `// Building and using a service component
|
|
65
|
+
const dataService = await slice.build('DataService', {
|
|
66
|
+
baseUrl: 'https://api.myapp.com/v1',
|
|
67
|
+
sliceId: 'data-service'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Using the service in a visual component
|
|
71
|
+
export default class ProductList extends HTMLElement {
|
|
72
|
+
constructor(props) {
|
|
73
|
+
super();
|
|
74
|
+
slice.attachTemplate(this);
|
|
75
|
+
this.$productList = this.querySelector('.product-list');
|
|
76
|
+
|
|
77
|
+
slice.controller.setComponentProps(this, props);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async init() {
|
|
81
|
+
// Get a reference to our service
|
|
82
|
+
this.dataService = slice.controller.getComponent('data-service');
|
|
83
|
+
|
|
84
|
+
// Load initial data
|
|
85
|
+
await this.loadProducts();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async loadProducts() {
|
|
89
|
+
try {
|
|
90
|
+
// Use the service to fetch data
|
|
91
|
+
const products = await this.dataService.fetchData('products');
|
|
92
|
+
|
|
93
|
+
// Render the products
|
|
94
|
+
this.renderProducts(products);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// Handle error
|
|
97
|
+
this.showError("Failed to load products");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
renderProducts(products) {
|
|
102
|
+
// Clear existing content
|
|
103
|
+
this.$productList.innerHTML = '';
|
|
104
|
+
|
|
105
|
+
// Create product items
|
|
106
|
+
products.forEach(async product => {
|
|
107
|
+
const productItem = await slice.build('ProductItem', { product });
|
|
108
|
+
this.$productList.appendChild(productItem);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}`,
|
|
112
|
+
language: 'javascript'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
this.querySelector('.service-usage-example').appendChild(serviceUsageExample);
|
|
116
|
+
|
|
117
|
+
// Create FetchManager example
|
|
118
|
+
const fetchManagerExample = await slice.build('CodeVisualizer', {
|
|
119
|
+
value: `// Using the built-in FetchManager service
|
|
120
|
+
const fetchManager = await slice.build('FetchManager', {
|
|
121
|
+
baseUrl: 'https://api.example.com',
|
|
122
|
+
timeout: 5000,
|
|
123
|
+
sliceId: 'api-manager'
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Making API requests with FetchManager
|
|
127
|
+
const userData = await fetchManager.request(
|
|
128
|
+
'GET', // HTTP Method
|
|
129
|
+
null, // Request body (for POST/PUT)
|
|
130
|
+
'users/profile', // Endpoint
|
|
131
|
+
(data, response) => { // onRequestSuccess callback
|
|
132
|
+
console.log('Success!', data);
|
|
133
|
+
},
|
|
134
|
+
(data, response) => { // onRequestError callback
|
|
135
|
+
console.error('Error:', response.status);
|
|
136
|
+
},
|
|
137
|
+
true, // refetchOnError
|
|
138
|
+
{ // requestOptions
|
|
139
|
+
headers: {
|
|
140
|
+
'Authorization': 'Bearer token123'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Enabling caching
|
|
146
|
+
fetchManager.enableCache();
|
|
147
|
+
|
|
148
|
+
// Setting default headers for all requests
|
|
149
|
+
fetchManager.setDefaultHeaders({
|
|
150
|
+
'Content-Type': 'application/json',
|
|
151
|
+
'X-API-Key': 'your-api-key'
|
|
152
|
+
});`,
|
|
153
|
+
language: 'javascript'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
this.querySelector('.fetch-manager-example').appendChild(fetchManagerExample);
|
|
157
|
+
|
|
158
|
+
// Create LocalStorageManager example
|
|
159
|
+
const localStorageExample = await slice.build('CodeVisualizer', {
|
|
160
|
+
value: `// Using the LocalStorageManager service
|
|
161
|
+
const storageManager = await slice.build('LocalStorageManager', {
|
|
162
|
+
sliceId: 'storage-manager'
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Storing data
|
|
166
|
+
storageManager.setItem('user-preferences', {
|
|
167
|
+
theme: 'dark',
|
|
168
|
+
language: 'en',
|
|
169
|
+
notifications: true
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Retrieving data
|
|
173
|
+
const preferences = storageManager.getItem('user-preferences');
|
|
174
|
+
console.log(preferences.theme); // 'dark'
|
|
175
|
+
|
|
176
|
+
// Removing data
|
|
177
|
+
storageManager.removeItem('temporary-data');
|
|
178
|
+
|
|
179
|
+
// Clearing all data
|
|
180
|
+
storageManager.clear();`,
|
|
181
|
+
language: 'javascript'
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
this.querySelector('.local-storage-example').appendChild(localStorageExample);
|
|
185
|
+
|
|
186
|
+
// Create IndexedDbManager example
|
|
187
|
+
const indexedDbExample = await slice.build('CodeVisualizer', {
|
|
188
|
+
value: `// Using the IndexedDbManager service
|
|
189
|
+
const dbManager = await slice.build('IndexedDbManager', {
|
|
190
|
+
databaseName: 'app-database',
|
|
191
|
+
storeName: 'tasks',
|
|
192
|
+
sliceId: 'db-manager'
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Opening the database
|
|
196
|
+
await dbManager.openDatabase();
|
|
197
|
+
|
|
198
|
+
// Adding an item
|
|
199
|
+
const newTask = {
|
|
200
|
+
title: 'Complete documentation',
|
|
201
|
+
priority: 'high',
|
|
202
|
+
completed: false,
|
|
203
|
+
dueDate: new Date()
|
|
204
|
+
};
|
|
205
|
+
const taskId = await dbManager.addItem(newTask);
|
|
206
|
+
|
|
207
|
+
// Getting an item
|
|
208
|
+
const task = await dbManager.getItem(taskId);
|
|
209
|
+
|
|
210
|
+
// Updating an item
|
|
211
|
+
task.completed = true;
|
|
212
|
+
await dbManager.updateItem(task);
|
|
213
|
+
|
|
214
|
+
// Getting all items
|
|
215
|
+
const allTasks = await dbManager.getAllItems();
|
|
216
|
+
|
|
217
|
+
// Deleting an item
|
|
218
|
+
await dbManager.deleteItem(taskId);
|
|
219
|
+
|
|
220
|
+
// Close the database when done
|
|
221
|
+
dbManager.closeDatabase();`,
|
|
222
|
+
language: 'javascript'
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
this.querySelector('.indexed-db-example').appendChild(indexedDbExample);
|
|
226
|
+
|
|
227
|
+
// Create translator example
|
|
228
|
+
const translatorExample = await slice.build('CodeVisualizer', {
|
|
229
|
+
value: `// Configuring the Translator service in sliceConfig.json
|
|
230
|
+
{
|
|
231
|
+
"translator": {
|
|
232
|
+
"enabled": true
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// messages.json structure
|
|
237
|
+
{
|
|
238
|
+
"en": {
|
|
239
|
+
"button": {
|
|
240
|
+
"value": "Submit"
|
|
241
|
+
},
|
|
242
|
+
"header": {
|
|
243
|
+
"title": "Welcome to our application"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"es": {
|
|
247
|
+
"button": {
|
|
248
|
+
"value": "Enviar"
|
|
249
|
+
},
|
|
250
|
+
"header": {
|
|
251
|
+
"title": "Bienvenido a nuestra aplicación"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Using translation in components
|
|
257
|
+
export default class Header extends HTMLElement {
|
|
258
|
+
constructor(props) {
|
|
259
|
+
super();
|
|
260
|
+
slice.attachTemplate(this);
|
|
261
|
+
this.$title = this.querySelector('.title');
|
|
262
|
+
|
|
263
|
+
slice.controller.setComponentProps(this, props);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
init() {
|
|
267
|
+
// Properties will be automatically translated
|
|
268
|
+
// based on the current language
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Changing the language
|
|
273
|
+
slice.translator.changeLanguage('es');`,
|
|
274
|
+
language: 'javascript'
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
this.querySelector('.translator-example').appendChild(translatorExample);
|
|
278
|
+
|
|
279
|
+
// Create custom service example
|
|
280
|
+
const customServiceExample = await slice.build('CodeVisualizer', {
|
|
281
|
+
value: `// Creating a custom service component
|
|
282
|
+
export default class AuthService {
|
|
283
|
+
constructor(props = {}) {
|
|
284
|
+
this.apiUrl = props.apiUrl || '/api/auth';
|
|
285
|
+
this.tokenKey = 'auth_token';
|
|
286
|
+
this.user = null;
|
|
287
|
+
|
|
288
|
+
// Register with controller
|
|
289
|
+
if (props.sliceId) {
|
|
290
|
+
slice.controller.registerComponent(this);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Create storage manager for token persistence
|
|
294
|
+
this.storageManager = new (slice.controller.classes.get('LocalStorageManager'))();
|
|
295
|
+
|
|
296
|
+
// Initialize fetch manager for API calls
|
|
297
|
+
this.fetchManager = new (slice.controller.classes.get('FetchManager'))({
|
|
298
|
+
baseUrl: this.apiUrl
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async init() {
|
|
303
|
+
// Check for existing token on initialization
|
|
304
|
+
const token = this.storageManager.getItem(this.tokenKey);
|
|
305
|
+
if (token) {
|
|
306
|
+
try {
|
|
307
|
+
// Validate the token and get user info
|
|
308
|
+
await this.validateToken(token);
|
|
309
|
+
} catch (error) {
|
|
310
|
+
// Clear invalid token
|
|
311
|
+
this.logout();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async login(username, password) {
|
|
317
|
+
try {
|
|
318
|
+
const response = await this.fetchManager.request(
|
|
319
|
+
'POST',
|
|
320
|
+
{ username, password },
|
|
321
|
+
'login'
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
if (response && response.token) {
|
|
325
|
+
this.storageManager.setItem(this.tokenKey, response.token);
|
|
326
|
+
this.user = response.user;
|
|
327
|
+
return this.user;
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
slice.logger.logError('AuthService', 'Login failed', error);
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async validateToken(token) {
|
|
336
|
+
try {
|
|
337
|
+
const response = await this.fetchManager.request(
|
|
338
|
+
'GET',
|
|
339
|
+
null,
|
|
340
|
+
'validate',
|
|
341
|
+
null,
|
|
342
|
+
null,
|
|
343
|
+
false,
|
|
344
|
+
{
|
|
345
|
+
headers: {
|
|
346
|
+
'Authorization': \`Bearer \${token}\`
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
if (response && response.valid) {
|
|
352
|
+
this.user = response.user;
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
return false;
|
|
356
|
+
} catch (error) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
isAuthenticated() {
|
|
362
|
+
return !!this.user;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
logout() {
|
|
366
|
+
this.user = null;
|
|
367
|
+
this.storageManager.removeItem(this.tokenKey);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
getUser() {
|
|
371
|
+
return this.user;
|
|
372
|
+
}
|
|
373
|
+
}`,
|
|
374
|
+
language: 'javascript'
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
this.querySelector('.custom-service-example').appendChild(customServiceExample);
|
|
378
|
+
|
|
379
|
+
// Create FAQ section
|
|
380
|
+
const faqQuestions = [
|
|
381
|
+
{
|
|
382
|
+
title: "How do services differ from visual components?",
|
|
383
|
+
text: "Service components focus on business logic and data management without any visual representation. They don't extend HTMLElement or use templates. Instead, they provide methods and properties that other components can use to perform operations like API calls, data storage, or other application services."
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
title: "Should I register service components with the controller?",
|
|
387
|
+
text: "Yes, registering service components with the controller allows them to be accessed globally via slice.controller.getComponent(). This makes it easy to share a single instance of a service across multiple components, following the singleton pattern for services like API clients or authentication managers."
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
title: "How can I handle authentication in Slice.js?",
|
|
391
|
+
text: "Create a dedicated AuthService component that handles login, logout, token management, and user information. Store authentication tokens using LocalStorageManager or IndexedDbManager, and add methods to check if the user is authenticated. Other components can then use this service to secure routes or display user-specific content."
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
title: "Can services communicate with each other?",
|
|
395
|
+
text: "Yes, services can communicate with each other by accessing other service instances through slice.controller.getComponent() or by dependency injection in the constructor. For example, an AuthService might use a FetchManager for API calls and a LocalStorageManager for token persistence."
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
title: "How do I handle offline functionality?",
|
|
399
|
+
text: "Implement a SyncService that works with IndexedDbManager to store data locally when offline. This service should track changes made offline and synchronize them when the connection is restored. You can use the FetchManager with a custom queue system to manage pending requests."
|
|
400
|
+
}
|
|
401
|
+
];
|
|
402
|
+
|
|
403
|
+
const faqContainer = this.querySelector('.faq-section');
|
|
404
|
+
|
|
405
|
+
for (const question of faqQuestions) {
|
|
406
|
+
const detailsComponent = await slice.build('Details', {
|
|
407
|
+
title: question.title,
|
|
408
|
+
text: question.text
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
faqContainer.appendChild(detailsComponent);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
customElements.define('slice-servicedocumentation', ServiceDocumentation);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
slice-slicestylesdocumentation {
|
|
2
|
+
color: var(--font-primary-color);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
slice-slicestylesdocumentation .style-section {
|
|
6
|
+
margin-bottom: 30px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
slice-slicestylesdocumentation .style-preview {
|
|
10
|
+
background-color: var(--secondary-background-color);
|
|
11
|
+
padding: 15px;
|
|
12
|
+
border-radius: var(--border-radius-slice);
|
|
13
|
+
margin: 10px 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
slice-slicestylesdocumentation .scrollbar-demo {
|
|
17
|
+
max-height: 100px;
|
|
18
|
+
overflow-y: scroll;
|
|
19
|
+
padding: 15px;
|
|
20
|
+
background-color: var(--secondary-background-color);
|
|
21
|
+
border-radius: var(--border-radius-slice);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
slice-slicestylesdocumentation .caret-demo {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: 20px;
|
|
28
|
+
margin: 20px 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
slice-slicestylesdocumentation .color-variable {
|
|
32
|
+
display: inline-block;
|
|
33
|
+
width: 20px;
|
|
34
|
+
height: 20px;
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
margin-right: 10px;
|
|
37
|
+
vertical-align: middle;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
slice-slicestylesdocumentation .variables-table {
|
|
41
|
+
width: 100%;
|
|
42
|
+
border-collapse: collapse;
|
|
43
|
+
margin: 20px 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
slice-slicestylesdocumentation .variables-table th,
|
|
47
|
+
slice-slicestylesdocumentation .variables-table td {
|
|
48
|
+
padding: 10px;
|
|
49
|
+
text-align: left;
|
|
50
|
+
border-bottom: 1px solid var(--primary-color-shade);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
slice-slicestylesdocumentation .variables-table th {
|
|
54
|
+
background-color: var(--primary-color);
|
|
55
|
+
color: var(--primary-color-contrast);
|
|
56
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<h1 id="sliceStyles">Slice Styles</h1>
|
|
2
|
+
<p>
|
|
3
|
+
Slice.js provides global styles through the <code>sliceStyles.css</code> file, which establishes consistent base styling across your application. These styles include CSS variables, resets, and utility classes.
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<h2 id="cssVariables">CSS Variables</h2>
|
|
7
|
+
<p>
|
|
8
|
+
Core CSS variables are defined in the <code>:root</code> element and are available throughout your application.
|
|
9
|
+
</p>
|
|
10
|
+
<div class="css-variables"></div>
|
|
11
|
+
|
|
12
|
+
<h2 id="bodyStyles">Base Body Styles</h2>
|
|
13
|
+
<p>
|
|
14
|
+
The framework applies minimal base styling to the <code>body</code> element.
|
|
15
|
+
</p>
|
|
16
|
+
<div class="body-styles"></div>
|
|
17
|
+
|
|
18
|
+
<h2 id="caretStyles">Caret/Dropdown Styles</h2>
|
|
19
|
+
<p>
|
|
20
|
+
The framework provides styles for dropdown carets used in various components.
|
|
21
|
+
</p>
|
|
22
|
+
<div class="caret-styles"></div>
|
|
23
|
+
|
|
24
|
+
<h2 id="scrollbarStyles">Custom Scrollbar</h2>
|
|
25
|
+
<p>
|
|
26
|
+
Slice.js includes global custom scrollbar styling for all elements.
|
|
27
|
+
</p>
|
|
28
|
+
<div class="scrollbar-styles"></div>
|