WIP Additional Fields API
This commit is contained in:
+40
-84
@@ -40,7 +40,7 @@
|
||||
<h3> </h3>
|
||||
<h4><a href="#additionalfields">Additional Fields</a></h4>
|
||||
<ul>
|
||||
<li><a href="#listadditionalfields">List Additional Field Sources</a></li>
|
||||
<li><a href="#listadditionalfields">List Additional Fields Sets</a></li>
|
||||
<li><a href="#retrieveadditionalfields">Retrieve Additional Fields</a></li>
|
||||
<li><a href="#updateadditionalfields">Update Additional Fields</a></li>
|
||||
</ul>
|
||||
@@ -315,9 +315,14 @@ error is parameter-specific. You can use this to display a message near
|
||||
<div class="method-description">
|
||||
<h3>Additional Fields</h3>
|
||||
<p>
|
||||
The additional fields resource allows you to run and receive output from pre-defined Mifos X additional fieldsreports.
|
||||
In Mifos X, any number of "Sets" of "Additional Fields" can be configured for a Mifos X database table ("Type").
|
||||
</p>
|
||||
<p> For example, portfolio_client is the database table that holds client data. Typically, MFI's want more client related fields than is provided by Mifos X out-of-the-box.
|
||||
The MFI might add a Set called "Additional Info" containing some fields that are typically input when creating a client. They might then add another Set called "Highly Improbable Info" containing some fields that are only input in exceptional circumstances.
|
||||
</p>
|
||||
<p>
|
||||
The additional fields resource allows you to retrieve and update any Additional Fields data that has been configured in Mifos X.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Mifos X Individual Lending client application uses a JQuery plugin called stretchydata which, itself, uses this additional fields resource to provide a pretty flexible additional fields User Interface (UI). Put a link to an example here.
|
||||
</p>
|
||||
@@ -328,94 +333,45 @@ The Mifos X Individual Lending client application uses a JQuery plugin called st
|
||||
|
||||
|
||||
|
||||
<a id="listadditionalfields" name="listadditionalfields" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>List Additional Fields</h4>
|
||||
<p>
|
||||
Lists the types of additional field data that has been defined in Mifox X. If an Additional Data Type has more than one Addition Data Set it will be listed the same number of times as it has Sets.
|
||||
</p>
|
||||
<a id="listadditionalfields" name="listadditionalfields" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
<div class="method-description">
|
||||
<h4>List Additional Fields Sets</h4>
|
||||
<p>
|
||||
Lists the Sets of additional fields have been defined in Mifos X.
|
||||
</p>
|
||||
|
||||
<h5>Arguments</h5>
|
||||
<dl class="argument-list">
|
||||
<dt>exportCSV</dt>
|
||||
<dd>optional, <span>The only valid value is 'true'. If any other value is provided the argument will be ignored</span></dd>
|
||||
<dd>Output will be delivered as a CSV file instead of JSON.</dd>
|
||||
</dl>
|
||||
<p>Example Request:
|
||||
<a style="word-wrap: break-word;" href="http://localhost:8080/mifosng-provider/api/v1/reports">http://localhost:8080/mifosng-provider/api/v1/reports</a>
|
||||
</p>
|
||||
<h5>Arguments</h5>
|
||||
<dl class="argument-list">
|
||||
<dt>type</dt>
|
||||
<dd>optional</span></dd>
|
||||
<dd>The Additional Field Type (Mifos X database table) to restrict the output to</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
<p>Example Request:
|
||||
<a style="word-wrap: break-word;" href="http://localhost:8080/mifosng-provider/api/v1/additionalfields?type=portfolio_client">http://localhost:8080/mifosng-provider/api/v1/additionalfields?type=portfolio_client</a>
|
||||
</p>
|
||||
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">GET https://thedomainname/v1/reports</code>
|
||||
<code class="method-response">{
|
||||
"columnHeaders": [
|
||||
</div>
|
||||
|
||||
<div class="method-example">
|
||||
<code class="method-declaration">GET https://thedomainname/v1/additionalfields</code>
|
||||
<code class="method-response">{
|
||||
"additionalFieldsSets": [
|
||||
{
|
||||
"columnName": "report_id",
|
||||
"columnType": "INT",
|
||||
"columnLength": null,
|
||||
"columnDisplayType": null,
|
||||
"columnValues": []
|
||||
"id": 1,
|
||||
"name": "Additional Information",
|
||||
"type": "portfolio_client"
|
||||
},
|
||||
{
|
||||
"columnName": "report_name",
|
||||
"columnType": "VARCHAR",
|
||||
"columnLength": null,
|
||||
"columnDisplayType": null,
|
||||
"columnValues": []
|
||||
},
|
||||
{
|
||||
"columnName": "report_type",
|
||||
"columnType": "VARCHAR",
|
||||
"columnLength": null,
|
||||
"columnDisplayType": null,
|
||||
"columnValues": []
|
||||
},
|
||||
... more "columnHeaders" entries
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"row": [
|
||||
"29",
|
||||
"Client Listing",
|
||||
"Table",
|
||||
null,
|
||||
null,
|
||||
"5",
|
||||
null,
|
||||
"selectOfficeId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"row": [
|
||||
"42",
|
||||
"Client Listing - Additional and Unlikely",
|
||||
"Table",
|
||||
null,
|
||||
null,
|
||||
"5",
|
||||
null,
|
||||
"selectOfficeId"
|
||||
]
|
||||
},
|
||||
{
|
||||
"row": [
|
||||
"30",
|
||||
"Client Loans Listing",
|
||||
"Table",
|
||||
null,
|
||||
null,
|
||||
"5",
|
||||
null,
|
||||
"selectOfficeId"
|
||||
]
|
||||
},
|
||||
... more "Row" entries
|
||||
"id": 9,
|
||||
"name": "Highly Improbable Info",
|
||||
"type": "portfolio_client"
|
||||
}
|
||||
]
|
||||
}</code>
|
||||
</div>
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -3,16 +3,16 @@ package org.mifosng.data;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement
|
||||
public class ExtraDatasetRow {
|
||||
public class AdditionalFieldSet {
|
||||
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String type;
|
||||
protected ExtraDatasetRow() {
|
||||
protected AdditionalFieldSet() {
|
||||
//
|
||||
}
|
||||
|
||||
public ExtraDatasetRow(final Integer id, final String name, final String type) {
|
||||
public AdditionalFieldSet(final Integer id, final String name, final String type) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.mifosng.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement
|
||||
public class AdditionalFieldSets {
|
||||
|
||||
private List<AdditionalFieldSet> additionalFieldsSets = new ArrayList<AdditionalFieldSet>();
|
||||
|
||||
protected AdditionalFieldSets() {
|
||||
//
|
||||
}
|
||||
|
||||
public AdditionalFieldSets(final List<AdditionalFieldSet> additionalFieldsSets) {
|
||||
this.additionalFieldsSets = additionalFieldsSets;
|
||||
}
|
||||
|
||||
public List<AdditionalFieldSet> getAdditionalFieldsSets() {
|
||||
return additionalFieldsSets;
|
||||
}
|
||||
|
||||
public void setAdditionalFieldsSets(List<AdditionalFieldSet> additionalFieldsSets) {
|
||||
this.additionalFieldsSets = additionalFieldsSets;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.mifosng.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@XmlRootElement
|
||||
public class ExtraDatasets {
|
||||
|
||||
private List<ExtraDatasetRow> extraDatasetRow = new ArrayList<ExtraDatasetRow>();
|
||||
|
||||
protected ExtraDatasets() {
|
||||
//
|
||||
}
|
||||
|
||||
public ExtraDatasets(final List<ExtraDatasetRow> extraDatasetRow) {
|
||||
this.extraDatasetRow = extraDatasetRow;
|
||||
}
|
||||
|
||||
public List<ExtraDatasetRow> getExtraDatasetRow() {
|
||||
return extraDatasetRow;
|
||||
}
|
||||
|
||||
public void setExtraDatasetRow(List<ExtraDatasetRow> extraDatasetRow) {
|
||||
this.extraDatasetRow = extraDatasetRow;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,14 +8,6 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
@XmlRootElement
|
||||
public class GenericResultset {
|
||||
|
||||
// [
|
||||
// [contact_email, field 2, field 3],
|
||||
// [
|
||||
// ["abb.net", "r2", "x"], ["abb.net", "r3"]
|
||||
// ]
|
||||
// ]
|
||||
|
||||
// create types for these
|
||||
private List<ResultsetColumnHeader> columnHeaders = new ArrayList<ResultsetColumnHeader>();
|
||||
private List<ResultsetDataRow> data = new ArrayList<ResultsetDataRow>();
|
||||
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
(function($) {
|
||||
|
||||
$.stretchyData = {};
|
||||
|
||||
$.stretchyData.displayAllExtraData = function(params) {
|
||||
|
||||
if (!(params.url)) {
|
||||
alert(doI18N("reportingInitError - url parameter"));
|
||||
return;
|
||||
}
|
||||
if (!(params.datasetType)) {
|
||||
alert(doI18N("reportingInitError - datasetType parameter"));
|
||||
return;
|
||||
}
|
||||
if (!(params.datasetPKValue)) {
|
||||
alert(doI18N("reportingInitError - datasetPKValue parameter"));
|
||||
return;
|
||||
}
|
||||
if (!(params.datasetTypeDiv)) {
|
||||
alert(doI18N("reportingInitError - datasetTypeDiv parameter"));
|
||||
return;
|
||||
}
|
||||
|
||||
var headingPrefix = "";
|
||||
if (params.headingPrefix)
|
||||
headingPrefix = params.headingPrefix;
|
||||
var headingClass = "";
|
||||
if (params.headingClass)
|
||||
headingClass = params.headingClass;
|
||||
var labelClass = "";
|
||||
if (params.labelClass)
|
||||
labelClass = params.labelClass;
|
||||
var valueClass = "";
|
||||
if (params.valueClass)
|
||||
valueClass = params.valueClass;
|
||||
displayAllExtraData(params.url, params.datasetType,
|
||||
params.datasetPKValue, params.datasetTypeDiv, headingPrefix,
|
||||
headingClass, labelClass, valueClass);
|
||||
};
|
||||
|
||||
$.stretchyData.popupEditDialog = function(url, datasetType, datasetName,
|
||||
datasetPKValue, dsnDivName, title, width, height) {
|
||||
popupEditDialog(url, datasetType, datasetName, datasetPKValue,
|
||||
dsnDivName, title, width, height);
|
||||
};
|
||||
|
||||
displayAllSuccessFunction = function(data, textStatus, jqXHR) {
|
||||
|
||||
var headingClassStr = "";
|
||||
if (displayAllVars.headingClass > "")
|
||||
headingClassStr = ' class="' + displayAllVars.headingClass + '" ';
|
||||
|
||||
var extraDataNamesVar = "";
|
||||
for ( var i in data.additionalFieldsSets) {
|
||||
var dsnDivName = generateDsnDivName(displayAllVars.datasetType, i, displayAllVars.datasetTypeDiv);
|
||||
extraDataNamesVar += '<br><span ' + headingClassStr + '><b>'
|
||||
+ doI18N(displayAllVars.headingPrefix)
|
||||
+ doI18N(data.additionalFieldsSets[i].name) + ' - </span></b> ';
|
||||
|
||||
extraDataNamesVar += editExtraDataLink(displayAllVars.url,
|
||||
displayAllVars.datasetType, data.additionalFieldsSets[i].name,
|
||||
displayAllVars.datasetPKValue, dsnDivName);
|
||||
|
||||
extraDataNamesVar += '<div id="' + dsnDivName + '">';
|
||||
extraDataNamesVar += '</div>';
|
||||
}
|
||||
$('#' + displayAllVars.datasetTypeDiv).html(extraDataNamesVar);
|
||||
for ( var i in data.additionalFieldsSets) {
|
||||
var dsnDivName = generateDsnDivName(displayAllVars.datasetType, i, displayAllVars.datasetTypeDiv);
|
||||
viewExtraData(displayAllVars.url, displayAllVars.datasetType,
|
||||
data.additionalFieldsSets[i].name, displayAllVars.datasetPKValue, dsnDivName);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
displayAllErrorFunction = function(jqXHR, textStatus, errorThrown) {
|
||||
alert(jqXHR.responseText);
|
||||
};
|
||||
|
||||
function displayAllExtraData(url, datasetType, datasetPKValue,
|
||||
datasetTypeDiv, headingPrefix, headingClass, labelClass, valueClass) {
|
||||
|
||||
displayAllVars = {
|
||||
url : url,
|
||||
datasetType : datasetType,
|
||||
datasetPKValue : datasetPKValue,
|
||||
datasetTypeDiv : datasetTypeDiv,
|
||||
headingPrefix : headingPrefix,
|
||||
headingClass : headingClass,
|
||||
labelClass : labelClass,
|
||||
valueClass : valueClass
|
||||
};
|
||||
|
||||
displayAllUrl = url + "api/v1/additionalfields?type="
|
||||
+ encodeURIComponent(datasetType);
|
||||
getData(displayAllUrl, displayAllSuccessFunction,
|
||||
displayAllErrorFunction);
|
||||
}
|
||||
|
||||
function editExtraDataLink(url, datasetType, datasetName, datasetPKValue,
|
||||
dsnDivName) {
|
||||
|
||||
var popupVar = "jQuery.stretchyData.popupEditDialog('" + url + "', '"
|
||||
+ datasetType + "', '" + datasetName + "', " + datasetPKValue
|
||||
+ ", '" + dsnDivName + "', '" + doI18N("Edit") + " "
|
||||
+ doI18N(datasetName) + "', 900, 500)";
|
||||
var editLink = '<A HREF="#" onClick="' + popupVar + '">'
|
||||
+ doI18N("Edit") + '</A><br>';
|
||||
// alert(editLink);
|
||||
return editLink;
|
||||
}
|
||||
|
||||
function viewExtraDataset(data, dsnDivName) {
|
||||
|
||||
var dataLength = data.data.length;
|
||||
var extraDataViewVar = '<table width="100%"><tr>';
|
||||
|
||||
var colsPerRow = 2;
|
||||
var colsPerRowCount = 0;
|
||||
var labelClassStr = "";
|
||||
var valueClassStr = "";
|
||||
if (displayAllVars.labelClass > "")
|
||||
labelClassStr = ' class="' + displayAllVars.labelClass + '" ';
|
||||
if (displayAllVars.valueClass > "")
|
||||
valueClassStr = ' class="' + displayAllVars.valueClass + '" ';
|
||||
|
||||
for ( var i in data.columnHeaders) {
|
||||
if (!(data.columnHeaders[i].columnName == "id")) {
|
||||
colsPerRowCount += 1;
|
||||
if (colsPerRowCount > colsPerRow) {
|
||||
extraDataViewVar += '</tr><tr>';
|
||||
colsPerRowCount = 1;
|
||||
}
|
||||
var colVal = "";
|
||||
if (dataLength > 0)
|
||||
colVal = data.data[0].row[i];
|
||||
if (colVal == null)
|
||||
colVal = "";
|
||||
|
||||
if (colVal > "" && data.columnHeaders[i].columnType == "Text")
|
||||
colVal = '<textarea rows="3" cols="40" readonly="readonly">'
|
||||
+ colVal + '</textarea>';
|
||||
extraDataViewVar += '<td valign="top"><span ' + labelClassStr
|
||||
+ '>' + doI18N(data.columnHeaders[i].columnName)
|
||||
+ ':</span></td><td valign="top"><span '
|
||||
+ valueClassStr + '>' + colVal + '</span></td>';
|
||||
}
|
||||
}
|
||||
extraDataViewVar += '</tr></table>';
|
||||
$('#' + dsnDivName).html(extraDataViewVar);
|
||||
// alert(dsnDivName + ": " + dsnDivName + extraDataViewVar);
|
||||
}
|
||||
;
|
||||
viewExtraDataErrorFunction = function(jqXHR, textStatus, errorThrown) {
|
||||
alert(jqXHR.responseText);
|
||||
};
|
||||
|
||||
function viewExtraData(url, datasetType, datasetName, datasetPKValue,
|
||||
dsnDivName) {
|
||||
var viewExtraDataUrl = url + "api/v1/additionalfields/" + encodeURIComponent(datasetType)
|
||||
+ "/" + encodeURIComponent(datasetName) + "/"
|
||||
+ encodeURIComponent(datasetPKValue);
|
||||
|
||||
var evalViewExtraDataSuccessFunction = "var viewExtraDataSuccessFunction = function(data, textStatus, jqXHR){ viewExtraDataset(data, '"
|
||||
+ dsnDivName + "'); };"
|
||||
eval(evalViewExtraDataSuccessFunction);
|
||||
getData(viewExtraDataUrl, viewExtraDataSuccessFunction,
|
||||
viewExtraDataErrorFunction);
|
||||
}
|
||||
|
||||
popupEditErrorFunction = function(jqXHR, textStatus, errorThrown) {
|
||||
alert("error");
|
||||
handleXhrError(jqXHR, textStatus, errorThrown, "#formErrorsTemplate",
|
||||
"#formerrors");
|
||||
};
|
||||
popupEditSuccessFunction = function(data, textStatus, jqXHR) {
|
||||
currentEditPopup.dialogDiv.append(extraDataBuildTemplate(data));
|
||||
extraDataOpenDialog(currentEditPopup.url);
|
||||
extraDataFormatDates(data.columnHeaders);
|
||||
};
|
||||
function popupEditDialog(url, datasetType, datasetName, datasetPKValue,
|
||||
dsnDivName, title, width, height) {
|
||||
|
||||
currentEditPopup = {
|
||||
dialogDiv : $("<div id='dialog-form'></div>"),
|
||||
dsnDivName : dsnDivName,
|
||||
title : title,
|
||||
width : width,
|
||||
height : height,
|
||||
datasetType : datasetType,
|
||||
datasetName : datasetName,
|
||||
datasetPKValue : datasetPKValue,
|
||||
baseUrl : url,
|
||||
url : url + "api/v1/additionalfields/" + encodeURIComponent(datasetType) + "/"
|
||||
+ encodeURIComponent(datasetName) + "/"
|
||||
+ encodeURIComponent(datasetPKValue)
|
||||
};
|
||||
getData(currentEditPopup.url, popupEditSuccessFunction,
|
||||
popupEditErrorFunction);
|
||||
}
|
||||
|
||||
function generateDsnDivName(datasetType, i, uniqueDivid) {
|
||||
return extraDataUnderscore(datasetType) + "_" + i + "_" + extraDataUnderscore(uniqueDivid);
|
||||
}
|
||||
|
||||
/* start of code to fill data in edit form */
|
||||
|
||||
function extraDataUnderscore(colName) {
|
||||
return colName.replace(/ /g, "_")
|
||||
}
|
||||
|
||||
function extraDataColDisplayHTML(colName, colType, colLength,
|
||||
colDisplayType, colAllowedValues, colVal) {
|
||||
var displayHTML = '<td valign="top"><label>' + colName
|
||||
+ ':</label></td><td valign="top">';
|
||||
var valueAttr = ""
|
||||
if (colVal != null)
|
||||
valueAttr = 'value="' + colVal.replace(/"/g, """) + '"';
|
||||
var colNameUnderscore = extraDataUnderscore(colName);
|
||||
|
||||
switch (colType) {
|
||||
case "String":
|
||||
var colAllowedValuesLength = colAllowedValues.length;
|
||||
if (colDisplayType != "List") {
|
||||
var colSize = 40;
|
||||
if (colLength < colSize)
|
||||
colSize = colLength;
|
||||
displayHTML += '<input id="' + colNameUnderscore + '" name="'
|
||||
+ colNameUnderscore + '" size="' + colSize + '" '
|
||||
+ valueAttr + ' type="text"/>'
|
||||
} else
|
||||
displayHTML += extraDataSelectTag(colNameUnderscore,
|
||||
colAllowedValues, colVal);
|
||||
break;
|
||||
case "Text":
|
||||
var textVal = "";
|
||||
if (colVal != null)
|
||||
textVal = colVal;
|
||||
displayHTML += '<textarea id="' + colNameUnderscore + '" name="'
|
||||
+ colNameUnderscore + '" rows="4" cols="40">' + textVal
|
||||
+ '</textarea>';
|
||||
break;
|
||||
case "Date":
|
||||
displayHTML += '<input id="' + colNameUnderscore + '" name="'
|
||||
+ colNameUnderscore + '" size="12" ' + valueAttr
|
||||
+ ' type="text"/>';
|
||||
break;
|
||||
case "Decimal":
|
||||
displayHTML += '<input id="' + colNameUnderscore + '" name="'
|
||||
+ colNameUnderscore + '" size="12" ' + valueAttr
|
||||
+ ' type="text"/>';
|
||||
break;
|
||||
case "Integer":
|
||||
displayHTML += '<input id="' + colNameUnderscore + '" name="'
|
||||
+ colNameUnderscore + '" size="12" ' + valueAttr
|
||||
+ ' type="text"/>';
|
||||
break;
|
||||
default:
|
||||
displayHTML += "'" + colType + "'";
|
||||
}
|
||||
displayHTML += '</td>';
|
||||
return displayHTML;
|
||||
}
|
||||
|
||||
function extraDataSelectTag(colName, colAllowedValues, colVal) {
|
||||
|
||||
var selectedVal = "";
|
||||
var selectHtml = '<select id="' + colName + '" name="' + colName + '">';
|
||||
|
||||
if ((colVal == null) || (colVal == ""))
|
||||
selectedVal = ' selected="selected" '
|
||||
else
|
||||
selectedVal = "";
|
||||
selectHtml += '<option value=""' + selectedVal + '></option>';
|
||||
|
||||
for ( var i in colAllowedValues) {
|
||||
if (colVal == colAllowedValues[i])
|
||||
selectedVal = ' selected="selected" '
|
||||
else
|
||||
selectedVal = "";
|
||||
selectHtml += '<option value="' + colAllowedValues[i] + '"'
|
||||
+ selectedVal + '>' + colAllowedValues[i] + '</option>';
|
||||
}
|
||||
|
||||
selectHtml += '</select>';
|
||||
// alert(selectHtml);
|
||||
return selectHtml;
|
||||
}
|
||||
|
||||
function extraDataBuildTemplate(data) {
|
||||
|
||||
var dataLength = data.data.length;
|
||||
var transType = 'E';
|
||||
if (dataLength == 0)
|
||||
transType = 'A';
|
||||
|
||||
var extraDataTemplateVar = '<form id="entityform"> <div id="formerrors"></div>';
|
||||
extraDataTemplateVar += '<input id="ed_transType" name="ed_transType" type="hidden" value="'
|
||||
+ transType + '"/>';
|
||||
|
||||
extraDataTemplateVar += '<table width="100%"><tr>';
|
||||
|
||||
var colsPerRow = 2;
|
||||
var colsPerRowCount = 0;
|
||||
|
||||
for ( var i in data.columnHeaders) {
|
||||
|
||||
if (!(data.columnHeaders[i].columnName == "id")) {
|
||||
colsPerRowCount += 1;
|
||||
if (colsPerRowCount > colsPerRow) {
|
||||
extraDataTemplateVar += '</tr><tr>';
|
||||
colsPerRowCount = 1;
|
||||
}
|
||||
var colVal = "";
|
||||
if (dataLength > 0)
|
||||
colVal = data.data[0].row[i];
|
||||
extraDataTemplateVar += extraDataColDisplayHTML(
|
||||
data.columnHeaders[i].columnName,
|
||||
data.columnHeaders[i].columnType,
|
||||
data.columnHeaders[i].columnLength,
|
||||
data.columnHeaders[i].columnDisplayType,
|
||||
data.columnHeaders[i].columnValues, colVal);
|
||||
}
|
||||
}
|
||||
extraDataTemplateVar += '</tr>';
|
||||
return extraDataTemplateVar += '</table></form>';
|
||||
}
|
||||
|
||||
function extraDataFormatDates(columnHeaders) {
|
||||
|
||||
for ( var i in columnHeaders) {
|
||||
// alert("in loop: " +
|
||||
// extraDataUnderscore(columnHeaders[i].columnName) + " Type: " +
|
||||
// columnHeaders[i].columnType);
|
||||
switch (columnHeaders[i].columnType) {
|
||||
case "Date":
|
||||
$('#' + extraDataUnderscore(columnHeaders[i].columnName))
|
||||
.datepicker({
|
||||
|
||||
changeMonth : true,
|
||||
changeYear : true,
|
||||
dateFormat : 'yy-mm-dd'
|
||||
});
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.serializeObject = function()
|
||||
{
|
||||
var o = {};
|
||||
var a = this.serializeArray();
|
||||
$.each(a, function() {
|
||||
if (o[this.name] !== undefined) {
|
||||
if (!o[this.name].push) {
|
||||
o[this.name] = [o[this.name]];
|
||||
}
|
||||
o[this.name].push(this.value || '');
|
||||
} else {
|
||||
o[this.name] = this.value || '';
|
||||
}
|
||||
});
|
||||
return o;
|
||||
};
|
||||
|
||||
function extraDataOpenDialog(url) {
|
||||
|
||||
// var saveButton = jQuery.i18n.prop('dialog.button.save');
|
||||
// var cancelButton = jQuery.i18n.prop('dialog.button.cancel');
|
||||
var saveButton = "save";
|
||||
var cancelButton = "cancel"
|
||||
|
||||
var buttonsOpts = {};
|
||||
buttonsOpts[saveButton] = function() {
|
||||
$('.multiSelectedItems option').each(function(i) {
|
||||
$(this).attr("selected", "selected");
|
||||
});
|
||||
|
||||
var form_data = JSON.stringify($('#entityform').serializeObject());
|
||||
//console.log(form_data);
|
||||
var jqxhr = $.ajax({
|
||||
url : url,
|
||||
type : 'POST',
|
||||
contentType : "application/json; charset=utf-8",
|
||||
// dataType : 'jsonp',
|
||||
// crossDomain : true,
|
||||
dataType : 'json',
|
||||
data : form_data,
|
||||
success : function(data, textStatus, jqXHR) {
|
||||
currentEditPopup.dialogDiv.dialog("close");
|
||||
viewExtraData(currentEditPopup.baseUrl,
|
||||
currentEditPopup.datasetType,
|
||||
currentEditPopup.datasetName,
|
||||
currentEditPopup.datasetPKValue,
|
||||
currentEditPopup.dsnDivName)
|
||||
},
|
||||
error : function(jqXHR, textStatus, errorThrown) {
|
||||
handleXhrError(jqXHR, textStatus, errorThrown,
|
||||
"#formErrorsTemplate", "#formerrors");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
buttonsOpts[cancelButton] = function() {
|
||||
$(this).dialog("close");
|
||||
};
|
||||
|
||||
currentEditPopup.dialogDiv
|
||||
.dialog(
|
||||
{
|
||||
// title: jQuery.i18n.prop(titleCode),
|
||||
title : currentEditPopup.title,
|
||||
width : currentEditPopup.width,
|
||||
height : currentEditPopup.height,
|
||||
modal : true,
|
||||
buttons : buttonsOpts,
|
||||
close : function() {
|
||||
// if i dont do this, theres a problem with
|
||||
// errors being appended to dialog view second
|
||||
// time round
|
||||
$(this).remove();
|
||||
},
|
||||
open : function(event, ui) {
|
||||
$('.multiadd')
|
||||
.click(
|
||||
function() {
|
||||
return !$(
|
||||
'.multiNotSelectedItems option:selected')
|
||||
.remove()
|
||||
.appendTo(
|
||||
'#selectedItems');
|
||||
});
|
||||
|
||||
$('.multiremove')
|
||||
.click(
|
||||
function() {
|
||||
return !$(
|
||||
'.multiSelectedItems option:selected')
|
||||
.remove()
|
||||
.appendTo(
|
||||
'#notSelectedItems');
|
||||
});
|
||||
}
|
||||
}).dialog('open');
|
||||
}
|
||||
|
||||
/* end of code to fill data in edit form and display it */
|
||||
|
||||
function getData(url, successFunction, errorFunction) {
|
||||
|
||||
$.ajax({
|
||||
url : url,
|
||||
cache : false,
|
||||
type : 'GET',
|
||||
contentType : "application/json; charset=utf-8",
|
||||
// dataType : 'jsonp',
|
||||
// crossDomain : true,
|
||||
dataType : 'json',
|
||||
//crossDomain : false,
|
||||
success : successFunction,
|
||||
error : errorFunction
|
||||
});
|
||||
}
|
||||
|
||||
function handleXhrError(jqXHR, textStatus, errorThrown, templateSelector,
|
||||
placeholderDiv) {
|
||||
if (jqXHR.status === 0) {
|
||||
alert('Not connect.\n Verify Network.');
|
||||
} else if (jqXHR.status == 404) {
|
||||
alert('Requested page not found. [404]');
|
||||
} else if (jqXHR.status == 500) {
|
||||
alert('Internal Server Error [500].');
|
||||
} else if (errorThrown === 'parsererror') {
|
||||
alert('Requested JSON parse failed.');
|
||||
} else if (errorThrown === 'timeout') {
|
||||
alert('Time out error.');
|
||||
} else if (errorThrown === 'abort') {
|
||||
alert('Ajax request aborted.');
|
||||
} else {
|
||||
// remove error class from all input fields
|
||||
var $inputs = $('#entityform :input');
|
||||
|
||||
$inputs.each(function() {
|
||||
$(this).removeClass("ui-state-error");
|
||||
});
|
||||
|
||||
$(placeholderDiv).html("");
|
||||
|
||||
var jsonErrors = JSON.parse(jqXHR.responseText);
|
||||
|
||||
var errorArray = new Array();
|
||||
var arrayIndex = 0;
|
||||
$.each(jsonErrors, function() {
|
||||
var fieldId = '#' + this.field;
|
||||
$(fieldId).addClass("ui-state-error");
|
||||
|
||||
var errorObj = new Object();
|
||||
errorObj.field = this.field;
|
||||
errorObj.code = this.code;
|
||||
errorObj.message = this.code;
|
||||
errorObj.value = this.value;
|
||||
|
||||
errorArray[arrayIndex] = errorObj;
|
||||
arrayIndex++
|
||||
});
|
||||
|
||||
var templateArray = new Array();
|
||||
var templateErrorObj = new Object();
|
||||
templateErrorObj.title = "You have the following errors:";
|
||||
templateErrorObj.errors = errorArray;
|
||||
|
||||
templateArray[0] = templateErrorObj;
|
||||
|
||||
var formErrorsHtml = $(templateSelector).render(templateArray);
|
||||
|
||||
$(placeholderDiv).append(formErrorsHtml);
|
||||
}
|
||||
}
|
||||
|
||||
function doI18N(xlateStr, params) {
|
||||
/*
|
||||
* if (I18N_Needed == "Y") { if (highlightMissingXlations == "Y") return
|
||||
* jQuery.i18n.prop(xlateStr, params) else { var xlated =
|
||||
* jQuery.i18n.prop(xlateStr, params); if (xlated.substr(0,1) == "[" &&
|
||||
* xlated.substr(xlated.length - 1, 1) == "]") return xlated.substr(1,
|
||||
* xlated.length - 2) else return xlated; } } else { var retStr =
|
||||
* xlateStr; if (retStr == 'rpt_select_one') retStr = 'Select One'; if
|
||||
* (retStr == 'rpt_select_all') retStr = 'Select All'; return retStr; }
|
||||
*/
|
||||
return xlateStr;
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
+2
-2
@@ -4,7 +4,7 @@ import java.util.Map;
|
||||
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.mifosng.data.ExtraDatasets;
|
||||
import org.mifosng.data.AdditionalFieldSets;
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
|
||||
public interface ReadExtraDataAndReportingService {
|
||||
@@ -16,7 +16,7 @@ public interface ReadExtraDataAndReportingService {
|
||||
GenericResultset retrieveGenericResultset(String name,
|
||||
String type, Map<String, String> extractedQueryParams);
|
||||
|
||||
ExtraDatasets retrieveExtraDatasetNames(String datasetType);
|
||||
AdditionalFieldSets retrieveExtraDatasetNames(String datasetType);
|
||||
|
||||
GenericResultset retrieveExtraData(String datasetType, String datasetName,
|
||||
String datasetPKValue);
|
||||
|
||||
+7
-7
@@ -20,8 +20,8 @@ import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.mifosng.data.ExtraDatasetRow;
|
||||
import org.mifosng.data.ExtraDatasets;
|
||||
import org.mifosng.data.AdditionalFieldSet;
|
||||
import org.mifosng.data.AdditionalFieldSets;
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
import org.mifosng.data.reports.ResultsetColumnHeader;
|
||||
import org.mifosng.data.reports.ResultsetDataRow;
|
||||
@@ -334,9 +334,9 @@ public class ReadExtraDataAndReportingServiceImpl implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtraDatasets retrieveExtraDatasetNames(String type) {
|
||||
public AdditionalFieldSets retrieveExtraDatasetNames(String type) {
|
||||
|
||||
List<ExtraDatasetRow> extraDatasetRows = new ArrayList<ExtraDatasetRow>();
|
||||
List<AdditionalFieldSet> additionalFieldsSets = new ArrayList<AdditionalFieldSet>();
|
||||
Connection db_connection;
|
||||
try {
|
||||
db_connection = dataSource.getConnection();
|
||||
@@ -354,8 +354,8 @@ public class ReadExtraDataAndReportingServiceImpl implements
|
||||
ResultSet rs = db_statement.executeQuery(sql);
|
||||
|
||||
while (rs.next()) {
|
||||
extraDatasetRows
|
||||
.add(new ExtraDatasetRow(rs.getInt("id"), rs
|
||||
additionalFieldsSets
|
||||
.add(new AdditionalFieldSet(rs.getInt("id"), rs
|
||||
.getString("datasetName"), rs
|
||||
.getString("datasetType")));
|
||||
}
|
||||
@@ -370,7 +370,7 @@ public class ReadExtraDataAndReportingServiceImpl implements
|
||||
.status(Status.BAD_REQUEST).entity(e.getMessage()).build());
|
||||
}
|
||||
|
||||
return new ExtraDatasets(extraDatasetRows);
|
||||
return new AdditionalFieldSets(additionalFieldsSets);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package org.mifosng.platform.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.codehaus.jettison.json.JSONArray;
|
||||
import org.codehaus.jettison.json.JSONException;
|
||||
import org.codehaus.jettison.json.JSONObject;
|
||||
import org.mifosng.data.EntityIdentifier;
|
||||
import org.mifosng.data.ErrorResponse;
|
||||
import org.mifosng.data.ErrorResponseList;
|
||||
import org.mifosng.data.AdditionalFieldSets;
|
||||
import org.mifosng.data.reports.GenericResultset;
|
||||
import org.mifosng.platform.InvalidSqlException;
|
||||
import org.mifosng.platform.ReadExtraDataAndReportingService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
@Path("/v1/additionalfields")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class AdditionalFieldsApiResource {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AdditionalFieldsApiResource.class);
|
||||
|
||||
@Autowired
|
||||
private ReadExtraDataAndReportingService readExtraDataAndReportingService;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ MediaType.APPLICATION_JSON})
|
||||
public Response datasets(@Context UriInfo uriInfo) {
|
||||
|
||||
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
|
||||
String type = queryParams.getFirst("type");
|
||||
|
||||
AdditionalFieldSets result = this.readExtraDataAndReportingService.retrieveExtraDatasetNames(type);
|
||||
return Response.ok().entity(result).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{datasetType}/{datasetName}/{datasetPKValue}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ MediaType.APPLICATION_JSON})
|
||||
public Response extraData(@PathParam("datasetType") final String datasetType,@PathParam("datasetName") final String datasetName, @PathParam("datasetPKValue") final String datasetPKValue, @Context UriInfo uriInfo) {
|
||||
|
||||
try {
|
||||
GenericResultset result = this.readExtraDataAndReportingService.retrieveExtraData(datasetType, datasetName, datasetPKValue);
|
||||
|
||||
return Response.ok().entity(result).build();
|
||||
} catch (InvalidSqlException e) {
|
||||
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
|
||||
|
||||
ErrorResponse err = new ErrorResponse("extradata.invalid.sql", "sql", e.getSql());
|
||||
allErrors.add(err);
|
||||
|
||||
throw new WebApplicationException(Response
|
||||
.status(Status.BAD_REQUEST)
|
||||
.entity(new ErrorResponseList(allErrors)).build());
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{datasetType}/{datasetName}/{datasetPKValue}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
|
||||
@Produces({ MediaType.APPLICATION_JSON})
|
||||
public Response saveExtraData(@PathParam("datasetType") final String datasetType,@PathParam("datasetName") final String datasetName, @PathParam("datasetPKValue") final String datasetPKValue, String reqbody) {
|
||||
|
||||
try {
|
||||
|
||||
Map<String, String> queryParams = new HashMap<String, String>();
|
||||
String pValue = "";
|
||||
String pName;
|
||||
try {
|
||||
JSONObject jsonObj = new JSONObject(reqbody);
|
||||
JSONArray jsonArr = jsonObj.names();
|
||||
if (jsonArr != null) {
|
||||
for (int i = 0; i < jsonArr.length(); i++) {
|
||||
pName = (String) jsonArr.get(i);
|
||||
pValue = jsonObj.getString(pName);
|
||||
logger.info( pName + " - " + pValue);
|
||||
queryParams.put(pName, pValue);
|
||||
}
|
||||
} else {
|
||||
throw new WebApplicationException(Response
|
||||
.status(Status.BAD_REQUEST)
|
||||
.entity("JSON body empty").build());
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new WebApplicationException(Response
|
||||
.status(Status.BAD_REQUEST)
|
||||
.entity("JSON body is wrong").build());
|
||||
}
|
||||
|
||||
|
||||
this.readExtraDataAndReportingService.tempSaveExtraData(datasetType, datasetName, datasetPKValue, queryParams);
|
||||
|
||||
EntityIdentifier entityIdentifier = new EntityIdentifier(Long.valueOf(datasetPKValue));
|
||||
|
||||
return Response.ok().entity(entityIdentifier).build();
|
||||
} catch (InvalidSqlException e) {
|
||||
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
|
||||
|
||||
ErrorResponse err = new ErrorResponse("extradata.invalid.sql", "sql", e.getSql());
|
||||
allErrors.add(err);
|
||||
|
||||
logger.info("way bad: " + err.toString());
|
||||
throw new WebApplicationException(Response
|
||||
.status(Status.BAD_REQUEST)
|
||||
.entity(new ErrorResponseList(allErrors)).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user