Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Field profile merging maxhaibt fork #196

Merged
merged 2 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ lerna-debug.log
**/.lsp
**/.clj-kondo

mobile/package-lock.json
23 changes: 11 additions & 12 deletions core/src/datastore/datastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ export class Datastore {
* @returns {Promise<IdaiFieldFindResult>} result object
* @throws [GENERIC_ERROR (, cause: any)] - in case of error, optionally including a cause
*/
public find: Datastore.Find = async (query: Query): Promise<Datastore.FindResult> => {

const { ids } = this.findIds(query);
public find: Datastore.Find = async (query: Query, logic?: 'AND' | 'OR'): Promise<Datastore.FindResult> => {
const effectiveLogic = logic || 'AND';
const { ids } = this.findIds(query, effectiveLogic);
const { documents, totalCount } = await this.getDocumentsForIds(ids, query.limit, query.offset);

return {
Expand All @@ -240,17 +240,17 @@ export class Datastore {
* @param query
* @returns
*/
public findIds: Datastore.FindIds = (query: Query): Datastore.FindIdsResult => {

const orderedResults: string[] = this.getIds(query);

public findIds: Datastore.FindIds = (query: Query, logic: 'AND' | 'OR' = 'AND'): Datastore.FindIdsResult => {
const orderedResults: string[] = this.getIds(query, logic); // Pass the logic parameter

return {
ids: orderedResults,
totalCount: orderedResults.length
};
}



/**
* Fetches a specific revision directly from the underlying datastore layer.
* Bypasses the cache and alway returns a new instance.
Expand All @@ -272,10 +272,9 @@ export class Datastore {
* If two or more documents have the same last modified date, their sort order is unspecified.
* The modified date is taken from document.modified[document.modified.length-1].date
*/
private getIds(query: Query): string[] {

private getIds(query: Query, logic: 'AND' | 'OR'): string[] {
try {
return this.indexFacade.find(query);
return this.indexFacade.find(query, logic); // Pass the logic parameter to IndexFacade's find method
} catch (err) {
throw [DatastoreErrors.GENERIC_ERROR, err];
}
Expand Down Expand Up @@ -381,9 +380,9 @@ export namespace Datastore {

export type Get = (id: string, options?: { skipCache?: boolean, conflicts?: boolean }) => Promise<Document>;

export type Find = (query: Query) => Promise<FindResult>;
export type Find = (query: Query, logic?: 'AND'|'OR') => Promise<FindResult>;

export type FindIds = (query: Query) => FindIdsResult;
export type FindIds = (query: Query, logic?: 'AND'|'OR') => FindIdsResult;

export type Update = (document: Document, squashRevisionsIds?: string[]) => Promise<Document>;

Expand Down
12 changes: 9 additions & 3 deletions core/src/index/index-facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,26 @@ export class IndexFacade {

private observers: Array<Observer<Document>> = [];
private indexItems: { [resourceId: string]: IndexItem } = {};
private defaultLogic: 'AND' | 'OR' = 'OR';


constructor(private constraintIndex: ConstraintIndex,
private fulltextIndex: FulltextIndex,
private projectConfiguration: ProjectConfiguration,
private showWarnings: boolean) {}
private showWarnings: boolean,
defaultLogic: 'AND' | 'OR' = 'OR'
) {
this.defaultLogic = defaultLogic;
}


public changesNotifications = (): Observable<Document|undefined> => ObserverUtil.register(this.observers);


public find(query: Query): Array<string /*resourceId*/> {
public find(query: Query, logic: 'AND' | 'OR' = this.defaultLogic): Array<string /*resourceId*/> {

const queryResult: Array<Resource.Id> = performQuery(query, this.constraintIndex, this.fulltextIndex);
console.log('find', query, logic)
const queryResult: Array<Resource.Id> = performQuery(query, this.constraintIndex, this.fulltextIndex, logic);
return this.getSortedResult(query, queryResult);
}

Expand Down
39 changes: 26 additions & 13 deletions core/src/index/perform-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import { ResultSets } from './result-sets';
*/
export function performQuery(query: Query,
constraintIndex: ConstraintIndex,
fulltextIndex: FulltextIndex): Array<Resource.Id> {
fulltextIndex: FulltextIndex,
logic: 'AND' | 'OR' = 'OR'): Array<Resource.Id> {

let resultSets = performConstraints(
constraintIndex,
query.constraints ? query.constraints : {}
query.constraints ? query.constraints : {},
logic
);

resultSets = ResultSets.containsOnlyEmptyAddSets(resultSets)
Expand All @@ -40,21 +42,32 @@ function performFulltext(fulltextIndex: FulltextIndex,
return resultSets;
}

//This seems to be the place where the query is actually performed upon the pouchdb.TOMORROW

function performConstraints(constraintIndex: ConstraintIndex,
constraints: { [name: string]: Constraint|string|string[] }): ResultSets<Resource.Id> {

return Object.keys(constraints)
.reduce((resultSets, name: string) => {
constraints: { [name: string]: Constraint|string|string[] },
logic: 'AND' | 'OR' = 'OR'): ResultSets<Resource.Id> {
let resultSets = ResultSets.make<Resource.Id>();
if (logic === 'OR') {

let orSets: Array<Array<Resource.Id>> = [];
for (let name in constraints) {
const { subtract, value, searchRecursively } = Constraint.convert(constraints[name]);

const get = !searchRecursively
? ConstraintIndex.get
: ConstraintIndex.getWithDescendants;

const get = !searchRecursively ? ConstraintIndex.get : ConstraintIndex.getWithDescendants;
const indexItemIds = get(constraintIndex, name, value);
orSets.push(indexItemIds);
}
resultSets.addSets.push(ResultSets.unionSets(orSets));
} else {
// Existing AND logic
Object.keys(constraints).forEach(name => {
const { subtract, value, searchRecursively } = Constraint.convert(constraints[name]);
const get = !searchRecursively ? ConstraintIndex.get : ConstraintIndex.getWithDescendants;
const indexItemIds = get(constraintIndex, name, value);

ResultSets.combine(resultSets, indexItemIds, subtract);
return resultSets;
}, ResultSets.make<Resource.Id>());
});
}

return resultSets;
}
4 changes: 4 additions & 0 deletions core/src/index/result-sets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,8 @@ export module ResultSets {

return union(resultSets.addSets);
}

export function unionSets<T>(resultSets: Array<Array<T>>): Array<T> {
return tsfun.union(resultSets);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ export class NavigationService {

if (!document.resource.id) return false; // do not show as long as it is not saved
if (this.viewFacade.isInExtendedSearchMode()) return false;

return (this.projectConfiguration
const relations = this.projectConfiguration
.getRelationsForRangeCategory(document.resource.category)
.map(relationDefinition => relationDefinition.name)
.indexOf('liesWithin') !== -1);
.map(relationDefinition => relationDefinition.name);

return (relations.indexOf('liesWithin') !== -1 || relations.indexOf('isPresentIn') !== -1);
}


Expand Down
104 changes: 63 additions & 41 deletions desktop/src/app/components/resources/view/documents-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,34 +104,40 @@ export class DocumentsManager {
}


public async moveInto(document: FieldDocument|string|undefined, resetFiltersAndSelection: boolean = false,
rebuildNavigationPath: boolean = false) {

try {
if (isString(document)) {
document = (await this.datastore.get(document)) as FieldDocument;
} else if (document) {
await this.datastore.get(document.resource.id);
}
} catch (errWithParams) {
throw errWithParams; // Throw error if the resource has been deleted from remote
public async moveInto(document: FieldDocument|string|undefined, resetFiltersAndSelection: boolean = false,
rebuildNavigationPath: boolean = false) {

let documentCategory: string | undefined;
try {
if (isString(document)) {
document = (await this.datastore.get(document)) as FieldDocument;
documentCategory = document.resource.category;
} else if (document) {
const fetchedDocument = (await this.datastore.get(document.resource.id)) as FieldDocument;
documentCategory = fetchedDocument.resource.category;
}
} catch (errWithParams) {
throw errWithParams; // Throw error if the resource has been deleted from remote
}

if (rebuildNavigationPath && document) {
await this.resourcesStateManager.updateNavigationPathForDocument(document, true);
}
if (rebuildNavigationPath && document) {
await this.resourcesStateManager.updateNavigationPathForDocument(document, true);
}

await this.resourcesStateManager.moveInto(document);
await this.resourcesStateManager.moveInto(document);

if (resetFiltersAndSelection) {
await this.setCategoryFilters([], false);
await this.setQueryString('', false);
await this.deselect();
await this.populateDocumentList();
} else {
await this.populateAndDeselectIfNecessary();
}
const logic = documentCategory === 'Profile' ? 'OR' : 'AND';

if (resetFiltersAndSelection) {
await this.setCategoryFilters([], false);
await this.setQueryString('', false);
await this.deselect();
await this.populateDocumentList(true, logic); // Pass the OR logic flag
} else {
await this.populateAndDeselectIfNecessary(); // Pass the OR logic flag
}
}



public deselect() {
Expand Down Expand Up @@ -197,7 +203,7 @@ export class DocumentsManager {
}


public async populateDocumentList(reset: boolean = true) {
public async populateDocumentList(reset: boolean = true, logic?: 'AND' | 'OR') {

this.populateInProgress = true;
if (this.loading) this.loading.start();
Expand All @@ -211,7 +217,8 @@ export class DocumentsManager {

this.currentQueryId = new Date().toISOString();
const queryId = this.currentQueryId;
const result = await this.createUpdatedDocumentList();
const effectiveLogic = logic || 'AND';
const result = await this.createUpdatedDocumentList(effectiveLogic);

await this.updateChildrenCountMap(result.documents as Array<FieldDocument>);

Expand All @@ -222,31 +229,35 @@ export class DocumentsManager {
}

this.documents = result.documents as Array<FieldDocument>;
console.log('This is',this.documents)
this.totalDocumentCount = result.totalCount;

this.populateInProgress = false;
ObserverUtil.notify(this.populateDocumentsObservers, this.documents);
}


public async createUpdatedDocumentList(): Promise<Datastore.FindResult> {

public async createUpdatedDocumentList(logic?: 'AND' | 'OR'): Promise<Datastore.FindResult> {
const isRecordedInTarget = this.makeIsRecordedInTarget();
if (!isRecordedInTarget && !this.resourcesStateManager.isInSpecialView()) {
return { documents: [], ids: [], totalCount: 0 };
}


const operationId: string|undefined = this.resourcesStateManager.isInSpecialView()
? undefined
: this.resourcesStateManager.get().view;


const query = DocumentsManager.buildQuery(
operationId,
this.resourcesStateManager,
this.getAllowedTypeNames()
);

return (await this.fetchDocuments(query));
console.log(query)
const effectiveLogic = logic || 'AND';
return (await this.fetchDocuments(query, effectiveLogic));
}


Expand Down Expand Up @@ -345,10 +356,10 @@ export class DocumentsManager {
}


private async fetchDocuments(query: Query): Promise<Datastore.FindResult> {
private async fetchDocuments(query: Query, logic: 'AND' | 'OR' = 'AND'): Promise<Datastore.FindResult> {

try {
return await this.datastore.find(query);
return await this.datastore.find(query, logic);
} catch (errWithParams) {
DocumentsManager.handleFindErr(errWithParams, query);
return { documents: [], ids: [], totalCount: 0 };
Expand All @@ -364,14 +375,15 @@ export class DocumentsManager {
const state = resourcesStateManager.get();
const categoryFilters = ResourcesState.getCategoryFilters(state);
const customConstraints = ResourcesState.getCustomConstraints(state);

const currentView = state.view;
return {
q: ResourcesState.getQueryString(state),
constraints: DocumentsManager.buildConstraints(
customConstraints,
operationId,
ResourcesState.getNavigationPath(state).selectedSegmentId,
extendedSearchMode
extendedSearchMode,
currentView
),
categories: (categoryFilters.length > 0)
? categoryFilters
Expand All @@ -384,22 +396,32 @@ export class DocumentsManager {


private static buildConstraints(customConstraints: Constraints,
operationId: string|undefined,
liesWithinId: string|undefined,
isInExtendedSearchMode: boolean): Constraints {
operationId: string|undefined,
liesWithinId: string|undefined,
isInExtendedSearchMode: boolean,
currentView: string): Constraints {

const constraints = clone(customConstraints);

if (!isInExtendedSearchMode) {
if (liesWithinId) constraints[CHILDOF_CONTAIN] = liesWithinId;
else if (operationId) constraints[CHILDOF_CONTAIN] = operationId as any;
else constraints[CHILDOF_EXIST] = UNKNOWN;
if (!isInExtendedSearchMode) {
if (liesWithinId) {
constraints[CHILDOF_CONTAIN] = liesWithinId ;
constraints['isPresentIn:contain'] = liesWithinId;
}
else if (operationId) {
constraints[CHILDOF_CONTAIN] = operationId as any;
} else {
constraints[CHILDOF_EXIST] = UNKNOWN;
}

} else {
if (operationId) constraints[CHILDOF_CONTAIN] = { value: operationId, searchRecursively: true } as any;
}
return constraints;
}
}




private static handleFindErr(errWithParams: Array<string>, query: Query) {

Expand Down
Loading
Loading