From 5c6ef91b43f0b0cc225b1a5b8abdc08b670a9317 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Sun, 09 Dec 2018 23:01:56 +0000
Subject: [PATCH] ...
---
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java | 14 ++
borgbutler-webapp/src/components/views/repos/RepoListView.css | 44 +++++++
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java | 6
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java | 6
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java | 6
borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java | 1
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java | 58 +++++++++
borgbutler-webapp/src/components/views/repos/RepoCard.jsx | 43 +++++++
borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java | 3
borgbutler-webapp/src/components/views/develop/RestServices.jsx | 6 +
borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java | 1
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java | 25 ++++
borgbutler-webapp/src/components/views/repos/RepoListView.jsx | 125 ++++++++++++++++++++
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java | 6
14 files changed, 329 insertions(+), 15 deletions(-)
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
index 7cb2908..d89de91 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
@@ -46,6 +46,20 @@
state = STATE.DIRTY;
}
+ /**
+ * Calls {@link #clear()} and removes the cache files. Therefore a new creation of this cache is forced.
+ */
+ public void clearAndReset() {
+ synchronized (this) {
+ if (cacheFile.exists()) {
+ log.info("Clearing cache and deleting cache file (recreation is forced): " + cacheFile.getAbsolutePath());
+ cacheFile.delete();
+ }
+ clear();
+ state = STATE.SAVED;
+ }
+ }
+
protected void setDirty() {
state = STATE.DIRTY;
}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
index c7e5ad4..67c2604 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
@@ -32,11 +32,11 @@
protected abstract T load(BorgRepoConfig repoConfig, String identifier);
- public abstract boolean matches(T element, String identifier);
+ protected abstract boolean matches(T element, String identifier);
- public abstract String getIdentifier(T element);
+ protected abstract String getIdentifier(T element);
- public abstract void updateFrom(T dest, T source);
+ protected abstract void updateFrom(T dest, T source);
/**
* Removes all entries (doesn't effect the cache files!).
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
index 3f31c3c..a2ec7d9 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
@@ -20,17 +20,17 @@
}
@Override
- public boolean matches(ArchiveInfo element, String identifier) {
+ protected boolean matches(ArchiveInfo element, String identifier) {
return element.matches(identifier);
}
@Override
- public String getIdentifier(ArchiveInfo element) {
+ protected String getIdentifier(ArchiveInfo element) {
return element.getRepository().getId();
}
@Override
- public void updateFrom(ArchiveInfo dest, ArchiveInfo source) {
+ protected void updateFrom(ArchiveInfo dest, ArchiveInfo source) {
dest.updateFrom(source);
}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
index 00ecb3b..946b81d 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -5,6 +5,8 @@
import de.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.json.borg.Archive;
import de.micromata.borgbutler.json.borg.FilesystemItem;
+import de.micromata.borgbutler.json.borg.RepoInfo;
+import de.micromata.borgbutler.json.borg.Repository;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -40,6 +42,29 @@
}
}
+ public Repository getRepository(String idOrName) {
+ BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(idOrName);
+ RepoInfo repoInfo = repoInfoCache.get(repoConfig, idOrName);
+ if (repoInfo == null) {
+ log.warn("Repo with name or id '" + idOrName + "' not found.");
+ return null;
+ }
+ return repoInfo.getRepository();
+ }
+
+ public List<Repository> getAllRepositories() {
+ List<Repository> repositories = new ArrayList<>();
+ for (BorgRepoConfig repoConfig : ConfigurationHandler.getConfiguration().getRepoConfigs()) {
+ RepoInfo repoInfo = repoInfoCache.get(repoConfig, repoConfig.getName());
+ if (repoInfo == null) {
+ log.warn("Repo with name '" + repoConfig.getName() + "' not found.");
+ continue;
+ }
+ repositories.add(repoInfo.getRepository());
+ }
+ return repositories;
+ }
+
public List<FilesystemItem> getArchiveContent(BorgRepoConfig repoConfig, Archive archive) {
if (archive == null || StringUtils.isBlank(archive.getArchive())) {
return null;
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
index b71fb55..703e504 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
@@ -20,17 +20,17 @@
}
@Override
- public boolean matches(RepoInfo element, String identifier) {
+ protected boolean matches(RepoInfo element, String identifier) {
return element.matches(identifier);
}
@Override
- public String getIdentifier(RepoInfo element) {
+ protected String getIdentifier(RepoInfo element) {
return element.getRepository().getId();
}
@Override
- public void updateFrom(RepoInfo dest, RepoInfo source) {
+ protected void updateFrom(RepoInfo dest, RepoInfo source) {
dest.updateFrom(source);
}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
index ef5773d..d09ea39 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
@@ -20,17 +20,17 @@
}
@Override
- public boolean matches(RepoList element, String identifier) {
+ protected boolean matches(RepoList element, String identifier) {
return element.matches(identifier);
}
@Override
- public String getIdentifier(RepoList element) {
+ protected String getIdentifier(RepoList element) {
return element.getRepository().getId();
}
@Override
- public void updateFrom(RepoList dest, RepoList source) {
+ protected void updateFrom(RepoList dest, RepoList source) {
dest.updateFrom(source);
}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
index e3bf842..c85144d 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
@@ -29,7 +29,7 @@
return instance.configuration;
}
- public void read() {
+ private void read() {
log.info("Reading config file '" + configFile.getAbsolutePath() + "'");
try {
String json = FileUtils.readFileToString(configFile, Definitions.STD_CHARSET);
@@ -68,5 +68,6 @@
configFile = new File(userHome, CONFIG_FILENAME);
backupConfigFile = new File(userHome, CONFIG_BACKUP_FILENAME);
workingDir = new File(userHome, APP_WORKING_DIR);
+ read();
}
}
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
index 132765a..b8c70a2 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/cache/CacheTest.java
@@ -23,7 +23,6 @@
@Test
void repoCacheTest() {
ConfigurationHandler configHandler = ConfigurationHandler.getInstance();
- configHandler.read();
Configuration config = ConfigurationHandler.getConfiguration();
if (config.getRepoConfigs().size() == 0) {
log.info("No repos configured. Please configure repos first in: " + configHandler.getConfigFile().getAbsolutePath());
diff --git a/borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java b/borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java
index 4d8489f..b5be676 100644
--- a/borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java
+++ b/borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java
@@ -12,7 +12,6 @@
File origConfigFile = new File(System.getProperty("user.home"), ".borgbutler-orig.json");
FileUtils.copyFile(ConfigurationHandler.getInstance().getConfigFile(), origConfigFile);
Configuration configuration = ConfigurationHandler.getConfiguration();
- ConfigurationHandler.getInstance().read();
ConfigurationHandler.getInstance().write();
FileUtils.copyFile(origConfigFile, ConfigurationHandler.getInstance().getConfigFile());
}
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java
new file mode 100644
index 0000000..23bcb52
--- /dev/null
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ReposRest.java
@@ -0,0 +1,58 @@
+package de.micromata.borgbutler.server.rest;
+
+import de.micromata.borgbutler.cache.ButlerCache;
+import de.micromata.borgbutler.json.JsonUtils;
+import de.micromata.borgbutler.json.borg.Repository;
+import org.apache.commons.collections4.CollectionUtils;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+
+@Path("/repos")
+public class ReposRest {
+ @GET
+ @Path("refresh")
+ @Produces(MediaType.TEXT_PLAIN)
+ /**
+ * Reloads all templates on the server.
+ * @return "OK"
+ */
+ public String refresh() {
+ ButlerCache.getInstance().getRepoInfoCache().clearAndReset();
+ return "OK";
+ }
+
+ @GET
+ @Path("repo")
+ @Produces(MediaType.APPLICATION_JSON)
+ /**
+ *
+ * @param id
+ * @param prettyPrinter If true then the json output will be in pretty format.
+ * @see JsonUtils#toJson(Object, boolean)
+ */
+ public String getTemplate(@QueryParam("id") String id, @QueryParam("prettyPrinter") boolean prettyPrinter) {
+ Repository repository = ButlerCache.getInstance().getRepository(id);
+ return JsonUtils.toJson(repository, prettyPrinter);
+ }
+
+ @GET
+ @Path("list")
+ @Produces(MediaType.APPLICATION_JSON)
+ /**
+ *
+ * @param prettyPrinter If true then the json output will be in pretty format.
+ * @see JsonUtils#toJson(Object, boolean)
+ */
+ public String getList(@QueryParam("prettyPrinter") boolean prettyPrinter) {
+ List<Repository> repositories = ButlerCache.getInstance().getAllRepositories();
+ if (CollectionUtils.isEmpty(repositories)) {
+ return "";
+ }
+ return JsonUtils.toJson(repositories, prettyPrinter);
+ }
+}
diff --git a/borgbutler-webapp/src/components/views/develop/RestServices.jsx b/borgbutler-webapp/src/components/views/develop/RestServices.jsx
index 2bb7977..76e4fde 100644
--- a/borgbutler-webapp/src/components/views/develop/RestServices.jsx
+++ b/borgbutler-webapp/src/components/views/develop/RestServices.jsx
@@ -93,6 +93,12 @@
Rest Services
</PageHeader>
<h3>
+ Repositories
+ </h3>
+ <ul>
+ <li><RestUrlLink service='repos/list'/></li>
+ </ul>
+ <h3>
Config
</h3>
<ul>
diff --git a/borgbutler-webapp/src/components/views/repos/RepoCard.jsx b/borgbutler-webapp/src/components/views/repos/RepoCard.jsx
new file mode 100644
index 0000000..e82a8e0
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/repos/RepoCard.jsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import {Link} from 'react-router-dom';
+import {Card, CardBody, CardFooter, CardHeader} from 'reactstrap';
+import {formatDateTime} from "../../../utilities/global";
+
+class RepoCard extends React.Component {
+
+ buildItem = (label, content) => {
+ return <li className="list-group-item">{label}{content.map((line, index) => {
+ return <div className="card-list-entry" key={index}>{line[0]} <span
+ className={`card-list-entry-value ${line[2]}`}>{line[1]}</span>
+ </div>;
+ })}</li>;
+ }
+
+ render = () => {
+ const repo = this.props.repo;
+ let repoId = repo.id ? repo.id : repo.name;
+ let content = [[Name, repo.name, 'name']];
+ let repoText = this.buildItem(null, content);
+
+ return <React.Fragment>
+ <Card tag={Link} to={`/repos/${repo.primaryKey}`} outline color="success" className={'repo'}
+ style={{backgroundColor: '#fff'}}>
+ <CardHeader>{repoId}</CardHeader>
+ <CardBody>
+ <ul className="list-group list-group-flush">
+ {repoText}
+ </ul>
+ </CardBody>
+ <CardFooter><span className={'lastModified'}>{formatDateTime(repo.lastModified)}</span></CardFooter>
+ </Card>
+ </React.Fragment>
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.buildItem = this.buildItem.bind(this);
+ }
+}
+
+export default repoCard;
diff --git a/borgbutler-webapp/src/components/views/repos/RepoListView.css b/borgbutler-webapp/src/components/views/repos/RepoListView.css
new file mode 100644
index 0000000..321ba8f
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/repos/RepoListView.css
@@ -0,0 +1,44 @@
+a.card-link {
+ color: #111;
+}
+
+a.card-link:hover {
+ text-decoration: none;
+}
+
+a.card.template {
+ margin: 5pt;
+ cursor: pointer;
+}
+
+a.card.template div.card-footer {
+ color: #666;
+ font-size: 12px;
+}
+
+a.card.template:hover div.card-body,
+a.card.template:hover div.card-body li.list-group-item {
+ background-color: #f5f5f5;
+}
+
+a.card.template div.card-list-entry {
+ color: grey;
+ font-size: 80%;
+}
+
+a.card.template div.card-list-entry .card-list-entry-value {
+ font-style: italic;
+}
+
+a.card.template div.card-list-entry .filename {
+ font-family: monospace;
+}
+
+a.card.template div.card-footer .lastModified {
+ float:right;
+}
+
+a.card.template:hover div.card-header,
+a.card.template:hover div.card-footer {
+ background-color: #eeee;
+}
diff --git a/borgbutler-webapp/src/components/views/repos/RepoListView.jsx b/borgbutler-webapp/src/components/views/repos/RepoListView.jsx
new file mode 100644
index 0000000..301f1c8
--- /dev/null
+++ b/borgbutler-webapp/src/components/views/repos/RepoListView.jsx
@@ -0,0 +1,125 @@
+import React from 'react'
+import './RepoListView.css';
+import {CardDeck} from 'reactstrap';
+import {PageHeader} from '../../general/BootstrapComponents';
+import {getRestServiceUrl} from '../../../utilities/global';
+import ErrorAlert from '../../general/ErrorAlert';
+import TemplateCard from './TemplateCard';
+import {IconRefresh} from "../../general/IconComponents";
+import I18n from "../../general/translation/I18n";
+
+class RepoListView extends React.Component {
+
+
+ path = getRestServiceUrl('repos');
+ state = {
+ isFetching: false
+ };
+
+ componentDidMount = () => {
+ this.fetchTemplates();
+ };
+
+ fetchTemplates = () => {
+ this.setState({
+ isFetching: true,
+ failed: false,
+ definitions: undefined,
+ templates: undefined
+ });
+ fetch(`${this.path}/list`, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json'
+ }
+ })
+ .then(response => response.json())
+ .then(json => {
+ const definitions = json.templateDefinitions.reduce((accumulator, current) => ({
+ ...accumulator,
+ [current.refId]: current
+ }), {});
+
+ const templates = json.templates.map(template => {
+ if (typeof template.templateDefinition === 'object') {
+ //console.log('refId: ' + template.templateDefinition.refId + ', templateDefinition: ' + JSON.stringify(template.templateDefinition))
+ definitions[template.templateDefinition.refId] = template.templateDefinition;
+ template.templateDefinition = template.templateDefinition.refId;
+ }
+
+ return {
+ id: template.id,
+ primaryKey: template.fileDescriptor.primaryKey,
+ filename: template.fileDescriptor.filename,
+ lastModified: template.fileDescriptor.lastModified,
+ templateDefinitionId: template.templateDefinitionId,
+ templateDefinition: template.templateDefinition
+ };
+ });
+
+ this.setState({
+ isFetching: false,
+ definitions, templates
+ })
+ })
+ .catch(() => this.setState({isFetching: false, failed: true}));
+ };
+
+ render = () => {
+ let content = undefined;
+
+ if (this.state.isFetching) {
+
+ content = <i>Loading...</i>;
+
+ } else if (this.state.failed) {
+
+ content = <ErrorAlert
+ title={'Cannot load Templates'}
+ description={'Something went wrong during contacting the rest api.'}
+ action={{
+ handleClick: this.fetchTemplates,
+ title: 'Try again'
+ }}
+ />;
+
+ } else if (this.state.templates) {
+
+ content = <React.Fragment>
+ <div
+ className={'btn btn-outline-primary refresh-button-right'}
+ onClick={this.fetchTemplates}
+ >
+ <IconRefresh/>
+ </div>
+ <CardDeck>
+ {this.state.templates.map(template => {
+ const definition = this.state.definitions[template.templateDefinition];
+
+ return <TemplateCard
+ key={template.primaryKey}
+ template={template}
+ definition={definition}
+ />;
+ })}
+ </CardDeck>
+ </React.Fragment>;
+
+ }
+
+ return <React.Fragment>
+ <PageHeader>
+ <I18n name={'templates'}/>
+ </PageHeader>
+ {content}
+ </React.Fragment>;
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.fetchTemplates = this.fetchTemplates.bind(this);
+ }
+}
+
+export default RepoListView;
--
Gitblit v1.10.0