Skip to content
Open
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
18 changes: 11 additions & 7 deletions projects/natural/src/lib/classes/abstract-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ export class NaturalAbstractList<
}

/**
* Delete multiple items at once
* Delete multiple items at once, and then refresh the list of items automatically
*/
protected bulkDelete(): Observable<void> {
const subject = new Subject<void>();
Expand All @@ -581,12 +581,16 @@ export class NaturalAbstractList<
// never call this method.
const selection = this.selection.selected as {id: string}[];

this.service.delete(selection).subscribe(() => {
this.selection.clear();
this.alertService.info($localize`Supprimé`);
subject.next();
subject.complete();
});
this.service
.delete(selection, {
refetchQueries: this.service.allQuery ? [this.service.allQuery] : [],
})
.subscribe(() => {
this.selection.clear();
this.alertService.info($localize`Supprimé`);
subject.next();
subject.complete();
});
}
});

Expand Down
36 changes: 0 additions & 36 deletions projects/natural/src/lib/services/abstract-model.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {type Literal} from '../types/types';
import {NullService} from '../testing/null.service';
import {Apollo} from 'apollo-angular';
import {takeWhile} from 'rxjs/operators';
import {type ObservableQuery} from '@apollo/client';

const observableError =
'Cannot use Observable as variables. Instead you should use .subscribe() to call the method with a real value';
Expand All @@ -27,41 +26,6 @@ describe('NaturalAbstractModelService', () => {
service = TestBed.inject(PostService);
});

it('should be delay deleted resolving', fakeAsync(() => {
const apollo = TestBed.inject(Apollo);

let resolveMyPromise: (value: ObservableQuery.Result<any>[]) => void;
apollo.client.refetchObservableQueries = () =>
new Promise<ObservableQuery.Result<any>[]>(resolve => {
resolveMyPromise = resolve;
});

let resolved = false;
let completed = false;
service.delete([{id: '123'}]).subscribe({
next: () => {
resolved = true;
},
complete: () => {
completed = true;
},
});

expect(resolved).toBeFalse();
expect(completed).toBeFalse();

tick(2000);

expect(resolved).toBeFalse();
expect(completed).toBeFalse();

resolveMyPromise!([]);
tick(2000);

expect(resolved).toBeTrue();
expect(completed).toBeTrue();
}));

it('should be created', () => {
expect(service).toBeTruthy();
});
Expand Down
47 changes: 27 additions & 20 deletions projects/natural/src/lib/services/abstract-model.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import {Apollo, gql, onlyCompleteData} from 'apollo-angular';
import {type ApolloLink, NetworkStatus, type ObservableQuery, type WatchQueryFetchPolicy} from '@apollo/client';
import {
type ApolloLink,
NetworkStatus,
type ObservableQuery,
type OperationVariables,
type WatchQueryFetchPolicy,
} from '@apollo/client';
import {
type AbstractControl,
type AsyncValidatorFn,
Expand All @@ -10,7 +16,7 @@ import {
import {type DocumentNode} from 'graphql';
import {merge, pick} from 'es-toolkit';
import {defaults} from 'es-toolkit/compat';
import {catchError, combineLatest, EMPTY, first, from, Observable, of, type OperatorFunction} from 'rxjs';
import {catchError, combineLatest, EMPTY, first, Observable, of, type OperatorFunction} from 'rxjs';
import {debounceTime, filter, map, shareReplay, startWith, switchMap, takeWhile, tap} from 'rxjs/operators';
import {NaturalQueryVariablesManager, type QueryVariables} from '../classes/query-variable-manager';
import {type Literal} from '../types/types';
Expand All @@ -32,6 +38,11 @@ export type FormControls = Record<string, AbstractControl>;

export type WithId<T> = {id: string} & T;

export type MutateOptionsWithoutVariables<Tcreate, Vcreate extends OperationVariables> = Omit<
Apollo.MutateOptions<Tcreate, Vcreate>,
'mutation' | 'variables'
>;

export abstract class NaturalAbstractModelService<
Tone,
Vone extends {id: string},
Expand Down Expand Up @@ -68,7 +79,7 @@ export abstract class NaturalAbstractModelService<
public constructor(
protected readonly name: string,
protected readonly oneQuery: DocumentNode | null,
protected readonly allQuery: DocumentNode | null,
public readonly allQuery: DocumentNode | null,
protected readonly createMutation: DocumentNode | null,
protected readonly updateMutation: DocumentNode | null,
protected readonly deleteMutation: DocumentNode | null,
Expand Down Expand Up @@ -362,9 +373,12 @@ export abstract class NaturalAbstractModelService<
}

/**
* Create an object in DB and then refetch the list of objects
* Create an object in DB
*/
public create(object: Vcreate['input']): Observable<Tcreate> {
public create(
object: Vcreate['input'],
options: MutateOptionsWithoutVariables<Literal, Literal> = {},
): Observable<Tcreate> {
this.throwIfObservable(object);
this.throwIfNotQuery(this.createMutation);

Expand All @@ -375,15 +389,11 @@ export abstract class NaturalAbstractModelService<

return this.apollo
.mutate<Tcreate, Vcreate>({
...(options as MutateOptionsWithoutVariables<Tcreate, Vcreate>),
mutation: this.createMutation,
variables: variables,
})
.pipe(
map(result => {
this.apollo.client.refetchObservableQueries();
return this.mapCreation(result);
}),
);
.pipe(map(result => this.mapCreation(result)));
}

/**
Expand Down Expand Up @@ -430,7 +440,10 @@ export abstract class NaturalAbstractModelService<
/**
* Delete objects and then refetch the list of objects
*/
public delete(objects: {id: string}[]): Observable<Tdelete> {
public delete(
objects: {id: string}[],
options: MutateOptionsWithoutVariables<Literal, Literal> = {},
): Observable<Tdelete> {
this.throwIfObservable(objects);
this.throwIfNotQuery(this.deleteMutation);

Expand All @@ -449,17 +462,11 @@ export abstract class NaturalAbstractModelService<

return this.apollo
.mutate<Tdelete, Vdelete>({
...(options as MutateOptionsWithoutVariables<Tdelete, Vdelete>),
mutation: this.deleteMutation,
variables: variables,
})
.pipe(
// Delay the observable until Apollo refetch is completed
switchMap(result => {
const mappedResult = this.mapDelete(result);

return from(this.apollo.client.refetchObservableQueries()).pipe(map(() => mappedResult));
}),
);
.pipe(map(result => this.mapDelete(result)));
}

/**
Expand Down