@oxygen-cms/ui 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.babelrc +1 -0
  2. package/.eslintrc.js +22 -0
  3. package/.github/workflows/node.js.yml +29 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/ui.iml +10 -0
  6. package/.jshintrc +3 -0
  7. package/README.md +7 -0
  8. package/assets/oxygen-icon.png +0 -0
  9. package/jest.init.js +1 -0
  10. package/package.json +72 -0
  11. package/src/AuthApi.js +116 -0
  12. package/src/CrudApi.js +112 -0
  13. package/src/EventsApi.js +16 -0
  14. package/src/GroupsApi.js +9 -0
  15. package/src/Internationalize.js +31 -0
  16. package/src/MediaApi.js +52 -0
  17. package/src/MediaDirectoryApi.js +62 -0
  18. package/src/PreferencesApi.js +47 -0
  19. package/src/UserPermissions.js +66 -0
  20. package/src/UserPreferences.js +69 -0
  21. package/src/UserPreferences.test.js +23 -0
  22. package/src/UsersApi.js +41 -0
  23. package/src/api.js +209 -0
  24. package/src/components/App.vue +61 -0
  25. package/src/components/AuthenticatedLayout.vue +254 -0
  26. package/src/components/AuthenticationLog.vue +196 -0
  27. package/src/components/CodeEditor.vue +90 -0
  28. package/src/components/EditButtonOnRowHover.vue +21 -0
  29. package/src/components/Error404.vue +25 -0
  30. package/src/components/EventsChooser.vue +88 -0
  31. package/src/components/EventsTable.vue +82 -0
  32. package/src/components/GenericEditableField.vue +74 -0
  33. package/src/components/GroupsChooser.vue +58 -0
  34. package/src/components/GroupsList.vue +129 -0
  35. package/src/components/ImportExport.vue +45 -0
  36. package/src/components/LegacyPage.vue +256 -0
  37. package/src/components/UserJoined.vue +35 -0
  38. package/src/components/UserManagement.vue +168 -0
  39. package/src/components/UserProfileForm.vue +214 -0
  40. package/src/components/ViewProfile.vue +32 -0
  41. package/src/components/auth/Auth404.vue +16 -0
  42. package/src/components/auth/Login.vue +135 -0
  43. package/src/components/auth/LoginLogo.vue +30 -0
  44. package/src/components/auth/Logout.vue +26 -0
  45. package/src/components/auth/PasswordRemind.vue +71 -0
  46. package/src/components/auth/PasswordReset.vue +97 -0
  47. package/src/components/auth/TwoFactorSetup.vue +115 -0
  48. package/src/components/auth/VerifyEmail.vue +71 -0
  49. package/src/components/auth/WelcomeFloat.vue +87 -0
  50. package/src/components/auth/login.scss +17 -0
  51. package/src/components/media/MediaChooseDirectory.vue +129 -0
  52. package/src/components/media/MediaDirectory.vue +109 -0
  53. package/src/components/media/MediaInsertModal.vue +88 -0
  54. package/src/components/media/MediaItem.vue +282 -0
  55. package/src/components/media/MediaItemPreview.vue +45 -0
  56. package/src/components/media/MediaList.vue +305 -0
  57. package/src/components/media/MediaPage.vue +44 -0
  58. package/src/components/media/MediaResponsiveImages.vue +51 -0
  59. package/src/components/media/MediaUpload.vue +133 -0
  60. package/src/components/media/media.scss +51 -0
  61. package/src/components/preferences/PreferencesAdminAppearance.vue +22 -0
  62. package/src/components/preferences/PreferencesAuthentication.vue +27 -0
  63. package/src/components/preferences/PreferencesEventTemplates.vue +22 -0
  64. package/src/components/preferences/PreferencesField.vue +215 -0
  65. package/src/components/preferences/PreferencesList.vue +50 -0
  66. package/src/components/preferences/PreferencesPageTemplates.vue +23 -0
  67. package/src/components/preferences/PreferencesSiteAppearance.vue +22 -0
  68. package/src/components/preferences/PreferencesThemeChooser.vue +73 -0
  69. package/src/components/preferences/ShowIfPermitted.vue +37 -0
  70. package/src/components/preferences/UserPreferences.vue +30 -0
  71. package/src/components/users/CreateUserModal.vue +73 -0
  72. package/src/components/util.css +47 -0
  73. package/src/icons.js +90 -0
  74. package/src/main.js +112 -0
  75. package/src/modules/LegacyPages.js +18 -0
  76. package/src/modules/Media.js +45 -0
  77. package/src/modules/UserManagement.js +24 -0
  78. package/src/routes/index.js +92 -0
  79. package/src/store/index.js +70 -0
  80. package/src/styles/_variables.scss +23 -0
  81. package/src/styles/app.scss +76 -0
  82. package/src/unsavedChanges.js +16 -0
  83. package/src/util.js +65 -0
  84. package/src/util.test.js +39 -0
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <ShowIfPermitted data-key="appearance.themes">
3
+ <h3 class="subtitle">Website Themes</h3>
4
+ <PreferencesField data-key="appearance.themes::theme" label="">
5
+ <template #default="slotProps">
6
+ <b-table
7
+ :data="Object.values(slotProps.options)"
8
+ :striped="false">
9
+ <b-table-column v-slot="props" label="Key">
10
+ <img :src="props.row.image" class="theme-logo" />
11
+ </b-table-column>
12
+
13
+ <b-table-column v-slot="props" field="name" label="Name">
14
+ {{ props.row.name }}
15
+ <strong v-if="getSelectedOption(slotProps.options, slotProps.value) === props.row">(current theme)</strong>
16
+ </b-table-column>
17
+
18
+ <b-table-column v-slot="props" field="provides" label="Provides preferences">
19
+ <div v-for="(provideGroup, keyGroup) in props.row.provides" :key="keyGroup" class="is-size-7">
20
+ <span v-for="(value, key) in provideGroup" :key="key"><code>{{ keyGroup }}::{{ key}}</code><br></span>
21
+ </div>
22
+ </b-table-column>
23
+
24
+ <b-table-column v-slot="props" label="">
25
+ <b-button v-if="getSelectedOption(slotProps.options, slotProps.value) !== props.row" :loading="updating" @click="switchToTheme(props.row.key, slotProps.updateValue)">Switch to this theme</b-button>
26
+ <b-button v-else type="is-success" disabled>Theme is already active</b-button>
27
+ </b-table-column>
28
+ </b-table>
29
+ </template>
30
+ </PreferencesField>
31
+ </ShowIfPermitted>
32
+ </template>
33
+
34
+ <script>
35
+ import PreferencesField from "./PreferencesField.vue";
36
+ import ShowIfPermitted from "./ShowIfPermitted.vue";
37
+ export default {
38
+ name: "PreferencesThemeChooser",
39
+ components: {ShowIfPermitted, PreferencesField},
40
+ data() {
41
+ return {
42
+ updating: false
43
+ }
44
+ },
45
+ methods: {
46
+ printTheme(theme) {
47
+ return theme.display.name;
48
+ },
49
+ getSelectedOption(options, value) {
50
+ return options[value];
51
+ },
52
+ async switchToTheme(value, updateFn) {
53
+ console.log(value);
54
+ this.updating = true;
55
+ await updateFn(value);
56
+ this.updating = false;
57
+ this.$emit('theme-changed', value);
58
+ }
59
+ }
60
+ }
61
+ </script>
62
+
63
+ <style scoped lang="scss">
64
+ .theme-logo {
65
+ display: block;
66
+ max-width: 10rem;
67
+ margin: 0 auto;
68
+ }
69
+
70
+ .b-table ::v-deep .table td {
71
+ vertical-align: middle;
72
+ }
73
+ </style>
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div v-show="permitted">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ import {canAccessPrefs} from "../../PreferencesApi";
9
+
10
+ export default {
11
+ name: "ShowIfPermitted",
12
+ props: {
13
+ dataKey: {
14
+ type: String,
15
+ default: null
16
+ },
17
+ keys: {
18
+ type: Array,
19
+ default: null
20
+ }
21
+ },
22
+ computed: {
23
+ keysArray() {
24
+ if(this.keys === null) {
25
+ return [this.dataKey];
26
+ } else {
27
+ return this.keys;
28
+ }
29
+ },
30
+ permitted() { return canAccessPrefs(this.$buefy, this.$store.getters.userPermissions, this.keysArray); }
31
+ }
32
+ }
33
+ </script>
34
+
35
+ <style scoped>
36
+
37
+ </style>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <div>
3
+ <h3 class="subtitle">General</h3>
4
+ <PreferencesField label="Font Size" data-key="user.general::fontSize" type="select" default-text="group"></PreferencesField>
5
+ <h3 class="subtitle">Editor</h3>
6
+ <PreferencesField label="Default Mode" data-key="user.editor::defaultMode" type="select" default-text="group"></PreferencesField>
7
+ <PreferencesField label="Overall Theme" data-key="user.editor::theme" type="select" default-text="group"></PreferencesField>
8
+ <h4 class="subtitle is-6">Code Editor</h4>
9
+ <PreferencesField label="Theme" data-key="user.editor::ace.theme" type="select" grouped default-text="group"></PreferencesField>
10
+ <PreferencesField label="Font Size" data-key="user.editor::ace.fontSize" type="select" default-text="group"></PreferencesField>
11
+ <PreferencesField label="Word Wrap" data-key="user.editor::ace.wordWrap" type="switch" default-text="group"></PreferencesField>
12
+ <PreferencesField label="Highlight Active Line" data-key="user.editor::ace.highlightActiveLine" type="switch" default-text="group"></PreferencesField>
13
+ <PreferencesField label="Show Print Margin" data-key="user.editor::ace.showPrintMargin" type="switch" default-text="group"></PreferencesField>
14
+ <PreferencesField label="Show Invisibles" data-key="user.editor::ace.showInvisibles" type="switch" default-text="group"></PreferencesField>
15
+ <h4 class="subtitle is-6">Design Editor</h4>
16
+ <PreferencesField label="Theme" data-key="user.editor::ckeditor.skin" type="select" grouped default-text="group"></PreferencesField>
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ import PreferencesField from "./PreferencesField.vue";
22
+ export default {
23
+ name: "UserPreferences",
24
+ components: {PreferencesField}
25
+ }
26
+ </script>
27
+
28
+ <style scoped>
29
+
30
+ </style>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <b-modal :closable="false" :active="active" has-modal-card trap-focus aria-role="dialog" aria-modal @update:active="a => $emit('update:active', a)">
3
+ <div class="modal-card" style="overflow: visible">
4
+ <header class="modal-card-head">
5
+ <p class="modal-card-title">
6
+ <b-icon icon="users" size="is-normal" class="push-right"></b-icon>
7
+ Create Account
8
+ </p>
9
+ </header>
10
+ <section class="modal-card-body" style="overflow: visible">
11
+ <b-field label="Username">
12
+ <b-input v-model="username" placeholder="e.g.: johndoe"></b-input>
13
+ </b-field>
14
+ <b-field label="Email Address">
15
+ <b-input v-model="email" type="email" placeholder="e.g.: example@example.com"></b-input>
16
+ </b-field>
17
+ <b-field label="Full Name">
18
+ <b-input v-model="fullName" placeholder="e.g.: John Doe"></b-input>
19
+ </b-field>
20
+ <b-field label="Group">
21
+ <GroupsChooser :value="group" @select="g => group = g" />
22
+ </b-field>
23
+ </section>
24
+ <footer class="modal-card-foot is-flex">
25
+ <div class="is-flex-grow-1"></div>
26
+ <b-button @click="$emit('update:active', false)">Cancel</b-button>
27
+ <b-button type="is-primary" :loading="submitting" @click="submit">Create Account</b-button>
28
+ </footer>
29
+ </div>
30
+ </b-modal>
31
+ </template>
32
+
33
+ <script>
34
+ import GroupsChooser from "../GroupsChooser.vue";
35
+ import UsersApi from "../../UsersApi";
36
+ import {morphToNotification} from "../../api";
37
+ export default {
38
+ name: "CreateUserModal",
39
+ components: {GroupsChooser},
40
+ props: {
41
+ active: { type: Boolean, required: true }
42
+ },
43
+ data() {
44
+ return {
45
+ username: '',
46
+ email: '',
47
+ fullName: '',
48
+ group: null,
49
+ submitting: false,
50
+ usersApi: new UsersApi(this.$buefy)
51
+ }
52
+ },
53
+ methods: {
54
+ async submit() {
55
+ let data = { username: this.username, email: this.email, fullName: this.fullName, group: this.group };
56
+ try {
57
+ this.submitting = true;
58
+ let response = await this.usersApi.create(data);
59
+ this.$buefy.notification.open(morphToNotification(response));
60
+ this.$emit('update:active', false);
61
+ this.$emit('update:users');
62
+ } catch(e) {
63
+ // let the user try again
64
+ }
65
+ this.submitting = false;
66
+ }
67
+ }
68
+ }
69
+ </script>
70
+
71
+ <style scoped>
72
+
73
+ </style>
@@ -0,0 +1,47 @@
1
+ .full-height-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ }
5
+ .column.full-height-container {
6
+ display: flex;
7
+ }
8
+ .box.full-height-container {
9
+ display: flex;
10
+ }
11
+
12
+ .scroll-container.pad,
13
+ .full-height-container.pad {
14
+ padding: 2em;
15
+ }
16
+
17
+ .full-height-flex {
18
+ flex: 1 1 auto;
19
+ }
20
+
21
+ .full-height {
22
+ height: 100%;
23
+ }
24
+
25
+ .scroll-container {
26
+ overflow-y: auto;
27
+ }
28
+
29
+ .transition-element.is-loading {
30
+ margin: 2rem auto;
31
+ max-width: 100%;
32
+ width: 30em;
33
+ }
34
+
35
+ .top-bar {
36
+ display: flex;
37
+ align-items: center;
38
+ margin-bottom: 1rem;
39
+ }
40
+
41
+ .top-bar .title {
42
+ margin-bottom: 0;
43
+ }
44
+
45
+ .top-bar .title:not(:first-child) {
46
+ margin-left: 1rem;
47
+ }
package/src/icons.js ADDED
@@ -0,0 +1,90 @@
1
+ import { library } from '@fortawesome/fontawesome-svg-core';
2
+
3
+ // internal icons
4
+ import {
5
+ faCheck,
6
+ faCheckCircle,
7
+ faInfoCircle,
8
+ faExternalLinkAlt,
9
+ faExclamationTriangle,
10
+ faExclamationCircle,
11
+ faArrowUp,
12
+ faAngleRight,
13
+ faAngleLeft,
14
+ faAngleDown,
15
+ faEye,
16
+ faEyeSlash,
17
+ faCaretDown,
18
+ faCaretUp,
19
+ faUpload,
20
+ faPlus,
21
+ faCogs,
22
+ faPuzzlePiece,
23
+ faPhotoVideo,
24
+ faUserPlus,
25
+ faMailBulk,
26
+ faUsers,
27
+ faArrowLeft,
28
+ faRecycle,
29
+ faList,
30
+ faFileAlt,
31
+ faFile,
32
+ faFileAudio,
33
+ faFileImage,
34
+ faFilePdf,
35
+ faUserAlt,
36
+ faStamp,
37
+ faCalendarAlt,
38
+ faAddressCard,
39
+ faFileImport,
40
+ faUser,
41
+ faFileExport,
42
+ faDownload,
43
+ faFileExcel,
44
+ faFileCsv,
45
+ faChevronCircleDown,
46
+ faChevronCircleUp,
47
+ faTrash,
48
+ faSearch,
49
+ faBan,
50
+ faShare,
51
+ faTicketAlt,
52
+ faPencilAlt,
53
+ faRedoAlt,
54
+ faTags,
55
+ faLock,
56
+ faUserSlash,
57
+ faUsersCog,
58
+ faMusic,
59
+ faCalendarDay,
60
+ faTimesCircle,
61
+ faEnvelope,
62
+ faUserCog,
63
+ faFolder,
64
+ faHome,
65
+ faSignInAlt,
66
+ faUserEdit,
67
+ faSignOutAlt,
68
+ faTag,
69
+ faFolderPlus,
70
+ faTimes,
71
+ faQuestionCircle,
72
+ faFileUpload,
73
+ faLandmark,
74
+ faFolderOpen,
75
+ faImages,
76
+ faMinusCircle
77
+ } from "@fortawesome/free-solid-svg-icons";
78
+
79
+ export const addIconsToLibrary = () => {
80
+ library.add(faCheck, faLock, faUserSlash, faUserEdit, faUsersCog, faMinusCircle, faSignInAlt,
81
+ faCheckCircle, faInfoCircle, faExclamationTriangle, faExclamationCircle, faFileAlt,
82
+ faArrowUp, faAngleRight, faEnvelope, faAngleLeft, faTicketAlt, faUserCog, faTags, faCalendarDay, faTimesCircle,
83
+ faMusic, faPencilAlt, faRedoAlt, faBan, faExternalLinkAlt,
84
+ faSearch, faAngleDown, faUserAlt, faCogs, faPhotoVideo, faPuzzlePiece, faPlus, faUserPlus, faMailBulk, faUsers,
85
+ faArrowLeft, faRecycle, faList, faStamp, faCalendarAlt, faAddressCard, faFileImport, faFileExport, faDownload,
86
+ faFileExcel, faFileCsv, faChevronCircleDown, faChevronCircleUp, faTrash,
87
+ faEye, faEyeSlash, faCaretDown, faCaretUp, faUpload, faUser, faFolder, faHome, faFilePdf, faSignOutAlt, faTag,
88
+ faFolderPlus, faTimes, faQuestionCircle, faFileUpload, faLandmark,
89
+ faFolderOpen, faFile, faFileAudio, faFileImage, faShare, faImages);
90
+ };
package/src/main.js ADDED
@@ -0,0 +1,112 @@
1
+ import Router from 'vue-router';
2
+ import App from './components/App.vue';
3
+ import UserPermissions from './UserPermissions';
4
+ import UserPreferences from './UserPreferences';
5
+ import VHotkey from 'v-hotkey';
6
+ import Buefy from 'buefy';
7
+ import AsyncComputed from 'vue-async-computed';
8
+ import { FetchBuilder } from './api';
9
+ import { addIconsToLibrary } from './icons';
10
+ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
11
+ import { AuthRoutes, makeAuthenticatedRoute } from "./routes";
12
+ import createStore from "./store/index";
13
+ import { checkAuthenticated } from "./AuthApi";
14
+ import Error404 from "./components/Error404.vue";
15
+
16
+ /**
17
+ * Creates the Vue.js Oxygen application, allowing for a few points of customization (i.e.: adding modules)
18
+ * @param Vue
19
+ * @param extraRoutes
20
+ * @param extraComponents
21
+ * @param beforeMount
22
+ */
23
+ export default class OxygenUI {
24
+ app;
25
+
26
+ constructor(Vue) {
27
+ this.Vue = Vue;
28
+ this.authenticatedRoutes = []
29
+ this.unauthenticatedRoutes = []
30
+ this.rootComponents = { App }
31
+ this.beforeMountHooks = []
32
+ }
33
+
34
+ addAuthenticatedRoutes(routes) {
35
+ for (let route of routes) {
36
+ this.authenticatedRoutes.push(route);
37
+ }
38
+ }
39
+
40
+ addRoute(route) {
41
+ this.authenticatedRoutes.push(route);
42
+ }
43
+
44
+ addUnauthenticatedRoutes(routes) {
45
+ for (let route of routes) {
46
+ this.unauthenticatedRoutes.push(route);
47
+ }
48
+ }
49
+
50
+ registerModule(module) {
51
+ module(this)
52
+ }
53
+
54
+ createApp() {
55
+ // this could occur if we encounter a bad link inside the <LegacyPage> functionality
56
+ // TODO: remove this once <LegacyPage> is gone
57
+ if (window.location !== window.parent.location) {
58
+ throw new Error('refusing to load application inside of an iframe');
59
+ }
60
+
61
+ addIconsToLibrary();
62
+ this.Vue.component('vue-fontawesome', FontAwesomeIcon);
63
+ this.Vue.use(Buefy, {
64
+ defaultIconComponent: 'vue-fontawesome',
65
+ defaultIconPack: 'fas',
66
+ });
67
+ this.Vue.use(VHotkey);
68
+ this.Vue.use(AsyncComputed);
69
+ this.Vue.use(Router);
70
+
71
+ const store = createStore(this.Vue);
72
+
73
+ const routes = AuthRoutes
74
+ .concat([
75
+ makeAuthenticatedRoute(this.authenticatedRoutes)
76
+ ])
77
+ .concat(this.unauthenticatedRoutes)
78
+ .concat([{
79
+ path: '*',
80
+ name: 'error404',
81
+ component: Error404,
82
+ meta: {title: 'Not found'}
83
+ }]);
84
+
85
+ const router = new Router({
86
+ routes: routes,
87
+ base: '/oxygen/',
88
+ mode: 'history'
89
+ });
90
+
91
+ router.beforeEach(checkAuthenticated(store));
92
+
93
+ this.app = new this.Vue({
94
+ router: router,
95
+ components: this.rootComponents,
96
+ store
97
+ });
98
+
99
+ FetchBuilder.setRouter(router);
100
+ UserPermissions.setBuefy(this.app.$buefy);
101
+ UserPreferences.setBuefy(this.app.$buefy)
102
+ return this;
103
+ }
104
+
105
+ mount(selector) {
106
+ for(let hook of this.beforeMountHooks) {
107
+ hook(this.app);
108
+ }
109
+ this.app.$mount(selector);
110
+ }
111
+ }
112
+
@@ -0,0 +1,18 @@
1
+ import LegacyPage from "../components/LegacyPage.vue";
2
+
3
+ export default function(ui) {
4
+ ui.addAuthenticatedRoutes([
5
+ {
6
+ // will match everything, try to render a legacy Oxygen page...
7
+ path: '(pages|partials|upcoming-events)/:subpath*',
8
+ component: LegacyPage,
9
+ props: (route) => {
10
+ return {
11
+ fullPath: route.fullPath,
12
+ legacyPrefix: '/oxygen/view',
13
+ adminPrefix: '/oxygen'
14
+ }
15
+ }
16
+ }
17
+ ]);
18
+ }
@@ -0,0 +1,45 @@
1
+ import MediaPage from "../components/media/MediaPage.vue";
2
+ import MediaResponsiveImages from "../components/media/MediaResponsiveImages.vue";
3
+
4
+ export default function(ui) {
5
+ ui.addAuthenticatedRoutes([
6
+ {
7
+ path: 'media/list/:currentPath(.*)?',
8
+ name: 'media.list',
9
+ props: true,
10
+ component: MediaPage,
11
+ meta: { title: 'Photos & File Uploads'}
12
+ },
13
+ {
14
+ path: 'media/list',
15
+ props: {
16
+ currentPath: ''
17
+ },
18
+ component: MediaPage,
19
+ meta: { title: 'Photos & File Uploads'}
20
+ },
21
+ {
22
+ path: 'media/trash',
23
+ name: 'media.trash',
24
+ props: {
25
+ inTrash: true,
26
+ currentPath: ''
27
+ },
28
+ component: MediaPage,
29
+ meta: { title: 'Deleted Photos & File Uploads'}
30
+ },
31
+ {
32
+ path: 'media/search/:searchQuery',
33
+ name: 'media.search',
34
+ props: true,
35
+ component: MediaPage,
36
+ meta: { title: 'Search Photos & File Uploads'}
37
+ },
38
+ {
39
+ path: 'media/responsive-images',
40
+ name: 'media.responsiveImages',
41
+ component: MediaResponsiveImages,
42
+ meta: { title: 'Responsive Images'}
43
+ }
44
+ ]);
45
+ }
@@ -0,0 +1,24 @@
1
+ import ViewProfile from "../components/ViewProfile.vue";
2
+ import AuthenticationLog from "../components/AuthenticationLog.vue";
3
+ import UserManagement from "../components/UserManagement.vue";
4
+
5
+ export default function(ui) {
6
+ ui.addAuthenticatedRoutes([
7
+ {
8
+ path: 'user/profile',
9
+ name: 'auth.viewProfile',
10
+ component: ViewProfile,
11
+ meta: { title: 'View Profile' }
12
+ },
13
+ {
14
+ path: 'user/login-log',
15
+ component: AuthenticationLog,
16
+ meta: { title: 'Logins & Login Attempts' }
17
+ },
18
+ {
19
+ path: 'users',
20
+ component: UserManagement,
21
+ meta: { title: 'Manage Users'}
22
+ }
23
+ ]);
24
+ }
@@ -0,0 +1,92 @@
1
+ import AuthenticatedLayout from "../components/AuthenticatedLayout.vue";
2
+ import Login from "../components/auth/Login.vue";
3
+ import Logout from "../components/auth/Logout.vue";
4
+ import WelcomeFloat from "../components/auth/WelcomeFloat.vue";
5
+ import TwoFactorSetup from "../components/auth/TwoFactorSetup.vue";
6
+ import PasswordRemind from "../components/auth/PasswordRemind.vue";
7
+ import PasswordReset from "../components/auth/PasswordReset.vue";
8
+ import Auth404 from "../components/auth/Auth404.vue";
9
+ import VerifyEmail from "../components/auth/VerifyEmail.vue";
10
+
11
+ export const AuthRoutes = [
12
+ {
13
+ path: '/auth',
14
+ component: WelcomeFloat,
15
+ meta: {
16
+ allowUnauthenticated: true
17
+ },
18
+ children: [
19
+ {
20
+ name: 'login',
21
+ path: 'login',
22
+ component: Login,
23
+ meta: {
24
+ title: 'Login',
25
+ allowUnauthenticated: true
26
+ }
27
+ },
28
+ {
29
+ name: 'logout',
30
+ path: 'logout',
31
+ component: Logout,
32
+ meta: {
33
+ title: 'Logout',
34
+ allowUnauthenticated: true
35
+ }
36
+ },
37
+ {
38
+ name: '2fa-setup',
39
+ path: '2fa-setup',
40
+ component: TwoFactorSetup,
41
+ meta: {
42
+ title: 'Setup two factor authentication'
43
+ }
44
+ },
45
+ {
46
+ name: 'forgot-password',
47
+ path: 'forgot-password',
48
+ component: PasswordRemind,
49
+ meta: {
50
+ title: 'Forgot Password',
51
+ allowUnauthenticated: true
52
+ }
53
+ },
54
+ {
55
+ name: 'reset-password',
56
+ path: 'reset-password',
57
+ component: PasswordReset,
58
+ meta: {
59
+ title: 'Reset Password',
60
+ allowUnauthenticated: true
61
+ }
62
+ },
63
+ {
64
+ name: 'needs-verified-email',
65
+ path: 'needs-verified-email',
66
+ component: VerifyEmail,
67
+ meta: {
68
+ title: 'Verify your email address'
69
+ }
70
+ },
71
+ {
72
+ path: '',
73
+ component: Auth404
74
+ },
75
+ {
76
+ path: '*',
77
+ component: Auth404
78
+ }
79
+ ]
80
+ }
81
+ ];
82
+
83
+ export const makeAuthenticatedRoute = (children) => {
84
+ return {
85
+ path: '/',
86
+ component: AuthenticatedLayout,
87
+ props: true,
88
+ redirect: '/dashboard',
89
+ children: children,
90
+ }
91
+ };
92
+