mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-15 02:33:22 +00:00
Make a generic AjaxSelect abstract class
This commit is contained in:
parent
f78b968075
commit
0af3505c2a
@ -112,42 +112,72 @@ class AutocompleteSelect extends inheritHtmlElement("select") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@registerComponent("user-ajax-select")
|
abstract class AjaxSelect extends AutocompleteSelect {
|
||||||
export class UserAjaxSelect extends AutocompleteSelect {
|
protected filter?: (items: TomOption[]) => TomOption[] = null;
|
||||||
public filter?: <T>(items: T[]) => T[];
|
|
||||||
|
|
||||||
protected minCharNumberForSearch = 2;
|
protected minCharNumberForSearch = 2;
|
||||||
|
|
||||||
|
protected abstract valueField: string;
|
||||||
|
protected abstract labelField: string;
|
||||||
|
protected abstract renderOption(
|
||||||
|
item: TomOption,
|
||||||
|
sanitize: typeof escape_html,
|
||||||
|
): string;
|
||||||
|
protected abstract renderItem(item: TomOption, sanitize: typeof escape_html): string;
|
||||||
|
protected abstract search(query: string): Promise<TomOption[]>;
|
||||||
|
|
||||||
|
public setFilter(filter?: (items: TomOption[]) => TomOption[]) {
|
||||||
|
this.filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getLoadFunction() {
|
||||||
|
// this will be replaced by TomSelect if we don't wrap it that way
|
||||||
|
return async (query: string, callback: TomLoadCallback) => {
|
||||||
|
const resp = await this.search(query);
|
||||||
|
if (this.filter) {
|
||||||
|
callback(this.filter(resp), []);
|
||||||
|
} else {
|
||||||
|
callback(resp, []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected tomSelectSettings(): RecursivePartial<TomSettings> {
|
protected tomSelectSettings(): RecursivePartial<TomSettings> {
|
||||||
return {
|
return {
|
||||||
...super.tomSelectSettings(),
|
...super.tomSelectSettings(),
|
||||||
hideSelected: true,
|
hideSelected: true,
|
||||||
diacritics: true,
|
diacritics: true,
|
||||||
duplicates: false,
|
duplicates: false,
|
||||||
valueField: "id",
|
valueField: this.valueField,
|
||||||
labelField: "display_name",
|
labelField: this.labelField,
|
||||||
searchField: [], // Disable local search filter and rely on tested backend
|
searchField: [], // Disable local search filter and rely on tested backend
|
||||||
load: (query: string, callback: TomLoadCallback) => {
|
load: this.getLoadFunction(),
|
||||||
userSearchUsers({
|
|
||||||
query: {
|
|
||||||
search: query,
|
|
||||||
},
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.data) {
|
|
||||||
if (this.filter) {
|
|
||||||
callback(this.filter(response.data.results), []);
|
|
||||||
} else {
|
|
||||||
callback(response.data.results, []);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback([], []);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: {
|
render: {
|
||||||
...super.tomSelectSettings().render,
|
...super.tomSelectSettings().render,
|
||||||
option: (item: UserProfileSchema, sanitize: typeof escape_html) => {
|
option: this.renderOption,
|
||||||
return `<div class="select-item">
|
item: this.renderItem,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@registerComponent("user-ajax-select")
|
||||||
|
export class UserAjaxSelect extends AjaxSelect {
|
||||||
|
protected valueField = "id";
|
||||||
|
protected labelField = "display_name";
|
||||||
|
|
||||||
|
protected async search(query: string): Promise<TomOption[]> {
|
||||||
|
const resp = await userSearchUsers({ query: { search: query } });
|
||||||
|
if (resp.data) {
|
||||||
|
return resp.data.results;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
protected tomSelectSettings(): RecursivePartial<TomSettings> {
|
||||||
|
return super.tomSelectSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected renderOption(item: UserProfileSchema, sanitize: typeof escape_html) {
|
||||||
|
return `<div class="select-item">
|
||||||
<img
|
<img
|
||||||
src="${sanitize(item.profile_pict)}"
|
src="${sanitize(item.profile_pict)}"
|
||||||
alt="${sanitize(item.display_name)}"
|
alt="${sanitize(item.display_name)}"
|
||||||
@ -155,11 +185,9 @@ export class UserAjaxSelect extends AutocompleteSelect {
|
|||||||
/>
|
/>
|
||||||
<span class="select-item-text">${sanitize(item.display_name)}</span>
|
<span class="select-item-text">${sanitize(item.display_name)}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
},
|
}
|
||||||
item: (item: UserProfileSchema, sanitize: typeof escape_html) => {
|
|
||||||
return `<span><i class="fa fa-times"></i>${sanitize(item.display_name)}</span>`;
|
protected renderItem(item: UserProfileSchema, sanitize: typeof escape_html) {
|
||||||
},
|
return `<span><i class="fa fa-times"></i>${sanitize(item.display_name)}</span>`;
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import type { Client, Options, RequestResult } from "@hey-api/client-fetch";
|
import type { Client, Options, RequestResult } from "@hey-api/client-fetch";
|
||||||
import { client } from "#openapi";
|
import { client } from "#openapi";
|
||||||
|
|
||||||
interface PaginatedResponse<T> {
|
export interface PaginatedResponse<T> {
|
||||||
count: number;
|
count: number;
|
||||||
next: string | null;
|
next: string | null;
|
||||||
previous: string | null;
|
previous: string | null;
|
||||||
results: T[];
|
results: T[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PaginatedRequest {
|
export interface PaginatedRequest {
|
||||||
query?: {
|
query?: {
|
||||||
page?: number;
|
page?: number;
|
||||||
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
// biome-ignore lint/style/useNamingConvention: api is in snake_case
|
||||||
|
@ -177,7 +177,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
|
|||||||
} as PicturesFetchPicturesData)
|
} as PicturesFetchPicturesData)
|
||||||
).map(PictureWithIdentifications.fromPicture);
|
).map(PictureWithIdentifications.fromPicture);
|
||||||
this.selector = this.$refs.search;
|
this.selector = this.$refs.search;
|
||||||
this.selector.filter = (users: UserProfileSchema[]) => {
|
this.selector.setFilter((users: UserProfileSchema[]) => {
|
||||||
const resp: UserProfileSchema[] = [];
|
const resp: UserProfileSchema[] = [];
|
||||||
const ids = [
|
const ids = [
|
||||||
...(this.currentPicture.identifications || []).map(
|
...(this.currentPicture.identifications || []).map(
|
||||||
@ -190,7 +190,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return resp;
|
return resp;
|
||||||
};
|
});
|
||||||
this.currentPicture = this.pictures.find(
|
this.currentPicture = this.pictures.find(
|
||||||
(i: PictureSchema) => i.id === config.firstPictureId,
|
(i: PictureSchema) => i.id === config.firstPictureId,
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user