diff --git a/Roadmap.txt b/Roadmap.txt
index 3d8886eb..9764ecfd 100644
--- a/Roadmap.txt
+++ b/Roadmap.txt
@@ -1,6 +1,6 @@
下一主版本:
- 导出看板功能;
+ ok 导出看板功能;
数据分析添加项目概念,用于分组管理数据集、图表、看板;
表格图表轮播效果;
看板展示页面可显示数据集结果数据;
diff --git a/datagear-analysis/src/main/java/org/datagear/analysis/TemplateDashboardWidgetResManager.java b/datagear-analysis/src/main/java/org/datagear/analysis/TemplateDashboardWidgetResManager.java
index d2280caf..6b03de7c 100644
--- a/datagear-analysis/src/main/java/org/datagear/analysis/TemplateDashboardWidgetResManager.java
+++ b/datagear-analysis/src/main/java/org/datagear/analysis/TemplateDashboardWidgetResManager.java
@@ -111,6 +111,15 @@ public interface TemplateDashboardWidgetResManager
*/
void copyFrom(String id, File directory) throws IOException;
+ /**
+ * 将指定{@linkplain TemplateDashboardWidget#getId()}的所有资源拷贝至目标目录。
+ *
+ * @param id
+ * @param directory
+ * @throws IOException
+ */
+ void copyTo(String id, File directory) throws IOException;
+
/**
* 是否包含指定名称的资源。
*
diff --git a/datagear-analysis/src/main/java/org/datagear/analysis/support/FileTemplateDashboardWidgetResManager.java b/datagear-analysis/src/main/java/org/datagear/analysis/support/FileTemplateDashboardWidgetResManager.java
index bef0e56a..65b7252d 100644
--- a/datagear-analysis/src/main/java/org/datagear/analysis/support/FileTemplateDashboardWidgetResManager.java
+++ b/datagear-analysis/src/main/java/org/datagear/analysis/support/FileTemplateDashboardWidgetResManager.java
@@ -148,6 +148,13 @@ public class FileTemplateDashboardWidgetResManager extends AbstractTemplateDashb
IOUtil.copy(directory, myDirectory, false);
}
+ @Override
+ public void copyTo(String id, File directory) throws IOException
+ {
+ File myDirectory = FileUtil.getDirectory(this.rootDirectory, id);
+ IOUtil.copy(myDirectory, directory, false);
+ }
+
@Override
public boolean containsResource(String id, String name)
{
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/AbstractController.java b/datagear-web/src/main/java/org/datagear/web/controller/AbstractController.java
index 98b1c399..c7b6e4a9 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/AbstractController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/AbstractController.java
@@ -4,6 +4,7 @@
package org.datagear.web.controller;
+import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@@ -17,6 +18,7 @@ import javax.servlet.http.HttpServletResponse;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.persistence.PagingQuery;
+import org.datagear.util.IOUtil;
import org.datagear.util.JDBCCompatiblity;
import org.datagear.util.StringUtil;
import org.datagear.web.OperationMessage;
@@ -619,6 +621,24 @@ public abstract class AbstractController
return pathInfo.substring(index + pathPrefix.length());
}
+ /**
+ * 将文件名转换为作为响应下载文件名。
+ *
+ * 此方法会对处理中文乱码问题。
+ *
+ *
+ * @param request
+ * @param response
+ * @param fileName
+ * @return
+ * @throws IOException
+ */
+ protected String toResponseAttachmentFileName(HttpServletRequest request, HttpServletResponse response,
+ String fileName) throws IOException
+ {
+ return new String(fileName.getBytes(RESPONSE_ENCODING), IOUtil.CHARSET_ISO_8859_1);
+ }
+
/**
* 判断对象、字符串、数组、集合、Map是否为空。
*
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/ChartPluginController.java b/datagear-web/src/main/java/org/datagear/web/controller/ChartPluginController.java
index 61fbcd31..7fd46362 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/ChartPluginController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/ChartPluginController.java
@@ -183,7 +183,8 @@ public class ChartPluginController extends AbstractChartPluginAwareController
public void download(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
@RequestParam("id") String[] ids) throws Exception
{
- response.addHeader("Content-Disposition", "attachment;filename=chartPlugins.zip");
+ response.addHeader("Content-Disposition",
+ "attachment;filename=" + toResponseAttachmentFileName(request, response, "chartPlugins.zip"));
response.setContentType("application/octet-stream");
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/DashboardController.java b/datagear-web/src/main/java/org/datagear/web/controller/DashboardController.java
index be8ad44c..0a583cf9 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/DashboardController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/DashboardController.java
@@ -16,6 +16,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -551,6 +552,40 @@ public class DashboardController extends AbstractDataAnalysisController implemen
return "/analysis/dashboard/dashboard_form";
}
+ @RequestMapping("/export")
+ public void export(HttpServletRequest request, HttpServletResponse response, org.springframework.ui.Model model,
+ @RequestParam("id") String id) throws Exception
+ {
+ User user = WebUtils.getUser(request, response);
+
+ HtmlTplDashboardWidgetEntity dashboard = this.htmlTplDashboardWidgetEntityService.getById(user, id);
+
+ if (dashboard == null)
+ throw new RecordNotFoundException();
+
+ TemplateDashboardWidgetResManager dashboardWidgetResManager = this.htmlTplDashboardWidgetEntityService
+ .getHtmlTplDashboardWidgetRenderer().getTemplateDashboardWidgetResManager();
+
+ File tmpDirectory = FileUtil.generateUniqueDirectory(this.tempDirectory);
+ dashboardWidgetResManager.copyTo(dashboard.getId(), tmpDirectory);
+
+ response.addHeader("Content-Disposition",
+ "attachment;filename=" + toResponseAttachmentFileName(request, response, dashboard.getName() + ".zip"));
+ response.setContentType("application/octet-stream");
+
+ ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
+
+ try
+ {
+ IOUtil.writeFileToZipOutputStream(zout, tmpDirectory, "");
+ }
+ finally
+ {
+ zout.flush();
+ zout.close();
+ }
+ }
+
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
@ResponseBody
public ResponseEntity delete(HttpServletRequest request, HttpServletResponse response,
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/DataController.java b/datagear-web/src/main/java/org/datagear/web/controller/DataController.java
index 802704f6..36e662a1 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/DataController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/DataController.java
@@ -686,8 +686,9 @@ public class DataController extends AbstractSchemaConnTableController
}
}.execute();
- response.setCharacterEncoding("utf-8");
- response.setHeader("Content-Disposition", "attachment; filename=" + columnName + "");
+ response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
+ response.setHeader("Content-Disposition",
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, columnName));
InputStream in = null;
OutputStream out = null;
@@ -735,7 +736,8 @@ public class DataController extends AbstractSchemaConnTableController
@RequestParam("file") String fileName) throws Throwable
{
response.setCharacterEncoding(RESPONSE_ENCODING);
- response.setHeader("Content-Disposition", "attachment; filename=" + fileName + "");
+ response.setHeader("Content-Disposition",
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
OutputStream out = null;
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/DataExchangeController.java b/datagear-web/src/main/java/org/datagear/web/controller/DataExchangeController.java
index fc1c34ae..a9ca230f 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/DataExchangeController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/DataExchangeController.java
@@ -1319,7 +1319,7 @@ public class DataExchangeController extends AbstractSchemaConnController
{
response.setCharacterEncoding(RESPONSE_ENCODING);
response.setHeader("Content-Disposition",
- "attachment; filename=" + new String(fileName.getBytes(RESPONSE_ENCODING), "iso-8859-1") + "");
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
File directory = getTempDataExchangeDirectory(dataExchangeId, true);
File file = FileUtil.getFile(directory, fileName);
@@ -1345,7 +1345,7 @@ public class DataExchangeController extends AbstractSchemaConnController
{
response.setCharacterEncoding(RESPONSE_ENCODING);
response.setHeader("Content-Disposition",
- "attachment; filename=" + new String(fileName.getBytes(RESPONSE_ENCODING), "iso-8859-1"));
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
File directory = getTempDataExchangeDirectory(dataExchangeId, true);
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/DataSetController.java b/datagear-web/src/main/java/org/datagear/web/controller/DataSetController.java
index 3cdf3deb..ce385acc 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/DataSetController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/DataSetController.java
@@ -505,10 +505,10 @@ public class DataSetController extends AbstractSchemaConnController
File entityFile = FileUtil.getFile(dataSetDirectory, dataSetEntity.getFileName());
String displayName = dataSetEntity.getDisplayName();
- displayName = new String(displayName.getBytes("UTF-8"), "ISO-8859-1");
- response.setCharacterEncoding("UTF-8");
- response.setHeader("Content-Disposition", "attachment; filename=" + displayName + "");
+ response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
+ response.setHeader("Content-Disposition",
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, displayName));
OutputStream out = response.getOutputStream();
IOUtil.write(entityFile, out);
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/DriverEntityController.java b/datagear-web/src/main/java/org/datagear/web/controller/DriverEntityController.java
index 2057672a..350461af 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/DriverEntityController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/DriverEntityController.java
@@ -245,7 +245,8 @@ public class DriverEntityController extends AbstractController
public void export(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "id", required = false) String[] driverEntityIds) throws Exception
{
- response.addHeader("Content-Disposition", "attachment;filename=drivers.zip");
+ response.addHeader("Content-Disposition",
+ "attachment;filename=" + toResponseAttachmentFileName(request, response, "drivers.zip"));
response.setContentType("application/octet-stream");
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
@@ -393,8 +394,9 @@ public class DriverEntityController extends AbstractController
{
DriverEntity driverEntity = this.driverEntityManager.get(id);
- response.setCharacterEncoding("UTF-8");
- response.setHeader("Content-Disposition", "attachment; filename=" + fileName + "");
+ response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
+ response.setHeader("Content-Disposition",
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, fileName));
OutputStream out = response.getOutputStream();
if (driverEntity != null)
diff --git a/datagear-web/src/main/java/org/datagear/web/controller/SqlpadController.java b/datagear-web/src/main/java/org/datagear/web/controller/SqlpadController.java
index d854feda..cf60c897 100644
--- a/datagear-web/src/main/java/org/datagear/web/controller/SqlpadController.java
+++ b/datagear-web/src/main/java/org/datagear/web/controller/SqlpadController.java
@@ -285,8 +285,9 @@ public class SqlpadController extends AbstractSchemaConnController
if (!blobFile.exists())
throw new FileNotFoundException(value);
- response.setCharacterEncoding("utf-8");
- response.setHeader("Content-Disposition", "attachment; filename=BLOB");
+ response.setCharacterEncoding(IOUtil.CHARSET_UTF_8);
+ response.setHeader("Content-Disposition",
+ "attachment; filename=" + toResponseAttachmentFileName(request, response, "BLOB"));
InputStream in = null;
OutputStream out = null;
diff --git a/datagear-web/src/main/resources/org/datagear/web/locales/datagear.properties b/datagear-web/src/main/resources/org/datagear/web/locales/datagear.properties
index a5626dc8..fed17279 100644
--- a/datagear-web/src/main/resources/org/datagear/web/locales/datagear.properties
+++ b/datagear-web/src/main/resources/org/datagear/web/locales/datagear.properties
@@ -753,7 +753,7 @@ dashboard.editDashboard=编辑看板
dashboard.viewDashboard=查看看板
dashboard.selectDashboard=选择看板
dashboard.importDashboard=导入看板
-dashboard.name=名称
+dashboard.name=看板名称
dashboard.template=模板内容
dashboard.templateEncoding=HTML模板编码
dashboard.templateName=模板文件名
@@ -762,7 +762,7 @@ dashboard.createTime=创建时间
dashboard.show=展示
dashboard.import.selectFile=选择文件
dashboard.import.desc=文件格式应为:*.html、*.htm、*.zip
-dashboard.import.template.desc=多个模板以英文逗号(,)分隔
+dashboard.import.templateName.desc=导入文件中作为看板模板的文件名,应是*.html、*.htm文件,多个模板以英文逗号(,)分隔
dashboard.import.validation.importDashboardFileRequired=请选择看板文件
dashboard.import.templateFileNotExists=导入看板文件中没有找到[{0}]模板文件
dashboard.typeChartIdHere=在此输入图表ID
diff --git a/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_grid.ftl b/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_grid.ftl
index 113504ed..55509896 100644
--- a/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_grid.ftl
+++ b/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_grid.ftl
@@ -26,14 +26,19 @@ selectOperation 是否选择操作,允许为null
<#else>
-
-
+
+
+
+
<#if !(currentUser.anonymous)>
#if>
+
#if>
@@ -58,8 +63,25 @@ selectOperation 是否选择操作,允许为null
(function(po)
{
$.initButtons(po.element(".operation"));
+ po.element(".addGroupSelect").selectmenu(
+ {
+ appendTo: po.element(),
+ classes:
+ {
+ "ui-selectmenu-button": "ui-button-icon-only splitbutton-select",
+ "ui-selectmenu-menu": "ui-widget-shadow ui-widget ui-widget-content"
+ },
+ select: function(event, ui)
+ {
+ var action = $(ui.item).attr("value");
+
+ if(action == "importDashboard")
+ po.open(po.url("import"));
+ }
+ });
+ po.element(".addGroup").controlgroup();
po.initDataFilter();
-
+
po.currentUser = <@writeJson var=currentUser />;
po.url = function(action)
@@ -84,11 +106,6 @@ selectOperation 是否选择操作,允许为null
});
});
- po.element("input[name=importButton]").click(function()
- {
- po.open(po.url("import"));
- });
-
po.element("input[name=editButton]").click(function()
{
po.executeOnSelect(function(row)
@@ -138,6 +155,16 @@ selectOperation 是否选择操作,允许为null
window.open(showUrl, showUrl);
});
});
+
+ po.element("input[name=exportButton]").click(function()
+ {
+ po.executeOnSelect(function(row)
+ {
+ var data = {"id" : row.id};
+
+ po.open(po.url("export"), { target: "_blank", data : data });
+ });
+ });
po.element("input[name=deleteButton]").click(
function()
diff --git a/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_import.ftl b/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_import.ftl
index 0466fbed..2eb418bf 100644
--- a/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_import.ftl
+++ b/datagear-web/src/main/resources/org/datagear/web/webapp/view/freemarker/analysis/dashboard/dashboard_import.ftl
@@ -13,11 +13,13 @@