Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding query string capability to filter data by column and exact value #24

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,14 @@ FakesAssemblies/
License.config
/Blomsterringen.Web/imagecache
maildrop
.idea/.idea.Geta.DdsAdmin/riderModule.iml
gatisb marked this conversation as resolved.
Show resolved Hide resolved
.idea/.idea.Geta.DdsAdmin/.idea/vcs.xml
.idea/.idea.Geta.DdsAdmin/.idea/misc.xml
.idea/.idea.Geta.DdsAdmin/.idea/indexLayout.xml
.idea/.idea.Geta.DdsAdmin/.idea/.name
.idea/.idea.Geta.DdsAdmin/.idea/.idea.Geta.DdsAdmin.iml
.idea/.idea.Geta.DdsAdmin/.idea/contentModel.xml
.idea/.idea.Geta.DdsAdmin/.idea/modules.xml
.idea/.idea.Geta.DdsAdmin/.idea/projectSettingsUpdater.xml
.idea/.idea.Geta.DdsAdmin/.idea/workspace.xml
.idea/.idea.Geta.DdsAdmin/.idea/encodings.xml
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ All notable changes to this project will be documented in this file.

## [11.0.0]
- Upgraded to CMS 11
- Upgraded to framework version 4.6.1
- Upgraded to framework version 4.6.1

## [11.0.4.6]
- Adding query string capability to filter data by column and exact value
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Where can I get it?
1. Add [EPiServer Nuget feed](http://nuget.episerver.com/en/Feed/) in Visual Studio Package Manager options (Tools ->Options -> Package Manager -> Package Sources).
1. Install DDSAdmin via NuGet in Visual Studio. Ensure that you also install the required dependencies.
1. Rebuild your solution.
1. Start editing your data in EPiServer DDS storages. It will be available in CMS menu: Geta->DDS Admin.
1. Start editing your data in EPiServer DDS storage's. It will be available in CMS menu: Geta->DDS Admin.

Where can I get more info?
------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/Dds/Interfaces/ICrudService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public interface ICrudService
{
StringResponse Create(string storeName, Dictionary<string, string> values);
StringResponse Delete(string storeName, string identityId);
ReadResponse Read(string storeName, int start, int pageSize, string search, int sortByColumn, string sortDirection);
ReadResponse Read(string storeName, int start, int pageSize, string search, int sortByColumn, string sortDirection, string filterColumnName, string filter);
gatisb marked this conversation as resolved.
Show resolved Hide resolved
StringResponse Update(string storeName, int columnId, string value, string id, string columnName);
}
}
38 changes: 27 additions & 11 deletions src/Dds/Services/CrudService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public StringResponse Delete(string storeName, string identityId)
return response;
}

public ReadResponse Read(string storeName, int start, int pageSize, string search, int sortByColumn, string sortDirection)
public ReadResponse Read(string storeName, int start, int pageSize, string search, int sortByColumn, string sortDirection, string filterColumnName, string filter)
{
var response = new ReadResponse { Success = false };
logger.Debug("Read started");
Expand All @@ -83,22 +83,38 @@ public ReadResponse Read(string storeName, int start, int pageSize, string searc
var store = DynamicDataStoreFactory.Instance.GetStore(storeName);
var storeMetadata = store.Metadata();

// TODO: we cannot order here due to fact that this is PropertyBag, if we could it would be great performance boost
// var orderBy = sortByColumn == 0 ? "Id" : StoreMetadata.Columns.ToList()[sortByColumn - 1].PropertyName;
var query = store.ItemsAsPropertyBag(); // .OrderBy(orderBy);
List<PropertyBag> data;
int count;

var data = sortByColumn == 0 && string.IsNullOrEmpty(search)
? (sortDirection == "asc"
? query.OrderBy(r => r.Id).Skip(start).Take(pageSize).ToList()
: query.OrderByDescending(r => r.Id).Skip(start).Take(pageSize).ToList())
: query.ToList();
var preSorted = false;

if (string.IsNullOrWhiteSpace(filterColumnName) || string.IsNullOrWhiteSpace(filter))
gatisb marked this conversation as resolved.
Show resolved Hide resolved
{
// TODO: we cannot order here due to fact that this is PropertyBag, if we could it would be great performance boost
// var orderBy = sortByColumn == 0 ? "Id" : StoreMetadata.Columns.ToList()[sortByColumn - 1].PropertyName;
var query = store.ItemsAsPropertyBag(); // .OrderBy(orderBy);

preSorted = sortByColumn == 0 && string.IsNullOrEmpty(search);
gatisb marked this conversation as resolved.
Show resolved Hide resolved

data = preSorted
? (sortDirection == "asc"
? query.OrderBy(r => r.Id).Skip(start).Take(pageSize).ToList()
: query.OrderByDescending(r => r.Id).Skip(start).Take(pageSize).ToList())
: query.ToList();
count = query.Count();
}
else
{
data = store.FindAsPropertyBag(filterColumnName, filter).ToList();
count = data.Count;
}

List<List<string>> stringData;
if (sortByColumn == 0 && string.IsNullOrEmpty(search))
if (preSorted)
{
// no sorting and no filtering, use fast code then
stringData = FormatData(storeMetadata, data);
totalCount = query.Count();
totalCount = count;
}
else
{
Expand Down
16 changes: 14 additions & 2 deletions src/Dds/Services/StoreService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,24 @@ public bool Delete(string storeName, Identity id)
}
}

public bool Flush(string storeName)
public bool Flush(string storeName, string filterColumnName, string filter)
gatisb marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
var store = DynamicDataStoreFactory.Instance.GetStore(storeName);
store.DeleteAll();
if (!string.IsNullOrWhiteSpace(filterColumnName) && !string.IsNullOrWhiteSpace(filter))
gatisb marked this conversation as resolved.
Show resolved Hide resolved
{
var itemsToBeDeleted = store.FindAsPropertyBag(filterColumnName, filter).ToList();
foreach (var itemToBeDeleted in itemsToBeDeleted)
{
store.Delete(itemToBeDeleted.Id);
}
}
else
{
store.DeleteAll();
}

return true;
}
catch (Exception ex)
Expand Down
Binary file modified src/modules/_protected/Geta.DdsAdmin/Admin/Constants.cs
Binary file not shown.
10 changes: 7 additions & 3 deletions src/modules/_protected/Geta.DdsAdmin/Admin/Data.ashx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private BaseResponse Delete(HttpContext context, string storeName)
return SerializeResponse(context, deleteResponse);
}

private BaseResponse Read(HttpContext context, string storeName)
private BaseResponse Read(HttpContext context, string storeName, string filterColumnName, string filter)
gatisb marked this conversation as resolved.
Show resolved Hide resolved
{
int start = Convert.ToInt32(context.Request.QueryString["iDisplayStart"]);
int pageSize = Convert.ToInt32(context.Request.QueryString["iDisplayLength"]);
Expand All @@ -82,7 +82,7 @@ private BaseResponse Read(HttpContext context, string storeName)
int sortByColumn = Convert.ToInt32(context.Request.QueryString["iSortCol_0"]);
string sortDirection = context.Request.QueryString["sSortDir_0"];

var readResponse = this.crudService.Read(storeName, start, pageSize, search, sortByColumn, sortDirection);
var readResponse = this.crudService.Read(storeName, start, pageSize, search, sortByColumn, sortDirection, filterColumnName, filter);

var result = new
{
Expand Down Expand Up @@ -113,6 +113,10 @@ private void WriteResponse(HttpContext context)
logger.InfoFormat("Operation:{0}", operation);
string storeName = context.Request.QueryString[Constants.StoreKey];
logger.InfoFormat("Store:{0}", operation);
string filterColumnName = context.Request.QueryString[Constants.FilterColumnNameKey];
logger.InfoFormat("Filter column name:{0}", filterColumnName);
string filter = context.Request.QueryString[Constants.FilterKey];
logger.InfoFormat("Filter:{0}", filter);

context.Response.Clear();
context.Response.ClearContent();
Expand All @@ -123,7 +127,7 @@ private void WriteResponse(HttpContext context)
{
case "read":
{
response = Read(context, storeName);
response = Read(context, storeName, filterColumnName, filter);
}
break;
case "update":
Expand Down
12 changes: 7 additions & 5 deletions src/modules/_protected/Geta.DdsAdmin/Admin/DdsAdmin.aspx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<html>
<head runat="server" ID="head1">
<meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>
<title><%# CurrentStoreName %></title>
<title><%# CurrentStoreName %> <%# CurrentFilterMessage%></title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"> </script>
<script type="text/javascript">
if (typeof jQuery == 'undefined') {
Expand Down Expand Up @@ -49,17 +49,19 @@
</asp:repeater>
</form>

<h3><%= string.IsNullOrEmpty(CustomHeading) ? string.Format("Selected Store Type: {0}", CurrentStoreName) : CustomHeading %></h3>
<h3><%= string.IsNullOrEmpty(CustomHeading) ? string.Format("Selected Store Type: {0}", CurrentStoreName) : CustomHeading %> <%= CurrentFilterMessage %></h3>
<%= CustomMessage %>

<form runat="server">
<span class="epi-cmsButton">
<asp:Button runat="server" ID="Flush" Text="Delete All Data" OnClick="FlushStore" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" OnClientClick="return confirm('Are you really want to delete all data from ths table??')"/>
<asp:Button runat="server" ID="Flush" OnClick="FlushStore" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" />
gatisb marked this conversation as resolved.
Show resolved Hide resolved
</span>
<span class="epi-cmsButton">
<asp:Button runat="server" ID="Export" Text="Export to Excel" OnClick="ExportStore" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Export"/>
<asp:Button runat="server" ID="Export" OnClick="ExportStore" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Export"/>
</span>
<input type="hidden" name="CurrentStoreName" value="<%= CurrentStoreName %>"/>
<input type="hidden" name="CurrentFilterColumnName" value="<%= CurrentFilterColumnName %>"/>
<input type="hidden" name="CurrentFilter" value="<%= CurrentFilter %>"/>
</form>

<br/>
Expand All @@ -84,7 +86,7 @@

<script type="text/javascript" charset="utf-8">
$(function() {
var storeParameter = "<%= Constants.StoreKey %>=<%= CurrentStoreName %>";
var storeParameter = "<%= GetParameters() %>";
var dataTable = $('#storeItems').dataTable({
sDom: "Rlfrtip",
bJQueryUI: true,
Expand Down
84 changes: 68 additions & 16 deletions src/modules/_protected/Geta.DdsAdmin/Admin/DdsAdmin.aspx.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Data;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -26,8 +26,11 @@ public DdsAdmin()

private int[] HiddenColumns { get; set; }
protected string CurrentStoreName { get; set; }
protected string CurrentFilterColumnName { get; set; }
protected string CurrentFilter { get; set; }
protected string CustomHeading { get; set; }
protected string CustomMessage { get; set; }
protected string CurrentFilterMessage { get; set; }
protected PropertyMap Item { get; set; }
protected StoreMetadata Store { get; set; }

Expand All @@ -47,17 +50,22 @@ protected override void OnPreRender(EventArgs e)

Page.Header.Controls.Add(new Literal
{
Text = "<link type=\"text/css\" rel=\"stylesheet\" href=\"" + Paths.ToClientResource(typeof (MenuProvider), "content/themes/DDSAdmin/custom/minified.css") + "\" />"
Text = "<link type=\"text/css\" rel=\"stylesheet\" href=\"" +
Paths.ToClientResource(typeof(MenuProvider), "content/themes/DDSAdmin/custom/minified.css") +
"\" />"
});

Page.Header.Controls.Add(new Literal
{
Text = "<script src=\"" + Paths.ToClientResource(typeof (MenuProvider), "scripts/datatables-1.9.4/media/js/jquery.dataTables.min.js") + "\"></script>"
Text = "<script src=\"" + Paths.ToClientResource(typeof(MenuProvider),
"scripts/datatables-1.9.4/media/js/jquery.dataTables.min.js") + "\"></script>"
});

Page.Header.Controls.Add(new Literal
{
Text = "<script src=\"" + Paths.ToClientResource(typeof (MenuProvider), "scripts/dataTables.jeditable.min.js") + "\"></script>"
Text = "<script src=\"" +
Paths.ToClientResource(typeof(MenuProvider), "scripts/dataTables.jeditable.min.js") +
"\"></script>"
});
}

Expand Down Expand Up @@ -87,9 +95,28 @@ protected string SetItem(RepeaterItem repeaterItem)
return string.Empty;
}

protected string GetParameters()
{
var result = $"{Constants.StoreKey}={CurrentStoreName}";
gatisb marked this conversation as resolved.
Show resolved Hide resolved

if (CurrentFilterMessage != null)
{
result += $"&{Constants.FilterColumnNameKey}={CurrentFilterColumnName}";
result += $"&{Constants.FilterKey}={CurrentFilter}";
}

return result;
}

private void GetQueryStringParameters()
{
CurrentStoreName = HttpUtility.HtmlEncode(Request.QueryString[Constants.StoreKey]);
CurrentFilterColumnName = HttpUtility.HtmlEncode(Request.QueryString[Constants.FilterColumnNameKey]);
CurrentFilter = HttpUtility.HtmlEncode(Request.QueryString[Constants.FilterKey]);
CurrentFilterMessage =
!string.IsNullOrWhiteSpace(CurrentFilterColumnName) && !string.IsNullOrWhiteSpace(CurrentFilter)
? $"filtered by {CurrentFilterColumnName} = {CurrentFilter}"
: null;
CustomHeading = HttpUtility.HtmlEncode(Request.QueryString[Constants.HeadingKey]);
CustomMessage = HttpUtility.HtmlEncode(Request.QueryString[Constants.MessageKey]);

Expand All @@ -101,10 +128,10 @@ private void GetQueryStringParameters()
}

HiddenColumns = hiddenColumns.Split(new[]
{
","
},
StringSplitOptions.RemoveEmptyEntries).Select(item => Convert.ToInt32(item)).ToArray();
{
","
},
StringSplitOptions.RemoveEmptyEntries).Select(item => Convert.ToInt32(item)).ToArray();
}

private void LoadAndDisplayData()
Expand All @@ -127,20 +154,34 @@ private void LoadAndDisplayData()
repForm.DataSource = Store.Columns;
repColumnsHeader.DataBind();
repForm.DataBind();

Flush.Text = string.IsNullOrWhiteSpace(CurrentFilterMessage) ? "Delete all data" : "Delete filtered data";
Flush.OnClientClick = string.IsNullOrWhiteSpace(CurrentFilterMessage)
? "return confirm('Do you really want to delete all data from this table?')"
: "return confirm('Do you really want to delete filtered data from this table?')";
Export.Text = string.IsNullOrWhiteSpace(CurrentFilterMessage)
? "Export to Excel"
: "Export filtered data to Excel";
}

protected void FlushStore(object sender, EventArgs e)
{
var storeName = Request.Form["CurrentStoreName"];
_storeService.Flush(storeName);
var filterColumnName = Request.Form["CurrentFilterColumnName"];
var filter = Request.Form["CurrentFilter"];

_storeService.Flush(storeName, filterColumnName, filter);

Response.Redirect(Request.RawUrl);
}

protected void ExportStore(object sender, EventArgs e)
{
var storeName = Request.Form["CurrentStoreName"];
var ddsDataSet = GetDdsStoreAsDataSet(storeName);
var filterColumnName = Request.Form["CurrentFilterColumnName"];
var filter = Request.Form["CurrentFilter"];

var ddsDataSet = GetDdsStoreAsDataSet(storeName, filterColumnName, filter);

using (var wb = new XLWorkbook())
{
Expand All @@ -150,7 +191,18 @@ protected void ExportStore(object sender, EventArgs e)
Response.Buffer = true;
Response.Charset = "";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", $"attachment;filename={storeName}.xlsx");
if (!string.IsNullOrWhiteSpace(filterColumnName) && !string.IsNullOrWhiteSpace(filter))
{
var fileName = $"{storeName}.{filterColumnName}.{filter}.xlsx";
Path.GetInvalidFileNameChars()
.Aggregate(fileName, (current, c) => current.Replace(c, '_'));
Response.AddHeader("content-disposition", $"attachment;filename={fileName.Substring(0, Math.Min(fileName.Length, 200))}");
}
else
{
Response.AddHeader("content-disposition", $"attachment;filename={storeName}.xlsx");
}

using (var MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
Expand All @@ -161,20 +213,20 @@ protected void ExportStore(object sender, EventArgs e)
}
}

private DataSet GetDdsStoreAsDataSet(string storeName)
private DataSet GetDdsStoreAsDataSet(string storeName, string filterColumnName, string filter)
{
var dataTable = new DataTable("record");

var columns = _storeService.GetMetadata(storeName);

foreach (var column in columns.Columns)
{
dataTable.Columns.Add(column.PropertyName, typeof (string));
dataTable.Columns.Add(column.PropertyName, typeof(string));
}

var allRecords = _crudService.Read(storeName, 0, int.MaxValue, null, 0, null);
var allRecords = _crudService.Read(storeName, 0, int.MaxValue, null, 0, null, filterColumnName, filter);

if (allRecords == null || !allRecords.Success || allRecords.TotalCount == 0)
if (allRecords == null || !allRecords.Success)
{
return null;
}
Expand Down Expand Up @@ -203,4 +255,4 @@ private DataSet GetDdsStoreAsDataSet(string storeName)
};
}
}
}
}
Loading