Multi-level navigation

This commit is contained in:
Jiang Yio 2023-05-08 20:19:10 -04:00
parent 45dda6f51d
commit 789e11e572
5 changed files with 77 additions and 22 deletions

View File

@ -1,4 +1,5 @@
<template> <template>
<Submenu :value="menu" />
<div class="container-fluid" style="padding-top: 5rem;"> <div class="container-fluid" style="padding-top: 5rem;">
<Navbar v-model:server="server" :user="user" /> <Navbar v-model:server="server" :user="user" />
<Throbber :client="client" /> <Throbber :client="client" />
@ -10,6 +11,7 @@
</template> </template>
<script> <script>
import Submenu from './Submenu.vue';
import Navbar from './Navbar.vue'; import Navbar from './Navbar.vue';
import Throbber from './Throbber.vue'; import Throbber from './Throbber.vue';
import Login from './Login.vue'; import Login from './Login.vue';
@ -24,7 +26,7 @@
export default { export default {
components: { components: {
Navbar, Throbber, Login Submenu, Navbar, Throbber, Login
}, },
props: { props: {
secret: String secret: String
@ -36,7 +38,16 @@
user: null, user: null,
heartbeat: null, heartbeat: null,
banner: '', banner: '',
authenticated: false authenticated: false,
menu: {
name: 'Main',
items: [
{ name: 'Schedule', href: '/' },
{ name: 'Lookup', href: '/lookup' },
{ name: 'Planner', href: '/planner' },
{ name: 'Recall', href: '/recall' }
]
}
}; };
}, },
watch: { watch: {

View File

@ -7,25 +7,16 @@
</button> </button>
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item"> <li v-if="menustate.length > 0" v-for="item in menustate[0].items" class="nav-item">
<router-link class="nav-link" to="/">Schedule</router-link> <router-link class="nav-link" :to="item.href">{{item.name}}</router-link>
</li> </li>
<li class="nav-item"> <li v-if="menustate.length > 1" v-for="menu in menustate.slice(1)" class="nav-item dropdown">
<router-link class="nav-link" to="/lookup">Lookup</router-link> <button class="nav-link btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">{{menu.name}}</button>
<ul class="dropdown-menu dropdown-menu-dark">
<li v-for="item in menu.items" class="nav-item">
<router-link class="nav-link" :to="item.href">{{item.name}}</router-link>
</li> </li>
<template v-if="($route.matched.length > 0) && ($route.matched[0].path == '/patient/:id')"> </ul>
<li class="nav-item">
<router-link class="nav-link" :to="'/patient/' + $route.params.id + '/visits'">Visits</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="'/patient/' + $route.params.id + '/orders'">Orders</router-link>
</li>
</template>
<li class="nav-item">
<router-link class="nav-link" to="/planner">Planner</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" to="/recall">Recall</router-link>
</li> </li>
<li class="nav-item" v-if="server"> <li class="nav-item" v-if="server">
<a class="nav-link disabled"><template v-if="user">{{user[2]}} @ </template>{{server.domain}}</a> <a class="nav-link disabled"><template v-if="user">{{user[2]}} @ </template>{{server.domain}}</a>
@ -48,6 +39,7 @@
<script> <script>
import vistax from './vistax.mjs'; import vistax from './vistax.mjs';
import { menustate } from './common.mjs';
export default { export default {
props: { props: {
@ -61,7 +53,9 @@
} }
}, },
data() { data() {
return {}; return {
menustate
};
} }
}; };
</script> </script>

View File

@ -7,6 +7,7 @@
<router-link class="btn btn-danger" :to="'/patient/' + patient_dfn + '?viewsensitive'">Proceed</router-link> <router-link class="btn btn-danger" :to="'/patient/' + patient_dfn + '?viewsensitive'">Proceed</router-link>
</div> </div>
<template v-if="patient_info"> <template v-if="patient_info">
<Submenu :value="menu" />
<div class="card mb-3 shadow"> <div class="card mb-3 shadow">
<div class="card-header">{{patient_info.name}} <span :title="patient_info.pid">{{patient_info.pid.slice(-4)}}</span> #{{patient_dfn}}</div> <div class="card-header">{{patient_info.name}} <span :title="patient_info.pid">{{patient_info.pid.slice(-4)}}</span> #{{patient_dfn}}</div>
<div class="card-body row" style="font-family: monospace;"> <div class="card-body row" style="font-family: monospace;">
@ -27,10 +28,11 @@
import { strptime_vista } from './util.mjs'; import { strptime_vista } from './util.mjs';
import Subtitle from './Subtitle.vue'; import Subtitle from './Subtitle.vue';
import Submenu from './Submenu.vue';
export default { export default {
components: { components: {
Subtitle Subtitle, Submenu
}, },
props: { props: {
client: Object client: Object
@ -42,6 +44,18 @@
patient_info: null patient_info: null
}; };
}, },
computed: {
menu() {
return this.patient_info ? {
name: this.patient_info.name,
items: [
{ name: 'Patient', href: '/patient/' + this.patient_dfn + (this.sensitive && '?viewsensitive' || '') },
{ name: 'Visits', href: '/patient/' + this.patient_dfn + '/visits' + (this.sensitive && '?viewsensitive' || '') },
{ name: 'Orders', href: '/patient/' + this.patient_dfn + '/orders' + (this.sensitive && '?viewsensitive' || '') }
]
} : null;
}
},
methods: { methods: {
strptime_vista, strptime_vista,
async loadinfo(dfn, viewsensitive) { async loadinfo(dfn, viewsensitive) {

33
htdocs/Submenu.vue Normal file
View File

@ -0,0 +1,33 @@
<script>
import { menustate } from './common.mjs';
export default {
props: ['value'],
data() {
return { ptr: null };
},
watch: {
value: {
handler(value) {
this.update(value);
}, immediate: true
}
},
methods: {
update(value) {
var idx = this.ptr ? menustate.indexOf(this.ptr) : -1;
if(idx >= 0) menustate.splice(idx, 1);
if(value) {
this.ptr = value;
if(idx >= 0) menustate.splice(idx, 0, this.ptr);
else menustate.unshift(this.ptr);
} else this.ptr = null;
console.log(menustate)
}
},
unmounted() {
this.update();
},
render() {}
};
</script>

3
htdocs/common.mjs Normal file
View File

@ -0,0 +1,3 @@
import { reactive } from 'vue';
export const menustate = reactive([]);