Skip to content

Commit

Permalink
feat: add loader in search-results (#209)
Browse files Browse the repository at this point in the history
Part of #191
  • Loading branch information
Kout95 authored Jul 4, 2024
1 parent 0066549 commit 0ee92b5
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 6 deletions.
4 changes: 2 additions & 2 deletions frontend/public/off.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@
color: rgba(0,0,0,.75);
}
/* search results styling */
searchalicious-results::part(results) {
searchalicious-results::part(results), searchalicious-results::part(results-loading) {
list-style: none;
display: grid;
gap: 5px;
gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
margin: 0;
padding: 0;
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/mixins/search-ctl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
SearchaliciousHistoryMixin,
} from './history';
import {SearchaliciousChart} from '../search-chart';
import {canResetSearch, isSearchChanged} from '../signals';
import {canResetSearch, isSearchChanged, isSearchLoading} from '../signals';
import {SignalWatcher} from '@lit-labs/preact-signals';
import {isTheSameSearchName} from '../utils/search';

Expand Down Expand Up @@ -490,6 +490,9 @@ export const SearchaliciousSearchMixin = <T extends Constructor<LitElement>>(
async search(page = 1) {
const {searchUrl, method, params, history} = this._searchUrl(page);
setCurrentURLHistory(history);

isSearchLoading(this.name).value = true;

let response;
if (method === 'GET') {
response = await fetch(
Expand All @@ -512,6 +515,7 @@ export const SearchaliciousSearchMixin = <T extends Constructor<LitElement>>(
this._currentPage = data.page;
this._pageCount = data.page_count;

isSearchLoading(this.name).value = false;
this.updateSearchSignals();

// dispatch an event with the results
Expand Down
62 changes: 59 additions & 3 deletions frontend/src/search-results.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {LitElement, html} from 'lit';
import {LitElement, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {repeat} from 'lit/directives/repeat.js';

Expand All @@ -9,6 +9,8 @@ import {
MultipleResultTemplateError,
} from './errors';
import {localized, msg} from '@lit/localize';
import {SignalWatcher} from '@lit-labs/preact-signals';
import {isSearchLoading} from './signals';

// we need it to declare functions
type htmlType = typeof html;
Expand All @@ -23,9 +25,31 @@ type htmlType = typeof html;
*/
@customElement('searchalicious-results')
@localized()
export class SearchaliciousResults extends SearchaliciousResultCtlMixin(
LitElement
export class SearchaliciousResults extends SignalWatcher(
SearchaliciousResultCtlMixin(LitElement)
) {
static override styles = css`
.loading {
height: 300px;
border-radius: 8px;
animation: loading 2.25s ease infinite;
box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
background-color: var(--first-loading-color, #cacaca);
}
@keyframes loading {
0% {
background-color: var(--first-loading-color, #cacaca);
}
50% {
background-color: var(--second-loading-color, #bbbbbb);
}
100% {
background-color: var(--first-loading-color, #cacaca);
}
}
`;

// the last search results
@state()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -35,6 +59,16 @@ export class SearchaliciousResults extends SearchaliciousResultCtlMixin(
@property({attribute: 'result-id'})
resultId = '';

@property({attribute: 'loadind-card-size', type: Number})
loadingCardSize = 200;

/**
* The parent width, used to compute the number of loading cards to display
*/
get parentWidth() {
return this.parentElement?.offsetWidth || 1200;
}

/**
* A function rendering a single result. We define this just to get it's prototype right.
*
Expand Down Expand Up @@ -109,9 +143,31 @@ export class SearchaliciousResults extends SearchaliciousResultCtlMixin(
return slots[0].innerHTML;
}

/**
* Render the loading cards
* We display 2 columns of loading cards
*/
renderLoading() {
// we take the row width and display 2 columns of loading cards
const numCols = Math.floor(this.parentWidth / this.loadingCardSize) * 2;

return html`
<slot name="loading">
<ul part="results-loading">
${Array(numCols)
.fill(0)
.map(() => html`<li part="result-loading" class="loading"></li>`)}
</ul>
</slot>
`;
}

override render() {
if (this.results.length) {
return this.renderResults();
// if we are loading, we display the loading cards
} else if (isSearchLoading(this.searchName).value) {
return this.renderLoading();
} else if (this.searchLaunched) {
return html`<slot name="no-results">${this.noResults}</slot>`;
} else {
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/signals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const _isSearchChanged: Record<string, Signal> = {} as Record<
Signal<boolean>
>;

/**
* Signals to indicate if the search is loading.
*/
const _isSearchLoading: Record<string, Signal> = {} as Record<
string,
Signal<boolean>
>;

/**
* Function to get or create a signal by search name.
* If the signal does not exist, it creates it.
Expand All @@ -37,6 +45,7 @@ const _getOrCreateSignal = (
/**
* Function to get the signal to indicate if the search has changed.
* It is use by reset-button to know if it should be displayed.
* @param searchName
*/
export const canResetSearch = (searchName: string) => {
return _getOrCreateSignal(_canResetSearch, searchName);
Expand All @@ -45,7 +54,17 @@ export const canResetSearch = (searchName: string) => {
/**
* Function to get the signal to indicate if the search has changed.
* it is used by the search button to know if it should be displayed.
* @param searchName
*/
export const isSearchChanged = (searchName: string) => {
return _getOrCreateSignal(_isSearchChanged, searchName);
};

/**
* Function to get the signal to indicate if the search is loading.
* The search-results utilize this to determine whether the loading card should be displayed.
* @param searchName
*/
export const isSearchLoading = (searchName: string) => {
return _getOrCreateSignal(_isSearchLoading, searchName);
};

0 comments on commit 0ee92b5

Please sign in to comment.