修正了一些modi的相关逻辑
This commit is contained in:
parent
8ae9ff9bfe
commit
b2c1760c6e
|
|
@ -2,7 +2,7 @@ import { AggregationResult, EntityDict, OperationResult, OpRecord, SelectOption
|
|||
import { StorageSchema } from "oak-domain/lib/types/Storage";
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { Checker, CheckerType, TxnOption } from 'oak-domain/lib/types';
|
||||
import { TreeStore, TreeStoreOperateOption } from 'oak-memory-tree-store';
|
||||
import { TreeStore, TreeStoreOperateOption, TreeStoreSelectOption } from 'oak-memory-tree-store';
|
||||
import { SyncContext, SyncRowStore } from 'oak-domain/lib/store/SyncRowStore';
|
||||
interface CachStoreOperation extends TreeStoreOperateOption {
|
||||
checkerTypes?: CheckerType[];
|
||||
|
|
@ -19,7 +19,7 @@ export declare class CacheStore<ED extends EntityDict & BaseEntityDict> extends
|
|||
data?: ED[T]['Operation']['data'];
|
||||
filter?: ED[T]['Operation']['filter'];
|
||||
}, context: SyncContext<ED>, checkerTypes?: CheckerType[]): void;
|
||||
select<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]["Schema"]>[];
|
||||
select<T extends keyof ED, OP extends TreeStoreSelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]["Schema"]>[];
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T, SyncContext<ED>>): void;
|
||||
count<T extends keyof ED, OP extends SelectOption>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: SyncContext<ED>, option: OP): number;
|
||||
begin(option?: TxnOption): string;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export default function render(props: WebComponentProps<EntityDict, 'path', true
|
|||
recursivable: boolean;
|
||||
legalSourceEntity: boolean;
|
||||
destEntityFixed: boolean;
|
||||
oakExecutable: boolean | Error;
|
||||
}, {
|
||||
updateDestEntity: (de: string) => void;
|
||||
selectPath: (value: string) => void;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export default function render(props) {
|
|||
</Form.Item>}
|
||||
</Form>
|
||||
<Flex justify="end" style={{ padding: 10 }}>
|
||||
<Button type="primary" onClick={() => confirm()} disabled={!legalSourceEntity || !oakExecutable}>
|
||||
<Button type="primary" onClick={() => confirm()} disabled={!legalSourceEntity || oakExecutable !== true}>
|
||||
{t('common::action.confirm')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
|
|
|||
|
|
@ -440,12 +440,18 @@ export class Cache extends Feature {
|
|||
const result = this.cacheStore.select(entity, selection, this.context, {
|
||||
dontCollect: true,
|
||||
includedDeleted: true,
|
||||
warnWhenAttributeMiss: !this.refreshing && process.env.NODE_ENV === 'development',
|
||||
});
|
||||
rollback && rollback();
|
||||
return result;
|
||||
}
|
||||
catch (err) {
|
||||
rollback && rollback();
|
||||
if (err instanceof OakRowUnexistedException) {
|
||||
// 现在只有外键缺失会抛出RowUnexisted异常,前台在modi中连接了其它表的外键时会出现
|
||||
this.fetchRows(err.getRows());
|
||||
return [];
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorterByName(name: string, refresh: boolean): void;
|
||||
getFreshValue(inModi?: boolean): Array<Partial<ED[T]['Schema']>>;
|
||||
getFreshValue(inModiNextBranch?: boolean): Array<Partial<ED[T]['Schema']>>;
|
||||
private addItemInner;
|
||||
addItem(lsn: number, item: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||
id?: string;
|
||||
|
|
@ -286,13 +286,10 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
private root;
|
||||
constructor(cache: Cache<ED>, schema: StorageSchema<ED>);
|
||||
createNode<T extends keyof ED>(options: CreateNodeOptions<ED, T>, isPage: boolean): ListNode<ED, T> | SingleNode<ED, T> | VirtualNode<ED>;
|
||||
private checkSingleNodeIsModiNode;
|
||||
checkIsModiNode(path: string): boolean;
|
||||
checkIsInModiNextBranch(path: string): boolean;
|
||||
private findNode;
|
||||
destroyNode(path: string, isPage: boolean): void;
|
||||
begin(): () => void;
|
||||
redoBranchOperations(path: string): void;
|
||||
redoBranchModis(path: string): void;
|
||||
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
||||
isDirty(path: string): boolean;
|
||||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||
|
|
@ -349,6 +346,19 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]["Operation"];
|
||||
}[] | undefined;
|
||||
private cachedOperations;
|
||||
private cachedModis;
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchOperations(path: string): void;
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchModis(path: string): void;
|
||||
tryExecute(path: string, action?: string): void;
|
||||
execute<T extends keyof ED>(path: string, action?: ED[T]['Action'], opers?: Array<{
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
|
|
|
|||
|
|
@ -703,7 +703,7 @@ class ListNode extends EntityNode {
|
|||
this.publish();
|
||||
}
|
||||
}
|
||||
getFreshValue(inModi) {
|
||||
getFreshValue(inModiNextBranch) {
|
||||
/**
|
||||
* 现在简化情况,只取sr中有id的数据,以及addItem中的create数据
|
||||
* 但是对于modi查询,需要查询“热更新”部分的数据(因为这部分数据不会被sync到内存中,逻辑不严密,后面再说)
|
||||
|
|
@ -716,7 +716,7 @@ class ListNode extends EntityNode {
|
|||
/**
|
||||
* 在非modi状态下,所取数据是在ids2中满足filter的部分(自身对象和其它对象的更新可能会影响这些行不再满足条件)
|
||||
*/
|
||||
const filter2 = inModi ? filter : (ids2.length > 0 ? combineFilters(this.entity, this.cache.getSchema(), [filter, {
|
||||
const filter2 = inModiNextBranch ? filter : (ids2.length > 0 ? combineFilters(this.entity, this.cache.getSchema(), [filter, {
|
||||
id: {
|
||||
$in: ids2,
|
||||
}
|
||||
|
|
@ -724,7 +724,7 @@ class ListNode extends EntityNode {
|
|||
if (filter2 && data) {
|
||||
const result = this.cache.get(this.entity, {
|
||||
data,
|
||||
filter: inModi ? filter : filter2,
|
||||
filter: inModiNextBranch ? filter : filter2,
|
||||
sorter,
|
||||
}, this.sr);
|
||||
return result;
|
||||
|
|
@ -1886,40 +1886,30 @@ export class RunningTree extends Feature {
|
|||
}
|
||||
return node;
|
||||
}
|
||||
checkSingleNodeIsModiNode(node) {
|
||||
const id = node.getId();
|
||||
if (id) {
|
||||
const modies = this.cache.get('modi', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
targetEntity: node.getEntity(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id,
|
||||
},
|
||||
iState: 'active',
|
||||
}
|
||||
});
|
||||
return modies.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
checkIsModiNode(path) {
|
||||
// 判断当前结点是否在:next的路径上(且有前项结点,两者同时满足就不用refresh了)
|
||||
checkIsInModiNextBranch(path) {
|
||||
if (!path.includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
return false;
|
||||
}
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof SingleNode) {
|
||||
return this.checkSingleNodeIsModiNode(node);
|
||||
const paths = path.split('.');
|
||||
if (paths[0].includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
// 根结点就是:next,这时候还是要取的
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
assert(node instanceof ListNode);
|
||||
const parent = node.getParent();
|
||||
assert(parent instanceof SingleNode);
|
||||
return this.checkSingleNodeIsModiNode(parent);
|
||||
let iter = 1;
|
||||
while (iter < paths.length) {
|
||||
if (paths[iter].includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
const path2 = paths.slice(0, iter) + paths[iter].replace(MODI_NEXT_PATH_SUFFIX, '');
|
||||
const node = this.findNode(path2);
|
||||
if (node) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
findNode(path) {
|
||||
if (this.root[path]) {
|
||||
|
|
@ -1967,29 +1957,11 @@ export class RunningTree extends Feature {
|
|||
begin() {
|
||||
return this.cache.begin();
|
||||
}
|
||||
redoBranchOperations(path) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
const rootNode = this.root[root];
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
redoBranchModis(path) {
|
||||
const { root } = analyzePath(path);
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
getFreshValue(path) {
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof ListNode) {
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(includeModi);
|
||||
const inModiNextBranch = path.includes(MODI_NEXT_PATH_SUFFIX) && !path.endsWith(MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(inModiNextBranch);
|
||||
}
|
||||
assert(node instanceof SingleNode);
|
||||
return node.getFreshValue();
|
||||
|
|
@ -2214,13 +2186,43 @@ export class RunningTree extends Feature {
|
|||
const operations = node?.composeOperations();
|
||||
return operations;
|
||||
}
|
||||
cachedOperations = {};
|
||||
cachedModis = {};
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchOperations(path) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
const rootNode = this.root[root];
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchModis(path) {
|
||||
const { root } = analyzePath(path);
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
tryExecute(path, action) {
|
||||
}
|
||||
async execute(path, action, opers) {
|
||||
const node = this.findNode(path);
|
||||
// assert(node.isDirty());
|
||||
node.setExecuting(true);
|
||||
let pollute = false;
|
||||
try {
|
||||
let operations = node.composeOperations() || [];
|
||||
let operations = this.getOperations(path) || [];
|
||||
if (opers) {
|
||||
operations.push(...opers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -422,7 +422,8 @@ export function reRender(option, extra) {
|
|||
const oakLoadingMore = this.features.runningTree.isLoadingMore(this.state.oakFullpath);
|
||||
const oakLoading = !oakLoadingMore && this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 这个很耗时,让用户去相应要execute的页面上调用
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||
let rollback = this.features.runningTree.begin();
|
||||
try {
|
||||
|
|
@ -489,7 +490,6 @@ export function reRender(option, extra) {
|
|||
}
|
||||
;
|
||||
Object.assign(data, {
|
||||
oakExecutable,
|
||||
oakDirty,
|
||||
oakLoading,
|
||||
oakLoadingMore,
|
||||
|
|
@ -523,11 +523,11 @@ export function reRender(option, extra) {
|
|||
*/
|
||||
const oakDirty = this.features.runningTree.isDirty(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
const oakLoading = this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
Object.assign(data, {
|
||||
oakDirty,
|
||||
oakExecutable,
|
||||
// oakExecutable,
|
||||
oakExecuting,
|
||||
oakLoading,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ const oakBehavior = Behavior({
|
|||
this.oakOption.lifetimes?.ready.call(this);
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.oakOption.stale &&
|
||||
!this.features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!this.features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!this.features.runningTree.isListDescandent(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
|
|
@ -791,7 +791,7 @@ export function createComponent(option, features) {
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ export function createComponent(option, features) {
|
|||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
@ -707,7 +707,7 @@ export function createComponent(option, features) {
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -325,7 +325,6 @@ export type OakComponentOnlyMethods = {
|
|||
setOakActions: () => void;
|
||||
};
|
||||
export type OakComponentData<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
oakExecutable: boolean | Error;
|
||||
oakExecuting: boolean;
|
||||
oakFocused: {
|
||||
attr: string;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { AggregationResult, EntityDict, OperationResult, OpRecord, SelectOption
|
|||
import { StorageSchema } from "oak-domain/lib/types/Storage";
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { Checker, CheckerType, TxnOption } from 'oak-domain/lib/types';
|
||||
import { TreeStore, TreeStoreOperateOption } from 'oak-memory-tree-store';
|
||||
import { TreeStore, TreeStoreOperateOption, TreeStoreSelectOption } from 'oak-memory-tree-store';
|
||||
import { SyncContext, SyncRowStore } from 'oak-domain/lib/store/SyncRowStore';
|
||||
interface CachStoreOperation extends TreeStoreOperateOption {
|
||||
checkerTypes?: CheckerType[];
|
||||
|
|
@ -19,7 +19,7 @@ export declare class CacheStore<ED extends EntityDict & BaseEntityDict> extends
|
|||
data?: ED[T]['Operation']['data'];
|
||||
filter?: ED[T]['Operation']['filter'];
|
||||
}, context: SyncContext<ED>, checkerTypes?: CheckerType[]): void;
|
||||
select<T extends keyof ED, OP extends SelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]["Schema"]>[];
|
||||
select<T extends keyof ED, OP extends TreeStoreSelectOption, Cxt extends SyncContext<ED>>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP): Partial<ED[T]["Schema"]>[];
|
||||
registerChecker<T extends keyof ED>(checker: Checker<ED, T, SyncContext<ED>>): void;
|
||||
count<T extends keyof ED, OP extends SelectOption>(entity: T, selection: Pick<ED[T]['Selection'], 'filter' | 'count'>, context: SyncContext<ED>, option: OP): number;
|
||||
begin(option?: TxnOption): string;
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedSorterByName(name: string, refresh: boolean): void;
|
||||
getFreshValue(inModi?: boolean): Array<Partial<ED[T]['Schema']>>;
|
||||
getFreshValue(inModiNextBranch?: boolean): Array<Partial<ED[T]['Schema']>>;
|
||||
private addItemInner;
|
||||
addItem(lsn: number, item: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||
id?: string;
|
||||
|
|
@ -286,13 +286,10 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
private root;
|
||||
constructor(cache: Cache<ED>, schema: StorageSchema<ED>);
|
||||
createNode<T extends keyof ED>(options: CreateNodeOptions<ED, T>, isPage: boolean): ListNode<ED, T> | SingleNode<ED, T> | VirtualNode<ED>;
|
||||
private checkSingleNodeIsModiNode;
|
||||
checkIsModiNode(path: string): boolean;
|
||||
checkIsInModiNextBranch(path: string): boolean;
|
||||
private findNode;
|
||||
destroyNode(path: string, isPage: boolean): void;
|
||||
begin(): () => void;
|
||||
redoBranchOperations(path: string): void;
|
||||
redoBranchModis(path: string): void;
|
||||
getFreshValue(path: string): Partial<ED[keyof ED]["Schema"]> | Partial<ED[keyof ED]["Schema"]>[] | undefined;
|
||||
isDirty(path: string): boolean;
|
||||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'> & {
|
||||
|
|
@ -349,6 +346,19 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]["Operation"];
|
||||
}[] | undefined;
|
||||
private cachedOperations;
|
||||
private cachedModis;
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchOperations(path: string): void;
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchModis(path: string): void;
|
||||
tryExecute(path: string, action?: string): void;
|
||||
execute<T extends keyof ED>(path: string, action?: ED[T]['Action'], opers?: Array<{
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
|
|
|
|||
|
|
@ -706,7 +706,7 @@ class ListNode extends EntityNode {
|
|||
this.publish();
|
||||
}
|
||||
}
|
||||
getFreshValue(inModi) {
|
||||
getFreshValue(inModiNextBranch) {
|
||||
/**
|
||||
* 现在简化情况,只取sr中有id的数据,以及addItem中的create数据
|
||||
* 但是对于modi查询,需要查询“热更新”部分的数据(因为这部分数据不会被sync到内存中,逻辑不严密,后面再说)
|
||||
|
|
@ -719,7 +719,7 @@ class ListNode extends EntityNode {
|
|||
/**
|
||||
* 在非modi状态下,所取数据是在ids2中满足filter的部分(自身对象和其它对象的更新可能会影响这些行不再满足条件)
|
||||
*/
|
||||
const filter2 = inModi ? filter : (ids2.length > 0 ? (0, filter_1.combineFilters)(this.entity, this.cache.getSchema(), [filter, {
|
||||
const filter2 = inModiNextBranch ? filter : (ids2.length > 0 ? (0, filter_1.combineFilters)(this.entity, this.cache.getSchema(), [filter, {
|
||||
id: {
|
||||
$in: ids2,
|
||||
}
|
||||
|
|
@ -727,7 +727,7 @@ class ListNode extends EntityNode {
|
|||
if (filter2 && data) {
|
||||
const result = this.cache.get(this.entity, {
|
||||
data,
|
||||
filter: inModi ? filter : filter2,
|
||||
filter: inModiNextBranch ? filter : filter2,
|
||||
sorter,
|
||||
}, this.sr);
|
||||
return result;
|
||||
|
|
@ -1889,40 +1889,30 @@ class RunningTree extends Feature_1.Feature {
|
|||
}
|
||||
return node;
|
||||
}
|
||||
checkSingleNodeIsModiNode(node) {
|
||||
const id = node.getId();
|
||||
if (id) {
|
||||
const modies = this.cache.get('modi', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
targetEntity: node.getEntity(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id,
|
||||
},
|
||||
iState: 'active',
|
||||
}
|
||||
});
|
||||
return modies.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
checkIsModiNode(path) {
|
||||
// 判断当前结点是否在:next的路径上(且有前项结点,两者同时满足就不用refresh了)
|
||||
checkIsInModiNextBranch(path) {
|
||||
if (!path.includes(exports.MODI_NEXT_PATH_SUFFIX)) {
|
||||
return false;
|
||||
}
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof SingleNode) {
|
||||
return this.checkSingleNodeIsModiNode(node);
|
||||
const paths = path.split('.');
|
||||
if (paths[0].includes(exports.MODI_NEXT_PATH_SUFFIX)) {
|
||||
// 根结点就是:next,这时候还是要取的
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
(0, assert_1.assert)(node instanceof ListNode);
|
||||
const parent = node.getParent();
|
||||
(0, assert_1.assert)(parent instanceof SingleNode);
|
||||
return this.checkSingleNodeIsModiNode(parent);
|
||||
let iter = 1;
|
||||
while (iter < paths.length) {
|
||||
if (paths[iter].includes(exports.MODI_NEXT_PATH_SUFFIX)) {
|
||||
const path2 = paths.slice(0, iter) + paths[iter].replace(exports.MODI_NEXT_PATH_SUFFIX, '');
|
||||
const node = this.findNode(path2);
|
||||
if (node) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
(0, assert_1.assert)(false);
|
||||
return false;
|
||||
}
|
||||
findNode(path) {
|
||||
if (this.root[path]) {
|
||||
|
|
@ -1970,29 +1960,11 @@ class RunningTree extends Feature_1.Feature {
|
|||
begin() {
|
||||
return this.cache.begin();
|
||||
}
|
||||
redoBranchOperations(path) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
const rootNode = this.root[root];
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
redoBranchModis(path) {
|
||||
const { root } = analyzePath(path);
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
getFreshValue(path) {
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof ListNode) {
|
||||
const includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(includeModi);
|
||||
const inModiNextBranch = path.includes(exports.MODI_NEXT_PATH_SUFFIX) && !path.endsWith(exports.MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(inModiNextBranch);
|
||||
}
|
||||
(0, assert_1.assert)(node instanceof SingleNode);
|
||||
return node.getFreshValue();
|
||||
|
|
@ -2217,13 +2189,43 @@ class RunningTree extends Feature_1.Feature {
|
|||
const operations = node?.composeOperations();
|
||||
return operations;
|
||||
}
|
||||
cachedOperations = {};
|
||||
cachedModis = {};
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchOperations(path) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
const rootNode = this.root[root];
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchModis(path) {
|
||||
const { root } = analyzePath(path);
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(exports.MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
tryExecute(path, action) {
|
||||
}
|
||||
async execute(path, action, opers) {
|
||||
const node = this.findNode(path);
|
||||
// assert(node.isDirty());
|
||||
node.setExecuting(true);
|
||||
let pollute = false;
|
||||
try {
|
||||
let operations = node.composeOperations() || [];
|
||||
let operations = this.getOperations(path) || [];
|
||||
if (opers) {
|
||||
operations.push(...opers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,7 +426,8 @@ function reRender(option, extra) {
|
|||
const oakLoadingMore = this.features.runningTree.isLoadingMore(this.state.oakFullpath);
|
||||
const oakLoading = !oakLoadingMore && this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 这个很耗时,让用户去相应要execute的页面上调用
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||
let rollback = this.features.runningTree.begin();
|
||||
try {
|
||||
|
|
@ -493,7 +494,6 @@ function reRender(option, extra) {
|
|||
}
|
||||
;
|
||||
Object.assign(data, {
|
||||
oakExecutable,
|
||||
oakDirty,
|
||||
oakLoading,
|
||||
oakLoadingMore,
|
||||
|
|
@ -527,11 +527,11 @@ function reRender(option, extra) {
|
|||
*/
|
||||
const oakDirty = this.features.runningTree.isDirty(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
const oakLoading = this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
Object.assign(data, {
|
||||
oakDirty,
|
||||
oakExecutable,
|
||||
// oakExecutable,
|
||||
oakExecuting,
|
||||
oakLoading,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ const oakBehavior = Behavior({
|
|||
this.oakOption.lifetimes?.ready.call(this);
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.oakOption.stale &&
|
||||
!this.features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!this.features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!this.features.runningTree.isListDescandent(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
|
|
@ -794,7 +794,7 @@ function createComponent(option, features) {
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react';
|
||||
import { Aspect, EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { BasicFeatures } from './features';
|
||||
|
|
@ -5,4 +6,4 @@ import { Feature } from './types/Feature';
|
|||
import { DataOption, OakComponentOption } from './types/Page';
|
||||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): any;
|
||||
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Aspect, CheckerType, EntityDict, OpRecord } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { BasicFeatures } from './features';
|
||||
import { NamedFilterItem, NamedSorterItem } from './types/NamedCondition';
|
||||
import { Feature } from './types/Feature';
|
||||
import { DataOption, ComponentProps, OakComponentOption, OakNavigateToParameters } from './types/Page';
|
||||
import { DataOption, ComponentData, ComponentProps, OakComponentOption, OakNavigateToParameters } from './types/Page';
|
||||
import { MessageProps } from './types/Message';
|
||||
import { NotificationProps } from './types/Notification';
|
||||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
|
|
@ -103,5 +104,23 @@ export declare function createComponent<IsList extends boolean, ED extends Entit
|
|||
setPageSize(pageSize: number, path?: string | undefined): void;
|
||||
setCurrentPage(currentPage: number, path?: string | undefined): void;
|
||||
subDataEvents(events: string[], callback: (event: string, opRecords: OpRecord<ED>[]) => void): Promise<() => void>;
|
||||
context: unknown;
|
||||
setState<K extends keyof TData | keyof FormedData | keyof import("./types/Page").OakComponentData<ED, T>>(state: ComponentData<ED, T, FormedData, TData> | ((prevState: Readonly<ComponentData<ED, T, FormedData, TData>>, props: Readonly<ComponentProps<ED, T, TProperty>>) => ComponentData<ED, T, FormedData, TData> | Pick<ComponentData<ED, T, FormedData, TData>, K> | null) | Pick<ComponentData<ED, T, FormedData, TData>, K> | null, callback?: (() => void) | undefined): void;
|
||||
forceUpdate(callback?: (() => void) | undefined): void;
|
||||
readonly props: Readonly<ComponentProps<ED, T, TProperty>>;
|
||||
state: Readonly<ComponentData<ED, T, FormedData, TData>>;
|
||||
refs: {
|
||||
[key: string]: React.ReactInstance;
|
||||
};
|
||||
shouldComponentUpdate?(nextProps: Readonly<ComponentProps<ED, T, TProperty>>, nextState: Readonly<ComponentData<ED, T, FormedData, TData>>, nextContext: any): boolean;
|
||||
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
||||
getSnapshotBeforeUpdate?(prevProps: Readonly<ComponentProps<ED, T, TProperty>>, prevState: Readonly<ComponentData<ED, T, FormedData, TData>>): any;
|
||||
componentWillMount?(): void;
|
||||
UNSAFE_componentWillMount?(): void;
|
||||
componentWillReceiveProps?(nextProps: Readonly<ComponentProps<ED, T, TProperty>>, nextContext: any): void;
|
||||
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<ComponentProps<ED, T, TProperty>>, nextContext: any): void;
|
||||
componentWillUpdate?(nextProps: Readonly<ComponentProps<ED, T, TProperty>>, nextState: Readonly<ComponentData<ED, T, FormedData, TData>>, nextContext: any): void;
|
||||
UNSAFE_componentWillUpdate?(nextProps: Readonly<ComponentProps<ED, T, TProperty>>, nextState: Readonly<ComponentData<ED, T, FormedData, TData>>, nextContext: any): void;
|
||||
};
|
||||
contextType?: React.Context<any> | undefined;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -652,7 +652,7 @@ function createComponent(option, features) {
|
|||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
@ -712,7 +712,7 @@ function createComponent(option, features) {
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react';
|
||||
import { Aspect, EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { BasicFeatures } from './features';
|
||||
|
|
@ -5,4 +6,4 @@ import { Feature } from './types/Feature';
|
|||
import { DataOption, OakComponentOption } from './types/Page';
|
||||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): any;
|
||||
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
exports.createComponent = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const react_1 = tslib_1.__importDefault(require("react"));
|
||||
const withRouter_1 = tslib_1.__importDefault(require("./platforms/web/router/withRouter"));
|
||||
const PullToRefresh_1 = tslib_1.__importDefault(require("./platforms/web/PullToRefresh"));
|
||||
const page_react_1 = require("./page.react");
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ type Props = {
|
|||
features: Record<string, Feature>;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
declare const FeaturesProvider: (props: Props) => any;
|
||||
declare const useFeatures: <FD2 extends Record<string, Feature>>() => any;
|
||||
declare const FeaturesProvider: (props: Props) => import("react/jsx-runtime").JSX.Element;
|
||||
declare const useFeatures: <FD2 extends Record<string, Feature>>() => FD2;
|
||||
export { FeaturesProvider, useFeatures };
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
type OakComponentProperties = {
|
||||
path?: string;
|
||||
properties?: Record<string, any>;
|
||||
};
|
||||
declare const withRouter: (Component: React.ComponentType<any>, { path, properties }: OakComponentProperties) => any;
|
||||
declare const withRouter: (Component: React.ComponentType<any>, { path, properties }: OakComponentProperties) => React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
export default withRouter;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react';
|
||||
import 'nprogress/nprogress.css';
|
||||
declare const _default: any;
|
||||
declare const _default: React.MemoExoticComponent<() => null>;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const react_1 = tslib_1.__importDefault(require("react"));
|
||||
const rmc_pull_to_refresh_1 = tslib_1.__importDefault(require("rmc-pull-to-refresh"));
|
||||
require("./PullToRefresh.css");
|
||||
const OakPullToRefresh = (props) => {
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ declare const FeaturesProvider: React.FC<{
|
|||
features: Record<string, Feature>;
|
||||
children: React.ReactNode;
|
||||
}>;
|
||||
declare const useFeatures: <FD2 extends Record<string, Feature>>() => any;
|
||||
declare const useFeatures: <FD2 extends Record<string, Feature>>() => FD2;
|
||||
export { FeaturesProvider, useFeatures };
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ import React from 'react';
|
|||
type AppContainerProps = {
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
declare const AppContainer: (props: AppContainerProps) => any;
|
||||
declare const AppContainer: (props: AppContainerProps) => import("react/jsx-runtime").JSX.Element;
|
||||
export default AppContainer;
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ interface ErrorProps<ED extends EntityDict & BaseEntityDict> {
|
|||
error: any;
|
||||
features: BasicFeatures<ED>;
|
||||
}
|
||||
declare function Error<ED extends EntityDict & BaseEntityDict>(props: ErrorProps<ED>): any;
|
||||
declare function Error<ED extends EntityDict & BaseEntityDict>(props: ErrorProps<ED>): import("react/jsx-runtime").JSX.Element;
|
||||
export default Error;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,34 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
const react_1 = tslib_1.__importStar(require("react"));
|
||||
const react_1 = require("react");
|
||||
const antd_1 = require("antd");
|
||||
const Exception_1 = require("oak-domain/lib/types/Exception");
|
||||
const ErrorPage_1 = require("../../../types/ErrorPage");
|
||||
const ErrorPage = (0, react_1.lazy)(() => Promise.resolve().then(() => tslib_1.__importStar(require('../../../components/errorPage'))));
|
||||
const ErrorPage = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../../../components/errorPage'))));
|
||||
function Error(props) {
|
||||
const { error, features } = props;
|
||||
if (error instanceof Exception_1.OakException) {
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ declare const AppRouter: <ED extends BaseEntityDict>(props: {
|
|||
routers: IRouter[];
|
||||
appName: string;
|
||||
features: BasicFeatures<ED>;
|
||||
}) => any;
|
||||
}) => import("react/jsx-runtime").JSX.Element;
|
||||
export default AppRouter;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const tslib_1 = require("tslib");
|
||||
const jsx_runtime_1 = require("react/jsx-runtime");
|
||||
// @ts-nocheck
|
||||
const react_1 = tslib_1.__importDefault(require("react"));
|
||||
const client_1 = tslib_1.__importDefault(require("react-dom/client"));
|
||||
const history_1 = require("history");
|
||||
const react_router_dom_1 = require("react-router-dom");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react';
|
||||
export type Width = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
||||
export type Keys = Width[];
|
||||
export type Values = {
|
||||
|
|
@ -15,4 +16,6 @@ export type Breakpoints = {
|
|||
export declare const keys: Keys;
|
||||
export declare const values: Values;
|
||||
export declare const defaultBreakpoints: Breakpoints;
|
||||
export declare const ResponsiveContext: any;
|
||||
export declare const ResponsiveContext: React.Context<{
|
||||
breakpoints?: Breakpoints | undefined;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
type OakComponentProperties = {
|
||||
path?: string;
|
||||
properties?: Record<string, any>;
|
||||
};
|
||||
declare const withRouter: (Component: React.ComponentType<any>, { path, properties }: OakComponentProperties) => any;
|
||||
declare const withRouter: (Component: React.ComponentType<any>, { path, properties }: OakComponentProperties) => React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
export default withRouter;
|
||||
|
|
|
|||
|
|
@ -325,7 +325,6 @@ export type OakComponentOnlyMethods = {
|
|||
setOakActions: () => void;
|
||||
};
|
||||
export type OakComponentData<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
oakExecutable: boolean | Error;
|
||||
oakExecuting: boolean;
|
||||
oakFocused: {
|
||||
attr: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { StorageSchema } from "oak-domain/lib/types/Storage";
|
|||
import { readOnlyActions } from 'oak-domain/lib/actions/action';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { Checker, CheckerType, Trigger, TxnOption } from 'oak-domain/lib/types';
|
||||
import { TreeStore, TreeStoreOperateOption } from 'oak-memory-tree-store';
|
||||
import { TreeStore, TreeStoreOperateOption, TreeStoreSelectOption } from 'oak-memory-tree-store';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { SyncContext, SyncRowStore } from 'oak-domain/lib/store/SyncRowStore';
|
||||
import SyncTriggerExecutor from './SyncTriggerExecutor';
|
||||
|
|
@ -73,7 +73,7 @@ export class CacheStore<ED extends EntityDict & BaseEntityDict> extends TreeStor
|
|||
|
||||
select<
|
||||
T extends keyof ED,
|
||||
OP extends SelectOption,
|
||||
OP extends TreeStoreSelectOption,
|
||||
Cxt extends SyncContext<ED>
|
||||
>(entity: T, selection: ED[T]['Selection'], context: Cxt, option: OP) {
|
||||
assert(context.getCurrentTxnId());
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export default function render(
|
|||
recursivable: boolean;
|
||||
legalSourceEntity: boolean;
|
||||
destEntityFixed: boolean;
|
||||
oakExecutable: boolean | Error;
|
||||
},
|
||||
{
|
||||
updateDestEntity: (de: string) => void;
|
||||
|
|
@ -186,7 +187,7 @@ export default function render(
|
|||
<Button
|
||||
type="primary"
|
||||
onClick={() => confirm()}
|
||||
disabled={!legalSourceEntity || !oakExecutable}
|
||||
disabled={!legalSourceEntity || oakExecutable !== true}
|
||||
>
|
||||
{t('common::action.confirm')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -862,7 +862,7 @@ class ListNode<
|
|||
}
|
||||
}
|
||||
|
||||
getFreshValue(inModi?: boolean): Array<Partial<ED[T]['Schema']>> {
|
||||
getFreshValue(inModiNextBranch?: boolean): Array<Partial<ED[T]['Schema']>> {
|
||||
/**
|
||||
* 现在简化情况,只取sr中有id的数据,以及addItem中的create数据
|
||||
* 但是对于modi查询,需要查询“热更新”部分的数据(因为这部分数据不会被sync到内存中,逻辑不严密,后面再说)
|
||||
|
|
@ -880,7 +880,7 @@ class ListNode<
|
|||
/**
|
||||
* 在非modi状态下,所取数据是在ids2中满足filter的部分(自身对象和其它对象的更新可能会影响这些行不再满足条件)
|
||||
*/
|
||||
const filter2 = inModi ? filter : (ids2.length > 0 ? combineFilters(
|
||||
const filter2 = inModiNextBranch ? filter : (ids2.length > 0 ? combineFilters(
|
||||
this.entity,
|
||||
this.cache.getSchema(),
|
||||
[filter, {
|
||||
|
|
@ -892,7 +892,7 @@ class ListNode<
|
|||
if (filter2 && data) {
|
||||
const result = this.cache.get(this.entity, {
|
||||
data,
|
||||
filter: inModi ? filter : filter2,
|
||||
filter: inModiNextBranch ? filter : filter2,
|
||||
sorter,
|
||||
}, this.sr);
|
||||
|
||||
|
|
@ -2291,41 +2291,33 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
return node;
|
||||
}
|
||||
|
||||
private checkSingleNodeIsModiNode(node: SingleNode<ED, keyof ED>) {
|
||||
const id = node.getId();
|
||||
if (id) {
|
||||
const modies = this.cache.get('modi', {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: {
|
||||
targetEntity: node.getEntity() as string,
|
||||
action: 'create',
|
||||
data: {
|
||||
id,
|
||||
},
|
||||
iState: 'active',
|
||||
}
|
||||
});
|
||||
return modies.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
checkIsModiNode(path: string) {
|
||||
// 判断当前结点是否在:next的路径上(且有前项结点,两者同时满足就不用refresh了)
|
||||
checkIsInModiNextBranch(path: string) {
|
||||
if (!path.includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
return false;
|
||||
}
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof SingleNode) {
|
||||
return this.checkSingleNodeIsModiNode(node);
|
||||
const paths = path.split('.');
|
||||
|
||||
if (paths[0].includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
// 根结点就是:next,这时候还是要取的
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
assert(node instanceof ListNode);
|
||||
const parent = node.getParent();
|
||||
assert(parent instanceof SingleNode);
|
||||
return this.checkSingleNodeIsModiNode(parent);
|
||||
let iter = 1;
|
||||
while(iter < paths.length) {
|
||||
if (paths[iter].includes(MODI_NEXT_PATH_SUFFIX)) {
|
||||
const path2 = paths.slice(0, iter) + paths[iter].replace(MODI_NEXT_PATH_SUFFIX, '');
|
||||
|
||||
const node = this.findNode(path2);
|
||||
if (node) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
iter ++;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private findNode(path: string) {
|
||||
|
|
@ -2376,33 +2368,11 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
return this.cache.begin()!;
|
||||
}
|
||||
|
||||
redoBranchOperations(path: string) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
|
||||
const rootNode = this.root[root!];
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
|
||||
redoBranchModis(path: string) {
|
||||
const { root } = analyzePath(path);
|
||||
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
|
||||
getFreshValue(path: string) {
|
||||
const node = this.findNode(path);
|
||||
if (node instanceof ListNode) {
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(includeModi);
|
||||
const inModiNextBranch = path.includes(MODI_NEXT_PATH_SUFFIX) && !path.endsWith(MODI_NEXT_PATH_SUFFIX);
|
||||
return node.getFreshValue(inModiNextBranch);
|
||||
}
|
||||
assert(node instanceof SingleNode);
|
||||
return node.getFreshValue();
|
||||
|
|
@ -2724,6 +2694,51 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
return operations;
|
||||
}
|
||||
|
||||
private cachedOperations: Record<string, {
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}[]> = {};
|
||||
|
||||
private cachedModis: Record<string, {
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}[]> = {};
|
||||
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,composeOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchOperations(path: string) {
|
||||
const paths = path.split('.');
|
||||
const root = paths.shift();
|
||||
|
||||
const rootNode = this.root[root!];
|
||||
|
||||
const opers = rootNode.composeOperations(paths);
|
||||
if (opers) {
|
||||
this.cache.redoOperation(opers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 这个函数在reRender时可能会反复调用,getModiOperations很消耗性能,在这里要做个缓存
|
||||
* @param path
|
||||
*/
|
||||
redoBranchModis(path: string) {
|
||||
const { root } = analyzePath(path);
|
||||
|
||||
const rootNode = this.root[root];
|
||||
const includeModi = path.includes(MODI_NEXT_PATH_SUFFIX);
|
||||
if (includeModi) {
|
||||
const modiOperations = rootNode.getModiOperations();
|
||||
modiOperations && this.cache.redoOperation(modiOperations);
|
||||
}
|
||||
}
|
||||
|
||||
tryExecute(path: string, action?: string) {
|
||||
|
||||
}
|
||||
|
||||
async execute<T extends keyof ED>(path: string, action?: ED[T]['Action'], opers?: Array<{
|
||||
entity: keyof ED,
|
||||
operation: ED[keyof ED]['Operation'],
|
||||
|
|
@ -2735,7 +2750,7 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
|
||||
let pollute = false;
|
||||
try {
|
||||
let operations = node.composeOperations() || [];
|
||||
let operations = this.getOperations(path) || [];
|
||||
if (opers) {
|
||||
operations.push(...opers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -518,7 +518,8 @@ export function reRender<
|
|||
const oakLoadingMore = this.features.runningTree.isLoadingMore(this.state.oakFullpath);
|
||||
const oakLoading = !oakLoadingMore && this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 这个很耗时,让用户去相应要execute的页面上调用
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// 现在取数据需要把runningTree上的更新应用了再取,判定actions也一样
|
||||
let rollback = this.features.runningTree.begin();
|
||||
try {
|
||||
|
|
@ -599,7 +600,6 @@ export function reRender<
|
|||
}
|
||||
};
|
||||
Object.assign(data, {
|
||||
oakExecutable,
|
||||
oakDirty,
|
||||
oakLoading,
|
||||
oakLoadingMore,
|
||||
|
|
@ -635,11 +635,11 @@ export function reRender<
|
|||
*/
|
||||
const oakDirty = this.features.runningTree.isDirty(this.state.oakFullpath);
|
||||
const oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
|
||||
const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
// const oakExecutable = !oakExecuting && this.tryExecute();
|
||||
const oakLoading = this.features.runningTree.isLoading(this.state.oakFullpath);
|
||||
Object.assign(data, {
|
||||
oakDirty,
|
||||
oakExecutable,
|
||||
// oakExecutable,
|
||||
oakExecuting,
|
||||
oakLoading,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -711,7 +711,7 @@ const oakBehavior = Behavior<
|
|||
const { oakFullpath } = this.state;
|
||||
if (
|
||||
oakFullpath && !this.oakOption.stale &&
|
||||
!this.features.runningTree.checkIsModiNode(
|
||||
!this.features.runningTree.checkIsInModiNextBranch(
|
||||
oakFullpath
|
||||
) &&
|
||||
!this.features.runningTree.isListDescandent(
|
||||
|
|
@ -1122,7 +1122,7 @@ export function createComponent<
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
|
|
|
|||
|
|
@ -980,7 +980,7 @@ export function createComponent<
|
|||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
@ -1050,7 +1050,7 @@ export function createComponent<
|
|||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !option.stale &&
|
||||
!features.runningTree.checkIsModiNode(oakFullpath) &&
|
||||
!features.runningTree.checkIsInModiNextBranch(oakFullpath) &&
|
||||
!features.runningTree.isListDescandent(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -558,7 +558,7 @@ export type OakComponentData<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED
|
||||
> = {
|
||||
oakExecutable: boolean | Error;
|
||||
// oakExecutable: boolean | Error;
|
||||
oakExecuting: boolean;
|
||||
oakFocused: {
|
||||
attr: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue