@fayz-ai/plugin-courses 0.8.0 → 0.8.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.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,14 @@ export interface CoursesPluginOptions {
3
3
  navPosition?: number;
4
4
  navSection?: 'main' | 'secondary' | 'settings';
5
5
  navLabel?: string;
6
+ /** Nav labels for the module entries (default English). */
7
+ labels?: {
8
+ membersArea?: string;
9
+ sales?: string;
10
+ subscriptions?: string;
11
+ financial?: string;
12
+ reports?: string;
13
+ };
6
14
  scope?: PluginScope;
7
15
  verticalId?: VerticalId;
8
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AA8B5E,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;CACF;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,cAAc,CAuElF;AAOD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AA8B5E,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2DAA2D;IAC3D,MAAM,CAAC,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;CACF;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,cAAc,CA2ElF;AAOD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { hashRouterAdapter, registerPluginFactory, registerTranslations, useTranslation } from '@fayz-ai/core';
2
2
  import { setCoursesTenantResolver, getCoursesProviderOptional, setCoursesProvider, createMockCoursesProvider, getCoursesProvider } from '@fayz-ai/courses';
3
- import { useOrganizationStore, PluginSettingsPanel, SettingsGroup, SelectRow, ToggleRow } from '@fayz-ai/saas';
3
+ import { useOrganizationStore, useLimitGuard, usePermissionOptional, PermissionGate, invalidateLimit, PluginSettingsPanel, SettingsGroup, SelectRow, ToggleRow } from '@fayz-ai/saas';
4
4
  import * as React2 from 'react';
5
5
  import { defineKpiWidget, useModuleLayout, PageHeaderActions, Button, Badge, Input, KpiCard, DataTable, Card, toast } from '@fayz-ai/ui';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -314,6 +314,8 @@ function CoursesListPage() {
314
314
  const shellOwnsHeader = useModuleLayout() === "tabs";
315
315
  const [courses, setCourses] = React2.useState(null);
316
316
  const [creating, setCreating] = React2.useState(false);
317
+ const guardCourses = useLimitGuard("courses");
318
+ const can = usePermissionOptional();
317
319
  const load = React2.useCallback(async () => {
318
320
  setCourses(await getCoursesProvider().listCourses());
319
321
  }, []);
@@ -321,24 +323,27 @@ function CoursesListPage() {
321
323
  void load();
322
324
  }, [load]);
323
325
  async function onCreate() {
326
+ if (!can("courses", "create")) return;
327
+ if (await guardCourses() === "blocked") return;
324
328
  setCreating(true);
325
329
  try {
326
330
  const course = await getCoursesProvider().createCourse({
327
331
  title: t("courses.editor.untitledCourse") || "Untitled course",
328
332
  status: "draft"
329
333
  });
334
+ invalidateLimit("courses");
330
335
  navigateTo(`/courses/${course.id}`);
331
336
  } finally {
332
337
  setCreating(false);
333
338
  }
334
339
  }
335
340
  return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-6xl p-6 md:p-8", children: [
336
- shellOwnsHeader ? /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsx(Button, { onClick: onCreate, disabled: creating, children: t("courses.new") || "New course" }) }) : /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center justify-between", children: [
341
+ shellOwnsHeader ? /* @__PURE__ */ jsx(PageHeaderActions, { children: /* @__PURE__ */ jsx(PermissionGate, { feature: "courses", action: "create", children: /* @__PURE__ */ jsx(Button, { onClick: onCreate, disabled: creating, children: t("courses.new") || "New course" }) }) }) : /* @__PURE__ */ jsxs("div", { className: "mb-6 flex items-center justify-between", children: [
337
342
  /* @__PURE__ */ jsxs("div", { children: [
338
343
  /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: t("courses.title") || "Courses" }),
339
344
  courses && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: (t("courses.count") || "{count} courses").replace("{count}", String(courses.length)) })
340
345
  ] }),
341
- /* @__PURE__ */ jsx(Button, { onClick: onCreate, disabled: creating, children: t("courses.new") || "New course" })
346
+ /* @__PURE__ */ jsx(PermissionGate, { feature: "courses", action: "create", children: /* @__PURE__ */ jsx(Button, { onClick: onCreate, disabled: creating, children: t("courses.new") || "New course" }) })
342
347
  ] }),
343
348
  courses && courses.length === 0 && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-dashed border-border p-12 text-center text-muted-foreground", children: t("courses.empty") || "No courses yet. Create your first one." }),
344
349
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: courses?.map((course) => /* @__PURE__ */ jsxs(
@@ -1000,13 +1005,14 @@ function createCoursesPlugin(options) {
1000
1005
  const base = options?.navPosition ?? 1;
1001
1006
  const section = options?.navSection ?? "main";
1002
1007
  const modules = options?.modules ?? {};
1008
+ const labels = options?.labels ?? {};
1003
1009
  const navigation = [
1004
1010
  { section, position: base, label: options?.navLabel ?? "Courses", route: "/courses", icon: "BookOpen", permission: read("courses") },
1005
- ...modules.membersArea ? [{ section, position: base + 1, label: "Members area", route: "/courses/members", icon: "GraduationCap", permission: read("courses") }] : [],
1006
- ...modules.sales ? [{ section, position: base + 2, label: "Sales", route: "/courses/sales", icon: "TrendingUp", permission: read("courses.sales") }] : [],
1007
- ...modules.subscriptions ? [{ section, position: base + 3, label: "Subscriptions", route: "/courses/subscriptions", icon: "Repeat", permission: read("courses.sales") }] : [],
1008
- ...modules.financial ? [{ section, position: base + 4, label: "Financial", route: "/courses/financial", icon: "CreditCard", permission: read("courses.finance") }] : [],
1009
- ...modules.reports ? [{ section, position: base + 5, label: "Reports", route: "/courses/reports", icon: "BarChart3", permission: read("courses.sales") }] : []
1011
+ ...modules.membersArea ? [{ section, position: base + 1, label: labels.membersArea ?? "Members area", route: "/courses/members", icon: "GraduationCap", permission: read("courses") }] : [],
1012
+ ...modules.sales ? [{ section, position: base + 2, label: labels.sales ?? "Sales", route: "/courses/sales", icon: "TrendingUp", permission: read("courses.sales") }] : [],
1013
+ ...modules.subscriptions ? [{ section, position: base + 3, label: labels.subscriptions ?? "Subscriptions", route: "/courses/subscriptions", icon: "Repeat", permission: read("courses.sales") }] : [],
1014
+ ...modules.financial ? [{ section, position: base + 4, label: labels.financial ?? "Financial", route: "/courses/financial", icon: "CreditCard", permission: read("courses.finance") }] : [],
1015
+ ...modules.reports ? [{ section, position: base + 5, label: labels.reports ?? "Reports", route: "/courses/reports", icon: "BarChart3", permission: read("courses.sales") }] : []
1010
1016
  ];
1011
1017
  const routes = [
1012
1018
  // Static segments outscore the `:id` param in the saas router, so these
@@ -1037,6 +1043,9 @@ function createCoursesPlugin(options) {
1037
1043
  { id: "courses.sales", label: "Sales", group: "Courses" },
1038
1044
  { id: "courses.finance", label: "Financial", group: "Courses" }
1039
1045
  ],
1046
+ declaredLimits: [
1047
+ { key: "courses", label: "Courses", table: "plg_courses_courses" }
1048
+ ],
1040
1049
  navigation,
1041
1050
  routes,
1042
1051
  widgets: [],