Document creation, edition, deletion, and signature
This commit is contained in:
parent
48a092432c
commit
eebda06c86
84
htdocs/ModalPromptSignatureCode.vue
Normal file
84
htdocs/ModalPromptSignatureCode.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<TransitionGroup>
|
||||
<div v-if="x_show" class="modal show" style="display: block;" tabindex="-1" @keydown.enter="submit" @keydown.esc="cancel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{label || 'Sign'}}</h5>
|
||||
<button type="button" class="btn-close" @click="cancel"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Code</span>
|
||||
<input ref="input" type="password" class="form-control" :class="{ 'is-invalid': valid === false }" v-model="x_modelValue" @input="() => valid = null" />
|
||||
<div v-if="valid === false" class="invalid-feedback">Invalid code.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" :disabled="!x_modelValue" @click="submit">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="x_show" class="modal-backdrop show"></div>
|
||||
</TransitionGroup>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.v-enter-active, .v-leave-active {
|
||||
transition: opacity 0.25s ease;
|
||||
}
|
||||
.v-enter-from, .v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
client: Object,
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
label: String,
|
||||
modelValue: null
|
||||
},
|
||||
emits: {
|
||||
'cancel': null,
|
||||
'submit': String,
|
||||
'update:show': String,
|
||||
'update:modelValue': null
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
valid: null,
|
||||
x_show: this.show,
|
||||
x_modelValue: this.modelValue
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
show(value) { this.x_show = value; },
|
||||
async x_show(value) {
|
||||
this.x_modelValue = '';
|
||||
this.$emit('update:show', value);
|
||||
await this.$nextTick();
|
||||
if((value) && (this.$refs.input)) this.$refs.input.focus();
|
||||
},
|
||||
modelValue(value) { this.x_modelValue = value; },
|
||||
x_modelValue(value) { this.$emit('update:modelValue', value); }
|
||||
},
|
||||
methods: {
|
||||
cancel() { this.x_show = false; },
|
||||
async submit() {
|
||||
var value = this.x_modelValue;
|
||||
if((this.client) && (value)) {
|
||||
if(this.valid = (await this.client.ORWU_VALIDSIG(' ' + value + ' ')) == '1') {
|
||||
this.x_show = false;
|
||||
this.$emit('submit', value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -2,15 +2,23 @@
|
||||
<Subtitle value="Documents" />
|
||||
<Subtitle :value="patient_info.name" />
|
||||
<div class="row">
|
||||
<div class="selector col-12" :class="{ 'col-xl-4': selection_text }">
|
||||
<div class="selector col-12" :class="{ 'col-xl-4': selection }">
|
||||
<div class="card mb-3 shadow">
|
||||
<div class="card-header"><template v-if="resultset.length > 0">{{resultset.length}}<template v-if="has_more">+</template></template><template v-else-if="is_loading">Loading</template><template v-else>No</template> record{{resultset.length == 1 ? '' : 's'}}</div>
|
||||
<ul class="scroller list-group list-group-flush" :class="{ 'list-skinny': selection_text }" ref="scroller">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><template v-if="resultset.length > 0">{{resultset.length}}<template v-if="has_more">+</template></template><template v-else-if="is_loading">Loading</template><template v-else>No</template> record{{resultset.length == 1 ? '' : 's'}}</span>
|
||||
<router-link :to="'/patient/' + patient_dfn + '/document/new'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" style="width: 1.25em; height: 1.25em; vertical-align: text-bottom;">
|
||||
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"/>
|
||||
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
|
||||
</svg>
|
||||
</router-link>
|
||||
</div>
|
||||
<ul class="scroller list-group list-group-flush" :class="{ 'list-skinny': selection }" ref="scroller">
|
||||
<router-link v-for="item in resultset" :to="'/patient/' + patient_dfn + '/document/' + item.IEN" replace custom v-slot="{ navigate, href }">
|
||||
<li :key="item" class="record list-group-item" :class="{ 'active': selection == item.IEN }" :title="datetimestring(strptime_vista(item.time)) + '\n' + item.title + '\n' + item.location + '\n' + item.author.byline" @click="navigate">
|
||||
<div class="row">
|
||||
<div class="cell col-4"><router-link :to="href" replace>{{datestring(strptime_vista(item.time))}}</router-link></div>
|
||||
<div class="cell col-8">{{item.title}}</div>
|
||||
<div class="cell col-8"><template v-if="item.status == 'unsigned'">✱</template>{{item.title}}</div>
|
||||
<div class="cell secondary col-7 col-lg-4 col-xl-7">{{item.location}}</div>
|
||||
<div class="cell secondary col-5 col-lg-8 col-xl-5">{{item.author.byline}}</div>
|
||||
</div>
|
||||
@ -20,16 +28,14 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="selection_text" class="col-12 col-xl-8">
|
||||
<div class="card mb-3 shadow">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span>{{doctitle(selection_text) || 'Document'}}</span>
|
||||
<router-link class="close" :to="'/patient/' + patient_dfn + '/document'" replace>❌</router-link>
|
||||
</div>
|
||||
<div class="detail card-body" ref="detail">{{selection_text}}</div>
|
||||
</div>
|
||||
<div v-if="selection == 'new'" class="col-12 col-xl-8">
|
||||
<ViewDocNew :client="client" :dfn="patient_dfn" :datetime="datetimestring(new Date())" @cancel="() => $router.replace({ path: '/patient/' + patient_dfn + '/document' })" @submit="doc_create" />
|
||||
</div>
|
||||
<div v-else-if="selection" class="detail col-12 col-xl-8" ref="detail">
|
||||
<ViewDocView :client="client" :dfn="patient_dfn" :ien="selection" @sign="doc_sign_prompt" @delete="doc_delete" @cancel="() => $router.replace({ path: '/patient/' + patient_dfn + '/document' })" />
|
||||
</div>
|
||||
</div>
|
||||
<ModalPromptSignatureCode :client="client" v-model:show="show_signature" @submit="doc_sign" label="Sign Document" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@ -73,7 +79,7 @@
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
}
|
||||
div.detail {
|
||||
div.detail /deep/ .card-body {
|
||||
scroll-margin-top: calc(3.6875rem + 2.5625rem + 25vh);
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
@ -88,7 +94,7 @@
|
||||
div.cell.secondary {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
div.detail {
|
||||
div.detail /deep/ .card-body {
|
||||
max-height: 75vh;
|
||||
scroll-margin-top: 0;
|
||||
overflow-y: auto;
|
||||
@ -100,12 +106,15 @@
|
||||
import { debounce, strptime_vista } from './util.mjs';
|
||||
|
||||
import Subtitle from './Subtitle.vue';
|
||||
import ViewDocNew from './ViewDocNew.vue';
|
||||
import ViewDocView from './ViewDocView.vue';
|
||||
import ModalPromptSignatureCode from './ModalPromptSignatureCode.vue';
|
||||
|
||||
const SZ_WINDOW = 100;
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Subtitle
|
||||
Subtitle, ViewDocNew, ViewDocView, ModalPromptSignatureCode
|
||||
},
|
||||
props: {
|
||||
client: Object,
|
||||
@ -118,13 +127,19 @@
|
||||
dfn: null,
|
||||
has_more: '',
|
||||
is_loading: false,
|
||||
resultset: [],
|
||||
rs_unsigned: [],
|
||||
rs_signed: [],
|
||||
selection: null,
|
||||
selection_text: null,
|
||||
show_signature: false,
|
||||
observer_scroller: null,
|
||||
observer_viewport: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
resultset() {
|
||||
return this.rs_unsigned.concat(this.rs_signed);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.params.tiu_da': {
|
||||
async handler(value) {
|
||||
@ -140,17 +155,6 @@
|
||||
datetimestring(date) {
|
||||
return date.toLocaleDateString('sv-SE') + ' ' + date.toLocaleTimeString('en-GB');
|
||||
},
|
||||
doctitle(doc) {
|
||||
if(doc) {
|
||||
var brk = doc.indexOf('\r\n');
|
||||
if(brk >= 0) {
|
||||
doc = doc.substring(0, brk);
|
||||
brk = doc.indexOf(': ');
|
||||
if(brk >= 0) return doc.substring(brk + 2).replace(/^\s+|\s+$/g, '');
|
||||
else return doc.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
}
|
||||
},
|
||||
async load_more() {
|
||||
try {
|
||||
this.is_loading = true;
|
||||
@ -158,7 +162,7 @@
|
||||
if(this.dfn != this.patient_dfn) {
|
||||
this.dfn = this.patient_dfn;
|
||||
this.has_more = '';
|
||||
this.resultset = [];
|
||||
this.rs_signed = [];
|
||||
}
|
||||
var res = await client.TIU_DOCUMENTS_BY_CONTEXT(3, 1, this.patient_dfn, -1, -1, 0, SZ_WINDOW, 'D', 1, 0, 1, this.has_more);
|
||||
if((res) && (res.length > 0)) {
|
||||
@ -168,44 +172,88 @@
|
||||
this.has_more = last.IEN;
|
||||
res.splice(res.length - 1, 1);
|
||||
}
|
||||
if(this.resultset.length > 0) Array.prototype.push.apply(this.resultset, res);
|
||||
else this.resultset = res;
|
||||
if(this.rs_signed.length > 0) Array.prototype.push.apply(this.rs_signed, res);
|
||||
else this.rs_signed = res;
|
||||
}
|
||||
} else {
|
||||
this.dfn = null;
|
||||
this.has_more = '';
|
||||
this.resultset = [];
|
||||
this.rs_signed = [];
|
||||
}
|
||||
} catch(ex) {
|
||||
console.warn(ex);
|
||||
} finally {
|
||||
this.is_loading = false;
|
||||
}
|
||||
},
|
||||
async load_unsigned() {
|
||||
this.rs_unsigned = [];
|
||||
this.rs_unsigned = await client.TIU_DOCUMENTS_BY_CONTEXT(3, 2, this.patient_dfn, 0, 0, 0, 0, 'D', 1, 0, 1, '');
|
||||
},
|
||||
async reload() {
|
||||
this.dfn = null;
|
||||
await client.TIU_DOCUMENTS_BY_CONTEXT_FLUSH(3, 2, this.patient_dfn, 0, 0, 0, 0, 'D', 1, 0, 1, '');
|
||||
await this.load_unsigned();
|
||||
await client.TIU_DOCUMENTS_BY_CONTEXT_FLUSH(3, 1, this.patient_dfn, -1, -1, 0, SZ_WINDOW, 'D', 1, 0, 1, '');
|
||||
await this.load_more();
|
||||
},
|
||||
async doc_create(params) {
|
||||
var vstr = params.location.datetime ? ('' + params.location.IEN + ';' + params.location.datetime + ';A') : ('' + params.location.IEN + ';' + params.datetime + ';E');
|
||||
var res = await this.client.TIU_CREATE_RECORD(this.patient_dfn, params.title, '', '', '', { '".01"': params.title, '"1202"': params.author, '"1301"': params.datetime, '"1205"': params.location.IEN }, vstr, '1');
|
||||
if(res) {
|
||||
this.reload();
|
||||
this.$router.replace({ path: '/patient/' + this.patient_dfn + '/document/' + res, query: { edit: '' } });
|
||||
} else {
|
||||
console.error('Unable to create document', params, res);
|
||||
window.alert('Unable to create document.');
|
||||
}
|
||||
},
|
||||
doc_sign_prompt(ien) {
|
||||
this.show_signature = true;
|
||||
},
|
||||
async doc_sign(code) {
|
||||
var selection = this.selection;
|
||||
if((selection) & (code)) {
|
||||
this.show_signature = false;
|
||||
await this.client.TIU_SIGN_RECORD(selection, ' ' + code + ' ');
|
||||
this.reload();
|
||||
this.selection = null;
|
||||
await this.$nextTick();
|
||||
this.selection = selection;
|
||||
}
|
||||
},
|
||||
async doc_delete(ien) {
|
||||
if(window.confirm('Delete this document?')) {
|
||||
var vstr = await this.client.ORWPCE_NOTEVSTR(ien);
|
||||
if(vstr) await this.client.ORWPCE_DELETE(vstr, this.patient_dfn);
|
||||
await this.client.TIU_DELETE_RECORD(ien);
|
||||
this.reload();
|
||||
if(this.selection == ien) {
|
||||
this.selection = null;
|
||||
this.$router.replace({ path: '/patient/' + this.patient_dfn + '/document' });
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$watch(
|
||||
() => (this.client, this.patient_dfn, {}),
|
||||
debounce(this.load_more, 500),
|
||||
debounce(() => { this.load_more(); this.load_unsigned(); }, 500),
|
||||
{ immediate: true }
|
||||
);
|
||||
this.$watch(
|
||||
() => (this.client, this.selection, {}),
|
||||
async function() {
|
||||
try {
|
||||
this.selection_text = (this.client) && (this.selection) ? await this.client.TIU_GET_RECORD_TEXT(this.selection) : null;
|
||||
} catch(ex) {
|
||||
this.selection_text = null;
|
||||
console.warn(ex);
|
||||
}
|
||||
if(this.$refs.scroller) {
|
||||
if(this.selection_text) { // scroll to selected item
|
||||
await this.$nextTick();
|
||||
var active = this.$refs.scroller.querySelectorAll(':scope > .active');
|
||||
if(active.length > 0) (Element.prototype.scrollIntoViewIfNeeded || Element.prototype.scrollIntoView).call(active[0]);
|
||||
if(this.$refs.detail) { // scroll to top of detail panel
|
||||
this.$refs.detail.scrollIntoView();
|
||||
this.$refs.detail.scrollTop = 0;
|
||||
if(this.selection) { // scroll to selected item
|
||||
if(this.selection != 'new') {
|
||||
await this.$nextTick();
|
||||
var active = this.$refs.scroller.querySelectorAll(':scope > .active');
|
||||
if(active.length > 0) (Element.prototype.scrollIntoViewIfNeeded || Element.prototype.scrollIntoView).call(active[0]);
|
||||
if(this.$refs.detail) { // scroll to top of detail panel
|
||||
this.$refs.detail.scrollIntoView();
|
||||
this.$refs.detail.scrollTop = 0;
|
||||
}
|
||||
}
|
||||
} else { // scroll to topmost item
|
||||
var offset = this.$refs.scroller.getBoundingClientRect().top;
|
||||
@ -224,9 +272,9 @@
|
||||
);
|
||||
},
|
||||
mounted() {
|
||||
this.observer_scroller = new IntersectionObserver(([entry]) => { if((entry.isIntersecting) && (this.selection_text) && (this.has_more) && (!this.is_loading)) this.load_more(); }, { root: this.$refs.scroller, rootMargin: '25%' });
|
||||
this.observer_scroller = new IntersectionObserver(([entry]) => { if((entry.isIntersecting) && (this.selection) && (this.has_more) && (!this.is_loading)) this.load_more(); }, { root: this.$refs.scroller, rootMargin: '25%' });
|
||||
this.observer_scroller.observe(this.$refs.bottom);
|
||||
this.observer_viewport = new IntersectionObserver(([entry]) => { if((entry.isIntersecting) && (!this.selection_text) && (this.has_more) && (!this.is_loading)) this.load_more(); }, { rootMargin: '25%' });
|
||||
this.observer_viewport = new IntersectionObserver(([entry]) => { if((entry.isIntersecting) && (!this.selection) && (this.has_more) && (!this.is_loading)) this.load_more(); }, { rootMargin: '25%' });
|
||||
this.observer_viewport.observe(this.$refs.bottom);
|
||||
},
|
||||
destroyed() {
|
||||
|
177
htdocs/ViewDocEdit.vue
Normal file
177
htdocs/ViewDocEdit.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div v-if="record !== null" class="card mb-3 shadow">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span>{{record['~.01'] && record['~.01'].description || 'Document'}}</span>
|
||||
<a class="widget" @click="() => update(true)">✔</a>
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><DateTimePicker v-model="datetime" /></li>
|
||||
<li class="list-group-item">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Subject</span>
|
||||
<input type="text" class="form-control" v-model="subject" />
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item"><textarea ref="textarea" class="form-control" v-model="text" @keydown.tab.exact.prevent="tab" @keydown.shift.tab.exact.prevent="untab" /></li>
|
||||
</ul>
|
||||
<div v-if="saved" class="card-footer" style="text-align: right;">Saved at {{saved.toLocaleString()}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a.widget {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
}
|
||||
textarea {
|
||||
font-family: monospace;
|
||||
tab-size: 8;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { debounce } from './util.mjs';
|
||||
import { strptime, strftime } from './fmdatetime.mjs';
|
||||
|
||||
import DateTimePicker from './DateTimePicker.vue';
|
||||
|
||||
function untab({ input, size=8, tab='\t', space=' ', join=true}={}) {
|
||||
input = input.split('\n');
|
||||
for(var i = input.length - 1; i >= 0; --i) input[i] = untab_line(input[i], size, tab, space);
|
||||
return join ? input.join('\n') : input;
|
||||
}
|
||||
function untab_line(line, size=8, tab='\t', space=' ') {
|
||||
var res = '', index = 0, offset = 0, next, count;
|
||||
while((next = line.indexOf(tab, index)) >= 0) {
|
||||
count = size - (next + offset)%size;
|
||||
res += line.substring(index, next) + Array(count + 1).join(space);
|
||||
offset += count - 1;
|
||||
index = next + 1;
|
||||
}
|
||||
return res + line.substring(index);
|
||||
}
|
||||
|
||||
function retab({ input, size=8, tab='\t', space=' ' }={}) {
|
||||
var re_space = new RegExp(space.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '+', 'g');
|
||||
return input.replace(re_space, function(m) { return Array(Math.ceil(m.length/size) + 1).join(tab); });
|
||||
}
|
||||
|
||||
function wrap({ input, width=80, cut=false, tabsize=8, tab='\t', space=' ', untab=false, join=true }={}) {
|
||||
var input = input.split('\n'), lines, res = [];
|
||||
if(untab) {
|
||||
for(var i = 0; i < input.length; ++i) {
|
||||
lines = wrap_line_split(untab_line(input[i], tabsize, tab, space), width, cut);
|
||||
for(var j = 0; j < lines.length; ++j) res.push(lines[j].replace(/(\s)\s+$/, '$1'));
|
||||
}
|
||||
return join ? res.join('\n') : res;
|
||||
} else {
|
||||
for(var i = 0; i < input.length; ++i) {
|
||||
lines = wrap_line_split(untab_line(input[i], tabsize, tab, tab), width, cut); // replace tabs with placeholder tabs
|
||||
for(var j = 0; j < lines.length; ++j) res.push(lines[j].replace(/(\s)\s+$/, '$1'));
|
||||
}
|
||||
res = retab({ input: res.join('\n'), size: tabsize, tab, space: tab }); // collapse placeholder tabs
|
||||
return join ? res : res.split('\n');
|
||||
}
|
||||
}
|
||||
function wrap_line(str, width=80, cut=false, brk='\n') {
|
||||
if(!str) return str;
|
||||
return str.match(new RegExp('.{1,' + width + '}(\\s+|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s+|$)'), 'g')).join(brk);
|
||||
}
|
||||
function wrap_line_split(str, width=80, cut=false) {
|
||||
if(!str) return [str];
|
||||
return str.match(new RegExp('.{1,' + width + '}(\\s+|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s+|$)'), 'g'));
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DateTimePicker
|
||||
},
|
||||
props: {
|
||||
client: Object,
|
||||
dfn: String,
|
||||
ien: String
|
||||
},
|
||||
emits: {
|
||||
'accept': null,
|
||||
'update': Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
record: null,
|
||||
saved: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
datetime: {
|
||||
get() { return this.record && this.record['~1301'] && this.record['~1301'].value; },
|
||||
set(value) { this.record['~1301'].value = strftime(strptime(value)); this.autosave(); }
|
||||
},
|
||||
subject: {
|
||||
get() { return this.record && this.record['~1701'] && this.record['~1701'].value; },
|
||||
set(value) { this.record['~1701'].value = this.record['~.07'].value = value; this.autosave(); }
|
||||
},
|
||||
text: {
|
||||
get() { return this.record && this.record.text; },
|
||||
set(value) { this.record.text = value; this.autosave(); }
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
text() {
|
||||
this.resize();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async tab(evt) {
|
||||
var target = event.target, value = target.value, start = target.selectionStart, end = target.selectionEnd;
|
||||
if(start == end) document.execCommand('insertText', false, '\t');
|
||||
else {
|
||||
start = target.selectionStart = value.lastIndexOf('\n', start - 1) + 1;
|
||||
end = target.selectionEnd = value.indexOf('\n', end); if(end < 0) end = value.length;
|
||||
var selection = value.substring(start, end);
|
||||
document.execCommand('insertText', false, selection.replace(/^/gm, '\t'));
|
||||
await this.$nextTick();
|
||||
target.selectionStart = start;
|
||||
target.selectionEnd = end + selection.split('\n').length;
|
||||
}
|
||||
},
|
||||
async untab(evt) {
|
||||
var target = event.target, value = target.value;
|
||||
var start = target.selectionStart = value.lastIndexOf('\n', target.selectionStart - 1) + 1;
|
||||
var end = target.selectionEnd = value.indexOf('\n', target.selectionEnd); if(end < 0) end = value.length;
|
||||
var selection = value.substring(start, end);
|
||||
document.execCommand('insertText', false, selection.replace(/^\t/gm, ''));
|
||||
await this.$nextTick();
|
||||
target.selectionStart = start;
|
||||
target.selectionEnd = end - (selection.match(/^\t/gm) || []).length;
|
||||
},
|
||||
async update(accept) {
|
||||
var res = this.record.reduce((acc, val) => (acc['"' + val.field + '"'] = val.value, acc), {});
|
||||
var text = wrap({input: this.text || '\x01', width: 80, cut: true, untab: false, join: false});
|
||||
for(var i = 0; i < text.length; ++i) res['"TEXT","' + (i + 1) + '","0"'] = text[i];
|
||||
this.$emit('update', res);
|
||||
if(await this.client.TIU_UPDATE_RECORD(this.ien, res, 0)) {
|
||||
await this.client.TIU_GET_RECORD_TEXT_FLUSH(this.ien);
|
||||
this.saved = new Date();
|
||||
if(accept) this.$emit('accept');
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.resize = debounce(async function() {
|
||||
var textarea = this.$refs.textarea;
|
||||
textarea.style.height = 'auto';
|
||||
await this.$nextTick();
|
||||
textarea.style.height = textarea.scrollHeight + 4 + 'px';
|
||||
}, 50);
|
||||
this.autosave = debounce(this.update, 2000);
|
||||
this.$watch(
|
||||
() => (this.client, this.ien, {}),
|
||||
async function() {
|
||||
this.record = (this.client) && (this.ien) ? await this.client.TIU_LOAD_RECORD_FOR_EDIT(this.ien, '.01;.06;.07;1301;1204;1208;1701;1205;1405;2101;70201;70202') : [];
|
||||
this.resize();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
79
htdocs/ViewDocNew.vue
Normal file
79
htdocs/ViewDocNew.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="card mb-3 shadow">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span>New document</span>
|
||||
<a class="close" @click="() => $emit('cancel')">❌</a>
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><ViewLocationLookup :client="client" :dfn="dfn" label="Visit" v-model="x_location" /></li>
|
||||
<li class="list-group-item"><ViewDocTitleLookup :client="client" label="Title" v-model="x_title" /></li>
|
||||
<li class="list-group-item"><ViewUserLookup :client="client" label="Author" v-model="x_author" /></li>
|
||||
<li class="list-group-item"><DateTimePicker v-model="x_datetime" /></li>
|
||||
</ul>
|
||||
<div class="card-footer btn-group" role="group"><button class="btn btn-primary" :disabled="!((x_location) && (x_location.IEN) && (x_title) && (x_author))" @click="() => $emit('submit', { location: x_location, title: x_title, author: x_author, datetime: fmdatetime(x_datetime) })">Create</button></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a.close {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { strptime, strftime } from './fmdatetime.mjs';
|
||||
|
||||
import ViewLocationLookup from './ViewLocationLookup.vue';
|
||||
import ViewDocTitleLookup from './ViewDocTitleLookup.vue';
|
||||
import ViewUserLookup from './ViewUserLookup.vue';
|
||||
import DateTimePicker from './DateTimePicker.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ViewLocationLookup, ViewDocTitleLookup, ViewUserLookup, DateTimePicker
|
||||
},
|
||||
props: {
|
||||
client: Object,
|
||||
dfn: String,
|
||||
location: String,
|
||||
title: String,
|
||||
author: String,
|
||||
datetime: {
|
||||
type: String,
|
||||
default: 'N'
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
'cancel': null,
|
||||
'submit': Object,
|
||||
'update:location': String,
|
||||
'update:title': String,
|
||||
'update:author': String,
|
||||
'update:datetime': String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
x_location: this.location,
|
||||
x_title: this.title,
|
||||
x_author: this.author,
|
||||
x_datetime: this.datetime
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
location(value) { this.x_location = value; },
|
||||
x_location(value) { this.$emit('update:location', value); },
|
||||
title(value) { this.x_title = value; },
|
||||
x_title(value) { this.$emit('update:title', value); },
|
||||
author(value) { this.x_author = value; },
|
||||
x_author(value) { this.$emit('update:author', value); },
|
||||
datetime(value) { this.x_datetime = value; },
|
||||
x_datetime(value) { this.$emit('update:datetime', value); }
|
||||
},
|
||||
methods: {
|
||||
fmdatetime(datetime) {
|
||||
return strftime(strptime(datetime));
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
123
htdocs/ViewDocTitleLookup.vue
Normal file
123
htdocs/ViewDocTitleLookup.vue
Normal file
@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div v-if="label" class="input-group">
|
||||
<span class="input-group-text">{{label}}</span>
|
||||
<input class="form-control" placeholder="Filter..." v-model="x_query" />
|
||||
</div>
|
||||
<input v-else class="form-control" placeholder="Filter..." v-model="x_query" />
|
||||
<div class="scroller" ref="scroller">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr v-for="item in resultset" :class="{ 'table-active': item.IEN == x_modelValue }" @click="x_modelValue = item.IEN">
|
||||
<td>{{item.name}}</td>
|
||||
<td style="text-align: right;">#{{item.IEN}}</td>
|
||||
</tr>
|
||||
<tr ref="bottom" />
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
div.scroller {
|
||||
max-height: 25vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
td {
|
||||
cursor: default;
|
||||
}
|
||||
.table-active, .table-active:nth-of-type(odd) > * {
|
||||
color: #fff;
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { debounce } from './util.mjs';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
client: Object,
|
||||
label: String,
|
||||
query: String,
|
||||
modelValue: String
|
||||
},
|
||||
emits: {
|
||||
'update:query': String,
|
||||
'update:modelValue': String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
resultset: [],
|
||||
has_more: false,
|
||||
is_loading: true,
|
||||
observer_bottom: null,
|
||||
x_query: this.query,
|
||||
x_modelValue: this.modelValue
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
query_view() {
|
||||
return this.x_query ? this.x_query.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ').toUpperCase() : '';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue(value) { this.x_modelValue = value; },
|
||||
x_modelValue(value) { this.$emit('update:modelValue', value); },
|
||||
query(value) { this.x_query = value; },
|
||||
x_query(value) { this.$emit('update:query', value); }
|
||||
},
|
||||
methods: {
|
||||
async handle_bottom([entry]) {
|
||||
if((entry.isIntersecting) && (this.has_more) && (!this.is_loading)) {
|
||||
this.is_loading = true;
|
||||
this.has_more = false;
|
||||
try {
|
||||
var batch = await this.client.TIU_LONG_LIST_OF_TITLES(3, this.resultset[this.resultset.length - 1].name, 1);
|
||||
if(this.query_view.length >= 1) batch = batch.filter(x => x.name.startsWith(this.query_view));
|
||||
if(batch.length > 0) {
|
||||
Array.prototype.push.apply(this.resultset, batch);
|
||||
this.has_more = true;
|
||||
} else this.has_more = false;
|
||||
} catch(ex) {
|
||||
this.has_more = false;
|
||||
} finally {
|
||||
this.is_loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$watch(
|
||||
() => (this.client, this.query_view, {}),
|
||||
debounce(async function() {
|
||||
if(this.client) {
|
||||
this.is_loading = true;
|
||||
this.has_more = false;
|
||||
try {
|
||||
var query = this.query_view;
|
||||
if(query.length >= 1) {
|
||||
var batch = await this.client.TIU_LONG_LIST_OF_TITLES(3, query.slice(0, -1) + String.fromCharCode(query.charCodeAt(query.length - 1) - 1) + '~', 1);
|
||||
this.resultset = batch.filter(x => x.name.startsWith(query));
|
||||
} else this.resultset = await this.client.TIU_LONG_LIST_OF_TITLES(3, '', 1);
|
||||
this.has_more = this.resultset.length > 0;
|
||||
} catch(ex) {
|
||||
this.resultset = [];
|
||||
this.has_more = false;
|
||||
} finally {
|
||||
this.is_loading = false;
|
||||
if(this.$refs.scroller) this.$refs.scroller.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
}, 500),
|
||||
{ immediate: true }
|
||||
);
|
||||
},
|
||||
mounted() {
|
||||
this.observer_bottom = new IntersectionObserver(this.handle_bottom, { root: this.$refs.scroller, rootMargin: '25%' });
|
||||
this.observer_bottom.observe(this.$refs.bottom);
|
||||
},
|
||||
destroyed() {
|
||||
if(this.observer_bottom) this.observer_bottom.disconnect();
|
||||
}
|
||||
};
|
||||
</script>
|
98
htdocs/ViewDocView.vue
Normal file
98
htdocs/ViewDocView.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<ViewDocEdit v-if="(can_edit) && (is_editing)" :client="client" :dfn="dfn" :ien="ien" @update="x => $emit('update', x)" @accept="doc_accept" />
|
||||
<div v-else class="card mb-3 shadow">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span>{{localtitle || 'Document'}}</span>
|
||||
<span>
|
||||
<a v-if="can_delete" class="widget" @click="() => $emit('delete', ien)">🗑</a>
|
||||
<a v-if="can_edit" class="widget" @click="() => is_editing = true">✏</a>
|
||||
<a v-if="can_sign" class="widget" @click="() => $emit('sign', ien)">🔏</a>
|
||||
<a class="widget" @click="() => $emit('cancel')">❌</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">{{text}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a.widget {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
}
|
||||
div.card-body {
|
||||
tab-size: 8;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import ViewDocEdit from './ViewDocEdit.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ViewDocEdit
|
||||
},
|
||||
props: {
|
||||
client: Object,
|
||||
dfn: String,
|
||||
ien: String,
|
||||
},
|
||||
emits: {
|
||||
'cancel': null,
|
||||
'sign': null,
|
||||
'update': Object,
|
||||
'delete': String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: null,
|
||||
can_sign: null,
|
||||
can_edit: null,
|
||||
can_delete: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
is_editing: {
|
||||
get() { return this.$route.query.hasOwnProperty('edit'); },
|
||||
set(value) {
|
||||
var query = { ...this.$route.query };
|
||||
if(value) query.edit = '';
|
||||
else delete query.edit;
|
||||
this.$router.replace({ query });
|
||||
}
|
||||
},
|
||||
localtitle() {
|
||||
var doc = this.text;
|
||||
if(doc) {
|
||||
var brk = doc.indexOf('\r\n');
|
||||
if(brk >= 0) {
|
||||
doc = doc.substring(0, brk);
|
||||
brk = doc.indexOf(': ');
|
||||
if(brk >= 0) return doc.substring(brk + 2).replace(/^\s+|\s+$/g, '');
|
||||
else return doc.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async doc_accept() {
|
||||
this.text = await this.client.TIU_GET_RECORD_TEXT(this.ien);
|
||||
this.is_editing = false;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$watch(
|
||||
() => (this.client, this.ien, {}),
|
||||
async function() {
|
||||
this.text = this.can_edit = this.can_delete = null;
|
||||
if((this.client) && (this.ien)) {
|
||||
this.text = await this.client.TIU_GET_RECORD_TEXT(this.ien);
|
||||
this.can_sign = (await this.client.TIU_AUTHORIZATION(this.ien, 'SIGNATURE') == '1') || (await this.client.TIU_AUTHORIZATION(this.ien, 'COSIGNATURE') == '1');
|
||||
this.can_edit = await this.client.TIU_AUTHORIZATION(this.ien, 'EDIT RECORD') == '1';
|
||||
this.can_delete = await this.client.TIU_AUTHORIZATION(this.ien, 'DELETE RECORD') == '1';
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
131
htdocs/ViewUserLookup.vue
Normal file
131
htdocs/ViewUserLookup.vue
Normal file
@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div v-if="label" class="input-group">
|
||||
<span class="input-group-text">{{label}}</span>
|
||||
<input class="form-control" placeholder="Filter..." v-model="x_query" />
|
||||
</div>
|
||||
<input v-else class="form-control" placeholder="Filter..." v-model="x_query" />
|
||||
<div class="scroller" ref="scroller">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr v-for="item in resultset" :class="{ 'table-active': item.DUZ == x_modelValue }" @click="x_modelValue = item.DUZ">
|
||||
<td>{{item.name}}</td>
|
||||
<td>{{item.description.replace(/^-\s*/g, '')}}</td>
|
||||
<td style="text-align: right;">#{{item.DUZ}}</td>
|
||||
</tr>
|
||||
<tr ref="bottom" />
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
div.scroller {
|
||||
max-height: 25vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
td {
|
||||
cursor: default;
|
||||
}
|
||||
.table-active, .table-active:nth-of-type(odd) > * {
|
||||
color: #fff;
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { debounce } from './util.mjs';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
client: Object,
|
||||
label: String,
|
||||
query: String,
|
||||
modelValue: String
|
||||
},
|
||||
emits: {
|
||||
'update:query': String,
|
||||
'update:modelValue': String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
resultset: [],
|
||||
has_more: false,
|
||||
is_loading: true,
|
||||
observer_bottom: null,
|
||||
x_query: this.query,
|
||||
x_modelValue: this.modelValue
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
query_view() {
|
||||
return this.x_query ? this.x_query.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ').toUpperCase() : '';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue(value) { this.x_modelValue = value; },
|
||||
x_modelValue(value) { this.$emit('update:modelValue', value); },
|
||||
query(value) { this.x_query = value; },
|
||||
x_query(value) { this.$emit('update:query', value); }
|
||||
},
|
||||
methods: {
|
||||
async set_default() {
|
||||
if(this.x_modelValue) return;
|
||||
var userinfo = await this.client.XUS_GET_USER_INFO();
|
||||
this.x_modelValue = userinfo[0];
|
||||
this.x_query = userinfo[1]
|
||||
},
|
||||
async handle_bottom([entry]) {
|
||||
if((entry.isIntersecting) && (this.has_more) && (!this.is_loading)) {
|
||||
this.is_loading = true;
|
||||
this.has_more = false;
|
||||
try {
|
||||
var batch = await this.client.ORWU_NEWPERS(this.resultset[this.resultset.length - 1].name, 1, '', '', '', '', '', '', 0);
|
||||
if(this.query_view.length >= 1) batch = batch.filter(x => x.name.toUpperCase().startsWith(this.query_view));
|
||||
if(batch.length > 0) {
|
||||
Array.prototype.push.apply(this.resultset, batch);
|
||||
this.has_more = true;
|
||||
} else this.has_more = false;
|
||||
} catch(ex) {
|
||||
this.has_more = false;
|
||||
} finally {
|
||||
this.is_loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$watch(
|
||||
() => (this.client, this.query_view, {}),
|
||||
debounce(async function() {
|
||||
if(this.client) {
|
||||
this.is_loading = true;
|
||||
this.has_more = false;
|
||||
try {
|
||||
var query = this.query_view;
|
||||
if(query.length >= 1) {
|
||||
var batch = await this.client.ORWU_NEWPERS(query.slice(0, -1) + String.fromCharCode(query.charCodeAt(query.length - 1) - 1) + '~', 1, '', '', '', '', '', '', 0);
|
||||
this.resultset = batch.filter(x => x.name.toUpperCase().startsWith(query));
|
||||
} else this.resultset = await this.client.ORWU_NEWPERS('', 1, '', '', '', '', '', '', 0);
|
||||
this.has_more = this.resultset.length > 0;
|
||||
} catch(ex) {
|
||||
this.resultset = [];
|
||||
this.has_more = false;
|
||||
} finally {
|
||||
this.is_loading = false;
|
||||
if(this.$refs.scroller) this.$refs.scroller.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
}, 500),
|
||||
{ immediate: true }
|
||||
);
|
||||
this.set_default();
|
||||
},
|
||||
mounted() {
|
||||
this.observer_bottom = new IntersectionObserver(this.handle_bottom, { root: this.$refs.scroller, rootMargin: '25%' });
|
||||
this.observer_bottom.observe(this.$refs.bottom);
|
||||
},
|
||||
destroyed() {
|
||||
if(this.observer_bottom) this.observer_bottom.disconnect();
|
||||
}
|
||||
};
|
||||
</script>
|
@ -189,6 +189,20 @@ export const d_parse_multireport = data => {
|
||||
return (res._ts = _ts, res);
|
||||
};
|
||||
|
||||
export const d_parse_tiurecordtiux = data => {
|
||||
var res = {};
|
||||
if(data.length < 1) return res;
|
||||
var brk = data.indexOf('$TXT'), text = undefined;
|
||||
if(brk >= 0) {
|
||||
text = data.slice(brk + 1).join('\r\n');
|
||||
data = data.slice(0, brk);
|
||||
}
|
||||
data = d_split(data, '^', 'field', 'value', 'description');
|
||||
data = data.reduce((acc, val) => (acc['~' + val.field] = val, acc), data);
|
||||
if(text) data.text = text;
|
||||
return data;
|
||||
};
|
||||
|
||||
export const d_parse_tiudocumentlist = data => d_split(data, '^', 'IEN', 'title', 'time', 'patient', 'author', 'location', 'status', 'visit').map(row => {
|
||||
row.author = row.author ? d_split1(row.author, ';', 'IEN', 'byline', 'name') : null;
|
||||
row.visit = row.visit ? d_split1(row.visit, ';', 'date', 'time') : null;
|
||||
@ -311,10 +325,24 @@ export function Client(cid, secret) {
|
||||
this.TIU_TEMPLATE_LOCK = aflow((...args) => this.call({ method: 'TIU_TEMPLATE_LOCK', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_TEMPLATE_UNLOCK = aflow((...args) => this.call({ method: 'TIU_TEMPLATE_UNLOCK', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_DOCUMENTS_BY_CONTEXT = aflow((...args) => this.call({ method: 'TIU_DOCUMENTS_BY_CONTEXT', context: ['OR CPRS GUI CHART'], ttl: 60, stale: false }, ...args), d_log, d_unwrap, d_parse_array, d_parse_tiudocumentlist);
|
||||
this.TIU_DOCUMENTS_BY_CONTEXT_FLUSH = aflow((...args) => this.call({ method: 'TIU_DOCUMENTS_BY_CONTEXT', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap, d_parse_array, d_parse_tiudocumentlist);
|
||||
this.TIU_GET_RECORD_TEXT = aflow((...args) => this.call({ method: 'TIU_GET_RECORD_TEXT', context: ['OR CPRS GUI CHART'], ttl: 60, stale: false }, ...args), d_log, d_unwrap, d_parse_text);
|
||||
this.TIU_GET_RECORD_TEXT_FLUSH = aflow((...args) => this.call({ method: 'TIU_GET_RECORD_TEXT', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap, d_parse_text);
|
||||
this.TIU_LONG_LIST_OF_TITLES = memoized(aflow((...args) => this.call({ method: 'TIU_LONG_LIST_OF_TITLES', context: ['OR CPRS GUI CHART'], ttl: 86400, stale: true, ttl: 86400, stale: true }, ...args), d_log, d_unwrap, f_split('^', 'IEN', 'name')));
|
||||
this.TIU_CREATE_RECORD = aflow((...args) => this.call({ method: 'TIU_CREATE_RECORD', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_AUTHORIZATION = aflow((...args) => this.call({ method: 'TIU_AUTHORIZATION', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_LOAD_RECORD_FOR_EDIT = aflow((...args) => this.call({ method: 'TIU_LOAD_RECORD_FOR_EDIT', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap, d_parse_tiurecordtiux);
|
||||
this.TIU_UPDATE_RECORD = aflow((...args) => this.call({ method: 'TIU_UPDATE_RECORD', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_DELETE_RECORD = aflow((...args) => this.call({ method: 'TIU_DELETE_RECORD', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
this.TIU_SIGN_RECORD = aflow((...args) => this.call({ method: 'TIU_SIGN_RECORD', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
|
||||
this.ORWPCE_NOTEVSTR = aflow((...args) => this.call({ method: 'ORWPCE_NOTEVSTR', context: ['OR CPRS GUI CHART'], ttl: 86400, stale: true }, ...args), d_log, d_unwrap);
|
||||
this.ORWPCE_DELETE = aflow((...args) => this.call({ method: 'ORWPCE_DELETE', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap);
|
||||
|
||||
this.ORWCV_VST = memoized(aflow((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWCV_VST', ...args), d_log, d_unwrap, f_split('^', 'apptinfo', 'datetime', 'location', 'status')));
|
||||
|
||||
this.ORWU_NEWPERS = memoized(aflow((...args) => this.call({ method: 'ORWU_NEWPERS', context: ['OR CPRS GUI CHART'], ttl: 86400, stale: true }, ...args), d_log, d_unwrap, f_split('^', 'DUZ', 'name', 'description')));
|
||||
this.ORWU_VALIDSIG = memoized(aflow((...args) => this.call({ method: 'ORWU_VALIDSIG', context: ['OR CPRS GUI CHART'], ttl: 0, stale: false }, ...args), d_log, d_unwrap));
|
||||
this.ORWU1_NEWLOC = memoized(aflow((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWU1_NEWLOC', ...args), d_log, d_unwrap, f_split('^', 'IEN', 'name')));
|
||||
|
||||
this.ORWDX_DGNM = memoized(aflow((...args) => this.callctx(['OR CPRS GUI CHART'], 'ORWDX_DGNM', ...args), d_log, d_unwrap));
|
||||
|
Loading…
Reference in New Issue
Block a user