Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
Checking in the text replacement feature
Browse files Browse the repository at this point in the history
Now in generally ES6-accepted notation.
  • Loading branch information
tangollama committed Apr 14, 2017
1 parent d097f69 commit c0ff406
Show file tree
Hide file tree
Showing 28 changed files with 406 additions and 19 deletions.
27 changes: 27 additions & 0 deletions app/admin/textreplace/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Ember from 'ember';
import EmberValidations from 'ember-validations';

export default Ember.Controller.extend(EmberValidations, {
hideCancelButton: true,
updateCapability: 'update_config',

createExpansion: function() {
let newExpansion = this.get('store').createRecord('text-expansion');
this.set('newExpansion', newExpansion);
}.on('init'),

actions: {
cancelExpansion() {
this.createExpansion();
}
},

validations: {
'newExpansion.from': {
presence: true
},
'newExpansion.to': {
presence: true
}
}
});
46 changes: 46 additions & 0 deletions app/admin/textreplace/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import AbstractIndexRoute from 'hospitalrun/routes/abstract-index-route';
import { translationMacro as t } from 'ember-i18n';

export default AbstractIndexRoute.extend({
pageTitle: t('admin.text_replacements.page_title'),
hideNewButton: true,

model() {
let store = this.get('store');
return store.findAll('text-expansion').then((result) => {
return result.filter((model) => {
let isNew = model.get('isNew');
console.log(`${model.get('from')} ${isNew}`);
return !isNew;
});
});
},

setupController(controller, model) {
this._super(controller, model);
controller.createExpansion();
},

actions: {
addExpansion(newExpansion) {
newExpansion.save()
.then(() => {
this.refresh();
})
.catch(() => {
this.refresh();
});
},

deleteExpansion(expansion) {
expansion.deleteRecord();
expansion.save()
.then(() => {
this.refresh();
})
.catch(() => {
this.refresh();
});
}
}
});
35 changes: 35 additions & 0 deletions app/admin/textreplace/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div class="panel panel-primary">
<h3>{{t 'admin.text_replacements.existing_repl'}}</h3>
<p>{{t 'admin.text_replacements.repl_desc'}}</p>
<table class="table">
<tr class="table-header">
<th>{{t 'labels.from'}}</th>
<th>{{t 'labels.to'}}</th>
<th/>
</tr>
<tbody>
{{#each model as |expansion|}}
<tr>
<td>#{{expansion.from}}</td>
<td>{{expansion.to}}</td>
<td>
<button class="pull-right btn button-default on-white" {{action 'deleteExpansion' expansion}}>{{t 'buttons.delete'}}</button>
</td>
</tr>
{{/each}}
</tbody>
</table>
<div class="panel">
<div class="panel-body">
<h3>{{t 'admin.text_replacements.create_new'}}</h3>
{{#em-form model=newExpansion action="addExpansion" formLayout="horizontal" showErrorsOnFocusIn="true" submitButton=false}}
{{em-input property="from" label=(t 'labels.from') placeholder=(t 'admin.text_replacements.to_replace')}}
{{em-input property="to" label=(t 'labels.from') placeholder=(t 'admin.text_replacements.replace_with')}}
{{/em-form}}
</div>
<div class="panel-footer">
<button class="btn button-primary on-white" disabled={{isInvalid}} {{action 'addExpansion' newExpansion}}>{{t 'buttons.add'}}</button>
<button class="btn button-default on-white" {{action 'cancelExpansion'}}>{{t 'buttons.cancel'}}</button>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion app/appointments/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@
}}
</div>
{{/if}}
{{em-text label=(t 'models.appointment.labels.notes') property="notes" rows=3 }}
{{expand-text label=(t 'models.appointment.labels.notes') property="notes" rows=3 }}
{{/em-form}}
{{/edit-panel}}
153 changes: 153 additions & 0 deletions app/components/expand-text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import Ember from 'ember';
import textExpansion from '../utils/text-expansion';

export default Ember.Component.extend({
i18n: Ember.inject.service(),
store: Ember.inject.service(),

userText: '',

didInsertElement() {
try {
let feedbackDiv = document.createElement('div');
feedbackDiv.style.position = 'absolute';
let textarea = this.$()[0].getElementsByTagName('textarea')[0];
this.set('textarea', textarea);
let textPos = textarea.getBoundingClientRect();
let fbStyle = feedbackDiv.style;
fbStyle.top = `${textPos.bottom}px`;
fbStyle.left = `${textPos.left}px`;
fbStyle.width = `${textarea.offsetWidth}px`;
fbStyle.backgroundColor = 'lightyellow';
fbStyle.borderStyle = 'solid';
fbStyle.borderWidth = '1px';
fbStyle.borderRadius = '3px';
fbStyle.paddingLeft = '5px';
fbStyle.visibility = 'hidden';

this.set('feedbackDiv', feedbackDiv);
this.get('feedbackText');
this.get('activeExpansionSite');

this.get('store')
.findAll('text-expansion')
.then((expansions) => {
return expansions.reduce((prev, curr) => {
// console.log(`curr ${JSON.stringify(prev)}`);
prev[curr.get('from')] = curr.get('to');
return prev;
}, {});
})
.then((expansions) => {
this.set('expansions', expansions);
});

} catch(e) {
// console.log(`didInsert {e}`);
}
},

keyUp(k) {
let textArea = k.target;
let text = textArea.value;
this.set('userText', text);
this.set('cursorLocation', textArea.selectionStart);
},

keyDown(k) {
if (k.keyCode === 13) {
let possibleSwaps = this.get('possibleSwaps');
if (possibleSwaps && possibleSwaps.length === 1) {
let swapTo = possibleSwaps[0].to;
let activeSite = this.get('activeExpansionSite');
let sliceLength = activeSite.match.length;
let currentText = k.target.value;
let modifiedText = currentText.slice(0, activeSite.index) + swapTo + currentText.slice(activeSite.index + sliceLength);
k.target.value = modifiedText;

k.preventDefault();
k.returnValue = false;
k.cancelBubble = true;
return false;
}
}
},

// Find an expandable word that has the cursor within it
activeExpansionSite: Ember.computed('userText', 'cursorLocation', function() {

let userText = this.get('userText');
let textarea = this.get('textarea');
if (!textarea) {
return null;
}
let cursorLoc = textarea.selectionStart;
let subjects = textExpansion.findExpansionSubjects(userText);
let sites = textExpansion.findExpansionSites(userText, subjects);

return sites.find((s) => {
let endIndex = s.index + s.match.length;

return cursorLoc >= s.index && cursorLoc <= endIndex;
});
}),

// If an expansion site is active, which possible swaps could occur there?
possibleSwaps: Ember.computed('activeExpansionSite', 'expansions', function() {
let activeSite = this.get('activeExpansionSite');

if (activeSite) {
let expansions = this.get('expansions');
return Object.keys(expansions)
.filter((ex) => {
return ex.startsWith(activeSite.term);
})
.sort()
.map((from) => {
return {
from,
to: expansions[from]
};
});
}
}),

expansionText: Ember.computed('possibleSwaps', 'activeExpansionSite', 'userText', function() {
let result = '';

let i18n = this.get('i18n');
let possibleSwaps = this.get('possibleSwaps');
if (possibleSwaps) {
let activeSite = this.get('activeExpansionSite');

if (possibleSwaps.length === 1) {
let swapTo = possibleSwaps[0].to;
result = i18n.t('admin.text_replacements.perform_expand', { from: activeSite.term, to: swapTo });
} else if (possibleSwaps.length > 1) {
let possible = possibleSwaps
.map((swap) => {
return swap.from;
}).join(', ');
result = i18n.t('admin.text_replacements.possible_expansions', { possible });
} else {
result = i18n.t('admin.text_replacements.no_matches', { term: activeSite.term });
}
}

return result;
}),

expansionDivStyle: Ember.computed('expansionText', function() {
let expansionText = this.get('expansionText');
let visiblility = expansionText ? 'visible' : 'hidden';
let textArea = this.get('textarea');

let styleString = `visibility: ${visiblility};`;

if (textArea) {
let textPos = textArea.getBoundingClientRect();
styleString += ` top: ${textPos.bottom}px; left: ${textPos.left}px; width: ${textArea.offsetWidth}px;`;
}
return new Ember.Handlebars.SafeString(styleString);
})
});
2 changes: 1 addition & 1 deletion app/imaging/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@
}}
{{em-input property="result" label=(t 'labels.result') class="result-input"}}
{{/if}}
{{em-text property="notes" label=(t 'labels.notes') rows=3 }}
{{expand-text property="notes" label=(t 'labels.notes') rows=3 }}
{{/em-form}}
{{/edit-panel}}
2 changes: 1 addition & 1 deletion app/incident/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
{{/if}}
</div>
<div class="row">
{{em-text label=(t 'incident.labels.description') property="description" class="required col-sm-12 incident-description" rows=3}}
{{expand-text label=(t 'incident.labels.description') property="description" class="required col-sm-12 incident-description" rows=3}}
</div>

{{#if canManageIncident}}
Expand Down
2 changes: 1 addition & 1 deletion app/incident/note/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{{date-picker property="dateRecorded" label=(t 'incident.labels.dateRecorded') class="col-sm-6" format="l h:mm A" showTime=true }}
</div>
<div class="row">
{{em-text property="description" label=(t 'incident.labels.note') class="col-sm-12 note-description"}}
{{expand-text property="description" label=(t 'incident.labels.note') class="col-sm-12 note-description"}}
</div>
{{/em-form}}
{{/modal-dialog}}
2 changes: 1 addition & 1 deletion app/inventory/adjust/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
}}
{{number-input property="adjustmentQuantity" label=(t 'labels.quantity') class="col-sm-3 required"}}
</div>
{{em-text label=(t 'inventory.labels.reason') property="reason" rows=3}}
{{expand-text label=(t 'inventory.labels.reason') property="reason" rows=3}}
<div class="row">
{{date-picker property="dateCompleted" label=(t 'inventory.labels.adjustmentDate') class="col-sm-4 required"}}
{{select-or-typeahead property="expenseAccount" label=(t 'inventory.labels.expense') list=expenseAccountList selection=model.expenseAccount class="col-sm-8"}}
Expand Down
2 changes: 1 addition & 1 deletion app/invoices/payment/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
{{number-input property="amount" label=(t 'labels.amount') class="required payment-amount"}}
{{date-picker property="datePaid" label=(t 'labels.datePaid') maxDate="now" class="required"}}
{{select-or-typeahead property="expenseAccount" label=(t 'labels.creditTo') list=expenseAccountList selection=model.expenseAccount }}
{{em-text property="notes" label=(t 'labels.notes')}}
{{expand-text property="notes" label=(t 'labels.notes')}}
{{/em-form}}
{{/modal-dialog}}
2 changes: 1 addition & 1 deletion app/labs/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
{{#if canComplete}}
{{em-input property="result" label=(t 'labels.result') class="test-result-input"}}
{{/if}}
{{em-text property="notes" label=(t 'labels.notes') rows=3 }}
{{expand-text property="notes" label=(t 'labels.notes') rows=3 }}
{{custom-form-manager model=model formType="lab"}}
{{/em-form}}
{{/edit-panel}}
14 changes: 14 additions & 0 deletions app/locales/en/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,17 @@ export default {
messages: { roleSaved: 'The {{roleName}} role has been saved.' },
titles: { roleSaved: 'Role Saved' }
},
text_replacements: {

This comment has been minimized.

Copy link
@jkleinsc

jkleinsc Apr 14, 2017

Member

These values should be camel cased; no underscores

create_new: 'Create a new text replacement',
existing_repl: 'Existing replacements',
repl_desc: 'When entering text, these shortcuts allow you to replace a short sequence of characters with a longer phrase.',
page_title: 'Text Replacements',
to_replace: 'Text to replace',
replace_with: 'Replace with',
perform_expand: "Press Enter to replace #{{from}} with '{{to}}'",
possible_expansions: 'Possible replacements: {{possible}}',
no_matches: "No replacements match '{{term}}'"
},
userRoles: 'User Roles',
users: 'Users',
visitForms: {
Expand Down Expand Up @@ -793,6 +804,7 @@ export default {
fileLoadSuccessful: 'File To Load Successful',
fileName: 'File Name',
fileToLoad: 'File Load',
from: 'From',
fulfill: 'Fulfill',
fulfillRequest: 'Fulfill Request',
fulfillRequestNow: 'Fulfill Request Now',
Expand Down Expand Up @@ -841,6 +853,7 @@ export default {
startTime: 'Start Time',
status: 'Status',
takenBy: 'Taken By',
to: 'To',
total: 'Total',
type: 'Type',
userCanAddNewValue: 'User Can Add New Values',
Expand Down Expand Up @@ -1098,6 +1111,7 @@ export default {
"today'sAppointments": "Today's Appointments",
userRoles: 'User Roles',
users: 'Users',
text_replacements: 'Text Replacements',
workflow: 'Workflow'
}
},
Expand Down
2 changes: 1 addition & 1 deletion app/medication/edit/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
{{static-text label=(t 'medication.labels.refills') class="col-xs-3" value=model.refills }}
</div>
{{else}}
{{em-text property="prescription" label=(t 'labels.prescription')rows="3" class=prescriptionClass }}
{{expand-text property="prescription" label=(t 'labels.prescription')rows="3" class=prescriptionClass }}
<div class="row">
{{date-picker property="prescriptionDate" label=(t 'labels.prescriptionDate') class="col-sm-4"}}
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/medication/return/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{{select-or-typeahead property="deliveryLocation" label=(t 'medication.labels.returnLocation') list=warehouseList selection=model.location className="col-xs-4"}}
{{select-or-typeahead property="deliveryAisle" label=(t 'medication.labels.returnAisle') list=aisleLocationList selection=model.aisleLocation className="col-xs-4"}}
</div>
{{em-text property="reason" label=(t 'medication.labels.returnReason') rows="3"}}
{{expand-text property="reason" label=(t 'medication.labels.returnReason') rows="3"}}
<div class="row">
{{date-picker property="dateCompleted" label=(t 'medication.labels.adjustmentDate') class="col-sm-4"}}
{{select-or-typeahead property="expenseAccount" label=(t 'medication.labels.creditToAccount') list=expenseAccountList selection=model.expenseAccount className="col-sm-8"}}
Expand Down
6 changes: 6 additions & 0 deletions app/mixins/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ export default Ember.Mixin.create({
route: 'admin.lookup',
capability: 'update_config'
},
{
title: 'Text Replacements',
iconClass: 'octicon-plus',
route: 'admin.textreplace',
capability: 'update_config'
},
{
title: 'Print Header',
iconClass: 'octicon-chevron-right',
Expand Down
Loading

0 comments on commit c0ff406

Please sign in to comment.