Skip to content
Snippets Groups Projects
Commit 228eea65 authored by Nils Brinckmann's avatar Nils Brinckmann
Browse files

Migration to new frontend structure for contacts

parent 913d519e
No related branches found
No related tags found
2 merge requests!97Migration to new frontend structure for contacts,!82Restructure frontend
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020-2021
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<div>
<v-row>
<v-col cols="12" md="3">
<label>Given name</label>
{{ value.givenName | orDefault }}
</v-col>
<v-col cols="12" md="3">
<label>Family name</label>
{{ value.familyName | orDefault }}
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<label>E-mail</label>
{{ value.email | orDefault }}
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<label>Website</label>
{{ value.website | orDefault }}
<a v-if="value.website.length > 0" :href="value.website" target="_blank">
<v-icon>
mdi-open-in-new
</v-icon>
</a>
</v-col>
</v-row>
</div>
</template>
<style lang="scss">
@import '~vuetify/src/styles/settings/variables';
@import '~vuetify/src/styles/settings/colors';
label {
/* TODO: move to its own file */
display: block;
font-size: map-deep-get($headings, 'caption', 'size');
font-weight: map-deep-get($headings, 'caption', 'weight');
letter-spacing: map-deep-get($headings, 'caption', 'letter-spacing');
line-height: map-deep-get($headings, 'caption', 'line-height');
font-family: map-deep-get($headings, 'caption', 'font-family');
color: map-get($grey, 'darken-1');
}
</style>
<script lang="ts">
import { Component, Vue, Prop } from 'nuxt-property-decorator'
import { Contact } from '@/models/Contact'
@Component
export default class ContactBasicData extends Vue {
@Prop({
default: () => new Contact(),
required: true,
type: Contact
})
readonly value!: Contact
}
</script>
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020-2021
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<v-form
ref="basicForm"
@submit.prevent
>
<v-row>
<v-col cols="12" md="3">
<v-text-field
:value="value.givenName"
label="Given name"
:readonly="readonly"
:disabled="readonly"
required
class="required"
:rules="[rules.required]"
@input="update('givenName', $event)"
/>
</v-col>
<v-col cols="12" md="3">
<v-text-field
:value="value.familyName"
label="Family name"
:readonly="readonly"
:disabled="readonly"
required
class="required"
:rules="[rules.required]"
@input="update('familyName', $event)"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<v-text-field
:value="value.email"
label="E-mail"
type="email"
:readonly="readonly"
:disabled="readonly"
required
class="required"
:rules="[rules.required]"
@input="update('email', $event)"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<v-text-field
v-if="readonly"
:value="value.website"
label="Website"
placeholder="https://"
type="url"
:readonly="true"
:disabled="true"
>
<template slot="append">
<a v-if="value.website.length > 0" :href="value.website" target="_blank">
<v-icon>
mdi-open-in-new
</v-icon>
</a>
</template>
</v-text-field>
<v-text-field
v-else
:value="value.website"
label="Website"
placeholder="https://"
type="url"
@input="update('email', $event)"
/>
</v-col>
</v-row>
</v-form>
</template>
<script lang="ts">
import { Component, Prop, mixins } from 'nuxt-property-decorator'
import { Rules } from '@/mixins/Rules'
import { Contact } from '@/models/Contact'
@Component
export default class ContactBasicDataForm extends mixins(Rules) {
@Prop({
required: true,
type: Contact
})
readonly value!: Contact
@Prop({
default: () => false,
type: Boolean
})
readonly readonly!: boolean
update (key: string, value: string) {
const newObj = Contact.createFromObject(this.value)
switch (key) {
case 'givenName':
newObj.givenName = value
break
case 'familyName':
newObj.familyName = value
break
case 'email':
newObj.email = value
break
case 'website':
newObj.website = value
break
default:
throw new TypeError('key ' + key + ' is not valid')
}
this.$emit('input', newObj)
}
public validateForm (): boolean {
return (this.$refs.basicForm as Vue & { validate: () => boolean }).validate()
}
}
</script>
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<div>
<ProgressIndicator
v-model="isLoading"
/>
<v-card flat>
<div v-if="isEditPage">
<NuxtChild
v-model="contact"
/>
</div>
<div v-else>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
color="primary"
small
nuxt
:to="'/contacts/' + contactId + '/edit'"
>
Edit
</v-btn>
</v-card-actions>
<ContactBasicData
v-model="contact"
/>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
color="primary"
small
nuxt
:to="'/contacts/' + contactId + '/edit'"
>
Edit
</v-btn>
</v-card-actions>
</div>
</v-card>
</div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'nuxt-property-decorator'
import { Contact } from '@/models/Contact'
import ContactBasicData from '@/components/ContactBasicData.vue'
import ProgressIndicator from '@/components/ProgressIndicator.vue'
@Component({
components: {
ContactBasicData,
ProgressIndicator
}
})
export default class ContactShowPage extends Vue {
private contact: Contact = new Contact()
private isLoading: boolean = true
created () {
this.initializeAppBar()
}
mounted () {
this.$api.contacts.findById(this.contactId).then((contact) => {
this.contact = contact
this.isLoading = false
}).catch((_error) => {
this.$store.commit('snackbar/setError', 'Loading contact failed')
this.isLoading = false
})
}
beforeDestroy () {
this.$store.dispatch('appbar/setDefaults')
}
initializeAppBar () {
this.$store.dispatch('appbar/init', {
title: 'Show Contact'
})
}
get contactId () {
return this.$route.params.contactId
}
@Watch('contact', { immediate: true, deep: true })
// @ts-ignore
onContactChanged (val: Contact) {
const fallbackText = this.isEditPage ? 'Edit contact' : 'Show contact'
if (val.id) {
this.$store.commit('appbar/setTitle', val?.toString() || fallbackText)
}
}
get isEditPage () {
return this.$route.path === '/contacts/' + this.contactId + '/edit' || this.$route.path === '/contact/' + this.contactId + '/edit/'
}
get isLoggedIn () {
return this.$store.getters['oidc/isAuthenticated']
}
}
</script>
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<div>
<ProgressIndicator
v-model="isLoading"
/>
<v-card flat>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
small
nuxt
:to="'/contacts/' + contactId"
>
cancel
</v-btn>
<v-btn
v-if="isLoggedIn"
color="green"
small
@click="onSaveButtonClicked"
>
apply
</v-btn>
</v-card-actions>
<ContactBasicDataForm
ref="basicForm"
v-model="contactCopy"
:readonly="false"
/>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
small
nuxt
:to="'/contacts/' + contactId"
>
cancel
</v-btn>
<v-btn
v-if="isLoggedIn"
color="green"
small
@click="onSaveButtonClicked"
>
apply
</v-btn>
</v-card-actions>
</v-card>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'nuxt-property-decorator'
import { Contact } from '@/models/Contact'
import ContactBasicDataForm from '@/components/ContactBasicDataForm.vue'
import ProgressIndicator from '@/components/ProgressIndicator.vue'
@Component({
components: {
ContactBasicDataForm,
ProgressIndicator
}
})
export default class ContactEditPage extends Vue {
private contactCopy: Contact = new Contact()
private isLoading: boolean = false
@Prop({
required: true,
type: Contact
})
readonly value!: Contact
mounted () {
this.contactCopy = Contact.createFromObject(this.value)
}
onSaveButtonClicked () {
if (!(this.$refs.basicForm as Vue & { validateForm: () => boolean }).validateForm()) {
this.$store.commit('snackbar/setError', 'Please correct your input')
return
}
this.isLoading = true
this.save().then((contact) => {
this.isLoading = false
this.$emit('input', contact)
this.$router.push('/contact/' + this.contactId)
}).catch((_error) => {
this.isLoading = false
this.$store.commit('snackbar/setError', 'Save failed')
})
}
save (): Promise<Contact> {
return new Promise((resolve, reject) => {
this.$api.contacts.save(this.contactCopy).then((savedContact) => {
resolve(savedContact)
}).catch((_error) => {
reject(_error)
})
})
}
get contactId () {
return this.$route.params.contactId
}
@Watch('value', { immediate: true, deep: true })
// @ts-ignore
onContactChanged (val: Contact) {
if (val.id) {
this.$store.commit('appbar/setTitle', val?.toString() || 'Edit contact')
}
this.contactCopy = Contact.createFromObject(val)
}
get isLoggedIn () {
return this.$store.getters['oidc/isAuthenticated']
}
}
</script>
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<div>
<v-card outlined>
<v-form ref="basicForm">
<v-card flat>
<v-card-title>
{{ title }}
</v-card-title>
<v-card-text>
<v-row>
<v-col cols="12" md="3">
<v-text-field
v-model="contact.givenName"
label="Given name"
:readonly="readonly"
:disabled="readonly"
/>
</v-col>
<v-col cols="12" md="3">
<v-text-field
v-model="contact.familyName"
label="Family name"
:readonly="readonly"
:disabled="readonly"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<v-text-field
v-model="contact.email"
label="E-mail"
type="email"
:readonly="readonly"
:disabled="readonly"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="9">
<v-text-field
v-if="readonly"
v-model="contact.website"
label="Website"
placeholder="https://"
type="url"
:readonly="true"
:disabled="true"
>
<template slot="append">
<a v-if="contact.website.length > 0" :href="contact.website" target="_blank">
<v-icon>
mdi-open-in-new
</v-icon>
</a>
</template>
</v-text-field>
<v-text-field
v-else
v-model="contact.website"
label="Website"
placeholder="https://"
type="url"
/>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-form>
<v-btn
v-if="!editMode && isLoggedIn"
fab
fixed
bottom
right
color="secondary"
@click="onEditButtonClick"
>
<v-icon>
mdi-pencil
</v-icon>
</v-btn>
</v-card>
</div>
</template>
<style lang="scss">
@import "@/assets/styles/_forms.scss";
</style>
<script lang="ts">
import { Component, Watch, Vue } from 'nuxt-property-decorator'
import { Contact } from '@/models/Contact'
@Component
export default class ContactIdPage extends Vue {
private contact: Contact = Contact.createEmpty()
private contactBackup: Contact | null = null
private editMode: boolean = false
created () {
this.initializeAppBar()
this.registerButtonActions()
}
mounted () {
this.loadContact().then((contact) => {
if (contact === null) {
this.$store.commit('appbar/setTitle', 'Add Contact')
}
}).catch(() => {
this.$store.commit('snackbar/setError', 'Loading contact failed')
})
}
beforeDestroy () {
this.unregisterButtonActions()
this.$store.dispatch('appbar/setDefaults')
}
registerButtonActions () {
this.$nuxt.$on('AppBarEditModeContent:save-btn-click', () => {
this.save().then(() => {
this.$store.commit('snackbar/setSuccess', 'Save successful')
}).catch(() => {
this.$store.commit('snackbar/setError', 'Save failed')
})
})
this.$nuxt.$on('AppBarEditModeContent:cancel-btn-click', () => {
this.cancel()
})
}
unregisterButtonActions () {
this.$nuxt.$off('AppBarEditModeContent:save-btn-click')
this.$nuxt.$off('AppBarEditModeContent:cancel-btn-click')
}
initializeAppBar () {
this.$store.dispatch('appbar/init', {
tabs: [],
title: 'Contacts',
saveBtnHidden: true,
cancelBtnHidden: true
})
}
loadContact (): Promise<Contact|null> {
return new Promise((resolve, reject) => {
const contactId = this.$route.params.id
if (!contactId) {
this.createBackup()
this.editMode = true && this.isLoggedIn
resolve(null)
return
}
this.editMode = false
this.$api.contacts.findById(contactId).then((foundContact) => {
this.contact = foundContact
resolve(foundContact)
}).catch((error) => {
reject(error)
})
})
}
createBackup () {
this.contactBackup = Contact.createFromObject(this.contact)
}
restoreBackup () {
if (!this.contactBackup) {
return
}
this.contact = this.contactBackup
this.contactBackup = null
}
save (): Promise<Contact|null> {
return new Promise((resolve, reject) => {
this.$api.contacts.save(this.contact).then((savedContact) => {
this.contact = savedContact
this.contactBackup = null
this.editMode = false
if (!this.$route.params.id && savedContact.id) {
this.setUrlWithNewId(savedContact.id)
// and we set the parameter so that we don't and up with
// multiple ids in the url
this.$route.params.id = savedContact.id
}
resolve(savedContact)
}).catch((error) => {
reject(error)
})
})
}
setUrlWithNewId (id: string) {
const oldUrl = this.$route.path
const newUrl = oldUrl + (oldUrl.endsWith('/') ? '' : '/') + id
history.pushState({}, '', newUrl)
}
cancel () {
this.restoreBackup()
if (this.contact.id) {
this.editMode = false
} else {
this.$router.push('search/contacts')
}
}
onEditButtonClick () {
this.createBackup()
this.editMode = true && this.isLoggedIn
}
get readonly () {
return !this.editMode
}
@Watch('contact', { immediate: true, deep: true })
onContactChanged (val: Contact) {
if (val.id) {
const fullName = this.getFullName(val)
this.$store.commit('appbar/setTitle', fullName || 'Add contact')
}
}
@Watch('editMode', { immediate: true, deep: true })
onEditModeChange (editMode: boolean) {
this.$store.commit('appbar/setSaveBtnHidden', !editMode)
this.$store.commit('appbar/setCancelBtnHidden', !editMode)
}
getFullName (contact: Contact) : string {
return contact.givenName + ' ' + contact.familyName
}
get title () : string {
const fullName = this.getFullName(this.contact).trim()
if (fullName) {
return 'Contact: ' + fullName
}
return 'Contact'
}
get isLoggedIn () {
return this.$store.getters['oidc/isAuthenticated']
}
}
</script>
<!--
Web client of the Sensor Management System software developed within the
Helmholtz DataHub Initiative by GFZ and UFZ.
Copyright (C) 2020-2021
- Nils Brinckmann (GFZ, nils.brinckmann@gfz-potsdam.de)
- Marc Hanisch (GFZ, marc.hanisch@gfz-potsdam.de)
- Helmholtz Centre Potsdam - GFZ German Research Centre for
Geosciences (GFZ, https://www.gfz-potsdam.de)
Parts of this program were developed within the context of the
following publicly funded projects or measures:
- Helmholtz Earth and Environment DataHub
(https://www.helmholtz.de/en/research/earth_and_environment/initiatives/#h51095)
Licensed under the HEESIL, Version 1.0 or - as soon they will be
approved by the "Community" - subsequent versions of the HEESIL
(the "Licence").
You may not use this work except in compliance with the Licence.
You may obtain a copy of the Licence at:
https://gitext.gfz-potsdam.de/software/heesil
Unless required by applicable law or agreed to in writing, software
distributed under the Licence is distributed on an "AS IS" basis,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the Licence for the specific language governing
permissions and limitations under the Licence.
-->
<template>
<div>
<ProgressIndicator
v-model="isLoading"
dark
/>
<v-card
flat
>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
small
text
nuxt
to="/search/contacts"
>
cancel
</v-btn>
<v-btn
v-if="isLoggedIn"
color="green"
small
@click="onSaveButtonClicked"
>
create
</v-btn>
</v-card-actions>
<ContactBasicDataForm
ref="basicForm"
v-model="contact"
/>
<v-card-actions>
<v-spacer />
<v-btn
v-if="isLoggedIn"
small
text
nuxt
to="/search/contacts"
>
cancel
</v-btn>
<v-btn
v-if="isLoggedIn"
color="green"
small
@click="onSaveButtonClicked"
>
create
</v-btn>
</v-card-actions>
</v-card>
</div>
</template>
<style lang="scss">
@import "@/assets/styles/_forms.scss";
</style>
<script lang="ts">
import { Component, mixins } from 'nuxt-property-decorator'
import { Rules } from '@/mixins/Rules'
import { Contact } from '@/models/Contact'
import ContactBasicDataForm from '@/components/ContactBasicDataForm.vue'
import ProgressIndicator from '@/components/ProgressIndicator.vue'
@Component({
components: {
ContactBasicDataForm,
ProgressIndicator
}
})
export default class ContactNewPage extends mixins(Rules) {
private numberOfTabs: number = 1
private contact: Contact = new Contact()
private isLoading: boolean = false
mounted () {
this.initializeAppBar()
}
beforeDestroy () {
this.$store.dispatch('appbar/setDefaults')
}
onSaveButtonClicked (): void {
if (!(this.$refs.basicForm as Vue & { validateForm: () => boolean }).validateForm()) {
this.$store.commit('snackbar/setError', 'Please correct your input')
return
}
if (!this.isLoggedIn) {
this.$store.commit('snackbar/setError', 'You need to be logged in to save the contact')
return
}
this.isLoading = true
this.$api.contacts.save(this.contact).then((savedContact) => {
this.isLoading = false
this.$store.commit('snackbar/setSuccess', 'Contact created')
this.$router.push('/contacts/' + savedContact.id + '')
}).catch((_error) => {
this.isLoading = false
this.$store.commit('snackbar/setError', 'Save failed')
})
}
initializeAppBar () {
this.$store.dispatch('appbar/init', {
title: 'Add Contact'
})
}
get isLoggedIn () {
return this.$store.getters['oidc/isAuthenticated']
}
}
</script>
......@@ -298,7 +298,7 @@ permissions and limitations under the Licence.
fab
fixed
right
to="/contacts"
to="/contacts/new"
>
<v-icon>
mdi-plus
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment