-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add admin view systems page Relates to #140
- Loading branch information
Showing
9 changed files
with
324 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<template> | ||
<q-page padding> | ||
<q-table title="Deployable Systems" :columns="systemColumns" :rows="adminSystemStore.systems" :loading="adminSystemStore.loading" v-model:pagination="adminSystemStore.pagination" @request="adminSystemStore.load"> | ||
|
||
<template v-slot:body-cell-createdAt="props"> | ||
<q-td :props="props"> | ||
{{ fromNow(props.row.createdAt) }} | ||
<q-tooltip class="bg-grey-5 text-black"> | ||
{{ formatDate(props.row.createdAt) }} | ||
</q-tooltip> | ||
</q-td> | ||
</template> | ||
|
||
<template v-slot:body-cell-updatedAt="props"> | ||
<q-td :props="props"> | ||
{{ fromNow(props.row.updatedAt) }} | ||
<q-tooltip class="bg-grey-5 text-black"> | ||
{{ formatDate(props.row.updatedAt) }} | ||
</q-tooltip> | ||
</q-td> | ||
</template> | ||
|
||
<template v-slot:body-cell-actions="props"> | ||
<q-td :props="props"> | ||
<q-btn size="sm" icon="delete" @click="confirmDelete(props.row)"> | ||
<q-tooltip>Delete System</q-tooltip> | ||
</q-btn> | ||
</q-td> | ||
</template> | ||
|
||
</q-table> | ||
|
||
<q-page-sticky position="bottom-right" :offset="[18, 18]"> | ||
<q-btn fab icon="add" color="accent" @click="showSystemAdd = true" /> | ||
</q-page-sticky> | ||
|
||
<q-dialog v-model="showSystemAdd"> | ||
<q-card> | ||
<q-card-section> | ||
<div class="text-h5">Add new deployable system</div> | ||
</q-card-section> | ||
<q-card-section> | ||
<div class="row q-mb-md"> | ||
<q-input dense style="min-width: 500px" v-model="activeSystem.name" label="System Name" :rules="[val => !!val || 'System Name is required']"/> | ||
</div> | ||
</q-card-section> | ||
<q-card-actions align="right"> | ||
<q-btn flat v-close-popup>Cancel</q-btn> | ||
<q-btn flat color="primary" @click="createSystem">Save</q-btn> | ||
</q-card-actions> | ||
</q-card> | ||
</q-dialog> | ||
</q-page> | ||
</template> | ||
|
||
<script setup> | ||
import { onMounted, ref } from 'vue' | ||
import { formatDate, fromNow } from '../utils/time' | ||
import { confirmAction } from '../utils/alerts' | ||
import { useAdminSystemStore } from 'stores/adminSystemStore' | ||
const adminSystemStore = useAdminSystemStore() | ||
// Reactive data | ||
const showSystemAdd = ref(false) | ||
const activeSystem = ref({ | ||
name: '' | ||
}) | ||
// Constant data | ||
const systemColumns = [ | ||
{ | ||
name: 'name', | ||
label: 'Name', | ||
field: 'name', | ||
align: 'left' | ||
}, | ||
{ | ||
name: 'createdAt', | ||
label: 'Created At', | ||
align: 'left' | ||
}, | ||
{ | ||
name: 'updatedAt', | ||
label: 'Updated At', | ||
align: 'left' | ||
}, | ||
{ | ||
name: 'actions', | ||
label: 'Actions', | ||
align: 'left' | ||
} | ||
] | ||
// Methods | ||
function createSystem () { | ||
showSystemAdd.value = false | ||
adminSystemStore.create(activeSystem.value) | ||
} | ||
function confirmDelete (system) { | ||
confirmAction( | ||
`Are you sure you want to delete system ${system.name}? This will cause all related components to be deleted as well!`, | ||
() => deleteSystem(system.id) | ||
) | ||
} | ||
function deleteSystem (id) { | ||
adminSystemStore.deleteSystem(id) | ||
} | ||
onMounted(() => { | ||
adminSystemStore.load() | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { defineStore } from 'pinia' | ||
import { api } from 'src/boot/axios' | ||
import { ref } from 'vue' | ||
import { doPagedRequest } from 'src/utils/data' | ||
|
||
export const useAdminSystemStore = defineStore('adminSystem', () => { | ||
const systems = ref([]) | ||
const loading = ref(false) | ||
const pagination = ref({ | ||
page: 1, | ||
rowsPerPage: 25, | ||
rowsNumber: 0 | ||
}) | ||
|
||
async function load (props) { | ||
doPagedRequest(loading, props, pagination, '/systems/admin', systems) | ||
} | ||
|
||
function create (systemData) { | ||
return api.post('/systems', systemData) | ||
.then(() => load()) | ||
} | ||
|
||
function deleteSystem (id) { | ||
api.delete(`/systems/${id}`) | ||
.then(() => load()) | ||
} | ||
|
||
return { systems, loading, load, create, deleteSystem } | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { defineStore } from 'pinia' | ||
import { api } from 'src/boot/axios' | ||
import { ref } from 'vue' | ||
|
||
export const useSystemStore = defineStore('system', () => { | ||
const systems = ref([]) | ||
const loading = ref(false) | ||
const currentSystem = ref(null) | ||
|
||
async function load () { | ||
loading.value = true | ||
|
||
const response = await api.get('/systems') | ||
systems.value = response.data | ||
loading.value = false | ||
} | ||
|
||
return { systems, loading, currentSystem, load } | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest' | ||
import { shallowMount } from '@vue/test-utils' | ||
import { describe, expect, it, vi } from 'vitest' | ||
import AdminSystemPage from 'pages/AdminSystemPage.vue' | ||
import { createTestingPinia } from '@pinia/testing' | ||
import { useAdminSystemStore } from 'src/stores/adminSystemStore' | ||
import { confirmAction } from 'src/utils/alerts' | ||
|
||
installQuasar() | ||
|
||
vi.mock('src/utils/alerts', () => { | ||
const confirmAction = vi.fn() | ||
|
||
return { confirmAction } | ||
}) | ||
|
||
const wrapper = shallowMount(AdminSystemPage, { | ||
global: { | ||
plugins: [createTestingPinia()] | ||
} | ||
}) | ||
|
||
describe('AdminSystemPage', () => { | ||
it('should mount the admin system page without errors', () => { | ||
expect(wrapper).toBeTruthy() | ||
}) | ||
}) | ||
|
||
describe('createSystem', () => { | ||
it('should call the admin system store to create a new system', () => { | ||
const adminSystemStore = useAdminSystemStore() | ||
adminSystemStore.create.mockImplementation(() => Promise.resolve(1)) | ||
|
||
wrapper.vm.activeSystem.name = 'kiwi' | ||
|
||
wrapper.vm.createSystem() | ||
|
||
expect(adminSystemStore.create).toHaveBeenLastCalledWith({ name: 'kiwi' }) | ||
expect(wrapper.vm.showSystemAdd).toEqual(false) | ||
}) | ||
}) | ||
|
||
describe('deleteSystem', () => { | ||
it('should call deleteSystem on the admin system store', () => { | ||
const adminSystemStore = useAdminSystemStore() | ||
|
||
wrapper.vm.deleteSystem(1) | ||
|
||
expect(adminSystemStore.deleteSystem).toHaveBeenCalledTimes(1) | ||
expect(adminSystemStore.deleteSystem).toHaveBeenLastCalledWith(1) | ||
}) | ||
}) | ||
|
||
describe('confirmDelete', () => { | ||
it('should call confirm utility', () => { | ||
wrapper.vm.confirmDelete({ name: 'kiwi', id: 1 }) | ||
|
||
expect(confirmAction).toHaveBeenCalled() | ||
expect(confirmAction).toHaveBeenCalledWith('Are you sure you want to delete system kiwi? This will cause all related components to be deleted as well!', expect.any(Function)) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { createPinia, setActivePinia } from 'pinia' | ||
import { useAdminSystemStore } from 'src/stores/adminSystemStore' | ||
import { beforeEach, describe, expect, it, vi } from 'vitest' | ||
import { api } from 'src/boot/axios' | ||
import { doPagedRequest } from 'src/utils/data' | ||
|
||
vi.mock('src/utils/data', () => { | ||
const doPagedRequest = vi.fn() | ||
|
||
return { doPagedRequest } | ||
}) | ||
|
||
beforeEach(() => { | ||
setActivePinia(createPinia()) | ||
|
||
vi.mock('src/boot/axios', () => { | ||
const api = { | ||
post: vi.fn().mockImplementation(() => Promise.resolve(true)), | ||
delete: vi.fn().mockImplementation(() => Promise.resolve(true)) | ||
} | ||
|
||
return { api } | ||
}) | ||
}) | ||
|
||
describe('load', () => { | ||
it('should load systems', async () => { | ||
const adminSystemStore = useAdminSystemStore() | ||
await adminSystemStore.load() | ||
|
||
expect(doPagedRequest).toHaveBeenCalled() | ||
}) | ||
}) | ||
|
||
describe('create', () => { | ||
it('should make call to create system', async () => { | ||
const adminSystemStore = useAdminSystemStore() | ||
await adminSystemStore.create({ name: 'kiwi' }) | ||
|
||
expect(api.post).toHaveBeenCalled() | ||
expect(api.post).toHaveBeenCalledWith('/systems', { name: 'kiwi' }) | ||
}) | ||
}) | ||
|
||
describe('deleteSystem', () => { | ||
it('should make call to delete system', async () => { | ||
const adminSystemStore = useAdminSystemStore() | ||
await adminSystemStore.deleteSystem(1) | ||
|
||
expect(api.delete).toHaveBeenCalled() | ||
expect(api.delete).toHaveBeenCalledWith('/systems/1') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { createPinia, setActivePinia } from 'pinia' | ||
import { useSystemStore } from 'src/stores/systemStore' | ||
import { beforeEach, describe, expect, it, vi } from 'vitest' | ||
import { api } from 'src/boot/axios' | ||
|
||
beforeEach(() => { | ||
setActivePinia(createPinia()) | ||
|
||
vi.mock('src/boot/axios', () => { | ||
const api = { | ||
get: vi.fn().mockImplementation(() => Promise.resolve({ data: [{ name: 'kiwi' }] })) | ||
} | ||
|
||
return { api } | ||
}) | ||
}) | ||
|
||
describe('load', () => { | ||
it('should load systems for user', async () => { | ||
const systemStore = useSystemStore() | ||
|
||
await systemStore.load() | ||
|
||
expect(api.get).toHaveBeenCalled() | ||
expect(api.get).toHaveBeenCalledWith('/systems') | ||
expect(systemStore.systems).toEqual([{ name: 'kiwi' }]) | ||
}) | ||
}) |