Add support for Notes tab in profile view
This commit is contained in:
parent
105dab7a3d
commit
d77de76c97
|
@ -1090,6 +1090,153 @@
|
|||
</b-tab-item>
|
||||
</%def>
|
||||
|
||||
<%def name="render_notes_tab_template()">
|
||||
<script type="text/x-template" id="notes-tab-template">
|
||||
<div>
|
||||
|
||||
% if request.has_perm('people_profile.add_note'):
|
||||
<b-button type="is-primary"
|
||||
class="control"
|
||||
@click="noteNew()"
|
||||
icon-pack="fas"
|
||||
icon-left="plus">
|
||||
Add Note
|
||||
</b-button>
|
||||
% endif
|
||||
|
||||
<b-table :data="notes">
|
||||
|
||||
<b-table-column field="note_type"
|
||||
label="Type"
|
||||
v-slot="props">
|
||||
{{ props.row.note_type_display }}
|
||||
</b-table-column>
|
||||
|
||||
<b-table-column field="subject"
|
||||
label="Subject"
|
||||
v-slot="props">
|
||||
{{ props.row.subject }}
|
||||
</b-table-column>
|
||||
|
||||
<b-table-column field="text"
|
||||
label="Text"
|
||||
v-slot="props">
|
||||
{{ props.row.text }}
|
||||
</b-table-column>
|
||||
|
||||
<b-table-column field="created"
|
||||
label="Created"
|
||||
v-slot="props">
|
||||
<span v-html="props.row.created_display"></span>
|
||||
</b-table-column>
|
||||
|
||||
<b-table-column field="created_by"
|
||||
label="Created By"
|
||||
v-slot="props">
|
||||
{{ props.row.created_by_display }}
|
||||
</b-table-column>
|
||||
|
||||
% if request.has_any_perm('people_profile.edit_note', 'people_profile.delete_note'):
|
||||
<b-table-column label="Actions"
|
||||
v-slot="props">
|
||||
% if request.has_perm('people_profile.edit_note'):
|
||||
<a href="#" @click.prevent="noteEdit(props.row)">
|
||||
<i class="fas fa-edit"></i>
|
||||
Edit
|
||||
</a>
|
||||
% endif
|
||||
% if request.has_perm('people_profile.delete_note'):
|
||||
<a href="#" @click.prevent="noteDelete(props.row)"
|
||||
class="has-text-danger">
|
||||
<i class="fas fa-trash"></i>
|
||||
Delete
|
||||
</a>
|
||||
% endif
|
||||
</b-table-column>
|
||||
% endif
|
||||
|
||||
</b-table>
|
||||
|
||||
<b-modal :active.sync="noteShowDialog"
|
||||
has-modal-card>
|
||||
|
||||
<div class="modal-card">
|
||||
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">
|
||||
{{ noteDialogTitle }}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<section class="modal-card-body">
|
||||
|
||||
<b-field label="Type"
|
||||
:type="!noteDeleting && !noteType ? 'is-danger' : null">
|
||||
<b-select v-model="noteType"
|
||||
:disabled="noteUUID">
|
||||
<option v-for="option in noteTypeOptions"
|
||||
:key="option.value"
|
||||
:value="option.value">
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</b-select>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Subject">
|
||||
<b-input v-model.trim="noteSubject"
|
||||
:disabled="noteDeleting">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Text">
|
||||
<b-input v-model.trim="noteText"
|
||||
type="textarea"
|
||||
:disabled="noteDeleting">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
<b-notification v-if="noteDeleting"
|
||||
type="is-danger"
|
||||
:closable="false">
|
||||
Are you sure you wish to delete this note?
|
||||
</b-notification>
|
||||
|
||||
</section>
|
||||
|
||||
<footer class="modal-card-foot">
|
||||
<b-button :type="noteDeleting ? 'is-danger' : 'is-primary'"
|
||||
@click="noteSave()"
|
||||
:disabled="noteSaving || (!noteDeleting && !noteType)"
|
||||
icon-pack="fas"
|
||||
icon-left="save">
|
||||
{{ noteSaving ? "Working, please wait..." : noteSaveText }}
|
||||
</b-button>
|
||||
<b-button @click="noteShowDialog = false">
|
||||
Cancel
|
||||
</b-button>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
</b-modal>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="render_notes_tab()">
|
||||
<b-tab-item label="Notes"
|
||||
value="notes"
|
||||
icon-pack="fas"
|
||||
:icon="notes.length ? 'check' : null">
|
||||
|
||||
<notes-tab :notes="notes"
|
||||
:note-type-options="noteTypeOptions"
|
||||
@new-notes-data="newNotesData">
|
||||
</notes-tab>
|
||||
|
||||
</b-tab-item>
|
||||
</%def>
|
||||
|
||||
<%def name="render_user_tab()">
|
||||
<b-tab-item label="User"
|
||||
value="user"
|
||||
|
@ -1154,6 +1301,7 @@
|
|||
${self.render_shopper_tab()}
|
||||
% endif
|
||||
${self.render_employee_tab()}
|
||||
${self.render_notes_tab()}
|
||||
${self.render_user_tab()}
|
||||
</%def>
|
||||
|
||||
|
@ -1271,6 +1419,7 @@
|
|||
${parent.render_this_page_template()}
|
||||
${self.render_personal_tab_template()}
|
||||
${self.render_employee_tab_template()}
|
||||
${self.render_notes_tab_template()}
|
||||
${self.render_profile_info_template()}
|
||||
</%def>
|
||||
|
||||
|
@ -1833,6 +1982,136 @@
|
|||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="declare_notes_tab_vars()">
|
||||
<script type="text/javascript">
|
||||
|
||||
let NotesTabData = {
|
||||
noteShowDialog: false,
|
||||
noteUUID: null,
|
||||
noteType: null,
|
||||
noteSubject: null,
|
||||
noteText: null,
|
||||
noteDeleting: false,
|
||||
noteSaving: false,
|
||||
}
|
||||
|
||||
let NotesTab = {
|
||||
template: '#notes-tab-template',
|
||||
mixins: [SimpleRequestMixin],
|
||||
props: {
|
||||
notes: Array,
|
||||
noteTypeOptions: Array,
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
||||
noteDialogTitle() {
|
||||
if (this.noteUUID) {
|
||||
if (this.noteDeleting) {
|
||||
return "Delete Note"
|
||||
}
|
||||
return "Edit Note"
|
||||
}
|
||||
return "New Note"
|
||||
},
|
||||
|
||||
noteSaveText() {
|
||||
if (this.noteDeleting) {
|
||||
return "Delete Note"
|
||||
}
|
||||
return "Save Note"
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
% if request.has_perm('people_profile.add_note'):
|
||||
|
||||
noteNew() {
|
||||
this.noteUUID = null
|
||||
this.noteType = null
|
||||
this.noteSubject = null
|
||||
this.noteText = null
|
||||
this.noteDeleting = false
|
||||
this.noteShowDialog = true
|
||||
},
|
||||
|
||||
% endif
|
||||
|
||||
% if request.has_perm('people_profile.edit_note'):
|
||||
|
||||
noteEdit(note) {
|
||||
this.noteUUID = note.uuid
|
||||
this.noteType = note.note_type
|
||||
this.noteSubject = note.subject
|
||||
this.noteText = note.text
|
||||
this.noteDeleting = false
|
||||
this.noteShowDialog = true
|
||||
},
|
||||
|
||||
% endif
|
||||
|
||||
% if request.has_perm('people_profile.delete_note'):
|
||||
|
||||
noteDelete(note) {
|
||||
this.noteUUID = note.uuid
|
||||
this.noteType = note.note_type
|
||||
this.noteSubject = note.subject
|
||||
this.noteText = note.text
|
||||
this.noteDeleting = true
|
||||
this.noteShowDialog = true
|
||||
},
|
||||
|
||||
% endif
|
||||
|
||||
% if request.has_any_perm('people_profile.add_note', 'people_profile.edit_note', 'people_profile.delete_note'):
|
||||
|
||||
noteSave() {
|
||||
this.noteSaving = true
|
||||
|
||||
let url = null
|
||||
if (!this.noteUUID) {
|
||||
url = '${master.get_action_url('profile_add_note', instance)}'
|
||||
} else if (this.noteDeleting) {
|
||||
url = '${master.get_action_url('profile_delete_note', instance)}'
|
||||
} else {
|
||||
url = '${master.get_action_url('profile_edit_note', instance)}'
|
||||
}
|
||||
|
||||
let params = {
|
||||
uuid: this.noteUUID,
|
||||
note_type: this.noteType,
|
||||
note_subject: this.noteSubject,
|
||||
note_text: this.noteText,
|
||||
}
|
||||
|
||||
this.simplePOST(url, params, response => {
|
||||
this.$emit('new-notes-data', response.data.notes)
|
||||
this.noteSaving = false
|
||||
this.noteShowDialog = false
|
||||
}, response => {
|
||||
this.notesSaving = false
|
||||
})
|
||||
},
|
||||
|
||||
% endif
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="make_notes_tab_component()">
|
||||
${self.declare_notes_tab_vars()}
|
||||
<script type="text/javascript">
|
||||
|
||||
NotesTab.data = function() { return NotesTabData }
|
||||
Vue.component('notes-tab', NotesTab)
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="declare_profile_info_vars()">
|
||||
<script type="text/javascript">
|
||||
|
||||
|
@ -1847,6 +2126,8 @@
|
|||
members: ${json.dumps(members_data)|n},
|
||||
employee: ${json.dumps(employee_data)|n},
|
||||
employeeHistory: ${json.dumps(employee_history_data)|n},
|
||||
notes: ${json.dumps(notes_data)|n},
|
||||
noteTypeOptions: ${json.dumps(note_type_options)|n},
|
||||
users: ${json.dumps(users_data)|n},
|
||||
phoneTypeOptions: ${json.dumps(phone_type_options)|n},
|
||||
emailTypeOptions: ${json.dumps(email_type_options)|n},
|
||||
|
@ -1876,6 +2157,10 @@
|
|||
computed: {},
|
||||
methods: {
|
||||
|
||||
newNotesData(notes) {
|
||||
this.notes = notes
|
||||
},
|
||||
|
||||
personUpdated(person) {
|
||||
this.person = person
|
||||
},
|
||||
|
@ -2001,6 +2286,7 @@
|
|||
${parent.make_this_page_component()}
|
||||
${self.make_personal_tab_component()}
|
||||
${self.make_employee_tab_component()}
|
||||
${self.make_notes_tab_component()}
|
||||
${self.make_profile_info_component()}
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ class PersonView(MasterView):
|
|||
has_versions = True
|
||||
bulk_deletable = True
|
||||
is_contact = True
|
||||
manage_notes_from_profile_view = False
|
||||
supports_autocomplete = True
|
||||
configurable = True
|
||||
|
||||
|
@ -460,6 +459,8 @@ class PersonView(MasterView):
|
|||
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid) if employee else None,
|
||||
'employee_history': employee.get_current_history() if employee else None,
|
||||
'employee_history_data': self.get_context_employee_history(employee),
|
||||
'notes_data': self.get_context_notes(person),
|
||||
'note_type_options': self.get_note_type_options(),
|
||||
'users_data': self.get_context_users(person),
|
||||
'dynamic_content_title': self.get_context_content_title(person),
|
||||
}
|
||||
|
@ -752,6 +753,29 @@ class PersonView(MasterView):
|
|||
})
|
||||
return data
|
||||
|
||||
def get_context_notes(self, person):
|
||||
data = []
|
||||
notes = sorted(person.notes, key=lambda n: n.created, reverse=True)
|
||||
for note in notes:
|
||||
data.append(self.get_context_note(note))
|
||||
return data
|
||||
|
||||
def get_context_note(self, note):
|
||||
app = self.get_rattail_app()
|
||||
return {
|
||||
'uuid': note.uuid,
|
||||
'note_type': note.type,
|
||||
'note_type_display': self.enum.PERSON_NOTE_TYPE.get(note.type, note.type),
|
||||
'subject': note.subject,
|
||||
'text': note.text,
|
||||
'created_display': raw_datetime(self.rattail_config, note.created),
|
||||
'created_by_display': str(note.created_by),
|
||||
}
|
||||
|
||||
def get_note_type_options(self):
|
||||
return [{'value': k, 'label': v}
|
||||
for k, v in self.enum.PERSON_NOTE_TYPE.items()]
|
||||
|
||||
def get_context_users(self, person):
|
||||
data = []
|
||||
users = person.users
|
||||
|
@ -1385,6 +1409,8 @@ class PersonView(MasterView):
|
|||
if mode == 'create':
|
||||
del schema['uuid']
|
||||
form = forms.Form(schema=schema, request=self.request)
|
||||
if mode != 'delete':
|
||||
form.set_validator('note_type', colander.OneOf(self.enum.PERSON_NOTE_TYPE))
|
||||
return form
|
||||
|
||||
def profile_add_note(self):
|
||||
|
@ -1406,11 +1432,15 @@ class PersonView(MasterView):
|
|||
person.notes.append(note)
|
||||
return note
|
||||
|
||||
def profile_add_note_success(self, note):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
def profile_add_note_success(self, note, person=None):
|
||||
return {
|
||||
'notes': self.get_context_notes(person or note.person),
|
||||
}
|
||||
|
||||
def profile_add_note_failure(self, person, form):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
return {
|
||||
'error': str(form.make_deform_form().error),
|
||||
}
|
||||
|
||||
def profile_edit_note(self):
|
||||
person = self.get_instance()
|
||||
|
@ -1429,10 +1459,10 @@ class PersonView(MasterView):
|
|||
return note
|
||||
|
||||
def profile_edit_note_success(self, note):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
return self.profile_add_note_success(note)
|
||||
|
||||
def profile_edit_note_failure(self, person, form):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
return self.profile_add_note_failure(person, form)
|
||||
|
||||
def profile_delete_note(self):
|
||||
person = self.get_instance()
|
||||
|
@ -1449,10 +1479,10 @@ class PersonView(MasterView):
|
|||
self.Session.delete(note)
|
||||
|
||||
def profile_delete_note_success(self, person):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
return self.profile_add_note_success(None, person=person)
|
||||
|
||||
def profile_delete_note_failure(self, person, form):
|
||||
return self.redirect(self.get_action_url('view_profile', person))
|
||||
return self.profile_add_note_failure(person, form)
|
||||
|
||||
def make_user(self):
|
||||
uuid = self.request.POST['person_uuid']
|
||||
|
@ -1657,32 +1687,41 @@ class PersonView(MasterView):
|
|||
permission='people_profile.view_versions',
|
||||
renderer='json')
|
||||
|
||||
# manage notes from profile view
|
||||
if cls.manage_notes_from_profile_view:
|
||||
# profile - add note
|
||||
config.add_tailbone_permission('people_profile',
|
||||
'people_profile.add_note',
|
||||
"Add new Note records")
|
||||
config.add_route(f'{route_prefix}.profile_add_note',
|
||||
f'{instance_url_prefix}/profile/new-note',
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_add_note',
|
||||
route_name=f'{route_prefix}.profile_add_note',
|
||||
permission='people_profile.add_note',
|
||||
renderer='json')
|
||||
|
||||
# add note
|
||||
config.add_tailbone_permission('people_profile', 'people_profile.add_note',
|
||||
"Add new {} Note records".format(model_title))
|
||||
config.add_route('{}.profile_add_note'.format(route_prefix), '{}/{{{}}}/profile/new-note'.format(url_prefix, model_key),
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_add_note', route_name='{}.profile_add_note'.format(route_prefix),
|
||||
permission='people_profile.add_note')
|
||||
# profile - edit note
|
||||
config.add_tailbone_permission('people_profile',
|
||||
'people_profile.edit_note',
|
||||
"Edit Note records")
|
||||
config.add_route(f'{route_prefix}.profile_edit_note',
|
||||
f'{instance_url_prefix}/profile/edit-note',
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_edit_note',
|
||||
route_name=f'{route_prefix}.profile_edit_note',
|
||||
permission='people_profile.edit_note',
|
||||
renderer='json')
|
||||
|
||||
# edit note
|
||||
config.add_tailbone_permission('people_profile', 'people_profile.edit_note',
|
||||
"Edit {} Note records".format(model_title))
|
||||
config.add_route('{}.profile_edit_note'.format(route_prefix), '{}/{{{}}}/profile/edit-note'.format(url_prefix, model_key),
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_edit_note', route_name='{}.profile_edit_note'.format(route_prefix),
|
||||
permission='people_profile.edit_note')
|
||||
|
||||
# delete note
|
||||
config.add_tailbone_permission('people_profile', 'people_profile.delete_note',
|
||||
"Delete {} Note records".format(model_title))
|
||||
config.add_route('{}.profile_delete_note'.format(route_prefix), '{}/{{{}}}/profile/delete-note'.format(url_prefix, model_key),
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_delete_note', route_name='{}.profile_delete_note'.format(route_prefix),
|
||||
permission='people_profile.delete_note')
|
||||
# profile - delete note
|
||||
config.add_tailbone_permission('people_profile',
|
||||
'people_profile.delete_note',
|
||||
"Delete Note records")
|
||||
config.add_route(f'{route_prefix}.profile_delete_note',
|
||||
f'{instance_url_prefix}/profile/delete-note',
|
||||
request_method='POST')
|
||||
config.add_view(cls, attr='profile_delete_note',
|
||||
route_name=f'{route_prefix}.profile_delete_note',
|
||||
permission='people_profile.delete_note',
|
||||
renderer='json')
|
||||
|
||||
# make user for person
|
||||
config.add_route('{}.make_user'.format(route_prefix), '{}/make-user'.format(url_prefix),
|
||||
|
|
Loading…
Reference in a new issue