@oxygen-cms/ui 1.6.5 → 1.7.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.
- package/package.json +1 -1
- package/src/Internationalize.js +4 -0
- package/src/UsersApi.js +5 -0
- package/src/components/CodeEditor.vue +2 -0
- package/src/components/Created.vue +25 -0
- package/src/components/Updated.vue +25 -0
- package/src/components/UserProfileDescription.vue +41 -0
- package/src/components/UserProfileForm.vue +3 -24
- package/src/components/UserProfilePage.vue +88 -0
- package/src/icons.js +2 -2
- package/src/modules/UserManagement.js +7 -0
- package/src/EventsApi.js +0 -21
- package/src/components/EventsChooser.vue +0 -88
- package/src/components/EventsTable.vue +0 -82
- package/src/components/dashboard/EventsPanel.vue +0 -20
- package/src/modules/Events.js +0 -35
package/package.json
CHANGED
package/src/Internationalize.js
CHANGED
|
@@ -12,6 +12,10 @@ export default class Internationalize {
|
|
|
12
12
|
return format.format(date);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
static formatDateExtended(date) {
|
|
16
|
+
return new Date(date).toDateString();
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
static formatLastUpdated(updatedAt) {
|
|
16
20
|
let d = new Date(updatedAt);
|
|
17
21
|
return d.toDateString() + ' ' + d.toLocaleTimeString();
|
package/src/UsersApi.js
CHANGED
|
@@ -23,6 +23,11 @@ export default class UsersApi extends CrudApi {
|
|
|
23
23
|
.fetch(getApiRoot() + 'users/' + id + '/fullName');
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
async getBasic(id) {
|
|
27
|
+
return this.request('get')
|
|
28
|
+
.fetch(this.constructor.getResourceRoot() + '/' + id + '/basic');
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
async impersonate(id) {
|
|
27
32
|
return await this.request('post')
|
|
28
33
|
.fetch(getApiRoot() + 'users/' + id + '/impersonate');
|
|
@@ -35,8 +35,10 @@ import AceEditor from 'vue2-ace-editor';
|
|
|
35
35
|
// language extension pre-requisite...
|
|
36
36
|
import 'brace/ext/language_tools';
|
|
37
37
|
import 'brace/mode/html';
|
|
38
|
+
import 'brace/mode/json';
|
|
38
39
|
import 'brace/mode/twig';
|
|
39
40
|
import 'brace/snippets/html';
|
|
41
|
+
import 'brace/snippets/json';
|
|
40
42
|
import 'brace/snippets/twig';
|
|
41
43
|
import 'brace/theme/tomorrow_night_eighties';
|
|
42
44
|
import 'brace/theme/tomorrow_night';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span>
|
|
3
|
+
{{ Internationalize.formatLastUpdated(model.createdAt) }}<span v-if="model.createdBy">, by <router-link :to="'/users/' + model.createdBy.id">{{ model.createdBy.fullName }}</router-link></span>
|
|
4
|
+
</span>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import Internationalize from "../Internationalize";
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
name: "Created",
|
|
12
|
+
props: {
|
|
13
|
+
model: { type: Object, required: true }
|
|
14
|
+
},
|
|
15
|
+
data() {
|
|
16
|
+
return {
|
|
17
|
+
Internationalize
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span>
|
|
3
|
+
{{ Internationalize.formatLastUpdated(model.updatedAt) }}<span v-if="model.updatedBy">, by <router-link :to="'/users/' + model.updatedBy.id">{{ model.updatedBy.fullName }}</router-link></span>
|
|
4
|
+
</span>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import Internationalize from "../Internationalize";
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
name: "Created",
|
|
12
|
+
props: {
|
|
13
|
+
model: { type: Object, required: true }
|
|
14
|
+
},
|
|
15
|
+
data() {
|
|
16
|
+
return {
|
|
17
|
+
Internationalize
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="content">
|
|
3
|
+
<div class="level level-left">
|
|
4
|
+
<strong class="mr-2">Username:</strong>
|
|
5
|
+
<span v-if="user">{{ user.username }}
|
|
6
|
+
<b-tooltip v-if="editable" label="To change username, please contact your administrator." position="is-right" multilined><b-icon icon="info-circle"></b-icon></b-tooltip>
|
|
7
|
+
</span>
|
|
8
|
+
</div>
|
|
9
|
+
<div class="level level-left"><strong class="mr-2">Group: </strong>
|
|
10
|
+
<transition name="fade" mode="out-in">
|
|
11
|
+
<span v-if="user">{{ user.group.name }}
|
|
12
|
+
<b-tooltip :label="user.group.description" position="is-right" multilined><b-icon icon="info-circle"></b-icon></b-tooltip>
|
|
13
|
+
</span>
|
|
14
|
+
<b-skeleton v-else width="20%" :animated="true" />
|
|
15
|
+
</transition>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="level level-left"><strong class="mr-2">Joined: </strong>
|
|
18
|
+
<transition name="fade" mode="out-in">
|
|
19
|
+
<UserJoined v-if="user" :user="user" />
|
|
20
|
+
<b-skeleton v-else width="20%" :animated="true" />
|
|
21
|
+
</transition>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
import UserJoined from "./UserJoined.vue";
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
name: "UserProfileDescription",
|
|
31
|
+
components: { UserJoined },
|
|
32
|
+
props: {
|
|
33
|
+
user: { type: Object, default: null },
|
|
34
|
+
editable: { type: Boolean, required: true }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
|
|
41
|
+
</style>
|
|
@@ -19,28 +19,7 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
|
-
<
|
|
23
|
-
<div class="level level-left">
|
|
24
|
-
<strong class="mr-2">Username:</strong>
|
|
25
|
-
<span>{{ user.username }}
|
|
26
|
-
<b-tooltip label="To change username, please contact your administrator." position="is-right" multilined><b-icon icon="info-circle"></b-icon></b-tooltip>
|
|
27
|
-
</span>
|
|
28
|
-
</div>
|
|
29
|
-
<div class="level level-left"><strong class="mr-2">Group: </strong>
|
|
30
|
-
<transition name="fade" mode="out-in">
|
|
31
|
-
<span v-if="user">{{ user.group.name }}
|
|
32
|
-
<b-tooltip :label="user.group.description" position="is-right" multilined><b-icon icon="info-circle"></b-icon></b-tooltip>
|
|
33
|
-
</span>
|
|
34
|
-
<b-skeleton v-else width="20%" :animated="true" />
|
|
35
|
-
</transition>
|
|
36
|
-
</div>
|
|
37
|
-
<div class="level level-left"><strong class="mr-2">Joined: </strong>
|
|
38
|
-
<transition name="fade" mode="out-in">
|
|
39
|
-
<UserJoined v-if="user" :user="user" />
|
|
40
|
-
<b-skeleton v-else width="20%" :animated="true" />
|
|
41
|
-
</transition>
|
|
42
|
-
</div>
|
|
43
|
-
</div>
|
|
22
|
+
<UserProfileDescription :user="user" :editable="true"></UserProfileDescription>
|
|
44
23
|
|
|
45
24
|
<b-modal :closable="false" :active.sync="isUserPreferencesModalActive" has-modal-card trap-focus aria-role="dialog" aria-modal>
|
|
46
25
|
<div class="modal-card">
|
|
@@ -136,16 +115,16 @@
|
|
|
136
115
|
|
|
137
116
|
<script>
|
|
138
117
|
import {morphToNotification} from "../api";
|
|
139
|
-
import UserJoined from "./UserJoined.vue";
|
|
140
118
|
import ShowIfPermitted from "./preferences/ShowIfPermitted.vue";
|
|
141
119
|
import UserPreferences from "./preferences/UserPreferences.vue";
|
|
142
120
|
import UsersApi from "../UsersApi";
|
|
143
121
|
import AuthApi from "../AuthApi";
|
|
144
122
|
import GenericEditableField from "./GenericEditableField.vue";
|
|
123
|
+
import UserProfileDescription from "./UserProfileDescription.vue";
|
|
145
124
|
|
|
146
125
|
export default {
|
|
147
126
|
name: "UserProfileForm",
|
|
148
|
-
components: {GenericEditableField, ShowIfPermitted,
|
|
127
|
+
components: {UserProfileDescription, GenericEditableField, ShowIfPermitted, UserPreferences },
|
|
149
128
|
props: {
|
|
150
129
|
user: {
|
|
151
130
|
type: Object,
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="full-height-container pad">
|
|
3
|
+
|
|
4
|
+
<div class="box middle-of-page">
|
|
5
|
+
|
|
6
|
+
<div>
|
|
7
|
+
<div class="has-background-grey-light huge-icon-container" style="display: inline-block;">
|
|
8
|
+
<b-icon icon="user" size="is-large" class="has-text-grey-lighter huge-icon"></b-icon>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<h2 class="title">
|
|
13
|
+
<transition name="fade" mode="out-in">
|
|
14
|
+
<span v-if="model">{{model.fullName}}</span>
|
|
15
|
+
<b-skeleton :active="!model" size="is-medium"></b-skeleton>
|
|
16
|
+
</transition>
|
|
17
|
+
</h2>
|
|
18
|
+
<h3 class="subtitle">
|
|
19
|
+
<transition name="fade" mode="out-in">
|
|
20
|
+
<a v-if="model" :href="'mailto:' + model.email">{{ model.email }}</a>
|
|
21
|
+
<b-skeleton :active="!model"></b-skeleton>
|
|
22
|
+
</transition>
|
|
23
|
+
</h3>
|
|
24
|
+
|
|
25
|
+
<div v-if="model && model.id == currentUserId">
|
|
26
|
+
<b-button type="is-primary" tag="router-link" to="/user/profile">Edit Your Profile</b-button>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<hr>
|
|
30
|
+
|
|
31
|
+
<UserProfileDescription :user="model" :editable="false"></UserProfileDescription>
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script>
|
|
38
|
+
import UsersApi from "../UsersApi";
|
|
39
|
+
import UserProfileDescription from "./UserProfileDescription.vue";
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
name: "UserProfilePage",
|
|
43
|
+
components: {UserProfileDescription},
|
|
44
|
+
data() {
|
|
45
|
+
return {
|
|
46
|
+
model: null,
|
|
47
|
+
loading: true,
|
|
48
|
+
usersApi: new UsersApi(this.$buefy)
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
computed: {
|
|
52
|
+
currentUserId() {
|
|
53
|
+
return this.$store.state.user.id;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
created() {
|
|
57
|
+
this.fetchData();
|
|
58
|
+
},
|
|
59
|
+
methods: {
|
|
60
|
+
async fetchData() {
|
|
61
|
+
this.model = (await this.usersApi.getBasic(this.$route.params.id)).item;
|
|
62
|
+
this.loading = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<style scoped>
|
|
69
|
+
@import '~@oxygen-cms/ui/src/components/util.css';
|
|
70
|
+
|
|
71
|
+
.middle-of-page {
|
|
72
|
+
width: 40rem;
|
|
73
|
+
max-width: 100%;
|
|
74
|
+
margin-left: auto;
|
|
75
|
+
margin-right: auto;
|
|
76
|
+
text-align: center;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.huge-icon {
|
|
80
|
+
width: 10rem;
|
|
81
|
+
height: 10rem;
|
|
82
|
+
font-size: 3rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.huge-icon-container {
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
}
|
|
88
|
+
</style>
|
package/src/icons.js
CHANGED
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
faFolderOpen,
|
|
75
75
|
faImages,
|
|
76
76
|
faMinusCircle,
|
|
77
|
-
faCalendarPlus, faPaperPlane, faHandshakeSlash, faHandshake
|
|
77
|
+
faCalendarPlus, faPaperPlane, faHandshakeSlash, faHandshake, faExclamation, faMousePointer, faUnlink, faAngry
|
|
78
78
|
} from "@fortawesome/free-solid-svg-icons";
|
|
79
79
|
|
|
80
80
|
export const addIconsToLibrary = () => {
|
|
@@ -87,5 +87,5 @@ export const addIconsToLibrary = () => {
|
|
|
87
87
|
faFileExcel, faFileCsv, faChevronCircleDown, faChevronCircleUp, faTrash,
|
|
88
88
|
faEye, faEyeSlash, faCaretDown, faCaretUp, faUpload, faUser, faFolder, faHome, faFilePdf, faSignOutAlt, faTag,
|
|
89
89
|
faFolderPlus, faTimes, faQuestionCircle, faFileUpload, faLandmark,
|
|
90
|
-
faFolderOpen, faFile, faFileAudio, faFileImage, faShare, faImages, faCalendarPlus, faPaperPlane, faHandshake, faHandshakeSlash);
|
|
90
|
+
faFolderOpen, faFile, faFileAudio, faFileImage, faShare, faImages, faCalendarPlus, faPaperPlane, faHandshake, faHandshakeSlash, faExclamation, faMousePointer, faUnlink, faAngry);
|
|
91
91
|
};
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import ViewProfile from "../components/ViewProfile.vue";
|
|
2
2
|
import AuthenticationLog from "../components/AuthenticationLog.vue";
|
|
3
3
|
import UserManagement from "../components/UserManagement.vue";
|
|
4
|
+
import UserProfilePage from "../components/UserProfilePage.vue";
|
|
4
5
|
|
|
5
6
|
export default function(ui) {
|
|
6
7
|
ui.addAuthenticatedRoutes([
|
|
8
|
+
{
|
|
9
|
+
path: 'users/:id',
|
|
10
|
+
name: 'users.viewProfile',
|
|
11
|
+
component: UserProfilePage,
|
|
12
|
+
meta: { title: 'User Profile' }
|
|
13
|
+
},
|
|
7
14
|
{
|
|
8
15
|
path: 'user/profile',
|
|
9
16
|
name: 'auth.viewProfile',
|
package/src/EventsApi.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { CrudApi } from './CrudApi';
|
|
2
|
-
|
|
3
|
-
export default class EventsApi extends CrudApi {
|
|
4
|
-
|
|
5
|
-
static prepareModelForAPI(data) {
|
|
6
|
-
let m = { ...data };
|
|
7
|
-
delete m.id;
|
|
8
|
-
delete m.bookings;
|
|
9
|
-
return m;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static getResourceName() {
|
|
13
|
-
return 'upcoming-events';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async listTrybookingSessions() {
|
|
17
|
-
return this.request('get')
|
|
18
|
-
.fetch(this.constructor.getResourceRoot() + '/trybooking-sessions');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<b-modal :active="active" trap-focus
|
|
3
|
-
aria-role="dialog"
|
|
4
|
-
aria-modal
|
|
5
|
-
@update:active="arg => $emit('update:active', arg)">
|
|
6
|
-
<div class="modal-card" style="width: auto">
|
|
7
|
-
<header class="modal-card-head">
|
|
8
|
-
<p class="modal-card-title">
|
|
9
|
-
<slot name="title">Choose an event</slot>
|
|
10
|
-
</p>
|
|
11
|
-
<button
|
|
12
|
-
type="button"
|
|
13
|
-
class="delete"
|
|
14
|
-
@click="$emit('update:active', false)"/>
|
|
15
|
-
</header>
|
|
16
|
-
<section class="modal-card-body full-height-container">
|
|
17
|
-
<slot name="explanation"></slot>
|
|
18
|
-
<b-field>
|
|
19
|
-
<b-input v-model="searchQuery"
|
|
20
|
-
placeholder="Search..."
|
|
21
|
-
type="search" icon="search" rounded>
|
|
22
|
-
</b-input>
|
|
23
|
-
</b-field>
|
|
24
|
-
<EventsTable :paginated-items="eventsPaginatedItems" :on-page-change="(page) => eventsPaginatedItems.currentPage = page">
|
|
25
|
-
<template #actions="slotProps">
|
|
26
|
-
<div class="buttons" style="flex-wrap: nowrap;">
|
|
27
|
-
<b-button icon-left="calendar-alt" size="is-small" tag="a" :href="'/oxygen/upcoming-events/' + slotProps.row.id + '/edit'" style="margin-left: 0.5rem;" rounded>Go to event</b-button>
|
|
28
|
-
<b-button rounded :type="disableEvent(slotProps.row) ? '' : 'is-success'" :disabled="disableEvent(slotProps.row)" @click="$emit('selected', slotProps.row)">Choose</b-button>
|
|
29
|
-
</div>
|
|
30
|
-
</template>
|
|
31
|
-
</EventsTable>
|
|
32
|
-
</section>
|
|
33
|
-
</div>
|
|
34
|
-
</b-modal>
|
|
35
|
-
</template>
|
|
36
|
-
|
|
37
|
-
<script>
|
|
38
|
-
import EventsApi from "../EventsApi";
|
|
39
|
-
import EventsTable from './EventsTable.vue';
|
|
40
|
-
|
|
41
|
-
export default {
|
|
42
|
-
name: "EventsChooser",
|
|
43
|
-
components: { EventsTable },
|
|
44
|
-
props: {
|
|
45
|
-
active: Boolean,
|
|
46
|
-
disableEvent: {
|
|
47
|
-
type: Function,
|
|
48
|
-
default: () => { return false; }
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
data() {
|
|
52
|
-
return {
|
|
53
|
-
eventsPaginatedItems: { items: null, itemsPerPage: null, totalItems: null, loading: false, currentPage: null },
|
|
54
|
-
eventsApi: new EventsApi(this.$buefy),
|
|
55
|
-
searchQuery: '',
|
|
56
|
-
searchDebounce: null
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
watch: {
|
|
60
|
-
'searchQuery': 'debounceFetchData',
|
|
61
|
-
'eventsPaginatedItems.currentPage': 'fetchData'
|
|
62
|
-
},
|
|
63
|
-
async created() {
|
|
64
|
-
await this.fetchData()
|
|
65
|
-
},
|
|
66
|
-
methods: {
|
|
67
|
-
async fetchData() {
|
|
68
|
-
this.eventsPaginatedItems.loading = true;
|
|
69
|
-
|
|
70
|
-
let data = await this.eventsApi.list(false, this.eventsPaginatedItems.currentPage, this.searchQuery !== '' ? this.searchQuery : null);
|
|
71
|
-
this.eventsPaginatedItems.items = data.items;
|
|
72
|
-
this.eventsPaginatedItems.itemsPerPage = data.itemsPerPage;
|
|
73
|
-
this.eventsPaginatedItems.totalItems = data.totalItems;
|
|
74
|
-
this.eventsPaginatedItems.loading = false;
|
|
75
|
-
},
|
|
76
|
-
debounceFetchData() {
|
|
77
|
-
clearTimeout(this.searchDebounce)
|
|
78
|
-
this.searchDebounce = setTimeout(() => {
|
|
79
|
-
this.fetchData();
|
|
80
|
-
}, 400);
|
|
81
|
-
},
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
</script>
|
|
85
|
-
|
|
86
|
-
<style scoped>
|
|
87
|
-
|
|
88
|
-
</style>
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<b-table
|
|
4
|
-
:data="paginatedItems === null || paginatedItems.items === null ? [] : paginatedItems.items"
|
|
5
|
-
:checked-rows="checkedRows"
|
|
6
|
-
:loading="paginatedItems.items === null || paginatedItems.loading"
|
|
7
|
-
:checkable="checkable"
|
|
8
|
-
custom-row-key="id"
|
|
9
|
-
:paginated="paginatedItems.totalItems > paginatedItems.itemsPerPage"
|
|
10
|
-
backend-pagination
|
|
11
|
-
:total="paginatedItems.totalItems"
|
|
12
|
-
:per-page="paginatedItems.itemsPerPage"
|
|
13
|
-
:current-page="paginatedItems.currentPage"
|
|
14
|
-
aria-next-label="Next page"
|
|
15
|
-
aria-previous-label="Previous page"
|
|
16
|
-
aria-page-label="Page"
|
|
17
|
-
aria-current-label="Current page"
|
|
18
|
-
class="full-height-flex full-height-container"
|
|
19
|
-
@update:checkedRows="$emit('update:checkedRows', $event)"
|
|
20
|
-
@page-change="onPageChange">
|
|
21
|
-
<b-table-column v-slot="props" label="Title">
|
|
22
|
-
{{ props.row.title }}
|
|
23
|
-
</b-table-column>
|
|
24
|
-
|
|
25
|
-
<b-table-column v-slot="props" label="Display on website">
|
|
26
|
-
<em v-if="!props.row.active">No</em>
|
|
27
|
-
<span v-else>{{ props.row.startDate ? new Date(props.row.startDate).toDateString() : '?'}} - {{ props.row.endDate ? new Date(props.row.endDate).toDateString() : '?'}}</span>
|
|
28
|
-
</b-table-column>
|
|
29
|
-
|
|
30
|
-
<b-table-column v-slot="props">
|
|
31
|
-
<slot name="actions" :row="props.row"></slot>
|
|
32
|
-
</b-table-column>
|
|
33
|
-
|
|
34
|
-
<template slot="empty">
|
|
35
|
-
<section class="section">
|
|
36
|
-
<div class="content has-text-grey has-text-centered">
|
|
37
|
-
<p>
|
|
38
|
-
<slot name="empty">
|
|
39
|
-
No events found.
|
|
40
|
-
</slot>
|
|
41
|
-
</p>
|
|
42
|
-
</div>
|
|
43
|
-
</section>
|
|
44
|
-
</template>
|
|
45
|
-
</b-table>
|
|
46
|
-
</div>
|
|
47
|
-
</template>
|
|
48
|
-
|
|
49
|
-
<script>
|
|
50
|
-
export default {
|
|
51
|
-
name: "EventsTable",
|
|
52
|
-
props: {
|
|
53
|
-
paginatedItems: {
|
|
54
|
-
type: Object,
|
|
55
|
-
required: true
|
|
56
|
-
},
|
|
57
|
-
onPageChange: {
|
|
58
|
-
type: Function,
|
|
59
|
-
required: true
|
|
60
|
-
},
|
|
61
|
-
checkedRows: {
|
|
62
|
-
type: Array,
|
|
63
|
-
default: () => { return []; }
|
|
64
|
-
},
|
|
65
|
-
checkable: Boolean
|
|
66
|
-
},
|
|
67
|
-
data() {
|
|
68
|
-
return {
|
|
69
|
-
};
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
</script>
|
|
73
|
-
|
|
74
|
-
<style scoped>
|
|
75
|
-
.b-table {
|
|
76
|
-
min-height: 10rem;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.b-table.is-loading {
|
|
80
|
-
margin-bottom: 5rem;
|
|
81
|
-
}
|
|
82
|
-
</style>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<article>
|
|
3
|
-
<p class="title">Events<b-icon icon="calendar-alt" size="is-medium"></b-icon></p>
|
|
4
|
-
<p class="subtitle">Promotion for upcoming concerts and events</p>
|
|
5
|
-
<div class="buttons">
|
|
6
|
-
<b-button tag="router-link" to="/upcoming-events" icon-left="list">Manage Events</b-button>
|
|
7
|
-
<b-button tag="router-link" to="/upcoming-events/create" icon-left="plus" type="is-success">Create New Event</b-button>
|
|
8
|
-
</div>
|
|
9
|
-
</article>
|
|
10
|
-
</template>
|
|
11
|
-
|
|
12
|
-
<script>
|
|
13
|
-
export default {
|
|
14
|
-
name: "EventsPanel"
|
|
15
|
-
}
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<style scoped lang="scss">
|
|
19
|
-
@import './panel.scss';
|
|
20
|
-
</style>
|
package/src/modules/Events.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import LegacyPage from "../components/LegacyPage.vue";
|
|
2
|
-
import { WEB_CONTENT } from "../main.js";
|
|
3
|
-
import PreferencesEventTemplates from "../components/preferences/PreferencesEventTemplates.vue";
|
|
4
|
-
|
|
5
|
-
export default function(ui) {
|
|
6
|
-
ui.addMainMenuGroup(WEB_CONTENT, {
|
|
7
|
-
name: 'Events',
|
|
8
|
-
icon: 'calendar-alt',
|
|
9
|
-
listAction: '/upcoming-events',
|
|
10
|
-
listPermission: 'upcomingEvents.getList',
|
|
11
|
-
addIcon: 'calendar-plus',
|
|
12
|
-
addPermission: 'upcomingEvents.postCreate',
|
|
13
|
-
addAction: '/upcoming-events/create',
|
|
14
|
-
items: {
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
ui.extraPrefs['appearance'].push({
|
|
18
|
-
key: 'appearance.events',
|
|
19
|
-
component: PreferencesEventTemplates
|
|
20
|
-
});
|
|
21
|
-
ui.addAuthenticatedRoutes([
|
|
22
|
-
{
|
|
23
|
-
// will match everything, try to render a legacy Oxygen page...
|
|
24
|
-
path: 'upcoming-events/:subpath*',
|
|
25
|
-
component: LegacyPage,
|
|
26
|
-
props: (route) => {
|
|
27
|
-
return {
|
|
28
|
-
fullPath: route.fullPath,
|
|
29
|
-
legacyPrefix: '/oxygen/view',
|
|
30
|
-
adminPrefix: '/oxygen'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
]);
|
|
35
|
-
}
|