rowvia 0.3.0 → 0.3.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/rowvia.css +1 -1
- package/dist/rowvia.es.js +6237 -5318
- package/dist/rowvia.umd.cjs +59 -49
- package/dist/types/contracts/work-item.d.ts +6 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/work-items/detail/detail-comments.d.ts +44 -0
- package/dist/types/work-items/detail/detail-history.d.ts +38 -0
- package/dist/types/work-items/detail/history-model.d.ts +48 -0
- package/dist/types/work-items/index.d.ts +8 -0
- package/dist/types/work-items/workflow-detail-model.d.ts +51 -0
- package/dist/types/work-items/workflow-detail-types.d.ts +95 -0
- package/dist/types/work-items/workflow-detail.d.ts +3 -0
- package/package.json +1 -1
|
@@ -198,12 +198,16 @@ export interface FormPlacement {
|
|
|
198
198
|
export interface FormGroupConfig {
|
|
199
199
|
id: string;
|
|
200
200
|
label: string;
|
|
201
|
-
items:
|
|
201
|
+
items: FormLayoutItem[];
|
|
202
|
+
columns?: 1 | 2;
|
|
203
|
+
columnRatio?: [number, number];
|
|
204
|
+
span?: 1 | 2;
|
|
202
205
|
visibleWhen?: FormCondition;
|
|
203
206
|
}
|
|
204
|
-
export type FormLayoutItem = FormPlacement | FormGroupConfig;
|
|
207
|
+
export type FormLayoutItem = FormPlacement | FormGroupConfig | FormBlockConfig;
|
|
205
208
|
export interface FormBlockConfig {
|
|
206
209
|
id: string;
|
|
210
|
+
span?: 1 | 2;
|
|
207
211
|
kind: 'roles' | 'meetings' | 'approval' | 'votes' | 'custom';
|
|
208
212
|
label?: string;
|
|
209
213
|
visibleWhen?: FormCondition;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export * from './gantt';
|
|
|
19
19
|
export * from './node-flow';
|
|
20
20
|
export * from './personnel';
|
|
21
21
|
export * from './work-items';
|
|
22
|
+
export { createWorkflowDetail } from './work-items/workflow-detail';
|
|
23
|
+
export type * from './work-items/workflow-detail-types';
|
|
22
24
|
export { createControlRegistry, BaseFieldControl, sanitizeRichText } from './work-items/fields/registry';
|
|
23
25
|
export { createWorkItemFormSurface, evalFormCondition, evalFormScope } from './forms/form-surface';
|
|
24
26
|
export type { ComponentInteraction, InteractionOptions, InteractionSource } from './shared/interaction';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { WorkItem } from '../../contracts/work-item';
|
|
2
|
+
import type { FieldServices, FieldOption } from '../../fields/types';
|
|
3
|
+
export type DetailComment = Exclude<WorkItem['comments'][number], string> & {
|
|
4
|
+
authorId?: string;
|
|
5
|
+
replyTo?: string;
|
|
6
|
+
};
|
|
7
|
+
export interface DetailCommentSave {
|
|
8
|
+
action: 'create' | 'edit' | 'reply';
|
|
9
|
+
id?: string;
|
|
10
|
+
replyTo?: string;
|
|
11
|
+
html: string;
|
|
12
|
+
content: string;
|
|
13
|
+
}
|
|
14
|
+
export interface DetailCommentsPermissions {
|
|
15
|
+
create?: boolean;
|
|
16
|
+
reply?: boolean | ((comment: DetailComment) => boolean);
|
|
17
|
+
edit?: boolean | ((comment: DetailComment) => boolean);
|
|
18
|
+
}
|
|
19
|
+
export interface DetailCommentsOptions {
|
|
20
|
+
comments?: Array<string | DetailComment>;
|
|
21
|
+
data?: Array<string | DetailComment>;
|
|
22
|
+
author: string | {
|
|
23
|
+
id: string;
|
|
24
|
+
display: string;
|
|
25
|
+
};
|
|
26
|
+
permissions?: DetailCommentsPermissions;
|
|
27
|
+
people?: FieldOption[];
|
|
28
|
+
services?: Pick<FieldServices, 'searchOptions'>;
|
|
29
|
+
onSave?: (command: DetailCommentSave, signal: AbortSignal) => WorkItem['comments'] | Promise<WorkItem['comments']>;
|
|
30
|
+
onPublish?: (payload: DetailCommentSave, signal: AbortSignal) => boolean | Promise<boolean>;
|
|
31
|
+
onEdit?: (id: string, payload: DetailCommentSave, signal: AbortSignal) => boolean | Promise<boolean>;
|
|
32
|
+
hasMore?: boolean;
|
|
33
|
+
onLoadMore?: (signal: AbortSignal) => void | Promise<void>;
|
|
34
|
+
renderActions?: (container: HTMLElement, comment: DetailComment) => void | (() => void);
|
|
35
|
+
renderAttachments?: (container: HTMLElement, comment: DetailComment) => void | (() => void);
|
|
36
|
+
}
|
|
37
|
+
export declare function createDetailComments(initial: DetailCommentsOptions): {
|
|
38
|
+
element: HTMLElement;
|
|
39
|
+
composer: HTMLDivElement;
|
|
40
|
+
decorateTab: (surface: HTMLElement) => void;
|
|
41
|
+
update: (patch: Partial<Pick<DetailCommentsOptions, "comments" | "data" | "permissions" | "hasMore">>) => void;
|
|
42
|
+
deactivate: () => void;
|
|
43
|
+
destroy: () => void;
|
|
44
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { WorkItem } from '../../contracts/work-item';
|
|
2
|
+
import { type HistoryQuery, type HistoryEntry, type HistoryModule } from './history-model';
|
|
3
|
+
export interface DetailHistoryPage {
|
|
4
|
+
rows: HistoryEntry[];
|
|
5
|
+
total?: number;
|
|
6
|
+
matching?: number;
|
|
7
|
+
nextCursor?: string | null;
|
|
8
|
+
previousCursor?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface DetailHistoryQuery extends HistoryQuery {
|
|
11
|
+
cursor?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface DetailHistoryOptions {
|
|
14
|
+
records?: WorkItem['history'];
|
|
15
|
+
rows?: HistoryEntry[];
|
|
16
|
+
query?: Partial<DetailHistoryQuery>;
|
|
17
|
+
nextCursor?: string | null;
|
|
18
|
+
previousCursor?: string | null;
|
|
19
|
+
actor?: string;
|
|
20
|
+
nodeFlow?: boolean;
|
|
21
|
+
mode?: 'server' | 'local';
|
|
22
|
+
page?: DetailHistoryPage;
|
|
23
|
+
modules?: HistoryModule[];
|
|
24
|
+
operators?: Array<{
|
|
25
|
+
id: string;
|
|
26
|
+
label: string;
|
|
27
|
+
}>;
|
|
28
|
+
onQuery?: (query: DetailHistoryQuery, signal: AbortSignal) => DetailHistoryPage | void | Promise<DetailHistoryPage | void>;
|
|
29
|
+
onLoadMore?: (cursor: string, query: DetailHistoryQuery, signal: AbortSignal) => DetailHistoryPage | void | Promise<DetailHistoryPage | void>;
|
|
30
|
+
renderDetail?: (container: HTMLElement, entry: HistoryEntry) => void | (() => void);
|
|
31
|
+
}
|
|
32
|
+
export declare function createDetailHistory(initial: DetailHistoryOptions): {
|
|
33
|
+
element: HTMLElement;
|
|
34
|
+
refresh: (loadMore?: boolean) => void;
|
|
35
|
+
deactivate: () => void;
|
|
36
|
+
update: (patch: Partial<Pick<DetailHistoryOptions, "records" | "rows" | "page" | "query" | "nextCursor" | "previousCursor" | "modules" | "operators">>) => void;
|
|
37
|
+
destroy: () => void;
|
|
38
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { WorkItem } from '../../contracts/work-item';
|
|
2
|
+
export type HistoryEntry = Exclude<WorkItem['history'][number], string>;
|
|
3
|
+
export interface HistoryModule {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
}
|
|
7
|
+
export interface HistoryQuery {
|
|
8
|
+
keyword: string;
|
|
9
|
+
keywordFilter: boolean;
|
|
10
|
+
operatorKinds: Set<string>;
|
|
11
|
+
operators: Set<string>;
|
|
12
|
+
modules: Set<string>;
|
|
13
|
+
start: string;
|
|
14
|
+
end: string;
|
|
15
|
+
page: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const historyModules: HistoryModule[];
|
|
18
|
+
export declare function normalizeHistory(item: Pick<WorkItem, 'history'>, actor: string): HistoryEntry[];
|
|
19
|
+
/** The log endpoint already supplies localized display content; origin_content is not HTML. */
|
|
20
|
+
export declare function adaptOperationRecords(records: Array<{
|
|
21
|
+
id: string;
|
|
22
|
+
operator?: {
|
|
23
|
+
user_key: string;
|
|
24
|
+
name: string;
|
|
25
|
+
};
|
|
26
|
+
operator_type: number;
|
|
27
|
+
op_record_type_key: string;
|
|
28
|
+
op_record_type_name: string;
|
|
29
|
+
content: string;
|
|
30
|
+
created_at: number;
|
|
31
|
+
}>): HistoryEntry[];
|
|
32
|
+
export declare function queryHistory(logs: HistoryEntry[], query: HistoryQuery): {
|
|
33
|
+
rows: {
|
|
34
|
+
id?: string;
|
|
35
|
+
actor: string;
|
|
36
|
+
actorId?: string;
|
|
37
|
+
actorKind?: "user" | "computed" | "automation" | "system";
|
|
38
|
+
module: string;
|
|
39
|
+
moduleKey?: string;
|
|
40
|
+
detail: string;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
}[];
|
|
43
|
+
total: number;
|
|
44
|
+
matching: number;
|
|
45
|
+
filteredTotal: number;
|
|
46
|
+
page: number;
|
|
47
|
+
pageCount: number;
|
|
48
|
+
};
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
export type * from '../contracts/work-item';
|
|
2
|
+
export { createWorkflowDetail } from './workflow-detail';
|
|
3
|
+
export type * from './workflow-detail-types';
|
|
4
|
+
export { createDetailComments } from './detail/detail-comments';
|
|
5
|
+
export type { DetailComment, DetailCommentSave, DetailCommentsPermissions, DetailCommentsOptions } from './detail/detail-comments';
|
|
6
|
+
export { createDetailHistory } from './detail/detail-history';
|
|
7
|
+
export type { DetailHistoryPage, DetailHistoryQuery, DetailHistoryOptions } from './detail/detail-history';
|
|
8
|
+
export { historyModules, normalizeHistory, queryHistory, adaptOperationRecords } from './detail/history-model';
|
|
9
|
+
export type { HistoryEntry, HistoryModule, HistoryQuery } from './detail/history-model';
|
|
2
10
|
export type { FormCondition, FormConditionOp, FormScope, FormSurfaceContext } from '../forms/form-conditions';
|
|
3
11
|
export { emptyView, matches } from './model';
|
|
4
12
|
export { createWorkItemTabs } from './tabs';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FlowDefinition, FlowNode } from '../node-flow/types';
|
|
2
|
+
/** demand_fetch 的 modules / biz_data / ui_data 在 demo 中的轻量投影。
|
|
3
|
+
* 配置控制区域与字段,FlowNode 只提供实例值;不依赖 node-flow 组件。 */
|
|
4
|
+
export declare function projectWorkflowDetail(flow: FlowDefinition): {
|
|
5
|
+
controls: {
|
|
6
|
+
roles: {
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
color?: string;
|
|
10
|
+
nodeIds?: string[];
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
tooltip?: string;
|
|
13
|
+
}[];
|
|
14
|
+
switches: {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
checked: boolean;
|
|
18
|
+
nodeIds?: string[];
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
21
|
+
graph: {
|
|
22
|
+
nodes: FlowNode[];
|
|
23
|
+
edges: {
|
|
24
|
+
from: string;
|
|
25
|
+
to: string;
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
nodeList: FlowNode[];
|
|
29
|
+
node: (node: FlowNode) => {
|
|
30
|
+
data: FlowNode;
|
|
31
|
+
form: import("..").FormItem[];
|
|
32
|
+
fields: {
|
|
33
|
+
key: "owner" | "schedule" | "estimate";
|
|
34
|
+
label: string;
|
|
35
|
+
}[];
|
|
36
|
+
sections: ("form" | "tasks")[];
|
|
37
|
+
completeLabel: string;
|
|
38
|
+
deletable: boolean;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/** 按实际依赖拓扑分列,不根据阶段名猜测连线。 */
|
|
42
|
+
export declare function layoutWorkflowGraph(graph: ReturnType<typeof projectWorkflowDetail>['graph']): {
|
|
43
|
+
nodes: {
|
|
44
|
+
node: FlowNode;
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
width: number;
|
|
48
|
+
}[];
|
|
49
|
+
paths: string[];
|
|
50
|
+
width: number;
|
|
51
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { CustomButton, FlowDefinition, FlowNode, FormItem, NodeField, SubTask } from '../node-flow/types';
|
|
2
|
+
export type WorkflowDetailCommand = {
|
|
3
|
+
type: 'update-node';
|
|
4
|
+
nodeId: string;
|
|
5
|
+
patch: Partial<FlowNode>;
|
|
6
|
+
detail: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'delete-node';
|
|
9
|
+
nodeId: string;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'update-flow';
|
|
12
|
+
detail: NonNullable<FlowDefinition['detail']>;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'action';
|
|
15
|
+
nodeId: string;
|
|
16
|
+
actionId: string;
|
|
17
|
+
};
|
|
18
|
+
export type WorkflowDetailPermission = 'edit' | 'complete' | 'delete' | 'create-task' | 'toggle-task' | 'configure' | 'action';
|
|
19
|
+
export interface WorkflowDetailRenderContext {
|
|
20
|
+
node: FlowNode;
|
|
21
|
+
surface: 'selected' | 'list';
|
|
22
|
+
readonly: boolean;
|
|
23
|
+
pending: boolean;
|
|
24
|
+
signal: AbortSignal;
|
|
25
|
+
context: WorkflowDetailContext;
|
|
26
|
+
can(permission: WorkflowDetailPermission, key?: string): boolean;
|
|
27
|
+
commit(patch: Partial<FlowNode>, detail?: string): Promise<boolean>;
|
|
28
|
+
action(actionId: string): Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
export interface WorkflowDetailContext {
|
|
31
|
+
currentUser?: string;
|
|
32
|
+
people?: {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}[];
|
|
36
|
+
workItems?: {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
}[];
|
|
40
|
+
}
|
|
41
|
+
export type WorkflowDetailResult = FlowDefinition | void | Promise<FlowDefinition | void>;
|
|
42
|
+
export interface WorkflowDetailCallbackContext {
|
|
43
|
+
flow: FlowDefinition;
|
|
44
|
+
signal: AbortSignal;
|
|
45
|
+
}
|
|
46
|
+
export interface WorkflowDetailOptions {
|
|
47
|
+
flow: FlowDefinition;
|
|
48
|
+
selectedNodeId?: string;
|
|
49
|
+
currentUser?: string;
|
|
50
|
+
workItems?: {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
}[];
|
|
54
|
+
readonly?: boolean;
|
|
55
|
+
context?: WorkflowDetailContext;
|
|
56
|
+
can?: (permission: WorkflowDetailPermission, node?: FlowNode, key?: string) => boolean;
|
|
57
|
+
onChange?: (nodeId: string, patch: Partial<FlowNode>, detail: string, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
58
|
+
onComplete?: (nodeId: string, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
59
|
+
onAction?: (nodeId: string, actionId: string, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
60
|
+
onDelete?: (nodeId: string, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
61
|
+
onFlowChange?: (detail: NonNullable<FlowDefinition['detail']>, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
62
|
+
onCreateTask?: (nodeId: string, context: WorkflowDetailCallbackContext) => WorkflowDetailResult;
|
|
63
|
+
taskColumns?: (node: FlowNode) => {
|
|
64
|
+
key: string;
|
|
65
|
+
label: string;
|
|
66
|
+
}[];
|
|
67
|
+
renderTaskField?: (host: HTMLElement, task: SubTask, column: {
|
|
68
|
+
key: string;
|
|
69
|
+
label: string;
|
|
70
|
+
}, context: WorkflowDetailRenderContext) => void | (() => void);
|
|
71
|
+
onCommand?: (command: WorkflowDetailCommand, context: {
|
|
72
|
+
flow: FlowDefinition;
|
|
73
|
+
signal: AbortSignal;
|
|
74
|
+
}) => FlowDefinition | void | Promise<FlowDefinition | void>;
|
|
75
|
+
onError?: (error: unknown, command: WorkflowDetailCommand) => void;
|
|
76
|
+
onSelectNode?: (nodeId: string) => void;
|
|
77
|
+
renderField?: (container: HTMLElement, field: FormItem | NodeField, context: WorkflowDetailRenderContext) => void | (() => void);
|
|
78
|
+
renderSystemField?: (container: HTMLElement, field: {
|
|
79
|
+
key: 'owner' | 'schedule' | 'estimate';
|
|
80
|
+
label: string;
|
|
81
|
+
}, context: WorkflowDetailRenderContext) => void | (() => void);
|
|
82
|
+
renderActions?: (container: HTMLElement, buttons: CustomButton[], context: WorkflowDetailRenderContext) => void | (() => void);
|
|
83
|
+
renderNodeFields?: (node: FlowNode, host: HTMLElement, context: WorkflowDetailRenderContext) => void | (() => void);
|
|
84
|
+
renderNodeForm?: (node: FlowNode, host: HTMLElement, context: WorkflowDetailRenderContext) => void | (() => void);
|
|
85
|
+
}
|
|
86
|
+
export interface WorkflowDetailApi {
|
|
87
|
+
element: HTMLElement;
|
|
88
|
+
nodeListElement: HTMLElement;
|
|
89
|
+
renderNodeDetails(): HTMLElement;
|
|
90
|
+
setFlow(flow: FlowDefinition): void;
|
|
91
|
+
update(options: Partial<WorkflowDetailOptions>): void;
|
|
92
|
+
selectNode(nodeId: string): void;
|
|
93
|
+
getSelectedNode(): FlowNode | undefined;
|
|
94
|
+
destroy(): void;
|
|
95
|
+
}
|