Make coreid SPA
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing

This commit is contained in:
Garrett Mills 2021-05-04 10:18:53 -05:00
parent ced3a15d00
commit f45e92af1e
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
12 changed files with 143 additions and 17 deletions

View File

@ -8,6 +8,8 @@ import AppSetupComponent from './dash/AppSetup.component.js'
import ListingComponent from './cobalt/Listing.component.js' import ListingComponent from './cobalt/Listing.component.js'
import FormComponent from './cobalt/Form.component.js' import FormComponent from './cobalt/Form.component.js'
import RootPageComponent from './dash/RootPage.component.js'
import OutletComponent from './dash/Outlet.component.js'
import { T } from './service/Translate.service.js' import { T } from './service/Translate.service.js'
@ -22,6 +24,8 @@ const dash_components = {
ListingComponent, ListingComponent,
FormComponent, FormComponent,
RootPageComponent,
OutletComponent,
} }
export { dash_components } export { dash_components }

View File

@ -1,6 +1,7 @@
import { Component } from '../../lib/vues6/vues6.js' import { Component } from '../../lib/vues6/vues6.js'
import { event_bus } from '../service/EventBus.service.js' import { event_bus } from '../service/EventBus.service.js'
import { session } from '../service/Session.service.js' import { session } from '../service/Session.service.js'
import { action_service } from '../service/Action.service.js'
const template = ` const template = `
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom"> <nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
@ -35,9 +36,9 @@ const template = `
aria-labelledby="navbarDropdown" aria-labelledby="navbarDropdown"
> >
<h6 class="dropdown-header">Hello, {{ first_name }}.</h6> <h6 class="dropdown-header">Hello, {{ first_name }}.</h6>
<a href="/dash/profile" class="dropdown-item">My Profile</a> <a href="/dash/profile" class="dropdown-item" @click="navigate('dash.profile')" onclick="return false;">My Profile</a>
<a href="/dash/c/listing/reflect/Token" v-if="can.api_tokens" class="dropdown-item">API Tokens</a> <a href="/dash/c/listing/reflect/Token" v-if="can.api_tokens" @click="cobalt('reflect/Token', 'list')" class="dropdown-item" onclick="return false;">API Tokens</a>
<a href="/dash/c/listing/system/Announcement" v-if="can.messages" class="dropdown-item">System Announcements</a> <a href="/dash/c/listing/system/Announcement" v-if="can.messages" @click="cobalt('system/Announcement', 'list')" class="dropdown-item" onclick="return false;">System Announcements</a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a href="/auth/logout" class="dropdown-item">Sign-Out of {{ app_name }}</a> <a href="/auth/logout" class="dropdown-item">Sign-Out of {{ app_name }}</a>
</div> </div>
@ -71,4 +72,20 @@ export default class NavBarComponent extends Component {
toggle_sidebar() { toggle_sidebar() {
this.toggle_event.fire() this.toggle_event.fire()
} }
navigate(page) {
action_service.perform({
action: 'navigate',
page,
})
}
cobalt(resource, action, id = undefined) {
action_service.perform({
type: 'resource',
resource,
action,
id,
})
}
} }

View File

@ -0,0 +1,45 @@
import { Component } from '../../lib/vues6/vues6.js'
import { event_bus } from '../service/EventBus.service.js'
const template = `
<coreid-root :page="page" :form_id="form_id" :resource="resource" :mode="mode" v-if="show"></coreid-root>
`
export default class OutletPageComponent extends Component {
static get selector() { return 'coreid-outlet' }
static get template() { return template }
static get props() { return ['initial_page', 'initial_form_id', 'initial_resource', 'initial_mode'] }
constructor() {
super()
this.navigate_event = event_bus.event('root.navigate')
this.show = true
console.log('navigate event', this.navigate_event)
}
async vue_on_create() {
this.page = this.initial_page
this.form_id = this.initial_form_id
this.resource = this.initial_resource
this.mode = this.initial_mode
this.navigate_event.subscribe((props = {}) => {
console.log('navigation event', props)
this.page = props.page
this.form_id = props.form_id
this.resource = props.resource
this.mode = props.mode
this.rerender()
})
this.$forceUpdate()
}
rerender() {
this.show = false
this.$forceUpdate()
requestAnimationFrame(() => {
this.show = true
this.$forceUpdate()
})
}
}

View File

@ -0,0 +1,32 @@
import { Component } from '../../lib/vues6/vues6.js'
const template = `
<span>
<coreid-profile-edit v-if="page === 'dash.profile'"></coreid-profile-edit>
<coreid-app-setup v-if="page === 'app.setup'"></coreid-app-setup>
<cobalt-form
v-if="page === 'cobalt.form' && form_id"
:resource="resource"
:form_id="form_id"
:initial_mode="mode"
></cobalt-form>
<cobalt-form
v-if="page === 'cobalt.form' && !form_id"
:resource="resource"
:initial_mode="mode"
></cobalt-form>
<cobalt-listing
v-if="page === 'cobalt.listing'"
:resource="resource"
></cobalt-listing>
</span>
`
export default class RootPageComponent extends Component {
static get selector() { return 'coreid-root' }
static get template() { return template }
static get props() { return ['page', 'form_id', 'resource', 'mode'] }
constructor() {
super()
}
}

View File

@ -33,8 +33,8 @@ export default class SideBarComponent extends Component {
this.possible_actions = [ this.possible_actions = [
{ {
text: 'Profile', text: 'Profile',
action: 'redirect', action: 'navigate',
next: '/dash/profile', page: 'dash.profile',
}, },
{ {
text: 'Users', text: 'Users',

View File

@ -8,7 +8,7 @@ import { utility } from '../../service/Utility.service.js'
import { profile_service } from '../../service/Profile.service.js' import { profile_service } from '../../service/Profile.service.js'
const template = ` const template = `
<div class="coreid-profile-container mb-5"> <div class="coreid-profile-container mb-5 offset-0 col-md-8 offset-md-2 col-xl-6 offset-xl-3">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">

View File

@ -40,10 +40,10 @@ class AppResource extends CRUDBase {
}, },
{ {
position: 'main', position: 'main',
action: 'redirect', action: 'navigate',
text: 'Setup Wizard', text: 'Setup Wizard',
color: 'success', color: 'success',
next: '/dash/app/setup', page: 'app.setup',
}, },
{ {
type: 'resource', type: 'resource',

View File

@ -1,5 +1,11 @@
import { location_service } from './Location.service.js' import { location_service } from './Location.service.js'
import { resource_service } from './Resource.service.js' import { resource_service } from './Resource.service.js'
import { event_bus } from './EventBus.service.js'
const pageMap = {
'dash.profile': '/dash/profile',
'app.setup': '/dash/app/setup',
}
class ActionService { class ActionService {
async perform({ text = '', action, ...args }) { async perform({ text = '', action, ...args }) {
@ -7,21 +13,44 @@ class ActionService {
if ( args.next ) { if ( args.next ) {
return location_service.redirect(args.next, args.delay || 0) return location_service.redirect(args.next, args.delay || 0)
} }
} else if ( action === 'navigate' ) {
if ( args.page && pageMap[args.page] ) {
window.history.pushState('pageNavigate', `Open ${args.page}`, pageMap[args.page])
return event_bus.event('root.navigate').fire(args)
}
} else if ( action === 'back' ) { } else if ( action === 'back' ) {
return location_service.back() return location_service.back()
} else if ( args.type === 'resource' ) { } else if ( args.type === 'resource' ) {
const { resource } = args const { resource } = args
if ( action === 'insert' ) { if ( action === 'insert' ) {
return location_service.redirect(`/dash/c/form/${resource}`, 0) window.history.pushState('cobaltForm', `Insert ${resource}`, `/dash/c/form/${resource}`)
return event_bus.event('root.navigate').fire({
page: 'cobalt.form',
resource,
mode: 'insert',
})
} else if ( action === 'update' ) { } else if ( action === 'update' ) {
const { id } = args const { id } = args
return location_service.redirect(`/dash/c/form/${resource}?id=${id}`, 0) window.history.pushState('cobaltForm', `Edit ${resource}`, `/dash/c/form/${resource}?id=${id}`)
return event_bus.event('root.navigate').fire({
page: 'cobalt.form',
resource,
mode: 'update',
form_id: id,
})
} else if ( action === 'delete' ) { } else if ( action === 'delete' ) {
const { id } = args const { id } = args
const rsc = await resource_service.get(resource) const rsc = await resource_service.get(resource)
await rsc.delete(id) await rsc.delete(id)
} else if ( action === 'list' ) { } else if ( action === 'list' ) {
return location_service.redirect(`/dash/c/listing/${resource}`, 0) window.history.pushState('cobaltListing', `View ${resource}`, `/dash/c/listing/${resource}`)
return event_bus.event('root.navigate').fire({
page: 'cobalt.listing',
resource,
})
} }
} else if ( action === 'post' ) { } else if ( action === 'post' ) {
const inputs = [] const inputs = []

View File

@ -4,5 +4,4 @@ block content
.cobalt-container .cobalt-container
.row.pad-top .row.pad-top
.col-12 .col-12
cobalt-form(v-if="form_id" :resource="resource" :form_id="form_id" :initial_mode="mode") coreid-outlet(initial_page="cobalt.form" :initial_resource="resource" :initial_form_id="form_id" :initial_mode="mode")
cobalt-form(v-if="!form_id" :resource="resource" :initial_mode="mode")

View File

@ -4,4 +4,4 @@ block content
.cobalt-container .cobalt-container
.row.pad-top .row.pad-top
.col-12 .col-12
cobalt-listing(:resource="resource") coreid-outlet(initial_page="cobalt.listing" :initial_resource="resource")

View File

@ -4,4 +4,4 @@ block content
.cobalt-container .cobalt-container
.row.pad-top .row.pad-top
.col-12 .col-12
coreid-app-setup coreid-outlet(initial_page="app.setup")

View File

@ -3,5 +3,5 @@ extends ../../theme/dash/base
block content block content
.profile-container .profile-container
.row.pad-top .row.pad-top
.col-12.offset-0.col-md-8.offset-md-2.col-xl-6.offset-xl-3 .col-12
coreid-profile-edit coreid-outlet(initial_page="dash.profile")