forked from p81075629/datagear
添加图表插件管理、上传、下载功能
This commit is contained in:
parent
b5d3389d5e
commit
51143ad430
|
@ -24,10 +24,10 @@ public interface ChartPluginManager
|
|||
/**
|
||||
* 移除指定ID的{@linkplain ChartPlugin}。
|
||||
*
|
||||
* @param id
|
||||
* @param ids
|
||||
* @return 被移除的{@linkplain ChartPlugin}或者{@code null}。
|
||||
*/
|
||||
ChartPlugin<?> remove(String id);
|
||||
ChartPlugin<?>[] remove(String... ids);
|
||||
|
||||
/**
|
||||
* 获取指定ID的{@linkplain ChartPlugin}。
|
||||
|
|
|
@ -86,6 +86,21 @@ public abstract class AbstractChartPluginManager implements ChartPluginManager
|
|||
return put;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除{@linkplain ChartPlugin}。
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
protected ChartPlugin<?>[] removeChartPlugins(String[] ids)
|
||||
{
|
||||
ChartPlugin<?>[] removed = new ChartPlugin<?>[ids.length];
|
||||
|
||||
for (int i = 0; i < ids.length; i++)
|
||||
removed[i] = removeChartPlugin(ids[i]);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除{@linkplain ChartPlugin}。
|
||||
*
|
||||
|
@ -128,8 +143,7 @@ public abstract class AbstractChartPluginManager implements ChartPluginManager
|
|||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends RenderContext> List<ChartPlugin<T>> findChartPlugins(
|
||||
Class<? extends T> renderContextType)
|
||||
protected <T extends RenderContext> List<ChartPlugin<T>> findChartPlugins(Class<? extends T> renderContextType)
|
||||
{
|
||||
List<ChartPlugin<T>> reChartPlugins = new ArrayList<ChartPlugin<T>>();
|
||||
|
||||
|
@ -232,23 +246,27 @@ public abstract class AbstractChartPluginManager implements ChartPluginManager
|
|||
|
||||
Version myVersion = null;
|
||||
Version oldVersion = null;
|
||||
|
||||
if(!StringUtil.isEmpty(my.getVersion()))
|
||||
|
||||
if (!StringUtil.isEmpty(my.getVersion()))
|
||||
{
|
||||
try
|
||||
{
|
||||
myVersion = Version.valueOf(my.getVersion());
|
||||
}
|
||||
catch(Exception e) {}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if(!StringUtil.isEmpty(old.getVersion()))
|
||||
if (!StringUtil.isEmpty(old.getVersion()))
|
||||
{
|
||||
try
|
||||
{
|
||||
oldVersion = Version.valueOf(old.getVersion());
|
||||
}
|
||||
catch(Exception e) {}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(oldVersion) && StringUtil.isEmpty(myVersion))
|
||||
|
@ -258,7 +276,7 @@ public abstract class AbstractChartPluginManager implements ChartPluginManager
|
|||
else if (StringUtil.isEmpty(myVersion))
|
||||
replace = false;
|
||||
else
|
||||
replace = myVersion.isHigherThan(oldVersion);
|
||||
replace = !myVersion.isLowerThan(oldVersion);
|
||||
|
||||
return replace;
|
||||
}
|
||||
|
|
|
@ -52,13 +52,13 @@ public class ConcurrentChartPluginManager extends AbstractChartPluginManager
|
|||
}
|
||||
|
||||
@Override
|
||||
public ChartPlugin<?> remove(String id)
|
||||
public ChartPlugin<?>[] remove(String... ids)
|
||||
{
|
||||
WriteLock writeLock = this.lock.writeLock();
|
||||
|
||||
try
|
||||
{
|
||||
return removeChartPlugin(id);
|
||||
return removeChartPlugins(ids);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -36,9 +36,9 @@ public class SimpleChartPluginManager extends AbstractChartPluginManager
|
|||
}
|
||||
|
||||
@Override
|
||||
public ChartPlugin<?> remove(String id)
|
||||
public ChartPlugin<?>[] remove(String... ids)
|
||||
{
|
||||
return removeChartPlugin(id);
|
||||
return removeChartPlugins(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.datagear.analysis.ChartPlugin;
|
||||
import org.datagear.analysis.ChartPluginManager;
|
||||
|
@ -138,7 +139,7 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
return ids;
|
||||
}
|
||||
|
||||
protected void upload(File file, Set<HtmlChartPlugin<?>> ids, int depth) throws IOException
|
||||
protected void upload(File file, Set<HtmlChartPlugin<?>> plugins, int depth) throws IOException
|
||||
{
|
||||
if (depth > 1 || !file.exists())
|
||||
return;
|
||||
|
@ -149,7 +150,11 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
{
|
||||
String name = generateUniquePluginFileName(file.getName());
|
||||
File pluginFile = FileUtil.getFile(this.directory, name);
|
||||
IOUtil.copy(file, pluginFile);
|
||||
IOUtil.copy(file, pluginFile, false);
|
||||
|
||||
HtmlChartPlugin<?> plugin = loadAndRegister(pluginFile);
|
||||
if (plugin != null)
|
||||
plugins.add(plugin);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -157,7 +162,7 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
if (children != null)
|
||||
{
|
||||
for (File child : children)
|
||||
upload(child, ids, depth + 1);
|
||||
upload(child, plugins, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,15 +170,19 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
{
|
||||
String name = generateUniquePluginFileName(file.getName());
|
||||
File pluginFile = FileUtil.getFile(this.directory, name);
|
||||
IOUtil.copy(file, pluginFile);
|
||||
IOUtil.copy(file, pluginFile, false);
|
||||
|
||||
HtmlChartPlugin<?> plugin = loadAndRegister(pluginFile);
|
||||
if (plugin != null)
|
||||
plugins.add(plugin);
|
||||
}
|
||||
else if (file.getName().toLowerCase().endsWith(".zip"))
|
||||
{
|
||||
File tmpDirectory = FileUtil.createTempDirectory("dgcp");
|
||||
File tmpDirectory = FileUtil.createTempDirectory();
|
||||
|
||||
IOUtil.unzip(IOUtil.getZipInputStream(file), tmpDirectory);
|
||||
|
||||
upload(tmpDirectory, ids, depth + 1);
|
||||
upload(tmpDirectory, plugins, depth + 1);
|
||||
|
||||
FileUtil.deleteFile(tmpDirectory);
|
||||
}
|
||||
|
@ -210,6 +219,35 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载指定ID的{@linkplain ChartPlugin}。
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void download(ZipOutputStream out, String... ids) throws IOException
|
||||
{
|
||||
ReadLock readLock = this.lock.readLock();
|
||||
|
||||
try
|
||||
{
|
||||
readLock.lock();
|
||||
|
||||
File tmpDirectory = FileUtil.createTempDirectory();
|
||||
|
||||
for (String id : ids)
|
||||
{
|
||||
PluginFileInfo pluginFileInfo = this.chartPluginFileInfoMap.get(id);
|
||||
IOUtil.copy(pluginFileInfo.getFile(), tmpDirectory, true);
|
||||
}
|
||||
|
||||
IOUtil.writeFileToZipOutputStream(out, tmpDirectory, "");
|
||||
}
|
||||
finally
|
||||
{
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends RenderContext> ChartPlugin<T> get(String id)
|
||||
{
|
||||
|
@ -312,20 +350,17 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
{
|
||||
ChartPlugin<?> plugin = this.htmlChartPluginLoader.loadFile(unload);
|
||||
|
||||
String pluginId = (plugin == null ? IDUtil.uuid() : plugin.getId());
|
||||
|
||||
// 无论是否加载成功,都应该存入PluginFileInfo,避免每次checkForReload()时都会将其当做是未加载的
|
||||
this.chartPluginFileInfoMap.put(IDUtil.uuid(), new PluginFileInfo(unload));
|
||||
this.chartPluginFileInfoMap.put(pluginId, new PluginFileInfo(unload));
|
||||
|
||||
if (plugin != null)
|
||||
registerChartPlugin(plugin);
|
||||
}
|
||||
|
||||
for (PluginFileInfo reload : reloads)
|
||||
{
|
||||
ChartPlugin<?> plugin = this.htmlChartPluginLoader.loadFile(reload.getFile());
|
||||
|
||||
if (plugin != null)
|
||||
registerChartPlugin(plugin);
|
||||
}
|
||||
loadAndRegister(reload.getFile());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -333,6 +368,25 @@ public class DirectoryHtmlChartPluginManager extends ConcurrentChartPluginManage
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载并注册插件,如果注册失败,将返回{@code null}。
|
||||
*
|
||||
* @param pluginFile
|
||||
* @return
|
||||
*/
|
||||
protected HtmlChartPlugin<?> loadAndRegister(File pluginFile)
|
||||
{
|
||||
HtmlChartPlugin<?> plugin = this.htmlChartPluginLoader.loadFile(pluginFile);
|
||||
|
||||
if (plugin != null)
|
||||
{
|
||||
boolean reg = registerChartPlugin(plugin);
|
||||
return (reg ? plugin : null);
|
||||
}
|
||||
else
|
||||
return plugin;
|
||||
}
|
||||
|
||||
protected static class PluginFileInfo
|
||||
{
|
||||
private File file;
|
||||
|
|
|
@ -345,7 +345,7 @@ public class HtmlChartPluginLoader
|
|||
{
|
||||
try
|
||||
{
|
||||
File tmpDirectory = FileUtil.createTempDirectory("dgcpl");
|
||||
File tmpDirectory = FileUtil.createTempDirectory();
|
||||
|
||||
IOUtil.unzip(in, tmpDirectory);
|
||||
|
||||
|
|
|
@ -322,6 +322,21 @@ public class FileUtil
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为指定后缀的文件名。
|
||||
*
|
||||
* @param fileName
|
||||
* @param extension
|
||||
* @return
|
||||
*/
|
||||
public static boolean isExtension(String fileName, String extension)
|
||||
{
|
||||
if (StringUtil.isEmpty(fileName))
|
||||
return false;
|
||||
|
||||
return fileName.toLowerCase().endsWith(extension.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接路径。
|
||||
*
|
||||
|
@ -457,12 +472,13 @@ public class FileUtil
|
|||
/**
|
||||
* 创建临时文件夹。
|
||||
*
|
||||
* @param prefix
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static File createTempDirectory(String prefix) throws IOException
|
||||
public static File createTempDirectory() throws IOException
|
||||
{
|
||||
String prefix = Global.PRODUCT_NAME_EN.toUpperCase() + "_TMP_DIR";
|
||||
|
||||
File tmp = File.createTempFile(prefix, null);
|
||||
|
||||
if (!tmp.delete())
|
||||
|
@ -473,4 +489,29 @@ public class FileUtil
|
|||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建临时文件。
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static File createTempFile() throws IOException
|
||||
{
|
||||
String prefix = Global.PRODUCT_NAME_EN.toUpperCase() + "_TMP_FILE";
|
||||
return File.createTempFile(prefix, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建临时文件。
|
||||
*
|
||||
* @param extension
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static File createTempFile(String extension) throws IOException
|
||||
{
|
||||
String prefix = Global.PRODUCT_NAME_EN.toUpperCase() + "_TMP_FILE";
|
||||
return File.createTempFile(prefix, extension);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -574,9 +574,10 @@ public class IOUtil
|
|||
*
|
||||
* @param src
|
||||
* @param dest
|
||||
* @param srcAsSubDirectory
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void copy(File src, File dest) throws IOException
|
||||
public static void copy(File src, File dest, boolean srcAsSubDirectory) throws IOException
|
||||
{
|
||||
if (src.isDirectory())
|
||||
{
|
||||
|
@ -585,25 +586,37 @@ public class IOUtil
|
|||
else if (!dest.isDirectory())
|
||||
throw new IllegalArgumentException("[dest] must be directory");
|
||||
|
||||
File targetDirectory = dest;
|
||||
if (srcAsSubDirectory)
|
||||
targetDirectory = FileUtil.getDirectory(dest, src.getName());
|
||||
|
||||
File[] children = src.listFiles();
|
||||
if (children != null)
|
||||
{
|
||||
for (File child : children)
|
||||
copy(child, new File(dest, child.getName()));
|
||||
copy(child, new File(targetDirectory, child.getName()), false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputStream out = null;
|
||||
|
||||
try
|
||||
if (dest.isDirectory())
|
||||
{
|
||||
out = IOUtil.getOutputStream(dest);
|
||||
IOUtil.write(src, out);
|
||||
File destFile = FileUtil.getFile(dest, src.getName());
|
||||
copy(src, destFile, false);
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
IOUtil.close(out);
|
||||
OutputStream out = null;
|
||||
|
||||
try
|
||||
{
|
||||
out = IOUtil.getOutputStream(dest);
|
||||
IOUtil.write(src, out);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.datagear.web.controller;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.datagear.analysis.ChartPlugin;
|
||||
import org.datagear.analysis.Icon;
|
||||
import org.datagear.analysis.RenderStyle;
|
||||
import org.datagear.analysis.support.html.DirectoryHtmlChartPluginManager;
|
||||
import org.datagear.analysis.support.html.HtmlChartPlugin;
|
||||
import org.datagear.analysis.support.html.HtmlRenderContext;
|
||||
import org.datagear.util.i18n.Label;
|
||||
import org.datagear.web.convert.ClassDataConverter;
|
||||
import org.datagear.web.util.KeywordMatcher;
|
||||
import org.datagear.web.util.WebUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
|
||||
/**
|
||||
* 抽象插件相关的控制器。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class AbstractChartPluginAwareController extends AbstractDataAnalysisController
|
||||
{
|
||||
@Autowired
|
||||
private DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager;
|
||||
|
||||
public AbstractChartPluginAwareController()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public AbstractChartPluginAwareController(MessageSource messageSource, ClassDataConverter classDataConverter,
|
||||
DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager)
|
||||
{
|
||||
super(messageSource, classDataConverter);
|
||||
this.directoryHtmlChartPluginManager = directoryHtmlChartPluginManager;
|
||||
}
|
||||
|
||||
public DirectoryHtmlChartPluginManager getDirectoryHtmlChartPluginManager()
|
||||
{
|
||||
return directoryHtmlChartPluginManager;
|
||||
}
|
||||
|
||||
public void setDirectoryHtmlChartPluginManager(DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager)
|
||||
{
|
||||
this.directoryHtmlChartPluginManager = directoryHtmlChartPluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找插件信息列表。
|
||||
*
|
||||
* @param request
|
||||
* @param keyword
|
||||
* @return
|
||||
*/
|
||||
protected List<HtmlChartPluginInfo> findHtmlChartPluginInfos(HttpServletRequest request, String keyword)
|
||||
{
|
||||
List<HtmlChartPluginInfo> pluginInfos = new ArrayList<HtmlChartPluginInfo>();
|
||||
|
||||
List<ChartPlugin<HtmlRenderContext>> plugins = getDirectoryHtmlChartPluginManager()
|
||||
.getAll(HtmlRenderContext.class);
|
||||
|
||||
if (plugins != null)
|
||||
{
|
||||
Locale locale = WebUtils.getLocale(request);
|
||||
RenderStyle renderStyle = resolveRenderStyle(request);
|
||||
|
||||
for (ChartPlugin<HtmlRenderContext> plugin : plugins)
|
||||
{
|
||||
if (plugin instanceof HtmlChartPlugin<?>)
|
||||
{
|
||||
HtmlChartPlugin<HtmlRenderContext> htmlChartPlugin = (HtmlChartPlugin<HtmlRenderContext>) plugin;
|
||||
pluginInfos.add(toHtmlChartPluginInfo(htmlChartPlugin, renderStyle, locale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return KeywordMatcher.<HtmlChartPluginInfo> match(pluginInfos, keyword,
|
||||
new KeywordMatcher.MatchValue<HtmlChartPluginInfo>()
|
||||
{
|
||||
@Override
|
||||
public String[] get(HtmlChartPluginInfo t)
|
||||
{
|
||||
return new String[] { t.getName(), t.getDesc() };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected HtmlChartPluginInfo toHtmlChartPluginInfo(HtmlChartPlugin<?> chartPlugin, RenderStyle renderStyle,
|
||||
Locale locale)
|
||||
{
|
||||
HtmlChartPluginInfo pluginInfo = new HtmlChartPluginInfo();
|
||||
|
||||
pluginInfo.setId(chartPlugin.getId());
|
||||
|
||||
Label nameLabel = chartPlugin.getNameLabel();
|
||||
if (nameLabel != null)
|
||||
pluginInfo.setName(nameLabel.getValue(locale));
|
||||
|
||||
Label descLabel = chartPlugin.getDescLabel();
|
||||
if (descLabel != null)
|
||||
pluginInfo.setDesc(descLabel.getValue(locale));
|
||||
|
||||
Label manualLabel = chartPlugin.getManualLabel();
|
||||
if (manualLabel != null)
|
||||
pluginInfo.setManual(manualLabel.getValue(locale));
|
||||
|
||||
Icon icon = chartPlugin.getIcon(renderStyle);
|
||||
pluginInfo.setHasIcon(icon != null);
|
||||
if (pluginInfo.isHasIcon())
|
||||
pluginInfo.setIconUrl(resolveIconUrl(chartPlugin));
|
||||
|
||||
pluginInfo.setVersion(chartPlugin.getVersion());
|
||||
|
||||
return pluginInfo;
|
||||
}
|
||||
|
||||
protected String resolveIconUrl(HtmlChartPlugin<?> plugin)
|
||||
{
|
||||
return "/analysis/chartPlugin/icon/" + plugin.getId();
|
||||
}
|
||||
|
||||
public static class HtmlChartPluginInfo implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String desc;
|
||||
|
||||
private String manual;
|
||||
|
||||
private boolean hasIcon;
|
||||
|
||||
private String iconUrl;
|
||||
|
||||
private String version;
|
||||
|
||||
public HtmlChartPluginInfo()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public HtmlChartPluginInfo(String id, String name)
|
||||
{
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc()
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc)
|
||||
{
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getManual()
|
||||
{
|
||||
return manual;
|
||||
}
|
||||
|
||||
public void setManual(String manual)
|
||||
{
|
||||
this.manual = manual;
|
||||
}
|
||||
|
||||
public boolean isHasIcon()
|
||||
{
|
||||
return hasIcon;
|
||||
}
|
||||
|
||||
public void setHasIcon(boolean hasIcon)
|
||||
{
|
||||
this.hasIcon = hasIcon;
|
||||
}
|
||||
|
||||
public String getIconUrl()
|
||||
{
|
||||
return iconUrl;
|
||||
}
|
||||
|
||||
public void setIconUrl(String iconUrl)
|
||||
{
|
||||
this.iconUrl = iconUrl;
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version)
|
||||
{
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,12 @@
|
|||
|
||||
package org.datagear.web.controller;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.datagear.analysis.ChartPlugin;
|
||||
import org.datagear.analysis.ChartPluginManager;
|
||||
import org.datagear.analysis.Icon;
|
||||
import org.datagear.analysis.RenderStyle;
|
||||
import org.datagear.analysis.support.html.HtmlChartPlugin;
|
||||
import org.datagear.analysis.support.html.HtmlRenderContext;
|
||||
import org.datagear.management.domain.HtmlChartWidgetEntity;
|
||||
|
@ -28,28 +19,24 @@ import org.datagear.management.service.HtmlChartWidgetEntityService;
|
|||
import org.datagear.persistence.PagingData;
|
||||
import org.datagear.persistence.PagingQuery;
|
||||
import org.datagear.util.IDUtil;
|
||||
import org.datagear.util.IOUtil;
|
||||
import org.datagear.util.i18n.Label;
|
||||
import org.datagear.web.OperationMessage;
|
||||
import org.datagear.web.util.WebUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
/**
|
||||
* 数据集控制器。
|
||||
* 图表控制器。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/analysis/chart")
|
||||
public class ChartController extends AbstractDataAnalysisController
|
||||
public class ChartController extends AbstractChartPluginAwareController
|
||||
{
|
||||
@Autowired
|
||||
private HtmlChartWidgetEntityService htmlChartWidgetEntityService;
|
||||
|
@ -95,10 +82,14 @@ public class ChartController extends AbstractDataAnalysisController
|
|||
{
|
||||
HtmlChartWidgetEntity chart = new HtmlChartWidgetEntity();
|
||||
|
||||
List<HtmlChartPluginInfo> pluginInfos = getAllHtmlChartPluginInfos(request);
|
||||
List<HtmlChartPluginInfo> pluginInfos = findHtmlChartPluginInfos(request, null);
|
||||
|
||||
if (pluginInfos.size() > 0)
|
||||
chart.setChartPlugin(pluginInfos.get(0).getChartPlugin());
|
||||
{
|
||||
String defaultChartPluginId = pluginInfos.get(0).getId();
|
||||
chart.setHtmlChartPlugin((HtmlChartPlugin<HtmlRenderContext>) this.chartPluginManager
|
||||
.<HtmlRenderContext> get(defaultChartPluginId));
|
||||
}
|
||||
|
||||
model.addAttribute("chart", chart);
|
||||
model.addAttribute("pluginInfos", pluginInfos);
|
||||
|
@ -137,7 +128,7 @@ public class ChartController extends AbstractDataAnalysisController
|
|||
if (chart == null)
|
||||
throw new RecordNotFoundException();
|
||||
|
||||
List<HtmlChartPluginInfo> pluginInfos = getAllHtmlChartPluginInfos(request);
|
||||
List<HtmlChartPluginInfo> pluginInfos = findHtmlChartPluginInfos(request, null);
|
||||
|
||||
model.addAttribute("chart", chart);
|
||||
model.addAttribute("pluginInfos", pluginInfos);
|
||||
|
@ -174,7 +165,7 @@ public class ChartController extends AbstractDataAnalysisController
|
|||
if (chart == null)
|
||||
throw new RecordNotFoundException();
|
||||
|
||||
List<HtmlChartPluginInfo> pluginInfos = getAllHtmlChartPluginInfos(request);
|
||||
List<HtmlChartPluginInfo> pluginInfos = findHtmlChartPluginInfos(request, null);
|
||||
|
||||
model.addAttribute("chart", chart);
|
||||
model.addAttribute("pluginInfos", pluginInfos);
|
||||
|
@ -231,41 +222,6 @@ public class ChartController extends AbstractDataAnalysisController
|
|||
return pagingData;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pluginicon/{pluginId}", produces = CONTENT_TYPE_JSON)
|
||||
public void getPluginIcon(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest,
|
||||
@PathVariable("pluginId") String pluginId) throws Exception
|
||||
{
|
||||
ChartPlugin<?> chartPlugin = this.chartPluginManager.get(pluginId);
|
||||
|
||||
if (chartPlugin == null)
|
||||
throw new FileNotFoundException();
|
||||
|
||||
RenderStyle renderStyle = resolveRenderStyle(request);
|
||||
Icon icon = chartPlugin.getIcon(renderStyle);
|
||||
|
||||
if (icon == null)
|
||||
throw new FileNotFoundException();
|
||||
|
||||
long lastModified = icon.getLastModified();
|
||||
if (webRequest.checkNotModified(lastModified))
|
||||
return;
|
||||
|
||||
response.setContentType("image/" + icon.getType());
|
||||
|
||||
OutputStream out = response.getOutputStream();
|
||||
InputStream iconIn = null;
|
||||
|
||||
try
|
||||
{
|
||||
iconIn = icon.getInputStream();
|
||||
IOUtil.write(iconIn, out);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(iconIn);
|
||||
}
|
||||
}
|
||||
|
||||
protected SqlDataSetFactoryEntity[] getSqlDataSetFactoryEntityParams(HttpServletRequest request)
|
||||
{
|
||||
String[] dataSetIds = request.getParameterValues("dataSetId");
|
||||
|
@ -294,123 +250,4 @@ public class ChartController extends AbstractDataAnalysisController
|
|||
if (isEmpty(chart.getChartPlugin()))
|
||||
throw new IllegalInputException();
|
||||
}
|
||||
|
||||
protected List<HtmlChartPluginInfo> getAllHtmlChartPluginInfos(HttpServletRequest request)
|
||||
{
|
||||
List<HtmlChartPluginInfo> pluginInfos = new ArrayList<HtmlChartPluginInfo>();
|
||||
|
||||
List<ChartPlugin<HtmlRenderContext>> plugins = this.chartPluginManager.getAll(HtmlRenderContext.class);
|
||||
|
||||
if (plugins != null)
|
||||
{
|
||||
Locale locale = WebUtils.getLocale(request);
|
||||
RenderStyle renderStyle = resolveRenderStyle(request);
|
||||
|
||||
for (ChartPlugin<HtmlRenderContext> plugin : plugins)
|
||||
{
|
||||
if (plugin instanceof HtmlChartPlugin<?>)
|
||||
{
|
||||
HtmlChartPluginInfo pluginInfo = new HtmlChartPluginInfo();
|
||||
pluginInfo.setChartPlugin((HtmlChartPlugin<HtmlRenderContext>) plugin);
|
||||
|
||||
Label nameLabel = plugin.getNameLabel();
|
||||
if (nameLabel != null)
|
||||
pluginInfo.setName(nameLabel.getValue(locale));
|
||||
|
||||
Label descLabel = plugin.getDescLabel();
|
||||
if (descLabel != null)
|
||||
pluginInfo.setDesc(descLabel.getValue(locale));
|
||||
|
||||
Label manualLabel = plugin.getManualLabel();
|
||||
if (manualLabel != null)
|
||||
pluginInfo.setManual(manualLabel.getValue(locale));
|
||||
|
||||
Icon icon = plugin.getIcon(renderStyle);
|
||||
pluginInfo.setHasIcon(icon != null);
|
||||
|
||||
pluginInfos.add(pluginInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pluginInfos;
|
||||
}
|
||||
|
||||
public static class HtmlChartPluginInfo implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HtmlChartPlugin<HtmlRenderContext> chartPlugin;
|
||||
private String name;
|
||||
private String desc;
|
||||
private String manual;
|
||||
private boolean hasIcon;
|
||||
|
||||
public HtmlChartPluginInfo()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public HtmlChartPluginInfo(HtmlChartPlugin<HtmlRenderContext> chartPlugin, String name)
|
||||
{
|
||||
super();
|
||||
this.chartPlugin = chartPlugin;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public HtmlChartPlugin<HtmlRenderContext> getChartPlugin()
|
||||
{
|
||||
return chartPlugin;
|
||||
}
|
||||
|
||||
public void setChartPlugin(HtmlChartPlugin<HtmlRenderContext> chartPlugin)
|
||||
{
|
||||
this.chartPlugin = chartPlugin;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return this.chartPlugin.getId();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc()
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc)
|
||||
{
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getManual()
|
||||
{
|
||||
return manual;
|
||||
}
|
||||
|
||||
public void setManual(String manual)
|
||||
{
|
||||
this.manual = manual;
|
||||
}
|
||||
|
||||
public boolean isHasIcon()
|
||||
{
|
||||
return hasIcon;
|
||||
}
|
||||
|
||||
public void setHasIcon(boolean hasIcon)
|
||||
{
|
||||
this.hasIcon = hasIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.web.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.datagear.analysis.ChartPlugin;
|
||||
import org.datagear.analysis.Icon;
|
||||
import org.datagear.analysis.RenderStyle;
|
||||
import org.datagear.analysis.support.html.DirectoryHtmlChartPluginManager;
|
||||
import org.datagear.analysis.support.html.HtmlChartPlugin;
|
||||
import org.datagear.analysis.support.html.HtmlChartPluginLoadException;
|
||||
import org.datagear.analysis.support.html.HtmlChartPluginLoader;
|
||||
import org.datagear.util.FileUtil;
|
||||
import org.datagear.util.IOUtil;
|
||||
import org.datagear.util.StringUtil;
|
||||
import org.datagear.web.OperationMessage;
|
||||
import org.datagear.web.convert.ClassDataConverter;
|
||||
import org.datagear.web.util.WebUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 图表插件控制器。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/analysis/chartPlugin")
|
||||
public class ChartPluginController extends AbstractChartPluginAwareController
|
||||
{
|
||||
@Autowired
|
||||
private File tempDirectory;
|
||||
|
||||
public ChartPluginController()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public ChartPluginController(MessageSource messageSource, ClassDataConverter classDataConverter,
|
||||
DirectoryHtmlChartPluginManager directoryHtmlChartPluginManager, File tempDirectory)
|
||||
{
|
||||
super(messageSource, classDataConverter, directoryHtmlChartPluginManager);
|
||||
}
|
||||
|
||||
public File getTempDirectory()
|
||||
{
|
||||
return tempDirectory;
|
||||
}
|
||||
|
||||
public void setTempDirectory(File tempDirectory)
|
||||
{
|
||||
this.tempDirectory = tempDirectory;
|
||||
}
|
||||
|
||||
@RequestMapping("/upload")
|
||||
public String upload(HttpServletRequest request, org.springframework.ui.Model model)
|
||||
{
|
||||
return "/analysis/chartPlugin/chartPlugin_upload";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/uploadFile", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public Map<String, Object> uploadFile(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam("file") MultipartFile multipartFile) throws Exception
|
||||
{
|
||||
String pluginFileName = "";
|
||||
|
||||
File tmpDirectory = FileUtil.generateUniqueDirectory(this.tempDirectory);
|
||||
|
||||
String zipFileName = multipartFile.getOriginalFilename();
|
||||
if (StringUtil.isEmpty(zipFileName))
|
||||
zipFileName = "plugin.zip";
|
||||
|
||||
if (!FileUtil.isExtension(zipFileName, ".zip"))
|
||||
zipFileName += ".zip";
|
||||
|
||||
File zipFile = FileUtil.getFile(tmpDirectory, zipFileName);
|
||||
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try
|
||||
{
|
||||
in = multipartFile.getInputStream();
|
||||
out = IOUtil.getOutputStream(zipFile);
|
||||
IOUtil.write(in, out);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(in);
|
||||
IOUtil.close(out);
|
||||
}
|
||||
|
||||
List<HtmlChartPluginInfo> pluginInfos = new ArrayList<HtmlChartPluginInfo>();
|
||||
|
||||
HtmlChartPluginLoader loader = getDirectoryHtmlChartPluginManager().getHtmlChartPluginLoader();
|
||||
|
||||
Locale locale = WebUtils.getLocale(request);
|
||||
RenderStyle renderStyle = resolveRenderStyle(request);
|
||||
|
||||
try
|
||||
{
|
||||
if (loader.isHtmlChartPluginZip(zipFile))
|
||||
{
|
||||
HtmlChartPlugin<?> chartPlugin = loader.loadZip(zipFile);
|
||||
pluginInfos.add(toHtmlChartPluginInfo(chartPlugin, renderStyle, locale));
|
||||
pluginFileName = tmpDirectory.getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
ZipInputStream zin = null;
|
||||
try
|
||||
{
|
||||
zin = IOUtil.getZipInputStream(zipFile);
|
||||
IOUtil.unzip(zin, tmpDirectory);
|
||||
|
||||
Set<HtmlChartPlugin<?>> loaded = loader.loads(tmpDirectory);
|
||||
|
||||
if (!loaded.isEmpty())
|
||||
{
|
||||
for (HtmlChartPlugin<?> chartPlugin : loaded)
|
||||
pluginInfos.add(toHtmlChartPluginInfo(chartPlugin, renderStyle, locale));
|
||||
|
||||
pluginFileName = tmpDirectory.getName();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(zin);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
catch (HtmlChartPluginLoadException e)
|
||||
{
|
||||
}
|
||||
|
||||
Map<String, Object> results = new HashMap<String, Object>();
|
||||
results.put("pluginFileName", pluginFileName);
|
||||
results.put("pluginInfos", pluginInfos);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/saveUpload", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public ResponseEntity<OperationMessage> saveUpload(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam("pluginFileName") String pluginFileName) throws Exception
|
||||
{
|
||||
if (StringUtil.isEmpty(pluginFileName))
|
||||
throw new IllegalInputException();
|
||||
|
||||
File tmpFile = FileUtil.getFile(this.tempDirectory, pluginFileName);
|
||||
|
||||
getDirectoryHtmlChartPluginManager().upload(tmpFile);
|
||||
|
||||
return buildOperationMessageSaveSuccessResponseEntity(request);
|
||||
}
|
||||
|
||||
@RequestMapping("/download")
|
||||
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.setContentType("application/octet-stream");
|
||||
|
||||
ZipOutputStream zout = IOUtil.getZipOutputStream(response.getOutputStream());
|
||||
|
||||
try
|
||||
{
|
||||
getDirectoryHtmlChartPluginManager().download(zout, ids);
|
||||
}
|
||||
finally
|
||||
{
|
||||
zout.flush();
|
||||
zout.close();
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/delete", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
|
||||
@RequestParam("id") String[] ids)
|
||||
{
|
||||
getDirectoryHtmlChartPluginManager().remove(ids);
|
||||
|
||||
return buildOperationMessageDeleteSuccessResponseEntity(request);
|
||||
}
|
||||
|
||||
@RequestMapping("/query")
|
||||
public String query(HttpServletRequest request, org.springframework.ui.Model model)
|
||||
{
|
||||
model.addAttribute(KEY_TITLE_MESSAGE_KEY, "chartPlugin.manageChartPlugin");
|
||||
|
||||
return "/analysis/chartPlugin/chartPlugin_grid";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/queryData", produces = CONTENT_TYPE_JSON)
|
||||
@ResponseBody
|
||||
public List<HtmlChartPluginInfo> queryData(HttpServletRequest request, HttpServletResponse response,
|
||||
final org.springframework.ui.Model springModel,
|
||||
@RequestParam(value = "keyword", required = false) String keyword) throws Exception
|
||||
{
|
||||
return findHtmlChartPluginInfos(request, keyword);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/icon/{pluginId}", produces = CONTENT_TYPE_JSON)
|
||||
public void getPluginIcon(HttpServletRequest request, HttpServletResponse response, WebRequest webRequest,
|
||||
@PathVariable("pluginId") String pluginId) throws Exception
|
||||
{
|
||||
ChartPlugin<?> chartPlugin = getDirectoryHtmlChartPluginManager().get(pluginId);
|
||||
|
||||
if (chartPlugin == null)
|
||||
throw new FileNotFoundException();
|
||||
|
||||
RenderStyle renderStyle = resolveRenderStyle(request);
|
||||
Icon icon = chartPlugin.getIcon(renderStyle);
|
||||
|
||||
if (icon == null)
|
||||
throw new FileNotFoundException();
|
||||
|
||||
long lastModified = icon.getLastModified();
|
||||
if (webRequest.checkNotModified(lastModified))
|
||||
return;
|
||||
|
||||
response.setContentType("image/" + icon.getType());
|
||||
|
||||
OutputStream out = response.getOutputStream();
|
||||
InputStream iconIn = null;
|
||||
|
||||
try
|
||||
{
|
||||
iconIn = icon.getInputStream();
|
||||
IOUtil.write(iconIn, out);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(iconIn);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -321,13 +321,13 @@
|
|||
<property name="authorizationService" ref="authorizationService" />
|
||||
</bean>
|
||||
|
||||
<bean id="chartPluginManager" class="org.datagear.analysis.support.html.DirectoryHtmlChartPluginManager" init-method="init">
|
||||
<bean id="directoryHtmlChartPluginManager" class="org.datagear.analysis.support.html.DirectoryHtmlChartPluginManager" init-method="init">
|
||||
<property name="directory" ref="chartPluginRootDirectory" />
|
||||
</bean>
|
||||
|
||||
<bean id="htmlChartWidgetEntityService" class="org.datagear.management.service.impl.HtmlChartWidgetEntityServiceImpl">
|
||||
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
|
||||
<property name="chartPluginManager" ref="chartPluginManager" />
|
||||
<property name="chartPluginManager" ref="directoryHtmlChartPluginManager" />
|
||||
<property name="sqlDataSetFactoryEntityService" ref="sqlDataSetFactoryEntityService" />
|
||||
<property name="authorizationService" ref="authorizationService" />
|
||||
</bean>
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
<intercept-url pattern="/schemaUrlBuilder/saveScriptCode" access="ROLE_ADMIN" />
|
||||
<intercept-url pattern="/schemaUrlBuilder/previewScriptCode" access="ROLE_ADMIN" />
|
||||
|
||||
<!-- 图表插件管理 -->
|
||||
<intercept-url pattern="/analysis/chartPlugin/icon/*" access="ROLE_USER, IS_AUTHENTICATED_ANONYMOUSLY" />
|
||||
<intercept-url pattern="/analysis/chartPlugin/**" access="ROLE_ADMIN" />
|
||||
|
||||
<intercept-url pattern="/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
|
||||
<intercept-url pattern="/register/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
|
||||
<intercept-url pattern="/resetPassword/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
|
||||
|
|
|
@ -227,6 +227,8 @@ main.manageUser=\u7BA1\u7406\u7528\u6237
|
|||
main.addUser=\u6DFB\u52A0\u7528\u6237
|
||||
main.manageRole=\u7BA1\u7406\u7528\u6237\u7EC4
|
||||
main.manageAuthorization=\u7BA1\u7406\u6388\u6743
|
||||
main.manageChartPlugin=\u7BA1\u7406\u56FE\u8868\u63D2\u4EF6
|
||||
main.uploadChartPlugin=\u4E0A\u4F20\u56FE\u8868\u63D2\u4EF6
|
||||
main.personalSet=\u4E2A\u4EBA\u8BBE\u7F6E
|
||||
main.changeTheme=\u5207\u6362\u80A4\u8272
|
||||
main.changeTheme.lightness=\u6D45\u8272
|
||||
|
@ -639,4 +641,16 @@ dashboard.name=\u540D\u79F0
|
|||
dashboard.template=\u6A21\u677F
|
||||
dashboard.createUser=\u521B\u5EFA\u7528\u6237
|
||||
dashboard.createTime=\u521B\u5EFA\u65F6\u95F4
|
||||
dashboard.show=\u5C55\u793A
|
||||
dashboard.show=\u5C55\u793A
|
||||
|
||||
#Chart plugin
|
||||
chartPlugin.manageChartPlugin=\u7BA1\u7406\u56FE\u8868\u63D2\u4EF6
|
||||
chartPlugin.uploadChartPlugin=\u4E0A\u4F20\u56FE\u8868\u63D2\u4EF6
|
||||
chartPlugin.name=\u540D\u79F0
|
||||
chartPlugin.desc=\u63CF\u8FF0
|
||||
chartPlugin.icon=\u56FE\u6807
|
||||
chartPlugin.version=\u7248\u672C
|
||||
chartPlugin.upload.selectFile=\u9009\u62E9\u6587\u4EF6
|
||||
chartPlugin.upload.desc=\u6587\u4EF6\u683C\u5F0F\u5E94\u4E3A\uFF1A*.zip
|
||||
chartPlugin.upload.review=\u4E0A\u4F20\u9884\u89C8
|
||||
chartPlugin.upload.validation.uploadChartPluginFileRequired=\u8BF7\u9009\u62E9\u5408\u6CD5\u7684\u63D2\u4EF6\u6587\u4EF6
|
|
@ -36,7 +36,7 @@ readonly 是否只读操作,允许为null
|
|||
<#list pluginInfos as pi>
|
||||
<li class="ui-state-default ui-corner-all" chart-plugin-id="${pi.id?html}" title="${pi.name?html}">
|
||||
<#if pi.hasIcon>
|
||||
<a class="plugin-icon" style="background-image: url(${contextPath}/analysis/chart/pluginicon/${pi.id?html})"> </a>
|
||||
<a class="plugin-icon" style="background-image: url(${contextPath}/${pi.iconUrl})"> </a>
|
||||
<#else>
|
||||
<a class="plugin-name">${pi.name?html}</a>
|
||||
</#if>
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
<#include "../../include/import_global.ftl">
|
||||
<#include "../../include/html_doctype.ftl">
|
||||
<#--
|
||||
titleMessageKey 标题标签I18N关键字,不允许null
|
||||
selectonly 是否选择操作,允许为null
|
||||
-->
|
||||
<#assign selectonly=(selectonly!false)>
|
||||
<html>
|
||||
<head>
|
||||
<#include "../../include/html_head.ftl">
|
||||
<title><#include "../../include/html_title_app_name.ftl"><@spring.message code='${titleMessageKey}' /></title>
|
||||
</head>
|
||||
<body class="fill-parent">
|
||||
<#if !isAjaxRequest>
|
||||
<div class="fill-parent">
|
||||
</#if>
|
||||
<div id="${pageId}" class="page-grid page-grid-chartPlugin">
|
||||
<div class="head">
|
||||
<div class="search">
|
||||
<#include "../../include/page_obj_searchform.html.ftl">
|
||||
</div>
|
||||
<div class="operation">
|
||||
<#if selectonly>
|
||||
<input name="confirmButton" type="button" class="recommended" value="<@spring.message code='confirm' />" />
|
||||
<input name="viewButton" type="button" value="<@spring.message code='view' />" />
|
||||
<#else>
|
||||
<input name="uploadButton" type="button" value="<@spring.message code='upload' />" />
|
||||
<input name="downloadButton" type="button" value="<@spring.message code='download' />" />
|
||||
<input name="deleteButton" type="button" value="<@spring.message code='delete' />" />
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<table id="${pageId}-table" width="100%" class="hover stripe">
|
||||
</table>
|
||||
</div>
|
||||
<div class="foot">
|
||||
<div class="pagination-wrapper">
|
||||
<div id="${pageId}-pagination" class="pagination"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<#if !isAjaxRequest>
|
||||
</div>
|
||||
</#if>
|
||||
<#include "../../include/page_js_obj.ftl">
|
||||
<#include "../../include/page_obj_searchform_js.ftl">
|
||||
<#include "../../include/page_obj_grid.ftl">
|
||||
<script type="text/javascript">
|
||||
(function(po)
|
||||
{
|
||||
$.initButtons(po.element(".operation"));
|
||||
|
||||
po.url = function(action)
|
||||
{
|
||||
return "${contextPath}/analysis/chartPlugin/" + action;
|
||||
};
|
||||
|
||||
<#if !selectonly>
|
||||
po.element("input[name=uploadButton]").click(function()
|
||||
{
|
||||
po.open(po.url("upload"),
|
||||
{
|
||||
pageParam :
|
||||
{
|
||||
afterSave : function()
|
||||
{
|
||||
po.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
po.element("input[name=downloadButton]").click(function()
|
||||
{
|
||||
var selectedDatas = po.getSelectedData();
|
||||
var param = $.getPropertyParamString(selectedDatas, "id");
|
||||
|
||||
var options = {target : "_file"};
|
||||
|
||||
po.open(po.url("download?"+param), options);
|
||||
});
|
||||
|
||||
po.element("input[name=deleteButton]").click(
|
||||
function()
|
||||
{
|
||||
po.executeOnSelects(function(rows)
|
||||
{
|
||||
po.confirm("<@spring.message code='confirmDelete' />",
|
||||
{
|
||||
"confirm" : function()
|
||||
{
|
||||
var data = $.getPropertyParamString(rows, "id");
|
||||
|
||||
$.post(po.url("delete"), data, function()
|
||||
{
|
||||
po.refresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</#if>
|
||||
|
||||
var columnIcon = $.buildDataTablesColumnSimpleOption("<@spring.message code='chartPlugin.icon' />", "iconUrl");
|
||||
columnIcon.render = function(data, type, row, meta)
|
||||
{
|
||||
if(data)
|
||||
data = "<a class=\"plugin-icon\" style=\"background-image: url(${contextPath}/"+data+")\"> </a>";
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
var tableColumns = [
|
||||
$.buildDataTablesColumnSimpleOption("<@spring.message code='id' />", "id", true),
|
||||
$.buildDataTablesColumnSimpleOption($.buildDataTablesColumnTitleSearchable("<@spring.message code='chartPlugin.name' />"), "name"),
|
||||
$.buildDataTablesColumnSimpleOption($.buildDataTablesColumnTitleSearchable("<@spring.message code='chartPlugin.desc' />"), "desc"),
|
||||
columnIcon,
|
||||
$.buildDataTablesColumnSimpleOption("<@spring.message code='chartPlugin.version' />", "version")
|
||||
];
|
||||
|
||||
var tableSettings = po.buildDataTableSettingsAjax(tableColumns, po.url("queryData"));
|
||||
po.initDataTable(tableSettings);
|
||||
})
|
||||
(${pageId});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,142 @@
|
|||
<#include "../../include/import_global.ftl">
|
||||
<#include "../../include/html_doctype.ftl">
|
||||
<html>
|
||||
<head>
|
||||
<#include "../../include/html_head.ftl">
|
||||
<title><#include "../../include/html_title_app_name.ftl"><@spring.message code='chartPlugin.uploadChartPlugin' /></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="${pageId}" class="page-form page-form-uploadChartPlugin">
|
||||
<form id="${pageId}-form" action="${contextPath}/analysis/chartPlugin/saveUpload" method="POST">
|
||||
<div class="form-head"></div>
|
||||
<div class="form-content">
|
||||
<input type="hidden" name="pluginFileName" value="" />
|
||||
<div class="form-item">
|
||||
<div class="form-item-label">
|
||||
<label><@spring.message code='chartPlugin.upload.selectFile' /></label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<div class="fileinput-button" title="<@spring.message code='chartPlugin.upload.desc' />">
|
||||
<@spring.message code='select' /><input type="file" accept=".zip" class="ignore">
|
||||
</div>
|
||||
<div class="upload-file-info"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item-label">
|
||||
<label><@spring.message code='chartPlugin.upload.review' /></label>
|
||||
</div>
|
||||
<div class="form-item-value">
|
||||
<input type="hidden" name="inputForValidate" value="" />
|
||||
<div class="ui-widget ui-widget-content input chart-plugin-infos"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-foot" style="text-align:center;">
|
||||
<input type="submit" value="<@spring.message code='save' />" class="recommended" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<#include "../../include/page_js_obj.ftl" >
|
||||
<#include "../../include/page_obj_form.ftl">
|
||||
<script type="text/javascript">
|
||||
(function(po)
|
||||
{
|
||||
po.element("input:submit, input:button, input:reset, button, .fileinput-button").button();
|
||||
|
||||
po.url = function(action)
|
||||
{
|
||||
return "${contextPath}/analysis/chartPlugin/" + action;
|
||||
};
|
||||
|
||||
po.chartPluginInfos = function(){ return this.element(".chart-plugin-infos"); };
|
||||
|
||||
po.fileUploadInfo = function(){ return this.element(".upload-file-info"); };
|
||||
|
||||
po.renderChartPluginInfos = function(uploadResult)
|
||||
{
|
||||
po.element("input[name='pluginFileName']").val(uploadResult.pluginFileName);
|
||||
|
||||
po.chartPluginInfos().empty();
|
||||
|
||||
var chartPluginInfos = uploadResult.pluginInfos;
|
||||
for(var i=0; i<chartPluginInfos.length; i++)
|
||||
{
|
||||
var chartPluginInfo = chartPluginInfos[i];
|
||||
|
||||
var $item = $("<div class='ui-widget ui-widget-content ui-corner-all chart-plugin-item' />")
|
||||
.appendTo(po.chartPluginInfos());
|
||||
|
||||
if(chartPluginInfo.hasIcon)
|
||||
$("<a class=\"plugin-icon\" style=\"background-image: url(${contextPath}/"+chartPluginInfo.iconUrl+")\"> </a>").appendTo($item);
|
||||
|
||||
$("<span class='name'></span>").text(chartPluginInfo.name).appendTo($item);
|
||||
|
||||
if(chartPluginInfo.version)
|
||||
$("<span class='version'></span>").text("(" +chartPluginInfo.version+")").appendTo($item);
|
||||
}
|
||||
};
|
||||
|
||||
po.element(".fileinput-button").fileupload(
|
||||
{
|
||||
url : po.url("uploadFile"),
|
||||
paramName : "file",
|
||||
success : function(uploadResult, textStatus, jqXHR)
|
||||
{
|
||||
$.fileuploadsuccessHandlerForUploadInfo(po.fileUploadInfo(), false);
|
||||
po.renderChartPluginInfos(uploadResult);
|
||||
}
|
||||
})
|
||||
.bind('fileuploadadd', function (e, data)
|
||||
{
|
||||
po.element("input[name='pluginFileName']").val("");
|
||||
po.form().validate().resetForm();
|
||||
$.fileuploadaddHandlerForUploadInfo(e, data, po.fileUploadInfo());
|
||||
})
|
||||
.bind('fileuploadprogressall', function (e, data)
|
||||
{
|
||||
$.fileuploadprogressallHandlerForUploadInfo(e, data, po.fileUploadInfo());
|
||||
});
|
||||
|
||||
$.validator.addMethod("uploadChartPluginFileRequired", function(value, element)
|
||||
{
|
||||
var thisForm = $(element).closest("form");
|
||||
var $pluginFileName = $("input[name='pluginFileName']", thisForm).val();
|
||||
|
||||
return $pluginFileName.length > 0;
|
||||
});
|
||||
|
||||
po.form().validate(
|
||||
{
|
||||
ignore : ".ignore",
|
||||
rules :
|
||||
{
|
||||
inputForValidate : "uploadChartPluginFileRequired"
|
||||
},
|
||||
messages :
|
||||
{
|
||||
inputForValidate : "<@spring.message code='chartPlugin.upload.validation.uploadChartPluginFileRequired' />"
|
||||
},
|
||||
submitHandler : function(form)
|
||||
{
|
||||
$(form).ajaxSubmit(
|
||||
{
|
||||
success : function()
|
||||
{
|
||||
var close = (po.pageParamCall("afterSave") != false);
|
||||
|
||||
if(close)
|
||||
po.close();
|
||||
}
|
||||
});
|
||||
},
|
||||
errorPlacement : function(error, element)
|
||||
{
|
||||
error.appendTo(element.closest(".form-item-value"));
|
||||
}
|
||||
});
|
||||
})
|
||||
(${pageId});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -595,6 +595,16 @@
|
|||
$.setGridPageHeightOption(options);
|
||||
po.open(contextPath+"/authorization/${statics['org.datagear.management.domain.Schema'].AUTHORIZATION_RESOURCE_TYPE}/query", options);
|
||||
}
|
||||
else if($item.hasClass("system-set-chartPlugin-manage"))
|
||||
{
|
||||
var options = {};
|
||||
$.setGridPageHeightOption(options);
|
||||
po.open(contextPath+"/analysis/chartPlugin/query", options);
|
||||
}
|
||||
else if($item.hasClass("system-set-chartPlugin-upload"))
|
||||
{
|
||||
po.open(contextPath+"/analysis/chartPlugin/upload");
|
||||
}
|
||||
else if($item.hasClass("system-set-personal-set"))
|
||||
{
|
||||
po.open(contextPath+"/user/personalSet");
|
||||
|
@ -1174,6 +1184,9 @@
|
|||
<li class="system-set-rold-manage"><a href="javascript:void(0);"><@spring.message code='main.manageRole' /></a></li>
|
||||
<li class="system-set-authorization-manage"><a href="javascript:void(0);"><@spring.message code='main.manageAuthorization' /></a></li>
|
||||
<li class="ui-widget-header"></li>
|
||||
<li class="system-set-chartPlugin-manage"><a href="javascript:void(0);"><@spring.message code='main.manageChartPlugin' /></a></li>
|
||||
<li class="system-set-chartPlugin-upload"><a href="javascript:void(0);"><@spring.message code='main.uploadChartPlugin' /></a></li>
|
||||
<li class="ui-widget-header"></li>
|
||||
</#if>
|
||||
<li class="system-set-personal-set"><a href="javascript:void(0);"><@spring.message code='main.personalSet' /></a></li>
|
||||
<#if currentUser.admin>
|
||||
|
|
|
@ -1971,4 +1971,37 @@ table.dataTable tbody tr .column-check .row-data-state .ui-icon{
|
|||
}
|
||||
.page-form-chart .add-data-set-button{
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.page-grid-chartPlugin{
|
||||
}
|
||||
.page-grid-chartPlugin a.plugin-icon{
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.page-form-uploadChartPlugin .chart-plugin-infos{
|
||||
display: inline-block;
|
||||
height: 8em;
|
||||
overflow: auto;
|
||||
padding: 3px 2px;
|
||||
}
|
||||
.page-form-uploadChartPlugin .chart-plugin-infos .chart-plugin-item{
|
||||
margin-bottom: 5px;
|
||||
padding: 4px 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.page-form-uploadChartPlugin .chart-plugin-infos .chart-plugin-item a.plugin-icon{
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
.page-form-uploadChartPlugin .chart-plugin-infos .chart-plugin-item .name{
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.page-form-uploadChartPlugin .chart-plugin-infos .chart-plugin-item .version{
|
||||
margin-left: 0.3em;
|
||||
}
|
Loading…
Reference in New Issue