@vue-skuilder/cli 0.1.7 → 0.1.8-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 +122 -8
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +34 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pack.d.ts +10 -0
- package/dist/commands/pack.d.ts.map +1 -1
- package/dist/commands/pack.js +1 -1
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/studio.d.ts.map +1 -1
- package/dist/commands/studio.js +640 -105
- package/dist/commands/studio.js.map +1 -1
- package/dist/commands/unpack.d.ts +12 -0
- package/dist/commands/unpack.d.ts.map +1 -1
- package/dist/commands/unpack.js +1 -1
- package/dist/commands/unpack.js.map +1 -1
- package/dist/express-assets/app.d.ts +6 -0
- package/dist/express-assets/app.d.ts.map +1 -0
- package/dist/express-assets/app.js +209 -0
- package/dist/express-assets/app.js.map +1 -0
- package/dist/express-assets/assets/classroomDesignDoc.js +24 -0
- package/dist/express-assets/assets/courseValidateDocUpdate.js +56 -0
- package/dist/express-assets/assets/get-tagsDesignDoc.json +9 -0
- package/dist/express-assets/attachment-preprocessing/index.d.ts +11 -0
- package/dist/express-assets/attachment-preprocessing/index.d.ts.map +1 -0
- package/dist/express-assets/attachment-preprocessing/index.js +204 -0
- package/dist/express-assets/attachment-preprocessing/index.js.map +1 -0
- package/dist/express-assets/attachment-preprocessing/normalize.d.ts +7 -0
- package/dist/express-assets/attachment-preprocessing/normalize.d.ts.map +1 -0
- package/dist/express-assets/attachment-preprocessing/normalize.js +90 -0
- package/dist/express-assets/attachment-preprocessing/normalize.js.map +1 -0
- package/dist/express-assets/client-requests/classroom-requests.d.ts +26 -0
- package/dist/express-assets/client-requests/classroom-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/classroom-requests.js +171 -0
- package/dist/express-assets/client-requests/classroom-requests.js.map +1 -0
- package/dist/express-assets/client-requests/course-requests.d.ts +10 -0
- package/dist/express-assets/client-requests/course-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/course-requests.js +135 -0
- package/dist/express-assets/client-requests/course-requests.js.map +1 -0
- package/dist/express-assets/client-requests/pack-requests.d.ts +19 -0
- package/dist/express-assets/client-requests/pack-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/pack-requests.js +130 -0
- package/dist/express-assets/client-requests/pack-requests.js.map +1 -0
- package/dist/express-assets/client.d.ts +31 -0
- package/dist/express-assets/client.d.ts.map +1 -0
- package/dist/express-assets/client.js +70 -0
- package/dist/express-assets/client.js.map +1 -0
- package/dist/express-assets/couchdb/authentication.d.ts +4 -0
- package/dist/express-assets/couchdb/authentication.d.ts.map +1 -0
- package/dist/express-assets/couchdb/authentication.js +69 -0
- package/dist/express-assets/couchdb/authentication.js.map +1 -0
- package/dist/express-assets/couchdb/index.d.ts +18 -0
- package/dist/express-assets/couchdb/index.d.ts.map +1 -0
- package/dist/express-assets/couchdb/index.js +52 -0
- package/dist/express-assets/couchdb/index.js.map +1 -0
- package/dist/express-assets/design-docs.d.ts +63 -0
- package/dist/express-assets/design-docs.d.ts.map +1 -0
- package/dist/express-assets/design-docs.js +90 -0
- package/dist/express-assets/design-docs.js.map +1 -0
- package/dist/express-assets/logger.d.ts +3 -0
- package/dist/express-assets/logger.d.ts.map +1 -0
- package/dist/express-assets/logger.js +62 -0
- package/dist/express-assets/logger.js.map +1 -0
- package/dist/express-assets/routes/logs.d.ts +3 -0
- package/dist/express-assets/routes/logs.d.ts.map +1 -0
- package/dist/express-assets/routes/logs.js +274 -0
- package/dist/express-assets/routes/logs.js.map +1 -0
- package/dist/express-assets/utils/env.d.ts +11 -0
- package/dist/express-assets/utils/env.d.ts.map +1 -0
- package/dist/express-assets/utils/env.js +39 -0
- package/dist/express-assets/utils/env.js.map +1 -0
- package/dist/express-assets/utils/processQueue.d.ts +39 -0
- package/dist/express-assets/utils/processQueue.d.ts.map +1 -0
- package/dist/express-assets/utils/processQueue.js +175 -0
- package/dist/express-assets/utils/processQueue.js.map +1 -0
- package/dist/studio-ui-src/App.vue +132 -0
- package/dist/studio-ui-src/api/index.ts +30 -0
- package/dist/studio-ui-src/components/StudioFlush.vue +108 -0
- package/dist/studio-ui-src/config/development.ts +98 -0
- package/dist/studio-ui-src/index.html +13 -0
- package/dist/studio-ui-src/main.ts +148 -0
- package/dist/studio-ui-src/package.json +35 -0
- package/dist/studio-ui-src/router/index.ts +32 -0
- package/dist/studio-ui-src/stores/useAuthStore.ts +3 -0
- package/dist/studio-ui-src/tsconfig.json +28 -0
- package/dist/studio-ui-src/views/BrowseView.vue +82 -0
- package/dist/studio-ui-src/views/BulkImportView.vue +89 -0
- package/dist/studio-ui-src/views/CourseEditorView.vue +62 -0
- package/dist/studio-ui-src/views/CreateCardView.vue +140 -0
- package/dist/studio-ui-src/vite.config.base.js +100 -0
- package/dist/studio-ui-src/vite.config.ts +26 -0
- package/dist/templates/.skuilder/README.md +29 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/ExpressManager.d.ts +28 -0
- package/dist/utils/ExpressManager.d.ts.map +1 -0
- package/dist/utils/ExpressManager.js +166 -0
- package/dist/utils/ExpressManager.js.map +1 -0
- package/dist/utils/NodeFileSystemAdapter.d.ts +6 -0
- package/dist/utils/NodeFileSystemAdapter.d.ts.map +1 -1
- package/dist/utils/NodeFileSystemAdapter.js +29 -1
- package/dist/utils/NodeFileSystemAdapter.js.map +1 -1
- package/dist/utils/error-reporting.d.ts +54 -0
- package/dist/utils/error-reporting.d.ts.map +1 -0
- package/dist/utils/error-reporting.js +143 -0
- package/dist/utils/error-reporting.js.map +1 -0
- package/dist/utils/pack-courses.d.ts.map +1 -1
- package/dist/utils/pack-courses.js +10 -27
- package/dist/utils/pack-courses.js.map +1 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +24 -0
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/questions-hash.d.ts +22 -0
- package/dist/utils/questions-hash.d.ts.map +1 -0
- package/dist/utils/questions-hash.js +96 -0
- package/dist/utils/questions-hash.js.map +1 -0
- package/dist/utils/template.d.ts +1 -1
- package/dist/utils/template.d.ts.map +1 -1
- package/dist/utils/template.js +202 -25
- package/dist/utils/template.js.map +1 -1
- package/eslint.config.mjs +1 -1
- package/package.json +30 -11
- package/src/cli.ts +3 -1
- package/src/commands/init.ts +48 -3
- package/src/commands/pack.ts +1 -1
- package/src/commands/studio.ts +850 -121
- package/src/commands/unpack.ts +1 -1
- package/src/types.ts +5 -0
- package/src/utils/ExpressManager.ts +210 -0
- package/src/utils/NodeFileSystemAdapter.ts +46 -2
- package/src/utils/error-reporting.ts +192 -0
- package/src/utils/pack-courses.ts +11 -36
- package/src/utils/prompts.ts +34 -0
- package/src/utils/questions-hash.ts +109 -0
- package/src/utils/template.ts +231 -27
- package/templates/.skuilder/README.md +29 -0
- package/dist/studio-ui-assets/assets/BrowseView-BJbixGOU.js +0 -2
- package/dist/studio-ui-assets/assets/BrowseView-BJbixGOU.js.map +0 -1
- package/dist/studio-ui-assets/assets/BrowseView-CM4HBO4j.css +0 -1
- package/dist/studio-ui-assets/assets/BulkImportView-DB6DYDJU.js +0 -2
- package/dist/studio-ui-assets/assets/BulkImportView-DB6DYDJU.js.map +0 -1
- package/dist/studio-ui-assets/assets/BulkImportView-g4wQUfPA.css +0 -1
- package/dist/studio-ui-assets/assets/CourseEditorView-BIlhlhw1.js +0 -2
- package/dist/studio-ui-assets/assets/CourseEditorView-BIlhlhw1.js.map +0 -1
- package/dist/studio-ui-assets/assets/CourseEditorView-WuPNLVKp.css +0 -1
- package/dist/studio-ui-assets/assets/CreateCardView-CyNOKCkm.css +0 -1
- package/dist/studio-ui-assets/assets/CreateCardView-DPjPvzzt.js +0 -2
- package/dist/studio-ui-assets/assets/CreateCardView-DPjPvzzt.js.map +0 -1
- package/dist/studio-ui-assets/assets/edit-ui.es-DiUxqbgF.js +0 -330
- package/dist/studio-ui-assets/assets/edit-ui.es-DiUxqbgF.js.map +0 -1
- package/dist/studio-ui-assets/assets/index--zY88pg6.css +0 -14
- package/dist/studio-ui-assets/assets/index-BnAv1C72.js +0 -287
- package/dist/studio-ui-assets/assets/index-BnAv1C72.js.map +0 -1
- package/dist/studio-ui-assets/assets/index-DHMXQY3-.js +0 -192
- package/dist/studio-ui-assets/assets/index-DHMXQY3-.js.map +0 -1
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/dist/studio-ui-assets/assets/vue-DZcMATiC.js +0 -28
- package/dist/studio-ui-assets/assets/vue-DZcMATiC.js.map +0 -1
- package/dist/studio-ui-assets/assets/vuetify-qg7mRxy_.js +0 -6
- package/dist/studio-ui-assets/assets/vuetify-qg7mRxy_.js.map +0 -1
- package/dist/studio-ui-assets/index.html +0 -16
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { createApp } from 'vue';
|
|
2
|
+
import { createPinia } from 'pinia';
|
|
3
|
+
|
|
4
|
+
// Vuetify
|
|
5
|
+
import 'vuetify/styles';
|
|
6
|
+
import { createVuetify } from 'vuetify';
|
|
7
|
+
import * as components from 'vuetify/components';
|
|
8
|
+
import * as directives from 'vuetify/directives';
|
|
9
|
+
import '@mdi/font/css/materialdesignicons.css';
|
|
10
|
+
|
|
11
|
+
// Component library styles
|
|
12
|
+
import '@vue-skuilder/courses/style';
|
|
13
|
+
import '@vue-skuilder/common-ui/style';
|
|
14
|
+
import '@vue-skuilder/edit-ui/style';
|
|
15
|
+
|
|
16
|
+
// Data layer initialization
|
|
17
|
+
import { initializeDataLayer } from '@vue-skuilder/db';
|
|
18
|
+
|
|
19
|
+
import App from './App.vue';
|
|
20
|
+
import router from './router';
|
|
21
|
+
import { getStudioConfig, getConfigErrorMessage } from './config/development';
|
|
22
|
+
|
|
23
|
+
// Initialize Vuetify with all components and directives
|
|
24
|
+
const vuetify = createVuetify({
|
|
25
|
+
components,
|
|
26
|
+
directives,
|
|
27
|
+
theme: {
|
|
28
|
+
defaultTheme: 'light',
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
(async () => {
|
|
33
|
+
// Get studio configuration (CLI-injected or environment variables)
|
|
34
|
+
const studioConfig = getStudioConfig();
|
|
35
|
+
|
|
36
|
+
if (!studioConfig) {
|
|
37
|
+
throw new Error(getConfigErrorMessage());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Parse the CLI-provided CouchDB URL (format: http://localhost:5985)
|
|
41
|
+
const couchUrl = new URL(studioConfig.couchdb.url);
|
|
42
|
+
const serverUrl = `${couchUrl.hostname}:${couchUrl.port}/`;
|
|
43
|
+
|
|
44
|
+
console.log('🎨 Studio Mode: Initializing data layer with CLI-provided CouchDB connection');
|
|
45
|
+
console.log(` Server: ${couchUrl.protocol}//${serverUrl}`);
|
|
46
|
+
console.log(` Username: ${studioConfig.couchdb.username}`);
|
|
47
|
+
|
|
48
|
+
await initializeDataLayer({
|
|
49
|
+
type: 'couch',
|
|
50
|
+
options: {
|
|
51
|
+
COUCHDB_SERVER_PROTOCOL: couchUrl.protocol.replace(':', ''),
|
|
52
|
+
COUCHDB_SERVER_URL: serverUrl,
|
|
53
|
+
COUCHDB_USERNAME: studioConfig.couchdb.username,
|
|
54
|
+
COUCHDB_PASSWORD: studioConfig.couchdb.password,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const pinia = createPinia();
|
|
59
|
+
const app = createApp(App);
|
|
60
|
+
|
|
61
|
+
// Register all course view components globally (like platform-ui)
|
|
62
|
+
console.log('🎨 Studio Mode: Importing course view components');
|
|
63
|
+
const { allCourses: Courses } = await import('@vue-skuilder/courses');
|
|
64
|
+
console.log(' ✅ Course components imported successfully');
|
|
65
|
+
|
|
66
|
+
// Check for custom questions configuration and import if available
|
|
67
|
+
console.log('🎨 Studio Mode: Checking for custom questions configuration');
|
|
68
|
+
let customQuestions = null;
|
|
69
|
+
try {
|
|
70
|
+
console.log(' 📁 Fetching custom-questions-config.json');
|
|
71
|
+
const configResponse = await fetch('/custom-questions-config.json');
|
|
72
|
+
if (configResponse.ok) {
|
|
73
|
+
console.log(' ✅ Custom questions config file found');
|
|
74
|
+
const customConfig = await configResponse.json();
|
|
75
|
+
console.log(' 📋 Custom config parsed:', customConfig);
|
|
76
|
+
if (customConfig.hasCustomQuestions && customConfig.importPath) {
|
|
77
|
+
console.log(`🎨 Studio Mode: Loading custom questions from ${customConfig.packageName}`);
|
|
78
|
+
console.log(` 📦 Import path: ${customConfig.importPath}`);
|
|
79
|
+
try {
|
|
80
|
+
const customModule = await import(customConfig.importPath);
|
|
81
|
+
console.log(' ✅ Custom module imported successfully');
|
|
82
|
+
customQuestions = customModule.allCustomQuestions?.();
|
|
83
|
+
if (customQuestions) {
|
|
84
|
+
console.log(
|
|
85
|
+
` ✅ Loaded custom questions: ${customQuestions.questionClasses?.length || 0} types`
|
|
86
|
+
);
|
|
87
|
+
console.log(' 📊 Custom questions object:', customQuestions);
|
|
88
|
+
} else {
|
|
89
|
+
console.log(' ⚠️ Custom module did not return questions data');
|
|
90
|
+
}
|
|
91
|
+
} catch (importError) {
|
|
92
|
+
console.warn(
|
|
93
|
+
` ⚠️ Failed to import custom questions: ${importError instanceof Error ? importError.message : String(importError)}`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
console.log(
|
|
98
|
+
' ℹ️ Custom config exists but hasCustomQuestions is false or importPath is missing'
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
console.log(' ℹ️ Custom questions config file not found (this is normal)');
|
|
103
|
+
}
|
|
104
|
+
} catch (configError) {
|
|
105
|
+
// No custom questions config - this is normal for default studio mode
|
|
106
|
+
console.log(' ℹ️ No custom questions config available (default studio mode)');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
console.log('🎨 Studio Mode: Collecting view components');
|
|
111
|
+
const viewComponents = Courses.allViewsRaw();
|
|
112
|
+
console.log(` ✅ Collected ${Object.keys(viewComponents).length} base view components`);
|
|
113
|
+
|
|
114
|
+
// Add custom question view components if available
|
|
115
|
+
if (customQuestions?.views) {
|
|
116
|
+
console.log(` 📦 Adding ${customQuestions.views.length} custom question view components`);
|
|
117
|
+
customQuestions.views.forEach((view: any) => {
|
|
118
|
+
if (view.name && view.component) {
|
|
119
|
+
console.log(` ➕ Registering custom view component: ${view.name}`);
|
|
120
|
+
viewComponents[view.name] = view.component;
|
|
121
|
+
} else {
|
|
122
|
+
console.warn(` ⚠️ Skipping invalid custom view (missing name or component):`, view);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
console.log(
|
|
126
|
+
` ✅ Total view components after custom additions: ${Object.keys(viewComponents).length}`
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
console.log(' ℹ️ No custom question views to add');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
Object.entries(viewComponents).forEach(([name, component]) => {
|
|
133
|
+
app.component(name, component);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
app.use(pinia);
|
|
137
|
+
app.use(vuetify);
|
|
138
|
+
app.use(router);
|
|
139
|
+
|
|
140
|
+
// Dynamically import piniaPlugin (like platform-ui)
|
|
141
|
+
const { piniaPlugin, useAuthStore } = await import('@vue-skuilder/common-ui');
|
|
142
|
+
app.use(piniaPlugin, { pinia });
|
|
143
|
+
|
|
144
|
+
// Initialize auth store like standalone-ui does
|
|
145
|
+
await useAuthStore().init();
|
|
146
|
+
|
|
147
|
+
app.mount('#app');
|
|
148
|
+
})();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vue-skuilder/studio-ui",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.1.8-0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"preview": "vite preview",
|
|
12
|
+
"lint": "eslint . --fix",
|
|
13
|
+
"lint:check": "eslint ."
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@mdi/font": "^7.3.67",
|
|
17
|
+
"@vue-skuilder/common": "workspace:*",
|
|
18
|
+
"@vue-skuilder/common-ui": "workspace:*",
|
|
19
|
+
"@vue-skuilder/courses": "workspace:*",
|
|
20
|
+
"@vue-skuilder/db": "workspace:*",
|
|
21
|
+
"@vue-skuilder/edit-ui": "workspace:*",
|
|
22
|
+
"pinia": "^2.3.0",
|
|
23
|
+
"vue": "^3.5.13",
|
|
24
|
+
"vue-router": "^4.2.0",
|
|
25
|
+
"vuetify": "^3.7.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
29
|
+
"eslint": "^9.30.1",
|
|
30
|
+
"typescript": "^5.7.2",
|
|
31
|
+
"vite": "^6.0.9",
|
|
32
|
+
"vue-tsc": "^1.8.0"
|
|
33
|
+
},
|
|
34
|
+
"stableVersion": "0.1.7"
|
|
35
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createRouter, createWebHistory } from 'vue-router';
|
|
2
|
+
import type { RouteRecordRaw } from 'vue-router';
|
|
3
|
+
|
|
4
|
+
const routes: RouteRecordRaw[] = [
|
|
5
|
+
{
|
|
6
|
+
path: '/',
|
|
7
|
+
name: 'browse',
|
|
8
|
+
component: () => import('../views/BrowseView.vue'),
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
path: '/course-editor',
|
|
12
|
+
name: 'course-editor',
|
|
13
|
+
component: () => import('../views/CourseEditorView.vue'),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
path: '/bulk-import',
|
|
17
|
+
name: 'bulk-import',
|
|
18
|
+
component: () => import('../views/BulkImportView.vue'),
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
path: '/create-card',
|
|
22
|
+
name: 'create-card',
|
|
23
|
+
component: () => import('../views/CreateCardView.vue'),
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const router = createRouter({
|
|
28
|
+
history: createWebHistory(),
|
|
29
|
+
routes,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export default router;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "preserve",
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
|
|
23
|
+
/* Node config (for vite.config.ts) */
|
|
24
|
+
"composite": true,
|
|
25
|
+
"allowSyntheticDefaultImports": true
|
|
26
|
+
},
|
|
27
|
+
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "vite.config.ts"]
|
|
28
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="browse-view">
|
|
3
|
+
<div v-if="loading" class="text-center pa-4">
|
|
4
|
+
<v-progress-circular indeterminate />
|
|
5
|
+
<p class="mt-2">Loading course...</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div v-else-if="error" class="text-center pa-4">
|
|
9
|
+
<v-icon color="error" size="48">mdi-alert-circle</v-icon>
|
|
10
|
+
<h2 class="mt-2">Browse Error</h2>
|
|
11
|
+
<p>{{ error }}</p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div v-else-if="courseId">
|
|
15
|
+
<course-information :course-id="courseId" :view-lookup-function="viewLookupFunction" :edit-mode="'full'">
|
|
16
|
+
<template #actions> </template>
|
|
17
|
+
</course-information>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div v-else class="text-center pa-4">
|
|
21
|
+
<v-icon size="48">mdi-school</v-icon>
|
|
22
|
+
<h2 class="mt-2">No Course Loaded</h2>
|
|
23
|
+
<p>Please load a course to start browsing.</p>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup lang="ts">
|
|
29
|
+
import { ref, onMounted } from 'vue';
|
|
30
|
+
import { CourseInformation } from '@vue-skuilder/common-ui';
|
|
31
|
+
import { allCourses } from '@vue-skuilder/courses';
|
|
32
|
+
import { getStudioConfig, getConfigErrorMessage } from '../config/development';
|
|
33
|
+
|
|
34
|
+
// Browse view state
|
|
35
|
+
const loading = ref(true);
|
|
36
|
+
const error = ref<string | null>(null);
|
|
37
|
+
const courseId = ref<string | null>(null);
|
|
38
|
+
|
|
39
|
+
// View lookup function with proper context binding
|
|
40
|
+
const viewLookupFunction = (viewDescription: any) => {
|
|
41
|
+
return allCourses.getView(viewDescription);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Initialize browse view
|
|
45
|
+
onMounted(async () => {
|
|
46
|
+
try {
|
|
47
|
+
// Get studio configuration (CLI-injected or environment variables)
|
|
48
|
+
const studioConfig = getStudioConfig();
|
|
49
|
+
|
|
50
|
+
if (!studioConfig) {
|
|
51
|
+
throw new Error(getConfigErrorMessage());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
courseId.value = studioConfig.database.name;
|
|
55
|
+
loading.value = false;
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('Browse view initialization error:', err);
|
|
58
|
+
error.value = err instanceof Error ? err.message : 'Unknown error';
|
|
59
|
+
loading.value = false;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<style scoped>
|
|
65
|
+
.browse-view {
|
|
66
|
+
height: 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.studio-header {
|
|
70
|
+
padding: 16px 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.studio-header h1 {
|
|
74
|
+
color: rgb(var(--v-theme-primary));
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.studio-header p {
|
|
79
|
+
color: rgb(var(--v-theme-on-surface-variant));
|
|
80
|
+
margin: 0;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="bulk-import-view">
|
|
3
|
+
<v-card>
|
|
4
|
+
<v-card-title>
|
|
5
|
+
<v-icon start>mdi-file-import</v-icon>
|
|
6
|
+
Bulk Import Cards
|
|
7
|
+
</v-card-title>
|
|
8
|
+
|
|
9
|
+
<v-card-text>
|
|
10
|
+
<div v-if="loading" class="text-center pa-4">
|
|
11
|
+
<v-progress-circular indeterminate />
|
|
12
|
+
<p class="mt-2">Loading bulk import tool...</p>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div v-else-if="error" class="text-center pa-4">
|
|
16
|
+
<v-icon color="error" size="24">mdi-alert-circle</v-icon>
|
|
17
|
+
<p class="mt-2 text-error">{{ error }}</p>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div v-else-if="courseId && courseConfig">
|
|
21
|
+
<!-- Bulk Import View from edit-ui package -->
|
|
22
|
+
<bulk-import-view
|
|
23
|
+
:course-cfg="courseConfig"
|
|
24
|
+
:view-lookup-function="allCourses.getView"
|
|
25
|
+
@import-completed="onImportCompleted"
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div v-else>
|
|
30
|
+
<p class="text-center">No course loaded</p>
|
|
31
|
+
</div>
|
|
32
|
+
</v-card-text>
|
|
33
|
+
</v-card>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { ref, onMounted } from 'vue';
|
|
39
|
+
import { BulkImportView } from '@vue-skuilder/edit-ui';
|
|
40
|
+
import { allCourses } from '@vue-skuilder/courses';
|
|
41
|
+
import { getStudioConfig, getConfigErrorMessage } from '../config/development';
|
|
42
|
+
import { getDataLayer } from '@vue-skuilder/db';
|
|
43
|
+
import type { CourseConfig } from '@vue-skuilder/common';
|
|
44
|
+
|
|
45
|
+
// Bulk import state
|
|
46
|
+
const loading = ref(true);
|
|
47
|
+
const error = ref<string | null>(null);
|
|
48
|
+
const courseId = ref<string | null>(null);
|
|
49
|
+
const courseConfig = ref<CourseConfig | null>(null);
|
|
50
|
+
|
|
51
|
+
// Initialize bulk import view
|
|
52
|
+
onMounted(async () => {
|
|
53
|
+
try {
|
|
54
|
+
// Get studio configuration (CLI-injected or environment variables)
|
|
55
|
+
const studioConfig = getStudioConfig();
|
|
56
|
+
|
|
57
|
+
if (!studioConfig) {
|
|
58
|
+
throw new Error(getConfigErrorMessage());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
courseId.value = studioConfig.database.name;
|
|
62
|
+
|
|
63
|
+
// Load course configuration
|
|
64
|
+
const dataLayer = getDataLayer();
|
|
65
|
+
const courseDB = dataLayer.getCourseDB(courseId.value);
|
|
66
|
+
courseConfig.value = await courseDB.getCourseConfig();
|
|
67
|
+
|
|
68
|
+
loading.value = false;
|
|
69
|
+
} catch (err) {
|
|
70
|
+
console.error('Bulk import initialization error:', err);
|
|
71
|
+
error.value = err instanceof Error ? err.message : 'Unknown error';
|
|
72
|
+
loading.value = false;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Handle import completion
|
|
77
|
+
const onImportCompleted = (result: unknown) => {
|
|
78
|
+
console.log('Import completed:', result);
|
|
79
|
+
// Could add success notification here
|
|
80
|
+
};
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style scoped>
|
|
84
|
+
.bulk-import-view {
|
|
85
|
+
max-width: 1200px;
|
|
86
|
+
margin: 0 auto;
|
|
87
|
+
padding: 16px;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="course-editor-view">
|
|
3
|
+
<div v-if="loading" class="text-center pa-4">
|
|
4
|
+
<v-progress-circular indeterminate />
|
|
5
|
+
<p class="mt-2">Loading course editor...</p>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div v-else-if="error" class="text-center pa-4">
|
|
9
|
+
<v-icon color="error" size="48">mdi-alert-circle</v-icon>
|
|
10
|
+
<h2 class="mt-2">Editor Error</h2>
|
|
11
|
+
<p>{{ error }}</p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div v-else-if="courseId">
|
|
15
|
+
<!-- Course Editor from edit-ui package -->
|
|
16
|
+
<course-editor :course="courseId" :view-lookup-function="allCourses.getView" />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div v-else class="text-center pa-4">
|
|
20
|
+
<v-icon size="48">mdi-school</v-icon>
|
|
21
|
+
<h2 class="mt-2">No Course Loaded</h2>
|
|
22
|
+
<p>Please load a course to start editing.</p>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { ref, onMounted } from 'vue';
|
|
29
|
+
import { CourseEditor } from '@vue-skuilder/edit-ui';
|
|
30
|
+
import { allCourses } from '@vue-skuilder/courses';
|
|
31
|
+
import { getStudioConfig, getConfigErrorMessage } from '../config/development';
|
|
32
|
+
|
|
33
|
+
// Course editor state
|
|
34
|
+
const loading = ref(true);
|
|
35
|
+
const error = ref<string | null>(null);
|
|
36
|
+
const courseId = ref<string | null>(null);
|
|
37
|
+
|
|
38
|
+
// Initialize course editor
|
|
39
|
+
onMounted(async () => {
|
|
40
|
+
try {
|
|
41
|
+
// Get studio configuration (CLI-injected or environment variables)
|
|
42
|
+
const studioConfig = getStudioConfig();
|
|
43
|
+
|
|
44
|
+
if (!studioConfig) {
|
|
45
|
+
throw new Error(getConfigErrorMessage());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
courseId.value = studioConfig.database.name;
|
|
49
|
+
loading.value = false;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error('Course editor initialization error:', err);
|
|
52
|
+
error.value = err instanceof Error ? err.message : 'Unknown error';
|
|
53
|
+
loading.value = false;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style scoped>
|
|
59
|
+
.course-editor-view {
|
|
60
|
+
height: 100%;
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="create-card-view">
|
|
3
|
+
<v-card>
|
|
4
|
+
<v-card-title>
|
|
5
|
+
<v-icon start>mdi-card-plus</v-icon>
|
|
6
|
+
Create New Card
|
|
7
|
+
</v-card-title>
|
|
8
|
+
|
|
9
|
+
<v-card-text>
|
|
10
|
+
<div v-if="loading" class="text-center pa-4">
|
|
11
|
+
<v-progress-circular indeterminate />
|
|
12
|
+
<p class="mt-2">Loading card creation form...</p>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div v-else-if="error" class="text-center pa-4">
|
|
16
|
+
<v-icon color="error" size="24">mdi-alert-circle</v-icon>
|
|
17
|
+
<p class="mt-2 text-error">{{ error }}</p>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div v-else-if="courseId && courseConfig">
|
|
21
|
+
<!-- Card type selector -->
|
|
22
|
+
<v-select
|
|
23
|
+
v-if="availableDataShapes.length > 1"
|
|
24
|
+
v-model="selectedDataShapeIndex"
|
|
25
|
+
:items="
|
|
26
|
+
availableDataShapes.map((shape, index) => ({
|
|
27
|
+
title: shape.name.replace(/^.*\./, ''),
|
|
28
|
+
value: index,
|
|
29
|
+
}))
|
|
30
|
+
"
|
|
31
|
+
label="Card Type"
|
|
32
|
+
class="mb-4"
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
<!-- Data Input Form from edit-ui package -->
|
|
36
|
+
<data-input-form
|
|
37
|
+
v-if="selectedDataShape"
|
|
38
|
+
:course-id="courseId"
|
|
39
|
+
:course-cfg="courseConfig"
|
|
40
|
+
:data-shape="selectedDataShape"
|
|
41
|
+
:view-lookup-function="allCourses.getView"
|
|
42
|
+
@card-created="onCardCreated"
|
|
43
|
+
/>
|
|
44
|
+
|
|
45
|
+
<div v-else-if="availableDataShapes.length === 0" class="text-center pa-4">
|
|
46
|
+
<v-icon color="warning" size="24">mdi-alert</v-icon>
|
|
47
|
+
<p class="mt-2">No card types available in this course</p>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div v-else>
|
|
52
|
+
<p class="text-center">No course loaded</p>
|
|
53
|
+
</div>
|
|
54
|
+
</v-card-text>
|
|
55
|
+
</v-card>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<script setup lang="ts">
|
|
60
|
+
import { ref, onMounted, computed } from 'vue';
|
|
61
|
+
import { DataInputForm } from '@vue-skuilder/edit-ui';
|
|
62
|
+
import { allCourses } from '@vue-skuilder/courses';
|
|
63
|
+
import { getStudioConfig, getConfigErrorMessage } from '../config/development';
|
|
64
|
+
import { getDataLayer } from '@vue-skuilder/db';
|
|
65
|
+
import type { CourseConfig, DataShape } from '@vue-skuilder/common';
|
|
66
|
+
|
|
67
|
+
// Create card state
|
|
68
|
+
const loading = ref(true);
|
|
69
|
+
const error = ref<string | null>(null);
|
|
70
|
+
const courseId = ref<string | null>(null);
|
|
71
|
+
const courseConfig = ref<CourseConfig | null>(null);
|
|
72
|
+
const selectedDataShapeIndex = ref<number>(0);
|
|
73
|
+
|
|
74
|
+
// Get available data shapes
|
|
75
|
+
const availableDataShapes = computed(() => {
|
|
76
|
+
if (!courseConfig.value?.dataShapes) return [];
|
|
77
|
+
return courseConfig.value.dataShapes;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Get currently selected data shape
|
|
81
|
+
const selectedDataShape = computed((): DataShape | null => {
|
|
82
|
+
const shapes = availableDataShapes.value;
|
|
83
|
+
if (shapes.length === 0) return null;
|
|
84
|
+
|
|
85
|
+
// Find the corresponding DataShape from allCourses
|
|
86
|
+
const shapeName = shapes[selectedDataShapeIndex.value]?.name;
|
|
87
|
+
if (!shapeName) return null;
|
|
88
|
+
|
|
89
|
+
// Search through all courses to find the DataShape
|
|
90
|
+
for (const course of allCourses.courses) {
|
|
91
|
+
for (const question of course.questions) {
|
|
92
|
+
for (const dataShape of question.dataShapes) {
|
|
93
|
+
if (dataShape.name === shapeName.split('.').pop()) {
|
|
94
|
+
return dataShape;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Initialize create card view
|
|
103
|
+
onMounted(async () => {
|
|
104
|
+
try {
|
|
105
|
+
// Get studio configuration (CLI-injected or environment variables)
|
|
106
|
+
const studioConfig = getStudioConfig();
|
|
107
|
+
|
|
108
|
+
if (!studioConfig) {
|
|
109
|
+
throw new Error(getConfigErrorMessage());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
courseId.value = studioConfig.database.name;
|
|
113
|
+
|
|
114
|
+
// Load course configuration
|
|
115
|
+
const dataLayer = getDataLayer();
|
|
116
|
+
const courseDB = dataLayer.getCourseDB(courseId.value);
|
|
117
|
+
courseConfig.value = await courseDB.getCourseConfig();
|
|
118
|
+
|
|
119
|
+
loading.value = false;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
console.error('Create card initialization error:', err);
|
|
122
|
+
error.value = err instanceof Error ? err.message : 'Unknown error';
|
|
123
|
+
loading.value = false;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Handle card creation
|
|
128
|
+
const onCardCreated = (cardData: unknown) => {
|
|
129
|
+
console.log('Card created:', cardData);
|
|
130
|
+
// Could add success notification or redirect here
|
|
131
|
+
};
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<style scoped>
|
|
135
|
+
.create-card-view {
|
|
136
|
+
max-width: 1200px;
|
|
137
|
+
margin: 0 auto;
|
|
138
|
+
padding: 16px;
|
|
139
|
+
}
|
|
140
|
+
</style>
|