solara 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/solara/lib/.DS_Store +0 -0
- data/solara/lib/core/.DS_Store +0 -0
- data/solara/lib/core/brands/brand_switcher.rb +58 -1
- data/solara/lib/core/dashboard/brand/BrandDetail.js +34 -2
- data/solara/lib/core/dashboard/brand/BrandDetailController.js +23 -233
- data/solara/lib/core/dashboard/brand/BrandDetailModel.js +13 -5
- data/solara/lib/core/dashboard/brand/BrandDetailView.js +16 -200
- data/solara/lib/core/dashboard/brand/SectionsFormManager.js +232 -0
- data/solara/lib/core/dashboard/brand/brand.html +187 -177
- data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +2 -5
- data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +36 -133
- data/solara/lib/core/dashboard/brands/Brands.js +31 -0
- data/solara/lib/core/dashboard/brands/BrandsController.js +0 -5
- data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
- data/solara/lib/core/dashboard/brands/brands.html +71 -52
- data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +6 -6
- data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +4 -4
- data/solara/lib/core/dashboard/component/ConfirmationDialog.js +15 -10
- data/solara/lib/core/dashboard/component/EditJsonSheet.js +160 -0
- data/solara/lib/core/dashboard/component/MessageBottomSheet.js +5 -5
- data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +5 -3
- data/solara/lib/core/dashboard/handler/base_handler.rb +1 -0
- data/solara/lib/core/dashboard/handler/edit_section_handler.rb +1 -5
- data/solara/lib/core/doctor/schema/brand_configurations.json +0 -8
- data/solara/lib/core/doctor/schema/platform/global/resources_manifest.json +30 -0
- data/solara/lib/core/doctor/schema/platform/json_manifest.json +57 -0
- data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +35 -1
- data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +30 -1
- data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +35 -1
- data/solara/lib/core/doctor/validator/template/template_validator.rb +9 -9
- data/solara/lib/core/scripts/brand_config_manager.rb +1 -1
- data/solara/lib/core/scripts/brand_configurations_manager.rb +41 -0
- data/solara/lib/core/scripts/code_generator.rb +342 -118
- data/solara/lib/core/scripts/file_path.rb +21 -1
- data/solara/lib/core/scripts/gitignore_manager.rb +11 -3
- data/solara/lib/core/scripts/json_manifest_processor.rb +95 -0
- data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +11 -1
- data/solara/lib/core/scripts/resource_manifest_processor.rb +151 -0
- data/solara/lib/core/scripts/solara_status_manager.rb +1 -1
- data/solara/lib/core/scripts/theme_generator.rb +21 -242
- data/solara/lib/core/solara_configurator.rb +1 -1
- data/solara/lib/core/template/brands/global/resources_manifest.json +10 -0
- data/solara/lib/core/template/brands/json/Json-Manifest.md +61 -0
- data/solara/lib/core/template/brands/json/json_manifest.json +18 -0
- data/solara/lib/core/template/brands/shared/theme.json +213 -29
- data/solara/lib/core/template/config/android_template_config.json +50 -0
- data/solara/lib/core/template/config/flutter_template_config.json +35 -0
- data/solara/lib/core/template/config/ios_template_config.json +50 -0
- data/solara/lib/core/template/configurations.json +46 -0
- data/solara/lib/core/template/project_template_generator.rb +2 -0
- data/solara/lib/solara/version.rb +1 -1
- data/solara/lib/solara.rb +19 -0
- metadata +13 -4
- data/solara/lib/core/dashboard/component/AddFieldSheet.js +0 -175
- data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +0 -73
@@ -1,6 +1,6 @@
|
|
1
1
|
import {DataSource} from './BrandDetailModel.js';
|
2
|
+
import SectionsFormManager from './SectionsFormManager.js';
|
2
3
|
import '../component/OnboardBrandBottomSheet.js';
|
3
|
-
import '../component/AddFieldSheet.js';
|
4
4
|
import '../component/ConfirmationDialog.js';
|
5
5
|
import '../component/MessageBottomSheet.js';
|
6
6
|
|
@@ -15,7 +15,6 @@ class BrandDetailView {
|
|
15
15
|
this.addBrandContainer = document.getElementById('add-brand-container');
|
16
16
|
|
17
17
|
this.sectionsContainer = document.getElementById('sections');
|
18
|
-
this.addFieldSheet = document.getElementById('addFieldSheet');
|
19
18
|
this.confirmationDialog = document.getElementById('confirmationDialog');
|
20
19
|
this.messageBottomSheet = document.getElementById('messageBottomSheet');
|
21
20
|
|
@@ -24,8 +23,9 @@ class BrandDetailView {
|
|
24
23
|
this.addNewBrandBtn = document.getElementById('newBrandBtn');
|
25
24
|
this.exportBrandBtn = document.getElementById('exportBrandBtn');
|
26
25
|
this.allBrandsButton = document.getElementById('allBrandsButton');
|
27
|
-
|
26
|
+
this.syncBrandButton = document.getElementById('syncBrandButton');
|
28
27
|
this.onboardSheet = document.getElementById('onboardBottomSheet');
|
28
|
+
this.sectionsFormManager = new SectionsFormManager();
|
29
29
|
|
30
30
|
this.initializeApp();
|
31
31
|
}
|
@@ -67,199 +67,12 @@ class BrandDetailView {
|
|
67
67
|
}
|
68
68
|
}
|
69
69
|
|
70
|
-
createSection(key, name, inputType) {
|
71
|
-
const section = document.createElement('div');
|
72
|
-
section.className = 'section';
|
73
|
-
|
74
|
-
section.dataset.key = key
|
75
|
-
section.dataset.name = name
|
76
|
-
section.dataset.inputType = inputType
|
77
|
-
|
78
|
-
const titleContainer = document.createElement('div');
|
79
|
-
titleContainer.className = 'section-title-container';
|
80
|
-
|
81
|
-
const title = document.createElement('h2');
|
82
|
-
title.textContent = name;
|
83
|
-
titleContainer.appendChild(title);
|
84
|
-
|
85
|
-
const subtitleElement = document.createElement('p');
|
86
|
-
subtitleElement.className = 'section-subtitle';
|
87
|
-
subtitleElement.textContent = key;
|
88
|
-
titleContainer.appendChild(subtitleElement);
|
89
|
-
|
90
|
-
section.appendChild(titleContainer);
|
91
|
-
|
92
|
-
return section;
|
93
|
-
}
|
94
|
-
|
95
|
-
populateJsonFields(data, container, content, inputType, level = 0) {
|
96
|
-
container.dataset.key = data.key
|
97
|
-
container.dataset.level = `${level}`
|
98
|
-
|
99
|
-
for (const [key, value] of Object.entries(content)) {
|
100
|
-
if (Array.isArray(value)) {
|
101
|
-
this.populateJsonArray(key, value, data, container, content, inputType, level)
|
102
|
-
continue
|
103
|
-
}
|
104
|
-
|
105
|
-
if (value !== null && typeof value === 'object') {
|
106
|
-
this.populateJsonObject(key, value, data, container, content, inputType, level)
|
107
|
-
continue
|
108
|
-
}
|
109
|
-
|
110
|
-
const fieldElement = this.createJsonField(data, key, value, inputType, level)
|
111
|
-
container.appendChild(fieldElement);
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
populateJsonArray(key, value, data, container, content, inputType, level) {
|
116
|
-
const arrayContainer = document.createElement('div');
|
117
|
-
arrayContainer.className = 'json-array';
|
118
|
-
arrayContainer.classList.add(`json-array-${level}`);
|
119
|
-
|
120
|
-
const labelContainer = document.createElement('div');
|
121
|
-
labelContainer.className = 'json-array-label-group';
|
122
|
-
const label = document.createElement('label');
|
123
|
-
label.textContent = key;
|
124
|
-
labelContainer.appendChild(label);
|
125
|
-
|
126
|
-
// TODO: to be implemented later
|
127
|
-
if (false) {
|
128
|
-
const addButton = document.createElement('button');
|
129
|
-
addButton.className = 'add-array-item';
|
130
|
-
addButton.textContent = '+';
|
131
|
-
let lastItemIndex = value.length - 1
|
132
|
-
addButton.addEventListener('click', () => {
|
133
|
-
const itemContainer = document.createElement('div');
|
134
|
-
itemContainer.className = 'json-array-item';
|
135
|
-
|
136
|
-
lastItemIndex += 1
|
137
|
-
let fieldKey = `${key}[${lastItemIndex}]`
|
138
|
-
|
139
|
-
const indexed = container.querySelectorAll(`.json-array-item-indexed-${level}`).length !== 0;
|
140
|
-
if (indexed) {
|
141
|
-
fieldKey = lastItemIndex
|
142
|
-
}
|
143
|
-
const field = this.createJsonField(data, fieldKey, '', inputType, level + 1)
|
144
|
-
field.classList.add(`json-array-item-${level}`);
|
145
|
-
itemContainer.appendChild(field);
|
146
|
-
|
147
|
-
arrayContainer.insertBefore(itemContainer, arrayContainer.lastElementChild);
|
148
|
-
|
149
|
-
this.onSectionChanged(data, container.closest('.section'));
|
150
|
-
});
|
151
|
-
}
|
152
|
-
arrayContainer.appendChild(labelContainer);
|
153
|
-
|
154
|
-
value.forEach((item, index) => {
|
155
|
-
const itemContainer = document.createElement('div');
|
156
|
-
itemContainer.className = 'json-array-item';
|
157
|
-
itemContainer.classList.add(`json-array-item-${level}`);
|
158
|
-
if (typeof item === 'object' && item !== null) {
|
159
|
-
this.populateJsonFields(data, itemContainer, item, inputType, level + 1);
|
160
|
-
} else {
|
161
|
-
itemContainer.dataset.level = `${level + 1}`
|
162
|
-
const field = this.createJsonField(data, `${index}`, item, inputType, level + 1)
|
163
|
-
itemContainer.classList.add(`json-array-item-indexed-${level}`);
|
164
|
-
itemContainer.appendChild(field);
|
165
|
-
}
|
166
|
-
arrayContainer.appendChild(itemContainer);
|
167
|
-
});
|
168
|
-
|
169
|
-
// TODO: to be implemented later
|
170
|
-
// arrayContainer.appendChild(addButton);
|
171
|
-
container.appendChild(arrayContainer);
|
172
|
-
}
|
173
|
-
|
174
|
-
populateJsonObject(key, value, data, container, content, inputType, level) {
|
175
|
-
const objectContainer = document.createElement('div');
|
176
|
-
objectContainer.className = 'json-object';
|
177
|
-
objectContainer.classList.add(`json-object-${level}`);
|
178
|
-
const objectLabel = document.createElement('label');
|
179
|
-
objectLabel.className = 'json-object-title';
|
180
|
-
objectLabel.textContent = key;
|
181
|
-
objectContainer.appendChild(objectLabel);
|
182
|
-
|
183
|
-
this.populateJsonFields(data, objectContainer, value, inputType, level + 1);
|
184
|
-
|
185
|
-
container.appendChild(objectContainer);
|
186
|
-
}
|
187
|
-
|
188
|
-
createJsonField(data, key, value, inputType, level) {
|
189
|
-
const fieldInputType = typeof value === 'boolean' ? 'boolean' : inputType;
|
190
|
-
const container = document.createElement('div');
|
191
|
-
container.className = 'input-group';
|
192
|
-
const label = document.createElement('label');
|
193
|
-
label.textContent = key;
|
194
|
-
container.appendChild(label);
|
195
|
-
|
196
|
-
const inputWrapper = document.createElement('div');
|
197
|
-
inputWrapper.className = 'input-wrapper';
|
198
|
-
|
199
|
-
if (fieldInputType === 'boolean') {
|
200
|
-
const checkbox = document.createElement('input');
|
201
|
-
checkbox.type = 'checkbox';
|
202
|
-
checkbox.id = key;
|
203
|
-
checkbox.checked = value;
|
204
|
-
|
205
|
-
const checkboxLabel = document.createElement('label');
|
206
|
-
checkboxLabel.className = 'checkbox-label';
|
207
|
-
checkboxLabel.htmlFor = key;
|
208
|
-
checkboxLabel.textContent = value ? 'True' : 'False';
|
209
|
-
|
210
|
-
checkbox.addEventListener('change', () => {
|
211
|
-
checkboxLabel.textContent = checkbox.checked ? 'True' : 'False';
|
212
|
-
this.onSectionChanged(data, container.closest('.section'));
|
213
|
-
});
|
214
|
-
|
215
|
-
inputWrapper.appendChild(checkbox);
|
216
|
-
inputWrapper.appendChild(checkboxLabel);
|
217
|
-
} else {
|
218
|
-
const input = document.createElement('input');
|
219
|
-
input.type = fieldInputType;
|
220
|
-
input.id = key;
|
221
|
-
|
222
|
-
console.log(value)
|
223
|
-
if (fieldInputType === 'color') {
|
224
|
-
input.value = value.startsWith('#') ? value : `#${value.substring(4)}`;
|
225
|
-
} else {
|
226
|
-
input.value = value;
|
227
|
-
}
|
228
|
-
|
229
|
-
inputWrapper.appendChild(input);
|
230
|
-
}
|
231
|
-
|
232
|
-
const deleteIcon = document.createElement('span');
|
233
|
-
deleteIcon.className = 'delete-icon';
|
234
|
-
deleteIcon.textContent = '×';
|
235
|
-
deleteIcon.onclick = () => this.onDeleteField(data, container);
|
236
|
-
inputWrapper.appendChild(deleteIcon);
|
237
|
-
|
238
|
-
container.appendChild(inputWrapper);
|
239
|
-
|
240
|
-
container.addEventListener('change', () => this.onSectionChanged(data, container.closest('.section')));
|
241
|
-
|
242
|
-
container.classList.add(`json-field-${level}`);
|
243
|
-
|
244
|
-
return container;
|
245
|
-
}
|
246
|
-
|
247
|
-
showAddFieldForm(data, sectionElement, inputType) {
|
248
|
-
this.addFieldSheet.show(inputType, (name, value) => {
|
249
|
-
const newField = this.createJsonField(data, name, value, inputType, 0);
|
250
|
-
sectionElement.insertBefore(newField, sectionElement.lastElementChild);
|
251
|
-
this.onSectionChanged(data, sectionElement);
|
252
|
-
})
|
253
|
-
}
|
254
|
-
|
255
70
|
showConfirmationDialog(message, onConfirm) {
|
256
71
|
this.confirmationDialog.showDialog(message, onConfirm);
|
257
72
|
}
|
258
73
|
|
259
|
-
|
260
|
-
|
261
|
-
applyChangesButton.style.display = 'block';
|
262
|
-
this.header.style.backgroundColor = '#ff4136';
|
74
|
+
setupSyncBrandButton(color) {
|
75
|
+
this.syncBrandButton.style.display = 'block';
|
263
76
|
}
|
264
77
|
|
265
78
|
showSwitchButton() {
|
@@ -276,14 +89,6 @@ class BrandDetailView {
|
|
276
89
|
this.messageBottomSheet.showMessage(message);
|
277
90
|
}
|
278
91
|
|
279
|
-
setOnSectionChangedHandler(handler) {
|
280
|
-
this.onSectionChanged = handler;
|
281
|
-
}
|
282
|
-
|
283
|
-
setOnDeleteFieldHandler(handler) {
|
284
|
-
this.onDeleteField = handler;
|
285
|
-
}
|
286
|
-
|
287
92
|
showOnboardBrandForm(onSubmit) {
|
288
93
|
this.onboardSheet.show('Brand Details', 'Add Brand', onSubmit);
|
289
94
|
}
|
@@ -309,6 +114,17 @@ class BrandDetailView {
|
|
309
114
|
this.onboardSheet.hide();
|
310
115
|
}
|
311
116
|
|
117
|
+
async toast(message) {
|
118
|
+
const toastElement = document.getElementById('toast');
|
119
|
+
toastElement.textContent = message;
|
120
|
+
toastElement.style.display = 'block';
|
121
|
+
|
122
|
+
setTimeout(() => {
|
123
|
+
toastElement.style.display = 'none';
|
124
|
+
}, 3000);
|
125
|
+
}
|
126
|
+
|
127
|
+
|
312
128
|
}
|
313
129
|
|
314
130
|
export default BrandDetailView;
|
@@ -0,0 +1,232 @@
|
|
1
|
+
import '../component/EditJsonSheet.js';
|
2
|
+
|
3
|
+
class SectionsFormManager {
|
4
|
+
|
5
|
+
constructor() {
|
6
|
+
this.sections = [];
|
7
|
+
this.sectionsContainer = document.getElementById('sections');
|
8
|
+
}
|
9
|
+
|
10
|
+
display(sections, onChange) {
|
11
|
+
this.sections = sections.map((section) => {
|
12
|
+
return new SectionItemManager(
|
13
|
+
section,
|
14
|
+
this.createSection(section),
|
15
|
+
onChange)
|
16
|
+
})
|
17
|
+
this.sections.forEach((item => {
|
18
|
+
item.displayJSONCards()
|
19
|
+
}))
|
20
|
+
}
|
21
|
+
|
22
|
+
createSection(section) {
|
23
|
+
const sectionElement = document.createElement('div');
|
24
|
+
sectionElement.className = 'section';
|
25
|
+
|
26
|
+
sectionElement.dataset.key = section.key
|
27
|
+
sectionElement.dataset.name = section.name
|
28
|
+
|
29
|
+
const titleContainer = document.createElement('div');
|
30
|
+
titleContainer.className = 'section-title-container';
|
31
|
+
|
32
|
+
const title = document.createElement('h2');
|
33
|
+
title.className = "section-title";
|
34
|
+
title.textContent = section.name;
|
35
|
+
titleContainer.appendChild(title);
|
36
|
+
|
37
|
+
sectionElement.appendChild(titleContainer);
|
38
|
+
|
39
|
+
sectionElement.id = section.key;
|
40
|
+
|
41
|
+
this.sectionsContainer.appendChild(sectionElement);
|
42
|
+
|
43
|
+
return sectionElement
|
44
|
+
}
|
45
|
+
|
46
|
+
data() {
|
47
|
+
const data = this.sections.map((section) => {
|
48
|
+
return section.section
|
49
|
+
})
|
50
|
+
return Array.from(data);
|
51
|
+
}
|
52
|
+
|
53
|
+
}
|
54
|
+
|
55
|
+
class SectionItemManager {
|
56
|
+
constructor(section, container, onChange) {
|
57
|
+
this.section = section
|
58
|
+
this.container = container
|
59
|
+
this.onChange = onChange
|
60
|
+
this.editJsonSheet = document.getElementById('editJsonSheet');
|
61
|
+
}
|
62
|
+
|
63
|
+
displayJSONCards() {
|
64
|
+
let cardContent = this.container.querySelector('.card-content')
|
65
|
+
if (cardContent !== null) this.container.innerHTML = ''
|
66
|
+
this.container.appendChild(this.createCard(this.section.content, 'root', null, this.section.key));
|
67
|
+
}
|
68
|
+
|
69
|
+
createCard(obj, key, parent, cardTitle) {
|
70
|
+
const card = document.createElement('div');
|
71
|
+
card.className = 'card';
|
72
|
+
|
73
|
+
const header = document.createElement('div');
|
74
|
+
header.className = 'card-header';
|
75
|
+
header.textContent = key === 'root' ? cardTitle : key;
|
76
|
+
header.onclick = () => {
|
77
|
+
if (key !== 'root') {
|
78
|
+
this.editKey(parent, key)
|
79
|
+
return
|
80
|
+
}
|
81
|
+
this.editJsonSheet.show(
|
82
|
+
JSON.stringify(this.section.content, null, 2),
|
83
|
+
cardTitle,
|
84
|
+
(value) => {
|
85
|
+
this.section.content = value
|
86
|
+
this.displayJSONCards()
|
87
|
+
this.notifyChange()
|
88
|
+
})
|
89
|
+
};
|
90
|
+
|
91
|
+
const actions = document.createElement('div');
|
92
|
+
actions.className = 'card-actions';
|
93
|
+
|
94
|
+
const addBtn = document.createElement('button');
|
95
|
+
addBtn.className = 'add-property-btn';
|
96
|
+
addBtn.innerHTML = '<i class="fas fa-plus"></i>';
|
97
|
+
addBtn.onclick = () => this.addProperty(obj);
|
98
|
+
actions.appendChild(addBtn);
|
99
|
+
|
100
|
+
if (key !== 'root') {
|
101
|
+
const deleteCardBtn = document.createElement('button');
|
102
|
+
deleteCardBtn.className = 'delete-btn';
|
103
|
+
deleteCardBtn.innerHTML = '<i class="fas fa-times"></i>';
|
104
|
+
deleteCardBtn.onclick = () => this.confirmDeleteProperty(parent, key);
|
105
|
+
actions.appendChild(deleteCardBtn);
|
106
|
+
}
|
107
|
+
|
108
|
+
header.appendChild(actions);
|
109
|
+
card.appendChild(header);
|
110
|
+
|
111
|
+
const content = document.createElement('div');
|
112
|
+
content.className = 'card-content';
|
113
|
+
|
114
|
+
const isArray = Array.isArray(obj)
|
115
|
+
|
116
|
+
for (const [k, v] of Object.entries(obj)) {
|
117
|
+
const item = document.createElement('div');
|
118
|
+
|
119
|
+
const cardValueContainer = document.createElement('div');
|
120
|
+
cardValueContainer.className = 'card-value-container';
|
121
|
+
item.appendChild(cardValueContainer);
|
122
|
+
|
123
|
+
const itemKey = document.createElement('span');
|
124
|
+
itemKey.className = 'card-key';
|
125
|
+
itemKey.onclick = () => {
|
126
|
+
if (isArray) return
|
127
|
+
this.editKey(obj, k)
|
128
|
+
};
|
129
|
+
cardValueContainer.appendChild(itemKey);
|
130
|
+
|
131
|
+
if (typeof v === 'object' && v !== null) {
|
132
|
+
item.appendChild(this.createCard(v, k, obj, null));
|
133
|
+
itemKey.textContent = isArray ? `${key}[${k}]` : ''
|
134
|
+
} else {
|
135
|
+
item.className = 'card-item';
|
136
|
+
itemKey.textContent = k.replace(/_/g, ' ')
|
137
|
+
|
138
|
+
if (this.isColorValue(v)) {
|
139
|
+
const itemValue = document.createElement('input');
|
140
|
+
itemValue.type = 'color';
|
141
|
+
itemValue.className = 'card-value';
|
142
|
+
itemValue.value = v;
|
143
|
+
itemValue.onchange = () => this.updateValue(obj, k, itemValue.value);
|
144
|
+
cardValueContainer.appendChild(itemValue);
|
145
|
+
} else {
|
146
|
+
const itemValue = document.createElement('textarea');
|
147
|
+
itemValue.className = 'card-value';
|
148
|
+
itemValue.value = v;
|
149
|
+
itemValue.onchange = () => this.updateValue(obj, k, itemValue.value);
|
150
|
+
cardValueContainer.appendChild(itemValue);
|
151
|
+
}
|
152
|
+
|
153
|
+
const deleteBtn = document.createElement('button');
|
154
|
+
deleteBtn.className = 'delete-btn';
|
155
|
+
deleteBtn.innerHTML = '<i class="fas fa-times"></i>';
|
156
|
+
deleteBtn.onclick = () => this.confirmDeleteProperty(obj, k);
|
157
|
+
cardValueContainer.appendChild(deleteBtn);
|
158
|
+
}
|
159
|
+
|
160
|
+
content.appendChild(item);
|
161
|
+
}
|
162
|
+
|
163
|
+
card.appendChild(content);
|
164
|
+
return card;
|
165
|
+
}
|
166
|
+
|
167
|
+
isColorValue(value) {
|
168
|
+
// Check if the value is a valid color (hex with opacity, RGBA, or RGB)
|
169
|
+
const hexPattern = /^#([0-9A-F]{3}){1,2}([0-9A-F]{2})?$/i; // 3, 6, or 8 hex digits
|
170
|
+
const rgbaPattern = /^rgba?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}\s*,?\s*(0|1|0?\.\d+|1?\.\d+)\s*\)$/;
|
171
|
+
|
172
|
+
return hexPattern.test(value) || rgbaPattern.test(value);
|
173
|
+
}
|
174
|
+
|
175
|
+
editKey(obj, oldKey) {
|
176
|
+
const newKey = prompt('Edit property name:', oldKey);
|
177
|
+
if (newKey && newKey !== oldKey) {
|
178
|
+
obj[newKey] = obj[oldKey];
|
179
|
+
delete obj[oldKey];
|
180
|
+
this.displayJSONCards();
|
181
|
+
}
|
182
|
+
this.notifyChange()
|
183
|
+
}
|
184
|
+
|
185
|
+
updateValue(obj, key, value) {
|
186
|
+
try {
|
187
|
+
obj[key] = JSON.parse(value);
|
188
|
+
} catch {
|
189
|
+
obj[key] = value;
|
190
|
+
}
|
191
|
+
this.displayJSONCards();
|
192
|
+
this.notifyChange()
|
193
|
+
}
|
194
|
+
|
195
|
+
confirmDeleteProperty(obj, key) {
|
196
|
+
const confirmationDialog = document.getElementById('confirmationDialog');
|
197
|
+
confirmationDialog.showDialog(`Are you sure you need to delete: ${key}?`,
|
198
|
+
async () => {
|
199
|
+
this.deleteProperty(obj, key)
|
200
|
+
});
|
201
|
+
}
|
202
|
+
|
203
|
+
deleteProperty(obj, key) {
|
204
|
+
if (Array.isArray(obj)) {
|
205
|
+
obj.splice(key, 1);
|
206
|
+
} else {
|
207
|
+
delete obj[key];
|
208
|
+
}
|
209
|
+
this.displayJSONCards();
|
210
|
+
this.notifyChange()
|
211
|
+
}
|
212
|
+
|
213
|
+
addProperty(obj) {
|
214
|
+
if (Array.isArray(obj)) {
|
215
|
+
obj.push('');
|
216
|
+
} else {
|
217
|
+
const key = prompt('Enter new property name:');
|
218
|
+
if (key) {
|
219
|
+
obj[key] = '';
|
220
|
+
}
|
221
|
+
}
|
222
|
+
this.displayJSONCards();
|
223
|
+
this.notifyChange()
|
224
|
+
}
|
225
|
+
|
226
|
+
notifyChange() {
|
227
|
+
this.onChange(this.section, this.container)
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
|
232
|
+
export default SectionsFormManager;
|