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:
Rijk van Zanten
2020-05-19 17:16:44 -04:00
committed by GitHub
parent c552364d1f
commit 0c745a6eee
15 changed files with 96 additions and 122 deletions

View File

@@ -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');

View File

@@ -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;

View File

@@ -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');
});
});

View File

@@ -1,3 +1,5 @@
__webpack_public_path__ = (window as any).$directusAssetBasePath || '/admin/';
import Vue from 'vue';
import { version } from '../package.json';

View File

@@ -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;

View 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/');
});
});

View 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;
}

View File

@@ -0,0 +1,4 @@
import getRootPath from './get-root-path';
export default getRootPath;
export { getRootPath };