* Fix store identifier

* Add relations store

* Remove rolesStore in favor of composition for user nav

* Fix tests
This commit is contained in:
Rijk van Zanten
2020-04-14 17:33:26 -04:00
committed by GitHub
parent 5e3914de9f
commit 7e2866373d
12 changed files with 103 additions and 47 deletions

View File

@@ -3,6 +3,8 @@ import VueCompositionAPI from '@vue/composition-api';
import { useAppStore } from '@/stores/app';
import { useStores, hydrate, dehydrate } from './hydrate';
jest.mock('@/api');
describe('Stores / App', () => {
beforeAll(() => {
Vue.use(VueCompositionAPI);

View File

@@ -8,7 +8,7 @@ import { useSettingsStore } from '@/stores/settings/';
import { useProjectsStore } from '@/stores/projects/';
import { useLatencyStore } from '@/stores/latency';
import { usePermissionsStore } from '@/stores/permissions';
import { useRolesStore } from '@/stores/roles';
import { useRelationsStore } from '@/stores/relations';
type GenericStore = {
id: string;
@@ -29,7 +29,7 @@ export function useStores(
useProjectsStore,
useLatencyStore,
usePermissionsStore,
useRolesStore,
useRelationsStore,
]
) {
return stores.map((useStore) => useStore()) as GenericStore[];

View File

@@ -5,7 +5,13 @@
<v-list-item-content>{{ $t('all_users') }}</v-list-item-content>
</v-list-item>
<v-divider />
<v-divider v-if="(roles && roles.length > 0) || loading" />
<template v-if="loading">
<v-list-item v-for="n in 4" :key="n">
<v-skeleton-loader type="list-item-icon" />
</v-list-item>
</template>
<v-list-item v-for="{ name, id } in roles" :key="id" :to="`/${project}/users/${id}`">
<v-list-item-icon><v-icon name="people" /></v-list-item-icon>
@@ -16,15 +22,15 @@
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import useRolesStore from '@/stores/roles';
import useProjectsStore from '@/stores/projects';
import useNavigation from '../../compositions/use-navigation';
export default defineComponent({
setup() {
const rolesStore = useRolesStore();
const projectsStore = useProjectsStore();
const { roles, loading } = useNavigation();
return { roles: rolesStore.state.roles, project: projectsStore.state.currentProjectKey };
return { roles, loading, project: projectsStore.state.currentProjectKey };
},
});
</script>

View File

@@ -0,0 +1,34 @@
import { ref, Ref } from '@vue/composition-api';
import useProjectsStore from '@/stores/projects';
import api from '@/api';
import { Role } from '@/stores/user/types';
let roles: Ref<Role[] | null> | null = null;
let loading: Ref<boolean> | null = null;
export default function useNavigation() {
if (roles === null) {
roles = ref<Role[]>(null);
}
if (loading === null) {
loading = ref(false);
}
if (roles.value === null && loading?.value === false) {
fetchRoles();
}
return { roles, loading };
async function fetchRoles() {
if (!loading || !roles) return;
loading.value = true;
const projectsStore = useProjectsStore();
const currentProjectKey = projectsStore.state.currentProjectKey;
const rolesResponse = await api.get(`/${currentProjectKey}/roles`);
roles.value = rolesResponse.data.data;
loading.value = false;
}
}

View File

@@ -0,0 +1,4 @@
import { useRelationsStore } from './relations';
export { useRelationsStore };
export default useRelationsStore;

View File

@@ -0,0 +1,32 @@
import { createStore } from 'pinia';
import { Relation } from './types';
import useProjectsStore from '@/stores/projects';
import api from '@/api';
export const useRelationsStore = createStore({
id: 'relationsStore',
state: () => ({
relations: [] as Relation[],
}),
actions: {
async hydrate() {
const projectsStore = useProjectsStore();
const currentProjectKey = projectsStore.state.currentProjectKey;
const response = await api.get(`/${currentProjectKey}/relations`);
this.state.relations = response.data.data;
},
async dehydrate() {
this.reset();
},
getRelationForField(collection: string, field: string) {
return this.state.relations.filter((relation) => {
return (
(relation.collection_many === collection && relation.field_many === field) ||
(relation.collection_one === collection && relation.field_one === field)
);
});
},
},
});

View File

@@ -0,0 +1,8 @@
export type Relation = {
id: number;
collection_many: string;
field_many: string;
collection_one: string;
field_one: null | string;
junction_field: null | string;
};

View File

@@ -1,4 +0,0 @@
import { useRolesStore } from './roles';
export { useRolesStore };
export default useRolesStore;

View File

@@ -1,25 +0,0 @@
import { createStore } from 'pinia';
import api from '@/api';
import { useProjectsStore } from '@/stores/projects';
import { Role } from './types';
export const useRolesStore = createStore({
id: 'rolesStore',
state: () => ({
roles: [] as Role[],
}),
actions: {
async hydrate() {
const projectsStore = useProjectsStore();
const currentProjectKey = projectsStore.state.currentProjectKey;
const rolesResponse = await api.get(`/${currentProjectKey}/roles`);
this.state.roles = rolesResponse.data.data;
},
async dehydrate() {
this.reset();
},
},
});

View File

@@ -1,10 +0,0 @@
export type Role = {
id: number;
name: string;
description: string;
collection_listing: null;
module_listing: null;
enforce_2fa: null | boolean;
external_id: null | string;
ip_whitelist: string[];
};

View File

@@ -15,7 +15,7 @@ import { i18n } from '@/lang';
*/
export const useSettingsStore = createStore({
id: 'settings',
id: 'settingsStore',
state: () => ({
settings: [] as Setting[],
}),

View File

@@ -1,4 +1,13 @@
import { Role } from '@/stores/roles/types';
export type Role = {
id: number;
name: string;
description: string;
collection_listing: null;
module_listing: null;
enforce_2fa: null | boolean;
external_id: null | string;
ip_whitelist: string[];
};
export type Avatar = {
data: {