#2319 add admin storage page
This commit is contained in:
parent
f9dac9a544
commit
848171cedb
19 changed files with 765 additions and 1 deletions
22
pom.xml
22
pom.xml
|
@ -50,6 +50,7 @@
|
|||
<asm.version>7.2</asm.version>
|
||||
<tika.version>1.22</tika.version>
|
||||
<groovy.version>3.0.0-rc-1</groovy.version>
|
||||
<minio.version>6.0.11</minio.version>
|
||||
|
||||
<!-- Crawler -->
|
||||
<crawler.version>3.4.4-SNAPSHOT</crawler.version>
|
||||
|
@ -1179,6 +1180,11 @@
|
|||
<artifactId>google-http-client-jackson2</artifactId>
|
||||
<version>1.33.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.http-client</groupId>
|
||||
<artifactId>google-http-client-xml</artifactId>
|
||||
<version>1.33.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codelibs</groupId>
|
||||
<artifactId>corelib</artifactId>
|
||||
|
@ -1249,6 +1255,17 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>${minio.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- suggest library -->
|
||||
<dependency>
|
||||
|
@ -1326,6 +1343,11 @@
|
|||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
|
|
|
@ -394,6 +394,14 @@ public class Constants extends CoreLibConstants {
|
|||
|
||||
public static final String NOTIFICATION_ADVANCE_SEARCH = "notification.advance.search";
|
||||
|
||||
public static final String STORAGE_ENDPOINT = "storage.endpoint";
|
||||
|
||||
public static final String STORAGE_ACCESS_KEY = "storage.accesskey";
|
||||
|
||||
public static final String STORAGE_SECRET_KEY = "storage.secretkey";
|
||||
|
||||
public static final String STORAGE_BUCKET = "storage.bucket";
|
||||
|
||||
public static final String MAPPING_TYPE_ARRAY = "array";
|
||||
|
||||
public static final String MAPPING_TYPE_STRING = "string";
|
||||
|
|
|
@ -166,6 +166,14 @@ public class AdminGeneralAction extends FessAdminAction {
|
|||
fessConfig.setLdapMemberofAttribute(form.ldapMemberofAttribute);
|
||||
fessConfig.setNotificationLogin(form.notificationLogin);
|
||||
fessConfig.setNotificationSearchTop(form.notificationSearchTop);
|
||||
fessConfig.setStorageEndpoint(form.storageEndpoint);
|
||||
if (form.storageAccessKey != null && StringUtil.isNotBlank(form.storageAccessKey.replace("*", " "))) {
|
||||
fessConfig.setStorageAccessKey(form.storageAccessKey);
|
||||
}
|
||||
if (form.storageSecretKey != null && StringUtil.isNotBlank(form.storageSecretKey.replace("*", " "))) {
|
||||
fessConfig.setStorageSecretKey(form.storageSecretKey);
|
||||
}
|
||||
fessConfig.setStorageBucket(form.storageBucket);
|
||||
|
||||
fessConfig.storeSystemProperties();
|
||||
ComponentUtil.getLdapManager().updateConfig();
|
||||
|
@ -218,6 +226,10 @@ public class AdminGeneralAction extends FessAdminAction {
|
|||
form.ldapMemberofAttribute = fessConfig.getLdapMemberofAttribute();
|
||||
form.notificationLogin = fessConfig.getNotificationLogin();
|
||||
form.notificationSearchTop = fessConfig.getNotificationSearchTop();
|
||||
form.storageEndpoint = fessConfig.getStorageEndpoint();
|
||||
form.storageAccessKey = StringUtil.isNotBlank(fessConfig.getStorageAccessKey()) ? DUMMY_PASSWORD : StringUtil.EMPTY;
|
||||
form.storageSecretKey = StringUtil.isNotBlank(fessConfig.getStorageSecretKey()) ? DUMMY_PASSWORD : StringUtil.EMPTY;
|
||||
form.storageBucket = fessConfig.getStorageBucket();
|
||||
form.logLevel = ComponentUtil.getSystemHelper().getLogLevel().toUpperCase();
|
||||
}
|
||||
|
||||
|
|
|
@ -162,4 +162,16 @@ public class EditForm {
|
|||
|
||||
@Size(max = 10)
|
||||
public String logLevel;
|
||||
|
||||
@Size(max = 1000)
|
||||
public String storageEndpoint;
|
||||
|
||||
@Size(max = 1000)
|
||||
public String storageAccessKey;
|
||||
|
||||
@Size(max = 1000)
|
||||
public String storageSecretKey;
|
||||
|
||||
@Size(max = 1000)
|
||||
public String storageBucket;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright 2012-2019 CodeLibs Project and the Others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.app.web.admin.storage;
|
||||
|
||||
import static org.codelibs.core.stream.StreamUtil.split;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.app.web.base.FessAdminAction;
|
||||
import org.codelibs.fess.crawler.Constants;
|
||||
import org.codelibs.fess.exception.StorageException;
|
||||
import org.codelibs.fess.mylasta.direction.FessConfig;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.codelibs.fess.util.RenderDataUtil;
|
||||
import org.lastaflute.web.Execute;
|
||||
import org.lastaflute.web.response.ActionResponse;
|
||||
import org.lastaflute.web.response.HtmlResponse;
|
||||
import org.lastaflute.web.ruts.process.ActionRuntime;
|
||||
|
||||
import io.minio.MinioClient;
|
||||
import io.minio.Result;
|
||||
import io.minio.messages.Item;
|
||||
|
||||
/**
|
||||
* @author shinsuke
|
||||
*/
|
||||
public class AdminStorageAction extends FessAdminAction {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(AdminStorageAction.class);
|
||||
|
||||
@Override
|
||||
protected void setupHtmlData(final ActionRuntime runtime) {
|
||||
super.setupHtmlData(runtime);
|
||||
runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameStorage()));
|
||||
}
|
||||
|
||||
@Execute
|
||||
public HtmlResponse index() {
|
||||
saveToken();
|
||||
return asListHtml(StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
// TODO
|
||||
// @Execute
|
||||
// public HtmlResponse create() {
|
||||
// }
|
||||
|
||||
@Execute
|
||||
public HtmlResponse upload(final ItemForm form) {
|
||||
validate(form, messages -> {}, () -> asListHtml(form.path));
|
||||
if (form.uploadFile == null) {
|
||||
throwValidationError(messages -> messages.addErrorsStorageNoUploadFile(GLOBAL), () -> asListHtml(form.path));
|
||||
}
|
||||
verifyToken(() -> asListHtml(form.path));
|
||||
final String fileName = form.uploadFile.getFileName();
|
||||
try (final InputStream in = form.uploadFile.getInputStream()) {
|
||||
final MinioClient minioClient = createClient(fessConfig);
|
||||
minioClient.putObject(fessConfig.getStorageBucket(), form.uploadFile.getFileName(), in, (long) form.uploadFile.getFileSize(),
|
||||
null, null, "application/octet-stream");
|
||||
} catch (final Exception e) {
|
||||
throwValidationError(messages -> messages.addErrorsStorageFileUploadFailure(GLOBAL, fileName), () -> asListHtml(form.path));
|
||||
}
|
||||
saveInfo(messages -> messages.addSuccessUploadFileToStorage(GLOBAL, fileName));
|
||||
return redirect(getClass()); // no-op
|
||||
}
|
||||
|
||||
@Execute
|
||||
public ActionResponse list(final String id) {
|
||||
saveToken();
|
||||
return asListHtml(decodePath(id));
|
||||
}
|
||||
|
||||
@Execute
|
||||
public ActionResponse download(final String id) {
|
||||
final String[] values = decodeId(id);
|
||||
if (StringUtil.isEmpty(values[1])) {
|
||||
throwValidationError(messages -> messages.addErrorsStorageFileNotFound(GLOBAL), () -> asListHtml(values[0]));
|
||||
}
|
||||
return asStream(values[1]).contentTypeOctetStream().stream(
|
||||
out -> {
|
||||
try (InputStream in = createClient(fessConfig).getObject(fessConfig.getStorageBucket(), values[0] + values[1])) {
|
||||
out.write(in);
|
||||
} catch (final Exception e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to access {}", fessConfig.getStorageEndpoint(), e);
|
||||
}
|
||||
throwValidationError(messages -> messages.addErrorsStorageAccessError(GLOBAL, e.getLocalizedMessage()),
|
||||
() -> asListHtml(values[0]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static List<Map<String, Object>> getFileItems(final String prefix) {
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final ArrayList<Map<String, Object>> list = new ArrayList<>();
|
||||
try {
|
||||
final MinioClient minioClient = createClient(fessConfig);
|
||||
for (final Result<Item> result : minioClient.listObjects(fessConfig.getStorageBucket(),
|
||||
prefix != null && prefix.length() > 0 ? prefix + "/" : prefix, false)) {
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
final Item item = result.get();
|
||||
final String objectName = item.objectName();
|
||||
map.put("id", URLEncoder.encode(objectName, Constants.UTF_8_CHARSET));
|
||||
map.put("name", getName(objectName));
|
||||
map.put("size", item.size());
|
||||
map.put("directory", item.isDir());
|
||||
if (!item.isDir()) {
|
||||
map.put("lastModified", item.lastModified());
|
||||
}
|
||||
list.add(map);
|
||||
if (list.size() > fessConfig.getStorageMaxItemsInPageAsInteger()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
throw new StorageException("Failed to access " + fessConfig.getStorageEndpoint(), e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static String getName(final String objectName) {
|
||||
final String[] values = objectName.split("/");
|
||||
if (values.length == 0) {
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
return values[values.length - 1];
|
||||
}
|
||||
|
||||
protected static MinioClient createClient(final FessConfig fessConfig) {
|
||||
try {
|
||||
return new MinioClient(fessConfig.getStorageEndpoint(), fessConfig.getStorageAccessKey(), fessConfig.getStorageSecretKey());
|
||||
} catch (final Exception e) {
|
||||
throw new StorageException("Failed to create MinioClient: " + fessConfig.getStorageEndpoint(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static String decodePath(final String id) {
|
||||
final String[] values = decodeId(id);
|
||||
if (StringUtil.isEmpty(values[0]) && StringUtil.isEmpty(values[1])) {
|
||||
return StringUtil.EMPTY;
|
||||
} else if (StringUtil.isEmpty(values[0])) {
|
||||
return values[1];
|
||||
} else {
|
||||
return values[0] + "/" + values[1];
|
||||
}
|
||||
}
|
||||
|
||||
protected static String[] decodeId(final String id) {
|
||||
final String value = URLDecoder.decode(id, Constants.UTF_8_CHARSET);
|
||||
final String[] values = split(value, "/").get(stream -> stream.filter(StringUtil::isNotEmpty).toArray(n -> new String[n]));
|
||||
if (values.length == 0) {
|
||||
// invalid?
|
||||
return new String[] { StringUtil.EMPTY, StringUtil.EMPTY };
|
||||
} else if (values.length == 1) {
|
||||
return new String[] { StringUtil.EMPTY, values[0] };
|
||||
} else {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (int i = 0; i < values.length - 1; i++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append('/');
|
||||
}
|
||||
buf.append(values[i]);
|
||||
}
|
||||
return new String[] { buf.toString(), values[values.length - 1] };
|
||||
}
|
||||
}
|
||||
|
||||
protected static String createParentId(final String prefix) {
|
||||
if (prefix == null) {
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
final String[] values = prefix.split("/");
|
||||
if (values.length > 1) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (int i = 0; i < values.length - 1; i++) {
|
||||
if (buf.length() > 0) {
|
||||
buf.append('/');
|
||||
}
|
||||
buf.append(values[i]);
|
||||
}
|
||||
return URLEncoder.encode(buf.toString(), Constants.UTF_8_CHARSET);
|
||||
}
|
||||
return StringUtil.EMPTY;
|
||||
}
|
||||
|
||||
protected static List<Map<String, String>> createPathItems(final String prefix) {
|
||||
final List<Map<String, String>> list = new ArrayList<>();
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
split(prefix, "/").of(stream -> stream.filter(StringUtil::isNotEmpty).forEach(s -> {
|
||||
if (buf.length() > 0) {
|
||||
buf.append('/');
|
||||
}
|
||||
buf.append(s);
|
||||
final Map<String, String> map = new HashMap<>();
|
||||
map.put("id", URLEncoder.encode(buf.toString(), Constants.UTF_8_CHARSET));
|
||||
map.put("name", s);
|
||||
list.add(map);
|
||||
}));
|
||||
return list;
|
||||
}
|
||||
|
||||
private HtmlResponse asListHtml(final String prefix) {
|
||||
return asHtml(path_AdminStorage_AdminStorageJsp).useForm(ItemForm.class).renderWith(data -> {
|
||||
RenderDataUtil.register(data, "endpoint", fessConfig.getStorageEndpoint());
|
||||
RenderDataUtil.register(data, "bucket", fessConfig.getStorageBucket());
|
||||
RenderDataUtil.register(data, "path", prefix);
|
||||
RenderDataUtil.register(data, "pathItems", createPathItems(prefix));
|
||||
RenderDataUtil.register(data, "parentId", createParentId(prefix));
|
||||
RenderDataUtil.register(data, "fileItems", getFileItems(prefix));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2012-2019 CodeLibs Project and the Others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.app.web.admin.storage;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.lastaflute.web.ruts.multipart.MultipartFormFile;
|
||||
import org.lastaflute.web.validation.Required;
|
||||
|
||||
public class ItemForm {
|
||||
@Required
|
||||
public String path;
|
||||
|
||||
@Size(max = 100)
|
||||
public String name;
|
||||
|
||||
public MultipartFormFile uploadFile;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2012-2019 CodeLibs Project and the Others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.exception;
|
||||
|
||||
public class StorageException extends FessSystemException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public StorageException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public StorageException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -396,8 +396,11 @@ public class SystemHelper {
|
|||
|
||||
public void setupAdminHtmlData(final TypicalAction action, final ActionRuntime runtime) {
|
||||
runtime.registerData("developmentMode", ComponentUtil.getFessEsClient().isEmbedded());
|
||||
final String url = ComponentUtil.getFessConfig().getOnlineHelpInstallation();
|
||||
final FessConfig fessConfig = ComponentUtil.getFessConfig();
|
||||
final String url = fessConfig.getOnlineHelpInstallation();
|
||||
runtime.registerData("installationLink", getHelpUrl(url));
|
||||
runtime.registerData("storageEnabled",
|
||||
StringUtil.isNotBlank(fessConfig.getStorageEndpoint()) && StringUtil.isNotBlank(fessConfig.getStorageBucket()));
|
||||
}
|
||||
|
||||
public String getSearchRoleByUser(final String name) {
|
||||
|
|
|
@ -352,6 +352,9 @@ public interface FessHtmlPath {
|
|||
/** The path of the HTML: /admin/searchlog/admin_searchlog_details.jsp */
|
||||
HtmlNext path_AdminSearchlog_AdminSearchlogDetailsJsp = new HtmlNext("/admin/searchlog/admin_searchlog_details.jsp");
|
||||
|
||||
/** The path of the HTML: /admin/storage/admin_storage.jsp */
|
||||
HtmlNext path_AdminStorage_AdminStorageJsp = new HtmlNext("/admin/storage/admin_storage.jsp");
|
||||
|
||||
/** The path of the HTML: /admin/suggest/admin_suggest.jsp */
|
||||
HtmlNext path_AdminSuggest_AdminSuggestJsp = new HtmlNext("/admin/suggest/admin_suggest.jsp");
|
||||
|
||||
|
|
|
@ -605,6 +605,9 @@ public class FessLabels extends UserMessages {
|
|||
/** The key of the message: Plugin */
|
||||
public static final String LABELS_menu_plugin = "{labels.menu_plugin}";
|
||||
|
||||
/** The key of the message: Storage */
|
||||
public static final String LABELS_menu_storage = "{labels.menu_storage}";
|
||||
|
||||
/** The key of the message: Search... */
|
||||
public static final String LABELS_SIDEBAR_placeholder_search = "{labels.sidebar.placeholder_search}";
|
||||
|
||||
|
@ -2544,6 +2547,9 @@ public class FessLabels extends UserMessages {
|
|||
/** The key of the message: Notification */
|
||||
public static final String LABELS_general_menu_notification = "{labels.general_menu_notification}";
|
||||
|
||||
/** The key of the message: Storage */
|
||||
public static final String LABELS_general_storage = "{labels.general_storage}";
|
||||
|
||||
/** The key of the message: LDAP URL */
|
||||
public static final String LABELS_ldap_provider_url = "{labels.ldap_provider_url}";
|
||||
|
||||
|
@ -2574,6 +2580,18 @@ public class FessLabels extends UserMessages {
|
|||
/** The key of the message: Search top page */
|
||||
public static final String LABELS_notification_search_top = "{labels.notification_search_top}";
|
||||
|
||||
/** The key of the message: Endpoint */
|
||||
public static final String LABELS_storage_endpoint = "{labels.storage_endpoint}";
|
||||
|
||||
/** The key of the message: Access Key */
|
||||
public static final String LABELS_storage_access_key = "{labels.storage_access_key}";
|
||||
|
||||
/** The key of the message: Secret Key */
|
||||
public static final String LABELS_storage_secret_key = "{labels.storage_secret_key}";
|
||||
|
||||
/** The key of the message: Bucket */
|
||||
public static final String LABELS_storage_bucket = "{labels.storage_bucket}";
|
||||
|
||||
/** The key of the message: Send TestMail */
|
||||
public static final String LABELS_send_testmail = "{labels.send_testmail}";
|
||||
|
||||
|
@ -3090,6 +3108,24 @@ public class FessLabels extends UserMessages {
|
|||
/** The key of the message: Install */
|
||||
public static final String LABELS_crud_button_install = "{labels.crud_button_install}";
|
||||
|
||||
/** The key of the message: Storage */
|
||||
public static final String LABELS_storage_configuration = "{labels.storage_configuration}";
|
||||
|
||||
/** The key of the message: Name */
|
||||
public static final String LABELS_storage_name = "{labels.storage_name}";
|
||||
|
||||
/** The key of the message: Size */
|
||||
public static final String LABELS_storage_size = "{labels.storage_size}";
|
||||
|
||||
/** The key of the message: Last Modified */
|
||||
public static final String LABELS_storage_last_modified = "{labels.storage_last_modified}";
|
||||
|
||||
/** The key of the message: Upload File */
|
||||
public static final String LABELS_storage_upload_file = "{labels.storage_upload_file}";
|
||||
|
||||
/** The key of the message: Upload */
|
||||
public static final String LABELS_storage_button_upload = "{labels.storage_button_upload}";
|
||||
|
||||
/**
|
||||
* Assert the property is not null.
|
||||
* @param property The value of the property. (NotNull)
|
||||
|
|
|
@ -404,6 +404,21 @@ public class FessMessages extends FessLabels {
|
|||
/** The key of the message: {0} should be date. */
|
||||
public static final String ERRORS_property_type_date = "{errors.property_type_date}";
|
||||
|
||||
/** The key of the message: Failed to upload {0}. */
|
||||
public static final String ERRORS_storage_file_upload_failure = "{errors.storage_file_upload_failure}";
|
||||
|
||||
/** The key of the message: The target file is not found in Storage. */
|
||||
public static final String ERRORS_storage_file_not_found = "{errors.storage_file_not_found}";
|
||||
|
||||
/** The key of the message: Failed to download {0}. */
|
||||
public static final String ERRORS_storage_file_download_failure = "{errors.storage_file_download_failure}";
|
||||
|
||||
/** The key of the message: Storage access error: {0} */
|
||||
public static final String ERRORS_storage_access_error = "{errors.storage_access_error}";
|
||||
|
||||
/** The key of the message: Upload file is required. */
|
||||
public static final String ERRORS_storage_no_upload_file = "{errors.storage_no_upload_file}";
|
||||
|
||||
/** The key of the message: Updated parameters. */
|
||||
public static final String SUCCESS_update_crawler_params = "{success.update_crawler_params}";
|
||||
|
||||
|
@ -488,6 +503,9 @@ public class FessMessages extends FessLabels {
|
|||
/** The key of the message: Deleting {0} plugin. */
|
||||
public static final String SUCCESS_delete_plugin = "{success.delete_plugin}";
|
||||
|
||||
/** The key of the message: Uploaded {0} */
|
||||
public static final String SUCCESS_upload_file_to_storage = "{success.upload_file_to_storage}";
|
||||
|
||||
/** The key of the message: Created data. */
|
||||
public static final String SUCCESS_crud_create_crud_table = "{success.crud_create_crud_table}";
|
||||
|
||||
|
@ -2323,6 +2341,79 @@ public class FessMessages extends FessLabels {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'errors.storage_file_upload_failure' with parameters.
|
||||
* <pre>
|
||||
* message: Failed to upload {0}.
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @param arg0 The parameter arg0 for message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addErrorsStorageFileUploadFailure(String property, String arg0) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(ERRORS_storage_file_upload_failure, arg0));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'errors.storage_file_not_found' with parameters.
|
||||
* <pre>
|
||||
* message: The target file is not found in Storage.
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addErrorsStorageFileNotFound(String property) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(ERRORS_storage_file_not_found));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'errors.storage_file_download_failure' with parameters.
|
||||
* <pre>
|
||||
* message: Failed to download {0}.
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @param arg0 The parameter arg0 for message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addErrorsStorageFileDownloadFailure(String property, String arg0) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(ERRORS_storage_file_download_failure, arg0));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'errors.storage_access_error' with parameters.
|
||||
* <pre>
|
||||
* message: Storage access error: {0}
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @param arg0 The parameter arg0 for message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addErrorsStorageAccessError(String property, String arg0) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(ERRORS_storage_access_error, arg0));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'errors.storage_no_upload_file' with parameters.
|
||||
* <pre>
|
||||
* message: Upload file is required.
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addErrorsStorageNoUploadFile(String property) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(ERRORS_storage_no_upload_file));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'success.update_crawler_params' with parameters.
|
||||
* <pre>
|
||||
|
@ -2723,6 +2814,21 @@ public class FessMessages extends FessLabels {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'success.upload_file_to_storage' with parameters.
|
||||
* <pre>
|
||||
* message: Uploaded {0}
|
||||
* </pre>
|
||||
* @param property The property name for the message. (NotNull)
|
||||
* @param arg0 The parameter arg0 for message. (NotNull)
|
||||
* @return this. (NotNull)
|
||||
*/
|
||||
public FessMessages addSuccessUploadFileToStorage(String property, String arg0) {
|
||||
assertPropertyNotNull(property);
|
||||
add(property, new UserMessage(SUCCESS_upload_file_to_storage, arg0));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the created action message for the key 'success.crud_create_crud_table' with parameters.
|
||||
* <pre>
|
||||
|
|
|
@ -1322,6 +1322,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
/** The key of the configuration. e.g. plugin */
|
||||
String ONLINE_HELP_NAME_PLUGIN = "online.help.name.plugin";
|
||||
|
||||
/** The key of the configuration. e.g. storage */
|
||||
String ONLINE_HELP_NAME_STORAGE = "online.help.name.storage";
|
||||
|
||||
/** The key of the configuration. e.g. ja */
|
||||
String ONLINE_HELP_SUPPORTED_LANGS = "online.help.supported.langs";
|
||||
|
||||
|
@ -1553,6 +1556,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
/** The key of the configuration. e.g. */
|
||||
String PLUGIN_VERSION_FILTER = "plugin.version.filter";
|
||||
|
||||
/** The key of the configuration. e.g. 1000 */
|
||||
String STORAGE_MAX_ITEMS_IN_PAGE = "storage.max.items.in.page";
|
||||
|
||||
/**
|
||||
* Get the value of property as {@link String}.
|
||||
* @param propertyKey The key of the property. (NotNull)
|
||||
|
@ -5625,6 +5631,13 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
*/
|
||||
String getOnlineHelpNamePlugin();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'online.help.name.storage'. <br>
|
||||
* The value is, e.g. storage <br>
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getOnlineHelpNameStorage();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'online.help.supported.langs'. <br>
|
||||
* The value is, e.g. ja <br>
|
||||
|
@ -6353,6 +6366,23 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
*/
|
||||
Integer getPluginVersionFilterAsInteger();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'storage.max.items.in.page'. <br>
|
||||
* The value is, e.g. 1000 <br>
|
||||
* comment: ------
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
*/
|
||||
String getStorageMaxItemsInPage();
|
||||
|
||||
/**
|
||||
* Get the value for the key 'storage.max.items.in.page' as {@link Integer}. <br>
|
||||
* The value is, e.g. 1000 <br>
|
||||
* comment: ------
|
||||
* @return The value of found property. (NotNull: if not found, exception but basically no way)
|
||||
* @throws NumberFormatException When the property is not integer.
|
||||
*/
|
||||
Integer getStorageMaxItemsInPageAsInteger();
|
||||
|
||||
/**
|
||||
* The simple implementation for configuration.
|
||||
* @author FreeGen
|
||||
|
@ -8450,6 +8480,10 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
return get(FessConfig.ONLINE_HELP_NAME_PLUGIN);
|
||||
}
|
||||
|
||||
public String getOnlineHelpNameStorage() {
|
||||
return get(FessConfig.ONLINE_HELP_NAME_STORAGE);
|
||||
}
|
||||
|
||||
public String getOnlineHelpSupportedLangs() {
|
||||
return get(FessConfig.ONLINE_HELP_SUPPORTED_LANGS);
|
||||
}
|
||||
|
@ -8854,6 +8888,14 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
return getAsInteger(FessConfig.PLUGIN_VERSION_FILTER);
|
||||
}
|
||||
|
||||
public String getStorageMaxItemsInPage() {
|
||||
return get(FessConfig.STORAGE_MAX_ITEMS_IN_PAGE);
|
||||
}
|
||||
|
||||
public Integer getStorageMaxItemsInPageAsInteger() {
|
||||
return getAsInteger(FessConfig.STORAGE_MAX_ITEMS_IN_PAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected java.util.Map<String, String> prepareGeneratedDefaultMap() {
|
||||
java.util.Map<String, String> defaultMap = super.prepareGeneratedDefaultMap();
|
||||
|
@ -9240,6 +9282,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
defaultMap.put(FessConfig.ONLINE_HELP_NAME_SEARCHLOG, "searchlog");
|
||||
defaultMap.put(FessConfig.ONLINE_HELP_NAME_MAINTENANCE, "maintenance");
|
||||
defaultMap.put(FessConfig.ONLINE_HELP_NAME_PLUGIN, "plugin");
|
||||
defaultMap.put(FessConfig.ONLINE_HELP_NAME_STORAGE, "storage");
|
||||
defaultMap.put(FessConfig.ONLINE_HELP_SUPPORTED_LANGS, "ja");
|
||||
defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_SEED, "0");
|
||||
defaultMap.put(FessConfig.SUGGEST_POPULAR_WORD_TAGS, "");
|
||||
|
@ -9318,6 +9361,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction
|
|||
defaultMap.put(FessConfig.PLUGIN_REPOSITORIES,
|
||||
"https://repo.maven.apache.org/maven2/org/codelibs/fess/,https://fess.codelibs.org/plugin/artifacts.yaml");
|
||||
defaultMap.put(FessConfig.PLUGIN_VERSION_FILTER, "");
|
||||
defaultMap.put(FessConfig.STORAGE_MAX_ITEMS_IN_PAGE, "1000");
|
||||
defaultMap.put(FessConfig.lasta_di_SMART_DEPLOY_MODE, "hot");
|
||||
defaultMap.put(FessConfig.DEVELOPMENT_HERE, "true");
|
||||
defaultMap.put(FessConfig.ENVIRONMENT_TITLE, "Local Development");
|
||||
|
|
|
@ -574,6 +574,38 @@ public interface FessProp {
|
|||
setSystemProperty(Constants.LDAP_MEMBEROF_ATTRIBUTE, value);
|
||||
}
|
||||
|
||||
default void setStorageEndpoint(final String value) {
|
||||
setSystemProperty(Constants.STORAGE_ENDPOINT, value);
|
||||
}
|
||||
|
||||
default String getStorageEndpoint() {
|
||||
return getSystemProperty(Constants.STORAGE_ENDPOINT, StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
default void setStorageAccessKey(final String value) {
|
||||
setSystemProperty(Constants.STORAGE_ACCESS_KEY, value);
|
||||
}
|
||||
|
||||
default String getStorageAccessKey() {
|
||||
return getSystemProperty(Constants.STORAGE_ACCESS_KEY, StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
default void setStorageSecretKey(final String value) {
|
||||
setSystemProperty(Constants.STORAGE_SECRET_KEY, value);
|
||||
}
|
||||
|
||||
default String getStorageSecretKey() {
|
||||
return getSystemProperty(Constants.STORAGE_SECRET_KEY, StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
default void setStorageBucket(final String value) {
|
||||
setSystemProperty(Constants.STORAGE_BUCKET, value);
|
||||
}
|
||||
|
||||
default String getStorageBucket() {
|
||||
return getSystemProperty(Constants.STORAGE_BUCKET, StringUtil.EMPTY);
|
||||
}
|
||||
|
||||
Integer getLdapMaxUsernameLengthAsInteger();
|
||||
|
||||
default String getLdapSecurityPrincipal(final String username) {
|
||||
|
|
|
@ -713,6 +713,7 @@ online.help.name.suggest=suggest
|
|||
online.help.name.searchlog=searchlog
|
||||
online.help.name.maintenance=maintenance
|
||||
online.help.name.plugin=plugin
|
||||
online.help.name.storage=storage
|
||||
|
||||
online.help.supported.langs=ja
|
||||
|
||||
|
@ -809,3 +810,9 @@ ldap.attr.homeDirectory=homeDirectory
|
|||
#plugin.repositories=https://repo.maven.apache.org/maven2/org/codelibs/fess/,https://oss.sonatype.org/content/repositories/snapshots/org/codelibs/fess/,https://fess.codelibs.org/plugin/artifacts.yaml
|
||||
plugin.repositories=https://repo.maven.apache.org/maven2/org/codelibs/fess/,https://fess.codelibs.org/plugin/artifacts.yaml
|
||||
plugin.version.filter=
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Storage
|
||||
# ------
|
||||
storage.max.items.in.page=1000
|
||||
|
||||
|
|
|
@ -193,6 +193,7 @@ labels.menu_maintenance=Maintenance
|
|||
labels.menu_related_content=Related Content
|
||||
labels.menu_related_query=Related Query
|
||||
labels.menu_plugin=Plugin
|
||||
labels.menu_storage=Storage
|
||||
labels.sidebar.placeholder_search=Search...
|
||||
labels.sidebar.menu=MENU
|
||||
labels.footer.copyright=©2019 <a href="https://github.com/codelibs">CodeLibs Project</a>.
|
||||
|
@ -839,6 +840,7 @@ labels.general_menu_logging=Logging
|
|||
labels.general_menu_suggest=Suggest
|
||||
labels.general_menu_ldap=LDAP
|
||||
labels.general_menu_notification=Notification
|
||||
labels.general_storage=Storage
|
||||
labels.ldap_provider_url=LDAP URL
|
||||
labels.ldap_security_principal=User DN
|
||||
labels.ldap_admin_security_principal=Bind DN
|
||||
|
@ -849,6 +851,10 @@ labels.ldap_group_filter=Group Filter
|
|||
labels.ldap_memberof_attribute=memberOf Attribute
|
||||
labels.notification_login=Login page
|
||||
labels.notification_search_top=Search top page
|
||||
labels.storage_endpoint=Endpoint
|
||||
labels.storage_access_key=Access Key
|
||||
labels.storage_secret_key=Secret Key
|
||||
labels.storage_bucket=Bucket
|
||||
labels.send_testmail=Send TestMail
|
||||
labels.backup_configuration=Back Up
|
||||
labels.backup_name=Name
|
||||
|
@ -1021,3 +1027,9 @@ labels.plugin_jar_file=Jar File
|
|||
labels.plugin_local_install=Local
|
||||
labels.plugin_remote_install=Remote
|
||||
labels.crud_button_install=Install
|
||||
labels.storage_configuration=Storage
|
||||
labels.storage_name=Name
|
||||
labels.storage_size=Size
|
||||
labels.storage_last_modified=Last Modified
|
||||
labels.storage_upload_file=Upload File
|
||||
labels.storage_button_upload=Upload
|
||||
|
|
|
@ -160,6 +160,12 @@ errors.property_type_float={0} should be numeric.
|
|||
errors.property_type_double={0} should be numeric.
|
||||
errors.property_type_date={0} should be date.
|
||||
|
||||
errors.storage_file_upload_failure=Failed to upload {0}.
|
||||
errors.storage_file_not_found=The target file is not found in Storage.
|
||||
errors.storage_file_download_failure=Failed to download {0}.
|
||||
errors.storage_access_error=Storage access error: {0}
|
||||
errors.storage_no_upload_file=Upload file is required.
|
||||
|
||||
success.update_crawler_params=Updated parameters.
|
||||
success.delete_doc_from_index=Started a process to delete the document from index.
|
||||
success.crawling_info_delete_all=Deleted session data.
|
||||
|
@ -188,6 +194,7 @@ success.bulk_process_started=Bulk process is started.
|
|||
success.print_thread_dump=Printed thread dump to log file.
|
||||
success.install_plugin=Installing {0} plugin.
|
||||
success.delete_plugin=Deleting {0} plugin.
|
||||
success.upload_file_to_storage=Uploaded {0}
|
||||
|
||||
success.crud_create_crud_table=Created data.
|
||||
success.crud_update_crud_table=Updated data.
|
||||
|
|
|
@ -471,6 +471,48 @@
|
|||
styleClass="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<%-- Storage --%>
|
||||
<h4><la:message key="labels.general_storage" /></h4>
|
||||
<div class="form-group">
|
||||
<label for="storageEndpoint"
|
||||
class="col-sm-3 control-label"><la:message
|
||||
key="labels.storage_endpoint" /></label>
|
||||
<div class="col-sm-9">
|
||||
<la:errors property="storageEndpoint" />
|
||||
<la:text styleId="storageEndpoint" property="storageEndpoint"
|
||||
styleClass="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="storageAccessKey"
|
||||
class="col-sm-3 control-label"><la:message
|
||||
key="labels.storage_access_key" /></label>
|
||||
<div class="col-sm-9">
|
||||
<la:errors property="storageAccessKey" />
|
||||
<la:password styleId="storageAccessKey" property="storageAccessKey"
|
||||
styleClass="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="storageSecretKey"
|
||||
class="col-sm-3 control-label"><la:message
|
||||
key="labels.storage_secret_key" /></label>
|
||||
<div class="col-sm-9">
|
||||
<la:errors property="storageSecretKey" />
|
||||
<la:password styleId="storageSecretKey" property="storageSecretKey"
|
||||
styleClass="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="storageBucket"
|
||||
class="col-sm-3 control-label"><la:message
|
||||
key="labels.storage_bucket" /></label>
|
||||
<div class="col-sm-9">
|
||||
<la:errors property="storageBucket" />
|
||||
<la:text styleId="storageBucket" property="storageBucket"
|
||||
styleClass="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
<div class="box-footer">
|
||||
|
|
117
src/main/webapp/WEB-INF/view/admin/storage/admin_storage.jsp
Normal file
117
src/main/webapp/WEB-INF/view/admin/storage/admin_storage.jsp
Normal file
|
@ -0,0 +1,117 @@
|
|||
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><la:message key="labels.admin_brand_title" /> | <la:message
|
||||
key="labels.storage_configuration" /></title>
|
||||
<jsp:include page="/WEB-INF/view/common/admin/head.jsp"></jsp:include>
|
||||
</head>
|
||||
<body class="hold-transition skin-blue sidebar-mini">
|
||||
<div class="wrapper">
|
||||
<jsp:include page="/WEB-INF/view/common/admin/header.jsp"></jsp:include>
|
||||
<jsp:include page="/WEB-INF/view/common/admin/sidebar.jsp">
|
||||
<jsp:param name="menuCategoryType" value="system" />
|
||||
<jsp:param name="menuType" value="storage" />
|
||||
</jsp:include>
|
||||
<div class="content-wrapper">
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
<la:message key="labels.storage_configuration" />
|
||||
</h1>
|
||||
<jsp:include page="/WEB-INF/view/common/admin/crud/breadcrumb.jsp"></jsp:include>
|
||||
</section>
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
<la:message key="labels.storage_configuration" />
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<%-- Message --%>
|
||||
<div>
|
||||
<la:info id="msg" message="true">
|
||||
<div class="alert alert-info">${msg}</div>
|
||||
</la:info>
|
||||
<la:errors />
|
||||
</div>
|
||||
<%-- List --%>
|
||||
<div class="data-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
Path: ${f:h(endpoint)}/${f:h(bucket)}<c:forEach var="item" varStatus="s" items="${pathItems}">/<a href="${contextPath}/admin/storage/list/${f:u(item.id)}/">${f:h(item.name)}</a></c:forEach>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<la:form action="/admin/storage/upload/" enctype="multipart/form-data" styleClass="form-inline">
|
||||
<div class="form-group">
|
||||
<label for="uploadFile"> <la:message key="labels.storage_upload_file" />
|
||||
</label> <input type="file" name="uploadFile" class="form-control" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success" name="upload">
|
||||
<em class="fa fa-upload"></em>
|
||||
<la:message key="labels.storage_button_upload" />
|
||||
</button>
|
||||
</la:form>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<table class="table table-bordered table-striped dataTable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><la:message key="labels.storage_name" /></th>
|
||||
<th><la:message key="labels.storage_size" /></th>
|
||||
<th><la:message key="labels.storage_last_modified" /></th>
|
||||
</tr>
|
||||
<c:if test="${not empty path and not empty parentId}">
|
||||
<tr
|
||||
data-href="${contextPath}/admin/storage/list/${f:u(data.parentId)}/">
|
||||
<td>..</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr></c:if>
|
||||
<c:if test="${not empty path and empty parentId}">
|
||||
<tr
|
||||
data-href="${contextPath}/admin/storage/">
|
||||
<td>..</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr></c:if>
|
||||
<c:forEach var="data" varStatus="s" items="${fileItems}">
|
||||
<c:if test="${not data.directory}">
|
||||
<tr
|
||||
data-href="${contextPath}/admin/storage/download/${f:u(data.id)}/">
|
||||
<td>${f:h(data.name)}</td>
|
||||
<td>${f:h(data.size)}</td>
|
||||
<td>${f:h(data.lastModifed)}</td>
|
||||
</tr>
|
||||
</c:if><c:if test="${data.directory.booleanValue()}">
|
||||
<tr
|
||||
data-href="${contextPath}/admin/storage/list/${f:u(data.id)}/">
|
||||
<td>${f:h(data.name)}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</c:if>
|
||||
</c:forEach>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.data-wrapper -->
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<jsp:include page="/WEB-INF/view/common/admin/footer.jsp"></jsp:include>
|
||||
</div>
|
||||
<jsp:include page="/WEB-INF/view/common/admin/foot.jsp"></jsp:include>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -82,6 +82,12 @@
|
|||
<span><la:message key="labels.menu_plugin" /></span>
|
||||
</la:link></li>
|
||||
|
||||
<c:if test="${storageEnabled.booleanValue()}"><li <c:if test="${param.menuType=='storage'}">class="active"</c:if>><la:link
|
||||
href="/admin/storage/">
|
||||
<em class='fa fa-genderless'></em>
|
||||
<span><la:message key="labels.menu_storage" /></span>
|
||||
</la:link></li></c:if>
|
||||
|
||||
</ul></li>
|
||||
<li
|
||||
class="treeview <c:if test="${param.menuCategoryType=='crawl'}">active</c:if>"><a
|
||||
|
|
Loading…
Add table
Reference in a new issue