mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Switch to history mode in app (#594)
* Switch to history mode in pp * Remove broken tests * Install asset manifest * Only build to modern * Remove override files in favor of settings * Build assets json * Use dynamic routing based on api basepath * Remove override files * Set webpack public path based on passed window var * Fix tests
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import VueCompositionAPI from '@vue/composition-api';
|
||||
import { onRequest, onResponse, onError, getRootPath, RequestError } from './api';
|
||||
import { onRequest, onResponse, onError, RequestError } from './api';
|
||||
import * as auth from '@/auth';
|
||||
import { useRequestsStore } from '@/stores/requests';
|
||||
|
||||
@@ -29,18 +29,6 @@ describe('API', () => {
|
||||
window = Object.create(window);
|
||||
});
|
||||
|
||||
it('Calculates the correct API root URL based on window', () => {
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
pathname: '/api/nested/admin',
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
const result = getRootPath();
|
||||
expect(result).toBe('/api/nested/');
|
||||
});
|
||||
|
||||
it('Calls startRequest on the store on any request', () => {
|
||||
const store = useRequestsStore({});
|
||||
const spy = jest.spyOn(store, 'startRequest');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
|
||||
import { useRequestsStore } from '@/stores/requests';
|
||||
import { LogoutReason, logout, checkAuth } from '@/auth';
|
||||
import getRootPath from '@/utils/get-root-path';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: getRootPath(),
|
||||
@@ -65,12 +66,4 @@ export const onError = async (error: RequestError) => {
|
||||
api.interceptors.request.use(onRequest);
|
||||
api.interceptors.response.use(onResponse, onError);
|
||||
|
||||
export function getRootPath(): string {
|
||||
const path = window.location.pathname;
|
||||
const parts = path.split('/');
|
||||
const adminIndex = parts.indexOf('admin');
|
||||
const rootPath = parts.slice(0, adminIndex).join('/') + '/';
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
export default api;
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import { mount, createLocalVue, Wrapper } from '@vue/test-utils';
|
||||
import VueCompositionAPI from '@vue/composition-api';
|
||||
import VNotice from './v-notice.vue';
|
||||
import VIcon from '@/components/v-icon/';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(VueCompositionAPI);
|
||||
localVue.component('v-icon', VIcon);
|
||||
|
||||
describe('Notice', () => {
|
||||
let component: Wrapper<Vue>;
|
||||
|
||||
beforeEach(() => {
|
||||
component = mount(VNotice, {
|
||||
localVue,
|
||||
slots: {
|
||||
default: 'I like pizza',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Renders the default slot in the notice', () => {
|
||||
expect(component.text()).toContain('I like pizza');
|
||||
});
|
||||
|
||||
it('Uses the right color / icon combo for success', async () => {
|
||||
component.setProps({
|
||||
success: true,
|
||||
});
|
||||
|
||||
await component.vm.$nextTick();
|
||||
|
||||
expect(component.classes()).toContain('success');
|
||||
expect((component.vm as any).iconName).toBe('check_circle');
|
||||
});
|
||||
|
||||
it('Uses the right color / icon combo for warning', async () => {
|
||||
component.setProps({
|
||||
warning: true,
|
||||
});
|
||||
|
||||
await component.vm.$nextTick();
|
||||
|
||||
expect(component.classes()).toContain('warning');
|
||||
expect((component.vm as any).iconName).toBe('warning');
|
||||
});
|
||||
|
||||
it('Uses the right color / icon combo for danger', async () => {
|
||||
component.setProps({
|
||||
danger: true,
|
||||
});
|
||||
|
||||
await component.vm.$nextTick();
|
||||
|
||||
expect(component.classes()).toContain('danger');
|
||||
expect((component.vm as any).iconName).toBe('error');
|
||||
});
|
||||
|
||||
it('Defaults to success if all props are given', async () => {
|
||||
component.setProps({
|
||||
success: true,
|
||||
warning: true,
|
||||
danger: true,
|
||||
});
|
||||
|
||||
await component.vm.$nextTick();
|
||||
|
||||
expect((component.vm as any).iconName).toBe('check_circle');
|
||||
expect(component.classes()).toContain('success');
|
||||
});
|
||||
|
||||
it('Allows setting a custom icon', async () => {
|
||||
component.setProps({
|
||||
icon: 'person',
|
||||
});
|
||||
await component.vm.$nextTick();
|
||||
expect((component.vm as any).iconName).toBe('person');
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
__webpack_public_path__ = (window as any).$directusAssetBasePath || '/admin/';
|
||||
|
||||
import Vue from 'vue';
|
||||
|
||||
import { version } from '../package.json';
|
||||
|
||||
@@ -11,6 +11,8 @@ import useAppStore from '@/stores/app';
|
||||
import useUserStore from '@/stores/user';
|
||||
import PrivateNotFoundRoute from '@/routes/private-not-found';
|
||||
|
||||
import getRootPath from '@/utils/get-root-path';
|
||||
|
||||
export const onBeforeEnterProjectChooser: NavigationGuard = (to, from, next) => {
|
||||
const projectsStore = useProjectsStore();
|
||||
projectsStore.state.currentProjectKey = null;
|
||||
@@ -43,6 +45,9 @@ export const defaultRoutes: RouteConfig[] = [
|
||||
name: 'login',
|
||||
path: '/:project/login',
|
||||
component: LoginRoute,
|
||||
props: (route) => ({
|
||||
ssoErrorCode: route.query.error,
|
||||
}),
|
||||
meta: {
|
||||
public: true,
|
||||
},
|
||||
@@ -83,13 +88,18 @@ export const defaultRoutes: RouteConfig[] = [
|
||||
];
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'hash',
|
||||
mode: 'history',
|
||||
base: getRootPath() + 'admin/',
|
||||
routes: defaultRoutes,
|
||||
});
|
||||
|
||||
export function replaceRoutes(routeFilter: (routes: RouteConfig[]) => RouteConfig[]): void {
|
||||
const newRoutes = routeFilter([...defaultRoutes]);
|
||||
const newRouter = new VueRouter({ routes: newRoutes });
|
||||
const newRouter = new VueRouter({
|
||||
mode: 'history',
|
||||
base: getRootPath() + 'admin/',
|
||||
routes: newRoutes,
|
||||
});
|
||||
|
||||
// @ts-ignore - Matcher is not officially part of the public API (https://github.com/vuejs/vue-router/issues/2844#issuecomment-509529927)
|
||||
router.matcher = newRouter.matcher;
|
||||
|
||||
15
src/utils/get-root-path/get-root-path.test.ts
Normal file
15
src/utils/get-root-path/get-root-path.test.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import getRootPath from './get-root-path';
|
||||
|
||||
describe('Utils / get root path', () => {
|
||||
it('Calculates the correct API root URL based on window', () => {
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
pathname: '/api/nested/admin',
|
||||
},
|
||||
writable: true,
|
||||
});
|
||||
|
||||
const result = getRootPath();
|
||||
expect(result).toBe('/api/nested/');
|
||||
});
|
||||
});
|
||||
7
src/utils/get-root-path/get-root-path.ts
Normal file
7
src/utils/get-root-path/get-root-path.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function getRootPath(): string {
|
||||
const path = window.location.pathname;
|
||||
const parts = path.split('/');
|
||||
const adminIndex = parts.indexOf('admin');
|
||||
const rootPath = parts.slice(0, adminIndex).join('/') + '/';
|
||||
return rootPath;
|
||||
}
|
||||
4
src/utils/get-root-path/index.ts
Normal file
4
src/utils/get-root-path/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import getRootPath from './get-root-path';
|
||||
|
||||
export default getRootPath;
|
||||
export { getRootPath };
|
||||
Reference in New Issue
Block a user