"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", |
"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": { |
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', |
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: { |
<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> |
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! | |||||
} | } |
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, | ||||
], | ], |
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; | |||||
} | |||||
} | } |
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') | |||||
} | |||||
} |