diff --git a/app/admin/query/template.hbs b/app/admin/query/template.hbs index 5a3f7307cb..317319b4fc 100644 --- a/app/admin/query/template.hbs +++ b/app/admin/query/template.hbs @@ -5,7 +5,7 @@
{{#em-form model=this submitButton=false as |form|}}
- {{form.select class="col-xs-3" label="Object Type" + {{form.select class="col-xs-3 form-input-group" label="Object Type" property="objectType" content=objectTypes selected=objectType }} diff --git a/app/admin/roles/template.hbs b/app/admin/roles/template.hbs index 3ecb3a1b0a..312c495c5d 100644 --- a/app/admin/roles/template.hbs +++ b/app/admin/roles/template.hbs @@ -2,7 +2,7 @@
{{#em-form model=this submitButton=false as |form|}} -
+
- {{#each visitTemplates as |visitTemplate|}} - - {{/each}} - +
+ +
{{/each}} diff --git a/app/custom-form-add/template.hbs b/app/custom-form-add/template.hbs index d24e99d05b..7d9a1803bb 100644 --- a/app/custom-form-add/template.hbs +++ b/app/custom-form-add/template.hbs @@ -7,7 +7,7 @@ {{#em-form model=model submitButton=false as |form|}} {{form.select label=(t 'customForms.labels.formToAdd') property="selectedForm" content=model.customForms - prompt=" " class="form-to-add" + prompt=" " class="form-to-add form-input-group" }} {{/em-form}} {{/modal-dialog}} diff --git a/app/imaging/edit/template.hbs b/app/imaging/edit/template.hbs index ee286e81c6..12df21f962 100644 --- a/app/imaging/edit/template.hbs +++ b/app/imaging/edit/template.hbs @@ -7,7 +7,7 @@ {{/if}} {{#if model.isNew}}
- {{form.select class="col-xs-3 required" label=(t 'labels.visit') + {{form.select class="col-xs-3 required form-input-group" label=(t 'labels.visit') property="visit" content=patientVisitsForSelect optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" prompt=(t 'imaging.labels.addNewVisit') diff --git a/app/incident/route.js b/app/incident/route.js index 46813b34b0..be8f6906ad 100644 --- a/app/incident/route.js +++ b/app/incident/route.js @@ -10,6 +10,9 @@ export default AbstractModuleRoute.extend({ name: 'incidentCategoryList', findArgs: ['inc-category'] }], + allowSearch: false, + editTitle: t('incidents.titles.editIncident'), + newTitle: t('incidents.titles.newIncident'), moduleName: 'incident', newButtonText: t('incident.buttons.newIncident'), sectionTitle: t('incident.titles.incidents') diff --git a/app/inventory/adjust/template.hbs b/app/inventory/adjust/template.hbs index e974d82f23..73cfa1c299 100644 --- a/app/inventory/adjust/template.hbs +++ b/app/inventory/adjust/template.hbs @@ -17,7 +17,7 @@

{{model.quantity}}

- {{form.select class="col-sm-4" label=(t 'inventory.labels.adjustmentType') + {{form.select class="col-sm-4 form-input-group" label=(t 'inventory.labels.adjustmentType') property="transactionType" content=adjustmentTypes optionValuePath="type" optionLabelPath="name" }} diff --git a/app/inventory/rank-select/template.hbs b/app/inventory/rank-select/template.hbs index 84d5f2a14c..c1b9f87068 100644 --- a/app/inventory/rank-select/template.hbs +++ b/app/inventory/rank-select/template.hbs @@ -2,6 +2,6 @@ label=(t 'inventory.labels.rank') property=property content=options - class=class + class=(concat 'form-input-group ' class) prompt=prompt }} diff --git a/app/invoices/edit/controller.js b/app/invoices/edit/controller.js index 18a7f0fd7e..a13d244065 100644 --- a/app/invoices/edit/controller.js +++ b/app/invoices/edit/controller.js @@ -133,7 +133,7 @@ export default AbstractEditController.extend(NumberFormat, PatientSubmodule, Pub }, showDeleteItem(itemToDelete, deleteFrom) { - this.showDeleteModal(itemToDelete, EmberObject.create({ + this.send('showDeleteModal', itemToDelete, EmberObject.create({ confirmAction: 'deleteCharge', deleteFrom, title: 'Delete Charge' @@ -141,7 +141,7 @@ export default AbstractEditController.extend(NumberFormat, PatientSubmodule, Pub }, showDeleteLineItem(item) { - this.showDeleteModal(item, EmberObject.create({ + this.send('showDeleteModal', item, EmberObject.create({ confirmAction: 'deleteLineItem', title: 'Delete Line Item' })); diff --git a/app/invoices/edit/template.hbs b/app/invoices/edit/template.hbs index d5c1fd6161..543b0617f0 100644 --- a/app/invoices/edit/template.hbs +++ b/app/invoices/edit/template.hbs @@ -13,7 +13,7 @@ {{date-picker model=model property="billDate" label=(t 'labels.billDate') class="col-xs-2"}} {{#if model.isNew}} {{patient-typeahead model=model property="patientTypeAhead" label=(t 'labels.patient') content=patientList selection=selectedPatient class="col-xs-4 required invoice-patient"}} - {{form.select class="col-xs-4 required invoice-visit" label=(t 'labels.visit') + {{form.select class="col-xs-4 required form-input-group invoice-visit" label=(t 'labels.visit') property="visit" content=patientVisitsForSelect optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" selected=model.visit @@ -33,7 +33,7 @@ content=pricingProfiles optionValuePath="selectObject" optionLabelPath="selectObject.name" - class="col-xs-3" + class="col-xs-3 form-input-group" prompt=" " selected=model.paymentProfile }} @@ -74,28 +74,28 @@ {{if item.showDetails 'glyphicon-minus' 'glyphicon-plus'}}" {{action "toggleDetails" item bubbles=false }}> - {{input class="form-control" value=item.name }} + {{input class="form-control item-name" value=item.name }}
- + {{number-format item.total}}
- {{input class="form-control text-right" value=item.discount }} + {{input class="form-control text-right item-discount" value=item.discount }}
- {{input class="form-control text-right" value=item.nationalInsurance }} + {{input class="form-control text-right item-national-insurance" value=item.nationalInsurance }}
- {{input class="form-control text-right" value=item.privateInsurance }} + {{input class="form-control text-right item-private-insurance" value=item.privateInsurance }}
- {{number-format item.amountOwed}} + {{number-format item.amountOwed}} {{#if canAddCharge}}
- + {{number-format detail.amountOwed}} @@ -161,11 +161,11 @@ {{t 'labels.total'}} {{categoryGroup.category}} - {{number-format categoryGroup.total}} - {{number-format categoryGroup.discount}} - {{number-format categoryGroup.nationalInsurance}} - {{number-format categoryGroup.privateInsurance}} - {{number-format categoryGroup.amountOwed }} + {{number-format categoryGroup.total}} + {{number-format categoryGroup.discount}} + {{number-format categoryGroup.nationalInsurance}} + {{number-format categoryGroup.privateInsurance}} + {{number-format categoryGroup.amountOwed }} {{/each}} @@ -173,11 +173,11 @@ {{t 'labels.total'}} - {{number-format model.total}} - {{number-format model.discount}} - {{number-format model.nationalInsurance}} - {{number-format model.privateInsurance}} - {{number-format model.finalPatientResponsibility}} + {{number-format model.total}} + {{number-format model.discount}} + {{number-format model.nationalInsurance}} + {{number-format model.privateInsurance}} + {{number-format model.finalPatientResponsibility}} @@ -185,7 +185,7 @@ {{t 'billing.labels.paymentsDeposits'}} - -{{number-format model.paidTotal}} + -{{number-format model.paidTotal}} @@ -193,7 +193,7 @@ {{t 'labels.grandTotal'}} - {{number-format model.remainingBalance}} + {{number-format model.remainingBalance}} {{#if model.paymentProfile}} diff --git a/app/labs/edit/template.hbs b/app/labs/edit/template.hbs index 957364f33f..235b92f883 100644 --- a/app/labs/edit/template.hbs +++ b/app/labs/edit/template.hbs @@ -7,7 +7,7 @@ {{/if}} {{#if model.isNew}}
- {{form.select class="col-xs-3 required test-visit-type" label=(t 'labels.visit') + {{form.select class="col-xs-3 required form-input-group test-visit-type" label=(t 'labels.visit') property="visit" content=patientVisitsForSelect optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" prompt=(t 'labs.labels.addNewVisit') diff --git a/app/locales/cn/translations.js b/app/locales/cn/translations.js new file mode 100755 index 0000000000..7e6ad0e5c7 --- /dev/null +++ b/app/locales/cn/translations.js @@ -0,0 +1,1489 @@ +export default { + languageName: '简体中文', + admin: { + address: { + address1Label: '地址标签1', + address2Label: '地址标签2', + address3Label: '地址标签3', + address4Label: '地址标签4', + addressLabel: '地址', + editTitle: '地址选项', + include1Label: '包括标签1', + include2Label: '包括标签2', + include3Label: '包括标签3', + include4Label: '包括标签4', + messages: { addressSaved: '地址选项已成功储存' }, + newTitle: '地址选项', + titles: { optionsSaved: '选项已成功储存' } + }, + addressOptions: '地址选项', + customForms: { + buttons: { + addField: '新增栏位', + moveDown: '往上移', + moveUp: '往下移', + newForm: '+ 新表格', + preview: '预览' + }, + labels: { + alwaysInclude: '总是包括', + checkbox: '选项欄', + colSpan: '欲展开之列数目', + columns: '列', + customForm: '自订表格', + dischargeReportFormType: '出院报告', + expenseTo: '支付者', + formName: '表格名称', + formType: '表格种类', + header: '标题', + incidentFormType: '事件', + includeOtherOption: '包括其他选项', + labFormType: '试验', + label: '标签', + newForm: '新增表格', + opdReportFormType: '门诊病人报告', + operativePlanFormType: '手术计画与报告', + otherOptionLabel: '其他选项标签', + patientFormType: '病患', + property: '属性', + radio: '单选按钮', + select: '复选单', + socialworkFormType: '社区服务', + text: '文字', + textarea: '放大文字', + visitFormType: '探访' + }, + messages: { formSaved: '{{name}}表格已成功储存' }, + titles: { + checkboxValues: '选项欄资料', + customForms: '自订表格', + deleteForm: '删除自订表格', + dropDownValues: '复选单资料', + editCustomForm: '编辑自订表格', + fields: '栏位', + formSaved: '表格成功储存', + headerValues: '标题文字', + newCustomForm: '新增自订表格', + radioValues: '单选按钮资料' + } + }, + header: { + editTitle: '标题选项', + facilityName: '设施名称', + headerLabel: '标题', + headerLine1: '标题第1行', + headerLine2: '标题第2行', + headerLine3: '标题第3行', + logoURL: '商标网址', + messages: { headerSaved: '标题选项已成功储存' }, + newTitle: '标题选项', + titles: { optionsSaved: '选项已成功储存' } + }, + loadDb: '启动数据库', + loaddb: { + displayAlertMessage: '请选择要开启的档案', + displayAlertTitle: '选择开启档案', + editTitle: '启动数据库', + errorDisplayAlertMessage: '无法启动数据库。问题:{{error}}', + errorDisplayAlertTitle: '启动时发生错误', + progressMessage: '请等待数据库启动', + progressTitle: '正在启动数据库' + }, + lookup: { + aisleLocationList: '库存通道位置', + alertImportListMessage: '请选择要汇入的档案.', + alertImportListSaveMessage: '查找列表已成功汇入', + alertImportListSaveTitle: '名单成功汇入', + alertImportListTitle: '请选择要汇入的档案', + alertImportListUpdateMessage: '查找列表已成功储存', + alertImportListUpdateTitle: '名单已储存', + anesthesiaTypes: '麻醉种类', + anesthesiologists: '麻醉师', + billingCategories: '建筑类别', + clinicList: '诊所地点', + countryList: '国家', + cptCodeList: 'CPT 编码', + diagnosisList: '诊断', + edit: { template: { + addTitle: '新增数值', + editTitle: '编辑数值', + labelTitle: '数值', + updateButtonTextAdd: '增加', + updateButtonTextUpdate: '编辑' + } }, + expenseAccountList: '费用帐户', + imagingPricingTypes: '影像价目类别', + incidentDepartments: '事件部门', + inventoryTypes: '库存类型', + labPricingTypes: '试验定价类型', + pageTitle: '查找列表', + patientStatusList: '病患状态表', + physicianList: '医师', + procedureList: '程序', + procedureLocations: '程序地点', + procedurePricingTypes: '程序定价类型', + radiologists: '放射科医生', + titles: { deleteLookupValue: '删除数值' }, + unitTypes: '单位类型', + vendorList: '供应商', + visitLocationList: '探访地点', + visitTypes: '探访类型', + wardPricingTypes: '病房定价类型', + warehouseList: '库存地点' + }, + lookupLists: '查找列表', + roles: { + capability: { + addAllergy: '新增过敏', + addAppointment: '新增预约', + addBillingDiagnosis: '增加计费诊断', + addCharge: '增加收费', + addDiagnosis: '增加诊断', + addImaging: '增加影像', + addIncident: '增加事件', + addIncidentCategory: '增加事件种类', + addInventoryItem: '增加库存项目', + addInventoryPurchase: '增加库存购买', + addInventoryRequest: '增加库存请求', + addInvoice: '增加单据', + addLab: '增加测试', + addMedication: '增加药物', + addNote: '增加笔记', + addOperationReport: '增加程序报告', + addOperativePlan: '增加程序类型', + addPatient: '增加病患', + addPayment: '新增付款', + addPhoto: '增加照片', + addPricing: '新增价錢', + addPricingProfile: '新增定价概况', + addProcedure: '新增程序', + addSocialwork: '新增社区工作', + addVisit: '新增探访', + addVitals: '新增命脉资料', + adjustInventoryLocation: '调整库存位置', + admin: '行政', + admitPatient: '接纳病患', + appointments: '预约', + billing: '计费', + cashier: '出纳员', + completeImaging: '完成影像', + completeLab: '完成测试', + defineUserRoles: '定义用戶角色', + deleteAppointment: '删除预约', + deleteDiagnosis: '删除诊断', + deleteImaging: '删除影像', + deleteIncident: '删除事件', + deleteIncidentCategory: '删除事件类型', + deleteInventoryItem: '删除库存项目', + deleteInvoice: '删除单据', + deleteLab: '删除测试', + deleteMedication: '删除药物', + deleteNote: '删除笔记', + deletePatient: '删除病患', + deletePhoto: '删除照片', + deletePricing: '删除定价', + deletePricingProfile: '删除定价概况', + deleteProcedure: '删除程序', + deleteSocialwork: '删除社会工作', + deleteVisit: '删除拜访', + deleteVitals: '删除命脉资料', + dischargePatient: '让病患出院', + editInvoice: '编辑单据', + fulfillInventory: '滿足库存', + fulfillMedication: '滿足药物', + generateIncidentReport: '生成事件报告', + imaging: '影像', + incident: '事件', + inventory: '库存', + invoices: '单据', + labs: '测试', + listPaidInvoices: '显示付清单据', + loadDb: '载入数据庫', + manageIncidents: '管理事件', + medication: '药物', + overrideInvoice: '覆盖单据', + patientReports: '病患报告', + patients: '病患', + pricing: '价錢', + updateConfig: '更新设置', + visits: '探访' + }, + messages: { roleSaved: '{{roleName}}任务已成功储存' }, + titles: { roleSaved: '任务已成功储存' } + }, + textReplacements: { + createNew: '新增简码', + existingRepl: '現有简码', + replDesc: '输入文字時,这些快捷键让您短的字句变成长的语句.', + pageTitle: '简码', + toReplace: '要取代之文字', + replaceWith: '用 ... 来取代', + performExpand: "按 Enter 来用 '{{to}}' 取代 #{{from}}", + possibleExpansions: '{{possible}} 可能的替代品', + noMatches: "'{{term}}' 沒有相對应的替代品" + }, + userRoles: '用戶角色', + users: '用戶', + visitForms: { + labels: { + followup: '跟进', + form: '表格', + initial: '初始', + visitType: '探访类型' + }, + titles: { visitForms: '探访表格' } + }, + workflow: { + admissionDepositLabel: '需要入院押金', + clinicPrepaymentLabel: '需要诊所付款', + editTitle: '流程选项', + followupPrepaymentLabel: '需要跟进付款', + messages: { optionsSaved: '流程选项已成功储存' }, + newTitle: '流程选项', + outpatientImagingLabel: '需要门诊病人影像付款', + outpatientLabLabel: '需要门诊病人测试付款', + outpatientMedicationLabel: '需要门诊病人药物付款', + titles: { optionsSaved: '选项已储存' }, + workflowLabel: '流程' + } + }, + alerts: { + errorExclamation: '发生错误!!!', + pleaseWait: '请稍候', + reportError: '生成报告時发生错误', + warningExclamation: '注意!!!' + }, + allergies: { + buttons: { addAllergy: '新增过敏' }, + labels: { + allergyName: '名称', + patientAllergy: '患者过敏' + }, + titles: { + addAllergy: '新增过敏', + editAllergy: '编辑过敏' + } + }, + application: { + messages: { sessionExpired: '请重新登入' }, + titles: { sessionExpired: '会话过期' } + }, + appointments: { + buttons: { + newButton: '+ 新增预约', + scheduleSurgery: '+ 预约手术' + }, + calendarTitle: '预约行事历', + currentScreenTitle: '预约列表', + editTitle: '更改预约', + labels: { + noLocation: '无地点', + selectedStartingDate: '显示在 ... 之后的预约' + }, + messages: { + appointmentSaved: '{{patient}}的预约已成功储存', + endTimeLaterThanStart: '请选择一个开始时间之后的结束时间' + }, + missed: '错过的预约', + newTitle: '新增预约', + searchTitle: '搜寻预约', + sectionTitle: '预约', + thisWeek: '本周预约', + titles: { + appointmentSaved: '预约已储存', + editSurgicalAppointment: '更改手术预约', + newSurgicalAppointment: '新增手术预约', + theaterSchedule: '手术室时间表' + }, + todayTitle: '本日预约' + }, + billing: { + alerts: { + noInvoiceFound: '找无单据', + noPricingItems: '找无定价项目', + noPricingProfiles: '找无定价概况' + }, + buttons: { + addOverride: '新增覆盖', + createInvoice: '建立单据?' + }, + labels: { + actualCharges: '实际收费', + discountAmount: '折扣金额', + discountPercentage: '折扣百分比', + externalInvoiceNumber: '外部收据 #', + hmoCom: 'HMO/COM', + insurance: '国家保险', + paymentProfile: '付款资料', + paymentsDeposits: '付款/存款', + pricingPanelOverrides: '定价资料覆盖', + pricingProfile: '定价资料', + setFee: '设定费用' + }, + messages: { + flatFeeMsg: '患者负责 {{currency}}{{setFee}} 的基本费用.', + flatDiscountMsg: '患者负责的基本费用已包含 {{currency}}{{discountAmount}} 的折扣.' + } + }, + buttons: { + add: '新增', + addItem: '新增项目', + addLineItem: '新增订单项目', + addValue: '新增数值', + addVisit: '新增探访', + allRequests: '全部要求', + barcode: '条码', + cancel: '取消', + clear: '清除', + close: '关', + complete: '完成', + 'delete': '删除', + dispense: '分发', + edit: '编辑', + filter: '筛选', + fulfill: '履行', + 'import': '输入', + loadFile: '载入档案', + newItem: '+ 新增项目', + newNote: '新增笔记', + newRequest: '新增要求', + newRequestPlus: '+ 新增要求', + newUser: '新增使用者', + ok: 'Ok', + print: '列印', + remove: '移除', + returnButton: '返回', + review: '检阅', + search: '搜寻', + showAll: '显示全部', + showFewer: '显示部分', + update: '更新' + }, + components: { + chargesByTypeTab: { charges: '收费' }, + customFormManager: { buttons: { addForm: '新增表格' } }, + dateTimePicker: { + amHour: '上午{{hour}}', + midnight: '午夜', + noon: '中午', + pmHour: '下午{{hour}}' + }, + imageUpload: { messages: { selectValidImageFile: '请选择一个有效的照片' } }, + operativeProcedures: { + buttons: { addProcedure: '新增程序' }, + labels: { procedure: '程序' }, + titles: { procedures: '程序' } + }, + patientOrders: { + buttons: { + newImaging: '新增影像', + newLab: '新增测试', + newMedication: '新增药物' + }, + labels: { + imagingOrderType: '影像', + labOrderType: '测试', + medicationOrderType: '药物', + orderType: '订購类型' + } + }, + priceList: { charges: '{{pricingType}} 收费' }, + quantityCalc: { result: '{{targetUnit}} 总和:{{calculated}}' }, + quantityConv: { + conversion: '一个 {{name}} 含有?', + unit: '单位' + }, + sortableColumn: { labels: { selectAll: '(全选)' } }, + takePhoto: { + camera: '相机', + how: '想如何加入相片', + labels: { + takeAPicture: '拍張照片', + uploadAFile: '上传档案' + }, + photo: '照片', + preview: '预览', + takePhoto: '拍照片', + uploadFile: '上传档案' + }, + upcomingAppointments: { + labels: { + date: '日期', + location: '地点', + type: '种类', + 'with': '与' + }, + titles: { upcomingAppointments: '将来预约' } + } + }, + customForms: { + buttons: { addForm: '加入表格' }, + labels: { formToAdd: '要加入之表格' }, + titles: { addCustomForm: '加入自订表格' } + }, + dashboard: { + needs_user_setup: '我们建议您建立使用者帐户', + standalone_welcome: '

感謝您下载 HospitalRun.

您正在使用 HospitalRun 的独立模式. 这个模式支援多个使用者在一台电脑. 这對于下列是理想的:

  • 评估 HospitalRun 以开发伺服器.
  • 使用平台来支援仅需单一设備(电脑)的诊所.

如果您\'考虑架构一个数台设備(电脑)的HospitalRun, 我们 正在试着开发功能 让您从这单一设置升级到一般的雲端/伺服器设置.

', + title: '欢迎来到 HospitalRun!' + }, + dates: { + 'long': '{{years}} 年 {{months}} 月 {{days}} 日', + longOmitDays: '{{years}} 年 {{months}} 月', + longOmitDaysPlural: '{{years}} 年 {{months}} 月', + longOmitDaysYears: '{{months}} 月', + longOmitYears: '{{months}} 月 {{days}} 日', + longPlural: '{{years}} 年 {{months}} 月 {{days}} 日', + 'short': '{{years}}年 {{months}}月 {{days}}日', + shortOmitYears: '{{months}}月 {{days}}日' + }, + diagnosis: { + labels: { + activeDiagnosis: '現行诊断', + date: '日期', + diagnosis: '诊断', + secondaryDiagnosis: '次要诊断' + }, + titles: { + addDiagnosis: '新增诊断', + editDiagnosis: '编辑诊断' + } + }, + errors: { + accepted: '必须要接受', + blank: '不能空白', + confirmation: '不符合 {{attribute}}', + empty: '不能空白', + equalTo: '必须等于 {{count}}', + even: '必须是偶数', + exclusion: '已保存', + greaterThan: '必须大于 {{count}}', + greaterThanOrEqualTo: '必须大于或等于 {{count}}', + inclusion: '不在名单內', + invalid: '不符合要求', + invalidNumber: '不是有效数字', + lessThan: '必须小于 {{count}}', + lessThanOrEqualTo: '必须小于或等于 {{count}}', + notANumber: '不是一个数字', + notAnInteger: '必须是一个整数', + odd: '必须是奇数', + otherThan: '不能等于 {{count}}', + present: '必须是空白', + result: '请先输入一个结果', + tooLong: '字数太长 (不能超过 {{count}} 字数)', + tooShort: '字数太短 (不能低于 {{count}} 字数)', + wrongLength: '字数不對 (必须等于 {{count}} 字数)' + }, + headings: { chargedItems: '收费项目' }, + imaging: { + alerts: { + completedMessage: '影像要求已完成', + completedTitle: '影像要求完成', + savedMessage: '影像要求已储存', + savedTitle: '影像要求已储存' + }, + buttons: { newButton: '+ 新增影像' }, + labels: { + addNewVisit: '--新增探访--', + radiologist: '放射科医师', + resultNotes: '结果笔记', + requestedNotes: '要求的笔记', + completedBy: '完成者' + }, + messages: { noCompleted: '找不到已完成的项目' }, + pageTitle: '影像要求', + sectionTitle: '影像', + titles: { + completedImaging: '已完成影像', + editTitle: '编辑影像要求', + newTitle: '新增影像要求' + } + }, + incident: { + buttons: { + add: '新增', + addForm: '+ 新增表格', + addItem: '新增表格', + cancel: '取消', + 'delete': '删除', + download: '下载', + edit: '编辑', + 'export': '输出报告', + generateRep: '生成报告', + newAttachment: '+ 新增附件', + newCategory: '+ 新增类型', + newIncident: '+ 新增事件', + newNote: '+ 新增笔记' + }, + labels: { + actions: '作用', + addedBy: '由...添加', + category: '类型', + categoryItem: '类型表格', + date: '日期', + dateRecorded: '纪录日期', + department: '部门', + description: '事件描述', + endDate: '结束日期', + givenBy: '由...提供', + howToAddAttachment: '您想如何增加附件?', + incidentDate: '事件日期', + incidentId: '事件 ID', + item: '项目', + lastUpdated: '上一次更新', + note: '笔记', + patientId: '患者 Id', + patientImpacted: '影響患者', + reportType: '报告种类', + reportedBy: '由...报告', + reportedDate: '报告日期', + reportedTo: '事件已报告给 (Full Name)', + sentinelEvent: '突发事件', + startDate: '开始日期', + status: '状态', + statusActive: '現行', + statusClosed: '完成', + statusFollowup: '跟进', + statusReported: '已报告', + title: '标题', + total: '总和', + updatedBy: '由...更新' + }, + messages: { + attachmentFileRequired: '储存附件前请先上传档案或拍張照片', + createNew: '新增事件?', + createNewIncidentCategory: '新增事件类型?', + fillIn: '填入上述选项以计算分数', + incidentCategorySaved: '{{name}} 类型已成功储存.', + noClosedIncidents: '找不到已完成的事件.', + noIncidentCategoriesFound: '找不到事件类型.', + noIncidents: '找不到事件.', + saved: '事件报告已成功储存.', + selectExistingPatient: '请选择一个現有的患者或不要填写此字段.' + }, + titles: { + addAttachment: '加入附件', + addCategoryItem: '加入类型项目', + addNote: '加入笔记', + attachments: '附件', + closed: '已完成事件', + current: '當前', + deleteAttachment: '删除附件', + deleteIncident: '删除事件', + deleteIncidentCategory: '删除事件类型', + deleteItem: '删除项目', + deleteNote: '删除笔记', + editAttachment: '编辑附件', + editIncident: '编辑事件', + editIncidentCategory: '编辑事件类型', + editNote: '编辑笔记', + general: '一般信息', + history: '历史', + incidentCategories: '事件类型', + incidentCategoryItem: '事件类型项目', + incidentCategoryName: '事件类型名称', + incidentCategorySaved: '事件类型已储存', + incidentSaved: '事件已储存', + incidents: '事件', + incidentsByCategory: '按类型显示事件', + incidentsByDepartment: '按部门显示事件', + newIncident: '新增事件', + newIncidentCategory: '新增事件类型', + notes: '笔记', + reports: '报告' + } + }, + inventory: { + edit: { + cost: '单位价:', + delivered: '传递给:', + location: '调整地点:', + prescription: '处方给:', + pulled: '来源:', + quantity: '完成数量:', + reason: '原因:', + returned: '患者给回:', + transferredFrom: '从...转来:', + transferredTo: '转去:' + }, + labels: { + action: '行动', + add: '加入', + addAdjustmentType: '加入', + adjust: '调整', + adjustmentDate: '调整日期', + adjustmentFor: '为...调整', + adjustmentType: '调整种类', + aisle: '通道', + aisleLocation: '通道地点', + allInventory: '全部清单', + allItems: '全部项目', + availableQuantity: '{{quantity}} 可用', + billTo: '记帐到', + consumePurchases: '消费购买', + consumptionRate: '消费率', + cost: '费用', + costPerUnit: '单位价', + crossReference: '交叉引用', + currentQuantity: '現前数量', + dateCompleted: '完成日期', + dateEffective: '生效日期', + dateEnd: '结束日期', + dateReceived: '收到日期', + dateStart: '开始日期', + dateTransferred: '转移日期', + daysLeft: '剩余天数', + deleteItem: '删除项目', + deliveryAisle: '发送通道', + deliveryLocation: '发送地点', + details: '细节', + distributionUnit: '分配单位', + editItem: '编辑项目', + expense: '记帐到', + expirationDate: '截止日期', + fulfillRequest: '实现需求', + fulfillRequestNow: '現在实现需求', + gift: '礼物', + giftInKindNo: 'N', + giftInKindYes: 'Y', + giftUsage: '礼物用途', + inventoryConsumed: '库存消耗', + inventoryItem: '库存项目', + inventoryObsolence: '库存报废', + invoiceItems: '单据项目', + invoiceLineItem: '单据单項', + invoiceNumber: '单据号码', + item: '项目', + itemNumber: '项目号码', + items: '项目', + location: '地点', + locations: '地点', + markAsConsumed: '标记为已消耗', + name: '名称', + newItem: '新增项目', + originalQuantity: '原本数量', + print: '列印', + printBarcode: '列印条码', + printer: '列印机', + pullFrom: '从...拉入', + purchaseCost: '购买价格', + purchaseInfo: '购买资料', + purchases: '购买', + quantity: '数目 ({{unit}})', + quantityAvailable: '可提供之数目', + quantityOnHand: '現有数目', + quantityRequested: '要求数目', + rank: '级別', + reason: '原因', + remove: '移除', + removeAdjustmentType: '移除', + reorderPoint: '订貨點', + requestedItems: '要求项目', + returnAdjustmentType: '退回', + returnToVendorAdjustmentType: '退回给供应商', + salePricePerUnit: '銷售单位价', + save: '储存', + serialNumber: '序列号', + total: '总和', + totalCost: '总价码', + totalReceived: '总收入: {{total}}', + transaction: '交易', + transactions: '交易', + transfer: '调动', + transferFrom: '从...调动', + transferTo: '调动到目的地', + transferToAisle: '调动到通道地点', + unit: '单位', + unitCost: '单位价', + vendor: '供应商', + vendorItemNumber: '供应商项目編号', + writeOffAdjustmentType: '注销', + xref: '外部参照' + }, + messages: { + adjust: '请调整适当地区的数目以解释误差 {{difference}}.', + createRequest: '加入新需求?', + itemNotFound: '找不到库存项目 {{item}}.
如果要加入新的库存项目, 请填入以下资料.
或选择取消以返回.', + loading: '载入交易...', + noItems: '找无项目.', + noRequests: '找无要求.', + purchaseSaved: '库存购买已成功储存.', + quantity: '总数目 ({{quantity}}) 不吻合地点的总数目 ({{locationQuantity}}).', + removeItem: '确定要从库存中移除此项目?', + removeItemRequest: '确定要从要求中移除此项目?', + requestFulfilled: '库存要求已完成.', + requestUpdated: '库存要求已更新.', + warning: '加入前请填入必要的栏位 (有 * 标註) 並更正错误.' + }, + reports: { + adjustment: '详细的调整', + daysSupply: '库存能支援天数', + expenseDetail: '详细的费用', + expenseSum: '费用概要', + expiration: '截止日期', + 'export': '输出报告', + fields: '要包括之栏位', + finance: '财政概要', + generate: '生成报告', + invLocation: '按地点显示库存', + invValuation: '库存计价', + purchaseDetail: '购买详细资料', + purchaseSum: '购买概要', + reportType: '报告种类', + rows: { + adjustments: '调整', + adjustmentsTotal: '总调整', + balanceBegin: '初期结余', + balanceEnd: '最終结余', + category: '类别', + consumed: '已消耗', + consumedGik: '已消耗GiK', + consumedGikTotal: '已消耗GiK总和', + consumedPuchases: '已消耗购买', + consumedPurchasesTotal: '已消耗购买总和', + consumedTotal: '已消耗总和', + errInFinSum: '生成财政概况报告時发生错误: ', + errInFindPur: '依购买搜寻库存项目時发生错误: ', + errInFindReq: '依要求搜寻库存项目時发生错误: ', + expensesFor: '...的费用: ', + noAccount: '(沒有帐户)', + subtotal: '小计: ', + subtotalFor: '小计:{{category}} - {{account}}: ', + total: '总和: ', + totalFor: '{{var}}总和: ', + totalPurchases: '购买总和', + transfer1: '{{quantity}}来自{{location}}', + trasnfer2: '从: {{source}} 到: {{target}}' + }, + stockTransferDetail: '库存传递详细资料', + stockTransferSum: '库存传递概要', + stockUsageDetail: '详细库存使用资料', + stockUsageSum: '库存使用概要', + titleDateRange: '{{name}} 报告 {{startDate}} - {{endDate}}', + titleSingleDate: '{{name}} 报告 {{date}}' + }, + titles: { + addPurchase: '加入购买', + addRequest: '新增需求', + adjustment: '调整', + editPurchase: '编辑购买', + editRequest: '编辑需求', + inventoryItem: '新增库存项目', + inventoryReport: '库存报告', + purchaseSaved: '库存购买已储存', + quickAddTitle: '新增库存项目', + removeItem: '移除项目', + requestFulfilled: '需求已滿足', + requestUpdated: '需求已更新', + transfer: '搬迁项目', + warning: '警告!!!!!' + } + }, + labels: { + action: '行动', + actions: '行动', + addNewOutpatientVisit: '--加入门诊病人探访--', + address: '地址', + age: '年龄', + allDay: '整天', + allItems: '所有项目', + amount: '数目', + anesthesia: '麻醉', + assisting: '助理', + balanceDue: '余額到期', + billDate: '收费日期', + billTo: '跟...收费', + category: '类别', + completed: '已完成', + country: '国家', + cptcode: 'CPT 代码', + creditTo: '归于', + currencySymbol: '$', + date: '日期', + dateCompleted: '完成日期', + dateOfBirth: '出生年月日', + dateOfBirthShort: '生日', + datePaid: '付款日期', + dateRequested: '要求的日期', + 'delete': '删除', + deleteRequest: '删除要求', + deleteUser: '删除使用者', + department: '部门', + description: '描述', + discount: '折扣', + displayName: '显示名称', + docRead: '已讀文件', + docWritten: '已填文件', + edit: '编辑', + editUser: '编辑使用者', + email: '电子邮件', + endDate: '结束日期', + endTime: '结束时间', + excess: '过量', + expenseTo: '由...付费', + fileLoadSuccessful: '成功载入档案', + fileName: '档案名称', + fileToLoad: '档案载入', + from: '来自', + fulfill: '实现', + fulfillRequest: '实现需求', + fulfillRequestNow: '現在实现需求', + fulfilled: '已实现', + grandTotal: '累计', + id: 'Id', + imageOrders: '图像订制', + imagingType: '影像种类', + importFile: '载入档案', + invoiceId: '单据ID', + labOrders: '指定试验', + lineItems: '订单项目', + loading: '正在载入', + location: '地点', + lookupType: '查找种类', + medication: '药物', + name: '名称', + newUser: '新增使用者', + newItem: '+ 新增项目', + note: '笔记', + notes: '笔记', + number: '数字', + on: '上', + password: '密码', + patient: '患者', + payments: '付款', + physician: '医师', + prescriber: '处方师', + prescription: '处方', + prescriptionDate: '处方日期', + price: '价格', + print: '列印', + procedures: '程序', + provider: '提供者', + pullFrom: '从...拉入', + quantity: '数目', + remarks: '备注', + requestedBy: '要求者', + requestedOn: '要求的日期', + requests: '要求', + result: '结果', + results: '结果', + role: '角色(任务)', + search: '搜寻', + sex: '性別', + startDate: '开始日期', + startTime: '开始时间', + status: '状态', + takenBy: '由...采取', + to: '给', + total: '总和', + type: '种类', + userCanAddNewValue: '使用者可加入数值', + username: '用戶名', + value: '数值', + view: '检视', + visit: '探访', + 'with': '与' + }, + labs: { + alerts: { + requestCompletedMessage: '测试要求已完成.', + requestCompletedTitle: '测试要求已完成', + requestSavedMessage: '测试要求已储存.', + requestSavedTitle: '测试要求已储存' + }, + buttons: { newButton: '+ 新增测试' }, + completedTitle: '已完成的测试', + deleteTitle: '删除要求', + editTitle: '编辑测试要求', + labels: { + addNewVisit: '--加入新探访--', + labType: '测试种类' + }, + messages: { + createNewRecord: '加入新纪录?', + noCompleted: '找无已完成的项目.', + noItemsFound: '找无测试.' + }, + newTitle: '新增测试要求', + requestsTitle: '测试要求', + sectionTitle: '测试' + }, + loading: { + messages: { + '0': '飞行最快的蝴蝶可以达到每小時12英里. 有些飞蛾能达到每小時25英里的飞行速度!', + '1': '貓头鹰是唯一能识別蓝色的鸟类.', + '2': '貓可以发出超过一百种声音,狗只能发出十种.', + '3': '人类說话時运用了72个不同的肌肉.', + '4': '非洲上的语言超过一千种.', + '5': 'Erythrophobe 这个詞形容一个容易脸红的人.', + '6': '世上最常见的恐惧症是怕痛的恐惧.', + '7': '當您站立不动的時候,您的身体运用了300个肌肉来平衡自己.', + '8': '特定青蛙能在被结冻又解冻后继续生存.', + '9': '人体的眼睛从出生就保持同样的大小, 但鼻子和耳朵會一直持续成长.', + '10': '舌头是您体內唯一仅附在最后端的肌肉.', + '11': '骆驼有三个眼皮来防护风吹砂.' + }, + progressBar: { progress: '{{progressBarValue}}% 完成' } + }, + login: { + labels: { + password: '密码', + signIn: '登入', + username: '用戶名' + }, + messages: { + error: '用戶名或密码不正確.', + offlineError: '离线時无法登入. 请连上网路后再试.', + signIn: '请登入' + } + }, + medication: { + alerts: { + fulfilledTitle: '药物要求完成', + returnedMessage: '药物已标记为退還.', + returnedTitle: '退還药物', + savedMessage: '药物纪录已储存.', + savedTitle: '药物要求已储存' + }, + buttons: { + dispenseMedication: '发放配药', + newButton: '+ 新增要求', + returnMedication: '退還药物' + }, + labels: { + adjustmentDate: '调整日期', + creditToAccount: '归于...帐户', + quantityDispensed: '分配数量', + quantityDistributed: '分发数量', + quantityRequested: '要求数量', + quantityToReturn: '要還的数量', + refills: '充值', + returnAisle: '退還通道', + returnLocation: '退還地点', + returnReason: '退還原因/备注' + }, + messages: { createNew: '新增药物要求?' }, + pageTitle: '药物要求', + returnMedication: '退還药物', + sectionTitle: '药物', + titles: { + completedMedication: '完成药物', + editMedicationRequest: '编辑药物要求', + newMedicationRequest: '新增药物要求' + } + }, + messages: { + createNewRecord: '建立新纪录?', + createNewUser: '建立新使用者?', + 'delete': '确定要删除 {{name}}?', + delete_plural: '确定要删除这些 {{name}}?', + delete_singular: '确定要删除 {{name}}?', + forAuthorizedPersons: '这报告只提供给特定授权人.', + newPatientHasToBeCreated: '必须建立一个新的患者...请稍候..', + noHistoryAvailable: '沒有历史.', + noItemsFound: '找无项目.', + noNotesAvailable: '沒有其他的其他的临床报告可提供给此次探访.', + noUsersFound: '找无使用者.', + onBehalfOf: '代表', + reportError: '生成报告時发生错误. 请通报错误给系統管理员.', + requiredFieldsCorrectErrors: '加入前请填入必要的栏位 (有 * 标註) 並更正错误.', + saveActionException: '尝试储存時发生错误: {{message}}', + sorry: '抱歉,发生错误...', + userHasBeenSaved: '使用者已储存.', + userSaved: '使用者已储存' + }, + models: { + appointment: { + labels: { + allDay: '整天', + appointmentDate: '日期', + appointmentType: '种类', + endDate: '结束日期', + location: '地点', + notes: '笔记', + patient: '患者', + provider: '与', + startDate: '开始日期', + status: '状态', + type: '种类' + }, + names: { + plural: '预约', + singular: '预约' + } + }, + attachment: { names: { + plural: '附件', + singular: '附件' + } }, + form: { names: { + plural: '表格', + singular: '表格' + } }, + imaging: { + names: '影像', + request: { + plural: '影像要求', + singular: '影像要求' + } + }, + incident: { names: { + plural: '事件', + singular: '事件' + } }, + item: { names: { + plural: '项目', + singular: '项目' + } }, + lab: { + names: { + plural: '测试', + singular: '测试' + }, + request: { + plural: '测试要求', + singular: '测试要求' + } + }, + medication: { + names: { + plural: '药物', + singular: '药物' + }, + request: { + plural: '药物要求', + singular: '药物要求' + } + }, + note: { names: { + plural: '笔记', + singular: '笔记' + } }, + patient: { + labels: { name: '名称' }, + names: { singular: '患者' } + }, + procedure: { names: { + plural: '程序', + singular: '程序' + } }, + user: { names: { + plural: '使用者', + singular: '使用者' + } }, + visit: { names: { + plural: '探访', + singular: '探访' + } }, + vital: { names: { + plural: '命脉资料', + singular: '命脉资料' + } } + }, + navigation: { + about: '关于HospitalRun', + actions: { + login: '登入', + logout: '登出', + selectLanguage: '选择语言' + }, + administration: '行政', + billing: '计费', + imaging: '影像', + incident: '事件', + inventory: '库存', + labs: '测试', + medication: '药物', + messages: { + logoutFailed: '現在无法登出. 离线時无法登出.' + }, + patients: '患者', + scheduling: '调度', + subnav: { + actions: '动作', + addAppointment: '新增预约', + addressFields: '地址栏位', + admittedPatients: '收入患者', + appointmentSearch: '搜寻预约', + appointmentsCalendar: '预约行事曆', + appointmentsThisWeek: '本周预约', + cashier: '收銀员', + completed: '已完成', + currentIncidents: '現行事件', + customForms: '自订表格', + dispense: '配药', + history: '历史', + incidentCategories: '事件类别', + inventoryReceived: '收到的库存', + inventoryReceivedPlus: '+ 收到的库存', + invoices: '清单', + items: '项目', + loadDB: '启动数据库', + lookupLists: '查找列表', + newIncident: '新增事件', + newInvoice: '新增清单', + newPatient: '新增患者', + newRequest: '新增要求', + newUser: '新增使用者', + outpatient: '门诊病人', + patientListing: '患者名单', + priceProfiles: '价格概况', + prices: '价格', + printHeader: '列印标题', + reports: '报告', + requests: '要求', + returnMedication: '退還药物', + scheduleSurgery: '排定手术', + textReplacements: '短代码', + theaterSchedule: '手术室时间表', + "today'sAppointments": '本日预约', + userRoles: '使用者角色(任务)', + users: '使用者', + workflow: '工作流程' + }, + titles: { + logoutFailed: '登出失敗' + } + }, + operationReport: { + labels: { + additionalNotes: '其他备注', + assistant: '助理', + caseComplexity: '案件复杂度', + operationDescription: '程序描述', + preOpPrimaryDiagnosis: '程序前主要诊断', + preOpSecondaryDiagnosis: '程序前次要诊断', + surgeon: '手术师', + surgeryDate: '手术日期' + }, + messages: { reportSaved: '程序报告已成功储存.' }, + titles: { + editTitle: '编辑程序报告', + newTitle: '新增程序报告', + reportSaved: '报告已储存' + } + }, + operativePlan: { + buttons: { completePlan: '完成计划' }, + labels: { + additionalNotes: '其他备注', + admissionInstructions: '入院后指导', + caseComplexity: '案件复杂度', + completedStatus: '已完成', + droppedStatus: '被取消', + operationDescription: '程序描述', + plannedStatus: '已计划', + status: '状态', + surgeon: '手术师' + }, + messages: { + planCompleted: '程序计划已完成. 您将被导向程序报告.', + planSaved: '程序计划已储存.' + }, + titles: { + editTitle: '编辑程序计划', + newTitle: '新增程序计划', + planCompleted: '计划已完成', + planSaved: '计划已储存' + } + }, + patients: { + buttons: { + addContact: '新增联络人', + addExpense: '新增费用', + addFamilyMember: '新增家庭成员', + addOperativePlan: '新增程序计划', + backToPatients: '回到患者名单', + download: '下载', + editOperativePlan: '現有程序计划', + newAppointment: '新增预约', + newImaging: '新增影像', + newLab: '新增测试', + newMedication: '新增药物', + newPatient: '+ 新增患者', + newPhoto: '新增照片', + newVisit: '新增探访', + patientCheckIn: '患者登记', + scheduleSurgery: '安排手术时间' + }, + labels: { + admissionDate: '入院日期', + admit: '收入患者', + bloodType: '血型', + caption: '說明', + civilStatus: '公民身份', + clinic: '诊所地点', + contacts: '联络人', + cost: '费用', + dateOfBirth: '出生年月日', + dateProcessed: '处理日期', + dischargeDate: '出院日期', + dob: '生日', + education: '學歷', + email: '电子邮件', + externalPatientId: '外部患者 Id', + firstName: '名', + income: '收入', + insurance: '保险', + lastName: '姓', + middleName: '中间名', + monthlyCost: '月费', + occupation: '职业', + operativePlan: '程序计划', + parent: '家长/监护人', + patientDays: '患者天数', + patientType: '患者类型', + patientTypeCharity: '慈善机构', + patientTypePrivate: '私人', + phone: '电话', + placeOfBirth: '出生地点', + primaryDiagnosis: '主要诊断', + referredBy: '由...推荐', + referredDate: '推荐日期', + relationship: '与患者的关係', + relationships: '关係', + religion: '宗教', + secondaryDiagnosis: '次要诊断', + sex: '性別', + sexNotEntered: '性別空白', + sources: '来源', + status: '患者状态', + totalMontlyExpense: '总共月费' + }, + messages: { + areYouSureDelete: '确定要删除 {{object}}?', + createNewPatient: '建立新的患者报告?', + deletingPatient: '正在删除患者与其所拥有的资料', + noPatientsFound: '找无患者.', + notFoundQuickAdd: '找不到患者 {{patientFullName}}. 若您想建立新患者, 请填入以下资料. 或选择取消以返回.', + photoFileRequired: '储存照片前请先上传档案或拍張照片.', + savedPatient: '患者的 {{displayName}} 资料已成功储存.' + }, + navigation: { + appointments: '预约', + general: '取消', + history: '历史', + imaging: '影像', + labs: '测试', + medication: '药物', + photos: '照片', + socialWork: '社区工作', + visits: '探访' + }, + notes: { + newNote: '为...新增备注', + onBehalfOfCopy: '代表', + onBehalfOfLabel: '代表', + pleaseSelectAVisit: '请选择一个探访', + updateNote: '从...更新资料' + }, + titles: { + addContact: '新增联络人', + addPhoto: '新增照片', + additionalContacts: '其他联络人', + admissionsDetail: '入院细节', + admissionsSummary: '入院概要', + admittedPatients: '入院患者', + 'delete': '删除患者', + deleteContact: '删除联络人', + deleteExpense: '删除费用', + deleteFamilyMember: '删除家庭成员', + deletePatientRecord: '删除患者纪录', + deletePhoto: '删除照片', + diagnosticTesting: '诊断测试', + dischargesDetail: '出院细节', + dischargesSummary: '出院概要', + edit: '编辑患者', + editPhoto: '编辑照片', + expenses: '费用', + familyInfo: '家庭资料', + familyInformation: '家庭资料', + 'new': '新增患者', + outpatientsForDate: '{{visitDate}} 的门诊病人', + patient: '患者报告', + patientListing: '患者名单', + patientReport: '患者报告', + patientStatus: '患者状态', + proceduresDetail: '程序细节', + proceduresSummary: '程序概要', + savedPatient: '患者已储存', + socialWork: '费用', + todaysOutpatients: '擁本日门诊病人', + totalPatientDays: '总和患者天数', + totalPatientDaysDetailed: '总和患者天数(细节)', + visit: '探访' + } + }, + pricing: { + labels: { + discountAmount: '折扣金额', + discountPercentage: '折扣百分比', + setFee: '设定费用' + } + }, + print: { invoice: { + labels: { + billedBy: '由...收费:', + billedDate: '收费日期:', + dateAdmitted: '入院:', + dateDischarged: '出院:', + dischargeNotes: '出院备注:', + patientAddress: '地址:', + patientAge: '年龄:', + patientId: '患者 #:', + patientName: '患者姓名:', + remarks: '备注:', + spacer: '__________________________________________' + }, + messages: { whereConducted: '接产中扣了...' }, + titles: { + billingStatement: '帐单', + patientMember: '患者成员', + patients: '患者', + relContact: '关係/联络电话' + } + } }, + procedures: { + buttons: { addMedication: '新增药物' }, + labels: { medicationUsed: '使用之药物' }, + messages: { saved: '程序纪录已储存.' }, + titles: { + addChargeItem: '新增收费项目', + addMedicationUsed: '新增使用药物', + deleteChargeItem: '删除收费项目', + deleteMedicationUsed: '新增使用药物', + edit: '编辑程序', + editChargeItem: '编辑收费项目', + editMedicationUsed: '编辑使用药物', + medicationUsed: '使用药物', + 'new': '新增程序', + saved: '程序已储存' + } + }, + reports: { + labels: { + admissionDate: '入院日期', + allProcedures: '已完成所有程序', + completedBy: '由...完成', + dischargeDate: '出院日期', + examiner: '审查者', + images: '照片', + labs: '测试', + location: '探访地点', + medications: '药物', + nextAppointment: '下个预约', + nextAppointments: '下个预约', + notes: { + author: '作者', + date: '日期', + title: '备注' + }, + operativePlan: { + description: '程序描述', + instructions: '入院后指导', + procedures: '已计划程序', + title: '程序计划' + }, + primaryDiagnosis: '主要诊断', + procedures: '程序', + secondaryDiagnosis: '次要诊断', + visitDate: '探访日期', + visitType: '探访类别' + }, + messages: { + 'delete': '确定要删除此报告?', + saved: '报告已成功储存.' + }, + titles: { + dischargeReport: '出院报告', + newDischargeReport: '新增出院报告', + newOPDReport: '新增OPD报告', + opdReport: 'OPD报告', + saved: '报告已储存' + } + }, + user: { + plusNewUser: '+ 新增使用者', + usersPageTile: '使用者名单' + }, + visits: { + buttons: { + addDiagnosis: '新增诊断', + checkIn: '报到', + checkOut: '退房', + discharge: '出院', + newAppointment: '新增预约', + newDischargeReport: '新增出院报告', + newOPDReport: '新增OPD报告', + newProcedure: '新增程序', + newVitals: '新增命脉资料' + }, + labels: { + appointment: '预约', + authoredBy: '由...創作', + checkInTime: '报到', + checkOutTime: '退房', + createNewPatient: '建立新患者', + diagnosis: '诊断', + examiner: '审查者', + finalDiagnosis: '最后诊断', + haveAppointment: 'Y', + haveDoneOrders: 'Y', + noAppointment: 'N', + ordersDone: '已完成订单', + ordersNotDone: 'N', + patientToCheckIn: '要报到之患者', + procedure: '程序', + procedureDate: '程序日期', + reasonForVisit: '探访原因', + reportType: '报告类型', + status: '探访状态', + statusAdmitted: '收入医院', + statusCheckedIn: '已报到', + statusCheckedOut: '已离開', + statusDischarged: '已出院', + visitDate: '探访日期', + visitInformation: '探访资料', + visitType: '探访类型' + }, + messages: { + checkOut: '确定要把 {{patientName}} 退房?', + checkedOut: '{{patientName}} 已被准許离開.', + discharged: '{{patientName}} 已出院.', + patientCheckedIn: '{{patientName}} 已报到.', + patientCreatedAndCheckedIn: '{{patientName}} 已建立並报到.', + visitAndPatientSaved: '探访与患者纪录已储存.', + visitSaved: '探访纪录已储存.' + }, + navigation: { + charges: '收费', + notes: '备注', + orders: '订購', + procedures: '程序', + reports: '报告', + vitals: '命脉资料' + }, + titles: { + additionalDiagnoses: '其他诊断', + checkOut: '患者离開', + checkedIn: '患者报到', + checkedOut: '患者退房', + discharged: '患者出院', + editVisit: '编辑探访', + newVisit: '新增探访', + patientCheckIn: '患者报到', + visitSaved: '探访已储存' + } + }, + vitals: { + labels: { + dateRecorded: '纪录之日期', + dbp: '出生年月日', + heartRate: '心率', + height: '身高', + respiratoryRate: '呼吸频率', + sbp: 'SBP', + temperature: '体溫', + weight: '体重' + } + } +}; diff --git a/app/locales/tw/translations.js b/app/locales/tw/translations.js new file mode 100755 index 0000000000..cec8531ef3 --- /dev/null +++ b/app/locales/tw/translations.js @@ -0,0 +1,1489 @@ +export default { + languageName: '繁體中文', + admin: { + address: { + address1Label: '地址標籤1', + address2Label: '地址標籤2', + address3Label: '地址標籤3', + address4Label: '地址標籤4', + addressLabel: '地址', + editTitle: '地址選項', + include1Label: '包括標籤1', + include2Label: '包括標籤2', + include3Label: '包括標籤3', + include4Label: '包括標籤4', + messages: { addressSaved: '地址選項已成功儲存' }, + newTitle: '地址選項', + titles: { optionsSaved: '選項已成功儲存' } + }, + addressOptions: '地址選項', + customForms: { + buttons: { + addField: '新增欄位', + moveDown: '往上移', + moveUp: '往下移', + newForm: '+ 新表格', + preview: '預覽' + }, + labels: { + alwaysInclude: '總是包括', + checkbox: '選項欄', + colSpan: '欲展開之列數目', + columns: '列', + customForm: '自訂表格', + dischargeReportFormType: '出院報告', + expenseTo: '支付者', + formName: '表格名稱', + formType: '表格種類', + header: '標題', + incidentFormType: '事件', + includeOtherOption: '包括其他選項', + labFormType: '試驗', + label: '標籤', + newForm: '新增表格', + opdReportFormType: '門診病人報告', + operativePlanFormType: '手術計畫與報告', + otherOptionLabel: '其他選項標籤', + patientFormType: '病患', + property: '屬性', + radio: '單選按鈕', + select: '複選單', + socialworkFormType: '社區服務', + text: '文字', + textarea: '放大文字', + visitFormType: '探訪' + }, + messages: { formSaved: '{{name}}表格已成功儲存' }, + titles: { + checkboxValues: '選項欄資料', + customForms: '自訂表格', + deleteForm: '刪除自訂表格', + dropDownValues: '複選單資料', + editCustomForm: '編輯自訂表格', + fields: '欄位', + formSaved: '表格成功儲存', + headerValues: '標題文字', + newCustomForm: '新增自訂表格', + radioValues: '單選按鈕資料' + } + }, + header: { + editTitle: '標題選項', + facilityName: '設施名稱', + headerLabel: '標題', + headerLine1: '標題第1行', + headerLine2: '標題第2行', + headerLine3: '標題第3行', + logoURL: '商標網址', + messages: { headerSaved: '標題選項已成功儲存' }, + newTitle: '標題選項', + titles: { optionsSaved: '選項已成功儲存' } + }, + loadDb: '啟動數據庫', + loaddb: { + displayAlertMessage: '請選擇要開啟的檔案', + displayAlertTitle: '選擇開啟檔案', + editTitle: '啟動數據庫', + errorDisplayAlertMessage: '無法啟動數據庫。問題:{{error}}', + errorDisplayAlertTitle: '啟動時發生錯誤', + progressMessage: '請等待數據庫啟動', + progressTitle: '正在啟動數據庫' + }, + lookup: { + aisleLocationList: '庫存通道位置', + alertImportListMessage: '請選擇要匯入的檔案.', + alertImportListSaveMessage: '查找列表已成功匯入', + alertImportListSaveTitle: '名單成功匯入', + alertImportListTitle: '請選擇要匯入的檔案', + alertImportListUpdateMessage: '查找列表已成功儲存', + alertImportListUpdateTitle: '名單已儲存', + anesthesiaTypes: '麻醉種類', + anesthesiologists: '麻醉師', + billingCategories: '建築類別', + clinicList: '診所地點', + countryList: '國家', + cptCodeList: 'CPT 編碼', + diagnosisList: '診斷', + edit: { template: { + addTitle: '新增數值', + editTitle: '編輯數值', + labelTitle: '數值', + updateButtonTextAdd: '增加', + updateButtonTextUpdate: '編輯' + } }, + expenseAccountList: '費用帳戶', + imagingPricingTypes: '影像價目類別', + incidentDepartments: '事件部門', + inventoryTypes: '庫存類型', + labPricingTypes: '試驗定價類型', + pageTitle: '查找列表', + patientStatusList: '病患狀態表', + physicianList: '醫師', + procedureList: '程序', + procedureLocations: '程序地點', + procedurePricingTypes: '程序定價類型', + radiologists: '放射科醫生', + titles: { deleteLookupValue: '刪除數值' }, + unitTypes: '單位類型', + vendorList: '供應商', + visitLocationList: '探訪地點', + visitTypes: '探訪類型', + wardPricingTypes: '病房定價類型', + warehouseList: '庫存地點' + }, + lookupLists: '查找列表', + roles: { + capability: { + addAllergy: '新增過敏', + addAppointment: '新增預約', + addBillingDiagnosis: '增加計費診斷', + addCharge: '增加收費', + addDiagnosis: '增加診斷', + addImaging: '增加影像', + addIncident: '增加事件', + addIncidentCategory: '增加事件種類', + addInventoryItem: '增加庫存項目', + addInventoryPurchase: '增加庫存購買', + addInventoryRequest: '增加庫存請求', + addInvoice: '增加單據', + addLab: '增加測試', + addMedication: '增加藥物', + addNote: '增加筆記', + addOperationReport: '增加程序報告', + addOperativePlan: '增加程序類型', + addPatient: '增加病患', + addPayment: '新增付款', + addPhoto: '增加照片', + addPricing: '新增價錢', + addPricingProfile: '新增定價概況', + addProcedure: '新增程序', + addSocialwork: '新增社區工作', + addVisit: '新增探訪', + addVitals: '新增命脈資料', + adjustInventoryLocation: '調整庫存位置', + admin: '行政', + admitPatient: '接納病患', + appointments: '預約', + billing: '計費', + cashier: '出納員', + completeImaging: '完成影像', + completeLab: '完成測試', + defineUserRoles: '定義用戶角色', + deleteAppointment: '刪除預約', + deleteDiagnosis: '刪除診斷', + deleteImaging: '刪除影像', + deleteIncident: '刪除事件', + deleteIncidentCategory: '刪除事件類型', + deleteInventoryItem: '刪除庫存項目', + deleteInvoice: '刪除單據', + deleteLab: '刪除測試', + deleteMedication: '刪除藥物', + deleteNote: '刪除筆記', + deletePatient: '刪除病患', + deletePhoto: '刪除照片', + deletePricing: '刪除定價', + deletePricingProfile: '刪除定價概況', + deleteProcedure: '刪除程序', + deleteSocialwork: '刪除社會工作', + deleteVisit: '刪除拜訪', + deleteVitals: '刪除命脈資料', + dischargePatient: '讓病患出院', + editInvoice: '編輯單據', + fulfillInventory: '滿足庫存', + fulfillMedication: '滿足藥物', + generateIncidentReport: '生成事件報告', + imaging: '影像', + incident: '事件', + inventory: '庫存', + invoices: '單據', + labs: '測試', + listPaidInvoices: '顯示付清單據', + loadDb: '載入數據庫', + manageIncidents: '管理事件', + medication: '藥物', + overrideInvoice: '覆蓋單據', + patientReports: '病患報告', + patients: '病患', + pricing: '價錢', + updateConfig: '更新設置', + visits: '探訪' + }, + messages: { roleSaved: '{{roleName}}任務已成功儲存' }, + titles: { roleSaved: '任務已成功儲存' } + }, + textReplacements: { + createNew: '新增簡碼', + existingRepl: '現有簡碼', + replDesc: '輸入文字時,這些快捷鍵讓您短的字句變成長的語句.', + pageTitle: '簡碼', + toReplace: '要取代之文字', + replaceWith: '用 ... 來取代', + performExpand: "按 Enter 來用 '{{to}}' 取代 #{{from}}", + possibleExpansions: '{{possible}} 可能的替代品', + noMatches: "'{{term}}' 沒有相對應的替代品" + }, + userRoles: '用戶角色', + users: '用戶', + visitForms: { + labels: { + followup: '跟進', + form: '表格', + initial: '初始', + visitType: '探訪類型' + }, + titles: { visitForms: '探訪表格' } + }, + workflow: { + admissionDepositLabel: '需要入院押金', + clinicPrepaymentLabel: '需要診所付款', + editTitle: '流程選項', + followupPrepaymentLabel: '需要跟進付款', + messages: { optionsSaved: '流程選項已成功儲存' }, + newTitle: '流程選項', + outpatientImagingLabel: '需要門診病人影像付款', + outpatientLabLabel: '需要門診病人測試付款', + outpatientMedicationLabel: '需要門診病人藥物付款', + titles: { optionsSaved: '選項已儲存' }, + workflowLabel: '流程' + } + }, + alerts: { + errorExclamation: '發生錯誤!!!', + pleaseWait: '請稍候', + reportError: '生成報告時發生錯誤', + warningExclamation: '注意!!!' + }, + allergies: { + buttons: { addAllergy: '新增過敏' }, + labels: { + allergyName: '名稱', + patientAllergy: '患者過敏' + }, + titles: { + addAllergy: '新增過敏', + editAllergy: '編輯過敏' + } + }, + application: { + messages: { sessionExpired: '請重新登入' }, + titles: { sessionExpired: '會話過期' } + }, + appointments: { + buttons: { + newButton: '+ 新增預約', + scheduleSurgery: '+ 預約手術' + }, + calendarTitle: '預約行事曆', + currentScreenTitle: '預約列表', + editTitle: '更改預約', + labels: { + noLocation: '無地點', + selectedStartingDate: '顯示在 ... 之後的預約' + }, + messages: { + appointmentSaved: '{{patient}}的預約已成功儲存', + endTimeLaterThanStart: '請選擇一個開始時間之後的結束時間' + }, + missed: '錯過的預約', + newTitle: '新增預約', + searchTitle: '搜尋預約', + sectionTitle: '預約', + thisWeek: '本週預約', + titles: { + appointmentSaved: '預約已儲存', + editSurgicalAppointment: '更改手術預約', + newSurgicalAppointment: '新增手術預約', + theaterSchedule: '手術室時間表' + }, + todayTitle: '本日預約' + }, + billing: { + alerts: { + noInvoiceFound: '找無單據', + noPricingItems: '找無定價項目', + noPricingProfiles: '找無定價概況' + }, + buttons: { + addOverride: '新增覆蓋', + createInvoice: '建立單據?' + }, + labels: { + actualCharges: '實際收費', + discountAmount: '折扣金額', + discountPercentage: '折扣百分比', + externalInvoiceNumber: '外部收據 #', + hmoCom: 'HMO/COM', + insurance: '國家保險', + paymentProfile: '付款資料', + paymentsDeposits: '付款/存款', + pricingPanelOverrides: '定價資料覆蓋', + pricingProfile: '定價資料', + setFee: '設定費用' + }, + messages: { + flatFeeMsg: '患者負責 {{currency}}{{setFee}} 的基本費用.', + flatDiscountMsg: '患者負責的基本費用已包含 {{currency}}{{discountAmount}} 的折扣.' + } + }, + buttons: { + add: '新增', + addItem: '新增項目', + addLineItem: '新增訂單項目', + addValue: '新增數值', + addVisit: '新增探訪', + allRequests: '全部要求', + barcode: '條碼', + cancel: '取消', + clear: '清除', + close: '關', + complete: '完成', + 'delete': '刪除', + dispense: '分發', + edit: '編輯', + filter: '篩選', + fulfill: '履行', + 'import': '輸入', + loadFile: '載入檔案', + newItem: '+ 新增項目', + newNote: '新增筆記', + newRequest: '新增要求', + newRequestPlus: '+ 新增要求', + newUser: '新增使用者', + ok: 'Ok', + print: '列印', + remove: '移除', + returnButton: '返回', + review: '檢閱', + search: '搜尋', + showAll: '顯示全部', + showFewer: '顯示部分', + update: '更新' + }, + components: { + chargesByTypeTab: { charges: '收費' }, + customFormManager: { buttons: { addForm: '新增表格' } }, + dateTimePicker: { + amHour: '上午{{hour}}', + midnight: '午夜', + noon: '中午', + pmHour: '下午{{hour}}' + }, + imageUpload: { messages: { selectValidImageFile: '請選擇一個有效的照片' } }, + operativeProcedures: { + buttons: { addProcedure: '新增程序' }, + labels: { procedure: '程序' }, + titles: { procedures: '程序' } + }, + patientOrders: { + buttons: { + newImaging: '新增影像', + newLab: '新增測試', + newMedication: '新增藥物' + }, + labels: { + imagingOrderType: '影像', + labOrderType: '測試', + medicationOrderType: '藥物', + orderType: '訂購類型' + } + }, + priceList: { charges: '{{pricingType}} 收費' }, + quantityCalc: { result: '{{targetUnit}} 總和:{{calculated}}' }, + quantityConv: { + conversion: '一個 {{name}} 含有?', + unit: '單位' + }, + sortableColumn: { labels: { selectAll: '(全選)' } }, + takePhoto: { + camera: '相機', + how: '想如何加入相片', + labels: { + takeAPicture: '拍張照片', + uploadAFile: '上傳檔案' + }, + photo: '照片', + preview: '預覽', + takePhoto: '拍照片', + uploadFile: '上傳檔案' + }, + upcomingAppointments: { + labels: { + date: '日期', + location: '地點', + type: '種類', + 'with': '與' + }, + titles: { upcomingAppointments: '將來預約' } + } + }, + customForms: { + buttons: { addForm: '加入表格' }, + labels: { formToAdd: '要加入之表格' }, + titles: { addCustomForm: '加入自訂表格' } + }, + dashboard: { + needs_user_setup: '我們建議您建立使用者帳戶', + standalone_welcome: '

感謝您下載 HospitalRun.

您正在使用 HospitalRun 的獨立模式. 這個模式支援多個使用者在一台電腦. 這對於下列是理想的:

  • 評估 HospitalRun 以開發伺服器.
  • 使用平台來支援僅需單一設備(電腦)的診所.

如果您\'考慮架構一個數台設備(電腦)的HospitalRun, 我們 正在試著開發功能 讓您從這單一設置升級到一般的雲端/伺服器設置.

', + title: '歡迎來到 HospitalRun!' + }, + dates: { + 'long': '{{years}} 年 {{months}} 月 {{days}} 日', + longOmitDays: '{{years}} 年 {{months}} 月', + longOmitDaysPlural: '{{years}} 年 {{months}} 月', + longOmitDaysYears: '{{months}} 月', + longOmitYears: '{{months}} 月 {{days}} 日', + longPlural: '{{years}} 年 {{months}} 月 {{days}} 日', + 'short': '{{years}}年 {{months}}月 {{days}}日', + shortOmitYears: '{{months}}月 {{days}}日' + }, + diagnosis: { + labels: { + activeDiagnosis: '現行診斷', + date: '日期', + diagnosis: '診斷', + secondaryDiagnosis: '次要診斷' + }, + titles: { + addDiagnosis: '新增診斷', + editDiagnosis: '編輯診斷' + } + }, + errors: { + accepted: '必須要接受', + blank: '不能空白', + confirmation: '不符合 {{attribute}}', + empty: '不能空白', + equalTo: '必須等於 {{count}}', + even: '必須是偶數', + exclusion: '已保存', + greaterThan: '必須大於 {{count}}', + greaterThanOrEqualTo: '必須大於或等於 {{count}}', + inclusion: '不在名單內', + invalid: '不符合要求', + invalidNumber: '不是有效數字', + lessThan: '必須小於 {{count}}', + lessThanOrEqualTo: '必須小於或等於 {{count}}', + notANumber: '不是一個數字', + notAnInteger: '必須是一個整數', + odd: '必須是奇數', + otherThan: '不能等於 {{count}}', + present: '必須是空白', + result: '請先輸入一個結果', + tooLong: '字數太長 (不能超過 {{count}} 字數)', + tooShort: '字數太短 (不能低於 {{count}} 字數)', + wrongLength: '字數不對 (必須等於 {{count}} 字數)' + }, + headings: { chargedItems: '收費項目' }, + imaging: { + alerts: { + completedMessage: '影像要求已完成', + completedTitle: '影像要求完成', + savedMessage: '影像要求已儲存', + savedTitle: '影像要求已儲存' + }, + buttons: { newButton: '+ 新增影像' }, + labels: { + addNewVisit: '--新增探訪--', + radiologist: '放射科醫師', + resultNotes: '結果筆記', + requestedNotes: '要求的筆記', + completedBy: '完成者' + }, + messages: { noCompleted: '找不到已完成的項目' }, + pageTitle: '影像要求', + sectionTitle: '影像', + titles: { + completedImaging: '已完成影像', + editTitle: '編輯影像要求', + newTitle: '新增影像要求' + } + }, + incident: { + buttons: { + add: '新增', + addForm: '+ 新增表格', + addItem: '新增表格', + cancel: '取消', + 'delete': '刪除', + download: '下載', + edit: '編輯', + 'export': '輸出報告', + generateRep: '生成報告', + newAttachment: '+ 新增附件', + newCategory: '+ 新增類型', + newIncident: '+ 新增事件', + newNote: '+ 新增筆記' + }, + labels: { + actions: '作用', + addedBy: '由...添加', + category: '類型', + categoryItem: '類型表格', + date: '日期', + dateRecorded: '紀錄日期', + department: '部門', + description: '事件描述', + endDate: '結束日期', + givenBy: '由...提供', + howToAddAttachment: '您想如何增加附件?', + incidentDate: '事件日期', + incidentId: '事件 ID', + item: '項目', + lastUpdated: '上一次更新', + note: '筆記', + patientId: '患者 Id', + patientImpacted: '影響患者', + reportType: '報告種類', + reportedBy: '由...報告', + reportedDate: '報告日期', + reportedTo: '事件已報告給 (Full Name)', + sentinelEvent: '突發事件', + startDate: '開始日期', + status: '狀態', + statusActive: '現行', + statusClosed: '完成', + statusFollowup: '跟進', + statusReported: '已報告', + title: '標題', + total: '總和', + updatedBy: '由...更新' + }, + messages: { + attachmentFileRequired: '儲存附件前請先上傳檔案或拍張照片', + createNew: '新增事件?', + createNewIncidentCategory: '新增事件類型?', + fillIn: '填入上述選項以計算分數', + incidentCategorySaved: '{{name}} 類型已成功儲存.', + noClosedIncidents: '找不到已完成的事件.', + noIncidentCategoriesFound: '找不到事件類型.', + noIncidents: '找不到事件.', + saved: '事件報告已成功儲存.', + selectExistingPatient: '請選擇一個現有的患者或不要填寫此字段.' + }, + titles: { + addAttachment: '加入附件', + addCategoryItem: '加入類型項目', + addNote: '加入筆記', + attachments: '附件', + closed: '已完成事件', + current: '當前', + deleteAttachment: '刪除附件', + deleteIncident: '刪除事件', + deleteIncidentCategory: '刪除事件類型', + deleteItem: '刪除項目', + deleteNote: '刪除筆記', + editAttachment: '編輯附件', + editIncident: '編輯事件', + editIncidentCategory: '編輯事件類型', + editNote: '編輯筆記', + general: '一般信息', + history: '歷史', + incidentCategories: '事件類型', + incidentCategoryItem: '事件類型項目', + incidentCategoryName: '事件類型名稱', + incidentCategorySaved: '事件類型已儲存', + incidentSaved: '事件已儲存', + incidents: '事件', + incidentsByCategory: '按類型顯示事件', + incidentsByDepartment: '按部門顯示事件', + newIncident: '新增事件', + newIncidentCategory: '新增事件類型', + notes: '筆記', + reports: '報告' + } + }, + inventory: { + edit: { + cost: '單位價:', + delivered: '傳遞給:', + location: '調整地點:', + prescription: '處方給:', + pulled: '來源:', + quantity: '完成數量:', + reason: '原因:', + returned: '患者給回:', + transferredFrom: '從...轉來:', + transferredTo: '轉去:' + }, + labels: { + action: '行動', + add: '加入', + addAdjustmentType: '加入', + adjust: '調整', + adjustmentDate: '調整日期', + adjustmentFor: '為...調整', + adjustmentType: '調整種類', + aisle: '通道', + aisleLocation: '通道地點', + allInventory: '全部清單', + allItems: '全部項目', + availableQuantity: '{{quantity}} 可用', + billTo: '記帳到', + consumePurchases: '消費購買', + consumptionRate: '消費率', + cost: '費用', + costPerUnit: '單位價', + crossReference: '交叉引用', + currentQuantity: '現前數量', + dateCompleted: '完成日期', + dateEffective: '生效日期', + dateEnd: '結束日期', + dateReceived: '收到日期', + dateStart: '開始日期', + dateTransferred: '轉移日期', + daysLeft: '剩餘天數', + deleteItem: '刪除項目', + deliveryAisle: '發送通道', + deliveryLocation: '發送地點', + details: '細節', + distributionUnit: '分配單位', + editItem: '編輯項目', + expense: '記帳到', + expirationDate: '截止日期', + fulfillRequest: '實現需求', + fulfillRequestNow: '現在實現需求', + gift: '禮物', + giftInKindNo: 'N', + giftInKindYes: 'Y', + giftUsage: '禮物用途', + inventoryConsumed: '庫存消耗', + inventoryItem: '庫存項目', + inventoryObsolence: '庫存報廢', + invoiceItems: '單據項目', + invoiceLineItem: '單據單項', + invoiceNumber: '單據號碼', + item: '項目', + itemNumber: '項目號碼', + items: '項目', + location: '地點', + locations: '地點', + markAsConsumed: '標記為已消耗', + name: '名稱', + newItem: '新增項目', + originalQuantity: '原本數量', + print: '列印', + printBarcode: '列印條碼', + printer: '列印機', + pullFrom: '從...拉入', + purchaseCost: '購買價格', + purchaseInfo: '購買資料', + purchases: '購買', + quantity: '數目 ({{unit}})', + quantityAvailable: '可提供之數目', + quantityOnHand: '現有數目', + quantityRequested: '要求數目', + rank: '級別', + reason: '原因', + remove: '移除', + removeAdjustmentType: '移除', + reorderPoint: '訂貨點', + requestedItems: '要求項目', + returnAdjustmentType: '退回', + returnToVendorAdjustmentType: '退回給供應商', + salePricePerUnit: '銷售單位價', + save: '儲存', + serialNumber: '序列號', + total: '總和', + totalCost: '總價碼', + totalReceived: '總收入: {{total}}', + transaction: '交易', + transactions: '交易', + transfer: '調動', + transferFrom: '從...調動', + transferTo: '調動到目的地', + transferToAisle: '調動到通道地點', + unit: '單位', + unitCost: '單位價', + vendor: '供應商', + vendorItemNumber: '供應商項目編號', + writeOffAdjustmentType: '註銷', + xref: '外部參照' + }, + messages: { + adjust: '請調整適當地區的數目以解釋誤差 {{difference}}.', + createRequest: '加入新需求?', + itemNotFound: '找不到庫存項目 {{item}}.
如果要加入新的庫存項目, 請填入以下資料.
或選擇取消以返回.', + loading: '載入交易...', + noItems: '找無項目.', + noRequests: '找無要求.', + purchaseSaved: '庫存購買已成功儲存.', + quantity: '總數目 ({{quantity}}) 不吻合地點的總數目 ({{locationQuantity}}).', + removeItem: '確定要從庫存中移除此項目?', + removeItemRequest: '確定要從要求中移除此項目?', + requestFulfilled: '庫存要求已完成.', + requestUpdated: '庫存要求已更新.', + warning: '加入前請填入必要的欄位 (有 * 標註) 並更正錯誤.' + }, + reports: { + adjustment: '詳細的調整', + daysSupply: '庫存能支援天數', + expenseDetail: '詳細的費用', + expenseSum: '費用概要', + expiration: '截止日期', + 'export': '輸出報告', + fields: '要包括之欄位', + finance: '財政概要', + generate: '生成報告', + invLocation: '按地點顯示庫存', + invValuation: '庫存計價', + purchaseDetail: '購買詳細資料', + purchaseSum: '購買概要', + reportType: '報告種類', + rows: { + adjustments: '調整', + adjustmentsTotal: '總調整', + balanceBegin: '初期結餘', + balanceEnd: '最終結餘', + category: '類別', + consumed: '已消耗', + consumedGik: '已消耗GiK', + consumedGikTotal: '已消耗GiK總和', + consumedPuchases: '已消耗購買', + consumedPurchasesTotal: '已消耗購買總和', + consumedTotal: '已消耗總和', + errInFinSum: '生成財政概況報告時發生錯誤: ', + errInFindPur: '依購買搜尋庫存項目時發生錯誤: ', + errInFindReq: '依要求搜尋庫存項目時發生錯誤: ', + expensesFor: '...的費用: ', + noAccount: '(沒有帳戶)', + subtotal: '小計: ', + subtotalFor: '小計:{{category}} - {{account}}: ', + total: '總和: ', + totalFor: '{{var}}總和: ', + totalPurchases: '購買總和', + transfer1: '{{quantity}}來自{{location}}', + trasnfer2: '從: {{source}} 到: {{target}}' + }, + stockTransferDetail: '庫存傳遞詳細資料', + stockTransferSum: '庫存傳遞概要', + stockUsageDetail: '詳細庫存使用資料', + stockUsageSum: '庫存使用概要', + titleDateRange: '{{name}} 報告 {{startDate}} - {{endDate}}', + titleSingleDate: '{{name}} 報告 {{date}}' + }, + titles: { + addPurchase: '加入購買', + addRequest: '新增需求', + adjustment: '調整', + editPurchase: '編輯購買', + editRequest: '編輯需求', + inventoryItem: '新增庫存項目', + inventoryReport: '庫存報告', + purchaseSaved: '庫存購買已儲存', + quickAddTitle: '新增庫存項目', + removeItem: '移除項目', + requestFulfilled: '需求已滿足', + requestUpdated: '需求已更新', + transfer: '搬遷項目', + warning: '警告!!!!!' + } + }, + labels: { + action: '行動', + actions: '行動', + addNewOutpatientVisit: '--加入門診病人探訪--', + address: '地址', + age: '年齡', + allDay: '整天', + allItems: '所有項目', + amount: '數目', + anesthesia: '麻醉', + assisting: '助理', + balanceDue: '餘額到期', + billDate: '收費日期', + billTo: '跟...收費', + category: '類別', + completed: '已完成', + country: '國家', + cptcode: 'CPT 代碼', + creditTo: '歸於', + currencySymbol: '$', + date: '日期', + dateCompleted: '完成日期', + dateOfBirth: '出生年月日', + dateOfBirthShort: '生日', + datePaid: '付款日期', + dateRequested: '要求的日期', + 'delete': '刪除', + deleteRequest: '刪除要求', + deleteUser: '刪除使用者', + department: '部門', + description: '描述', + discount: '折扣', + displayName: '顯示名稱', + docRead: '已讀文件', + docWritten: '已填文件', + edit: '編輯', + editUser: '編輯使用者', + email: '電子郵件', + endDate: '結束日期', + endTime: '結束時間', + excess: '過量', + expenseTo: '由...付費', + fileLoadSuccessful: '成功載入檔案', + fileName: '檔案名稱', + fileToLoad: '檔案載入', + from: '來自', + fulfill: '實現', + fulfillRequest: '實現需求', + fulfillRequestNow: '現在實現需求', + fulfilled: '已實現', + grandTotal: '累計', + id: 'Id', + imageOrders: '圖像訂製', + imagingType: '影像種類', + importFile: '載入檔案', + invoiceId: '單據ID', + labOrders: '指定試驗', + lineItems: '訂單項目', + loading: '正在載入', + location: '地點', + lookupType: '查找種類', + medication: '藥物', + name: '名稱', + newUser: '新增使用者', + newItem: '+ 新增項目', + note: '筆記', + notes: '筆記', + number: '數字', + on: '上', + password: '密碼', + patient: '患者', + payments: '付款', + physician: '醫師', + prescriber: '處方師', + prescription: '處方', + prescriptionDate: '處方日期', + price: '價格', + print: '列印', + procedures: '程序', + provider: '提供者', + pullFrom: '從...拉入', + quantity: '數目', + remarks: '備註', + requestedBy: '要求者', + requestedOn: '要求的日期', + requests: '要求', + result: '結果', + results: '結果', + role: '角色(任務)', + search: '搜尋', + sex: '性別', + startDate: '開始日期', + startTime: '開始時間', + status: '狀態', + takenBy: '由...採取', + to: '給', + total: '總和', + type: '種類', + userCanAddNewValue: '使用者可加入數值', + username: '用戶名', + value: '數值', + view: '檢視', + visit: '探訪', + 'with': '與' + }, + labs: { + alerts: { + requestCompletedMessage: '測試要求已完成.', + requestCompletedTitle: '測試要求已完成', + requestSavedMessage: '測試要求已儲存.', + requestSavedTitle: '測試要求已儲存' + }, + buttons: { newButton: '+ 新增測試' }, + completedTitle: '已完成的測試', + deleteTitle: '刪除要求', + editTitle: '編輯測試要求', + labels: { + addNewVisit: '--加入新探訪--', + labType: '測試種類' + }, + messages: { + createNewRecord: '加入新紀錄?', + noCompleted: '找無已完成的項目.', + noItemsFound: '找無測試.' + }, + newTitle: '新增測試要求', + requestsTitle: '測試要求', + sectionTitle: '測試' + }, + loading: { + messages: { + '0': '飛行最快的蝴蝶可以達到每小時12英里. 有些飛蛾能達到每小時25英里的飛行速度!', + '1': '貓頭鷹是唯一能識別藍色的鳥類.', + '2': '貓可以發出超過一百種聲音,狗只能發出十種.', + '3': '人類說話時運用了72個不同的肌肉.', + '4': '非洲上的語言超過一千種.', + '5': 'Erythrophobe 這個詞形容一個容易臉紅的人.', + '6': '世上最常見的恐懼症是怕痛的恐懼.', + '7': '當您站立不動的時候,您的身體運用了300個肌肉來平衡自己.', + '8': '特定青蛙能在被結凍又解凍後繼續生存.', + '9': '人體的眼睛從出生就保持同樣的大小, 但鼻子和耳朵會一直持續成長.', + '10': '舌頭是您體內唯一僅附在最後端的肌肉.', + '11': '駱駝有三個眼皮來防護風吹砂.' + }, + progressBar: { progress: '{{progressBarValue}}% 完成' } + }, + login: { + labels: { + password: '密碼', + signIn: '登入', + username: '用戶名' + }, + messages: { + error: '用戶名或密碼不正確.', + offlineError: '離線時無法登入. 請連上網路後再試.', + signIn: '請登入' + } + }, + medication: { + alerts: { + fulfilledTitle: '藥物要求完成', + returnedMessage: '藥物已標記為退還.', + returnedTitle: '退還藥物', + savedMessage: '藥物紀錄已儲存.', + savedTitle: '藥物要求已儲存' + }, + buttons: { + dispenseMedication: '發放配藥', + newButton: '+ 新增要求', + returnMedication: '退還藥物' + }, + labels: { + adjustmentDate: '調整日期', + creditToAccount: '歸於...帳戶', + quantityDispensed: '分配數量', + quantityDistributed: '分發數量', + quantityRequested: '要求數量', + quantityToReturn: '要還的數量', + refills: '充值', + returnAisle: '退還通道', + returnLocation: '退還地點', + returnReason: '退還原因/備註' + }, + messages: { createNew: '新增藥物要求?' }, + pageTitle: '藥物要求', + returnMedication: '退還藥物', + sectionTitle: '藥物', + titles: { + completedMedication: '完成藥物', + editMedicationRequest: '編輯藥物要求', + newMedicationRequest: '新增藥物要求' + } + }, + messages: { + createNewRecord: '建立新紀錄?', + createNewUser: '建立新使用者?', + 'delete': '確定要刪除 {{name}}?', + delete_plural: '確定要刪除這些 {{name}}?', + delete_singular: '確定要刪除 {{name}}?', + forAuthorizedPersons: '這報告只提供給特定授權人.', + newPatientHasToBeCreated: '必須建立一個新的患者...請稍候..', + noHistoryAvailable: '沒有歷史.', + noItemsFound: '找無項目.', + noNotesAvailable: '沒有其他的其他的臨床報告可提供給此次探訪.', + noUsersFound: '找無使用者.', + onBehalfOf: '代表', + reportError: '生成報告時發生錯誤. 請通報錯誤給系統管理員.', + requiredFieldsCorrectErrors: '加入前請填入必要的欄位 (有 * 標註) 並更正錯誤.', + saveActionException: '嘗試儲存時發生錯誤: {{message}}', + sorry: '抱歉,發生錯誤...', + userHasBeenSaved: '使用者已儲存.', + userSaved: '使用者已儲存' + }, + models: { + appointment: { + labels: { + allDay: '整天', + appointmentDate: '日期', + appointmentType: '種類', + endDate: '結束日期', + location: '地點', + notes: '筆記', + patient: '患者', + provider: '與', + startDate: '開始日期', + status: '狀態', + type: '種類' + }, + names: { + plural: '預約', + singular: '預約' + } + }, + attachment: { names: { + plural: '附件', + singular: '附件' + } }, + form: { names: { + plural: '表格', + singular: '表格' + } }, + imaging: { + names: '影像', + request: { + plural: '影像要求', + singular: '影像要求' + } + }, + incident: { names: { + plural: '事件', + singular: '事件' + } }, + item: { names: { + plural: '項目', + singular: '項目' + } }, + lab: { + names: { + plural: '測試', + singular: '測試' + }, + request: { + plural: '測試要求', + singular: '測試要求' + } + }, + medication: { + names: { + plural: '藥物', + singular: '藥物' + }, + request: { + plural: '藥物要求', + singular: '藥物要求' + } + }, + note: { names: { + plural: '筆記', + singular: '筆記' + } }, + patient: { + labels: { name: '名稱' }, + names: { singular: '患者' } + }, + procedure: { names: { + plural: '程序', + singular: '程序' + } }, + user: { names: { + plural: '使用者', + singular: '使用者' + } }, + visit: { names: { + plural: '探訪', + singular: '探訪' + } }, + vital: { names: { + plural: '命脈資料', + singular: '命脈資料' + } } + }, + navigation: { + about: '關於HospitalRun', + actions: { + login: '登入', + logout: '登出', + selectLanguage: '選擇語言' + }, + administration: '行政', + billing: '計費', + imaging: '影像', + incident: '事件', + inventory: '庫存', + labs: '測試', + medication: '藥物', + messages: { + logoutFailed: '現在無法登出. 離線時無法登出.' + }, + patients: '患者', + scheduling: '調度', + subnav: { + actions: '動作', + addAppointment: '新增預約', + addressFields: '地址欄位', + admittedPatients: '收入患者', + appointmentSearch: '搜尋預約', + appointmentsCalendar: '預約行事曆', + appointmentsThisWeek: '本週預約', + cashier: '收銀員', + completed: '已完成', + currentIncidents: '現行事件', + customForms: '自訂表格', + dispense: '配藥', + history: '歷史', + incidentCategories: '事件類別', + inventoryReceived: '收到的庫存', + inventoryReceivedPlus: '+ 收到的庫存', + invoices: '清單', + items: '項目', + loadDB: '啟動數據庫', + lookupLists: '查找列表', + newIncident: '新增事件', + newInvoice: '新增清單', + newPatient: '新增患者', + newRequest: '新增要求', + newUser: '新增使用者', + outpatient: '門診病人', + patientListing: '患者名單', + priceProfiles: '價格概況', + prices: '價格', + printHeader: '列印標題', + reports: '報告', + requests: '要求', + returnMedication: '退還藥物', + scheduleSurgery: '排定手術', + textReplacements: '短代碼', + theaterSchedule: '手術室時間表', + "today'sAppointments": '本日預約', + userRoles: '使用者角色(任務)', + users: '使用者', + workflow: '工作流程' + }, + titles: { + logoutFailed: '登出失敗' + } + }, + operationReport: { + labels: { + additionalNotes: '其他備註', + assistant: '助理', + caseComplexity: '案件複雜度', + operationDescription: '程序描述', + preOpPrimaryDiagnosis: '程序前主要診斷', + preOpSecondaryDiagnosis: '程序前次要診斷', + surgeon: '手術師', + surgeryDate: '手術日期' + }, + messages: { reportSaved: '程序報告已成功儲存.' }, + titles: { + editTitle: '編輯程序報告', + newTitle: '新增程序報告', + reportSaved: '報告已儲存' + } + }, + operativePlan: { + buttons: { completePlan: '完成計畫' }, + labels: { + additionalNotes: '其他備註', + admissionInstructions: '入院後指導', + caseComplexity: '案件複雜度', + completedStatus: '已完成', + droppedStatus: '被取消', + operationDescription: '程序描述', + plannedStatus: '已計劃', + status: '狀態', + surgeon: '手術師' + }, + messages: { + planCompleted: '程序計畫已完成. 您將被導向程序報告.', + planSaved: '程序計畫已儲存.' + }, + titles: { + editTitle: '編輯程序計畫', + newTitle: '新增程序計畫', + planCompleted: '計畫已完成', + planSaved: '計畫已儲存' + } + }, + patients: { + buttons: { + addContact: '新增聯絡人', + addExpense: '新增費用', + addFamilyMember: '新增家庭成員', + addOperativePlan: '新增程序計畫', + backToPatients: '回到患者名單', + download: '下載', + editOperativePlan: '現有程序計畫', + newAppointment: '新增預約', + newImaging: '新增影像', + newLab: '新增測試', + newMedication: '新增藥物', + newPatient: '+ 新增患者', + newPhoto: '新增照片', + newVisit: '新增探訪', + patientCheckIn: '患者登記', + scheduleSurgery: '安排手術時間' + }, + labels: { + admissionDate: '入院日期', + admit: '收入患者', + bloodType: '血型', + caption: '說明', + civilStatus: '公民身份', + clinic: '診所地點', + contacts: '聯絡人', + cost: '費用', + dateOfBirth: '出生年月日', + dateProcessed: '處理日期', + dischargeDate: '出院日期', + dob: '生日', + education: '學歷', + email: '電子郵件', + externalPatientId: '外部患者 Id', + firstName: '名', + income: '收入', + insurance: '保險', + lastName: '姓', + middleName: '中間名', + monthlyCost: '月費', + occupation: '職業', + operativePlan: '程序計畫', + parent: '家長/監護人', + patientDays: '患者天數', + patientType: '患者類型', + patientTypeCharity: '慈善機構', + patientTypePrivate: '私人', + phone: '電話', + placeOfBirth: '出生地點', + primaryDiagnosis: '主要診斷', + referredBy: '由...推薦', + referredDate: '推薦日期', + relationship: '與患者的關係', + relationships: '關係', + religion: '宗教', + secondaryDiagnosis: '次要診斷', + sex: '性別', + sexNotEntered: '性別空白', + sources: '來源', + status: '患者狀態', + totalMontlyExpense: '總共月費' + }, + messages: { + areYouSureDelete: '確定要刪除 {{object}}?', + createNewPatient: '建立新的患者報告?', + deletingPatient: '正在刪除患者與其所擁有的資料', + noPatientsFound: '找無患者.', + notFoundQuickAdd: '找不到患者 {{patientFullName}}. 若您想建立新患者, 請填入以下資料. 或選擇取消以返回.', + photoFileRequired: '儲存照片前請先上傳檔案或拍張照片.', + savedPatient: '患者的 {{displayName}} 資料已成功儲存.' + }, + navigation: { + appointments: '預約', + general: '取消', + history: '歷史', + imaging: '影像', + labs: '測試', + medication: '藥物', + photos: '照片', + socialWork: '社區工作', + visits: '探訪' + }, + notes: { + newNote: '為...新增備註', + onBehalfOfCopy: '代表', + onBehalfOfLabel: '代表', + pleaseSelectAVisit: '請選擇一個探訪', + updateNote: '從...更新資料' + }, + titles: { + addContact: '新增聯絡人', + addPhoto: '新增照片', + additionalContacts: '其他聯絡人', + admissionsDetail: '入院細節', + admissionsSummary: '入院概要', + admittedPatients: '入院患者', + 'delete': '刪除患者', + deleteContact: '刪除聯絡人', + deleteExpense: '刪除費用', + deleteFamilyMember: '刪除家庭成員', + deletePatientRecord: '刪除患者紀錄', + deletePhoto: '刪除照片', + diagnosticTesting: '診斷測試', + dischargesDetail: '出院細節', + dischargesSummary: '出院概要', + edit: '編輯患者', + editPhoto: '編輯照片', + expenses: '費用', + familyInfo: '家庭資料', + familyInformation: '家庭資料', + 'new': '新增患者', + outpatientsForDate: '{{visitDate}} 的門診病人', + patient: '患者報告', + patientListing: '患者名單', + patientReport: '患者報告', + patientStatus: '患者狀態', + proceduresDetail: '程序細節', + proceduresSummary: '程序概要', + savedPatient: '患者已儲存', + socialWork: '費用', + todaysOutpatients: '本日門診病人', + totalPatientDays: '總和患者天數', + totalPatientDaysDetailed: '總和患者天數(細節)', + visit: '探訪' + } + }, + pricing: { + labels: { + discountAmount: '折扣金額', + discountPercentage: '折扣百分比', + setFee: '設定費用' + } + }, + print: { invoice: { + labels: { + billedBy: '由...收費:', + billedDate: '收費日期:', + dateAdmitted: '入院:', + dateDischarged: '出院:', + dischargeNotes: '出院備註:', + patientAddress: '地址:', + patientAge: '年齡:', + patientId: '患者 #:', + patientName: '患者姓名:', + remarks: '備註:', + spacer: '__________________________________________' + }, + messages: { whereConducted: '接產中扣了...' }, + titles: { + billingStatement: '帳單', + patientMember: '患者成員', + patients: '患者', + relContact: '關係/聯絡電話' + } + } }, + procedures: { + buttons: { addMedication: '新增藥物' }, + labels: { medicationUsed: '使用之藥物' }, + messages: { saved: '程序紀錄已儲存.' }, + titles: { + addChargeItem: '新增收費項目', + addMedicationUsed: '新增使用藥物', + deleteChargeItem: '刪除收費項目', + deleteMedicationUsed: '新增使用藥物', + edit: '編輯程序', + editChargeItem: '編輯收費項目', + editMedicationUsed: '編輯使用藥物', + medicationUsed: '使用藥物', + 'new': '新增程序', + saved: '程序已儲存' + } + }, + reports: { + labels: { + admissionDate: '入院日期', + allProcedures: '已完成所有程序', + completedBy: '由...完成', + dischargeDate: '出院日期', + examiner: '審查者', + images: '照片', + labs: '測試', + location: '探訪地點', + medications: '藥物', + nextAppointment: '下個預約', + nextAppointments: '下個預約', + notes: { + author: '作者', + date: '日期', + title: '備註' + }, + operativePlan: { + description: '程序描述', + instructions: '入院後指導', + procedures: '已計劃程序', + title: '程序計畫' + }, + primaryDiagnosis: '主要診斷', + procedures: '程序', + secondaryDiagnosis: '次要診斷', + visitDate: '探訪日期', + visitType: '探訪類別' + }, + messages: { + 'delete': '確定要刪除此報告?', + saved: '報告已成功儲存.' + }, + titles: { + dischargeReport: '出院報告', + newDischargeReport: '新增出院報告', + newOPDReport: '新增OPD報告', + opdReport: 'OPD報告', + saved: '報告已儲存' + } + }, + user: { + plusNewUser: '+ 新增使用者', + usersPageTile: '使用者名單' + }, + visits: { + buttons: { + addDiagnosis: '新增診斷', + checkIn: '報到', + checkOut: '退房', + discharge: '出院', + newAppointment: '新增預約', + newDischargeReport: '新增出院報告', + newOPDReport: '新增OPD報告', + newProcedure: '新增程序', + newVitals: '新增命脈資料' + }, + labels: { + appointment: '預約', + authoredBy: '由...創作', + checkInTime: '報到', + checkOutTime: '退房', + createNewPatient: '建立新患者', + diagnosis: '診斷', + examiner: '審查者', + finalDiagnosis: '最後診斷', + haveAppointment: 'Y', + haveDoneOrders: 'Y', + noAppointment: 'N', + ordersDone: '已完成訂單', + ordersNotDone: 'N', + patientToCheckIn: '要報到之患者', + procedure: '程序', + procedureDate: '程序日期', + reasonForVisit: '探訪原因', + reportType: '報告類型', + status: '探訪狀態', + statusAdmitted: '收入醫院', + statusCheckedIn: '已報到', + statusCheckedOut: '已離開', + statusDischarged: '已出院', + visitDate: '探訪日期', + visitInformation: '探訪資料', + visitType: '探訪類型' + }, + messages: { + checkOut: '確定要把 {{patientName}} 退房?', + checkedOut: '{{patientName}} 已被准許離開.', + discharged: '{{patientName}} 已出院.', + patientCheckedIn: '{{patientName}} 已報到.', + patientCreatedAndCheckedIn: '{{patientName}} 已建立並報到.', + visitAndPatientSaved: '探訪與患者紀錄已儲存.', + visitSaved: '探訪紀錄已儲存.' + }, + navigation: { + charges: '收費', + notes: '備註', + orders: '訂購', + procedures: '程序', + reports: '報告', + vitals: '命脈資料' + }, + titles: { + additionalDiagnoses: '其他診斷', + checkOut: '患者離開', + checkedIn: '患者報到', + checkedOut: '患者退房', + discharged: '患者出院', + editVisit: '編輯探訪', + newVisit: '新增探訪', + patientCheckIn: '患者報到', + visitSaved: '探訪已儲存' + } + }, + vitals: { + labels: { + dateRecorded: '紀錄之日期', + dbp: '出生年月日', + heartRate: '心率', + height: '身高', + respiratoryRate: '呼吸頻率', + sbp: 'SBP', + temperature: '體溫', + weight: '體重' + } + } +}; diff --git a/app/medication/edit/template.hbs b/app/medication/edit/template.hbs index 03f018ccdf..0fdd42d07d 100644 --- a/app/medication/edit/template.hbs +++ b/app/medication/edit/template.hbs @@ -8,7 +8,7 @@ {{patient-typeahead model=model property="patientTypeAhead" label=(t 'labels.patient') content=patientList selection=selectedPatient class="col-xs-6 required test-patient-input"}} {{/if}} {{#if model.isNew}} - {{form.select class="col-xs-4 required test-add-visit" label=(t 'labels.visit') + {{form.select class="col-xs-4 required form-input-group test-add-visit" label=(t 'labels.visit') property="visit" content=patientVisitsForSelect optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" prompt=(t 'labels.addNewOutpatientVisit') diff --git a/app/medication/return/template.hbs b/app/medication/return/template.hbs index ebcbdb07fd..0fcc1c59ed 100644 --- a/app/medication/return/template.hbs +++ b/app/medication/return/template.hbs @@ -1,7 +1,7 @@ {{#edit-panel editPanelProps=editPanelProps}} {{#em-form model=model submitButton=false as |form|}} {{#if showPatientMedicationList}} - {{form.select class="required" label=(t 'labels.medication') + {{form.select class="required form-input-group" label=(t 'labels.medication') property="medication" content=patientMedication optionValuePath="selectObject" optionLabelPath="selectObject.inventoryItem.name" selected=model.medication @@ -11,7 +11,7 @@ {{/if}}
{{patient-typeahead model=model property="patientTypeAhead" label=(t 'labels.patient') content=patientList selection=selectedPatient class="col-xs-6"}} - {{form.select class="col-xs-6" label=(t 'labels.visit') + {{form.select class="col-xs-6 form-input-group" label=(t 'labels.visit') property="visit" content=patientVisitsForSelect optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" selected=model.visit diff --git a/app/models/billing-line-item.js b/app/models/billing-line-item.js index 73e962fb83..4af84995e9 100644 --- a/app/models/billing-line-item.js +++ b/app/models/billing-line-item.js @@ -1,6 +1,5 @@ import { mapBy, sum } from '@ember/object/computed'; import { debounce } from '@ember/runloop'; -import { computed } from '@ember/object'; import AbstractModel from 'hospitalrun/models/abstract'; import DS from 'ember-data'; import NumberFormat from 'hospitalrun/mixins/number-format'; @@ -18,7 +17,7 @@ export default AbstractModel.extend(NumberFormat, { /* The individual objects that make up this line item. */ details: DS.hasMany('line-item-detail', { async: false }), - amountOwedChanged: computed('discount', 'nationalInsurance', 'privateInsurance', 'total', function() { + amountOwedChanged: function() { debounce(this, function() { let discount = this._getValidNumber(this.get('discount')); let nationalInsurance = this._getValidNumber(this.get('nationalInsurance')); @@ -32,7 +31,7 @@ export default AbstractModel.extend(NumberFormat, { this.set('amountOwed', this._numberFormat(amountOwed, true)); } }, 500); - }), + }.observes('discount', 'nationalInsurance', 'privateInsurance', 'total'), detailTotals: mapBy('details', 'amountOwed'), total: sum('detailTotals'), diff --git a/app/patients/notes/controller.js b/app/patients/notes/controller.js index 14a8030c36..e58d0f2e42 100644 --- a/app/patients/notes/controller.js +++ b/app/patients/notes/controller.js @@ -1,6 +1,7 @@ import { Promise as EmberPromise } from 'rsvp'; import { alias } from '@ember/object/computed'; import { inject as controller } from '@ember/controller'; +import { computed } from '@ember/object'; import AbstractEditController from 'hospitalrun/controllers/abstract-edit-controller'; import IsUpdateDisabled from 'hospitalrun/mixins/is-update-disabled'; import moment from 'moment'; @@ -11,6 +12,7 @@ export default AbstractEditController.extend(IsUpdateDisabled, UserSession, Pati cancelAction: 'closeModal', updateAction: 'updateNote', moduleController: controller('patients'), + applicationController: controller('application'), physicianList: alias('moduleController.physicianList'), lookupListsToUpdate: [{ name: 'physicianList', @@ -24,6 +26,9 @@ export default AbstractEditController.extend(IsUpdateDisabled, UserSession, Pati return `${this.get('i18n').t('patients.notes.newNote')} ${moment(this.get('model.date')).format('MM/DD/YYYY')} for ${this.get('model.patient.displayName')}`; } }.property('model.patient.displayName'), + showSelectVisit: computed('applicationController.currentPath', function() { + return (this.get('applicationController.currentPath') == 'patients.edit'); + }), updateCapability: 'add_note', beforeUpdate() { this._setNoteType(); diff --git a/app/patients/notes/template.hbs b/app/patients/notes/template.hbs index 042ab338fc..23566342cc 100644 --- a/app/patients/notes/template.hbs +++ b/app/patients/notes/template.hbs @@ -7,12 +7,14 @@ updateButtonText=updateButtonText }} {{#em-form model=model submitButton=false as |form|}} {{expand-text label=(t 'labels.note') property="content" rows=3 class="test-note-content required form-input-group" form=form}} - {{form.select class="required" label=(t 'labels.visit') - property="visit" content=patientVisitsForSelect - optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" - prompt=(t 'patients.notes.pleaseSelectAVisit') - selected=model.visit - }} + {{#if showSelectVisit}} + {{form.select class="required form-input-group test-note-visit" label=(t 'labels.visit') + property="visit" content=patientVisitsForSelect + optionValuePath="selectObject" optionLabelPath="selectObject.visitDescription" + prompt=(t 'patients.notes.pleaseSelectAVisit') + selected=model.visit + }} + {{/if}} {{select-or-typeahead form=form model=model property="attribution" label=(t 'patients.notes.onBehalfOfLabel' ) diff --git a/app/patients/reports/template.hbs b/app/patients/reports/template.hbs index 2e12322972..8238619ecc 100644 --- a/app/patients/reports/template.hbs +++ b/app/patients/reports/template.hbs @@ -14,6 +14,7 @@
{{#if isStatusReport}} {{form.select property="status" label="Patient Status" + class="form-input-group" content=statusList prompt=" " }} @@ -29,21 +30,21 @@ {{/if}} {{#if isVisitReport}}
- {{form.select class="col-sm-6" label="Visit Type" + {{form.select class="col-sm-6 form-input-group" label="Visit Type" property="visitType" content=visitTypes prompt=" " }} - {{form.select class="col-sm-6" label="Examiner" + {{form.select class="col-sm-6 form-input-group" label="Examiner" property="examiner" content=physicianList prompt=" " }}
- {{form.select class="col-sm-6" label="Location" + {{form.select class="col-sm-6 form-input-group" label="Location" property="location" content=locationList prompt=" " }} - {{form.select class="col-sm-6" label="Clinic" + {{form.select class="col-sm-6 form-input-group" label="Clinic" property="clinic" content=clinicList prompt=" " }} diff --git a/app/patients/socialwork/expense/template.hbs b/app/patients/socialwork/expense/template.hbs index 3e717577fb..de2e3da110 100644 --- a/app/patients/socialwork/expense/template.hbs +++ b/app/patients/socialwork/expense/template.hbs @@ -6,7 +6,7 @@ updateButtonAction=updateButtonAction updateButtonText=updateButtonText }} {{#em-form model=model submitButton=false as |form|}} - {{form.select label=(t 'inventory.reports.rows.category') property="category" class="required" + {{form.select label=(t 'inventory.reports.rows.category') property="category" class="required form-input-group" content=categoryTypes prompt=" " }} diff --git a/app/pricing/override/template.hbs b/app/pricing/override/template.hbs index a407e63a1e..43118779f2 100644 --- a/app/pricing/override/template.hbs +++ b/app/pricing/override/template.hbs @@ -9,7 +9,7 @@ content=pricingProfiles optionValuePath="selectObject" optionLabelPath="selectObject.name" - class="required pricing-profile" + class="required form-input-group pricing-profile" prompt=" " }} {{number-input model=model label=(t 'labels.price') property="price" class="required pricing-override-price"}} diff --git a/app/templates/components/custom-form.hbs b/app/templates/components/custom-form.hbs index 5e6996d742..f60ed330b7 100644 --- a/app/templates/components/custom-form.hbs +++ b/app/templates/components/custom-form.hbs @@ -50,7 +50,7 @@ model=model property=(concat propertyPrefix field.property) content=field.values - class=field.displayClassNames + class=(concat 'form-input-group ' field.displayClassNames) prompt=field.prompt optionValuePath="label" optionLabelPath="label" diff --git a/app/templates/inventory-basic.hbs b/app/templates/inventory-basic.hbs index 61d3efe63a..e59d90c82d 100644 --- a/app/templates/inventory-basic.hbs +++ b/app/templates/inventory-basic.hbs @@ -19,7 +19,7 @@
{{form.select label=(t 'labels.type') property="inventoryType" content=inventoryTypes - class="required col-sm-4 test-inv-type" + class="required col-sm-4 form-input-group test-inv-type" prompt=" " }} {{form.input property="crossReference" label=(t 'inventory.labels.crossReference') class="col-sm-8 test-inv-cross"}} @@ -27,7 +27,7 @@
{{form.input property="reorderPoint" label=(t 'inventory.labels.reorderPoint') class="col-sm-3 test-inv-reorder"}} {{number-input model=model property="price" label=(t 'inventory.labels.salePricePerUnit') class="col-sm-3 test-inv-price"}} - {{form.select label=(t 'inventory.labels.distributionUnit') class="col-sm-3 required test-inv-dist-unit" + {{form.select label=(t 'inventory.labels.distributionUnit') class="col-sm-3 required form-input-group test-inv-dist-unit" property="distributionUnit" content=unitListForSelect prompt=" " diff --git a/app/users/edit/template.hbs b/app/users/edit/template.hbs index 2c6b009ce2..d5a019c71c 100644 --- a/app/users/edit/template.hbs +++ b/app/users/edit/template.hbs @@ -11,7 +11,7 @@ {{form.input property="displayName" label=(t 'labels.displayName') class="user-display-name"}} {{form.input property="email" type="email" label=(t 'labels.email') class="user-email"}} {{form.input property="password" type="password" label=(t 'labels.password') class="user-password"}} -
+
{{role-select selection=model.roles content=userRoles action=(action (mut model.roles)) class="user-role"}}
diff --git a/app/visits/edit/template.hbs b/app/visits/edit/template.hbs index 8460cbfe88..cab7d15de0 100644 --- a/app/visits/edit/template.hbs +++ b/app/visits/edit/template.hbs @@ -53,7 +53,7 @@
{{#if isAdmissionVisit}} - {{date-picker model=model property="startDate" label=(t "patients.labels.admissionDate") showTime=true class="col-sm-4 required"}} + {{date-picker model=model property="startDate" label=(t "patients.labels.admissionDate") showTime=true class="col-sm-4 required test-visit-start"}} {{date-picker model=model property="endDate" label=(t "patients.labels.dischargeDate") showTime=true class="col-sm-4"}} {{else}} {{date-picker model=model property="startDate" label=(t "visits.labels.checkInTime") showTime=true class="col-sm-4 required checkin-date"}} diff --git a/package.json b/package.json index aac6b5b1da..33c9d51931 100644 --- a/package.json +++ b/package.json @@ -93,16 +93,16 @@ "hospitalrun-server-routes": "1.0.0-beta", "loader.js": "^4.2.3", "minimatch": "^3.0.2", - "nano": "6.4.3", + "nano": "6.4.4", "pouchdb": "6.3.4", - "pouchdb-adapter-memory": "6.3.4", + "pouchdb-adapter-memory": "6.4.0", "pouchdb-list": "^4.0.0", "pouchdb-users": "^1.0.3", "qunit-dom": "^0.6.2", - "stylelint": "~9.2.0", + "stylelint": "~9.3.0", "stylelint-config-concentric": "^2.0.0", "stylelint-declaration-use-variable": "1.6.1", - "stylelint-scss": "3.0.1", + "stylelint-scss": "3.1.1", "tosource-polyfill": "^0.3.1", "uuid": "^3.0.0", "worker-pouch": "2.1.0" diff --git a/tests/.eslintrc.js b/tests/.eslintrc.js index b855638715..0b29f3743c 100644 --- a/tests/.eslintrc.js +++ b/tests/.eslintrc.js @@ -14,23 +14,8 @@ module.exports = { globals: { '$': true, - 'addOfflineUsersForElectron': true, - 'attachCustomForm': true, - 'authenticateUser': true, - 'checkCustomFormIsDisplayed': true, - 'checkCustomFormIsFilled': true, - 'checkCustomFormIsFilledAndReadonly': true, - 'createCustomFormForType': true, - 'fillCustomForm': true, - 'invalidateSession': true, 'require': true, - 'runWithPouchDump': true, - 'select': true, - 'selectDate': true, - 'typeAheadFillIn': true, 'wait': true, - 'waitToAppear': true, - 'waitToDisappear': true }, rules: { diff --git a/tests/acceptance/admin-test.js b/tests/acceptance/admin-test.js index 2b0219dc92..cfc1df1a94 100644 --- a/tests/acceptance/admin-test.js +++ b/tests/acceptance/admin-test.js @@ -1,10 +1,14 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | admin'); test('visiting /admin', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin'); assert.equal(currentURL(), '/admin'); @@ -20,7 +24,7 @@ test('visiting /admin', function(assert) { }); test('add new lookup value', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin'); assert.equal(currentURL(), '/admin'); @@ -38,7 +42,7 @@ test('add new lookup value', function(assert) { }); test('delete lookup value', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin'); assert.equal(currentURL(), '/admin'); @@ -56,7 +60,7 @@ test('delete lookup value', function(assert) { }); test('Update address options', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin/address'); assert.equal(currentURL(), '/admin/address'); @@ -69,7 +73,7 @@ test('Update address options', function(assert) { }); test('Update header options', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin/print-header'); assert.equal(currentURL(), '/admin/print-header'); @@ -84,7 +88,7 @@ test('Update header options', function(assert) { test('Update workflow options', function(assert) { let selector = 'input[type=checkbox]'; - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin/workflow'); assert.equal(currentURL(), '/admin/workflow', 'Correctly navigated to admin workflow'); diff --git a/tests/acceptance/appointments-test.js b/tests/acceptance/appointments-test.js index e38eb5812f..8f857aac6d 100644 --- a/tests/acceptance/appointments-test.js +++ b/tests/acceptance/appointments-test.js @@ -1,6 +1,12 @@ import { test } from 'qunit'; import moment from 'moment'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import selectDate from 'hospitalrun/tests/helpers/select-date'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; const DATE_TIME_FORMAT = 'l h:mm A'; const DATE_FORMAT = 'l'; @@ -9,7 +15,7 @@ const TIME_FORMAT = 'h:mm'; moduleForAcceptance('Acceptance | appointments'); test('visiting /appointments', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/appointments'); assert.equal(currentURL(), '/appointments'); @@ -19,7 +25,7 @@ test('visiting /appointments', function(assert) { }); test('visiting /appointments/missed', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); let url = '/appointments'; let today = moment(); @@ -38,7 +44,7 @@ test('visiting /appointments/missed', function(assert) { }); test('test appointment for today', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); await visit('/appointments/today'); assert.dom('.appointment-date').doesNotExist('should have 0 appointment today'); @@ -56,7 +62,7 @@ test('test appointment for today', function(assert) { }); test('Creating a new appointment', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); await visit('/appointments/edit/new'); @@ -75,7 +81,7 @@ test('Creating a new appointment', function(assert) { }); test('Creating a new appointment from patient screen', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { let today = moment().startOf('day'); let tomorrow = moment(today).add(24, 'hours'); await authenticateUser(); @@ -106,7 +112,7 @@ test('Creating a new appointment from patient screen', function(assert) { }); test('Change appointment type', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { let today = moment().startOf('day'); await authenticateUser(); await visit('/appointments/edit/new'); @@ -134,7 +140,7 @@ test('Change appointment type', function(assert) { }); test('Checkin to a visit from appointment', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); await createAppointment(assert); await visit('/appointments'); @@ -171,7 +177,7 @@ test('Checkin to a visit from appointment', function(assert) { }); test('Delete an appointment', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); await createAppointment(assert); await visit('/appointments'); @@ -196,7 +202,7 @@ test('Delete an appointment', function(assert) { }); test('Appointment calendar', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); let today = moment().startOf('day'); let later = moment(today).add(1, 'hours'); @@ -225,7 +231,7 @@ test('Appointment calendar', function(assert) { }); test('visiting /appointments/search', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); await createAppointment(assert); @@ -260,7 +266,7 @@ test('visiting /appointments/search', function(assert) { }); test('Theater scheduling', function(assert) { - runWithPouchDump('appointments', async function() { + return runWithPouchDump('appointments', async function() { await authenticateUser(); let later = moment(); diff --git a/tests/acceptance/custom-forms-test.js b/tests/acceptance/custom-forms-test.js index 8467490f38..a95b9f67a7 100644 --- a/tests/acceptance/custom-forms-test.js +++ b/tests/acceptance/custom-forms-test.js @@ -1,5 +1,9 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import { createCustomFormForType } from 'hospitalrun/tests/helpers/scenarios/custom-forms'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | custom forms'); @@ -33,7 +37,7 @@ test('crud operations on custom-forms', function(assert) { await click('button:contains(Preview)'); // Hide preview to reset it back to being closed. } - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/admin/custom-forms'); assert.equal(currentURL(), '/admin/custom-forms', 'Navigated to custom forms index page'); @@ -62,7 +66,7 @@ test('crud operations on custom-forms', function(assert) { }); test('switching between pages with custom forms happens without errors', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await createCustomFormForType('Patient', true); diff --git a/tests/acceptance/imaging-test.js b/tests/acceptance/imaging-test.js index 9c99bbdab0..81d162e437 100644 --- a/tests/acceptance/imaging-test.js +++ b/tests/acceptance/imaging-test.js @@ -1,10 +1,14 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | imaging'); test('visiting /imaging', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/imaging'); assert.equal(currentURL(), '/imaging'); @@ -19,7 +23,7 @@ test('visiting /imaging', function(assert) { }); test('create a new imaging request', (assert) => { - runWithPouchDump('imaging', async function() { + return runWithPouchDump('imaging', async function() { await authenticateUser(); await visit('/imaging/edit/new'); assert.equal(currentURL(), '/imaging/edit/new'); @@ -46,7 +50,7 @@ test('create a new imaging request', (assert) => { }); test('completed requests are displayed', (assert) => { - runWithPouchDump('imaging', async function() { + return runWithPouchDump('imaging', async function() { await authenticateUser(); await visit('/imaging/completed'); assert.equal(currentURL(), '/imaging/completed'); @@ -55,7 +59,7 @@ test('completed requests are displayed', (assert) => { }); test('mark an imaging request as completed', (assert) => { - runWithPouchDump('imaging', async function() { + return runWithPouchDump('imaging', async function() { await authenticateUser(); await visit('/imaging'); assert.equal(currentURL(), '/imaging'); diff --git a/tests/acceptance/incident-test.js b/tests/acceptance/incident-test.js index c9c7cfbdbc..215412c765 100644 --- a/tests/acceptance/incident-test.js +++ b/tests/acceptance/incident-test.js @@ -1,6 +1,11 @@ import moment from 'moment'; import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; const DATE_FORMAT = 'l'; const DATE_TIME_FORMAT = 'l h:mm A'; @@ -15,7 +20,7 @@ const REPORTED_TO = 'Jack Bridges'; moduleForAcceptance('Acceptance | Incidents'); test('Incident category management', function(assert) { - runWithPouchDump('incident', async function() { + return runWithPouchDump('incident', async function() { await authenticateUser(); await visit('/admin/inc-category'); assert.equal(currentURL(), '/admin/inc-category', 'Incident Categories url is correct'); @@ -45,7 +50,7 @@ test('Incident category management', function(assert) { }); test('Incident creation and editing', function(assert) { - runWithPouchDump('incident', async function() { + return runWithPouchDump('incident', async function() { let now = moment(); await authenticateUser(); await visit('/incident'); @@ -186,7 +191,7 @@ test('Incident creation and editing', function(assert) { }); test('Incident deletion', function(assert) { - runWithPouchDump('incident', async function() { + return runWithPouchDump('incident', async function() { await authenticateUser(); await visit('/incident'); assert.equal(currentURL(), '/incident', 'Incident listing url is correct'); diff --git a/tests/acceptance/inventory-test.js b/tests/acceptance/inventory-test.js index 7ab18fa828..5ba8e17420 100644 --- a/tests/acceptance/inventory-test.js +++ b/tests/acceptance/inventory-test.js @@ -1,11 +1,17 @@ import moment from 'moment'; import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import selectDate from 'hospitalrun/tests/helpers/select-date'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | inventory'); test('visiting /inventory', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/inventory'); assert.equal(currentURL(), '/inventory'); @@ -17,7 +23,7 @@ test('visiting /inventory', function(assert) { }); test('Adding a new inventory item', (assert) => { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/inventory/edit/new'); assert.equal(currentURL(), '/inventory/edit/new'); @@ -50,7 +56,7 @@ test('Adding a new inventory item', (assert) => { }); test('Items with negative quantites should not be saved', (assert) => { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/inventory/edit/new'); assert.equal(currentURL(), '/inventory/edit/new'); @@ -87,7 +93,7 @@ test('Items with negative quantites should not be saved', (assert) => { }); test('Visiting /inventory/barcode', (assert) => { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory/listing'); assert.equal(currentURL(), '/inventory/listing'); @@ -99,7 +105,7 @@ test('Visiting /inventory/barcode', (assert) => { }); test('Deleting the last inventory item', (assert) => { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory/listing'); assert.equal(currentURL(), '/inventory/listing'); @@ -116,7 +122,7 @@ test('Deleting the last inventory item', (assert) => { }); test('Creating a new inventory request', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory/request/new'); assert.equal(currentURL(), '/inventory/request/new'); @@ -141,7 +147,7 @@ test('Creating a new inventory request', function(assert) { }); test('Fulfilling an inventory request', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory'); assert.equal(currentURL(), '/inventory'); @@ -165,7 +171,7 @@ test('Fulfilling an inventory request', function(assert) { }); test('Deleting an inventory request', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory'); assert.equal(currentURL(), '/inventory', 'Navigated to /inventory'); @@ -183,7 +189,7 @@ test('Deleting an inventory request', function(assert) { }); test('User with add_inventory_request and without fulfill_inventory rights should not be able to delete others\' requests', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser({ name: 'nurse.mgr', roles: ['Nurse Manager', 'user'], @@ -197,7 +203,7 @@ test('User with add_inventory_request and without fulfill_inventory rights shoul }); test('Receiving inventory', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory/batch/new'); assert.equal(currentURL(), '/inventory/batch/new'); @@ -220,7 +226,7 @@ test('Receiving inventory', function(assert) { }); test('Searching inventory', function(assert) { - runWithPouchDump('inventory', async function() { + return runWithPouchDump('inventory', async function() { await authenticateUser(); await visit('/inventory'); @@ -257,7 +263,7 @@ testSingleDateReportForm('Inventory Valuation'); function testSimpleReportForm(reportName) { test(`${reportName} report can be generated`, function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/inventory/reports'); assert.equal(currentURL(), '/inventory/reports'); @@ -280,7 +286,7 @@ function testSimpleReportForm(reportName) { function testSingleDateReportForm(reportName) { test(`${reportName} report can be generated`, function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/inventory/reports'); assert.equal(currentURL(), '/inventory/reports'); diff --git a/tests/acceptance/invoices-test.js b/tests/acceptance/invoices-test.js index 43e037e53c..58af2e97ac 100644 --- a/tests/acceptance/invoices-test.js +++ b/tests/acceptance/invoices-test.js @@ -1,10 +1,15 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | invoices'); test('visiting /invoices', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices'); assert.equal(currentURL(), '/invoices'); @@ -12,7 +17,7 @@ test('visiting /invoices', function(assert) { }); test('create invoice', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices/edit/new'); assert.equal(currentURL(), '/invoices/edit/new'); @@ -29,7 +34,7 @@ test('create invoice', function(assert) { }); test('print invoice', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { window.print = function() {}; // Disable browser print dialog. await authenticateUser(); await visit('/invoices'); @@ -45,7 +50,7 @@ test('print invoice', function(assert) { // test pricing profile test('pricing profiles', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing/profiles'); assert.equal(find('.btn-primary:contains(+ new item)').length, 1, 'We can add a new pricing profile'); @@ -87,7 +92,7 @@ test('pricing profiles', function(assert) { }); test('delete invoice', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices'); assert.equal(currentURL(), '/invoices'); @@ -107,7 +112,7 @@ test('delete invoice', function(assert) { }); test('add payment', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices'); assert.equal(currentURL(), '/invoices'); @@ -127,7 +132,7 @@ test('add payment', function(assert) { }); test('add deposit', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices'); assert.equal(currentURL(), '/invoices'); @@ -145,7 +150,7 @@ test('add deposit', function(assert) { }); test('cashier role', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser({ name: 'cashier@hospitalrun.io', roles: ['Cashier', 'user'], @@ -169,7 +174,7 @@ test('cashier role', function(assert) { }); test('Searching invoices', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/invoices'); @@ -192,3 +197,143 @@ test('Searching invoices', function(assert) { assert.dom('.invoice-number').doesNotExist('There is no search result'); }); }); + +test('Delete invoice line item detail', function(assert) { + return runWithPouchDump('billing', async function() { + await authenticateUser(); + await visit('/invoices/edit/new'); + assert.equal(currentURL(), '/invoices/edit/new'); + + await typeAheadFillIn('.invoice-patient', 'Joe Bagadonuts - TCH 00001'); + await waitToAppear('.invoice-visit option:contains((Admission))'); + await select('.invoice-visit', '(Admission)'); + + await click('.glyphicon-plus'); + await click('button:contains(Add Charge)'); + + // delete the first line item detail (second Delete button from top, as the very first is for the line item itself) + await click($('button:contains(Delete):eq(1)')[0]); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('Delete Charge', 'Delete Charge modal displays'); + await click('.modal-footer button:contains(Ok)'); + await waitToDisappear('.modal-dialog'); + + // topmost detail showing should now be the blank one we added at beginning of this test + assert.equal(find('.detail-quantity').val(), '', 'First line item detail no longer appears.'); + }); +}); + +test('Delete invoice line item', function(assert) { + return runWithPouchDump('billing', async function() { + await authenticateUser(); + await visit('/invoices/edit/new'); + assert.equal(currentURL(), '/invoices/edit/new'); + + await typeAheadFillIn('.invoice-patient', 'Joe Bagadonuts - TCH 00001'); + await waitToAppear('.invoice-visit option:contains((Admission))'); + await select('.invoice-visit', '(Admission)'); + + await click('button:contains(Delete)'); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('Delete Line Item', 'Delete Line Item modal displays'); + await click('.modal-footer button:contains(Ok)'); + await waitToDisappear('.modal-dialog'); + assert.equal(find('.item-name').val(), 'Pharmacy', 'First line item no longer appears.'); + }); +}); + +test('Calculate totals', function(assert) { + return runWithPouchDump('billing', async function() { + await authenticateUser(); + await visit('/invoices/edit/new'); + assert.equal(currentURL(), '/invoices/edit/new'); + + await typeAheadFillIn('.invoice-patient', 'Joe Bagadonuts - TCH 00001'); + await waitToAppear('.invoice-visit option:contains((Admission))'); + await select('.invoice-visit', '(Admission)'); + + // first item, discounts and details + await fillIn('.item-discount:eq(0)', '1'); + await fillIn('.item-national-insurance:eq(0)', '2'); + await fillIn('.item-private-insurance:eq(0)', '3'); + await click('.glyphicon-plus'); + await fillIn('.detail-price:eq(0)', '3'); + await click('button:contains(Add Charge)'); + await fillIn($('.detail-quantity:eq(1)'), '60'); + await fillIn($('.detail-price:eq(1)'), '4'); + + // second item, discounts and details + await click('.glyphicon-plus'); + await fillIn($('.item-discount:eq(1)'), '4'); + await fillIn($('.item-national-insurance:eq(1)'), '6'); + await fillIn($('.item-private-insurance:eq(1)'), '1'); + await fillIn($('.detail-price:eq(2)'), '14'); + + // add a payment + await click('button:contains(Add Payment)'); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('Add Payment', 'Add Payment modal displays'); + await fillIn('.payment-amount input', '100'); + await click('.update-payment-btn'); + await waitToAppear('.modal-title:contains(Payment Added)'); + assert.dom('.modal-title').hasText('Payment Added', 'Payment was saved successfully'); + await click('.modal-footer button:contains(Ok)'); + await waitToDisappear('.modal-dialog'); + + // total for first 2 items (2 details per item) + let expected = +$('.detail-amount-owed:eq(0)').text() + +$('.detail-amount-owed:eq(1)').text(); + assert.dom($('.item-total:eq(0)')[0]).hasText(expected.toString(), 'First item total is correct'); + expected = +$('.detail-amount-owed:eq(2)').text() + +$('.detail-amount-owed:eq(3)').text(); + assert.dom($('.item-total:eq(1)')[0]).hasText(expected.toString(), 'Second item total is correct'); + + // amount owed for first 2 items (2 details per item) + expected = +$('.item-total:eq(0)').text() - (+$('.item-discount:eq(0)').val() + +$('.item-national-insurance:eq(0)').val() + +$('.item-private-insurance:eq(0)').val()); + assert.dom($('.item-amount-owed:eq(0)')[0]).hasText(expected.toString(), 'First item amount owed is correct'); + expected = +$('.item-total:eq(1)').text() - (+$('.item-discount:eq(1)').val() + +$('.item-national-insurance:eq(1)').val() + +$('.item-private-insurance:eq(1)').val()); + assert.dom($('.item-amount-owed:eq(1)')[0]).hasText(expected.toString(), 'Second item amount owed is correct'); + + // detail amount owed for first 4 details + expected = $('.detail-quantity:eq(0)').val() * $('.detail-price:eq(0)').val(); + assert.dom($('.detail-amount-owed:eq(0)')[0]).hasText(expected.toString(), 'First detail amount owed is correct'); + expected = $('.detail-quantity:eq(1)').val() * $('.detail-price:eq(1)').val(); + assert.dom($('.detail-amount-owed:eq(1)')[0]).hasText(expected.toString(), 'Second detail amount owed is correct'); + expected = $('.detail-quantity:eq(2)').val() * $('.detail-price:eq(2)').val(); + assert.dom($('.detail-amount-owed:eq(2)')[0]).hasText(expected.toString(), 'Third detail amount owed is correct'); + expected = $('.detail-quantity:eq(3)').val() * $('.detail-price:eq(3)').val(); + assert.dom($('.detail-amount-owed:eq(3)')[0]).hasText(expected.toString(), 'Fourth detail amount owed is correct'); + + // category group and invoice total (same thing as this test only uses 1 category) + expected = +$('.item-total:eq(0)').text() + +$('.item-total:eq(1)').text() + +$('.item-total:eq(2)').text() + +$('.item-total:eq(3)').text(); + assert.dom('.category-group-total').hasText(expected.toString(), 'Category group total is correct'); + expected = +$('.item-total:eq(0)').text() + +$('.item-total:eq(1)').text() + +$('.item-total:eq(2)').text() + +$('.item-total:eq(3)').text(); + assert.dom('.total').hasText(expected.toString(), 'Total is correct'); + + // category group and invoice discount + expected = +$('.item-discount:eq(0)').val() + +$('.item-discount:eq(1)').val(); + assert.dom('.category-group-discount').hasText(expected.toString(), 'Category group discount is correct'); + expected = +$('.item-discount:eq(0)').val() + +$('.item-discount:eq(1)').val(); + assert.dom('.discount').hasText(expected.toString(), 'Discount is correct'); + + // category group and invoice national insurance + expected = +$('.item-national-insurance:eq(0)').val() + +$('.item-national-insurance:eq(1)').val(); + assert.dom('.category-group-national-insurance').hasText(expected.toString(), 'Category group national insurance is correct'); + expected = +$('.item-national-insurance:eq(0)').val() + +$('.item-national-insurance:eq(1)').val(); + assert.dom('.national-insurance').hasText(expected.toString(), 'National insurance is correct'); + + // category group and invoice private insurance + expected = +$('.item-private-insurance:eq(0)').val() + +$('.item-private-insurance:eq(1)').val(); + assert.dom('.category-group-private-insurance').hasText(expected.toString(), 'Category group private insurance is correct'); + expected = +$('.item-private-insurance:eq(0)').val() + +$('.item-private-insurance:eq(1)').val(); + assert.dom('.private-insurance').hasText(expected.toString(), 'Private insurance is correct'); + + // category group and invoice amount owed + expected = +$('.item-amount-owed:eq(0)').text() + +$('.item-amount-owed:eq(1)').text() + +$('.item-amount-owed:eq(2)').text() + +$('.item-amount-owed:eq(3)').text(); + assert.dom('.category-group-amount-owed').hasText(expected.toString(), 'Category group amount owed is correct'); + expected = +$('.item-amount-owed:eq(0)').text() + +$('.item-amount-owed:eq(1)').text() + +$('.item-amount-owed:eq(2)').text() + +$('.item-amount-owed:eq(3)').text(); + assert.dom('.final-patient-responsibility').hasText(expected.toString(), 'Final patient responsibility is correct'); + + // remaining balance after paid total is taken off + expected = +$('.final-patient-responsibility:eq(0)').text() - Math.abs(+$('.paid-total:eq(0)').text()); + assert.dom('.remaining-balance').hasText(expected.toString(), 'Remaining balance is correct'); + }); +}); \ No newline at end of file diff --git a/tests/acceptance/labs-test.js b/tests/acceptance/labs-test.js index a3892011b7..b7f6684398 100644 --- a/tests/acceptance/labs-test.js +++ b/tests/acceptance/labs-test.js @@ -1,10 +1,22 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import { + attachCustomForm, + createCustomFormForType, + checkCustomFormIsDisplayed, + fillCustomForm, + checkCustomFormIsFilled, + checkCustomFormIsFilledAndReadonly +} from 'hospitalrun/tests/helpers/scenarios/custom-forms'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | labs'); test('visiting /labs', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/labs'); assert.equal(currentURL(), '/labs'); @@ -14,7 +26,7 @@ test('visiting /labs', function(assert) { }); test('Adding a new lab request', function(assert) { - runWithPouchDump('labs', async function() { + return runWithPouchDump('labs', async function() { await authenticateUser(); await visit('/labs'); @@ -40,7 +52,7 @@ test('Adding a new lab request', function(assert) { }); test('Marking a lab request as completed', function(assert) { - runWithPouchDump('labs', async function() { + return runWithPouchDump('labs', async function() { await authenticateUser(); await visit('/labs/completed'); assert.dom('.alert-info').hasText('No completed items found.', 'No completed requests are displayed'); @@ -59,7 +71,7 @@ test('Marking a lab request as completed', function(assert) { }); test('Lab with always included custom form', function(assert) { - runWithPouchDump('labs', async function() { + return runWithPouchDump('labs', async function() { await authenticateUser(); await createCustomFormForType('Lab', true); @@ -104,7 +116,7 @@ test('Lab with always included custom form', function(assert) { }); test('Lab with additional form', function(assert) { - runWithPouchDump('labs', async function() { + return runWithPouchDump('labs', async function() { await authenticateUser(); await createCustomFormForType('Lab'); @@ -151,7 +163,7 @@ test('Lab with additional form', function(assert) { }); test('Lab with always included custom form and additional form', function(assert) { - runWithPouchDump('labs', async function() { + return runWithPouchDump('labs', async function() { await authenticateUser(); await createCustomFormForType('Lab', true); diff --git a/tests/acceptance/language-select-test.js b/tests/acceptance/language-select-test.js index ebbf309c2a..096475afa7 100644 --- a/tests/acceptance/language-select-test.js +++ b/tests/acceptance/language-select-test.js @@ -1,5 +1,10 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import addOfflineUsersForElectron from 'hospitalrun/tests/helpers/add-offline-users-for-electron'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser, invalidateSession } from 'hospitalrun/tests/helpers/authenticate-user'; import english from 'hospitalrun/locales/en/translations'; import french from 'hospitalrun/locales/fr/translations'; @@ -8,7 +13,7 @@ import german from 'hospitalrun/locales/de/translations'; moduleForAcceptance('Acceptance | language dropdown'); test('setting a language preference persists after logout', (assert) => { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await addOfflineUsersForElectron(); await authenticateUser(); @@ -30,7 +35,7 @@ test('setting a language preference persists after logout', (assert) => { }); test('different users can have different language preferences on the same browser', (assert) => { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await addOfflineUsersForElectron(); await authenticateUser(); diff --git a/tests/acceptance/login-test.js b/tests/acceptance/login-test.js index 82f0aec34a..4e65a1385e 100644 --- a/tests/acceptance/login-test.js +++ b/tests/acceptance/login-test.js @@ -1,40 +1,40 @@ -import { run } from '@ember/runloop'; -import { module, test } from 'qunit'; -import startApp from 'hospitalrun/tests/helpers/start-app'; +import { test } from 'qunit'; import FakeServer, { stubRequest } from 'ember-cli-fake-server'; -module('Acceptance | login', { +import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; + +moduleForAcceptance('Acceptance | login', { beforeEach() { FakeServer.start(); - this.application = startApp(); }, afterEach() { FakeServer.stop(); - run(this.application, 'destroy'); } }); test('visiting / redirects user to login', function(assert) { assert.expect(1); - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await visit('/'); assert.equal(currentURL(), '/login'); }); }); test('login with correct credentials', function(assert) { - login(assert); + return login(assert); }); test('login with correct credentials but space around username', function(assert) { - login(assert, true); + return login(assert, true); }); test('incorrect credentials shows an error message on the screen', function(assert) { if (!window.ELECTRON) { assert.expect(2); } - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await visit('/'); let errorMessage = 'Username or password is incorrect.'; @@ -57,7 +57,7 @@ function login(assert, spaceAroundUsername) { if (!window.ELECTRON) { assert.expect(2); } - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await visit('/login'); stubRequest('post', '/auth/login', function(request) { diff --git a/tests/acceptance/medication-test.js b/tests/acceptance/medication-test.js index 855bb15901..a2b4d8866a 100644 --- a/tests/acceptance/medication-test.js +++ b/tests/acceptance/medication-test.js @@ -1,10 +1,14 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | medication'); test('visiting /medication', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/medication'); @@ -18,7 +22,7 @@ test('visiting /medication', function(assert) { }); test('creating a new medication request', function(assert) { - runWithPouchDump('medication', async function() { + return runWithPouchDump('medication', async function() { await authenticateUser(); await visit('/medication/edit/new'); assert.equal(currentURL(), '/medication/edit/new'); @@ -41,7 +45,7 @@ test('creating a new medication request', function(assert) { }); test('fulfilling a medication request', function(assert) { - runWithPouchDump('medication', async function() { + return runWithPouchDump('medication', async function() { await authenticateUser(); await visit('/medication'); await click('button:contains(Fulfill)'); @@ -62,7 +66,7 @@ test('fulfilling a medication request', function(assert) { }); test('complete a medication request', function(assert) { - runWithPouchDump('medication', async function() { + return runWithPouchDump('medication', async function() { await authenticateUser(); await visit('/medication/completed'); assert.dom('.clickable').doesNotExist('Should have 0 completed request'); @@ -84,7 +88,7 @@ test('complete a medication request', function(assert) { }); test('returning medication', function(assert) { - runWithPouchDump('medication', async function() { + return runWithPouchDump('medication', async function() { await authenticateUser(); await visit('/medication/return/new'); assert.equal(currentURL(), '/medication/return/new'); @@ -103,7 +107,7 @@ test('returning medication', function(assert) { }); test('Searching medications', function(assert) { - runWithPouchDump('medication', async function() { + return runWithPouchDump('medication', async function() { await authenticateUser(); await visit('/medication'); diff --git a/tests/acceptance/navigation-test.js b/tests/acceptance/navigation-test.js index 97d6af75c6..fb30c5a681 100644 --- a/tests/acceptance/navigation-test.js +++ b/tests/acceptance/navigation-test.js @@ -1,22 +1,22 @@ -import { run } from '@ember/runloop'; -import { module, test } from 'qunit'; -import startApp from 'hospitalrun/tests/helpers/start-app'; +import { test } from 'qunit'; import FakeServer, { stubRequest } from 'ember-cli-fake-server'; +import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; -module('Acceptance | navigation', { +moduleForAcceptance('Acceptance | navigation', { beforeEach() { FakeServer.start(); - this.application = startApp(); }, afterEach() { FakeServer.stop(); - run(this.application, 'destroy'); } }); test('about dialog', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/'); @@ -34,7 +34,7 @@ test('about dialog', function(assert) { }); test('search text clears after search', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients'); @@ -46,7 +46,7 @@ test('search text clears after search', function(assert) { }); test('search text clears after selecting new nav item', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients'); diff --git a/tests/acceptance/operative-test.js b/tests/acceptance/operative-test.js index 0d41b515b3..dd3cf7f222 100644 --- a/tests/acceptance/operative-test.js +++ b/tests/acceptance/operative-test.js @@ -1,5 +1,9 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; const ADDITIONAL_NOTES = 'Additional Notes here'; const CASE_COMPLEXITY = 7; @@ -11,7 +15,7 @@ const PROCEDURE_HIP = 'hip adductor release'; moduleForAcceptance('Acceptance | Operative Plan and Operation Report'); test('Plan and report creation', function(assert) { - runWithPouchDump('operative', async function() { + return runWithPouchDump('operative', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients', 'Patients listing url is correct'); diff --git a/tests/acceptance/outpatient-test.js b/tests/acceptance/outpatient-test.js index a56a89f850..58f830557b 100644 --- a/tests/acceptance/outpatient-test.js +++ b/tests/acceptance/outpatient-test.js @@ -1,11 +1,17 @@ import { test } from 'qunit'; import moment from 'moment'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import selectDate from 'hospitalrun/tests/helpers/select-date'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | outpatient'); test('Check In/Check Out Existing outpatient', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients/outpatient'); assert.equal(currentURL(), '/patients/outpatient', 'Outpatient url is correct'); @@ -45,7 +51,7 @@ test('Check In/Check Out Existing outpatient', function(assert) { }); test('Check In/Check Out new outpatient', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { let visitDate = moment('2015-10-01'); let visitLocation = 'Outpatient Followup'; await authenticateUser(); diff --git a/tests/acceptance/patient-notes-test.js b/tests/acceptance/patient-notes-test.js index f0937a94d6..858a10b3aa 100644 --- a/tests/acceptance/patient-notes-test.js +++ b/tests/acceptance/patient-notes-test.js @@ -1,10 +1,14 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; +import select from 'hospitalrun/tests/helpers/select'; moduleForAcceptance('Acceptance | patient notes'); test('patient notes crud testing', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/edit/new'); assert.equal(currentURL(), '/patients/edit/new'); @@ -60,3 +64,69 @@ test('patient notes crud testing', function(assert) { assert.equal(find('#visit-notes table tr td:contains(This is an updated note.)').length, 0, 'Successfully deleted note.'); }); }); + +test('add a note from Edit Patient', function(assert) { + return runWithPouchDump('default', async function() { + await authenticateUser(); + await visit('/patients/edit/new'); + assert.equal(currentURL(), '/patients/edit/new'); + await fillIn('.test-first-name input', 'John'); + await fillIn('.test-last-name input', 'Doe'); + await click('.panel-footer button:contains(Add)'); + await waitToAppear('.message:contains(The patient record for John Doe has been saved)'); + assert.dom('.message').hasText('The patient record for John Doe has been saved.'); + + await waitToAppear('.patient-summary'); + assert.dom('.patient-summary').exists(); + + await click('[data-test-selector=visits-tab]'); + assert.dom('#visits').exists(); + + // add a first visit with type 'Admission' + await click('button:contains(New Visit)'); + assert.equal(currentURL(), '/visits/edit/new', 'Now in add visiting information route'); + await select('.visit-type', 'Admission'); + await fillIn('.test-visit-start input', '5/20/2017'); + await click('.panel-footer button:contains(Add)'); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('Visit Saved', 'New visit has been saved'); + await click('button:contains(Ok)'); + await click('button:contains(Return)'); + + // add a second visit with type 'Lab' + await click('button:contains(New Visit)'); + assert.equal(currentURL(), '/visits/edit/new', 'Now in add visiting information route'); + await select('.visit-type', 'Lab'); + await fillIn('.checkin-date input', '5/20/2017'); + await click('.panel-footer button:contains(Add)'); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('Visit Saved', 'New visit has been saved'); + await click('button:contains(Ok)'); + + // go back to 'Edit Patient' + await click('button:contains(Return)'); + assert.dom('.view-current-title').hasText('Edit Patient'); + + // add a note to the 'Lab' visit + await click('button:contains(New Note)'); + await waitToAppear('.modal-dialog'); + assert.dom('.modal-title').hasText('New Note for John Doe', 'Notes modal appeared'); + await fillIn('.test-note-content textarea', 'This is a note.'); + await select('.test-note-visit', '5/20/2017 (Lab)'); + await click('.modal-footer button:contains(Add)'); + await waitToDisappear('.modal-dialog'); + + await waitToAppear('.ph-visit-type'); + await click('.ph-visit-type:contains(Admission)'); + await click('[data-test-selector=notes-tab]'); + await waitToAppear('#visit-notes table'); + assert.equal(find('#visit-notes table tr td:contains(This is a note.)').length, 0, 'Note is not attached to the "Admission" visit.'); + await click('button:contains(Return)'); + + await waitToAppear('.ph-visit-type'); + await click('.ph-visit-type:contains(Lab)'); + await click('[data-test-selector=notes-tab]'); + await waitToAppear('#visit-notes table'); + assert.equal(find('#visit-notes table tr td:contains(This is a note.)').length, 1, 'Note is attached to the "Lab" visit.'); + }); +}); diff --git a/tests/acceptance/patients-test.js b/tests/acceptance/patients-test.js index f3a4cb34d9..5936b6a28a 100644 --- a/tests/acceptance/patients-test.js +++ b/tests/acceptance/patients-test.js @@ -1,10 +1,14 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | patients'); test('visiting /patients route', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients'); @@ -20,7 +24,7 @@ test('visiting /patients route', function(assert) { }); test('View reports tab', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/reports'); @@ -47,7 +51,7 @@ reportNames.forEach((reportName) => { }); test('View reports tab | Patient Status', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/reports'); await select('[data-test-selector="select-report-type"] select', 'Patient Status'); @@ -62,7 +66,7 @@ test('View reports tab | Patient Status', function(assert) { }); test('Testing admitted patient', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients/admitted'); assert.equal(currentURL(), '/patients/admitted'); @@ -84,7 +88,7 @@ test('Testing admitted patient', function(assert) { }); test('Adding a new patient record', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/edit/new'); assert.equal(currentURL(), '/patients/edit/new'); @@ -102,7 +106,7 @@ test('Adding a new patient record', function(assert) { }); test('Delete a patient record', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients', 'Patient listing url is correct'); @@ -124,7 +128,7 @@ test('Delete a patient record', function(assert) { }); test('Searching patients', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients'); @@ -147,7 +151,7 @@ test('Searching patients', function(assert) { function testSimpleReportForm(reportName) { test(`View reports tab | ${reportName} shows start and end dates`, function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/reports'); await select('[data-test-selector="select-report-type"] select', reportName); @@ -164,7 +168,7 @@ function testSimpleReportForm(reportName) { function testExportReportName(reportName) { test(`View reports tab | Export reports name for ${reportName} shows report name, start and end dates`, (assert) => { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await visit('/patients/reports'); await select('[data-test-selector="select-report-type"] select', reportName); diff --git a/tests/acceptance/pricing-test.js b/tests/acceptance/pricing-test.js index ee34f73d2d..85f19a8abb 100644 --- a/tests/acceptance/pricing-test.js +++ b/tests/acceptance/pricing-test.js @@ -1,8 +1,12 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; function verifyPricingLists(path, includesPrices, excludesPrices, assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit(path); assert.equal(currentURL(), path); @@ -24,7 +28,7 @@ test('visiting /pricing', function(assert) { 'Leg Casting', 'Gauze pad' ]; - verifyPricingLists('/pricing', includesPrices, [], assert); + return verifyPricingLists('/pricing', includesPrices, [], assert); }); test('visiting /pricing/imaging', function(assert) { @@ -36,7 +40,7 @@ test('visiting /pricing/imaging', function(assert) { let includesPrices = [ 'Xray Hand' ]; - verifyPricingLists('/pricing/imaging', includesPrices, excludesPrices, assert); + return verifyPricingLists('/pricing/imaging', includesPrices, excludesPrices, assert); }); @@ -49,7 +53,7 @@ test('visiting /pricing/lab', function(assert) { let includesPrices = [ 'Blood test' ]; - verifyPricingLists('/pricing/lab', includesPrices, excludesPrices, assert); + return verifyPricingLists('/pricing/lab', includesPrices, excludesPrices, assert); }); test('visiting /pricing/procedure', function(assert) { @@ -61,7 +65,7 @@ test('visiting /pricing/procedure', function(assert) { let includesPrices = [ 'Leg Casting' ]; - verifyPricingLists('/pricing/procedure', includesPrices, excludesPrices, assert); + return verifyPricingLists('/pricing/procedure', includesPrices, excludesPrices, assert); }); test('visiting /pricing/ward', function(assert) { @@ -73,11 +77,11 @@ test('visiting /pricing/ward', function(assert) { let includesPrices = [ 'Gauze pad' ]; - verifyPricingLists('/pricing/ward', includesPrices, excludesPrices, assert); + return verifyPricingLists('/pricing/ward', includesPrices, excludesPrices, assert); }); test('create new price', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing'); await click('button:contains(+ new item)'); @@ -105,7 +109,7 @@ test('create new price', function(assert) { }); test('delete price', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing/lab'); assert.equal(currentURL(), '/pricing/lab'); @@ -125,7 +129,7 @@ test('delete price', function(assert) { }); test('create new pricing profile', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing/profiles'); assert.equal(currentURL(), '/pricing/profiles'); @@ -146,7 +150,7 @@ test('create new pricing profile', function(assert) { }); test('delete pricing profile', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing/profiles'); assert.equal(currentURL(), '/pricing/profiles'); @@ -163,7 +167,7 @@ test('delete pricing profile', function(assert) { }); test('Searching pricing', function(assert) { - runWithPouchDump('billing', async function() { + return runWithPouchDump('billing', async function() { await authenticateUser(); await visit('/pricing'); diff --git a/tests/acceptance/procedure-test.js b/tests/acceptance/procedure-test.js index ff6343fcff..3a7a8a0cc7 100644 --- a/tests/acceptance/procedure-test.js +++ b/tests/acceptance/procedure-test.js @@ -1,5 +1,9 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; moduleForAcceptance('Acceptance | procedures'); @@ -101,7 +105,7 @@ testWithVisit('Delete procedure', async function(assert) { function testWithVisit(testLabel, testFunction) { test(testLabel, function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients', 'Patient url is correct'); diff --git a/tests/acceptance/role-test.js b/tests/acceptance/role-test.js index 9b6085c7ee..33eb6e9daf 100644 --- a/tests/acceptance/role-test.js +++ b/tests/acceptance/role-test.js @@ -1,11 +1,15 @@ import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser, invalidateSession } from 'hospitalrun/tests/helpers/authenticate-user'; import { PREDEFINED_USER_ROLES } from 'hospitalrun/mixins/user-roles'; moduleForAcceptance('Acceptance | roles'); test('visiting /admin/roles', function(assert) { - runWithPouchDump('admin', async function() { + return runWithPouchDump('admin', async function() { await authenticateUser(); await visit('/admin/roles'); assert.equal(currentURL(), '/admin/roles'); @@ -44,7 +48,7 @@ test('visiting /admin/roles', function(assert) { PREDEFINED_USER_ROLES.forEach((role) => { if (role.defaultRoute && role.name !== 'User Administrator') { test(`Testing User Role homescreen for ${role.name}`, (assert) =>{ - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser({ roles: role.roles, role: role.name, diff --git a/tests/acceptance/users-test.js b/tests/acceptance/users-test.js index 940cc39ad6..64c26a6d5f 100644 --- a/tests/acceptance/users-test.js +++ b/tests/acceptance/users-test.js @@ -1,9 +1,14 @@ -import { run } from '@ember/runloop'; import RSVP from 'rsvp'; import FakeServer, { stubRequest } from 'ember-cli-fake-server'; -import startApp from 'hospitalrun/tests/helpers/start-app'; import { PREDEFINED_USER_ROLES } from 'hospitalrun/mixins/user-roles'; -import { module, test } from 'qunit'; +import { test } from 'qunit'; + +import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import addOfflineUsersForElectron from 'hospitalrun/tests/helpers/add-offline-users-for-electron'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; const MOCK_USER_DATA = [{ 'id': 'org.couchdb.user:hradmin', @@ -64,20 +69,18 @@ function addAllUsers(assert) { return RSVP.resolve(); } -module('Acceptance | users', { +moduleForAcceptance('Acceptance | users', { beforeEach() { FakeServer.start(); - this.application = startApp(); }, afterEach() { FakeServer.stop(); - run(this.application, 'destroy'); } }); test('visiting /admin/users', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { let role = PREDEFINED_USER_ROLES.findBy('name', 'User Administrator'); await authenticateUser({ roles: role.roles, @@ -97,7 +100,7 @@ test('visiting /admin/users', function(assert) { }); test('create new user', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await addAllUsers(assert); @@ -137,7 +140,7 @@ test('create new user', function(assert) { }); test('delete user', function(assert) { - runWithPouchDump('default', async function() { + return runWithPouchDump('default', async function() { await authenticateUser(); await addAllUsers(assert); diff --git a/tests/acceptance/visit-test.js b/tests/acceptance/visit-test.js index c5179eff40..d96be72a41 100644 --- a/tests/acceptance/visit-test.js +++ b/tests/acceptance/visit-test.js @@ -2,6 +2,17 @@ import { isEmpty } from '@ember/utils'; import moment from 'moment'; import { test } from 'qunit'; import moduleForAcceptance from 'hospitalrun/tests/helpers/module-for-acceptance'; +import runWithPouchDump from 'hospitalrun/tests/helpers/run-with-pouch-dump'; +import select from 'hospitalrun/tests/helpers/select'; +import typeAheadFillIn from 'hospitalrun/tests/helpers/typeahead-fillin'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; +import { authenticateUser } from 'hospitalrun/tests/helpers/authenticate-user'; +import { + createCustomFormForType, + attachCustomForm, + fillCustomForm, + checkCustomFormIsFilledAndReadonly +} from 'hospitalrun/tests/helpers/scenarios/custom-forms'; const LOCATION = 'Springfield Hospital'; const EXAMINER = 'Sarah Kearney'; @@ -39,7 +50,7 @@ const opdReportTestCases = { moduleForAcceptance('Acceptance | visits'); test('Add admission visit', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await addVisit(assert); await addAdmissionData(assert); @@ -52,7 +63,7 @@ test('Add admission visit', function(assert) { for (let testCase in opdReportTestCases) { test(testCase, function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); for (let f of (opdReportTestCases[testCase].customForms || [])) { @@ -70,7 +81,7 @@ for (let testCase in opdReportTestCases) { } test('Edit visit', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients', 'Patient url is correct'); @@ -165,7 +176,7 @@ test('Edit visit', function(assert) { }); test('Delete visit', function(assert) { - runWithPouchDump('patient', async function() { + return runWithPouchDump('patient', async function() { await authenticateUser(); await visit('/patients'); assert.equal(currentURL(), '/patients', 'Patient url is correct'); diff --git a/tests/helpers/add-offline-users-for-electron.js b/tests/helpers/add-offline-users-for-electron.js index 25f893329a..f2723cb5f1 100644 --- a/tests/helpers/add-offline-users-for-electron.js +++ b/tests/helpers/add-offline-users-for-electron.js @@ -1,4 +1,3 @@ -import { registerAsyncHelper } from '@ember/test'; import PouchDB from 'pouchdb'; import PouchAdapterMemory from 'npm:pouchdb-adapter-memory'; @@ -42,18 +41,17 @@ const MOCK_USER_DATA = [{ } }]; -export default registerAsyncHelper('addOfflineUsersForElectron', function() { +async function addOfflineUsersForElectron() { + await wait(); if (window.ELECTRON) { - return wait().then(() => { - PouchDB.plugin(PouchAdapterMemory); - let usersDB = new PouchDB('_users', { - adapter: 'memory' - }); - let [, joeUser] = MOCK_USER_DATA; // hradmin already added by run-with-pouch-dump - delete joeUser.doc._rev; - return usersDB.put(joeUser.doc); + PouchDB.plugin(PouchAdapterMemory); + let usersDB = new PouchDB('_users', { + adapter: 'memory' }); - } else { - return wait(); + let [, joeUser] = MOCK_USER_DATA; // hradmin already added by run-with-pouch-dump + delete joeUser.doc._rev; + return usersDB.put(joeUser.doc); } -}); +} + +export default addOfflineUsersForElectron; diff --git a/tests/helpers/authenticate-user.js b/tests/helpers/authenticate-user.js index a9ff0a68ef..bdaf30e9ec 100644 --- a/tests/helpers/authenticate-user.js +++ b/tests/helpers/authenticate-user.js @@ -1,19 +1,21 @@ -import { registerHelper } from '@ember/test'; import { merge } from '@ember/polyfills'; -import { authenticateSession } from 'hospitalrun/tests/helpers/ember-simple-auth'; -import { invalidateSession } from 'hospitalrun/tests/helpers/ember-simple-auth'; +import { getContext } from '@ember/test-helpers'; +import { + authenticateSession, + invalidateSession as _invalidateSession +} from 'hospitalrun/tests/helpers/ember-simple-auth'; -registerHelper('authenticateUser', function(app, attrs = {}) { +export function authenticateUser(attrs = {}) { let expiresAt = new Date().getTime() + 600000; - authenticateSession(app, merge({ + authenticateSession(getContext().application, merge({ name: 'hradmin', roles: ['System Administrator', 'admin', 'user'], expires_at: expiresAt, role: 'System Administrator', prefix: 'p1' }, attrs)); -}); +} -registerHelper('invalidateSession', function(app) { - invalidateSession(app); -}); +export function invalidateSession() { + _invalidateSession(getContext().application); +} diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js index 90a93bac2b..a16b525ea5 100644 --- a/tests/helpers/module-for-acceptance.js +++ b/tests/helpers/module-for-acceptance.js @@ -1,5 +1,6 @@ import { module } from 'qunit'; import { resolve } from 'rsvp'; +import { setContext, unsetContext } from '@ember/test-helpers'; import startApp from '../helpers/start-app'; import destroyApp from '../helpers/destroy-app'; @@ -8,6 +9,8 @@ export default function(name, options = {}) { beforeEach() { this.application = startApp(); + setContext(this); + if (options.beforeEach) { return options.beforeEach.apply(this, arguments); } @@ -15,7 +18,10 @@ export default function(name, options = {}) { afterEach() { let afterEach = options.afterEach && options.afterEach.apply(this, arguments); - return resolve(afterEach).then(() => destroyApp(this.application)); + return resolve(afterEach).then(() => { + unsetContext(); + return destroyApp(this.application); + }); } }); } diff --git a/tests/helpers/run-with-pouch-dump.js b/tests/helpers/run-with-pouch-dump.js index 4ac8e0497c..b59ed3c445 100644 --- a/tests/helpers/run-with-pouch-dump.js +++ b/tests/helpers/run-with-pouch-dump.js @@ -1,5 +1,5 @@ /* jshint ignore:start */ -import { registerAsyncHelper } from '@ember/test'; +import { getContext } from '@ember/test-helpers'; import { Promise as EmberPromise, all } from 'rsvp'; import { set, get } from '@ember/object'; @@ -36,7 +36,7 @@ function destroyDatabases(dbs) { return all(destroyQueue); } -async function runWithPouchDumpAsyncHelper(app, dumpName, functionToRun) { +async function runWithPouchDump(dumpName, functionToRun) { PouchDB.plugin(PouchAdapterMemory); PouchDB.plugin(PouchDBUsers); @@ -123,8 +123,9 @@ async function runWithPouchDumpAsyncHelper(app, dumpName, functionToRun) { } }); - app.__deprecatedInstance__.register('service:config', InMemoryConfigService); - app.__deprecatedInstance__.register('service:database', InMemoryDatabaseService); + let owner = getContext().application.__deprecatedInstance__; + owner.register('service:config', InMemoryConfigService); + owner.register('service:database', InMemoryDatabaseService); await promise; @@ -150,5 +151,6 @@ async function runWithPouchDumpAsyncHelper(app, dumpName, functionToRun) { } } -registerAsyncHelper('runWithPouchDump', runWithPouchDumpAsyncHelper); +export default runWithPouchDump; + /* jshint ignore:end */ diff --git a/tests/helpers/scenarios/custom-forms.js b/tests/helpers/scenarios/custom-forms.js index 20513f0937..1268becbc0 100644 --- a/tests/helpers/scenarios/custom-forms.js +++ b/tests/helpers/scenarios/custom-forms.js @@ -1,176 +1,142 @@ -import { registerAsyncHelper } from '@ember/test'; +import select from 'hospitalrun/tests/helpers/select'; +import { waitToAppear, waitToDisappear } from 'hospitalrun/tests/helpers/wait-to-appear'; const crusts = ['Thin', 'Deep Dish', 'Flatbread']; const desserts = ['Ice Cream', 'Cookies', 'Cake']; const toppings = ['Cheese', 'Pepperoni', 'Mushrooms']; const header = ['______________________________']; -registerAsyncHelper('createCustomFormForType', function(app, formType, alwaysInclude, assert) { - function addField(fieldType, label, values) { - click('button:contains(Add Field)'); - waitToAppear('.modal-dialog'); - andThen(function() { - if (assert) { - assert.dom('.modal-title').hasText('Add Value', 'Add Value modal displays.'); - } +export async function createCustomFormForType(formType, alwaysInclude, assert) { + async function addField(fieldType, label, values) { + await click('button:contains(Add Field)'); + await waitToAppear('.modal-dialog'); + if (assert) { + assert.dom('.modal-title').hasText('Add Value', 'Add Value modal displays.'); + } + + select('.custom-field-select', fieldType); + fillIn('.custom-field-label input', label); + fillIn('.custom-field-colspan input', '1'); - select('.custom-field-select', fieldType); - fillIn('.custom-field-label input', label); - fillIn('.custom-field-colspan input', '1'); - }); if (values) { if (assert) { - click('button:contains(Add Value)'); - andThen(function() { - fillIn('.custom-field-value:last', 'Delete Me'); - }); - andThen(function() { - assert.equal(find('.custom-field-value:contains(Delete Me)').length, 0, 'Field value successfully added'); - click('button.delete-field-value'); - }); - andThen(function() { - assert.equal(find('.custom-field-value:contains(Delete Me)').length, 0, 'Field value successfully deleted'); - }); + await click('button:contains(Add Value)'); + await fillIn('.custom-field-value:last', 'Delete Me'); + assert.equal(find('.custom-field-value:contains(Delete Me)').length, 0, 'Field value successfully added'); + + await click('button.delete-field-value'); + assert.equal(find('.custom-field-value:contains(Delete Me)').length, 0, 'Field value successfully deleted'); } - andThen(function() { - values.forEach(function(value) { - click('button:contains(Add Value)'); - andThen(function() { - fillIn('.custom-field-value:last', value); - }); - }); - }); - } - andThen(function() { - click('.modal-footer button:contains(Add)'); - }); - } - visit('/admin/custom-forms'); - click('button:contains(new form)'); - andThen(function() { - if (assert) { - assert.dom('.view-current-title').hasText('New Custom Form', 'New custom form edit page displays'); - assert.equal(currentURL(), '/admin/custom-forms/edit/new', 'Navigated to create new custom form'); + for (let value of values) { + await click('button:contains(Add Value)'); + await fillIn('.custom-field-value:last', value); + } } - fillIn('.custom-form-name input', `Test Custom Form for ${formType} ${alwaysInclude ? '' : 'NOT '}included`); - fillIn('.custom-form-columns input', '2'); - select('.custom-form-type', formType); - if (alwaysInclude) { - click('.js-custom-form-always-include input'); - } - click('.panel-footer button:contains(Add)'); - waitToAppear('.modal-dialog'); - }); - andThen(function() { - if (assert) { - assert.dom('.modal-title').hasText('Form Saved', 'Form is saved'); - } + await click('.modal-footer button:contains(Add)'); + } - click('.modal-footer button:contains(Ok)'); - addField('Header', 'Create a Pizza', header); - }); - andThen(function() { - addField('Checkbox', 'Pizza Toppings', toppings); - }); - andThen(function() { - addField('Dropdown', 'Pizza Crust', crusts); - }); - andThen(function() { - addField('Radio', 'Dessert', desserts); - }); - andThen(function() { - addField('Text', 'Beverage'); - }); - andThen(function() { - addField('Large Text', 'Special Instructions'); - }); - andThen(function() { - click('button:contains(Update)'); - waitToAppear('.modal-dialog'); - }); - andThen(function() { - if (assert) { - assert.dom('.modal-title').hasText('Form Saved', 'Form is updated'); - } + await visit('/admin/custom-forms'); + await click('button:contains(new form)'); + if (assert) { + assert.dom('.view-current-title').hasText('New Custom Form', 'New custom form edit page displays'); + assert.equal(currentURL(), '/admin/custom-forms/edit/new', 'Navigated to create new custom form'); + } - click('.modal-footer button:contains(Ok)'); - }); -}); + await fillIn('.custom-form-name input', `Test Custom Form for ${formType} ${alwaysInclude ? '' : 'NOT '}included`); + await fillIn('.custom-form-columns input', '2'); + await select('.custom-form-type', formType); + if (alwaysInclude) { + await click('.js-custom-form-always-include input'); + } + await click('.panel-footer button:contains(Add)'); + await waitToAppear('.modal-dialog'); + if (assert) { + assert.dom('.modal-title').hasText('Form Saved', 'Form is saved'); + } + + await click('.modal-footer button:contains(Ok)'); + await addField('Header', 'Create a Pizza', header); + await addField('Checkbox', 'Pizza Toppings', toppings); + await addField('Dropdown', 'Pizza Crust', crusts); + await addField('Radio', 'Dessert', desserts); + await addField('Text', 'Beverage'); + await addField('Large Text', 'Special Instructions'); + await click('button:contains(Update)'); + await waitToAppear('.modal-dialog'); + if (assert) { + assert.dom('.modal-title').hasText('Form Saved', 'Form is updated'); + } -registerAsyncHelper('checkCustomFormIsDisplayed', function(app, assert, header) { - waitToAppear(`h4:contains(${header})`); + await click('.modal-footer button:contains(Ok)'); +} - andThen(() => { - assert.equal(find(`h4:contains(${header})`).length, 1, `Form ${header} is displayed`); +export async function checkCustomFormIsDisplayed(assert, header) { + await waitToAppear(`h4:contains(${header})`); + assert.equal(find(`h4:contains(${header})`).length, 1, `Form ${header} is displayed`); - let formDiv = find(`h4:contains(${header}) + .js-custom-form`); + let formDiv = find(`h4:contains(${header}) + .js-custom-form`); - assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); + assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); - assert.equal(find('label:contains(Pizza Crust)', formDiv).length, 1, 'There is a dropdown header'); - assert.dom('select', formDiv[0]).exists({ count: 1 }, 'There is a dropdown'); - assert.equal(find('option', formDiv).length, crusts.length, 'There are options'); + assert.equal(find('label:contains(Pizza Crust)', formDiv).length, 1, 'There is a dropdown header'); + assert.dom('select', formDiv[0]).exists({ count: 1 }, 'There is a dropdown'); + assert.equal(find('option', formDiv).length, crusts.length, 'There are options'); - assert.equal(find('label:contains(Pizza Toppings)', formDiv).length, 1, 'There is a checkbox header'); - assert.equal(find('input[type=checkbox]', formDiv).length, toppings.length, 'There are checkboxes'); + assert.equal(find('label:contains(Pizza Toppings)', formDiv).length, 1, 'There is a checkbox header'); + assert.equal(find('input[type=checkbox]', formDiv).length, toppings.length, 'There are checkboxes'); - assert.equal(find('label:contains(Special Instructions)', formDiv).length, 1, 'There is a textarea header'); - assert.dom('textarea', formDiv[0]).exists({ count: 1 }, 'There is a textarea'); + assert.equal(find('label:contains(Special Instructions)', formDiv).length, 1, 'There is a textarea header'); + assert.dom('textarea', formDiv[0]).exists({ count: 1 }, 'There is a textarea'); - assert.equal(find('label:contains(Dessert)', formDiv).length, 1, 'There is a radio header'); - assert.equal(find('input[type=radio]', formDiv).length, desserts.length, 'There are radios'); + assert.equal(find('label:contains(Dessert)', formDiv).length, 1, 'There is a radio header'); + assert.equal(find('input[type=radio]', formDiv).length, desserts.length, 'There are radios'); - assert.equal(find('label:contains(Beverage)', formDiv).length, 1, 'There is a text header'); - assert.equal(find('label:contains(Beverage)+input[type=text]', formDiv).length, 1, 'There is a text input'); - }); -}); + assert.equal(find('label:contains(Beverage)', formDiv).length, 1, 'There is a text header'); + assert.equal(find('label:contains(Beverage)+input[type=text]', formDiv).length, 1, 'There is a text input'); +} -registerAsyncHelper('fillCustomForm', function(app, header) { +export async function fillCustomForm(header) { let formSelector = `h4:contains(${header}) + .js-custom-form`; - select(`${formSelector} select`, crusts[2]); - click(`${formSelector} input[type=checkbox]:last`); - click(`${formSelector} input[type=radio]:nth(1)`); - fillIn(`${formSelector} textarea`, `Large text for the form ${header}`); - fillIn(`${formSelector} label:contains(Beverage)+input[type=text]`, `Small text for the form ${header}`); -}); - -registerAsyncHelper('checkCustomFormIsFilled', function(app, assert, header) { - waitToAppear(`h4:contains(${header})`); - - andThen(() => { - let formDiv = find(`h4:contains(${header}) + .js-custom-form`); - - assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); - assert.dom('select', formDiv[0]).hasValue(crusts[2], 'There is value in select'); - assert.ok(find('input[type=checkbox]:last', formDiv).is(':checked'), 'There is value in checkbox'); - assert.equal(find('input:radio:checked', formDiv).val(), desserts[1], 'There is value in radio'); - assert.dom('textarea', formDiv[0]).hasValue(`Large text for the form ${header}`, 'There is value in textarea'); - assert.equal(find('label:contains(Beverage)+input[type=text]', formDiv).val(), `Small text for the form ${header}`, 'There is value in the input'); - }); -}); - -registerAsyncHelper('checkCustomFormIsFilledAndReadonly', function(app, assert, header) { - waitToAppear(`h4:contains(${header})`); - - andThen(() => { - let formDiv = find(`h4:contains(${header}) + .js-custom-form`); - - assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); - assert.equal(find(`p:contains(${crusts[2]})`, formDiv).length, 1, 'There is text from select'); - assert.equal(find(`p:contains(${desserts[1]})`, formDiv).length, 1, 'There is text from radio'); - assert.ok(find('input[type=checkbox]:last', formDiv).is(':checked'), 'There is value in checkbox'); - assert.equal(find(`p:contains(Large text for the form ${header})`, formDiv).length, 1, 'There is text from textarea'); - assert.equal(find(`p:contains(Small text for the form ${header})`, formDiv).length, 1, 'There is text from input'); - }); -}); - -registerAsyncHelper('attachCustomForm', function(app, name) { - waitToAppear('button:contains(Add Form)'); - click('button:contains(Add Form)'); - waitToAppear('.modal-dialog'); - select('.form-to-add', name); - click('.modal-footer button:contains(Add Form)'); - waitToDisappear('.modal-dialog'); -}); + await select(`${formSelector} select`, crusts[2]); + await click(`${formSelector} input[type=checkbox]:last`); + await click(`${formSelector} input[type=radio]:nth(1)`); + await fillIn(`${formSelector} textarea`, `Large text for the form ${header}`); + await fillIn(`${formSelector} label:contains(Beverage)+input[type=text]`, `Small text for the form ${header}`); +} + +export async function checkCustomFormIsFilled(assert, header) { + await waitToAppear(`h4:contains(${header})`); + + let formDiv = find(`h4:contains(${header}) + .js-custom-form`); + + assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); + assert.dom('select', formDiv[0]).hasValue(crusts[2], 'There is value in select'); + assert.ok(find('input[type=checkbox]:last', formDiv).is(':checked'), 'There is value in checkbox'); + assert.equal(find('input:radio:checked', formDiv).val(), desserts[1], 'There is value in radio'); + assert.dom('textarea', formDiv[0]).hasValue(`Large text for the form ${header}`, 'There is value in textarea'); + assert.equal(find('label:contains(Beverage)+input[type=text]', formDiv).val(), `Small text for the form ${header}`, 'There is value in the input'); +} + +export async function checkCustomFormIsFilledAndReadonly(assert, header) { + await waitToAppear(`h4:contains(${header})`); + + let formDiv = find(`h4:contains(${header}) + .js-custom-form`); + + assert.equal(find('label:contains(Create a Pizza)', formDiv).length, 1, 'There is a form header'); + assert.equal(find(`p:contains(${crusts[2]})`, formDiv).length, 1, 'There is text from select'); + assert.equal(find(`p:contains(${desserts[1]})`, formDiv).length, 1, 'There is text from radio'); + assert.ok(find('input[type=checkbox]:last', formDiv).is(':checked'), 'There is value in checkbox'); + assert.equal(find(`p:contains(Large text for the form ${header})`, formDiv).length, 1, 'There is text from textarea'); + assert.equal(find(`p:contains(Small text for the form ${header})`, formDiv).length, 1, 'There is text from input'); +} + +export async function attachCustomForm(name) { + await waitToAppear('button:contains(Add Form)'); + await click('button:contains(Add Form)'); + await waitToAppear('.modal-dialog'); + await select('.form-to-add', name); + await click('.modal-footer button:contains(Add Form)'); + await waitToDisappear('.modal-dialog'); +} diff --git a/tests/helpers/select-date.js b/tests/helpers/select-date.js index 6729b38f98..5d9d6f880b 100644 --- a/tests/helpers/select-date.js +++ b/tests/helpers/select-date.js @@ -1,9 +1,8 @@ // Derived from https://raw.githubusercontent.com/edgycircle/ember-pikaday/master/addon/helpers/pikaday.js -import { Promise as EmberPromise } from 'rsvp'; - -import { registerAsyncHelper } from '@ember/test'; import moment from 'moment'; +import { waitToAppear } from 'hospitalrun/tests/helpers/wait-to-appear'; + function triggerNativeEvent(element, eventName) { if (document.createEvent) { let event = document.createEvent('Events'); @@ -14,15 +13,11 @@ function triggerNativeEvent(element, eventName) { } } -registerAsyncHelper('selectDate', function(app, selector, date) { - return new EmberPromise(function(resolve) { - click(selector); - waitToAppear('.pika-single:not(.is-hidden)').then(function() { - fillIn(selector, moment(date).format('l')); - andThen(function() { - triggerNativeEvent(app.$(selector)[0], 'change'); - resolve(); - }); - }); - }); -}); +async function selectDate(selector, date) { + await click(selector); + await waitToAppear('.pika-single:not(.is-hidden)'); + await fillIn(selector, moment(date).format('l')); + triggerNativeEvent($(selector)[0], 'change'); +} + +export default selectDate; diff --git a/tests/helpers/select.js b/tests/helpers/select.js index 1752cc3c20..e5c7a5a88d 100644 --- a/tests/helpers/select.js +++ b/tests/helpers/select.js @@ -1,9 +1,8 @@ import { run } from '@ember/runloop'; import $ from 'jquery'; -import { registerAsyncHelper } from '@ember/test'; -registerAsyncHelper('select', function(app, selector, ...texts) { - let $options = app.testHelpers.findWithAssert(`${selector} option`); +async function select(selector, ...texts) { + let $options = findWithAssert(`${selector} option`); $options.each(function() { let $option = $(this); @@ -16,5 +15,7 @@ registerAsyncHelper('select', function(app, selector, ...texts) { }); }); - return app.testHelpers.wait(); -}); + await wait(); +} + +export default select; diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js index 9b1ffb5565..f735d7f09f 100644 --- a/tests/helpers/start-app.js +++ b/tests/helpers/start-app.js @@ -3,16 +3,6 @@ import config from '../../config/environment'; import { merge } from '@ember/polyfills'; import { run } from '@ember/runloop'; -import './run-with-pouch-dump'; -import './authenticate-user'; -import './add-offline-users-for-electron'; -import './select'; -import './select-date'; -import './typeahead-fillin'; -import './wait-to-appear'; - -import './scenarios/custom-forms'; - function createTranslationWrapper(original, context) { function t(str, data) { let result = original.call(context, str, data); diff --git a/tests/helpers/typeahead-fillin.js b/tests/helpers/typeahead-fillin.js index 636d27c7d8..258dcc7043 100644 --- a/tests/helpers/typeahead-fillin.js +++ b/tests/helpers/typeahead-fillin.js @@ -1,9 +1,8 @@ -import { registerAsyncHelper } from '@ember/test'; - -registerAsyncHelper('typeAheadFillIn', function(app, selector, value) { +async function typeAheadFillIn(selector, value) { let typeAheadSelector = `${selector} .tt-input`; - fillIn(typeAheadSelector, value); - triggerEvent(typeAheadSelector, 'input'); - triggerEvent(typeAheadSelector, 'blur'); - return app.testHelpers.wait(); -}); + await fillIn(typeAheadSelector, value); + await triggerEvent(typeAheadSelector, 'input'); + await triggerEvent(typeAheadSelector, 'blur'); +} + +export default typeAheadFillIn; diff --git a/tests/helpers/wait-to-appear.js b/tests/helpers/wait-to-appear.js index d53ac061ed..a910a576fb 100644 --- a/tests/helpers/wait-to-appear.js +++ b/tests/helpers/wait-to-appear.js @@ -1,31 +1,13 @@ -import { registerAsyncHelper } from '@ember/test'; -import { Promise as EmberPromise } from 'rsvp'; -import { later } from '@ember/runloop'; +import { waitUntil } from '@ember/test-helpers'; function isVisible(selector) { return $(selector).length > 0; } -function checkVisibility(selector, interval, resolve, visibility) { - if (isVisible(selector) === visibility) { - resolve($(selector)); - } else { - later(null, function() { - checkVisibility(selector, interval, resolve, visibility); - }, interval); - } +export async function waitToAppear(selector) { + await waitUntil(() => isVisible(selector)); } -function waitToAppear(app, selector, interval = 200) { - return new EmberPromise(function(resolve) { - checkVisibility(selector, interval, resolve, true); - }); +export async function waitToDisappear(selector) { + await waitUntil(() => !isVisible(selector)); } - -function waitToDisappear(app, selector, interval = 200) { - return new EmberPromise(function(resolve) { - checkVisibility(selector, interval, resolve, false); - }); -} -registerAsyncHelper('waitToAppear', waitToAppear); -registerAsyncHelper('waitToDisappear', waitToDisappear);