Files
directus/app/src/api.ts
Rijk van Zanten f64a5bef7e Add new advanced filters experience (#8570)
* Remove advanced filter sidebar detail

So long, and thanks for all the fish.

* Remove filter conversion logic

* Start replacing/removing old skool filters

* Add inline mode for usages in search bar

* Make filter work in header bar

* Emit empty string as null in filter

* Move shared filter types to shared

* Upgrade use-items

* Fix manual sort on tabular

* Cleanup styling in search bar usage

* Tweak styling

* Fix filtering issues

* Update cards

* Remove activeFilterCount from tabular

* Update maps to work with new filters

* Update calendar to new filter/sort structure

* Fix activity module nav/search

* Fix no-results message

* Update file library filtering

* Finalize user search

* Allow filtering in drawer-collection

* Handle cancelled responses semi-gracefully

* Add loading start state timeout

* Replace sort type in api

* Last commit before redoing a bunch

* Finish new visual style

* Remove unused rounded prop from v-menu

* Tweak sizing

* Enough size tweaking for now

* Count all filter operators instead of top

* Fix archive casting

* Fix api build

* Add merge filters util

* Split filter in user vs system

* Fix export sidebar detail

* Show field label on permissions configuration

* Add migration for filter/sort

* Use filters in insights
2021-10-07 18:06:03 -04:00

110 lines
3.0 KiB
TypeScript

import { logout, LogoutReason, refresh } from '@/auth';
import { useRequestsStore } from '@/stores/';
import { getRootPath } from '@/utils/get-root-path';
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import { addQueryToPath } from './utils/add-query-to-path';
import PQueue from 'p-queue';
const api = axios.create({
baseURL: getRootPath(),
withCredentials: true,
headers: {
'Cache-Control': 'no-store',
},
});
const queue = new PQueue({ concurrency: 5, intervalCap: 5, interval: 500, carryoverConcurrencyCount: true });
interface RequestConfig extends AxiosRequestConfig {
id: string;
}
interface Response extends AxiosResponse {
config: RequestConfig;
}
export interface RequestError extends AxiosError {
response: Response;
}
export const onRequest = (config: AxiosRequestConfig): Promise<RequestConfig> => {
const requestsStore = useRequestsStore();
const id = requestsStore.startRequest();
const requestConfig: RequestConfig = {
id: id,
...config,
};
return new Promise((resolve) => {
queue.add(() => resolve(requestConfig));
});
};
export const onResponse = (response: AxiosResponse | Response): AxiosResponse | Response => {
const requestsStore = useRequestsStore();
const id = (response.config as RequestConfig)?.id;
if (id) requestsStore.endRequest(id);
return response;
};
export const onError = async (error: RequestError): Promise<RequestError> => {
const requestsStore = useRequestsStore();
// Note: Cancelled requests don't respond with the config
const id = (error.response?.config as RequestConfig)?.id;
if (id) requestsStore.endRequest(id);
// If a request fails with the unauthorized error, it either means that your user doesn't have
// access, or that your session doesn't exist / has expired.
// In case of the second, we should force the app to logout completely and redirect to the login
// view.
const status = error.response?.status;
const code = error.response?.data?.errors?.[0]?.extensions?.code;
if (
status === 401 &&
code === 'INVALID_CREDENTIALS' &&
error.request.responseURL.includes('refresh') === false &&
error.request.responseURL.includes('login') === false &&
error.request.responseURL.includes('tfa') === false
) {
let newToken: string | undefined;
try {
newToken = await refresh();
} catch {
logout({ reason: LogoutReason.SESSION_EXPIRED });
return Promise.reject();
}
if (newToken) {
return api.request({
...error.config,
headers: {
Authorization: `Bearer ${newToken}`,
},
});
}
}
return Promise.reject(error);
};
api.interceptors.request.use(onRequest);
api.interceptors.response.use(onResponse, onError);
export default api;
export function getToken(): string | null {
return api.defaults.headers?.['Authorization']?.split(' ')[1] || null;
}
export function addTokenToURL(url: string, token?: string): string {
const accessToken = token || getToken();
if (!accessToken) return url;
return addQueryToPath(url, { access_token: accessToken });
}