@vue-skuilder/platform-ui 0.1.1

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.
Files changed (108) hide show
  1. package/LICENCE +661 -0
  2. package/README.md +64 -0
  3. package/dist/assets/Roboto-Black-B0ZKieaB.woff +0 -0
  4. package/dist/assets/Roboto-Black-VhoA2qKx.woff2 +0 -0
  5. package/dist/assets/Roboto-BlackItalic-D0gSnuIb.woff +0 -0
  6. package/dist/assets/Roboto-BlackItalic-D4yie1YO.woff2 +0 -0
  7. package/dist/assets/Roboto-Bold-D9plYbeK.woff +0 -0
  8. package/dist/assets/Roboto-Bold-hN3duQhD.woff2 +0 -0
  9. package/dist/assets/Roboto-BoldItalic-BWDm51uc.woff2 +0 -0
  10. package/dist/assets/Roboto-BoldItalic-CyLKvOHD.woff +0 -0
  11. package/dist/assets/Roboto-Light-Cu-PAxXt.woff +0 -0
  12. package/dist/assets/Roboto-Light-DHTugVNA.woff2 +0 -0
  13. package/dist/assets/Roboto-LightItalic-CZg5kHIB.woff +0 -0
  14. package/dist/assets/Roboto-LightItalic-JQyp2Y3P.woff2 +0 -0
  15. package/dist/assets/Roboto-Medium-ByKogCTi.woff2 +0 -0
  16. package/dist/assets/Roboto-Medium-b81vv18W.woff +0 -0
  17. package/dist/assets/Roboto-MediumItalic-DFQ-RYa0.woff +0 -0
  18. package/dist/assets/Roboto-MediumItalic-i1eR0KbF.woff2 +0 -0
  19. package/dist/assets/Roboto-Regular-BX5l9hRW.woff +0 -0
  20. package/dist/assets/Roboto-Regular-C6rbFxYz.woff2 +0 -0
  21. package/dist/assets/Roboto-RegularItalic-BjnLZsam.woff +0 -0
  22. package/dist/assets/Roboto-RegularItalic-CvPUdkvM.woff2 +0 -0
  23. package/dist/assets/Roboto-Thin-BfJvJcog.woff +0 -0
  24. package/dist/assets/Roboto-Thin-NicBC1pN.woff2 +0 -0
  25. package/dist/assets/Roboto-ThinItalic-CKlCjrO_.woff2 +0 -0
  26. package/dist/assets/Roboto-ThinItalic-DnIWFxRE.woff +0 -0
  27. package/dist/assets/index-CQ-sNKGW.css +14 -0
  28. package/dist/assets/index-EbqpUgvM.js +161 -0
  29. package/dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
  30. package/dist/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
  31. package/dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
  32. package/dist/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
  33. package/dist/assets/workbox-window.prod.es5-p40uij6f.js +1 -0
  34. package/dist/favicon.ico +0 -0
  35. package/dist/img/icons/safari-pinned-tab.svg +149 -0
  36. package/dist/index.html +19 -0
  37. package/dist/manifest.json +20 -0
  38. package/dist/manifest.webmanifest +1 -0
  39. package/dist/robots.txt +2 -0
  40. package/dist/sw.js +1 -0
  41. package/dist/workbox-1be04862.js +1 -0
  42. package/package.json +105 -0
  43. package/src/App.vue +156 -0
  44. package/src/ENVIRONMENT_VARS.ts +79 -0
  45. package/src/components/Classrooms/ClassroomCtrlPanel.vue +206 -0
  46. package/src/components/Classrooms/CreateClassroom.vue +159 -0
  47. package/src/components/Classrooms/JoinCode.vue +83 -0
  48. package/src/components/Courses/CourseCardBrowser.vue +365 -0
  49. package/src/components/Courses/CourseEditor.vue +164 -0
  50. package/src/components/Courses/CourseInformation.vue +164 -0
  51. package/src/components/Courses/CourseRouter.vue +116 -0
  52. package/src/components/Courses/CourseStubCard.vue +76 -0
  53. package/src/components/Courses/EloModeration.vue +122 -0
  54. package/src/components/Courses/TagInformation.vue +209 -0
  55. package/src/components/Edit/BulkImport/CardPreviewList.vue +345 -0
  56. package/src/components/Edit/BulkImportView.vue +633 -0
  57. package/src/components/Edit/CardBrowser.vue +79 -0
  58. package/src/components/Edit/ComponentRegistration/ComponentRegistration.vue +235 -0
  59. package/src/components/Edit/ComponentRegistration/UnregisteredComponentsTable.vue +19 -0
  60. package/src/components/Edit/CourseEditor.vue +162 -0
  61. package/src/components/Edit/NavigationStrategy/NavigationStrategyEditor.vue +170 -0
  62. package/src/components/Edit/NavigationStrategy/NavigationStrategyList.vue +92 -0
  63. package/src/components/Edit/TagsInput.vue +247 -0
  64. package/src/components/Edit/ViewableDataInputForm/DataInputForm.vue +524 -0
  65. package/src/components/Edit/ViewableDataInputForm/FieldInput.types.ts +33 -0
  66. package/src/components/Edit/ViewableDataInputForm/FieldInputs/AudioInput.vue +188 -0
  67. package/src/components/Edit/ViewableDataInputForm/FieldInputs/ChessPuzzleInput.vue +79 -0
  68. package/src/components/Edit/ViewableDataInputForm/FieldInputs/FieldInput.css +12 -0
  69. package/src/components/Edit/ViewableDataInputForm/FieldInputs/ImageInput.vue +231 -0
  70. package/src/components/Edit/ViewableDataInputForm/FieldInputs/IntegerInput.vue +49 -0
  71. package/src/components/Edit/ViewableDataInputForm/FieldInputs/MarkdownInput.vue +34 -0
  72. package/src/components/Edit/ViewableDataInputForm/FieldInputs/MediaDragDropUploader.vue +246 -0
  73. package/src/components/Edit/ViewableDataInputForm/FieldInputs/MidiInput.vue +113 -0
  74. package/src/components/Edit/ViewableDataInputForm/FieldInputs/NumberInput.vue +49 -0
  75. package/src/components/Edit/ViewableDataInputForm/FieldInputs/StringInput.vue +49 -0
  76. package/src/components/Edit/ViewableDataInputForm/FieldInputs/typeValidators.ts +49 -0
  77. package/src/components/Edit/ViewableDataInputForm/OptionsFieldInput.ts +161 -0
  78. package/src/components/Study/SessionConfiguration.vue +371 -0
  79. package/src/components/TextSwap.vue +65 -0
  80. package/src/components/User/UserStats.vue +30 -0
  81. package/src/dev/DataInputFormTester.vue +117 -0
  82. package/src/dev/readme.md +3 -0
  83. package/src/enums.ts +0 -0
  84. package/src/glyphs.txt +933 -0
  85. package/src/main.ts +45 -0
  86. package/src/plugins/vuetify.ts +41 -0
  87. package/src/registerServiceWorker.ts +18 -0
  88. package/src/router.ts +184 -0
  89. package/src/server/index.spec.ts +192 -0
  90. package/src/server/index.ts +71 -0
  91. package/src/shims-vue.d.ts +5 -0
  92. package/src/store.mock.ts +122 -0
  93. package/src/stores/useDataInputFormStore.ts +49 -0
  94. package/src/stores/useFieldInputStore.ts +191 -0
  95. package/src/types/shims-vuetify.d.ts +12 -0
  96. package/src/types/svg.d.ts +4 -0
  97. package/src/utils/bulkImport/index.ts +94 -0
  98. package/src/views/About.vue +29 -0
  99. package/src/views/Admin.vue +128 -0
  100. package/src/views/Classrooms.vue +258 -0
  101. package/src/views/Courses.vue +265 -0
  102. package/src/views/Home.vue +154 -0
  103. package/src/views/Login.vue +75 -0
  104. package/src/views/ReleaseNotes.vue +20 -0
  105. package/src/views/SignUp.vue +32 -0
  106. package/src/views/Study.vue +261 -0
  107. package/src/views/User.vue +109 -0
  108. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,116 @@
1
+ <template>
2
+ <div>
3
+ <div v-if="initComplete">
4
+ <course-information v-if="courseId !== undefined && courseId !== ''" :course-id="courseId" />
5
+ <v-container v-else-if="candidates.length === 0">
6
+ <v-row class="text-h4">
7
+ {{ query }}
8
+ </v-row>
9
+ <v-divider></v-divider>
10
+ <v-row class="ma-3 text-h5">Nothing here!</v-row>
11
+
12
+ <v-row class="ma-3">
13
+ <v-dialog v-model="newCourseDialog" fullscreen transition="dialog-bottom-transition" :overlay="false">
14
+ <template #activator="{ props }">
15
+ <v-btn color="primary" v-bind="props">Start a new Quilt</v-btn>
16
+ </template>
17
+ <course-editor :name="query" @course-editing-complete="newCourseDialog = false" />
18
+ </v-dialog>
19
+ </v-row>
20
+ </v-container>
21
+ <v-container v-else>
22
+ <div>
23
+ <span class="text-h3">{{ query }} </span> <span class="text-h5">could refer to:</span>
24
+ <v-divider></v-divider>
25
+
26
+ <div v-for="(c, i) in candidates" :key="i" class="ma-5">
27
+ <v-row class="text-h5">
28
+ <a @click="loadQuery(c.courseID)">{{ c.name }} </a>
29
+ -
30
+ <v-text-field
31
+ :id="`${i}-disambiguator`"
32
+ v-model="c.disambiguator"
33
+ label="Disambiguator"
34
+ @change="update(c)"
35
+ ></v-text-field>
36
+ {{ c.description }}
37
+ </v-row>
38
+ </div>
39
+ </div>
40
+ </v-container>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script lang="ts">
46
+ import { defineComponent } from 'vue';
47
+ import { getDataLayer } from '@vue-skuilder/db';
48
+ import { CourseConfig } from '@vue-skuilder/common';
49
+ import CourseEditor from './CourseEditor.vue';
50
+ import CourseInformation from './CourseInformation.vue';
51
+
52
+ export default defineComponent({
53
+ name: 'CourseRouter',
54
+
55
+ components: {
56
+ CourseInformation,
57
+ CourseEditor,
58
+ },
59
+
60
+ props: {
61
+ query: {
62
+ type: String,
63
+ required: true,
64
+ },
65
+ },
66
+
67
+ data() {
68
+ return {
69
+ courseList: [] as CourseConfig[],
70
+ courseId: undefined as string | undefined,
71
+ candidates: [] as CourseConfig[],
72
+ newCourseDialog: false,
73
+ initComplete: false,
74
+ };
75
+ },
76
+
77
+ async created() {
78
+ this.courseList = await getDataLayer().getCoursesDB().getCourseList();
79
+ this.loadQuery();
80
+ },
81
+
82
+ methods: {
83
+ update(c: CourseConfig) {
84
+ if (c.courseID && c.disambiguator) {
85
+ getDataLayer().getCoursesDB().disambiguateCourse(c.courseID, c.disambiguator);
86
+ } else {
87
+ // todo: indicate error on input box
88
+ }
89
+ },
90
+
91
+ loadQuery(q?: string) {
92
+ let query: string;
93
+ if (q) {
94
+ query = q.toLowerCase();
95
+ } else {
96
+ query = this.query.toLowerCase();
97
+ }
98
+
99
+ this.candidates = this.courseList.filter((c) => {
100
+ const snakedName = c.name.replaceAll(' ', '_').toLowerCase();
101
+ return query === snakedName || query === c.courseID || query === `${snakedName}_(${c.disambiguator})`;
102
+ });
103
+
104
+ if (this.candidates.length === 1) {
105
+ this.courseId = this.candidates[0].courseID!;
106
+ } else if (this.candidates.length === 0) {
107
+ this.courseId = '';
108
+ }
109
+
110
+ this.initComplete = true;
111
+ },
112
+ },
113
+ });
114
+ </script>
115
+
116
+ <style></style>
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <v-card v-if="!updatePending && courseConfig" data-cy="available-course-card">
3
+ <v-card-item>
4
+ <v-card-title data-cy="course-title">
5
+ {{ courseConfig.name }}
6
+ <v-icon v-if="isPrivate" icon="mdi-eye-off" class="ml-2"></v-icon>
7
+ </v-card-title>
8
+ </v-card-item>
9
+
10
+ <v-card-text>
11
+ Questions: {{ questionCount }}
12
+ <p>{{ courseConfig.description }}</p>
13
+ </v-card-text>
14
+
15
+ <v-card-actions>
16
+ <v-btn color="primary" @click="navigateToInfo">More Info</v-btn>
17
+ <v-btn data-cy="register-course-button" :loading="addingCourse" color="primary" @click="registerForCourse">
18
+ Register
19
+ </v-btn>
20
+ </v-card-actions>
21
+ </v-card>
22
+ </template>
23
+
24
+ <script lang="ts">
25
+ import { getCurrentUser } from '@vue-skuilder/common-ui';
26
+ import { CourseConfig, log } from '@vue-skuilder/common';
27
+ import { getDataLayer } from '@vue-skuilder/db';
28
+ import { defineComponent } from 'vue';
29
+
30
+ export default defineComponent({
31
+ name: 'CourseStubCard',
32
+
33
+ props: {
34
+ courseId: {
35
+ type: String,
36
+ required: true,
37
+ },
38
+ },
39
+ emits: ['refresh'],
40
+
41
+ data() {
42
+ return {
43
+ courseConfig: null as CourseConfig | null,
44
+ questionCount: 0,
45
+ isPrivate: false,
46
+ updatePending: true,
47
+ addingCourse: false,
48
+ };
49
+ },
50
+
51
+ async created() {
52
+ try {
53
+ const db = getDataLayer().getCourseDB(this.courseId);
54
+ this.courseConfig = (await db.getCourseConfig())!;
55
+ this.isPrivate = !this.courseConfig.public;
56
+ this.questionCount = (await db.getCourseInfo()).cardCount;
57
+ this.updatePending = false;
58
+ } catch (e) {
59
+ console.error(`Error loading course ${this.courseId}: ${e}`);
60
+ }
61
+ },
62
+
63
+ methods: {
64
+ async registerForCourse() {
65
+ this.addingCourse = true;
66
+ log(`Attempting to register for ${this.courseId}.`);
67
+ await (await getCurrentUser()).registerForCourse(this.courseId);
68
+ this.$emit('refresh');
69
+ },
70
+ navigateToInfo() {
71
+ const path = `/q/${this.courseConfig?.name.replaceAll(' ', '_')}`;
72
+ this.$router.push(path);
73
+ },
74
+ },
75
+ });
76
+ </script>
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <v-container v-if="!updatePending">
3
+ <v-row>
4
+ <v-col cols="12">
5
+ <h1>Which seems <em>harder</em>?</h1>
6
+ </v-col>
7
+ </v-row>
8
+
9
+ <v-row>
10
+ <v-col>
11
+ <v-btn color="success" class="ma-5" @click="vote('a')">
12
+ <v-icon>mdi-check</v-icon>
13
+ </v-btn>
14
+ <card-loader class="ma-2" :qualified_id="id1" :view-lookup="viewLookup" />
15
+ </v-col>
16
+ </v-row>
17
+
18
+ <v-row>
19
+ <v-col>
20
+ <v-btn color="success" class="ma-5" @click="vote('b')">
21
+ <v-icon>mdi-check</v-icon>
22
+ </v-btn>
23
+ <card-loader class="ma-2" :qualified_id="id2" :view-lookup="viewLookup" />
24
+ </v-col>
25
+ </v-row>
26
+ </v-container>
27
+ </template>
28
+
29
+ <script lang="ts">
30
+ import { CardLoader } from '@vue-skuilder/common-ui';
31
+ import { allCourses } from '@vue-skuilder/courses';
32
+ import { CourseElo, adjustCourseScores, CourseConfig } from '@vue-skuilder/common';
33
+ import { CourseDBInterface, getDataLayer } from '@vue-skuilder/db';
34
+ import { defineComponent } from 'vue';
35
+
36
+ export default defineComponent({
37
+ name: 'ELOModerator',
38
+
39
+ components: {
40
+ CardLoader,
41
+ },
42
+
43
+ props: {
44
+ courseId: {
45
+ type: String,
46
+ required: true,
47
+ },
48
+ },
49
+
50
+ data() {
51
+ return {
52
+ courseDB: null as CourseDBInterface | null,
53
+ updatePending: true,
54
+ courseConfig: null as CourseConfig | null,
55
+ cards: [] as {
56
+ courseId: string;
57
+ cardId: string;
58
+ elo: CourseElo;
59
+ count: number;
60
+ }[],
61
+ id1: '',
62
+ id2: '',
63
+ elo1: null as CourseElo | null,
64
+ elo2: null as CourseElo | null,
65
+ viewLookup: allCourses.getView,
66
+ };
67
+ },
68
+
69
+ async created() {
70
+ this.courseDB = getDataLayer().getCourseDB(this.courseId);
71
+
72
+ this.courseConfig = (await this.courseDB!.getCourseConfig())!;
73
+ await this.getNewCards();
74
+ },
75
+
76
+ methods: {
77
+ vote(x: 'a' | 'b') {
78
+ if (!this.elo1 || !this.elo2) return;
79
+
80
+ const scores = adjustCourseScores(this.elo1, this.elo2, x === 'a' ? 1 : 0, {
81
+ globalOnly: true,
82
+ });
83
+
84
+ this.courseDB!.updateCardElo(this.cards[0].cardId, scores.userElo);
85
+ this.courseDB!.updateCardElo(this.cards[1].cardId, scores.cardElo);
86
+
87
+ this.getNewCards();
88
+ },
89
+
90
+ async getNewCards() {
91
+ if (!this.courseDB) return;
92
+
93
+ this.updatePending = true;
94
+ this.cards = await this.courseDB!.getInexperiencedCards();
95
+
96
+ // console.log('Comparing:\n\t' + JSON.stringify(this.cards));
97
+
98
+ this.id1 = '';
99
+ this.id2 = '';
100
+
101
+ this.id1 = `${this.courseId}-${this.cards[0].cardId}`;
102
+ this.id2 = `${this.courseId}-${this.cards[1].cardId}`;
103
+
104
+ this.elo1 = this.cards[0].elo;
105
+ this.elo2 = this.cards[1].elo;
106
+
107
+ this.updatePending = false;
108
+ },
109
+ },
110
+ });
111
+ </script>
112
+
113
+ <style scoped>
114
+ .component-fade-enter-active,
115
+ .component-fade-leave-active {
116
+ transition: opacity 0.5s ease;
117
+ }
118
+ .component-fade-enter, .component-fade-leave-to
119
+ /* .component-fade-leave-active below version 2.1.8 */ {
120
+ opacity: 0;
121
+ }
122
+ </style>
@@ -0,0 +1,209 @@
1
+ <template>
2
+ <div>
3
+ <!-- todo: -->
4
+ <h1>
5
+ <router-link :to="`/q/${course.name}`">{{ course.name }}</router-link> > Tag: {{ tag.name }}
6
+ </h1>
7
+ <br />
8
+ <p>{{ tag.taggedCards.length }} card{{ tag.taggedCards.length === 1 ? '' : 's' }}</p>
9
+
10
+ <v-text-field
11
+ ref="snippetEditor"
12
+ v-model="snippetModel"
13
+ variant="outlined"
14
+ :readonly="!editingSnippet"
15
+ :counter="editingSnippet"
16
+ label="Brief tag description:"
17
+ placeholder="No snippet yet - add one!"
18
+ type="text"
19
+ >
20
+ <template #prepend>
21
+ <span v-if="editingSnippet">
22
+ <v-icon color="primary" @click="saveSnippet">mdi-content-save</v-icon>
23
+ </span>
24
+ <v-icon v-else color="primary" @click="editSnippet">mdi-pencil</v-icon>
25
+ </template>
26
+ <template #append>
27
+ <v-icon v-if="editingSnippet" @click="cancelEditSnippet">mdi-cancel</v-icon>
28
+ <v-fade-transition leave-absolute>
29
+ <!-- spinner while awaiting async write of edits -->
30
+ <v-progress-circular v-if="snippetSaving" size="20" color="info" indeterminate></v-progress-circular>
31
+ </v-fade-transition>
32
+ </template>
33
+ </v-text-field>
34
+
35
+ <v-text-field
36
+ ref="wikiEditor"
37
+ v-model="wikiModel"
38
+ variant="outlined"
39
+ :readonly="!editingWiki"
40
+ :counter="editingWiki"
41
+ label="Extended tag description:"
42
+ placeholder="No wiki yet - consider adding one!"
43
+ textarea
44
+ >
45
+ <template #prepend>
46
+ <span v-if="editingWiki">
47
+ <v-icon color="primary" @click="saveWiki">mdi-content-save</v-icon>
48
+ </span>
49
+ <v-icon v-else color="primary" @click="editWiki">mdi-pencil</v-icon>
50
+ </template>
51
+ <template #append>
52
+ <v-icon v-if="editingWiki" @click="cancelEditWiki">mdi-cancel</v-icon>
53
+ <v-fade-transition leave-absolute>
54
+ <!-- spinner while awaiting async write of edits -->
55
+ <v-progress-circular v-if="wikiSaving" size="20" color="info" indeterminate></v-progress-circular>
56
+ </v-fade-transition>
57
+ </template>
58
+ </v-text-field>
59
+
60
+ <course-card-browser :course-id="courseId" :tag-id="tagId" />
61
+ </div>
62
+ </template>
63
+
64
+ <script lang="ts">
65
+ import { defineComponent } from 'vue';
66
+ import { DocType, Tag, getDataLayer, CourseDBInterface } from '@vue-skuilder/db';
67
+ import { Status, CourseConfig } from '@vue-skuilder/common';
68
+ import CourseCardBrowser from './CourseCardBrowser.vue';
69
+ import { alertUser } from '@vue-skuilder/common-ui';
70
+
71
+ export default defineComponent({
72
+ name: 'TagInformation',
73
+
74
+ components: {
75
+ CourseCardBrowser,
76
+ },
77
+
78
+ props: {
79
+ tagId: {
80
+ type: String,
81
+ required: true,
82
+ },
83
+ courseId: {
84
+ type: String,
85
+ required: true,
86
+ },
87
+ },
88
+
89
+ data() {
90
+ return {
91
+ snippetModel: '',
92
+ editingSnippet: false,
93
+ snippetSaving: false,
94
+
95
+ wikiModel: '',
96
+ editingWiki: false,
97
+ wikiSaving: false,
98
+
99
+ courseDB: null as CourseDBInterface | null,
100
+
101
+ tag: {
102
+ course: this.courseId,
103
+ name: this.tagId,
104
+ snippet: '',
105
+ wiki: '',
106
+ taggedCards: [],
107
+ docType: DocType.TAG,
108
+ } as Tag,
109
+
110
+ course: {
111
+ courseID: this.courseId,
112
+ name: '',
113
+ description: '',
114
+ public: false,
115
+ deleted: false,
116
+ dataShapes: [],
117
+ questionTypes: [],
118
+ creator: '',
119
+ admins: [],
120
+ moderators: [],
121
+ } as CourseConfig,
122
+ };
123
+ },
124
+
125
+ async created() {
126
+ this.courseDB = getDataLayer().getCourseDB(this.courseId);
127
+ this.tag = await this.courseDB.getTag(this.tagId);
128
+ this.snippetModel = this.tag.snippet;
129
+ this.wikiModel = this.tag.wiki;
130
+ this.course = await this.courseDB.getCourseConfig();
131
+ },
132
+
133
+ methods: {
134
+ editSnippet() {
135
+ console.log('[TagInformation] EditSnip');
136
+ this.editingSnippet = true;
137
+ (this.$refs.snippetEditor as HTMLInputElement).focus();
138
+ },
139
+
140
+ editWiki() {
141
+ console.log('[TagInformation] EditWiki');
142
+ this.editingWiki = true;
143
+ (this.$refs.wikiEditor as HTMLInputElement).focus();
144
+ },
145
+
146
+ async saveSnippet() {
147
+ this.snippetSaving = true;
148
+
149
+ const update = await this.courseDB!.updateTag({
150
+ ...this.tag,
151
+ snippet: this.snippetModel,
152
+ });
153
+
154
+ if (update.ok) {
155
+ console.log('[TagInformation] OK');
156
+ this.tag.snippet = this.snippetModel;
157
+ alertUser({
158
+ text: `Updated applied - thanks!`,
159
+ status: Status.ok,
160
+ });
161
+ } else {
162
+ alertUser({
163
+ text: `error in applying update!`,
164
+ status: Status.error,
165
+ });
166
+ }
167
+
168
+ this.editingSnippet = false;
169
+ this.snippetSaving = false;
170
+ },
171
+
172
+ async saveWiki() {
173
+ this.wikiSaving = true;
174
+
175
+ const update = await this.courseDB!.updateTag({
176
+ ...this.tag,
177
+ wiki: this.wikiModel,
178
+ });
179
+
180
+ if (update.ok) {
181
+ this.tag.wiki = this.wikiModel;
182
+ alertUser({
183
+ text: `Updated applied - thanks!`,
184
+ status: Status.ok,
185
+ });
186
+ } else {
187
+ alertUser({
188
+ text: `error in applying update!`,
189
+ status: Status.error,
190
+ });
191
+ }
192
+
193
+ this.editingWiki = false;
194
+ this.wikiSaving = false;
195
+ },
196
+
197
+ cancelEditSnippet() {
198
+ console.log('[TagInformation] Cancelling EditSnip');
199
+ this.editingSnippet = false;
200
+ this.snippetModel = this.tag.snippet;
201
+ },
202
+
203
+ cancelEditWiki() {
204
+ this.editingWiki = false;
205
+ this.wikiModel = this.tag.wiki;
206
+ },
207
+ },
208
+ });
209
+ </script>