@instructure/platform-modules 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +72 -0
  2. package/dist/analytics/context.d.ts +15 -0
  3. package/dist/analytics/context.d.ts.map +1 -0
  4. package/dist/analytics/index.d.ts +3 -0
  5. package/dist/analytics/index.d.ts.map +1 -0
  6. package/dist/analytics/types.d.ts +13 -0
  7. package/dist/analytics/types.d.ts.map +1 -0
  8. package/dist/components/FilterChips.d.ts +1 -1
  9. package/dist/components/FilterChips.d.ts.map +1 -1
  10. package/dist/components/ModuleCard.d.ts.map +1 -1
  11. package/dist/components/ModuleItemRow.d.ts.map +1 -1
  12. package/dist/components/ModulesList.d.ts +7 -1
  13. package/dist/components/ModulesList.d.ts.map +1 -1
  14. package/dist/config/index.d.ts +1 -0
  15. package/dist/config/index.d.ts.map +1 -1
  16. package/dist/config/organizePreview.d.ts +8 -0
  17. package/dist/config/organizePreview.d.ts.map +1 -0
  18. package/dist/i18n.d.ts +6 -0
  19. package/dist/i18n.d.ts.map +1 -1
  20. package/dist/index.d.ts +4 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2137 -1546
  23. package/dist/organize/Organize.stories.d.ts +33 -0
  24. package/dist/organize/Organize.stories.d.ts.map +1 -0
  25. package/dist/organize/OrganizeForm.d.ts +11 -0
  26. package/dist/organize/OrganizeForm.d.ts.map +1 -0
  27. package/dist/organize/OrganizeModulesButton.d.ts +10 -0
  28. package/dist/organize/OrganizeModulesButton.d.ts.map +1 -0
  29. package/dist/organize/OrganizeModulesModal.d.ts +12 -0
  30. package/dist/organize/OrganizeModulesModal.d.ts.map +1 -0
  31. package/dist/organize/ProposalPreview.d.ts +7 -0
  32. package/dist/organize/ProposalPreview.d.ts.map +1 -0
  33. package/dist/organize/fixture.d.ts +5 -0
  34. package/dist/organize/fixture.d.ts.map +1 -0
  35. package/dist/organize/index.d.ts +9 -0
  36. package/dist/organize/index.d.ts.map +1 -0
  37. package/dist/organize/types.d.ts +64 -0
  38. package/dist/organize/types.d.ts.map +1 -0
  39. package/dist/organize/useOrganizeModules.d.ts +30 -0
  40. package/dist/organize/useOrganizeModules.d.ts.map +1 -0
  41. package/dist/organize/validation.d.ts +8 -0
  42. package/dist/organize/validation.d.ts.map +1 -0
  43. package/dist/types/extensions.d.ts +7 -1
  44. package/dist/types/extensions.d.ts.map +1 -1
  45. package/dist/types/index.d.ts +1 -1
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/locales/en.json +48 -3
  48. package/package.json +12 -2
@@ -0,0 +1,33 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import { ThemeName } from '../components/storyThemes';
3
+ type Surface = 'button' | 'list' | 'form' | 'preview';
4
+ type Outcome = 'proposal' | 'unplaced' | 'warnings' | 'failure';
5
+ type ApplyOutcome = 'success' | 'failure';
6
+ type FormState = 'default' | 'invalid' | 'disabled';
7
+ type ProposalShape = 'small' | 'rich';
8
+ interface OrganizeStoryArgs {
9
+ surface: Surface;
10
+ outcome: Outcome;
11
+ proposalShape: ProposalShape;
12
+ organizeMs: number;
13
+ applyMs: number;
14
+ applyOutcome: ApplyOutcome;
15
+ formState: FormState;
16
+ theme: ThemeName;
17
+ }
18
+ declare const meta: Meta<OrganizeStoryArgs>;
19
+ export default meta;
20
+ type Story = StoryObj<typeof meta>;
21
+ export declare const Trigger: Story;
22
+ export declare const InModulesList: Story;
23
+ export declare const Form: Story;
24
+ export declare const FormWithErrors: Story;
25
+ export declare const FormDisabledWhileApplying: Story;
26
+ export declare const Preview: Story;
27
+ export declare const PreviewWithUnplacedItems: Story;
28
+ export declare const PreviewWithWarnings: Story;
29
+ /** Submit to watch the wait cross `ORGANIZE_SLOW_AFTER_MS` (10s) and add its second line. */
30
+ export declare const SlowGeneration: Story;
31
+ export declare const GenerationFailure: Story;
32
+ export declare const ApplyFailure: Story;
33
+ //# sourceMappingURL=Organize.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Organize.stories.d.ts","sourceRoot":"","sources":["../../src/organize/Organize.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAUtD,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAA;AAYlC,KAAK,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;AACrD,KAAK,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;AAC/D,KAAK,YAAY,GAAG,SAAS,GAAG,SAAS,CAAA;AACzC,KAAK,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;AACnD,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;AAErC,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,aAAa,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,YAAY,CAAA;IAC1B,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;CACjB;AA4JD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,iBAAiB,CA0BjC,CAAA;AAED,eAAe,IAAI,CAAA;AACnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAA;AAElC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAA;AAEhC,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,KAElB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED,eAAO,MAAM,yBAAyB,EAAE,KAEvC,CAAA;AAED,eAAO,MAAM,OAAO,EAAE,KAErB,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,KAEtC,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,KAEjC,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { ReactElement } from 'react';
2
+ import { OrganizeInputErrors } from './validation';
3
+ import { OrganizeInput } from './types';
4
+ export interface OrganizeFormProps {
5
+ input: OrganizeInput;
6
+ errors: OrganizeInputErrors;
7
+ onChange: (patch: Partial<OrganizeInput>) => void;
8
+ disabled?: boolean;
9
+ }
10
+ export declare function OrganizeForm({ input, errors, onChange, disabled, }: OrganizeFormProps): ReactElement;
11
+ //# sourceMappingURL=OrganizeForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrganizeForm.d.ts","sourceRoot":"","sources":["../../src/organize/OrganizeForm.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAA;IACpB,MAAM,EAAE,mBAAmB,CAAA;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAmBD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,QAAgB,GACjB,EAAE,iBAAiB,GAAG,YAAY,CA2GlC"}
@@ -0,0 +1,10 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { ModuleOrganizationActions } from './types';
3
+ export interface OrganizeModulesButtonProps {
4
+ actions: ModuleOrganizationActions;
5
+ onApplied?: () => void;
6
+ aiDisclosure?: ReactNode;
7
+ display?: 'block' | 'inline-block';
8
+ }
9
+ export declare function OrganizeModulesButton({ actions, onApplied, aiDisclosure, display, }: OrganizeModulesButtonProps): ReactElement;
10
+ //# sourceMappingURL=OrganizeModulesButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrganizeModulesButton.d.ts","sourceRoot":"","sources":["../../src/organize/OrganizeModulesButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAA;AAGnE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAExD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,yBAAyB,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB,OAAO,CAAC,EAAE,OAAO,GAAG,cAAc,CAAA;CACnC;AAED,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,SAAS,EACT,YAAY,EACZ,OAAwB,GACzB,EAAE,0BAA0B,GAAG,YAAY,CA2B3C"}
@@ -0,0 +1,12 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { ModuleOrganizationActions } from './types';
3
+ export interface OrganizeModulesModalProps {
4
+ actions: ModuleOrganizationActions;
5
+ open: boolean;
6
+ onDismiss: () => void;
7
+ onApplied?: () => void;
8
+ /** The host's AI disclosure, drawn in the header. Its content is host policy, not ours. */
9
+ aiDisclosure?: ReactNode;
10
+ }
11
+ export declare function OrganizeModulesModal({ actions, open, onDismiss, onApplied, aiDisclosure, }: OrganizeModulesModalProps): ReactElement;
12
+ //# sourceMappingURL=OrganizeModulesModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrganizeModulesModal.d.ts","sourceRoot":"","sources":["../../src/organize/OrganizeModulesModal.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAA;AAI5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAGxD,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,yBAAyB,CAAA;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,2FAA2F;IAC3F,YAAY,CAAC,EAAE,SAAS,CAAA;CACzB;AAqBD,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,YAAY,GACb,EAAE,yBAAyB,GAAG,YAAY,CA0K1C"}
@@ -0,0 +1,7 @@
1
+ import { ReactElement } from 'react';
2
+ import { OrganizeProposal } from './types';
3
+ export interface ProposalPreviewProps {
4
+ proposal: OrganizeProposal;
5
+ }
6
+ export declare function ProposalPreview({ proposal }: ProposalPreviewProps): ReactElement;
7
+ //# sourceMappingURL=ProposalPreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProposalPreview.d.ts","sourceRoot":"","sources":["../../src/organize/ProposalPreview.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,OAAO,CAAA;AAO5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAa/C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,gBAAgB,CAAA;CAC3B;AAkBD,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,YAAY,CAsDhF"}
@@ -0,0 +1,5 @@
1
+ import { InMemoryFixture } from '../adapters';
2
+ import { OrganizeProposal } from './types';
3
+ export declare const PROPOSAL_PREVIEW_COURSE_ID = "organize-preview";
4
+ export declare function proposalToFixture(proposal: OrganizeProposal): InMemoryFixture;
5
+ //# sourceMappingURL=fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/organize/fixture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAOlD,OAAO,KAAK,EAAE,gBAAgB,EAAgC,MAAM,SAAS,CAAA;AAE7E,eAAO,MAAM,0BAA0B,qBAAqB,CAAA;AA+D5D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,eAAe,CAgC7E"}
@@ -0,0 +1,9 @@
1
+ export { hasOrganizeInputErrors, type OrganizeInputErrors, validateOrganizeInput, } from './validation';
2
+ export { PROPOSAL_PREVIEW_COURSE_ID, proposalToFixture } from './fixture';
3
+ export { OrganizeForm, type OrganizeFormProps } from './OrganizeForm';
4
+ export { OrganizeModulesButton, type OrganizeModulesButtonProps } from './OrganizeModulesButton';
5
+ export { OrganizeModulesModal, type OrganizeModulesModalProps } from './OrganizeModulesModal';
6
+ export { ProposalPreview, type ProposalPreviewProps } from './ProposalPreview';
7
+ export { defaultOrganizeInput, MAX_DIRECTION_CHARS, type ModuleOrganizationActions, ORGANIZE_CONTENT_TYPES, ORGANIZE_MODES, type OrganizeContentType, type OrganizeInput, type OrganizeMode, type OrganizeProposal, type ProposedCompletionRequirement, type ProposedItem, type ProposedModule, type UnplacedItem, } from './types';
8
+ export { ORGANIZE_SLOW_AFTER_MS, type OrganizeStatus, useOrganizeModules, type UseOrganizeModulesOptions, type UseOrganizeModulesResult, } from './useOrganizeModules';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/organize/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAAE,qBAAqB,EAAE,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AAChG,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAC7F,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC9E,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,yBAAyB,EAC9B,sBAAsB,EACtB,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAClC,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,sBAAsB,EACtB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,GAC9B,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { CompletionRequirementType } from '../types';
2
+ export declare const ORGANIZE_MODES: readonly ["place_new", "reorganize_all"];
3
+ export type OrganizeMode = (typeof ORGANIZE_MODES)[number];
4
+ export declare const ORGANIZE_CONTENT_TYPES: readonly ["assignment", "discussion", "quiz", "page", "file"];
5
+ export type OrganizeContentType = (typeof ORGANIZE_CONTENT_TYPES)[number];
6
+ export declare const MAX_DIRECTION_CHARS = 1000;
7
+ export interface OrganizeInput {
8
+ mode: OrganizeMode;
9
+ contentTypes: readonly OrganizeContentType[];
10
+ /**
11
+ * Whether to *propose* prerequisites and per-item requirements. Canvas honours both at
12
+ * generation time only: apply writes whatever the proposal carries. Unchecked therefore means
13
+ * "propose none", not "propose them and leave them out of the course".
14
+ */
15
+ setPrerequisites: boolean;
16
+ setRequirements: boolean;
17
+ direction: string;
18
+ }
19
+ export interface ProposedCompletionRequirement {
20
+ type: CompletionRequirementType;
21
+ minScore?: number | null;
22
+ }
23
+ export interface ProposedItem {
24
+ contentType: OrganizeContentType;
25
+ contentId: string;
26
+ title: string;
27
+ /** False when the item already sits in the module the proposal put it in. */
28
+ isNew: boolean;
29
+ completionRequirement?: ProposedCompletionRequirement | null;
30
+ }
31
+ export interface ProposedModule {
32
+ /** 1-based, and the only handle a prerequisite has. Not an array index. */
33
+ position: number;
34
+ name: string;
35
+ isNew: boolean;
36
+ existingModuleId?: string | null;
37
+ rationale?: string;
38
+ prerequisitePositions: readonly number[];
39
+ requirementType?: 'all' | 'one';
40
+ items: readonly ProposedItem[];
41
+ }
42
+ export interface UnplacedItem {
43
+ contentType: OrganizeContentType;
44
+ contentId: string;
45
+ title: string;
46
+ }
47
+ export interface OrganizeProposal {
48
+ modules: readonly ProposedModule[];
49
+ unplacedItems: readonly UnplacedItem[];
50
+ /** Already in the reader's language. The package renders them, it does not interpret them. */
51
+ warnings: readonly string[];
52
+ /** Opaque to this package: a host's handle on the generation call, for its own telemetry. */
53
+ responseId?: string | null;
54
+ }
55
+ /**
56
+ * The host's transport, injected the way `executeQuery` is. `organize` owns whatever polling,
57
+ * retry or job plumbing its backend needs and resolves only once the proposal is final.
58
+ */
59
+ export interface ModuleOrganizationActions {
60
+ organize(input: OrganizeInput, signal?: AbortSignal): Promise<OrganizeProposal>;
61
+ apply(proposal: OrganizeProposal, input: OrganizeInput, signal?: AbortSignal): Promise<void>;
62
+ }
63
+ export declare const defaultOrganizeInput: () => OrganizeInput;
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/organize/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAEzD,eAAO,MAAM,cAAc,0CAA2C,CAAA;AAEtE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1D,eAAO,MAAM,sBAAsB,+DAAgE,CAAA;AAEnG,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzE,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAA;IAC5C;;;;OAIG;IACH,gBAAgB,EAAE,OAAO,CAAA;IACzB,eAAe,EAAE,OAAO,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,yBAAyB,CAAA;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,mBAAmB,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,6EAA6E;IAC7E,KAAK,EAAE,OAAO,CAAA;IACd,qBAAqB,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,eAAe,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;IAC/B,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,mBAAmB,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;IAClC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,8FAA8F;IAC9F,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC/E,KAAK,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7F;AAED,eAAO,MAAM,oBAAoB,QAAO,aAMtC,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { OrganizeInputErrors } from './validation';
2
+ import { ModuleOrganizationActions, OrganizeInput, OrganizeProposal } from './types';
3
+ /**
4
+ * How long the teacher waits before the wait itself is worth saying out loud. Long enough that a
5
+ * fast generation never flashes the line, short enough to land before a spinner reads as hung.
6
+ */
7
+ export declare const ORGANIZE_SLOW_AFTER_MS = 10000;
8
+ export type OrganizeStatus = 'form' | 'loading' | 'preview' | 'applying' | 'error';
9
+ export interface UseOrganizeModulesOptions {
10
+ actions: ModuleOrganizationActions;
11
+ onApplied?: () => void;
12
+ }
13
+ export interface UseOrganizeModulesResult {
14
+ status: OrganizeStatus;
15
+ input: OrganizeInput;
16
+ setInput: (patch: Partial<OrganizeInput>) => void;
17
+ errors: OrganizeInputErrors;
18
+ canSubmit: boolean;
19
+ proposal: OrganizeProposal | null;
20
+ error: Error | null;
21
+ /** The request has outlived `ORGANIZE_SLOW_AFTER_MS` and is still running. */
22
+ takingLong: boolean;
23
+ submit: () => void;
24
+ regenerate: () => void;
25
+ apply: () => void;
26
+ /** Abandons whatever is in flight and returns to the form, keeping what was typed. */
27
+ cancel: () => void;
28
+ }
29
+ export declare function useOrganizeModules({ actions, onApplied, }: UseOrganizeModulesOptions): UseOrganizeModulesResult;
30
+ //# sourceMappingURL=useOrganizeModules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOrganizeModules.d.ts","sourceRoot":"","sources":["../../src/organize/useOrganizeModules.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,SAAS,CAAA;AAEhB;;;GAGG;AACH,eAAO,MAAM,sBAAsB,QAAS,CAAA;AAE5C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAA;AAElF,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,yBAAyB,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,aAAa,CAAA;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IACjD,MAAM,EAAE,mBAAmB,CAAA;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAA;IACjC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAA;IACnB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,sFAAsF;IACtF,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AA8BD,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,SAAS,GACV,EAAE,yBAAyB,GAAG,wBAAwB,CA0GtD"}
@@ -0,0 +1,8 @@
1
+ import { OrganizeInput } from './types';
2
+ export interface OrganizeInputErrors {
3
+ contentTypes?: 'none_selected';
4
+ direction?: 'too_long';
5
+ }
6
+ export declare function validateOrganizeInput(input: OrganizeInput): OrganizeInputErrors;
7
+ export declare const hasOrganizeInputErrors: (errors: OrganizeInputErrors) => boolean;
8
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/organize/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,SAAS,CAAA;AAEjE,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,eAAe,CAAA;IAC9B,SAAS,CAAC,EAAE,UAAU,CAAA;CACvB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,mBAAmB,CAO/E;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,mBAAmB,KAAG,OACrC,CAAA"}
@@ -1,5 +1,11 @@
1
- import { ModuleItem } from './domain';
1
+ import { Module, ModuleItem } from './domain';
2
2
  export declare const EXT_CAREER_ESTIMATED_DURATION_MINUTES = "career.estimatedDurationMinutes";
3
3
  export declare function getEstimatedDurationMinutes(item: Pick<ModuleItem, 'extensions'>): number | null;
4
4
  export declare function withEstimatedDurationMinutes(extensions: Record<string, unknown> | undefined, minutes: number | null | undefined): Record<string, unknown> | undefined;
5
+ export declare const EXT_ORGANIZE_NEW_PLACEMENT = "organize.newPlacement";
6
+ export declare const EXT_ORGANIZE_NEW_MODULE = "organize.newModule";
7
+ export declare const EXT_ORGANIZE_ADDED_ITEM_COUNT = "organize.addedItemCount";
8
+ export declare function isNewPlacement(item: Pick<ModuleItem, 'extensions'>): boolean;
9
+ export declare function isProposedNewModule(module: Pick<Module, 'extensions'>): boolean;
10
+ export declare function getAddedItemCount(module: Pick<Module, 'extensions'>): number;
5
11
  //# sourceMappingURL=extensions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/types/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,eAAO,MAAM,qCAAqC,oCAAoC,CAAA;AAEtF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,GAAG,IAAI,CAI/F;AAED,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC/C,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGrC"}
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/types/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAElD,eAAO,MAAM,qCAAqC,oCAAoC,CAAA;AAEtF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,MAAM,GAAG,IAAI,CAI/F;AAED,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC/C,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAGrC;AAED,eAAO,MAAM,0BAA0B,0BAA0B,CAAA;AAEjE,eAAO,MAAM,uBAAuB,uBAAuB,CAAA;AAE3D,eAAO,MAAM,6BAA6B,4BAA4B,CAAA;AAEtE,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,GAAG,OAAO,CAE5E;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,OAAO,CAE/E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,CAI5E"}
@@ -1,5 +1,5 @@
1
1
  export type { ModuleItemStatus, ModuleProgress, ModuleStatus, CompletionRequirement, CompletionRequirementType, Module, ModuleItem, ModuleItemsPage, ModuleItemType, ModulesPage, PageInfo, PrerequisiteModule, } from './domain';
2
2
  export { type FilterCapabilities, type FilterClause, FilterClauseSchema, type FilterTarget, servesClause, type TargetCapabilities, } from './filterClause';
3
3
  export { CompletionRequirementSchema, CompletionRequirementTypeSchema, ModuleItemStatusSchema, ModuleProgressSchema, ModuleStatusSchema, ModuleItemSchema, ModuleItemsPageSchema, ModuleItemTypeSchema, ModuleSchema, ModulesPageSchema, PageInfoSchema, PrerequisiteModuleSchema, } from './schemas';
4
- export { EXT_CAREER_ESTIMATED_DURATION_MINUTES, getEstimatedDurationMinutes, withEstimatedDurationMinutes, } from './extensions';
4
+ export { EXT_CAREER_ESTIMATED_DURATION_MINUTES, EXT_ORGANIZE_ADDED_ITEM_COUNT, EXT_ORGANIZE_NEW_MODULE, EXT_ORGANIZE_NEW_PLACEMENT, getAddedItemCount, getEstimatedDurationMinutes, isNewPlacement, isProposedNewModule, withEstimatedDurationMinutes, } from './extensions';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,EACzB,MAAM,EACN,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,QAAQ,EACR,kBAAkB,GACnB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,YAAY,EACjB,YAAY,EACZ,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,wBAAwB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,qCAAqC,EACrC,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,EACzB,MAAM,EACN,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,QAAQ,EACR,kBAAkB,GACnB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,kBAAkB,EAClB,KAAK,YAAY,EACjB,YAAY,EACZ,KAAK,kBAAkB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,wBAAwB,GACzB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,qCAAqC,EACrC,6BAA6B,EAC7B,uBAAuB,EACvB,0BAA0B,EAC1B,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,cAAc,CAAA"}
package/locales/en.json CHANGED
@@ -24,7 +24,7 @@
24
24
  "modulesLoadingSpinnerLabel": "Loading modules",
25
25
  "noModulesEmptyState": "This course has no modules.",
26
26
  "filteredEmptyState": {
27
- "one": "The only loaded module does not match this filter.",
27
+ "one": "%{count} loaded module does not match this filter.",
28
28
  "other": "None of the %{count} loaded modules match this filter."
29
29
  },
30
30
  "noFilterMatches": "No modules match this filter.",
@@ -32,7 +32,7 @@
32
32
  "loadMoreModulesLoading": "Loading more modules…",
33
33
  "loadMoreModules": "Load more modules (%{count} loaded)",
34
34
  "allModulesLoaded": {
35
- "one": "The only module in this course is loaded.",
35
+ "one": "%{count} module in this course is loaded.",
36
36
  "other": "All %{count} modules in this course are loaded."
37
37
  },
38
38
  "filterGroupLabel": "Filter",
@@ -134,5 +134,50 @@
134
134
  "durationMinutes": "%{count} min",
135
135
  "itemUnpublishedLabel": "Unpublished",
136
136
  "itemUntitled": "Untitled item",
137
- "opensInNewWindow": "opens in a new window"
137
+ "opensInNewWindow": "opens in a new window",
138
+ "organizeModulesTrigger": "Organize with AI",
139
+ "organizeModalLabel": "Organize content into modules",
140
+ "organizeProgressionLegend": "Module progression",
141
+ "organizeSetPrerequisites": "Set module prerequisites",
142
+ "organizeSetRequirements": "Set item requirements per module",
143
+ "organizeCloseModal": "Close",
144
+ "organizeModeLegend": "What should this do?",
145
+ "organizeModePlaceNew": "Place new content only",
146
+ "organizeModeReorganizeAll": "Reorganize the whole course",
147
+ "organizeReorganizeWarning": "This rebuilds every module in the course. Existing modules can be renamed, refilled, or removed.",
148
+ "organizeContentTypesLegend": "Content to organize",
149
+ "organizeDirectionLabel": "Anything else it should know? (optional)",
150
+ "organizeDirectionPlaceholder": "For example: keep the lab work together and put it last.",
151
+ "organizeDirectionCount": "%{used}/%{max}",
152
+ "organizeErrorPickAContentType": "Choose at least one kind of content.",
153
+ "organizeSubmit": "Organize",
154
+ "organizeCancel": "Cancel",
155
+ "organizeStartOver": "Start over",
156
+ "organizeRegenerate": "Regenerate",
157
+ "organizeApply": "Apply",
158
+ "organizeTryAgain": "Try again",
159
+ "organizeLoadingLabel": "Organizing your content\u2026",
160
+ "organizeApplyingLabel": "Creating your modules\u2026",
161
+ "organizeStillWorking": "Still working. Large courses take longer.",
162
+ "organizeProposalReadyAnnouncement": "Your proposal is ready to review.",
163
+ "organizeAppliedAnnouncement": "Your modules were created.",
164
+ "organizeFailed": "Your content could not be organized: %{message}",
165
+ "organizeApplyFailed": "Your modules could not be created: %{message}",
166
+ "organizePreviewHeading": "Proposed modules",
167
+ "organizeNewModuleLabel": "New module",
168
+ "organizeItemsAddedLabel": {
169
+ "one": "%{count} item added",
170
+ "other": "%{count} items added"
171
+ },
172
+ "organizeNewItemPill": "New",
173
+ "metaFieldNewPlacementLabel": "New placement",
174
+ "organizeUnplacedHeading": {
175
+ "one": "%{count} item was not placed",
176
+ "other": "%{count} items were not placed"
177
+ },
178
+ "organizeUnplacedExplanation": "You can still apply this. Anything left out stays where it is.",
179
+ "organizeWarningsHeading": {
180
+ "one": "%{count} thing to know",
181
+ "other": "%{count} things to know"
182
+ }
138
183
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/platform-modules",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -21,17 +21,22 @@
21
21
  "@instructure/ui-a11y-content": "^11.0.0",
22
22
  "@instructure/ui-alerts": "^11.7.0",
23
23
  "@instructure/ui-buttons": "^11.7.0",
24
+ "@instructure/ui-checkbox": "^11.7.0",
24
25
  "@instructure/ui-color-utils": "^11.7.0",
25
26
  "@instructure/ui-flex": "^11.7.0",
26
27
  "@instructure/ui-heading": "^11.7.0",
27
28
  "@instructure/ui-icons": "^11.7.0",
28
29
  "@instructure/ui-link": "^11.7.0",
30
+ "@instructure/ui-list": "^11.7.0",
29
31
  "@instructure/ui-menu": "^11.7.0",
32
+ "@instructure/ui-modal": "^11.7.0",
30
33
  "@instructure/ui-pill": "^11.7.0",
31
34
  "@instructure/ui-progress": "^11.7.0",
35
+ "@instructure/ui-radio-input": "^11.7.0",
32
36
  "@instructure/ui-responsive": "^11.0.0",
33
37
  "@instructure/ui-spinner": "^11.7.0",
34
38
  "@instructure/ui-text": "^11.7.0",
39
+ "@instructure/ui-text-area": "^11.7.0",
35
40
  "@instructure/ui-text-input": "^11.7.0",
36
41
  "@instructure/ui-tooltip": "^11.7.0",
37
42
  "@instructure/ui-view": "^11.7.0",
@@ -44,7 +49,7 @@
44
49
  "dependencies": {
45
50
  "graphql-tag": "^2.12.6",
46
51
  "p-limit": "^6.1.0",
47
- "@instructure/platform-instui-bindings": "0.6.4",
52
+ "@instructure/platform-instui-bindings": "0.6.5",
48
53
  "@instructure/platform-with-breakpoints": "0.3.0"
49
54
  },
50
55
  "devDependencies": {
@@ -52,17 +57,22 @@
52
57
  "@instructure/ui-a11y-content": "11.7.4",
53
58
  "@instructure/ui-alerts": "11.7.4",
54
59
  "@instructure/ui-buttons": "11.7.4",
60
+ "@instructure/ui-checkbox": "11.7.4",
55
61
  "@instructure/ui-color-utils": "11.7.4",
56
62
  "@instructure/ui-flex": "11.7.4",
57
63
  "@instructure/ui-heading": "11.7.4",
58
64
  "@instructure/ui-icons": "11.7.4",
59
65
  "@instructure/ui-link": "11.7.4",
66
+ "@instructure/ui-list": "11.7.4",
60
67
  "@instructure/ui-menu": "11.7.4",
68
+ "@instructure/ui-modal": "11.7.4",
61
69
  "@instructure/ui-pill": "11.7.4",
62
70
  "@instructure/ui-progress": "11.7.4",
71
+ "@instructure/ui-radio-input": "11.7.4",
63
72
  "@instructure/ui-responsive": "11.7.4",
64
73
  "@instructure/ui-spinner": "11.7.4",
65
74
  "@instructure/ui-text": "11.7.4",
75
+ "@instructure/ui-text-area": "11.7.4",
66
76
  "@instructure/ui-text-input": "11.7.4",
67
77
  "@instructure/ui-themes": "11.7.4",
68
78
  "@instructure/ui-tooltip": "11.7.4",