Browse Source

Geräte bearbeiten

tags/v0.9.1
akimmig 4 years ago
parent
commit
85048c2646
9 changed files with 244 additions and 19 deletions
  1. +15
    -0
      client/package-lock.json
  2. +1
    -0
      client/package.json
  3. +3
    -0
      client/src/plugins/vuetify.js
  4. +34
    -18
      client/src/views/components/management/apparatus.vue
  5. +104
    -0
      client/src/views/components/management/dialogs/EditApparatus.vue
  6. +5
    -0
      server/schema.gql
  7. +2
    -1
      server/src/apparatus/apparatus.module.ts
  8. +57
    -0
      server/src/apparatus/resolver/apparatus.mutation.ts
  9. +23
    -0
      server/src/apparatus/resolver/apparatus.subscription.ts

+ 15
- 0
client/package-lock.json View File

"vue-cookies": "^1.7.4", "vue-cookies": "^1.7.4",
"vue-router": "^3.2.0", "vue-router": "^3.2.0",
"vuetify": "^2.4.0", "vuetify": "^2.4.0",
"vuetify-image-input": "^19.2.2",
"vuex": "^3.4.0" "vuex": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {
"vue": "^2.6.4" "vue": "^2.6.4"
} }
}, },
"node_modules/vuetify-image-input": {
"version": "19.2.2",
"resolved": "https://registry.npmjs.org/vuetify-image-input/-/vuetify-image-input-19.2.2.tgz",
"integrity": "sha512-U3qKkMXBiYSXV3IaRyTxNCw9rpgr52lqck0zWM7geOMdUu9IXKDGN1kfIbFGzT6FU6QntFoduHwwEOcug62bxw==",
"peerDependencies": {
"vuetify": "^2"
}
},
"node_modules/vuetify-loader": { "node_modules/vuetify-loader": {
"version": "1.7.2", "version": "1.7.2",
"resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.7.2.tgz", "resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.7.2.tgz",
"integrity": "sha512-Lpnwm64xYVEXb5BXdadSRaH0QHjXLFhPPjuVU9VuqWp3Nzr+WP5vA9nMPkJAfUj8vKIJGTRXqyGTGVa4VwrO3A==", "integrity": "sha512-Lpnwm64xYVEXb5BXdadSRaH0QHjXLFhPPjuVU9VuqWp3Nzr+WP5vA9nMPkJAfUj8vKIJGTRXqyGTGVa4VwrO3A==",
"requires": {} "requires": {}
}, },
"vuetify-image-input": {
"version": "19.2.2",
"resolved": "https://registry.npmjs.org/vuetify-image-input/-/vuetify-image-input-19.2.2.tgz",
"integrity": "sha512-U3qKkMXBiYSXV3IaRyTxNCw9rpgr52lqck0zWM7geOMdUu9IXKDGN1kfIbFGzT6FU6QntFoduHwwEOcug62bxw==",
"requires": {}
},
"vuetify-loader": { "vuetify-loader": {
"version": "1.7.2", "version": "1.7.2",
"resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.7.2.tgz", "resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.7.2.tgz",

+ 1
- 0
client/package.json View File

"vue-cookies": "^1.7.4", "vue-cookies": "^1.7.4",
"vue-router": "^3.2.0", "vue-router": "^3.2.0",
"vuetify": "^2.4.0", "vuetify": "^2.4.0",
"vuetify-image-input": "^19.2.2",
"vuex": "^3.4.0" "vuex": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {

+ 3
- 0
client/src/plugins/vuetify.js View File



import '@/sass/overrides.sass' import '@/sass/overrides.sass'


import VImageInput from 'vuetify-image-input/a-la-carte'

Vue.use(Vuetify) Vue.use(Vuetify)
Vue.component('VImageInput', VImageInput)


const theme = { const theme = {
primary: '#FF041D', primary: '#FF041D',

+ 34
- 18
client/src/views/components/management/apparatus.vue View File

mobile-breakpoint="0" mobile-breakpoint="0"
:search="filter" :search="filter"
@click:row="open" @click:row="open"
/>
>
<template #item.logo="{item}">
<img
v-if="item.logo"
height="64"
:src="item.logo"
>
<v-avatar
v-else
color="grey lighten-2"
size="32"
>
{{ item.name.substr(0,2) }}
</v-avatar>
</template>
</v-data-table>
</v-card> </v-card>
<!--edit-people
<edit-apparatus
:id="dialog.id" :id="dialog.id"
v-model="dialog.open" v-model="dialog.open"
/-->
/>
</v-container> </v-container>
</template> </template>


<script> <script>
import { useAuth } from '@/plugins/auth' import { useAuth } from '@/plugins/auth'
import gql from 'graphql-tag' import gql from 'graphql-tag'
// import { updateQuery, deleteQuery } from '@/graphql'
import { updateQuery, deleteQuery } from '@/plugins/graphql'


export default { export default {
name: 'People', name: 'People',


components: { components: {
// EditPeople: () => import('./dialogs/EditPeople'),
EditApparatus: () => import('./dialogs/EditApparatus')
}, },


setup (props, context) { setup (props, context) {
{ {
text: '', text: '',
value: 'logo', value: 'logo',
sortable: false
sortable: false,
width: 100
}, },
{ {
text: 'Name', text: 'Name',


apollo: { apollo: {
ApparatusFind: { ApparatusFind: {
query: gql`query { ApparatusFind { _id name logo } }`
/* subscribeToMore: {
document: gql`subscription { PersonUpdated { _id vorname nachname geburtstag dtbid gymnet { id } email { email typ } tel { nummer typ } adresse { strasse hausnummer plz ort land typ } turnportal { typ gueltigvon gueltigbis lastcheck sperre festgeturnt verein vermerk } } }`,
updateQuery: updateQuery('PersonList', 'PersonUpdated')
} */
}
/* $subscribe: {
query: gql`query { ApparatusFind { _id name logo } }`,
subscribeToMore: {
document: gql`subscription { ApparatusUpdated { _id name logo } }`,
updateQuery: updateQuery('ApparatusFind', 'ApparatusUpdated')
}
},
$subscribe: {
PersonDeleted: { PersonDeleted: {
query: gql`subscription { PersonDeleted }`,
query: gql`subscription { ApparatusDeleted }`,
result (id) { result (id) {
deleteQuery('PersonList', 'PersonUpdated', this.PersonList, id)
},
},
}, */
deleteQuery('ApparatusFind', 'ApparatusDeleted', this.ApparatusFind, id)
}
}
}
}, },


methods: { methods: {

+ 104
- 0
client/src/views/components/management/dialogs/EditApparatus.vue View File

<template>
<base-material-dialog
:value="value"
icon="mdi-home"
title="Gerät bearbeiten"
:sub-title="id ? id : 'NEU'"
color="rgb(255, 4, 29)"
:actions="[doc && isMaster ? 'del' : '', isMaster ? 'save' : '', 'cancel']"
@del="del"
@save="save"
@close="close"
@esc="close"
>
<v-row v-if="!isMaster">
Kein Zugriff! {{ isMaster }}
</v-row>
<v-row v-else>
<v-col
cols="12"
sm="6"
md="9"
>
<v-text-field
v-model="data.name"
label="Gerätename"
/>
</v-col>
<v-col
cols="12"
sm="6"
md="3"
>
<v-image-input
ref="logo"
v-model="data.logo"
:image-quality="0.60"
:image-height="128"
:image-width="128"
overlay-padding="10px"
overlay-border-width="2px"
overlay-border-color="#f00"
upload-icon="fa-cloud-upload"
flip-horizontally-icon="fa-arrows-h"
flip-vertically-icon="fa-arrows-v"
rotate-clockwise-icon="fa-redo"
rotate-counter-clockwise-icon="fa-undo"
image-min-scaling="contain"
clearable
/>
</v-col>
</v-row>
</base-material-dialog>
</template>

<script>
import { useAuth } from '@/plugins/auth'
import { useEditDialog } from '@/plugins/editdialog'

export default {
name: 'EditApparatus',
props: {
value: {
type: Boolean,
required: true
},
id: {
type: String,
default: null
}
},

setup (props, context) {
return {
...useAuth(context),
...useEditDialog(props, context, 'Apparatus(id: $id) { _id name logo }', ['name', 'logo'])
}
},

methods: {
update () {
return {
mutation: `mutation($id: UUID!, $name: String, $logo: String) {
ApparatusUpdate(id: $id, name: $name, logo: $logo) {
_id name logo
}
}`
}
},
create () {
return {
mutation: `mutation($name: String!, $logo: String) {
ApparatusCreate(name: $name, logo: $logo) {
_id name logo
}
}`
}
}
}
}
</script>

<style lang="sass">
$dialog-elevation: 0
</style>

+ 5
- 0
server/schema.gql View File

PersonUpdate(master: Boolean, email: EmailAddress, familyName: String, givenName: String, id: UUID!): Person! PersonUpdate(master: Boolean, email: EmailAddress, familyName: String, givenName: String, id: UUID!): Person!
PersonCreate(master: Boolean, email: EmailAddress!, familyName: String!, givenName: String!): Person! PersonCreate(master: Boolean, email: EmailAddress!, familyName: String!, givenName: String!): Person!
PersonDelete(id: UUID!): UUID! PersonDelete(id: UUID!): UUID!
ApparatusUpdate(logo: String, name: String, id: UUID!): Apparatus!
ApparatusCreate(logo: String, name: String!): Apparatus!
ApparatusDelete(id: UUID!): UUID!
OrganizerRegister(ort: String, plz: Int, name: String!): Organizer! OrganizerRegister(ort: String, plz: Int, name: String!): Organizer!
EventCreate(name: String, date: Date!, organizer: UUID!): Event! EventCreate(name: String, date: Date!, organizer: UUID!): Event!
} }
type Subscription { type Subscription {
PersonUpdated: Person PersonUpdated: Person
PersonDeleted: UUID! PersonDeleted: UUID!
ApparatusUpdated: Apparatus
ApparatusDeleted: UUID!
} }

+ 2
- 1
server/src/apparatus/apparatus.module.ts View File

import { ApparatusResolverM } from './resolver/apparatus.mutation'; import { ApparatusResolverM } from './resolver/apparatus.mutation';
import { ApparatusService } from './apparatus.service'; import { ApparatusService } from './apparatus.service';
import { ApparatusResolver } from './resolver/apparatus'; import { ApparatusResolver } from './resolver/apparatus';
import {ApparatusResolverS} from './resolver/apparatus.subscription'


@Module({ @Module({
providers: [ providers: [
ApparatusResolverQ, ApparatusResolverM,
ApparatusResolverQ, ApparatusResolverM, ApparatusResolverS,
ApparatusService, ApparatusService,
ApparatusResolver, ApparatusResolver,
], ],

+ 57
- 0
server/src/apparatus/resolver/apparatus.mutation.ts View File

import { Client } from '../../client'; import { Client } from '../../client';
import { ApparatusService } from '../apparatus.service'; import { ApparatusService } from '../apparatus.service';
import { HttpException } from '@nestjs/common'; import { HttpException } from '@nestjs/common';
import {UUID} from '../../global/scalars/UUID'
import {pubsub} from '../../main'


@Resolver(() => Apparatus) @Resolver(() => Apparatus)
export class ApparatusResolverM { export class ApparatusResolverM {
constructor( constructor(
private readonly service: ApparatusService, private readonly service: ApparatusService,
) {} ) {}

@Mutation(() => Apparatus, { nullable: false })
async ApparatusUpdate(
@Context('client') client: Client,
@Args('id', { type: () => UUID, nullable: false }) id: UUID,
@Args('name', { nullable: true }) name?: string,
@Args('logo', { nullable: true }) logo?: string,
): Promise<Apparatus> {
if (!client.isMaster()) throw new HttpException('Access denied', 403);

const tmp = await this.service.findOneById(id);

const set: {
name?: string
logo?: string
} = {};

if (name !== undefined && name !== tmp.name) set.name = name
if (logo !== undefined && logo !== tmp.logo) set.logo = logo

if (Object.values(set).length === 0) return tmp;

const neu = await this.service.update(client, tmp._id, {$set: set});
pubsub.publish('ApparatusUpdated', { ApparatusUpdated: neu });
return neu;
}

@Mutation(() => Apparatus, { nullable: false })
async ApparatusCreate(
@Context('client') client: Client,
@Args('name', { nullable: false }) name: string,
@Args('logo', { nullable: true }) logo?: string,
): Promise<Apparatus> {
if (!client.isMaster()) throw new HttpException('Access denied', 403);

const neu = await this.service.insert(client, { name, logo });

pubsub.publish('ApparatusUpdated', { ApparatusUpdated: neu });

return neu;
}

@Mutation(() => UUID, { nullable: false })
async ApparatusDelete(
@Context('client') client: Client,
@Args('id', { type: () => UUID, nullable: false }) id: UUID
): Promise<UUID> {
if (!client.isMaster()) throw new HttpException('Access denied', 403);

this.service.delete(client, id);

pubsub.publish('ApparatusDeleted', { ApparatusDeleted: id });

return id;
}
} }

+ 23
- 0
server/src/apparatus/resolver/apparatus.subscription.ts View File

import {Resolver, Subscription} from '@nestjs/graphql'
import {ApparatusService} from '../apparatus.service'
import {Apparatus} from '../models/Apparatus'

import { pubsub } from '../../main'
import { UUID } from '../../global/scalars/UUID'

@Resolver(() => Apparatus)
export class ApparatusResolverS {
constructor(
private readonly service: ApparatusService,
) {}

@Subscription(() => Apparatus,{ nullable: true })
async ApparatusUpdated() {
return pubsub.asyncIterator('ApparatusUpdated');
}

@Subscription(() => UUID, { nullable: false })
async ApparatusDeleted() {
return pubsub.asyncIterator('ApparatusDeleted')
}
}

Loading…
Cancel
Save