forked from verdnatura/salix-front
feat(navBar): refs #7632 isLoading
This commit is contained in:
parent
5c5393db6d
commit
175ebbc343
|
@ -2,9 +2,11 @@ import axios from 'axios';
|
|||
import { useSession } from 'src/composables/useSession';
|
||||
import { Router } from 'src/router';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useStateQueryStore } from 'src/stores/useStateQueryStore';
|
||||
|
||||
const session = useSession();
|
||||
const { notify } = useNotify();
|
||||
const stateQuery = useStateQueryStore();
|
||||
const baseUrl = '/api/';
|
||||
|
||||
axios.defaults.baseURL = baseUrl;
|
||||
|
@ -15,7 +17,7 @@ const onRequest = (config) => {
|
|||
if (token.length && !config.headers.Authorization) {
|
||||
config.headers.Authorization = token;
|
||||
}
|
||||
|
||||
stateQuery.add(config);
|
||||
return config;
|
||||
};
|
||||
|
||||
|
@ -24,9 +26,10 @@ const onRequestError = (error) => {
|
|||
};
|
||||
|
||||
const onResponse = (response) => {
|
||||
const { method } = response.config;
|
||||
const config = response.config;
|
||||
stateQuery.remove(config);
|
||||
|
||||
const isSaveRequest = method === 'patch';
|
||||
const isSaveRequest = config.method === 'patch';
|
||||
if (isSaveRequest) {
|
||||
notify('globals.dataSaved', 'positive');
|
||||
}
|
||||
|
@ -35,6 +38,8 @@ const onResponse = (response) => {
|
|||
};
|
||||
|
||||
const onResponseError = (error) => {
|
||||
stateQuery.remove(error.config);
|
||||
|
||||
let message = '';
|
||||
|
||||
const response = error.response;
|
||||
|
|
|
@ -3,6 +3,7 @@ import { onMounted, ref } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { useStateQueryStore } from 'src/stores/useStateQueryStore';
|
||||
import { useQuasar } from 'quasar';
|
||||
import PinnedModules from './PinnedModules.vue';
|
||||
import UserPanel from 'components/UserPanel.vue';
|
||||
|
@ -12,6 +13,7 @@ import VnAvatar from './ui/VnAvatar.vue';
|
|||
const { t } = useI18n();
|
||||
const stateStore = useStateStore();
|
||||
const quasar = useQuasar();
|
||||
const stateQuery = useStateQueryStore();
|
||||
const state = useState();
|
||||
const user = state.getUser();
|
||||
const appName = 'Lilium';
|
||||
|
@ -50,6 +52,14 @@ const pinnedModulesRef = ref();
|
|||
</QBtn>
|
||||
</RouterLink>
|
||||
<VnBreadcrumbs v-if="$q.screen.gt.sm" />
|
||||
<QSpinner
|
||||
color="primary"
|
||||
class="q-ml-md"
|
||||
:class="{
|
||||
'no-visible': !stateQuery.isLoading().value,
|
||||
}"
|
||||
size="xs"
|
||||
/>
|
||||
<QSpace />
|
||||
<div id="searchbar" class="searchbar"></div>
|
||||
<QSpace />
|
||||
|
@ -104,6 +114,9 @@ const pinnedModulesRef = ref();
|
|||
.q-header {
|
||||
background-color: var(--vn-section-color);
|
||||
}
|
||||
.no-visible {
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
en:
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import { ref, computed } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
export const useStateQueryStore = defineStore('stateQueryStore', () => {
|
||||
const queries = ref(new Set());
|
||||
|
||||
function add(query) {
|
||||
queries.value.add(query);
|
||||
return query;
|
||||
}
|
||||
|
||||
function isLoading() {
|
||||
return computed(() => queries.value.size);
|
||||
}
|
||||
|
||||
function remove(query) {
|
||||
queries.value.delete(query);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
queries.value = new Set();
|
||||
}
|
||||
|
||||
return {
|
||||
add,
|
||||
isLoading,
|
||||
remove,
|
||||
queries,
|
||||
reset,
|
||||
};
|
||||
});
|
|
@ -7,41 +7,46 @@ vi.mock('src/composables/useSession', () => ({
|
|||
getToken: () => 'DEFAULT_TOKEN',
|
||||
isLoggedIn: () => vi.fn(),
|
||||
destroy: () => vi.fn(),
|
||||
})
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('src/stores/useStateQueryStore', () => ({
|
||||
useStateQueryStore: () => ({
|
||||
add: () => vi.fn(),
|
||||
remove: () => vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('Axios boot', () => {
|
||||
|
||||
describe('onRequest()', async () => {
|
||||
it('should set the "Authorization" property on the headers', async () => {
|
||||
const config = { headers: {} };
|
||||
|
||||
const resultConfig = onRequest(config);
|
||||
|
||||
expect(resultConfig).toEqual(expect.objectContaining({
|
||||
expect(resultConfig).toEqual(
|
||||
expect.objectContaining({
|
||||
headers: {
|
||||
Authorization: 'DEFAULT_TOKEN'
|
||||
}
|
||||
}));
|
||||
});
|
||||
Authorization: 'DEFAULT_TOKEN',
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onResponseError()', async () => {
|
||||
it('should call to the Notify plugin with a message error for an status code "500"', async () => {
|
||||
Notify.create = vi.fn()
|
||||
Notify.create = vi.fn();
|
||||
|
||||
const error = {
|
||||
response: {
|
||||
status: 500
|
||||
}
|
||||
status: 500,
|
||||
},
|
||||
};
|
||||
|
||||
const result = onResponseError(error);
|
||||
|
||||
|
||||
expect(result).rejects.toEqual(
|
||||
expect.objectContaining(error)
|
||||
);
|
||||
expect(result).rejects.toEqual(expect.objectContaining(error));
|
||||
expect(Notify.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: 'An internal server error has ocurred',
|
||||
|
@ -51,25 +56,22 @@ describe('Axios boot', () => {
|
|||
});
|
||||
|
||||
it('should call to the Notify plugin with a message from the response property', async () => {
|
||||
Notify.create = vi.fn()
|
||||
Notify.create = vi.fn();
|
||||
|
||||
const error = {
|
||||
response: {
|
||||
status: 401,
|
||||
data: {
|
||||
error: {
|
||||
message: 'Invalid user or password'
|
||||
}
|
||||
}
|
||||
}
|
||||
message: 'Invalid user or password',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = onResponseError(error);
|
||||
|
||||
|
||||
expect(result).rejects.toEqual(
|
||||
expect.objectContaining(error)
|
||||
);
|
||||
expect(result).rejects.toEqual(expect.objectContaining(error));
|
||||
expect(Notify.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: 'Invalid user or password',
|
||||
|
@ -77,5 +79,5 @@ describe('Axios boot', () => {
|
|||
})
|
||||
);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import { describe, expect, it, beforeEach, beforeAll } from 'vitest';
|
||||
import { createWrapper } from 'app/test/vitest/helper';
|
||||
|
||||
import { useStateQueryStore } from 'src/stores/useStateQueryStore';
|
||||
|
||||
describe('useStateQueryStore', () => {
|
||||
beforeAll(() => {
|
||||
createWrapper({}, {});
|
||||
});
|
||||
|
||||
const stateQueryStore = useStateQueryStore();
|
||||
const { add, isLoading, remove, reset } = useStateQueryStore();
|
||||
const firstQuery = { url: 'myQuery' };
|
||||
const secondQuery = { url: 'myQuery' };
|
||||
|
||||
function getQueries() {
|
||||
return stateQueryStore.queries;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
reset();
|
||||
expect(getQueries().size).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should add two queries', async () => {
|
||||
expect(getQueries().size).toBeFalsy();
|
||||
add(firstQuery);
|
||||
|
||||
expect(getQueries().size).toBeTruthy();
|
||||
expect(getQueries().has(firstQuery)).toBeTruthy();
|
||||
|
||||
add();
|
||||
expect(getQueries().size).toBe(2);
|
||||
});
|
||||
|
||||
it('should add and remove loading state', async () => {
|
||||
expect(isLoading().value).toBeFalsy();
|
||||
add(firstQuery);
|
||||
expect(isLoading().value).toBeTruthy();
|
||||
remove(firstQuery);
|
||||
expect(isLoading().value).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should add and remove hash', async () => {
|
||||
add(firstQuery);
|
||||
add(secondQuery);
|
||||
|
||||
const beforeCount = getQueries().size;
|
||||
const hash = add();
|
||||
expect(getQueries().has(hash)).toBeTruthy();
|
||||
|
||||
remove(hash);
|
||||
expect(getQueries().has(hash)).toBeFalsy();
|
||||
expect(getQueries().size).toBe(beforeCount);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue