@appscode/design-system 2.17.70-alpha-1 → 2.17.70-alpha-4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appscode/design-system",
3
- "version": "2.17.70-alpha-1",
3
+ "version": "2.17.70-alpha-4",
4
4
  "description": "A design system for Appscode websites and dashboards made using Bulma",
5
5
  "main": "main.scss",
6
6
  "scripts": {
@@ -50,7 +50,6 @@ import AcDropdownMenu from "./v3/dropdown/DropdownMenu.vue";
50
50
 
51
51
  import AcEditor from "./v3/editor/Editor.vue";
52
52
  import AcFilteredFileEditor from "./v3/editor/FilteredFileEditor.vue";
53
- import AcLightweightEditor from "./v3/editor/LightweightEditor.vue";
54
53
  import AcMonacoEditor from "./v3/editor/MonacoEditor.vue";
55
54
  import AcResourceKeyValueEditor from "./v3/editor/ResourceKeyValueEditor.vue";
56
55
 
@@ -233,7 +232,6 @@ export {
233
232
  AcDropdownMenu,
234
233
  AcEditor,
235
234
  AcFilteredFileEditor,
236
- AcLightweightEditor,
237
235
  AcMonacoEditor,
238
236
  AcResourceKeyValueEditor,
239
237
  AcFooterArea,
@@ -106,3 +106,19 @@ onMounted(() => {
106
106
  </div>
107
107
  </ac-input-text>
108
108
  </template>
109
+
110
+ <style lang="scss">
111
+ .ac-single-input {
112
+ input.ac-input:read-only {
113
+ background-color: #eeeeee !important;
114
+ cursor: not-allowed !important;
115
+ }
116
+
117
+ label.show-label::after {
118
+ background-color: #eeeeee !important;
119
+ }
120
+ :hover {
121
+ border-color: #cbd5e1 !important;
122
+ }
123
+ }
124
+ </style>
@@ -4,7 +4,7 @@ import { computed, defineAsyncComponent, ref } from "vue";
4
4
  import GridIcon from "../icons/GridIcon.vue";
5
5
 
6
6
  export interface Props {
7
- currentApp?: "console" | "db" | "platform" | "billing" | "selfhost" | "learn" | "grafana";
7
+ currentApp?: "console" | "db" | "platform" | "billing" | "selfhost" | "learn" | "grafana" | "observe";
8
8
  baseUrl?: string;
9
9
  activeOrganization?: string;
10
10
  rootDomain?: string;
@@ -41,6 +41,13 @@ const appList = [
41
41
  port: "3005",
42
42
  sub_title: "Analyze your activities",
43
43
  },
44
+ {
45
+ name: "observe",
46
+ icon_url: "https://cdn.appscode.com/images/products/observe/logos/observe.png",
47
+ title: "Observe",
48
+ port: "5992",
49
+ sub_title: "Observe your system",
50
+ },
44
51
  {
45
52
  name: "selfhost",
46
53
  icon_url: "https://cdn.appscode.com/images/products/selfhost/logos/selfhost.svg",
@@ -1,343 +0,0 @@
1
- <template>
2
- <div :id="id" ref="editorRef" class="lightweight-editor" :style="style"></div>
3
- </template>
4
-
5
- <script setup lang="ts">
6
- import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
7
- import { EditorState } from "@codemirror/state";
8
- import { EditorView, keymap, lineNumbers, drawSelection, dropCursor } from "@codemirror/view";
9
- import { foldGutter, syntaxHighlighting, defaultHighlightStyle, indentUnit } from "@codemirror/language";
10
- import { defaultKeymap, insertTab, history, historyKeymap } from "@codemirror/commands";
11
- import { search, searchKeymap as searchKeys, highlightSelectionMatches } from "@codemirror/search";
12
- import { json } from "@codemirror/lang-json";
13
- import { yaml } from "@codemirror/lang-yaml";
14
- import { linter, lintGutter } from "@codemirror/lint";
15
- import Ajv from "ajv";
16
- import * as yamlParser from "js-yaml";
17
-
18
- interface Props {
19
- id?: string;
20
- modelValue?: string;
21
- language?: "json" | "yaml";
22
- width?: string | number;
23
- height?: string | number;
24
- schema?: Record<string, any>;
25
- enableSearch?: boolean;
26
- readOnly?: boolean;
27
- validate?: boolean;
28
- }
29
-
30
- const props = withDefaults(defineProps<Props>(), {
31
- id: "",
32
- modelValue: "",
33
- language: "yaml",
34
- width: "100%",
35
- schema: undefined,
36
- height: "300px",
37
- enableSearch: true,
38
- readOnly: false,
39
- validate: true,
40
- });
41
-
42
- const emit = defineEmits<{
43
- "update:modelValue": [value: string];
44
- "validation-error": [errors: any[]];
45
- change: [value: string];
46
- }>();
47
-
48
- const editorRef = ref<HTMLElement>();
49
- let editorView: EditorView | null = null;
50
- let isUpdatingFromWithin = false;
51
- const ajv = new Ajv({ allErrors: true });
52
-
53
- const style = computed(() => ({
54
- width: typeof props.width === "number" ? `${props.width}px` : props.width,
55
- height: typeof props.height === "number" ? `${props.height}px` : props.height,
56
- }));
57
-
58
- // Create linter for validation
59
- const createLinter = () => {
60
- return linter((view) => {
61
- const diagnostics: any[] = [];
62
- const content = view.state.doc.toString();
63
-
64
- // Skip validation for empty content
65
- if (!content.trim() || !props.validate) {
66
- emit("validation-error", []);
67
- return [];
68
- }
69
-
70
- try {
71
- let parsedContent: any;
72
-
73
- // Parse content based on language for syntax validation
74
- if (props.language === "json") {
75
- parsedContent = JSON.parse(content);
76
- } else {
77
- parsedContent = yamlParser.load(content);
78
- }
79
-
80
- // If schema is provided, validate against it
81
- if (props.schema && parsedContent !== null) {
82
- const validate = ajv.compile(props.schema);
83
- const valid = validate(parsedContent);
84
-
85
- if (!valid && validate.errors) {
86
- // Process all schema validation errors
87
- validate.errors.forEach((error, index) => {
88
- const errorPath = error.instancePath || error.schemaPath || "";
89
- const line = getLineFromPath(content, errorPath);
90
- const lineInfo = view.state.doc.line(Math.min(line, view.state.doc.lines));
91
-
92
- // Try to find the specific position of the error within the line
93
- const { from, to } = getErrorPosition(lineInfo, error, content);
94
-
95
- diagnostics.push({
96
- from,
97
- to,
98
- severity: "error",
99
- message: `Schema validation: ${error.message}`,
100
- source: `schema-validation-${index}`,
101
- });
102
- });
103
-
104
- // Emit validation errors
105
- emit("validation-error", validate.errors);
106
- } else {
107
- emit("validation-error", []);
108
- }
109
- } else {
110
- // No schema errors if parsing succeeded
111
- emit("validation-error", []);
112
- }
113
- } catch (parseError: any) {
114
- // Handle syntax/parse errors
115
- const line = getLineFromError(parseError);
116
- const lineInfo = view.state.doc.line(Math.min(line, view.state.doc.lines));
117
-
118
- // For syntax errors, try to find the specific position if possible
119
- let from = lineInfo.from;
120
- let to = lineInfo.to;
121
-
122
- if (parseError.mark && parseError.mark.column !== undefined) {
123
- // YAML errors often have column information
124
- from = lineInfo.from + parseError.mark.column;
125
- to = Math.min(from + 10, lineInfo.to); // Highlight a small range
126
- } else if (parseError.message.includes("position")) {
127
- // JSON errors might have position info
128
- const posMatch = parseError.message.match(/position (\d+)/);
129
- if (posMatch) {
130
- const pos = parseInt(posMatch[1]);
131
- from = Math.min(pos, content.length);
132
- to = Math.min(from + 5, content.length);
133
- }
134
- }
135
-
136
- diagnostics.push({
137
- from,
138
- to,
139
- severity: "error",
140
- message: `Syntax error: ${parseError.message}`,
141
- source: "syntax-error",
142
- });
143
-
144
- emit("validation-error", [{ message: `Syntax error: ${parseError.message}`, instancePath: "/" }]);
145
- }
146
-
147
- return diagnostics;
148
- });
149
- };
150
-
151
- // Helper function to get line number from JSON path
152
- const getLineFromPath = (content: string, path: string): number => {
153
- const lines = content.split("\n");
154
- const pathParts = path.split("/").filter(Boolean);
155
-
156
- if (pathParts.length === 0) return 1;
157
-
158
- // Try to find the property/key mentioned in the path
159
- const searchTerms = pathParts.slice(-2); // Get last two parts for better matching
160
-
161
- for (let i = 0; i < lines.length; i++) {
162
- const line = lines[i];
163
- // Check if line contains any of the search terms
164
- if (
165
- searchTerms.some(
166
- (term) =>
167
- line.includes(`"${term}"`) || line.includes(`${term}:`) || line.includes(`'${term}'`) || line.includes(term),
168
- )
169
- ) {
170
- return i + 1;
171
- }
172
- }
173
- return 1;
174
- };
175
-
176
- // Helper function to get specific error position within a line
177
- const getErrorPosition = (lineInfo: any, error: any, content: string) => {
178
- const lineText = content.slice(lineInfo.from, lineInfo.to);
179
-
180
- // Try to find the specific field/property that has the error
181
- if (error.instancePath) {
182
- const pathParts = error.instancePath.split("/").filter(Boolean);
183
- const fieldName = pathParts[pathParts.length - 1];
184
-
185
- if (fieldName) {
186
- // Look for the field name in the line
187
- const fieldMatch = lineText.match(new RegExp(`["']?${fieldName}["']?\\s*:`));
188
- if (fieldMatch) {
189
- const matchStart = lineInfo.from + fieldMatch.index!;
190
- const matchEnd = matchStart + fieldMatch[0].length;
191
- return { from: matchStart, to: matchEnd };
192
- }
193
- }
194
- }
195
-
196
- // If we can't find the specific field, highlight the whole line
197
- return { from: lineInfo.from, to: lineInfo.to };
198
- };
199
-
200
- // Helper function to get line number from parse error
201
- const getLineFromError = (error: any): number => {
202
- if (error.mark && error.mark.line) {
203
- return error.mark.line + 1;
204
- }
205
- // Try to extract line number from error message
206
- const lineMatch = error.message.match(/line (\d+)/i);
207
- if (lineMatch) {
208
- return parseInt(lineMatch[1]);
209
- }
210
- return 1;
211
- };
212
-
213
- // Create editor extensions
214
- const createExtensions = () => {
215
- const extensions = [
216
- history(),
217
- lineNumbers(),
218
- foldGutter(),
219
- drawSelection(),
220
- dropCursor(),
221
- syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
222
- indentUnit.of(" "), // Set indent to 2 spaces
223
- keymap.of([
224
- { key: "Tab", run: insertTab },
225
- ...historyKeymap,
226
- ...defaultKeymap,
227
- ...(props.enableSearch ? searchKeys : []),
228
- ]),
229
- EditorView.updateListener.of((update) => {
230
- if (update.docChanged) {
231
- isUpdatingFromWithin = true;
232
- const newValue = update.state.doc.toString();
233
- emit("update:modelValue", newValue);
234
- emit("change", newValue);
235
- // Reset flag after Vue has processed the update
236
- nextTick(() => {
237
- isUpdatingFromWithin = false;
238
- });
239
- }
240
- }),
241
- ];
242
-
243
- // Add language support
244
- if (props.language === "json") {
245
- extensions.push(json());
246
- } else {
247
- extensions.push(yaml());
248
- }
249
-
250
- // Add search if enabled
251
- if (props.enableSearch) {
252
- extensions.push(search(), highlightSelectionMatches());
253
- }
254
-
255
- // Add linting - always enabled for syntax validation
256
- extensions.push(lintGutter(), createLinter());
257
-
258
- // Add read-only state - always add editable extension
259
- extensions.push(EditorView.editable.of(!props.readOnly));
260
- if (props.readOnly) {
261
- extensions.push(EditorState.readOnly.of(true));
262
- }
263
-
264
- return extensions;
265
- };
266
-
267
- const initializeEditor = async () => {
268
- if (!editorRef.value) return;
269
-
270
- const state = EditorState.create({
271
- doc: props.modelValue,
272
- extensions: createExtensions(),
273
- });
274
-
275
- editorView = new EditorView({
276
- state,
277
- parent: editorRef.value,
278
- });
279
- };
280
-
281
- const updateEditor = () => {
282
- if (!editorView) return;
283
-
284
- // Skip update if the change is coming from within the editor
285
- if (isUpdatingFromWithin) return;
286
-
287
- const currentValue = editorView.state.doc.toString();
288
- if (props.modelValue !== currentValue) {
289
- editorView.dispatch({
290
- changes: {
291
- from: 0,
292
- to: editorView.state.doc.length,
293
- insert: props.modelValue,
294
- },
295
- });
296
- }
297
- };
298
-
299
- const recreateEditor = async () => {
300
- if (editorView) {
301
- editorView.destroy();
302
- editorView = null;
303
- }
304
- await nextTick();
305
- initializeEditor();
306
- };
307
-
308
- // Expose methods
309
- const getEditor = () => editorView;
310
- const focus = () => editorView?.focus();
311
- const setValue = (value: string) => {
312
- if (!editorView) return;
313
- editorView.dispatch({
314
- changes: {
315
- from: 0,
316
- to: editorView.state.doc.length,
317
- insert: value,
318
- },
319
- });
320
- };
321
- const getValue = () => editorView?.state.doc.toString() || "";
322
-
323
- defineExpose({
324
- getEditor,
325
- focus,
326
- setValue,
327
- getValue,
328
- });
329
-
330
- // Watchers
331
- watch(() => props.modelValue, updateEditor);
332
- watch(() => [props.language, props.schema, props.readOnly], recreateEditor);
333
-
334
- onMounted(() => {
335
- initializeEditor();
336
- });
337
-
338
- onUnmounted(() => {
339
- if (editorView) {
340
- editorView.destroy();
341
- }
342
- });
343
- </script>