@vue-skuilder/common-ui 0.1.5 → 0.1.7

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.
@@ -1,11 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { defineComponent, createElementBlock, openBlock, createCommentVNode, Fragment, renderList, normalizeStyle, toDisplayString, resolveComponent, createBlock, withCtx, createVNode, createTextVNode, createElementVNode, mergeProps, ref, computed, watch, onMounted, onBeforeUnmount, normalizeClass, renderSlot, Transition, resolveDynamicComponent, markRaw, defineAsyncComponent, withKeys, withDirectives, vModelText, getCurrentInstance, h, withModifiers } from "vue";
4
+ import { defineComponent, createElementBlock, openBlock, createCommentVNode, Fragment, renderList, normalizeStyle, toDisplayString, resolveComponent, createBlock, withCtx, createVNode, createTextVNode, createElementVNode, mergeProps, ref, computed, watch, onMounted, onBeforeUnmount, normalizeClass, renderSlot, Transition, resolveDynamicComponent, markRaw, defineAsyncComponent, withKeys, withDirectives, vModelText, getCurrentInstance, h, withModifiers, vShow } from "vue";
5
5
  import { Status, FieldType, isCourseElo, toCourseElo, displayableDataToViewData, adjustCourseScores, log } from "@vue-skuilder/common";
6
6
  import { docIsDeleted, isReview, newInterval, isQuestionRecord, getStudySource, SessionController, getDataLayer, GuestUsername } from "@vue-skuilder/db";
7
7
  import { defineStore, setActivePinia } from "pinia";
8
8
  import { useRouter, useRoute } from "vue-router";
9
+ import { VueTagsInput } from "@vojtechlanka/vue-tags-input";
9
10
  //! moment.js
10
11
  //! version : 2.30.1
11
12
  //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
@@ -4000,7 +4001,7 @@ hooks.HTML5_FMT = {
4000
4001
  MONTH: "YYYY-MM"
4001
4002
  // <input type="month" />
4002
4003
  };
4003
- const _sfc_main$l = defineComponent({
4004
+ const _sfc_main$q = defineComponent({
4004
4005
  name: "HeatMap",
4005
4006
  props: {
4006
4007
  // Accept activity records directly as a prop
@@ -4245,10 +4246,10 @@ const _export_sfc = (sfc, props) => {
4245
4246
  }
4246
4247
  return target;
4247
4248
  };
4248
- const _hoisted_1$b = ["width", "height"];
4249
- const _hoisted_2$4 = ["transform"];
4250
- const _hoisted_3$2 = ["y", "width", "height", "fill", "onMouseover"];
4251
- function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
4249
+ const _hoisted_1$f = ["width", "height"];
4250
+ const _hoisted_2$7 = ["transform"];
4251
+ const _hoisted_3$5 = ["y", "width", "height", "fill", "onMouseover"];
4252
+ function _sfc_render$k(_ctx, _cache, $props, $setup, $data, $options) {
4252
4253
  return openBlock(), createElementBlock("div", null, [
4253
4254
  (openBlock(), createElementBlock("svg", {
4254
4255
  width: _ctx.width,
@@ -4269,11 +4270,11 @@ function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
4269
4270
  fill: _ctx.getColor(day.count),
4270
4271
  onMouseover: ($event) => _ctx.showTooltip(day, $event),
4271
4272
  onMouseout: _cache[0] || (_cache[0] = (...args) => _ctx.hideTooltip && _ctx.hideTooltip(...args))
4272
- }, null, 40, _hoisted_3$2);
4273
+ }, null, 40, _hoisted_3$5);
4273
4274
  }), 128))
4274
- ], 8, _hoisted_2$4);
4275
+ ], 8, _hoisted_2$7);
4275
4276
  }), 128))
4276
- ], 8, _hoisted_1$b)),
4277
+ ], 8, _hoisted_1$f)),
4277
4278
  _ctx.tooltipData ? (openBlock(), createElementBlock("div", {
4278
4279
  key: 0,
4279
4280
  class: "tooltip",
@@ -4281,7 +4282,7 @@ function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
4281
4282
  }, toDisplayString(_ctx.tooltipData.count) + " review" + toDisplayString(_ctx.tooltipData.count !== 1 ? "s" : "") + " on " + toDisplayString(_ctx.toDateString(_ctx.tooltipData.date)), 5)) : createCommentVNode("", true)
4282
4283
  ]);
4283
4284
  }
4284
- const HeatMap = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["render", _sfc_render$h], ["__scopeId", "data-v-ca46239a"]]);
4285
+ const HeatMap = /* @__PURE__ */ _export_sfc(_sfc_main$q, [["render", _sfc_render$k], ["__scopeId", "data-v-ca46239a"]]);
4285
4286
  function getDefaultExportFromCjs(x) {
4286
4287
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
4287
4288
  }
@@ -4861,7 +4862,7 @@ const _SkldrMouseTrap = class _SkldrMouseTrap {
4861
4862
  };
4862
4863
  __publicField(_SkldrMouseTrap, "_instance");
4863
4864
  let SkldrMouseTrap = _SkldrMouseTrap;
4864
- const _sfc_main$k = defineComponent({
4865
+ const _sfc_main$p = defineComponent({
4865
4866
  name: "SkMouseTrap",
4866
4867
  props: {
4867
4868
  refreshInterval: {
@@ -4891,8 +4892,8 @@ const _sfc_main$k = defineComponent({
4891
4892
  }
4892
4893
  }
4893
4894
  });
4894
- const _hoisted_1$a = { class: "text-caption ml-2" };
4895
- function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
4895
+ const _hoisted_1$e = { class: "text-caption ml-2" };
4896
+ function _sfc_render$j(_ctx, _cache, $props, $setup, $data, $options) {
4896
4897
  const _component_v_icon = resolveComponent("v-icon");
4897
4898
  const _component_v_btn = resolveComponent("v-btn");
4898
4899
  const _component_v_toolbar_title = resolveComponent("v-toolbar-title");
@@ -4961,7 +4962,7 @@ function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
4961
4962
  _: 2
4962
4963
  }, 1024),
4963
4964
  createVNode(_component_v_spacer),
4964
- createElementVNode("span", _hoisted_1$a, toDisplayString(hk.command), 1)
4965
+ createElementVNode("span", _hoisted_1$e, toDisplayString(hk.command), 1)
4965
4966
  ]),
4966
4967
  _: 2
4967
4968
  }, 1024);
@@ -4976,8 +4977,8 @@ function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
4976
4977
  _: 1
4977
4978
  })) : createCommentVNode("", true);
4978
4979
  }
4979
- const SkMouseTrap = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["render", _sfc_render$g]]);
4980
- const _sfc_main$j = defineComponent({
4980
+ const SkMouseTrap = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["render", _sfc_render$j]]);
4981
+ const _sfc_main$o = defineComponent({
4981
4982
  name: "SkMouseTrapToolTip",
4982
4983
  props: {
4983
4984
  hotkey: {
@@ -5126,7 +5127,7 @@ const _sfc_main$j = defineComponent({
5126
5127
  };
5127
5128
  }
5128
5129
  });
5129
- function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
5130
+ function _sfc_render$i(_ctx, _cache, $props, $setup, $data, $options) {
5130
5131
  return openBlock(), createElementBlock("div", {
5131
5132
  class: normalizeClass(["sk-mousetrap-tooltip-wrapper", [
5132
5133
  _ctx.isControlKeyPressed && !_ctx.disabled && _ctx.highlightEffect !== "none" ? `sk-mousetrap-highlight-${_ctx.highlightEffect}` : ""
@@ -5150,7 +5151,7 @@ function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
5150
5151
  })
5151
5152
  ], 2);
5152
5153
  }
5153
- const SkMouseTrapToolTip = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$f], ["__scopeId", "data-v-5d6fb09c"]]);
5154
+ const SkMouseTrapToolTip = /* @__PURE__ */ _export_sfc(_sfc_main$o, [["render", _sfc_render$i], ["__scopeId", "data-v-5d6fb09c"]]);
5154
5155
  const SnackbarServiceModule = /* @__PURE__ */ (() => {
5155
5156
  let _instance = null;
5156
5157
  return {
@@ -5174,7 +5175,7 @@ const SnackbarServiceModule = /* @__PURE__ */ (() => {
5174
5175
  };
5175
5176
  })();
5176
5177
  const { setInstance, alertUser } = SnackbarServiceModule;
5177
- const SnackbarService$1 = defineComponent({
5178
+ const _sfc_main$n = defineComponent({
5178
5179
  name: "SnackbarService",
5179
5180
  data() {
5180
5181
  return {
@@ -5212,8 +5213,8 @@ const SnackbarService$1 = defineComponent({
5212
5213
  }
5213
5214
  }
5214
5215
  });
5215
- const _hoisted_1$9 = { class: "d-flex align-center justify-space-between w-100" };
5216
- function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
5216
+ const _hoisted_1$d = { class: "d-flex align-center justify-space-between w-100" };
5217
+ function _sfc_render$h(_ctx, _cache, $props, $setup, $data, $options) {
5217
5218
  const _component_v_icon = resolveComponent("v-icon");
5218
5219
  const _component_v_btn = resolveComponent("v-btn");
5219
5220
  const _component_v_snackbar = resolveComponent("v-snackbar");
@@ -5228,7 +5229,7 @@ function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
5228
5229
  color: _ctx.getColor(snack)
5229
5230
  }, {
5230
5231
  default: withCtx(() => [
5231
- createElementVNode("div", _hoisted_1$9, [
5232
+ createElementVNode("div", _hoisted_1$d, [
5232
5233
  createElementVNode("span", null, toDisplayString(snack.text), 1),
5233
5234
  createVNode(_component_v_btn, {
5234
5235
  icon: "",
@@ -5252,8 +5253,8 @@ function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
5252
5253
  }), 128))
5253
5254
  ]);
5254
5255
  }
5255
- const SnackbarService = /* @__PURE__ */ _export_sfc(SnackbarService$1, [["render", _sfc_render$e]]);
5256
- const _sfc_main$i = defineComponent({
5256
+ const SnackbarService = /* @__PURE__ */ _export_sfc(_sfc_main$n, [["render", _sfc_render$h]]);
5257
+ const _sfc_main$m = defineComponent({
5257
5258
  name: "PaginatingToolbar",
5258
5259
  props: {
5259
5260
  pages: {
@@ -5277,11 +5278,12 @@ const _sfc_main$i = defineComponent({
5277
5278
  },
5278
5279
  emits: ["first", "prev", "next", "last", "set-page"]
5279
5280
  });
5280
- const _hoisted_1$8 = {
5281
+ const _hoisted_1$c = {
5281
5282
  key: 0,
5282
- class: "ms-2 text-subtitle-2"
5283
+ class: "ms-2 text-subtitle-2",
5284
+ "data-cy": "paginating-toolbar-subtitle"
5283
5285
  };
5284
- function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
5286
+ function _sfc_render$g(_ctx, _cache, $props, $setup, $data, $options) {
5285
5287
  const _component_v_toolbar_title = resolveComponent("v-toolbar-title");
5286
5288
  const _component_v_spacer = resolveComponent("v-spacer");
5287
5289
  const _component_v_icon = resolveComponent("v-icon");
@@ -5293,7 +5295,7 @@ function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
5293
5295
  createVNode(_component_v_toolbar_title, null, {
5294
5296
  default: withCtx(() => [
5295
5297
  createElementVNode("span", null, toDisplayString(_ctx.title), 1),
5296
- _ctx.subtitle ? (openBlock(), createElementBlock("span", _hoisted_1$8, toDisplayString(_ctx.subtitle), 1)) : createCommentVNode("", true)
5298
+ _ctx.subtitle ? (openBlock(), createElementBlock("span", _hoisted_1$c, toDisplayString(_ctx.subtitle), 1)) : createCommentVNode("", true)
5297
5299
  ]),
5298
5300
  _: 1
5299
5301
  }),
@@ -5385,7 +5387,7 @@ function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
5385
5387
  _: 1
5386
5388
  });
5387
5389
  }
5388
- const PaginatingToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$d], ["__scopeId", "data-v-39413af8"]]);
5390
+ const PaginatingToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["render", _sfc_render$g], ["__scopeId", "data-v-a75fea7e"]]);
5389
5391
  function useViewable(props, emit, componentName) {
5390
5392
  const startTime = ref(hooks.utc());
5391
5393
  const hotKeys = ref([]);
@@ -5554,7 +5556,7 @@ class Question extends Displayable {
5554
5556
  with 7 * 4 = 21
5555
5557
  */
5556
5558
  }
5557
- const _sfc_main$h = defineComponent({
5559
+ const _sfc_main$l = defineComponent({
5558
5560
  name: "StudySessionTimer",
5559
5561
  props: {
5560
5562
  /**
@@ -5608,7 +5610,7 @@ const _sfc_main$h = defineComponent({
5608
5610
  };
5609
5611
  }
5610
5612
  });
5611
- function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
5613
+ function _sfc_render$f(_ctx, _cache, $props, $setup, $data, $options) {
5612
5614
  const _component_v_icon = resolveComponent("v-icon");
5613
5615
  const _component_v_btn = resolveComponent("v-btn");
5614
5616
  const _component_v_progress_circular = resolveComponent("v-progress-circular");
@@ -5662,8 +5664,8 @@ function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
5662
5664
  _: 1
5663
5665
  });
5664
5666
  }
5665
- const StudySessionTimer = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["render", _sfc_render$c], ["__scopeId", "data-v-5960940a"]]);
5666
- const _sfc_main$g = defineComponent({
5667
+ const StudySessionTimer = /* @__PURE__ */ _export_sfc(_sfc_main$l, [["render", _sfc_render$f], ["__scopeId", "data-v-5960940a"]]);
5668
+ const _sfc_main$k = defineComponent({
5667
5669
  name: "CardViewer",
5668
5670
  ref: {},
5669
5671
  props: {
@@ -5717,7 +5719,7 @@ const _sfc_main$g = defineComponent({
5717
5719
  }
5718
5720
  }
5719
5721
  });
5720
- function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
5722
+ function _sfc_render$e(_ctx, _cache, $props, $setup, $data, $options) {
5721
5723
  const _component_v_card = resolveComponent("v-card");
5722
5724
  return openBlock(), createBlock(_component_v_card, { elevation: "12" }, {
5723
5725
  default: withCtx(() => [
@@ -5741,7 +5743,7 @@ function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
5741
5743
  _: 1
5742
5744
  });
5743
5745
  }
5744
- const CardViewer = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$b], ["__scopeId", "data-v-a180fe1c"]]);
5746
+ const CardViewer = /* @__PURE__ */ _export_sfc(_sfc_main$k, [["render", _sfc_render$e], ["__scopeId", "data-v-a180fe1c"]]);
5745
5747
  var module$1 = {};
5746
5748
  (function main(global, module2, isWorker, workerSize) {
5747
5749
  var canUseWorker = !!(global.Worker && global.Blob && global.Promise && global.OffscreenCanvas && global.OffscreenCanvasRenderingContext2D && global.HTMLCanvasElement && global.HTMLCanvasElement.prototype.transferControlToOffscreen && global.URL && global.URL.createObjectURL);
@@ -6438,7 +6440,7 @@ var module$1 = {};
6438
6440
  }(), module$1, false);
6439
6441
  const confetti = module$1.exports;
6440
6442
  module$1.exports.create;
6441
- const _sfc_main$f = defineComponent({
6443
+ const _sfc_main$j = defineComponent({
6442
6444
  name: "StudySession",
6443
6445
  ref: {},
6444
6446
  components: {
@@ -6861,22 +6863,22 @@ const _sfc_main$f = defineComponent({
6861
6863
  }
6862
6864
  }
6863
6865
  });
6864
- const _hoisted_1$7 = {
6866
+ const _hoisted_1$b = {
6865
6867
  key: 0,
6866
6868
  class: "StudySession"
6867
6869
  };
6868
- const _hoisted_2$3 = { class: "text-h3" };
6869
- const _hoisted_3$1 = {
6870
+ const _hoisted_2$6 = { class: "text-h3" };
6871
+ const _hoisted_3$4 = {
6870
6872
  key: 0,
6871
6873
  class: "text-h4"
6872
6874
  };
6873
- const _hoisted_4$1 = { key: 0 };
6874
- const _hoisted_5$1 = {
6875
+ const _hoisted_4$3 = { key: 0 };
6876
+ const _hoisted_5$3 = {
6875
6877
  key: 1,
6876
6878
  ref: "shadowWrapper"
6877
6879
  };
6878
6880
  const _hoisted_6$1 = { key: 2 };
6879
- function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
6881
+ function _sfc_render$d(_ctx, _cache, $props, $setup, $data, $options) {
6880
6882
  const _component_v_progress_circular = resolveComponent("v-progress-circular");
6881
6883
  const _component_v_spacer = resolveComponent("v-spacer");
6882
6884
  const _component_v_col = resolveComponent("v-col");
@@ -6886,12 +6888,12 @@ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
6886
6888
  const _component_card_viewer = resolveComponent("card-viewer");
6887
6889
  const _component_StudySessionTimer = resolveComponent("StudySessionTimer");
6888
6890
  const _component_SkMouseTrap = resolveComponent("SkMouseTrap");
6889
- return _ctx.sessionPrepared ? (openBlock(), createElementBlock("div", _hoisted_1$7, [
6891
+ return _ctx.sessionPrepared ? (openBlock(), createElementBlock("div", _hoisted_1$b, [
6890
6892
  createVNode(_component_v_row, { align: "center" }, {
6891
6893
  default: withCtx(() => [
6892
6894
  createVNode(_component_v_col, null, {
6893
6895
  default: withCtx(() => [
6894
- createElementVNode("h1", _hoisted_2$3, [
6896
+ createElementVNode("h1", _hoisted_2$6, [
6895
6897
  createTextVNode(toDisplayString(_ctx.courseNames[_ctx.courseID]) + ": ", 1),
6896
6898
  _ctx.loading ? (openBlock(), createBlock(_component_v_progress_circular, {
6897
6899
  key: 0,
@@ -6909,9 +6911,9 @@ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
6909
6911
  _: 1
6910
6912
  }),
6911
6913
  _cache[7] || (_cache[7] = createElementVNode("br", null, null, -1)),
6912
- _ctx.sessionFinished ? (openBlock(), createElementBlock("div", _hoisted_3$1, [
6914
+ _ctx.sessionFinished ? (openBlock(), createElementBlock("div", _hoisted_3$4, [
6913
6915
  _cache[6] || (_cache[6] = createElementVNode("p", null, "Study session finished! Great job!", -1)),
6914
- _ctx.sessionController ? (openBlock(), createElementBlock("p", _hoisted_4$1, toDisplayString(_ctx.sessionController.report), 1)) : createCommentVNode("", true),
6916
+ _ctx.sessionController ? (openBlock(), createElementBlock("p", _hoisted_4$3, toDisplayString(_ctx.sessionController.report), 1)) : createCommentVNode("", true),
6915
6917
  createElementVNode("p", null, [
6916
6918
  _cache[3] || (_cache[3] = createTextVNode(" Start ")),
6917
6919
  createElementVNode("a", {
@@ -6931,7 +6933,7 @@ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
6931
6933
  createVNode(_component_heat_map, {
6932
6934
  "activity-records-getter": () => _ctx.user.getActivityRecords()
6933
6935
  }, null, 8, ["activity-records-getter"])
6934
- ])) : (openBlock(), createElementBlock("div", _hoisted_5$1, [
6936
+ ])) : (openBlock(), createElementBlock("div", _hoisted_5$3, [
6935
6937
  createVNode(_component_card_viewer, {
6936
6938
  ref: "cardViewer",
6937
6939
  class: normalizeClass(_ctx.loading ? "muted" : ""),
@@ -6987,7 +6989,7 @@ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
6987
6989
  })
6988
6990
  ])) : createCommentVNode("", true);
6989
6991
  }
6990
- const StudySession = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$a], ["__scopeId", "data-v-37cad857"]]);
6992
+ const StudySession = /* @__PURE__ */ _export_sfc(_sfc_main$j, [["render", _sfc_render$d], ["__scopeId", "data-v-37cad857"]]);
6991
6993
  let _pinia = null;
6992
6994
  const setPinia = (pinia) => {
6993
6995
  _pinia = pinia;
@@ -7082,7 +7084,7 @@ Exceeded maximum ancestor lookup depth.`;
7082
7084
  }
7083
7085
  }
7084
7086
  });
7085
- const _sfc_main$e = defineComponent({
7087
+ const _sfc_main$i = defineComponent({
7086
7088
  name: "MultipleChoiceOption",
7087
7089
  components: {
7088
7090
  MarkdownRenderer: defineAsyncComponent(() => Promise.resolve().then(() => MarkdownRenderer$1))
@@ -7168,7 +7170,7 @@ const _sfc_main$e = defineComponent({
7168
7170
  }
7169
7171
  }
7170
7172
  });
7171
- function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
7173
+ function _sfc_render$c(_ctx, _cache, $props, $setup, $data, $options) {
7172
7174
  const _component_markdown_renderer = resolveComponent("markdown-renderer");
7173
7175
  const _component_v_card = resolveComponent("v-card");
7174
7176
  return openBlock(), createBlock(_component_v_card, {
@@ -7182,8 +7184,8 @@ function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
7182
7184
  _: 1
7183
7185
  }, 8, ["class", "onMouseover", "onClick"]);
7184
7186
  }
7185
- const MultipleChoiceOption = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$9], ["__scopeId", "data-v-96de7172"]]);
7186
- const _sfc_main$d = defineComponent({
7187
+ const MultipleChoiceOption = /* @__PURE__ */ _export_sfc(_sfc_main$i, [["render", _sfc_render$c], ["__scopeId", "data-v-96de7172"]]);
7188
+ const _sfc_main$h = defineComponent({
7187
7189
  name: "RadioMultipleChoice",
7188
7190
  components: {
7189
7191
  MultipleChoiceOption
@@ -7322,13 +7324,13 @@ const _sfc_main$d = defineComponent({
7322
7324
  // },
7323
7325
  }
7324
7326
  });
7325
- const _hoisted_1$6 = {
7327
+ const _hoisted_1$a = {
7326
7328
  ref: "containerRef",
7327
7329
  class: "multipleChoice"
7328
7330
  };
7329
- function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
7331
+ function _sfc_render$b(_ctx, _cache, $props, $setup, $data, $options) {
7330
7332
  const _component_MultipleChoiceOption = resolveComponent("MultipleChoiceOption");
7331
- return openBlock(), createElementBlock("div", _hoisted_1$6, [
7333
+ return openBlock(), createElementBlock("div", _hoisted_1$a, [
7332
7334
  (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.choiceList, (choice, i) => {
7333
7335
  return openBlock(), createBlock(_component_MultipleChoiceOption, {
7334
7336
  key: i,
@@ -7342,8 +7344,8 @@ function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
7342
7344
  }), 128))
7343
7345
  ], 512);
7344
7346
  }
7345
- const RadioMultipleChoice = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$8]]);
7346
- const _sfc_main$c = defineComponent({
7347
+ const RadioMultipleChoice = /* @__PURE__ */ _export_sfc(_sfc_main$h, [["render", _sfc_render$b]]);
7348
+ const _sfc_main$g = defineComponent({
7347
7349
  name: "TrueFalse",
7348
7350
  components: {
7349
7351
  RadioMultipleChoice
@@ -7359,10 +7361,10 @@ const _sfc_main$c = defineComponent({
7359
7361
  }
7360
7362
  }
7361
7363
  });
7362
- const _hoisted_1$5 = { "data-viewable": "TrueFalse" };
7363
- function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
7364
+ const _hoisted_1$9 = { "data-viewable": "TrueFalse" };
7365
+ function _sfc_render$a(_ctx, _cache, $props, $setup, $data, $options) {
7364
7366
  const _component_RadioMultipleChoice = resolveComponent("RadioMultipleChoice");
7365
- return openBlock(), createElementBlock("div", _hoisted_1$5, [
7367
+ return openBlock(), createElementBlock("div", _hoisted_1$9, [
7366
7368
  createVNode(_component_RadioMultipleChoice, {
7367
7369
  "choice-list": ["True", "False"],
7368
7370
  MouseTrap: _ctx.MouseTrap,
@@ -7370,8 +7372,8 @@ function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
7370
7372
  }, null, 8, ["MouseTrap", "submit"])
7371
7373
  ]);
7372
7374
  }
7373
- const TrueFalse = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$7]]);
7374
- const _sfc_main$b = defineComponent({
7375
+ const TrueFalse = /* @__PURE__ */ _export_sfc(_sfc_main$g, [["render", _sfc_render$a]]);
7376
+ const _sfc_main$f = defineComponent({
7375
7377
  name: "UserInputNumber",
7376
7378
  ref: {},
7377
7379
  extends: UserInput,
@@ -7391,7 +7393,7 @@ const _sfc_main$b = defineComponent({
7391
7393
  }
7392
7394
  }
7393
7395
  });
7394
- function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
7396
+ function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
7395
7397
  const _component_v_text_field = resolveComponent("v-text-field");
7396
7398
  const _component_v_container = resolveComponent("v-container");
7397
7399
  return openBlock(), createBlock(_component_v_container, { class: "pa-0" }, {
@@ -7412,8 +7414,8 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
7412
7414
  _: 1
7413
7415
  });
7414
7416
  }
7415
- const UserInputNumber = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["render", _sfc_render$6], ["__scopeId", "data-v-a56dcd1c"]]);
7416
- const _sfc_main$a = defineComponent({
7417
+ const UserInputNumber = /* @__PURE__ */ _export_sfc(_sfc_main$f, [["render", _sfc_render$9], ["__scopeId", "data-v-a56dcd1c"]]);
7418
+ const _sfc_main$e = defineComponent({
7417
7419
  name: "UserInputString",
7418
7420
  extends: UserInput,
7419
7421
  props: {
@@ -7450,10 +7452,10 @@ const _sfc_main$a = defineComponent({
7450
7452
  // },
7451
7453
  }
7452
7454
  });
7453
- const _hoisted_1$4 = { class: "user-input-container" };
7454
- const _hoisted_2$2 = ["autofocus"];
7455
- function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
7456
- return openBlock(), createElementBlock("span", _hoisted_1$4, [
7455
+ const _hoisted_1$8 = { class: "user-input-container" };
7456
+ const _hoisted_2$5 = ["autofocus"];
7457
+ function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
7458
+ return openBlock(), createElementBlock("span", _hoisted_1$8, [
7457
7459
  withDirectives(createElementVNode("input", {
7458
7460
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.answer = $event),
7459
7461
  autofocus: _ctx.autofocus,
@@ -7461,13 +7463,13 @@ function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
7461
7463
  class: "user-input-string",
7462
7464
  ref: "input",
7463
7465
  onKeyup: _cache[1] || (_cache[1] = withKeys(($event) => _ctx.submitAnswer(_ctx.answer), ["enter"]))
7464
- }, null, 40, _hoisted_2$2), [
7466
+ }, null, 40, _hoisted_2$5), [
7465
7467
  [vModelText, _ctx.answer]
7466
7468
  ])
7467
7469
  ]);
7468
7470
  }
7469
- const UserInputString = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$5], ["__scopeId", "data-v-aa14961f"]]);
7470
- const _sfc_main$9 = defineComponent({
7471
+ const UserInputString = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["render", _sfc_render$8], ["__scopeId", "data-v-aa14961f"]]);
7472
+ const _sfc_main$d = defineComponent({
7471
7473
  name: "FillInInput",
7472
7474
  components: {
7473
7475
  UserInputString
@@ -7500,13 +7502,13 @@ const _sfc_main$9 = defineComponent({
7500
7502
  };
7501
7503
  }
7502
7504
  });
7503
- const _hoisted_1$3 = {
7505
+ const _hoisted_1$7 = {
7504
7506
  key: 0,
7505
7507
  class: "text-h5 underline"
7506
7508
  };
7507
- function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
7509
+ function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
7508
7510
  const _component_user_input_string = resolveComponent("user-input-string");
7509
- return _ctx.radioType ? (openBlock(), createElementBlock("span", _hoisted_1$3, "             ")) : (openBlock(), createBlock(_component_user_input_string, {
7511
+ return _ctx.radioType ? (openBlock(), createElementBlock("span", _hoisted_1$7, "             ")) : (openBlock(), createBlock(_component_user_input_string, {
7510
7512
  key: 1,
7511
7513
  id: "input",
7512
7514
  icon: false,
@@ -7514,8 +7516,8 @@ function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
7514
7516
  value: _ctx.processedText
7515
7517
  }, null, 8, ["value"]));
7516
7518
  }
7517
- const FillInInput = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$4], ["__scopeId", "data-v-486ac035"]]);
7518
- const _sfc_main$8 = defineComponent({
7519
+ const FillInInput = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["render", _sfc_render$7], ["__scopeId", "data-v-486ac035"]]);
7520
+ const _sfc_main$c = defineComponent({
7519
7521
  name: "CardLoader",
7520
7522
  components: {
7521
7523
  CardViewer
@@ -7589,7 +7591,7 @@ const _sfc_main$8 = defineComponent({
7589
7591
  }
7590
7592
  }
7591
7593
  });
7592
- function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
7594
+ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
7593
7595
  const _component_card_viewer = resolveComponent("card-viewer");
7594
7596
  return !_ctx.loading ? (openBlock(), createBlock(_component_card_viewer, {
7595
7597
  key: 0,
@@ -7602,7 +7604,7 @@ function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
7602
7604
  onEmitResponse: _cache[0] || (_cache[0] = ($event) => _ctx.processResponse($event))
7603
7605
  }, null, 8, ["class", "view", "data", "card_id", "course_id", "session-order"])) : createCommentVNode("", true);
7604
7606
  }
7605
- const CardLoader = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$3], ["__scopeId", "data-v-9ca53bc4"]]);
7607
+ const CardLoader = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["render", _sfc_render$6], ["__scopeId", "data-v-9ca53bc4"]]);
7606
7608
  function _getDefaults() {
7607
7609
  return {
7608
7610
  async: false,
@@ -9813,7 +9815,7 @@ function isComponent(token2) {
9813
9815
  return token2.type === "text" && token2.text.startsWith("{{") && token2.text.endsWith("}}");
9814
9816
  }
9815
9817
  const playbackGap = 500;
9816
- const _sfc_main$7 = /* @__PURE__ */ defineComponent({
9818
+ const _sfc_main$b = /* @__PURE__ */ defineComponent({
9817
9819
  __name: "AudioAutoPlayer",
9818
9820
  props: {
9819
9821
  src: {}
@@ -9924,7 +9926,7 @@ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
9924
9926
  };
9925
9927
  }
9926
9928
  });
9927
- const AudioAutoPlayer = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-e1a0f62c"]]);
9929
+ const AudioAutoPlayer = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-e1a0f62c"]]);
9928
9930
  var core;
9929
9931
  var hasRequiredCore;
9930
9932
  function requireCore() {
@@ -15157,12 +15159,12 @@ function python(hljs) {
15157
15159
  ]
15158
15160
  };
15159
15161
  }
15160
- const _hoisted_1$2 = { class: "code-block-wrapper pa-2" };
15161
- const _hoisted_2$1 = {
15162
+ const _hoisted_1$6 = { class: "code-block-wrapper pa-2" };
15163
+ const _hoisted_2$4 = {
15162
15164
  key: 0,
15163
15165
  class: "language-indicator"
15164
15166
  };
15165
- const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15167
+ const _sfc_main$a = /* @__PURE__ */ defineComponent({
15166
15168
  __name: "CodeBlockRenderer",
15167
15169
  props: {
15168
15170
  code: {
@@ -15193,8 +15195,8 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15193
15195
  }
15194
15196
  return (_ctx, _cache) => {
15195
15197
  const _component_highlightjs = resolveComponent("highlightjs");
15196
- return openBlock(), createElementBlock("div", _hoisted_1$2, [
15197
- __props.language ? (openBlock(), createElementBlock("div", _hoisted_2$1, toDisplayString(__props.language), 1)) : createCommentVNode("", true),
15198
+ return openBlock(), createElementBlock("div", _hoisted_1$6, [
15199
+ __props.language ? (openBlock(), createElementBlock("div", _hoisted_2$4, toDisplayString(__props.language), 1)) : createCommentVNode("", true),
15198
15200
  createVNode(_component_highlightjs, {
15199
15201
  language: __props.language,
15200
15202
  code: __props.code
@@ -15203,11 +15205,11 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15203
15205
  };
15204
15206
  }
15205
15207
  });
15206
- const _hoisted_1$1 = { key: 0 };
15207
- const _hoisted_2 = { key: 0 };
15208
- const _hoisted_3 = { key: 0 };
15209
- const _hoisted_4 = { key: 1 };
15210
- const _hoisted_5 = { key: 2 };
15208
+ const _hoisted_1$5 = { key: 0 };
15209
+ const _hoisted_2$3 = { key: 0 };
15210
+ const _hoisted_3$3 = { key: 0 };
15211
+ const _hoisted_4$2 = { key: 1 };
15212
+ const _hoisted_5$2 = { key: 2 };
15211
15213
  const _hoisted_6 = { key: 1 };
15212
15214
  const _hoisted_7 = { key: 1 };
15213
15215
  const _hoisted_8 = {
@@ -15245,7 +15247,7 @@ const _hoisted_27 = ["innerHTML"];
15245
15247
  const _hoisted_28 = { key: 16 };
15246
15248
  const _hoisted_29 = { key: 17 };
15247
15249
  const _hoisted_30 = { key: 18 };
15248
- const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15250
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
15249
15251
  __name: "MdTokenRenderer",
15250
15252
  props: {
15251
15253
  token: {
@@ -15312,21 +15314,21 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15312
15314
  });
15313
15315
  return (_ctx, _cache) => {
15314
15316
  const _component_md_token_renderer = resolveComponent("md-token-renderer", true);
15315
- return isText(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_1$1, [
15316
- !__props.token.tokens || __props.token.tokens.length === 0 ? (openBlock(), createElementBlock("span", _hoisted_2, [
15317
- isComponent$1(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_3, [
15317
+ return isText(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_1$5, [
15318
+ !__props.token.tokens || __props.token.tokens.length === 0 ? (openBlock(), createElementBlock("span", _hoisted_2$3, [
15319
+ isComponent$1(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_3$3, [
15318
15320
  !__props.last ? (openBlock(), createBlock(resolveDynamicComponent(getComponent(parsedComponent(__props.token).is)), {
15319
15321
  key: 0,
15320
15322
  text: parsedComponent(__props.token).text
15321
15323
  }, null, 8, ["text"])) : createCommentVNode("", true)
15322
- ])) : containsComponent$1(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_4, [
15324
+ ])) : containsComponent$1(__props.token) ? (openBlock(), createElementBlock("span", _hoisted_4$2, [
15323
15325
  (openBlock(true), createElementBlock(Fragment, null, renderList(splitTextToken$1(__props.token), (subTok, j) => {
15324
15326
  return openBlock(), createBlock(_component_md_token_renderer, {
15325
15327
  key: j,
15326
15328
  token: subTok
15327
15329
  }, null, 8, ["token"]);
15328
15330
  }), 128))
15329
- ])) : (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(decodeBasicEntities(__props.token.text)), 1))
15331
+ ])) : (openBlock(), createElementBlock("span", _hoisted_5$2, toDisplayString(decodeBasicEntities(__props.token.text)), 1))
15330
15332
  ])) : __props.token.tokens && __props.token.tokens.length !== 0 ? (openBlock(), createElementBlock("span", _hoisted_6, [
15331
15333
  (openBlock(true), createElementBlock(Fragment, null, renderList(__props.token.tokens, (subTok, j) => {
15332
15334
  return openBlock(), createBlock(_component_md_token_renderer, {
@@ -15459,7 +15461,7 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15459
15461
  ], 8, _hoisted_25)) : __props.token.type === "html" ? (openBlock(), createElementBlock("span", {
15460
15462
  key: 13,
15461
15463
  innerHTML: __props.token.raw
15462
- }, null, 8, _hoisted_26)) : __props.token.type === "code" ? (openBlock(), createBlock(_sfc_main$6, {
15464
+ }, null, 8, _hoisted_26)) : __props.token.type === "code" ? (openBlock(), createBlock(_sfc_main$a, {
15463
15465
  key: 14,
15464
15466
  code: __props.token.text,
15465
15467
  language: __props.token.lang
@@ -15485,8 +15487,8 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15485
15487
  };
15486
15488
  }
15487
15489
  });
15488
- const MdTokenRenderer = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-047d0fa4"]]);
15489
- const _sfc_main$4 = defineComponent({
15490
+ const MdTokenRenderer = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-047d0fa4"]]);
15491
+ const _sfc_main$8 = defineComponent({
15490
15492
  name: "MarkdownRenderer",
15491
15493
  components: {
15492
15494
  MdTokenRenderer,
@@ -15504,7 +15506,7 @@ const _sfc_main$4 = defineComponent({
15504
15506
  }
15505
15507
  }
15506
15508
  });
15507
- function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
15509
+ function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
15508
15510
  const _component_md_token_renderer = resolveComponent("md-token-renderer");
15509
15511
  const _component_audio_auto_player = resolveComponent("audio-auto-player");
15510
15512
  return openBlock(), createElementBlock("div", null, [
@@ -15522,7 +15524,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
15522
15524
  }), 128))
15523
15525
  ]);
15524
15526
  }
15525
- const MarkdownRenderer = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$2]]);
15527
+ const MarkdownRenderer = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$5]]);
15526
15528
  const MarkdownRenderer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
15527
15529
  __proto__: null,
15528
15530
  default: MarkdownRenderer
@@ -15574,6 +15576,22 @@ const useAuthStore = () => {
15574
15576
  },
15575
15577
  setRegDialog(open) {
15576
15578
  this.loginAndRegistration.regDialogOpen = open;
15579
+ },
15580
+ async resetUserData() {
15581
+ try {
15582
+ if (!this._user) {
15583
+ throw new Error("No user available for data reset");
15584
+ }
15585
+ const result = await this._user.resetUserData();
15586
+ if (result.status !== "ok") {
15587
+ throw new Error(result.error || "Reset failed");
15588
+ }
15589
+ console.log("User data reset successfully");
15590
+ return result;
15591
+ } catch (error) {
15592
+ console.error("Failed to reset user data:", error);
15593
+ throw error;
15594
+ }
15577
15595
  }
15578
15596
  },
15579
15597
  getters: {
@@ -15638,185 +15656,364 @@ const useConfigStore = () => {
15638
15656
  }
15639
15657
  })();
15640
15658
  };
15641
- const _sfc_main$3 = defineComponent({
15642
- name: "UserChip",
15643
- data() {
15644
- return {
15645
- username: "",
15646
- items: [],
15647
- checked: false,
15648
- authStore: useAuthStore(),
15649
- configStore: useConfigStore()
15650
- };
15651
- },
15652
- computed: {
15653
- hasNewItems() {
15654
- return this.items.length > 0;
15659
+ function useAuthUI() {
15660
+ const isLoading = ref(true);
15661
+ const syncStrategyDetected = ref(false);
15662
+ const isLocalOnlyMode = ref(false);
15663
+ const config = computed(() => {
15664
+ if (isLocalOnlyMode.value) {
15665
+ return {
15666
+ showLoginRegistration: false,
15667
+ showLogout: false,
15668
+ showResetData: true,
15669
+ logoutLabel: "",
15670
+ resetLabel: "Reset User Data"
15671
+ };
15672
+ } else {
15673
+ return {
15674
+ showLoginRegistration: true,
15675
+ showLogout: true,
15676
+ showResetData: false,
15677
+ logoutLabel: "Log out",
15678
+ resetLabel: ""
15679
+ };
15655
15680
  }
15656
- },
15657
- created() {
15658
- getCurrentUser().then((u) => {
15659
- this.username = u.getUsername();
15681
+ });
15682
+ const detectSyncStrategy = async () => {
15683
+ try {
15684
+ isLoading.value = true;
15685
+ const user = await getCurrentUser();
15686
+ const userInternal = user;
15687
+ const canCreateAccount = userInternal.syncStrategy?.canCreateAccount?.();
15688
+ isLocalOnlyMode.value = !canCreateAccount;
15689
+ syncStrategyDetected.value = true;
15690
+ } catch (error) {
15691
+ console.error("Failed to detect sync strategy:", error);
15692
+ isLocalOnlyMode.value = false;
15693
+ syncStrategyDetected.value = true;
15694
+ } finally {
15695
+ isLoading.value = false;
15696
+ }
15697
+ };
15698
+ return {
15699
+ config,
15700
+ isLoading,
15701
+ syncStrategyDetected,
15702
+ isLocalOnlyMode,
15703
+ detectSyncStrategy
15704
+ };
15705
+ }
15706
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
15707
+ __name: "UserChip",
15708
+ setup(__props) {
15709
+ const router = useRouter();
15710
+ const authStore = useAuthStore();
15711
+ const configStore = useConfigStore();
15712
+ const authUI = useAuthUI();
15713
+ const username = ref("");
15714
+ const items = ref([]);
15715
+ const showResetDialog = ref(false);
15716
+ const confirmationText = ref("");
15717
+ const isConfirmationValid = computed(() => confirmationText.value === "reset");
15718
+ const resetDialogState = () => {
15719
+ confirmationText.value = "";
15720
+ showResetDialog.value = false;
15721
+ };
15722
+ const hasNewItems = computed(() => items.value.length > 0);
15723
+ const authUIConfig = computed(() => {
15724
+ const configValue = authUI.config.value;
15725
+ const fallback = {
15726
+ showLoginRegistration: true,
15727
+ showLogout: true,
15728
+ showResetData: false,
15729
+ logoutLabel: "Log out",
15730
+ resetLabel: ""
15731
+ };
15732
+ return configValue || fallback;
15660
15733
  });
15661
- },
15662
- methods: {
15663
- async gotoSettings() {
15664
- this.$router.push(`/u/${(await getCurrentUser()).getUsername()}`);
15665
- },
15666
- async gotoStats() {
15667
- this.$router.push(`/u/${(await getCurrentUser()).getUsername()}/stats`);
15668
- },
15669
- dismiss(item) {
15670
- const index = this.items.indexOf(item);
15671
- this.items.splice(index, 1);
15672
- },
15673
- async logout() {
15674
- const res = await this.authStore._user.logout();
15734
+ onMounted(async () => {
15735
+ const user = await getCurrentUser();
15736
+ username.value = user.getUsername();
15737
+ await authUI.detectSyncStrategy();
15738
+ });
15739
+ const gotoSettings = async () => {
15740
+ router.push(`/u/${(await getCurrentUser()).getUsername()}`);
15741
+ };
15742
+ const gotoStats = async () => {
15743
+ router.push(`/u/${(await getCurrentUser()).getUsername()}/stats`);
15744
+ };
15745
+ const dismiss = (item) => {
15746
+ const index = items.value.indexOf(item);
15747
+ items.value.splice(index, 1);
15748
+ };
15749
+ const logout = async () => {
15750
+ const res = await authStore._user.logout();
15675
15751
  if (res.ok) {
15676
- this.authStore.loginAndRegistration = {
15752
+ authStore.loginAndRegistration = {
15677
15753
  init: true,
15678
15754
  loggedIn: false,
15679
15755
  regDialogOpen: false,
15680
15756
  loginDialogOpen: false
15681
15757
  };
15682
- this.configStore.resetDefaults();
15683
- this.$router.push("/home");
15758
+ configStore.resetDefaults();
15759
+ router.push("/home");
15684
15760
  }
15685
- }
15686
- }
15687
- });
15688
- function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
15689
- const _component_v_icon = resolveComponent("v-icon");
15690
- const _component_v_avatar = resolveComponent("v-avatar");
15691
- const _component_v_chip = resolveComponent("v-chip");
15692
- const _component_v_list_item_title = resolveComponent("v-list-item-title");
15693
- const _component_v_list_item = resolveComponent("v-list-item");
15694
- const _component_v_divider = resolveComponent("v-divider");
15695
- const _component_v_list = resolveComponent("v-list");
15696
- const _component_v_menu = resolveComponent("v-menu");
15697
- const _component_v_badge = resolveComponent("v-badge");
15698
- return openBlock(), createBlock(_component_v_badge, {
15699
- content: _ctx.items.length,
15700
- "model-value": _ctx.hasNewItems,
15701
- color: "accent",
15702
- location: "end top"
15703
- }, {
15704
- default: withCtx(() => [
15705
- createVNode(_component_v_menu, {
15706
- location: "bottom end",
15707
- transition: "scale-transition"
15708
- }, {
15709
- activator: withCtx(({ props }) => [
15710
- createVNode(_component_v_chip, mergeProps(props, { class: "ma-2" }), {
15711
- default: withCtx(() => [
15712
- createVNode(_component_v_avatar, {
15713
- start: "",
15714
- class: "bg-primary"
15715
- }, {
15716
- default: withCtx(() => [
15717
- createVNode(_component_v_icon, null, {
15718
- default: withCtx(() => _cache[0] || (_cache[0] = [
15719
- createTextVNode("mdi-school")
15720
- ])),
15721
- _: 1
15722
- })
15723
- ]),
15724
- _: 1
15725
- }),
15726
- createTextVNode(" " + toDisplayString(_ctx.username), 1)
15727
- ]),
15728
- _: 2
15729
- }, 1040)
15730
- ]),
15731
- default: withCtx(() => [
15732
- createVNode(_component_v_list, null, {
15733
- default: withCtx(() => [
15734
- (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.items, (item) => {
15735
- return openBlock(), createBlock(_component_v_list_item, {
15736
- key: item,
15737
- onClick: ($event) => _ctx.dismiss(item)
15738
- }, {
15761
+ };
15762
+ const executeReset = async () => {
15763
+ try {
15764
+ await authStore.resetUserData();
15765
+ configStore.resetDefaults();
15766
+ resetDialogState();
15767
+ router.push("/home");
15768
+ } catch (error) {
15769
+ console.error("Failed to reset user data:", error);
15770
+ }
15771
+ };
15772
+ return (_ctx, _cache) => {
15773
+ const _component_v_icon = resolveComponent("v-icon");
15774
+ const _component_v_avatar = resolveComponent("v-avatar");
15775
+ const _component_v_chip = resolveComponent("v-chip");
15776
+ const _component_v_list_item_title = resolveComponent("v-list-item-title");
15777
+ const _component_v_list_item = resolveComponent("v-list-item");
15778
+ const _component_v_divider = resolveComponent("v-divider");
15779
+ const _component_v_list = resolveComponent("v-list");
15780
+ const _component_v_menu = resolveComponent("v-menu");
15781
+ const _component_v_badge = resolveComponent("v-badge");
15782
+ const _component_v_card_title = resolveComponent("v-card-title");
15783
+ const _component_v_text_field = resolveComponent("v-text-field");
15784
+ const _component_v_card_text = resolveComponent("v-card-text");
15785
+ const _component_v_spacer = resolveComponent("v-spacer");
15786
+ const _component_v_btn = resolveComponent("v-btn");
15787
+ const _component_v_card_actions = resolveComponent("v-card-actions");
15788
+ const _component_v_card = resolveComponent("v-card");
15789
+ const _component_v_dialog = resolveComponent("v-dialog");
15790
+ return openBlock(), createElementBlock(Fragment, null, [
15791
+ createVNode(_component_v_badge, {
15792
+ content: items.value.length,
15793
+ "model-value": hasNewItems.value,
15794
+ color: "accent",
15795
+ location: "end top"
15796
+ }, {
15797
+ default: withCtx(() => [
15798
+ createVNode(_component_v_menu, {
15799
+ location: "bottom end",
15800
+ transition: "scale-transition"
15801
+ }, {
15802
+ activator: withCtx(({ props }) => [
15803
+ createVNode(_component_v_chip, mergeProps(props, { class: "ma-2" }), {
15739
15804
  default: withCtx(() => [
15740
- createVNode(_component_v_list_item_title, null, {
15805
+ createVNode(_component_v_avatar, {
15806
+ start: "",
15807
+ class: "bg-primary"
15808
+ }, {
15741
15809
  default: withCtx(() => [
15742
- createTextVNode(toDisplayString(item), 1)
15810
+ createVNode(_component_v_icon, null, {
15811
+ default: withCtx(() => _cache[4] || (_cache[4] = [
15812
+ createTextVNode("mdi-school")
15813
+ ])),
15814
+ _: 1
15815
+ })
15743
15816
  ]),
15744
- _: 2
15745
- }, 1024)
15817
+ _: 1
15818
+ }),
15819
+ createTextVNode(" " + toDisplayString(username.value), 1)
15746
15820
  ]),
15747
15821
  _: 2
15748
- }, 1032, ["onClick"]);
15749
- }), 128)),
15750
- _ctx.items.length ? (openBlock(), createBlock(_component_v_divider, { key: 0 })) : createCommentVNode("", true),
15751
- createVNode(_component_v_list_item, { onClick: _ctx.gotoStats }, {
15752
- prepend: withCtx(() => [
15753
- createVNode(_component_v_icon, null, {
15754
- default: withCtx(() => _cache[1] || (_cache[1] = [
15755
- createTextVNode("mdi-trending-up")
15756
- ])),
15757
- _: 1
15758
- })
15759
- ]),
15760
- default: withCtx(() => [
15761
- createVNode(_component_v_list_item_title, null, {
15762
- default: withCtx(() => _cache[2] || (_cache[2] = [
15763
- createTextVNode("Stats")
15764
- ])),
15765
- _: 1
15766
- })
15767
- ]),
15768
- _: 1
15769
- }, 8, ["onClick"]),
15770
- createVNode(_component_v_list_item, { onClick: _ctx.gotoSettings }, {
15771
- prepend: withCtx(() => [
15772
- createVNode(_component_v_icon, null, {
15773
- default: withCtx(() => _cache[3] || (_cache[3] = [
15774
- createTextVNode("mdi-cog")
15775
- ])),
15776
- _: 1
15777
- })
15778
- ]),
15779
- default: withCtx(() => [
15780
- createVNode(_component_v_list_item_title, null, {
15781
- default: withCtx(() => _cache[4] || (_cache[4] = [
15782
- createTextVNode("Settings")
15783
- ])),
15784
- _: 1
15785
- })
15786
- ]),
15787
- _: 1
15788
- }, 8, ["onClick"]),
15789
- createVNode(_component_v_list_item, { onClick: _ctx.logout }, {
15790
- prepend: withCtx(() => [
15791
- createVNode(_component_v_icon, null, {
15792
- default: withCtx(() => _cache[5] || (_cache[5] = [
15793
- createTextVNode("mdi-logout")
15794
- ])),
15795
- _: 1
15796
- })
15797
- ]),
15798
- default: withCtx(() => [
15799
- createVNode(_component_v_list_item_title, null, {
15800
- default: withCtx(() => _cache[6] || (_cache[6] = [
15801
- createTextVNode("Log out")
15802
- ])),
15803
- _: 1
15804
- })
15805
- ]),
15806
- _: 1
15807
- }, 8, ["onClick"])
15808
- ]),
15809
- _: 1
15810
- })
15811
- ]),
15812
- _: 1
15813
- })
15814
- ]),
15815
- _: 1
15816
- }, 8, ["content", "model-value"]);
15817
- }
15818
- const UserChip = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$1]]);
15819
- const _sfc_main$2 = /* @__PURE__ */ defineComponent({
15822
+ }, 1040)
15823
+ ]),
15824
+ default: withCtx(() => [
15825
+ createVNode(_component_v_list, null, {
15826
+ default: withCtx(() => [
15827
+ (openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (item) => {
15828
+ return openBlock(), createBlock(_component_v_list_item, {
15829
+ key: item,
15830
+ onClick: ($event) => dismiss(item)
15831
+ }, {
15832
+ default: withCtx(() => [
15833
+ createVNode(_component_v_list_item_title, null, {
15834
+ default: withCtx(() => [
15835
+ createTextVNode(toDisplayString(item), 1)
15836
+ ]),
15837
+ _: 2
15838
+ }, 1024)
15839
+ ]),
15840
+ _: 2
15841
+ }, 1032, ["onClick"]);
15842
+ }), 128)),
15843
+ items.value.length ? (openBlock(), createBlock(_component_v_divider, { key: 0 })) : createCommentVNode("", true),
15844
+ createVNode(_component_v_list_item, { onClick: gotoStats }, {
15845
+ prepend: withCtx(() => [
15846
+ createVNode(_component_v_icon, null, {
15847
+ default: withCtx(() => _cache[5] || (_cache[5] = [
15848
+ createTextVNode("mdi-trending-up")
15849
+ ])),
15850
+ _: 1
15851
+ })
15852
+ ]),
15853
+ default: withCtx(() => [
15854
+ createVNode(_component_v_list_item_title, null, {
15855
+ default: withCtx(() => _cache[6] || (_cache[6] = [
15856
+ createTextVNode("Stats")
15857
+ ])),
15858
+ _: 1
15859
+ })
15860
+ ]),
15861
+ _: 1
15862
+ }),
15863
+ createVNode(_component_v_list_item, { onClick: gotoSettings }, {
15864
+ prepend: withCtx(() => [
15865
+ createVNode(_component_v_icon, null, {
15866
+ default: withCtx(() => _cache[7] || (_cache[7] = [
15867
+ createTextVNode("mdi-cog")
15868
+ ])),
15869
+ _: 1
15870
+ })
15871
+ ]),
15872
+ default: withCtx(() => [
15873
+ createVNode(_component_v_list_item_title, null, {
15874
+ default: withCtx(() => _cache[8] || (_cache[8] = [
15875
+ createTextVNode("Settings")
15876
+ ])),
15877
+ _: 1
15878
+ })
15879
+ ]),
15880
+ _: 1
15881
+ }),
15882
+ authUIConfig.value.showLogout ? (openBlock(), createBlock(_component_v_list_item, {
15883
+ key: 1,
15884
+ onClick: logout
15885
+ }, {
15886
+ prepend: withCtx(() => [
15887
+ createVNode(_component_v_icon, null, {
15888
+ default: withCtx(() => _cache[9] || (_cache[9] = [
15889
+ createTextVNode("mdi-logout")
15890
+ ])),
15891
+ _: 1
15892
+ })
15893
+ ]),
15894
+ default: withCtx(() => [
15895
+ createVNode(_component_v_list_item_title, null, {
15896
+ default: withCtx(() => [
15897
+ createTextVNode(toDisplayString(authUIConfig.value.logoutLabel), 1)
15898
+ ]),
15899
+ _: 1
15900
+ })
15901
+ ]),
15902
+ _: 1
15903
+ })) : createCommentVNode("", true),
15904
+ authUIConfig.value.showResetData ? (openBlock(), createBlock(_component_v_list_item, {
15905
+ key: 2,
15906
+ onClick: _cache[0] || (_cache[0] = ($event) => showResetDialog.value = true)
15907
+ }, {
15908
+ prepend: withCtx(() => [
15909
+ createVNode(_component_v_icon, null, {
15910
+ default: withCtx(() => _cache[10] || (_cache[10] = [
15911
+ createTextVNode("mdi-delete-sweep")
15912
+ ])),
15913
+ _: 1
15914
+ })
15915
+ ]),
15916
+ default: withCtx(() => [
15917
+ createVNode(_component_v_list_item_title, null, {
15918
+ default: withCtx(() => [
15919
+ createTextVNode(toDisplayString(authUIConfig.value.resetLabel), 1)
15920
+ ]),
15921
+ _: 1
15922
+ })
15923
+ ]),
15924
+ _: 1
15925
+ })) : createCommentVNode("", true)
15926
+ ]),
15927
+ _: 1
15928
+ })
15929
+ ]),
15930
+ _: 1
15931
+ })
15932
+ ]),
15933
+ _: 1
15934
+ }, 8, ["content", "model-value"]),
15935
+ createVNode(_component_v_dialog, {
15936
+ modelValue: showResetDialog.value,
15937
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => showResetDialog.value = $event),
15938
+ "max-width": "500px",
15939
+ persistent: ""
15940
+ }, {
15941
+ default: withCtx(() => [
15942
+ createVNode(_component_v_card, null, {
15943
+ default: withCtx(() => [
15944
+ createVNode(_component_v_card_title, { class: "text-h5 d-flex align-center" }, {
15945
+ default: withCtx(() => [
15946
+ createVNode(_component_v_icon, {
15947
+ color: "warning",
15948
+ class: "mr-3"
15949
+ }, {
15950
+ default: withCtx(() => _cache[11] || (_cache[11] = [
15951
+ createTextVNode("mdi-alert-circle")
15952
+ ])),
15953
+ _: 1
15954
+ }),
15955
+ _cache[12] || (_cache[12] = createTextVNode(" Reset All User Data "))
15956
+ ]),
15957
+ _: 1
15958
+ }),
15959
+ createVNode(_component_v_card_text, null, {
15960
+ default: withCtx(() => [
15961
+ _cache[13] || (_cache[13] = createElementVNode("p", { class: "mb-4" }, "This will permanently delete:", -1)),
15962
+ _cache[14] || (_cache[14] = createElementVNode("ul", { class: "mb-4" }, [
15963
+ createElementVNode("li", null, "All course progress and history"),
15964
+ createElementVNode("li", null, "Scheduled card reviews"),
15965
+ createElementVNode("li", null, "Course registrations"),
15966
+ createElementVNode("li", null, "User preferences")
15967
+ ], -1)),
15968
+ _cache[15] || (_cache[15] = createElementVNode("p", { class: "mb-4 text-error font-weight-bold" }, "This cannot be undone.", -1)),
15969
+ createVNode(_component_v_text_field, {
15970
+ modelValue: confirmationText.value,
15971
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => confirmationText.value = $event),
15972
+ label: 'Type "reset" to confirm',
15973
+ outlined: "",
15974
+ dense: "",
15975
+ onKeyup: _cache[2] || (_cache[2] = withKeys(($event) => isConfirmationValid.value && executeReset(), ["enter"]))
15976
+ }, null, 8, ["modelValue"])
15977
+ ]),
15978
+ _: 1
15979
+ }),
15980
+ createVNode(_component_v_card_actions, null, {
15981
+ default: withCtx(() => [
15982
+ createVNode(_component_v_spacer),
15983
+ createVNode(_component_v_btn, {
15984
+ text: "",
15985
+ onClick: resetDialogState
15986
+ }, {
15987
+ default: withCtx(() => _cache[16] || (_cache[16] = [
15988
+ createTextVNode("Cancel")
15989
+ ])),
15990
+ _: 1
15991
+ }),
15992
+ createVNode(_component_v_btn, {
15993
+ color: "error",
15994
+ disabled: !isConfirmationValid.value,
15995
+ onClick: executeReset
15996
+ }, {
15997
+ default: withCtx(() => _cache[17] || (_cache[17] = [
15998
+ createTextVNode(" Reset All Data ")
15999
+ ])),
16000
+ _: 1
16001
+ }, 8, ["disabled"])
16002
+ ]),
16003
+ _: 1
16004
+ })
16005
+ ]),
16006
+ _: 1
16007
+ })
16008
+ ]),
16009
+ _: 1
16010
+ }, 8, ["modelValue"])
16011
+ ], 64);
16012
+ };
16013
+ }
16014
+ });
16015
+ const UserChip = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-53f0aa4d"]]);
16016
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15820
16017
  __name: "UserLogin",
15821
16018
  emits: ["toggle"],
15822
16019
  setup(__props, { emit: __emit }) {
@@ -16003,8 +16200,8 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
16003
16200
  };
16004
16201
  }
16005
16202
  });
16006
- const UserLogin = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-acfaa2d0"]]);
16007
- const _sfc_main$1 = defineComponent({
16203
+ const UserLogin = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-acfaa2d0"]]);
16204
+ const _sfc_main$5 = defineComponent({
16008
16205
  name: "UserRegistration",
16009
16206
  emits: ["toggle"],
16010
16207
  data() {
@@ -16103,7 +16300,7 @@ Author: ${this.author}
16103
16300
  }
16104
16301
  }
16105
16302
  });
16106
- function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
16303
+ function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
16107
16304
  const _component_v_card_title = resolveComponent("v-card-title");
16108
16305
  const _component_v_text_field = resolveComponent("v-text-field");
16109
16306
  const _component_v_btn = resolveComponent("v-btn");
@@ -16238,13 +16435,17 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
16238
16435
  _: 1
16239
16436
  });
16240
16437
  }
16241
- const UserRegistration = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
16242
- const _hoisted_1 = { key: 0 };
16243
- const _sfc_main = /* @__PURE__ */ defineComponent({
16438
+ const UserRegistration = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4]]);
16439
+ const _hoisted_1$4 = { key: 0 };
16440
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
16244
16441
  __name: "UserLoginAndRegistrationContainer",
16245
16442
  setup(__props) {
16246
16443
  const route = useRoute();
16247
16444
  const authStore = useAuthStore();
16445
+ const authUI = useAuthUI();
16446
+ onMounted(async () => {
16447
+ await authUI.detectSyncStrategy();
16448
+ });
16248
16449
  const display = computed(() => {
16249
16450
  if (!route.name || typeof route.name !== "string") {
16250
16451
  return true;
@@ -16259,6 +16460,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
16259
16460
  }
16260
16461
  return !authStore.loginAndRegistration.loggedIn;
16261
16462
  });
16463
+ const authUIConfig = computed(() => authUI.config.value || {
16464
+ showLoginRegistration: true,
16465
+ showLogout: true,
16466
+ showResetData: false,
16467
+ logoutLabel: "Log out",
16468
+ resetLabel: ""
16469
+ });
16262
16470
  const regDialog = computed({
16263
16471
  get: () => authStore.loginAndRegistration.regDialogOpen,
16264
16472
  set: (value) => {
@@ -16290,7 +16498,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
16290
16498
  mode: "out-in"
16291
16499
  }, {
16292
16500
  default: withCtx(() => [
16293
- guestMode.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
16501
+ guestMode.value && authUIConfig.value.showLoginRegistration ? (openBlock(), createElementBlock("div", _hoisted_1$4, [
16294
16502
  createVNode(_component_v_dialog, {
16295
16503
  modelValue: regDialog.value,
16296
16504
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => regDialog.value = $event),
@@ -16341,12 +16549,966 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
16341
16549
  };
16342
16550
  }
16343
16551
  });
16344
- const UserLoginAndRegistrationContainer = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e53f877f"]]);
16552
+ const UserLoginAndRegistrationContainer = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-6091ae05"]]);
16553
+ const _sfc_main$3 = defineComponent({
16554
+ name: "SkTagsInput",
16555
+ components: {
16556
+ VueTagsInput
16557
+ },
16558
+ props: {
16559
+ courseID: {
16560
+ type: String,
16561
+ required: true,
16562
+ default: ""
16563
+ },
16564
+ cardID: {
16565
+ type: String,
16566
+ required: false,
16567
+ default: ""
16568
+ },
16569
+ hideSubmit: {
16570
+ type: Boolean,
16571
+ required: false,
16572
+ default: false
16573
+ }
16574
+ },
16575
+ data() {
16576
+ return {
16577
+ loading: true,
16578
+ tag: "",
16579
+ tags: [],
16580
+ initialTags: [],
16581
+ availableCourseTags: [],
16582
+ separators: [";", ",", " "],
16583
+ courseDB: null
16584
+ };
16585
+ },
16586
+ computed: {
16587
+ autoCompleteSuggestions() {
16588
+ return this.availableCourseTags.filter((availableTag) => {
16589
+ return availableTag.name.toLowerCase().indexOf(this.tag.toLowerCase()) !== -1;
16590
+ }).map((availableTag) => {
16591
+ return {
16592
+ text: availableTag.name,
16593
+ data: {
16594
+ snippet: availableTag.snippet
16595
+ }
16596
+ };
16597
+ });
16598
+ }
16599
+ },
16600
+ watch: {
16601
+ async cardID() {
16602
+ await this.getAppliedTags();
16603
+ },
16604
+ async courseID() {
16605
+ this.courseDB = getDataLayer().getCourseDB(this.courseID);
16606
+ await this.updateAvailableCourseTags();
16607
+ }
16608
+ },
16609
+ async created() {
16610
+ this.courseDB = getDataLayer().getCourseDB(this.courseID);
16611
+ await this.updateAvailableCourseTags();
16612
+ await this.getAppliedTags();
16613
+ },
16614
+ methods: {
16615
+ tagsChanged(newTags) {
16616
+ console.log(`[TagsInput] Tags changing: ${JSON.stringify(newTags)}`);
16617
+ this.tags = newTags;
16618
+ },
16619
+ async getAppliedTags() {
16620
+ this.initialTags = [];
16621
+ this.tags = [];
16622
+ try {
16623
+ const appliedDocsFindResult = await this.courseDB.getAppliedTags(this.cardID);
16624
+ appliedDocsFindResult.rows.forEach((row) => {
16625
+ console.log(`[TagsInput] The following tag is applied:
16626
+ ${JSON.stringify(row)}`);
16627
+ this.tags.push({
16628
+ text: row.value.name,
16629
+ style: "",
16630
+ classes: ""
16631
+ });
16632
+ });
16633
+ this.initialTags = this.tags.map((tag2) => tag2.text);
16634
+ } catch (e) {
16635
+ console.error(`Error in init-getAppliedTags: ${JSON.stringify(e)}, ${e}`);
16636
+ } finally {
16637
+ this.loading = false;
16638
+ }
16639
+ },
16640
+ async updateAvailableCourseTags() {
16641
+ try {
16642
+ this.availableCourseTags = (await this.courseDB.getCourseTagStubs()).rows.map((row) => {
16643
+ console.log(`[TagsInput] available tag: ${JSON.stringify(row)}`);
16644
+ return row.doc;
16645
+ });
16646
+ } catch (e) {
16647
+ console.error(`Error in init-availableCourseTags: ${JSON.stringify(e)}`);
16648
+ }
16649
+ },
16650
+ async submit() {
16651
+ console.log(`[TagsInput] tagsInput is submitting...`);
16652
+ this.loading = true;
16653
+ try {
16654
+ await Promise.all(
16655
+ this.tags.map(async (currentTag) => {
16656
+ if (!this.initialTags.includes(currentTag.text)) {
16657
+ try {
16658
+ await this.courseDB.addTagToCard(this.cardID, currentTag.text);
16659
+ console.log(`[TagsInput] Successfully added tag: ${currentTag.text}`);
16660
+ } catch (error) {
16661
+ console.error(`Failed to add tag ${currentTag.text}:`, error);
16662
+ }
16663
+ }
16664
+ })
16665
+ );
16666
+ } catch (e) {
16667
+ console.error(`Exception adding tags: ${JSON.stringify(e)}`);
16668
+ }
16669
+ try {
16670
+ await Promise.all(
16671
+ this.initialTags.map(async (initialTag) => {
16672
+ if (this.tags.filter((tag2) => {
16673
+ return tag2.text === initialTag;
16674
+ }).length === 0) {
16675
+ try {
16676
+ await this.courseDB.removeTagFromCard(this.cardID, initialTag);
16677
+ console.log(`[TagsInput] Successfully removed tag: ${initialTag}`);
16678
+ } catch (error) {
16679
+ console.error(`Failed to remove tag ${initialTag}:`, error);
16680
+ }
16681
+ }
16682
+ })
16683
+ );
16684
+ } catch (e) {
16685
+ console.error(`Exception removing tags: ${JSON.stringify(e)}`);
16686
+ }
16687
+ this.loading = false;
16688
+ }
16689
+ }
16690
+ });
16691
+ const _hoisted_1$3 = { "data-cy": "tags-input" };
16692
+ const _hoisted_2$2 = { class: "tag-name" };
16693
+ const _hoisted_3$2 = {
16694
+ key: 0,
16695
+ class: "tag-snippet"
16696
+ };
16697
+ function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
16698
+ const _component_vue_tags_input = resolveComponent("vue-tags-input");
16699
+ const _component_v_btn = resolveComponent("v-btn");
16700
+ return openBlock(), createElementBlock("div", _hoisted_1$3, [
16701
+ createVNode(_component_vue_tags_input, {
16702
+ modelValue: _ctx.tag,
16703
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.tag = $event),
16704
+ tags: _ctx.tags,
16705
+ "autocomplete-items": _ctx.autoCompleteSuggestions,
16706
+ separators: _ctx.separators,
16707
+ "add-on-key": _ctx.separators,
16708
+ onTagsChanged: _ctx.tagsChanged
16709
+ }, {
16710
+ "autocomplete-item": withCtx((props) => [
16711
+ createElementVNode("div", {
16712
+ class: normalizeClass(["autocomplete-item", { "is-active": props.selected }])
16713
+ }, [
16714
+ createElementVNode("span", _hoisted_2$2, toDisplayString(props.item.text), 1),
16715
+ props.item.data && props.item.data.snippet ? (openBlock(), createElementBlock("span", _hoisted_3$2, " - " + toDisplayString(props.item.data.snippet), 1)) : createCommentVNode("", true)
16716
+ ], 2)
16717
+ ]),
16718
+ _: 1
16719
+ }, 8, ["modelValue", "tags", "autocomplete-items", "separators", "add-on-key", "onTagsChanged"]),
16720
+ !_ctx.hideSubmit ? (openBlock(), createBlock(_component_v_btn, {
16721
+ key: 0,
16722
+ color: "success",
16723
+ loading: _ctx.loading,
16724
+ onClick: _ctx.submit
16725
+ }, {
16726
+ default: withCtx(() => _cache[1] || (_cache[1] = [
16727
+ createTextVNode("Save Changes")
16728
+ ])),
16729
+ _: 1
16730
+ }, 8, ["loading", "onClick"])) : createCommentVNode("", true)
16731
+ ]);
16732
+ }
16733
+ const TagsInput = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3], ["__scopeId", "data-v-dec3b5c8"]]);
16734
+ function isConstructor(obj) {
16735
+ try {
16736
+ new obj();
16737
+ return true;
16738
+ } catch (e) {
16739
+ console.warn(`not a constructor: ${obj}, err: ${e}`);
16740
+ return false;
16741
+ }
16742
+ }
16743
+ const _sfc_main$2 = defineComponent({
16744
+ name: "CourseCardBrowser",
16745
+ components: {
16746
+ CardLoader,
16747
+ TagsInput,
16748
+ PaginatingToolbar
16749
+ },
16750
+ props: {
16751
+ courseId: {
16752
+ type: String,
16753
+ required: true
16754
+ },
16755
+ tagId: {
16756
+ type: String,
16757
+ required: false,
16758
+ default: ""
16759
+ },
16760
+ viewLookupFunction: {
16761
+ type: Function,
16762
+ required: true,
16763
+ default: (x) => {
16764
+ console.warn("No viewLookupFunction provided to CourseCardBrowser");
16765
+ return null;
16766
+ }
16767
+ },
16768
+ editMode: {
16769
+ type: String,
16770
+ required: false,
16771
+ default: "full"
16772
+ }
16773
+ },
16774
+ data() {
16775
+ return {
16776
+ courseDB: null,
16777
+ page: 1,
16778
+ pages: [],
16779
+ cards: [],
16780
+ cardData: {},
16781
+ cardPreview: {},
16782
+ internalEditMode: "none",
16783
+ delBtn: false,
16784
+ updatePending: true,
16785
+ userIsRegistered: false,
16786
+ questionCount: 0,
16787
+ tags: [],
16788
+ viewLookup: this.viewLookupFunction
16789
+ };
16790
+ },
16791
+ async created() {
16792
+ try {
16793
+ this.courseDB = getDataLayer().getCourseDB(this.courseId);
16794
+ if (this.tagId) {
16795
+ this.questionCount = (await this.courseDB.getTag(this.tagId)).taggedCards.length;
16796
+ } else {
16797
+ this.questionCount = (await this.courseDB.getCourseInfo()).cardCount;
16798
+ }
16799
+ for (let i = 1; (i - 1) * 25 < this.questionCount; i++) {
16800
+ this.pages.push(i);
16801
+ }
16802
+ await this.populateTableData();
16803
+ } catch (error) {
16804
+ console.error("Error initializing CourseCardBrowser:", error);
16805
+ } finally {
16806
+ this.updatePending = false;
16807
+ }
16808
+ },
16809
+ methods: {
16810
+ first() {
16811
+ this.page = 1;
16812
+ this.populateTableData();
16813
+ },
16814
+ prev() {
16815
+ this.page--;
16816
+ this.populateTableData();
16817
+ },
16818
+ next() {
16819
+ this.page++;
16820
+ this.populateTableData();
16821
+ },
16822
+ last() {
16823
+ this.page = this.pages.length;
16824
+ this.populateTableData();
16825
+ },
16826
+ setPage(n) {
16827
+ this.page = n;
16828
+ this.populateTableData();
16829
+ },
16830
+ clearSelections(exception = "") {
16831
+ this.cards.forEach((card) => {
16832
+ if (card.id !== exception) {
16833
+ card.isOpen = false;
16834
+ }
16835
+ });
16836
+ this.internalEditMode = "none";
16837
+ this.delBtn = false;
16838
+ },
16839
+ async deleteCard(c) {
16840
+ console.log(`Deleting card ${c}`);
16841
+ const res = await this.courseDB.removeCard(c.split("-")[1]);
16842
+ if (res.ok) {
16843
+ this.cards = this.cards.filter((card) => card.id != c);
16844
+ this.clearSelections();
16845
+ } else {
16846
+ console.error(`Failed to delete card:
16847
+
16848
+ ${JSON.stringify(res)}`);
16849
+ alertUser({
16850
+ text: "Failed to delete card",
16851
+ status: Status.error
16852
+ });
16853
+ }
16854
+ },
16855
+ async populateTableData() {
16856
+ this.updatePending = true;
16857
+ if (this.tagId) {
16858
+ const tag2 = await this.courseDB.getTag(this.tagId);
16859
+ this.cards = tag2.taggedCards.map((c) => {
16860
+ return { id: `${this.courseId}-${c}`, isOpen: false, delBtn: false };
16861
+ });
16862
+ } else {
16863
+ this.cards = (await this.courseDB.getCardsByELO(0, 25)).map((c) => {
16864
+ return {
16865
+ id: c,
16866
+ isOpen: false,
16867
+ delBtn: false
16868
+ };
16869
+ });
16870
+ }
16871
+ const toRemove = [];
16872
+ const hydratedCardData = (await this.courseDB.getCourseDocs(
16873
+ this.cards.map((c) => c.id.split("-")[1]),
16874
+ {
16875
+ include_docs: true
16876
+ }
16877
+ )).rows.filter((r2) => {
16878
+ if (r2.doc) {
16879
+ return true;
16880
+ } else {
16881
+ console.error(`Card ${r2.id}.doc not found.
16882
+ card: ${JSON.stringify(r2)}`);
16883
+ return false;
16884
+ }
16885
+ }).map((r2) => r2.doc);
16886
+ this.cards = this.cards.filter((c) => !toRemove.includes(c.id.split("-")[1]));
16887
+ hydratedCardData.forEach((c) => {
16888
+ if (c && c.id_displayable_data) {
16889
+ this.cardData[c._id] = c.id_displayable_data;
16890
+ }
16891
+ });
16892
+ try {
16893
+ await Promise.all(
16894
+ this.cards.map(async (c) => {
16895
+ const _cardID = c.id.split("-")[1];
16896
+ const tmpCardData = hydratedCardData.find((c2) => c2._id == _cardID);
16897
+ if (!tmpCardData || !tmpCardData.id_displayable_data) {
16898
+ console.error(`No valid data found for card ${_cardID}`);
16899
+ return;
16900
+ }
16901
+ const tmpView = this.viewLookupFunction(
16902
+ tmpCardData.id_view || "default.question.BlanksCard.FillInView"
16903
+ );
16904
+ const tmpDataDocs = tmpCardData.id_displayable_data.map((id) => {
16905
+ return this.courseDB.getCourseDoc(id, {
16906
+ attachments: false,
16907
+ binary: true
16908
+ });
16909
+ });
16910
+ const allDocs = await Promise.all(tmpDataDocs);
16911
+ await Promise.all(
16912
+ allDocs.map((doc) => {
16913
+ const tmpData = [];
16914
+ tmpData.unshift(displayableDataToViewData(doc));
16915
+ if (isConstructor(tmpView)) {
16916
+ const view = new tmpView();
16917
+ view.data = tmpData;
16918
+ this.cardPreview[c.id] = view.toString();
16919
+ } else {
16920
+ this.cardPreview[c.id] = tmpView.name ? tmpView.name : "Unknown";
16921
+ }
16922
+ })
16923
+ );
16924
+ })
16925
+ );
16926
+ } catch (error) {
16927
+ console.error("Error populating table data:", error);
16928
+ } finally {
16929
+ this.updatePending = false;
16930
+ this.$forceUpdate();
16931
+ }
16932
+ }
16933
+ }
16934
+ });
16935
+ const _hoisted_1$2 = {
16936
+ key: 0,
16937
+ class: "d-flex justify-center align-center pa-6"
16938
+ };
16939
+ const _hoisted_2$1 = { key: 1 };
16940
+ const _hoisted_3$1 = {
16941
+ key: 0,
16942
+ class: "px-4 py-2 bg-blue-grey-lighten-5"
16943
+ };
16944
+ const _hoisted_4$1 = { class: "mt-4" };
16945
+ const _hoisted_5$1 = {
16946
+ key: 0,
16947
+ class: "ml-4"
16948
+ };
16949
+ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
16950
+ const _component_v_progress_circular = resolveComponent("v-progress-circular");
16951
+ const _component_paginating_toolbar = resolveComponent("paginating-toolbar");
16952
+ const _component_v_list_item_title = resolveComponent("v-list-item-title");
16953
+ const _component_v_list_item_subtitle = resolveComponent("v-list-item-subtitle");
16954
+ const _component_v_btn = resolveComponent("v-btn");
16955
+ const _component_v_icon = resolveComponent("v-icon");
16956
+ const _component_v_speed_dial = resolveComponent("v-speed-dial");
16957
+ const _component_v_list_item = resolveComponent("v-list-item");
16958
+ const _component_card_loader = resolveComponent("card-loader");
16959
+ const _component_tags_input = resolveComponent("tags-input");
16960
+ const _component_v_list = resolveComponent("v-list");
16961
+ const _component_v_card = resolveComponent("v-card");
16962
+ return openBlock(), createBlock(_component_v_card, null, {
16963
+ default: withCtx(() => [
16964
+ _ctx.updatePending ? (openBlock(), createElementBlock("div", _hoisted_1$2, [
16965
+ createVNode(_component_v_progress_circular, {
16966
+ indeterminate: "",
16967
+ color: "primary"
16968
+ })
16969
+ ])) : (openBlock(), createElementBlock("div", _hoisted_2$1, [
16970
+ createVNode(_component_paginating_toolbar, {
16971
+ title: "Exercises",
16972
+ page: _ctx.page,
16973
+ pages: _ctx.pages,
16974
+ subtitle: `(${_ctx.questionCount})`,
16975
+ onFirst: _ctx.first,
16976
+ onPrev: _ctx.prev,
16977
+ onNext: _ctx.next,
16978
+ onLast: _ctx.last,
16979
+ onSetPage: _cache[0] || (_cache[0] = (n) => _ctx.setPage(n))
16980
+ }, null, 8, ["page", "pages", "subtitle", "onFirst", "onPrev", "onNext", "onLast"]),
16981
+ createVNode(_component_v_list, null, {
16982
+ default: withCtx(() => [
16983
+ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.cards, (c) => {
16984
+ return openBlock(), createElementBlock(Fragment, {
16985
+ key: c.id
16986
+ }, [
16987
+ createVNode(_component_v_list_item, {
16988
+ class: normalizeClass({
16989
+ "bg-blue-grey-lighten-5": c.isOpen,
16990
+ "elevation-4": c.isOpen
16991
+ }),
16992
+ density: "compact",
16993
+ "data-cy": "course-card"
16994
+ }, {
16995
+ prepend: withCtx(() => [
16996
+ createElementVNode("div", null, [
16997
+ createVNode(_component_v_list_item_title, {
16998
+ class: normalizeClass([{ "text-blue-grey-darken-1": c.isOpen }, "font-weight-medium"])
16999
+ }, {
17000
+ default: withCtx(() => [
17001
+ createTextVNode(toDisplayString(_ctx.cardPreview[c.id]), 1)
17002
+ ]),
17003
+ _: 2
17004
+ }, 1032, ["class"]),
17005
+ createVNode(_component_v_list_item_subtitle, null, {
17006
+ default: withCtx(() => [
17007
+ createTextVNode(toDisplayString(c.id.split("-").length === 3 ? c.id.split("-")[2] : ""), 1)
17008
+ ]),
17009
+ _: 2
17010
+ }, 1024)
17011
+ ])
17012
+ ]),
17013
+ append: withCtx(() => [
17014
+ _ctx.editMode === "full" ? (openBlock(), createBlock(_component_v_speed_dial, {
17015
+ key: 0,
17016
+ modelValue: c.isOpen,
17017
+ "onUpdate:modelValue": ($event) => c.isOpen = $event,
17018
+ location: "left center",
17019
+ transition: "slide-x-transition",
17020
+ style: { "display": "flex", "flex-direction": "row-reverse" },
17021
+ persistent: ""
17022
+ }, {
17023
+ activator: withCtx(({ props }) => [
17024
+ createVNode(_component_v_btn, mergeProps({ ref_for: true }, props, {
17025
+ icon: c.isOpen ? "mdi-close" : "mdi-plus",
17026
+ size: "small",
17027
+ variant: "text",
17028
+ onClick: ($event) => _ctx.clearSelections(c.id)
17029
+ }), null, 16, ["icon", "onClick"])
17030
+ ]),
17031
+ default: withCtx(() => [
17032
+ createVNode(_component_v_btn, {
17033
+ key: "tags",
17034
+ icon: "",
17035
+ size: "small",
17036
+ variant: _ctx.internalEditMode !== "tags" ? "outlined" : "elevated",
17037
+ color: _ctx.internalEditMode === "tags" ? "teal" : "teal-darken-3",
17038
+ onClick: _cache[1] || (_cache[1] = withModifiers(($event) => _ctx.internalEditMode = "tags", ["stop"]))
17039
+ }, {
17040
+ default: withCtx(() => [
17041
+ createVNode(_component_v_icon, null, {
17042
+ default: withCtx(() => _cache[4] || (_cache[4] = [
17043
+ createTextVNode("mdi-bookmark")
17044
+ ])),
17045
+ _: 1
17046
+ })
17047
+ ]),
17048
+ _: 1
17049
+ }, 8, ["variant", "color"]),
17050
+ createVNode(_component_v_btn, {
17051
+ key: "flag",
17052
+ icon: "",
17053
+ size: "small",
17054
+ variant: _ctx.internalEditMode !== "flag" ? "outlined" : "elevated",
17055
+ color: _ctx.internalEditMode === "flag" ? "error" : "error-darken-3",
17056
+ onClick: _cache[2] || (_cache[2] = withModifiers(($event) => _ctx.internalEditMode = "flag", ["stop"]))
17057
+ }, {
17058
+ default: withCtx(() => [
17059
+ createVNode(_component_v_icon, null, {
17060
+ default: withCtx(() => _cache[5] || (_cache[5] = [
17061
+ createTextVNode("mdi-flag")
17062
+ ])),
17063
+ _: 1
17064
+ })
17065
+ ]),
17066
+ _: 1
17067
+ }, 8, ["variant", "color"])
17068
+ ]),
17069
+ _: 2
17070
+ }, 1032, ["modelValue", "onUpdate:modelValue"])) : createCommentVNode("", true)
17071
+ ]),
17072
+ _: 2
17073
+ }, 1032, ["class"]),
17074
+ c.isOpen ? (openBlock(), createElementBlock("div", _hoisted_3$1, [
17075
+ createVNode(_component_card_loader, {
17076
+ qualified_id: c.id,
17077
+ "view-lookup": _ctx.viewLookup,
17078
+ class: "elevation-1"
17079
+ }, null, 8, ["qualified_id", "view-lookup"]),
17080
+ withDirectives(createVNode(_component_tags_input, {
17081
+ "course-i-d": _ctx.courseId,
17082
+ "card-i-d": c.id.split("-")[1],
17083
+ class: "mt-4"
17084
+ }, null, 8, ["course-i-d", "card-i-d"]), [
17085
+ [vShow, _ctx.internalEditMode === "tags"]
17086
+ ]),
17087
+ withDirectives(createElementVNode("div", _hoisted_4$1, [
17088
+ createVNode(_component_v_btn, {
17089
+ color: "error",
17090
+ variant: "outlined",
17091
+ onClick: ($event) => c.delBtn = true
17092
+ }, {
17093
+ default: withCtx(() => _cache[6] || (_cache[6] = [
17094
+ createTextVNode(" Delete this card ")
17095
+ ])),
17096
+ _: 2
17097
+ }, 1032, ["onClick"]),
17098
+ c.delBtn ? (openBlock(), createElementBlock("span", _hoisted_5$1, [
17099
+ _cache[8] || (_cache[8] = createElementVNode("span", { class: "mr-2" }, "Are you sure?", -1)),
17100
+ createVNode(_component_v_btn, {
17101
+ color: "error",
17102
+ variant: "elevated",
17103
+ onClick: ($event) => _ctx.deleteCard(c.id)
17104
+ }, {
17105
+ default: withCtx(() => _cache[7] || (_cache[7] = [
17106
+ createTextVNode(" Confirm ")
17107
+ ])),
17108
+ _: 2
17109
+ }, 1032, ["onClick"])
17110
+ ])) : createCommentVNode("", true)
17111
+ ], 512), [
17112
+ [vShow, _ctx.internalEditMode === "flag"]
17113
+ ])
17114
+ ])) : createCommentVNode("", true)
17115
+ ], 64);
17116
+ }), 128))
17117
+ ]),
17118
+ _: 1
17119
+ }),
17120
+ createVNode(_component_paginating_toolbar, {
17121
+ class: "elevation-0",
17122
+ page: _ctx.page,
17123
+ pages: _ctx.pages,
17124
+ onFirst: _ctx.first,
17125
+ onPrev: _ctx.prev,
17126
+ onNext: _ctx.next,
17127
+ onLast: _ctx.last,
17128
+ onSetPage: _cache[3] || (_cache[3] = (n) => _ctx.setPage(n))
17129
+ }, null, 8, ["page", "pages", "onFirst", "onPrev", "onNext", "onLast"])
17130
+ ]))
17131
+ ]),
17132
+ _: 1
17133
+ });
17134
+ }
17135
+ const CourseCardBrowser = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2], ["__scopeId", "data-v-0beef6a4"]]);
17136
+ const _sfc_main$1 = defineComponent({
17137
+ name: "CourseInformation",
17138
+ components: {
17139
+ // MidiConfig, // Removed to break circular dependency
17140
+ CourseCardBrowser
17141
+ },
17142
+ props: {
17143
+ courseId: {
17144
+ type: String,
17145
+ required: true
17146
+ },
17147
+ viewLookupFunction: {
17148
+ type: Function,
17149
+ required: false,
17150
+ default: (x) => {
17151
+ console.warn("No viewLookupFunction provided to CourseInformation");
17152
+ return null;
17153
+ }
17154
+ },
17155
+ editMode: {
17156
+ type: String,
17157
+ required: false,
17158
+ default: "full"
17159
+ }
17160
+ },
17161
+ data() {
17162
+ return {
17163
+ courseDB: null,
17164
+ nameRules: [
17165
+ (value) => {
17166
+ const max2 = 30;
17167
+ return value.length > max2 ? `Course name must be ${max2} characters or less` : true;
17168
+ }
17169
+ ],
17170
+ updatePending: true,
17171
+ courseConfig: {},
17172
+ userIsRegistered: false,
17173
+ tags: [],
17174
+ user: null
17175
+ };
17176
+ },
17177
+ computed: {
17178
+ // isPianoCourse removed - piano-specific logic should be in wrapper component
17179
+ },
17180
+ async created() {
17181
+ this.courseDB = getDataLayer().getCourseDB(this.courseId);
17182
+ this.user = await getCurrentUser();
17183
+ const userCourses = await this.user.getCourseRegistrationsDoc();
17184
+ if (this.user.getUsername() === "admin") {
17185
+ this.userIsRegistered = true;
17186
+ } else {
17187
+ this.userIsRegistered = userCourses.courses.filter((c) => {
17188
+ return c.courseID === this.courseId && (c.status === "active" || c.status === void 0);
17189
+ }).length === 1;
17190
+ }
17191
+ this.courseConfig = await this.courseDB.getCourseConfig();
17192
+ this.tags = (await this.courseDB.getCourseTagStubs()).rows.map((r2) => r2.doc);
17193
+ this.updatePending = false;
17194
+ },
17195
+ methods: {
17196
+ async register() {
17197
+ log(`Registering for ${this.courseId}`);
17198
+ const res = await this.user.registerForCourse(this.courseId);
17199
+ if (res.ok) {
17200
+ this.userIsRegistered = true;
17201
+ }
17202
+ },
17203
+ async drop() {
17204
+ log(`Dropping course ${this.courseId}`);
17205
+ const res = await this.user.dropCourse(this.courseId);
17206
+ if (res.ok) {
17207
+ this.userIsRegistered = false;
17208
+ }
17209
+ }
17210
+ }
17211
+ });
17212
+ const _hoisted_1$1 = { key: 0 };
17213
+ const _hoisted_2 = { class: "text-h4 mb-2" };
17214
+ const _hoisted_3 = { class: "text-body-2" };
17215
+ const _hoisted_4 = { key: 0 };
17216
+ const _hoisted_5 = { key: 1 };
17217
+ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
17218
+ const _component_v_btn = resolveComponent("v-btn");
17219
+ const _component_v_icon = resolveComponent("v-icon");
17220
+ const _component_v_toolbar_title = resolveComponent("v-toolbar-title");
17221
+ const _component_v_toolbar_items = resolveComponent("v-toolbar-items");
17222
+ const _component_v_toolbar = resolveComponent("v-toolbar");
17223
+ const _component_v_chip = resolveComponent("v-chip");
17224
+ const _component_v_card_text = resolveComponent("v-card-text");
17225
+ const _component_v_card = resolveComponent("v-card");
17226
+ const _component_course_card_browser = resolveComponent("course-card-browser");
17227
+ return !_ctx.updatePending ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
17228
+ renderSlot(_ctx.$slots, "header", {
17229
+ courseConfig: _ctx.courseConfig,
17230
+ courseId: _ctx.courseId
17231
+ }, () => [
17232
+ createElementVNode("h1", _hoisted_2, toDisplayString(_ctx.courseConfig.name), 1)
17233
+ ], true),
17234
+ createElementVNode("p", _hoisted_3, toDisplayString(_ctx.courseConfig.description), 1),
17235
+ renderSlot(_ctx.$slots, "actions", {
17236
+ userIsRegistered: _ctx.userIsRegistered,
17237
+ courseId: _ctx.courseId,
17238
+ editMode: _ctx.editMode,
17239
+ register: _ctx.register,
17240
+ drop: _ctx.drop
17241
+ }, () => [
17242
+ createVNode(Transition, {
17243
+ name: "component-fade",
17244
+ mode: "out-in"
17245
+ }, {
17246
+ default: withCtx(() => [
17247
+ _ctx.userIsRegistered ? (openBlock(), createElementBlock("div", _hoisted_4, [
17248
+ createVNode(_component_v_btn, {
17249
+ color: "success",
17250
+ class: "me-2"
17251
+ }, {
17252
+ default: withCtx(() => _cache[0] || (_cache[0] = [
17253
+ createTextVNode("Start a study session")
17254
+ ])),
17255
+ _: 1
17256
+ }),
17257
+ _ctx.editMode === "full" ? (openBlock(), createBlock(_component_v_btn, {
17258
+ key: 0,
17259
+ "data-cy": "add-content-btn",
17260
+ color: "indigo-lighten-1",
17261
+ class: "me-2"
17262
+ }, {
17263
+ default: withCtx(() => [
17264
+ createVNode(_component_v_icon, { start: "" }, {
17265
+ default: withCtx(() => _cache[1] || (_cache[1] = [
17266
+ createTextVNode("mdi-plus")
17267
+ ])),
17268
+ _: 1
17269
+ }),
17270
+ _cache[2] || (_cache[2] = createTextVNode(" Add content "))
17271
+ ]),
17272
+ _: 1
17273
+ })) : createCommentVNode("", true),
17274
+ _ctx.editMode === "full" ? (openBlock(), createBlock(_component_v_btn, {
17275
+ key: 1,
17276
+ color: "green-darken-2",
17277
+ title: "Rank course content for difficulty",
17278
+ class: "me-2"
17279
+ }, {
17280
+ default: withCtx(() => [
17281
+ createVNode(_component_v_icon, { start: "" }, {
17282
+ default: withCtx(() => _cache[3] || (_cache[3] = [
17283
+ createTextVNode("mdi-format-list-numbered")
17284
+ ])),
17285
+ _: 1
17286
+ }),
17287
+ _cache[4] || (_cache[4] = createTextVNode(" Arrange "))
17288
+ ]),
17289
+ _: 1
17290
+ })) : createCommentVNode("", true),
17291
+ _ctx.editMode === "full" ? (openBlock(), createBlock(_component_v_btn, {
17292
+ key: 2,
17293
+ color: "error",
17294
+ size: "small",
17295
+ variant: "outlined",
17296
+ onClick: _ctx.drop
17297
+ }, {
17298
+ default: withCtx(() => _cache[5] || (_cache[5] = [
17299
+ createTextVNode(" Drop this course ")
17300
+ ])),
17301
+ _: 1
17302
+ }, 8, ["onClick"])) : createCommentVNode("", true)
17303
+ ])) : (openBlock(), createElementBlock("div", _hoisted_5, [
17304
+ createVNode(_component_v_btn, {
17305
+ "data-cy": "register-btn",
17306
+ color: "primary",
17307
+ class: "me-2",
17308
+ onClick: _ctx.register
17309
+ }, {
17310
+ default: withCtx(() => _cache[6] || (_cache[6] = [
17311
+ createTextVNode("Register")
17312
+ ])),
17313
+ _: 1
17314
+ }, 8, ["onClick"]),
17315
+ createVNode(_component_v_btn, {
17316
+ variant: "outlined",
17317
+ color: "primary",
17318
+ class: "me-2"
17319
+ }, {
17320
+ default: withCtx(() => _cache[7] || (_cache[7] = [
17321
+ createTextVNode("Start a trial study session")
17322
+ ])),
17323
+ _: 1
17324
+ })
17325
+ ]))
17326
+ ]),
17327
+ _: 1
17328
+ })
17329
+ ], true),
17330
+ renderSlot(_ctx.$slots, "additional-content", {}, void 0, true),
17331
+ createVNode(_component_v_card, { class: "my-2" }, {
17332
+ default: withCtx(() => [
17333
+ createVNode(_component_v_toolbar, { density: "compact" }, {
17334
+ default: withCtx(() => [
17335
+ createVNode(_component_v_toolbar_title, null, {
17336
+ default: withCtx(() => _cache[8] || (_cache[8] = [
17337
+ createTextVNode("Tags")
17338
+ ])),
17339
+ _: 1
17340
+ }),
17341
+ createVNode(_component_v_toolbar_items, null, {
17342
+ default: withCtx(() => [
17343
+ createVNode(_component_v_btn, { variant: "text" }, {
17344
+ default: withCtx(() => [
17345
+ createTextVNode("(" + toDisplayString(_ctx.tags.length) + ")", 1)
17346
+ ]),
17347
+ _: 1
17348
+ })
17349
+ ]),
17350
+ _: 1
17351
+ })
17352
+ ]),
17353
+ _: 1
17354
+ }),
17355
+ createVNode(_component_v_card_text, null, {
17356
+ default: withCtx(() => [
17357
+ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.tags, (tag2, i) => {
17358
+ return openBlock(), createElementBlock("span", { key: i }, [
17359
+ renderSlot(_ctx.$slots, "tag-link", {
17360
+ tag: tag2,
17361
+ courseId: _ctx.courseId
17362
+ }, () => [
17363
+ createVNode(_component_v_chip, {
17364
+ variant: "tonal",
17365
+ class: "me-2 mb-2"
17366
+ }, {
17367
+ default: withCtx(() => [
17368
+ createTextVNode(toDisplayString(tag2.name), 1)
17369
+ ]),
17370
+ _: 2
17371
+ }, 1024)
17372
+ ], true)
17373
+ ]);
17374
+ }), 128))
17375
+ ]),
17376
+ _: 3
17377
+ })
17378
+ ]),
17379
+ _: 3
17380
+ }),
17381
+ createVNode(_component_course_card_browser, {
17382
+ class: "my-3",
17383
+ "course-id": _ctx.courseId,
17384
+ "view-lookup-function": _ctx.viewLookupFunction,
17385
+ "edit-mode": _ctx.editMode
17386
+ }, null, 8, ["course-id", "view-lookup-function", "edit-mode"])
17387
+ ])) : createCommentVNode("", true);
17388
+ }
17389
+ const CourseInformation = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1], ["__scopeId", "data-v-2d9f1cf6"]]);
17390
+ const _sfc_main = defineComponent({
17391
+ name: "CardBrowser",
17392
+ components: {
17393
+ CardViewer
17394
+ },
17395
+ props: {
17396
+ views: {
17397
+ type: Array,
17398
+ required: true
17399
+ },
17400
+ data: {
17401
+ type: Array,
17402
+ required: true
17403
+ },
17404
+ suppressSpinner: {
17405
+ type: Boolean,
17406
+ default: false
17407
+ }
17408
+ },
17409
+ data() {
17410
+ return {
17411
+ viewIndex: 0,
17412
+ previewMode: useCardPreviewModeStore()
17413
+ };
17414
+ },
17415
+ computed: {
17416
+ spinner() {
17417
+ return this.views.length > 1;
17418
+ }
17419
+ },
17420
+ created() {
17421
+ console.log(`[CardBrowser] Card browser created. Cards now in 'prewviewMode'`);
17422
+ this.previewMode.setPreviewMode(true);
17423
+ },
17424
+ unmounted() {
17425
+ console.log(`[CardBrowser] Card browser unmounted. Cards no longer in 'prewviewMode'`);
17426
+ this.previewMode.setPreviewMode(false);
17427
+ },
17428
+ methods: {
17429
+ incrementView() {
17430
+ this.viewIndex++;
17431
+ this.viewIndex = (this.viewIndex + this.views.length) % this.views.length;
17432
+ },
17433
+ decrementView() {
17434
+ this.viewIndex--;
17435
+ this.viewIndex = (this.viewIndex + this.views.length) % this.views.length;
17436
+ }
17437
+ }
17438
+ });
17439
+ const _hoisted_1 = {
17440
+ key: 0,
17441
+ class: "text-subtitle-1 pa-2"
17442
+ };
17443
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
17444
+ const _component_CardViewer = resolveComponent("CardViewer");
17445
+ const _component_v_icon = resolveComponent("v-icon");
17446
+ const _component_v_btn = resolveComponent("v-btn");
17447
+ const _component_v_row = resolveComponent("v-row");
17448
+ return openBlock(), createBlock(_component_v_row, {
17449
+ column: "",
17450
+ align: "center",
17451
+ justify: "center"
17452
+ }, {
17453
+ default: withCtx(() => [
17454
+ createVNode(_component_CardViewer, {
17455
+ view: _ctx.views[_ctx.viewIndex],
17456
+ data: _ctx.data,
17457
+ course_id: "[browsing]",
17458
+ card_id: "[browsing]"
17459
+ }, null, 8, ["view", "data"]),
17460
+ _cache[2] || (_cache[2] = createElementVNode("br", null, null, -1)),
17461
+ _cache[3] || (_cache[3] = createElementVNode("br", null, null, -1)),
17462
+ !_ctx.suppressSpinner ? (openBlock(), createElementBlock("div", _hoisted_1, [
17463
+ _ctx.spinner ? (openBlock(), createBlock(_component_v_btn, {
17464
+ key: 0,
17465
+ icon: "",
17466
+ variant: "outlined",
17467
+ color: "primary",
17468
+ onClick: _ctx.decrementView
17469
+ }, {
17470
+ default: withCtx(() => [
17471
+ createVNode(_component_v_icon, null, {
17472
+ default: withCtx(() => _cache[0] || (_cache[0] = [
17473
+ createTextVNode("mdi-chevron-left")
17474
+ ])),
17475
+ _: 1
17476
+ })
17477
+ ]),
17478
+ _: 1
17479
+ }, 8, ["onClick"])) : createCommentVNode("", true),
17480
+ createTextVNode(" " + toDisplayString(_ctx.views[_ctx.viewIndex].name) + " ", 1),
17481
+ _ctx.spinner ? (openBlock(), createBlock(_component_v_btn, {
17482
+ key: 1,
17483
+ icon: "",
17484
+ variant: "outlined",
17485
+ color: "primary",
17486
+ onClick: _ctx.incrementView
17487
+ }, {
17488
+ default: withCtx(() => [
17489
+ createVNode(_component_v_icon, null, {
17490
+ default: withCtx(() => _cache[1] || (_cache[1] = [
17491
+ createTextVNode("mdi-chevron-right")
17492
+ ])),
17493
+ _: 1
17494
+ })
17495
+ ]),
17496
+ _: 1
17497
+ }, 8, ["onClick"])) : createCommentVNode("", true)
17498
+ ])) : createCommentVNode("", true)
17499
+ ]),
17500
+ _: 1
17501
+ });
17502
+ }
17503
+ const CardBrowser = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
16345
17504
  export {
16346
17505
  AudioAutoPlayer,
17506
+ CardBrowser,
16347
17507
  CardLoader,
16348
17508
  CardViewer,
16349
- _sfc_main$6 as CodeBlockRenderer,
17509
+ _sfc_main$a as CodeBlockRenderer,
17510
+ CourseCardBrowser,
17511
+ CourseInformation,
16350
17512
  Displayable,
16351
17513
  FillInInput,
16352
17514
  HeatMap,
@@ -16363,6 +17525,7 @@ export {
16363
17525
  StudySession,
16364
17526
  StudySessionTimer,
16365
17527
  TrueFalse as TFSelect,
17528
+ TagsInput,
16366
17529
  UserChip,
16367
17530
  UserInputNumber,
16368
17531
  UserInputString,