From 1ee0e6c1d7484930387438b7ebb15340595b5383 Mon Sep 17 00:00:00 2001 From: Christian Hofmaier Date: Sun, 24 Mar 2019 16:02:18 +0000 Subject: [eventmanager] Add module and functionality - list to show all events, buttons to create/delete events - can add groups/clients to event - can add blacklist to event --- server/api/configloader.js | 230 +++++--- server/api/events.js | 86 +++ server/api/roles.js | 18 +- server/migrations/20190226151600-create-event.js | 31 + .../20190226152330-create-client_x_event.js | 33 ++ .../20190226152400-create-group_x_event.js | 33 ++ server/models/client.js | 2 + server/models/event.js | 26 + server/models/group.js | 3 + webapp/src/components/EventModule.vue | 83 +++ webapp/src/components/EventModuleDelete.vue | 66 +++ webapp/src/components/EventModuleEdit.vue | 638 +++++++++++++++++++++ webapp/src/components/EventModuleEventList.vue | 85 +++ webapp/src/components/PermissionModule.vue | 4 +- webapp/src/components/PermissionModuleEdit.vue | 1 + webapp/src/components/PermissionModuleRoleList.vue | 2 +- webapp/src/config/dashboard.js | 4 +- webapp/src/config/i18n.js | 6 +- webapp/src/config/store.js | 4 +- webapp/src/store/events.js | 35 ++ 20 files changed, 1300 insertions(+), 90 deletions(-) create mode 100644 server/api/events.js create mode 100644 server/migrations/20190226151600-create-event.js create mode 100644 server/migrations/20190226152330-create-client_x_event.js create mode 100644 server/migrations/20190226152400-create-group_x_event.js create mode 100644 server/models/event.js create mode 100644 webapp/src/components/EventModule.vue create mode 100644 webapp/src/components/EventModuleDelete.vue create mode 100644 webapp/src/components/EventModuleEdit.vue create mode 100644 webapp/src/components/EventModuleEventList.vue create mode 100644 webapp/src/store/events.js diff --git a/server/api/configloader.js b/server/api/configloader.js index 2422693..0ede64f 100644 --- a/server/api/configloader.js +++ b/server/api/configloader.js @@ -1,70 +1,125 @@ /* global __appdir */ -const path = require('path') +var path = require('path') var db = require(path.join(__appdir, 'lib', 'sequelize')) var express = require('express') -var noAuthRouter = express.Router() +const { decorateApp } = require('@awaitjs/express') +var noAuthRouter = decorateApp(express.Router()) // if client in db -> load script (default if none is found), else load registration script -noAuthRouter.get('/:uuid', (req, res) => { +noAuthRouter.getAsync('/:uuid', async (req, res) => { const uuid = req.params.uuid res.setHeader('content-type', 'text/plain') - db.client.findOne({ where: { uuid: uuid }, include: ['groups'] }).then(client => { - if (client !== null) { - // Check for registration hooks. - if (client.registrationState !== null) { - // client is in registration state, load scripts - db.registrationhook.findOne({ where: { id: client.registrationState } }).then(hook => { - if (hook.type === 'IPXE') res.send(hook.script) - else if (hook.type === 'BASH') res.sendFile(path.join(__appdir, 'ipxe', 'minilinux.ipxe')) - }) + var client = await db.client.findOne({ where: { uuid: uuid }, include: ['groups', 'events'] }) + if (client !== null) { + // Client is in db, check for registration hooks. + if (client.registrationState !== null) { + // client is in registration state, load scripts + var hook = await db.registrationhook.findOne({ where: { id: client.registrationState } }) + if (hook.type === 'IPXE') res.send(hook.script) + else if (hook.type === 'BASH') res.sendFile(path.join(__appdir, 'ipxe', 'minilinux.ipxe')) + return + } + + var events = [] + var blacklist = [] + var importantEvents = [] + var groupIds = [] + var result + + for (let i = 0; i < client.events.length; i++) { + if (client.events[i].important) importantEvents.push(client.events[i]) + if (client.events[i].client_x_event.blacklist) blacklist.push(client.events[i].id) + else events.push(client.events[i]) + } + + importantEvents = importantEvents.filter(e => !blacklist.includes(e.id)) + importantEvents = importantEvents.map(e => e.config) + importantEvents = importantEvents.filter(c => c !== null) + importantEvents = importantEvents.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + if (importantEvents.length === 1) { + result = await createIpxeScript(importantEvents[0]) + res.send(result) + return + } + if (importantEvents.length > 1) { + result = await createDynamicMenu(importantEvents) + res.send(result) + return + } + + events = events.filter(e => !blacklist.includes(e.id)) + events = events.map(e => e.config) + events = events.filter(c => c !== null) + events = events.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + + groupIds = client.groups.map(x => x.id) + + var response = await fetchParentConfigs(groupIds, blacklist) + if (response.ids.length > 0) { + // Check if there is an important event + if (response.type === 'important') { + if (response.ids.length === 1) { + result = await createIpxeScript(response.ids[0]) + res.send(result) + return + } + if (response.ids.length > 1) { + result = await createDynamicMenu(response.ids) + res.send(result) + return + } + } + // No important event, use client event if existent + if (events.length === 1) { + result = await createIpxeScript(events[0]) + res.send(result) return } - - // client is in db - if (client.configId !== null) { - // client has a config - createIpxeScript(client.configId).then(response => { - res.send(response) - }) + if (events.length > 1) { + result = await createDynamicMenu(events) + res.send(result) return } - // client has no config, check parent groups - var parentIds = [] - var configIds = [] - for (var i = 0; i < client.groups.length; i++) { - // gather parent ids - parentIds.push(client.groups[i].id) + // No client event, use events of lowest parents + if (response.type === 'event') { + if (response.ids.length === 1) { + result = await createIpxeScript(response.ids[0]) + res.send(result) + return + } + if (response.ids.length > 1) { + result = await createDynamicMenu(response.ids) + res.send(result) + return + } + } + // No events, use client config + if (client.configId !== null) { + result = await createIpxeScript(client.configId) + res.send(result) + return } - if (parentIds.length !== 0) { - // client has a parent to look for - checkGroupsForConfigs(parentIds).then(response => { - configIds = response - if (configIds.length === 1) { - // only one parent has a config, load it - createIpxeScript(configIds[0]).then(response => { - res.send(response) - }) - return - } else if (configIds.length > 1) { - // multiple parents have a config, make dynamic menu - createDynamicMenu(configIds).then(response => { - res.send(response) - }) - return - } - // no parent has a config, load default - res.sendFile(path.join(__appdir, 'ipxe', 'default.ipxe')) - }) - } else { - // no config given, load default - res.sendFile(path.join(__appdir, 'ipxe', 'default.ipxe')) + // No client config, use configs of lowest parents + if (response.type === 'config') { + if (response.ids.length === 1) { + result = await createIpxeScript(response.ids[0]) + res.send(result) + return + } + if (response.ids.length > 1) { + result = await createDynamicMenu(response.ids) + res.send(result) + return + } } - } else { - // client not known, start registration - res.sendFile(path.join(__appdir, 'ipxe', 'registration.ipxe')) } - }) + // No config found, use default config + res.sendFile(path.join(__appdir, 'ipxe', 'default.ipxe')) + } else { + // client not known, start registration + res.sendFile(path.join(__appdir, 'ipxe', 'registration.ipxe')) + } }) // load config by given id @@ -77,32 +132,54 @@ noAuthRouter.get('/getconfig/:configId', (req, res) => { }) }) -// recursive iteration through the layers of parents until a config is found or no parents left -function checkGroupsForConfigs (groupIds) { +async function fetchParentConfigs(groupIds, blacklist) { + if (groupIds.length === 0) return {'ids': [], 'type': ''} + + var importantEvents = [] + var events = [] + var configs = [] var parentIds = [] - var configIds = [] - if (groupIds.length === 0) { - return configIds - } - return db.group.findAll({ where: { id: groupIds }, include: ['parents'] }).then(groups => { - groups.forEach(group => { - group.parents.forEach(parent => { - if (!parentIds.includes(parent.id)) { - parentIds.push(parent.id) - } - }) - if (group.configId !== null && !configIds.includes(group.configId)) { - configIds.push(group.configId) - } - }) - if (configIds.length !== 0 || parentIds.length === 0) { - return configIds - } else { - return checkGroupsForConfigs(parentIds).then(response => { - return response - }) + var newBlacklist = blacklist.slice(0) + + var groups = await db.group.findAll({ where: { id: groupIds }, include: ['parents', 'events'] }) + for (let i = 0; i < groups.length; i++) { + configs.push(groups[i].configId) + // groups[i].map(g => g.parents.map(p => p.id)) + for (let j = 0; j < groups[i].parents.length; j++) { + parentIds.push(groups[i].parents[j].id) } - }) + for (let j = 0; j < groups[i].events.length; j++) { + if (groups[i].events[j].important) importantEvents.push(groups[i].events[j]) + if (groups[i].events[j].group_x_event.blacklist) newBlacklist.push(groups[i].events[j].id) + else events.push(groups[i].events[j]) + } + } + + importantEvents = importantEvents.filter(e => !newBlacklist.includes(e.id)) + importantEvents = importantEvents.map(e => e.config) + importantEvents = importantEvents.filter(c => c !== null) + importantEvents = importantEvents.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + if (importantEvents.length > 0) return {'ids': importantEvents, 'type': 'important'} + + var response = await fetchParentConfigs(parentIds, newBlacklist) + + if (response.type === 'important') return response + + events = events.filter(e => !newBlacklist.includes(e.id)) + events = events.map(e => e.config) + events = events.filter(c => c !== null) + events = events.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + if (events.length > 0) return {'ids': events, 'type': 'event'} + + if (response.type === 'event') return response + + configs = configs.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + configs = configs.filter(c => c !== null) + if (configs.length > 0) return {'ids': configs, 'type': 'config'} + + if (response.type === 'config') return response + + return {'ids': [], 'type': ''} } // create the config script from database @@ -143,6 +220,7 @@ function createIpxeScript (id) { } // create dynamic menu to load the different given configs for a client +// TODO: Hardcoded Chain Port?! function createDynamicMenu (ids) { return db.config.findAll({ where: { id: ids } }).then(configs => { var script = '' diff --git a/server/api/events.js b/server/api/events.js new file mode 100644 index 0000000..96bf15e --- /dev/null +++ b/server/api/events.js @@ -0,0 +1,86 @@ +/* global __appdir */ +var path = require('path') +var db = require(path.join(__appdir, 'lib', 'sequelize')) +var groupUtil = require(path.join(__appdir, 'lib', 'grouputil')) +var express = require('express') +const { decorateApp } = require('@awaitjs/express') +var router = decorateApp(express.Router()) + +// ############################################################################ +// ########################### GET requests ################################# + +/* + * @return: Returns event of given id. + */ +router.getAsync('/:id', async (req, res) => { + var event = await db.event.findOne({ where: { id: req.params.id }, include: ['clients', 'groups'] }) + if (event) res.send(event) + else res.status(404).end() +}) + +/* + * @return: Returns a list of all events in the database. + */ +router.getAsync('', async (req, res) => { + var events = await db.event.findAll({ include: ['clients', 'groups'] }) + if (events) res.status(200).send(events) + else res.status(404).end() +}) + +// ############################################################################ +// ########################## POST requests ################################# + +router.postAsync('/blacklist', async (req, res) => { + console.log('body: ' + req.body.groups) + if (req.body.groups) { + var blacklist = await groupUtil.getAllChildren(req.body.groups) + res.send(blacklist) + } + else res.status(404).end() +}) + +// Create, Update or Delete POST +router.postAsync(['', '/:id'], async (req, res) => { + if (req.query.delete !== undefined && req.query.delete !== 'false') { + await db.event.destroy({ where: { id: req.params.id || req.body.ids } }).then(count => { res.send({ count }) }) + } else { + var promises = [] + var promisesBlacklist = [] + var eventDb + if (req.body.config.length !== 1) req.body.config = null + if (req.body.times.length === 0) req.body.times = null + if (req.params.id > 0) { + // Update existing role + eventDb = await db.event.findOne({ where: { id: req.params.id } }) + console.log('Blacklist: ' + req.body.blacklistGroups) + console.log('Groups: ' + req.body.groups) + if (eventDb !== null) { + promises.push(eventDb.update({ name: req.body.name, description: req.body.description, config: req.body.config || null, times: req.body.times, important: req.body.important })) + promises.push(eventDb.setGroups(req.body.groups, { through: { blacklist: 0 } })) + promises.push(eventDb.setClients(req.body.clients, { through: { blacklist: 0 } })) + await Promise.all(promises) + promisesBlacklist.push(eventDb.addGroups(req.body.blacklistGroups, { through: { blacklist: 1 } })) + promisesBlacklist.push(eventDb.addClients(req.body.blacklistClients, { through: { blacklist: 1 } })) + await Promise.all(promisesBlacklist) + res.send({ id: req.params.id }) + } else { + res.status(404).end() + } + } else { + // Create new role + eventDb = await db.event.create({ name: req.body.name, description: req.body.description, config: req.body.config || null, times: req.body.times, important: req.body.important }) + promises.push(eventDb.setGroups(req.body.groups, { through: { blacklist: 0 } })) + promises.push(eventDb.setClients(req.body.clients, { through: { blacklist: 0 } })) + await Promise.all(promises) + promisesBlacklist.push(eventDb.addGroups(req.body.blacklistGroups, { through: { blacklist: 1 } })) + promisesBlacklist.push(eventDb.addClients(req.body.blacklistClients, { through: { blacklist: 1 } })) + await Promise.all(promisesBlacklist) + res.send({ id: req.body.id }) + } + } +}) + +// ############################################################################ +// ############################################################################ + +module.exports.router = router diff --git a/server/api/roles.js b/server/api/roles.js index d90d1bd..4d75bfb 100644 --- a/server/api/roles.js +++ b/server/api/roles.js @@ -59,13 +59,17 @@ router.postAsync(['', '/:id'], async (req, res) => { res.send({ id: req.body.id }) } else { // Update existing role - roleDb = await db.role.findOne({ where: { id: req.body.id } }) - promises.push(roleDb.update({ name: req.body.name, descr: req.body.descr })) - promises.push(roleDb.setPermissions(req.body.permissions)) - promises.push(roleDb.setGroups(req.body.groups, { through: { blacklist: 0 } })) - promises.push(roleDb.addGroups(req.body.blacklist, { through: { blacklist: 1 } })) - await Promise.all(promises) - res.send({ id: req.body.id }) + roleDb = await db.role.findOne({ where: { id: req.params.id } }) + if (roleDb !== null) { + promises.push(roleDb.update({ name: req.body.name, descr: req.body.descr })) + promises.push(roleDb.setPermissions(req.body.permissions)) + promises.push(roleDb.setGroups(req.body.groups, { through: { blacklist: 0 } })) + promises.push(roleDb.addGroups(req.body.blacklist, { through: { blacklist: 1 } })) + await Promise.all(promises) + res.send({ id: req.params.id }) + } else { + res.status(404).end() + } } } }) diff --git a/server/migrations/20190226151600-create-event.js b/server/migrations/20190226151600-create-event.js new file mode 100644 index 0000000..59cab86 --- /dev/null +++ b/server/migrations/20190226151600-create-event.js @@ -0,0 +1,31 @@ +'use strict' +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('events', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + description: { + type: Sequelize.STRING(2048) + }, + config: { + type: Sequelize.INTEGER + }, + times: { + type: Sequelize.STRING(4096) + }, + important: { + type: Sequelize.BOOLEAN + } + }) + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('permissions') + } +} diff --git a/server/migrations/20190226152330-create-client_x_event.js b/server/migrations/20190226152330-create-client_x_event.js new file mode 100644 index 0000000..1d6952e --- /dev/null +++ b/server/migrations/20190226152330-create-client_x_event.js @@ -0,0 +1,33 @@ +'use strict' +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('client_x_event', { + clientId: { + primaryKey: true, + allowNull: false, + type: Sequelize.INTEGER, + onDelete: 'cascade', + references: { + model: 'clients', + key: 'id' + } + }, + eventId: { + primaryKey: true, + allowNull: false, + type: Sequelize.INTEGER, + onDelete: 'cascade', + references: { + model: 'events', + key: 'id' + } + }, + blacklist: { + type: Sequelize.BOOLEAN + } + }) + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('client_x_event') + } +} diff --git a/server/migrations/20190226152400-create-group_x_event.js b/server/migrations/20190226152400-create-group_x_event.js new file mode 100644 index 0000000..8c438de --- /dev/null +++ b/server/migrations/20190226152400-create-group_x_event.js @@ -0,0 +1,33 @@ +'use strict' +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('group_x_event', { + groupId: { + primaryKey: true, + allowNull: false, + type: Sequelize.INTEGER, + onDelete: 'cascade', + references: { + model: 'groups', + key: 'id' + } + }, + eventId: { + primaryKey: true, + allowNull: false, + type: Sequelize.INTEGER, + onDelete: 'cascade', + references: { + model: 'events', + key: 'id' + } + }, + blacklist: { + type: Sequelize.BOOLEAN + } + }) + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('group_x_event') + } +} diff --git a/server/models/client.js b/server/models/client.js index 6483573..502f668 100644 --- a/server/models/client.js +++ b/server/models/client.js @@ -20,6 +20,8 @@ module.exports = (sequelize, DataTypes) => { var GroupXClient = sequelize.define('group_x_client', {}, { timestamps: false, freezeTableName: true }) client.belongsToMany(models.group, { as: 'groups', through: GroupXClient, foreignKey: 'clientId', otherKey: 'groupId' }) client.belongsTo(models.config) + var ClientXEvent = sequelize.define('client_x_event', { blacklist: DataTypes.BOOLEAN }, { timestamps: false, freezeTableName: true }) + client.belongsToMany(models.event, { as: 'events', through: ClientXEvent, foreignKey: 'clientId', otherKey: 'eventId' }) } return client } diff --git a/server/models/event.js b/server/models/event.js new file mode 100644 index 0000000..11a35e7 --- /dev/null +++ b/server/models/event.js @@ -0,0 +1,26 @@ +'use strict' +module.exports = (sequelize, DataTypes) => { + var event = sequelize.define('event', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: DataTypes.INTEGER + }, + name: DataTypes.STRING, + description: DataTypes.STRING(2048), + config: DataTypes.INTEGER, + times: DataTypes.STRING(4096), + important: DataTypes.BOOLEAN + }, { + timestamps: false + }) + event.associate = function (models) { + var ClientXEvent = sequelize.define('client_x_event', { blacklist: DataTypes.BOOLEAN }, { timestamps: false, freezeTableName: true }) + event.belongsToMany(models.client, { as: 'clients', through: ClientXEvent, foreignKey: 'eventId', otherKey: 'clientId' }) + + var GroupXEvent = sequelize.define('group_x_event', { blacklist: DataTypes.BOOLEAN }, { timestamps: false, freezeTableName: true }) + event.belongsToMany(models.group, { as: 'groups', through: GroupXEvent, foreignKey: 'eventId', otherKey: 'groupId' }) + } + return event +} diff --git a/server/models/group.js b/server/models/group.js index 30fc78d..6ff9034 100644 --- a/server/models/group.js +++ b/server/models/group.js @@ -15,11 +15,14 @@ module.exports = (sequelize, DataTypes) => { group.associate = function (models) { var GroupXGroup = sequelize.define('group_x_group', {}, { timestamps: false, freezeTableName: true }) var GroupXClient = sequelize.define('group_x_client', {}, { timestamps: false, freezeTableName: true }) + var GroupXEvent = sequelize.define('group_x_event', { blacklist: DataTypes.BOOLEAN }, { timestamps: false, freezeTableName: true }) group.belongsToMany(group, { as: 'parents', through: GroupXGroup, foreignKey: 'childId', otherKey: 'parentId' }) group.belongsToMany(group, { as: 'subgroups', through: GroupXGroup, foreignKey: 'parentId', otherKey: 'childId' }) group.belongsToMany(models.client, { as: 'clients', through: GroupXClient, foreignKey: 'groupId', otherKey: 'clientId' }) + group.belongsToMany(models.event, { as: 'events', through: GroupXEvent, foreignKey: 'groupId', otherKey: 'eventId' }) group.belongsTo(models.config) group.hasMany(models.iprange, { as: 'ipranges' }) + } return group } diff --git a/webapp/src/components/EventModule.vue b/webapp/src/components/EventModule.vue new file mode 100644 index 0000000..68f9537 --- /dev/null +++ b/webapp/src/components/EventModule.vue @@ -0,0 +1,83 @@ + +{ + "en": { + "events": "Events", + "eventCalendar": "Event Calendar", + "eventList": "Event List" + }, + "de": { + "events": "Veranstaltungen", + "eventCalendar": "Veranstaltungskalendar", + "eventList": "Veranstaltungsliste" + } +} + + + + + + + diff --git a/webapp/src/components/EventModuleDelete.vue b/webapp/src/components/EventModuleDelete.vue new file mode 100644 index 0000000..f22fc41 --- /dev/null +++ b/webapp/src/components/EventModuleDelete.vue @@ -0,0 +1,66 @@ + +{ + "en": { + "delete-are-you-sure": "Are you sure you want to delete this event? | Are you sure you want to delete these events?" + }, + "de": { + "delete-are-you-sure": "Sind sie sicher, dass sie diese Veranstaltung Löschen wollen? | Sind sie sicher, dass sie diese Veranstaltungen löschen wollen?" + } +} + + + + + + + + diff --git a/webapp/src/components/EventModuleEdit.vue b/webapp/src/components/EventModuleEdit.vue new file mode 100644 index 0000000..2b6dbc3 --- /dev/null +++ b/webapp/src/components/EventModuleEdit.vue @@ -0,0 +1,638 @@ + +{ + "en": { + "april": "April", + "august": "August", + "blacklist": "Blacklist", + "blacklistClients": "Blacklist Clients", + "blacklistGroups": "Blacklist Groups", + "clients": "Clients", + "config": "Configuration", + "day": "Day", + "days": "Days", + "december": "December", + "description": "Description", + "endDate": "End Date", + "endTime": "End Time", + "event": "Event", + "eventName": "Event Name", + "eventNameEmptyError": "Event Name can't be empty!", + "february": "February", + "friday": "Friday", + "groups": "Groups", + "groupsAndClients": "Groups / Clients", + "id": "ID", + "importantEvent": "Important Event", + "interval": "Interval", + "intervalMustBeNumberError": "Interval must be a valid number!", + "intervalTypes": "Interval Types", + "ip": "IP", + "january": "January", + "july": "July", + "june": "June", + "march": "March", + "may": "May", + "monday": "Monday", + "month": "Month", + "months": "Months", + "name": "Name", + "november": "November", + "october": "October", + "repetitiveModeSwitch": "repetitive Event", + "saturday": "Saturday", + "september": "September", + "startDate": "Start Date", + "startTime": "Start Time", + "sunday": "Sunday", + "thursday": "Thursday", + "tuesday": "Tuesday", + "uuid": "UUID", + "wednesday": "Wednesday", + "week": "Week" + }, + "de": { + "april": "April", + "august": "August", + "blacklist": "Blacklist", + "blacklistClients": "Blacklist Clienten", + "blacklistGroups": "Blacklist Gruppen", + "clients": "Clients", + "config": "Konfiguration", + "day": "Tag", + "days": "Tage", + "december": "Dezember", + "description": "Beschreibung", + "endDate": "End Datum", + "endTime": "End Zeit", + "event": "Veranstaltung", + "eventName": "Veranstaltungsname", + "eventNameEmptyError": "Der Veranstaltungsname kann nicht leer sein!", + "february": "Februar", + "friday": "Freitag", + "groups": "Gruppen", + "groupsAndClients": "Gruppen / Clients", + "id": "ID", + "importantEvent": "Wichtige Veranstaltung", + "interval": "Intervall", + "intervalMustBeNumberError": "Das Intervall muss eine gültige Zahl sein!", + "intervalTypes": "Intervalltypen", + "ip": "IP", + "january": "Januar", + "july": "Juli", + "june": "Juni", + "march": "März", + "may": "Mai", + "monday": "Montag", + "month": "Monat", + "months": "Monate", + "name": "Name", + "november": "November", + "october": "Oktober", + "repetitiveModeSwitch": "Wiederholende Veranstaltung", + "saturday": "Samstag", + "september": "September", + "startDate": "Start Datum", + "startTime": "Start Zeit", + "sunday": "Sonntag", + "thursday": "Donnerstag", + "tuesday": "Dienstag", + "uuid": "UUID", + "wednesday": "Mittwoch", + "week": "Woche" + } +} + + + + + + + + diff --git a/webapp/src/components/EventModuleEventList.vue b/webapp/src/components/EventModuleEventList.vue new file mode 100644 index 0000000..fe2ac1a --- /dev/null +++ b/webapp/src/components/EventModuleEventList.vue @@ -0,0 +1,85 @@ + +{ + "en": { + "create-event": "Create Event", + "delete-event": "Delete {0} Event | Delete {0} Events", + "name": "Name", + "description": "Description", + "config": "Configuration", + "times": "Times" + }, + "de": { + "create-event": "Veranstaltung erstellen", + "delete-event": "Lösche {0} Veranstaltung | Lösche {0} Veranstaltungen", + "name": "Name", + "description": "Beschreibung", + "config": "Konfiguration", + "times": "Zeiten" + } +} + + + + + + + + diff --git a/webapp/src/components/PermissionModule.vue b/webapp/src/components/PermissionModule.vue index 213ca4f..109007c 100644 --- a/webapp/src/components/PermissionModule.vue +++ b/webapp/src/components/PermissionModule.vue @@ -3,14 +3,14 @@ "en": { "roles": "Roles", "users": "Users", - "delete-are-you-sure": "Are you sure you want to delete this role? | Are you sure you want to delete those roles?", + "delete-are-you-sure": "Are you sure you want to delete this role? | Are you sure you want to delete these roles?", "delete-permission": "Delete {0} role | Delete {0} roles", "delete-role": "Delete {0} Role | Delete {0} Roles" }, "de": { "roles": "Rollen", "users": "Nutzer", - "delete-are-you-sure": "Sind sie sicher, dass sie diese Rolle Löschen wollen? | Sind sie sicher, dass sie diese Rollen Löschen wollen?", + "delete-are-you-sure": "Sind sie sicher, dass sie diese Rolle Löschen wollen? | Sind sie sicher, dass sie diese Rollen löschen wollen?", "delete-permission": "Delete {0} role | Delete {0} roles", "delete-role": "Lösche {0} Rolle | Lösche {0} Rollen" } diff --git a/webapp/src/components/PermissionModuleEdit.vue b/webapp/src/components/PermissionModuleEdit.vue index c026f54..f88eb4c 100644 --- a/webapp/src/components/PermissionModuleEdit.vue +++ b/webapp/src/components/PermissionModuleEdit.vue @@ -274,6 +274,7 @@ export default { }).then(response => { this.$snackbar({ color: 'success', text: this.$t('roleSavedSuccess') }) this.$store.dispatch('permissions/loadRoleData') + this.$store.dispatch('permissions/loadUserData') this.$store.commit('permissions/setEdit', false) }).catch(error => { console.log(error) diff --git a/webapp/src/components/PermissionModuleRoleList.vue b/webapp/src/components/PermissionModuleRoleList.vue index 7b744b6..67fbb9f 100644 --- a/webapp/src/components/PermissionModuleRoleList.vue +++ b/webapp/src/components/PermissionModuleRoleList.vue @@ -52,7 +52,7 @@ export default { { text: this.$t('id'), key: 'id' }, { text: this.$t('name'), key: 'name' }, { text: this.$t('description'), key: 'descr' }, - { sortable: false, key: 'action' } + { sortable: false, key: 'action', width: '60px' } ], canEdit: false } diff --git a/webapp/src/config/dashboard.js b/webapp/src/config/dashboard.js index 26de0fc..7a5244e 100644 --- a/webapp/src/config/dashboard.js +++ b/webapp/src/config/dashboard.js @@ -6,6 +6,7 @@ import PermissionModule from '@/components/PermissionModule' import IpxeBuilderModule from '@/components/IpxeBuilderModule' import UserModule from '@/components/UserModule' import LogModule from '@/components/LogModule' +import EventModule from '@/components/EventModule' export default [ { path: 'groups', component: GroupModule, icon: 'category' }, @@ -15,5 +16,6 @@ export default [ { path: 'permissions', component: PermissionModule, icon: 'lock_open' }, { path: 'ipxe', component: IpxeBuilderModule, icon: 'merge_type' }, { path: 'users', component: UserModule, icon: 'contacts' }, - { path: 'log', component: LogModule, icon: 'error_outline' } + { path: 'log', component: LogModule, icon: 'error_outline' }, + { path: 'events', component: EventModule, icon: 'event' } ] diff --git a/webapp/src/config/i18n.js b/webapp/src/config/i18n.js index c9cf137..25e6f3a 100644 --- a/webapp/src/config/i18n.js +++ b/webapp/src/config/i18n.js @@ -30,7 +30,8 @@ export default { 'PermissionModule': 'Permission Manager', 'IpxeBuilderModule': 'iPXE Builder', 'UserModule': 'User Management', - 'LogModule': 'System Log' + 'LogModule': 'System Log', + 'EventModule': 'Event Manager' } }, 'de': { @@ -64,7 +65,8 @@ export default { 'PermissionModule': 'Rechteverwaltung', 'IpxeBuilderModule': 'iPXE Builder', 'UserModule': 'Benutzerverwaltung', - 'LogModule': 'System Protokoll' + 'LogModule': 'System Protokoll', + 'EventModule': 'Veranstaltungsverwaltung' } } } diff --git a/webapp/src/config/store.js b/webapp/src/config/store.js index ac65696..f8bb4f0 100644 --- a/webapp/src/config/store.js +++ b/webapp/src/config/store.js @@ -5,6 +5,7 @@ import registration from '@/store/registration' import backends from '@/store/backends' import permissions from '@/store/permissions' import users from '@/store/users' +import events from '@/store/events' export default { notifications, @@ -13,5 +14,6 @@ export default { registration, backends, permissions, - users + users, + events } diff --git a/webapp/src/store/events.js b/webapp/src/store/events.js new file mode 100644 index 0000000..27cb3e7 --- /dev/null +++ b/webapp/src/store/events.js @@ -0,0 +1,35 @@ +import axios from 'axios' + +export default { + namespaced: true, + state: { + events: [], + configList: [], + dialog: { show: false, type: null, info: {} } + }, + mutations: { + setEvents (state, value) { state.events = value }, + setConfigList (state, value) { state.configList = value }, + setDialog (state, { show, type, info }) { + if (show !== undefined) state.dialog.show = show + if (type !== undefined) state.dialog.type = type + if (info !== undefined) state.dialog.info = info + } + }, + actions: { + loadEvents (context) { + axios.get('/api/events').then(response => { + context.commit('setEvents', response.data) + }) + }, + loadConfigs (context) { + axios.get('/api/configurator/configs').then(result => { + context.commit('setConfigList', result.data) + }) + }, + loadLists (context) { + context.dispatch('loadEvents') + context.dispatch('loadConfigs') + } + } +} -- cgit v1.2.3-55-g7522