@tasenor/common-plugins 1.10.35 → 1.10.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-ci.log +2 -8
- package/dist/Finnish/ui/index.d.ts +1 -0
- package/dist/Finnish/ui/index.js +4 -1
- package/dist/Finnish/ui/index.js.map +1 -1
- package/dist/GitBackup/backend/index.d.ts +15 -3
- package/dist/GitBackup/backend/index.js +63 -9
- package/dist/GitBackup/backend/index.js.map +1 -1
- package/dist/GitBackup/common/types.d.ts +10 -0
- package/dist/GitBackup/common/types.js +2 -0
- package/dist/GitBackup/common/types.js.map +1 -0
- package/dist/GitBackup/ui/index.js +60 -13
- package/dist/GitBackup/ui/index.js.map +1 -1
- package/package.json +5 -5
- package/src/Finnish/ui/index.tsx +5 -1
- package/src/GitBackup/backend/index.ts +74 -12
- package/src/GitBackup/common/types.ts +11 -0
- package/src/GitBackup/ui/index.tsx +74 -28
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-ci.log
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @tasenor/common-plugins@1.10.
|
|
2
|
+
> @tasenor/common-plugins@1.10.36 ci /home/ci/tasenor-qa/tasenor-bookkeeper/packages/tasenor-common-plugins
|
|
3
3
|
> pnpm run lint
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @tasenor/common-plugins@1.10.
|
|
6
|
+
> @tasenor/common-plugins@1.10.36 lint /home/ci/tasenor-qa/tasenor-bookkeeper/packages/tasenor-common-plugins
|
|
7
7
|
> eslint 'src/**/*.{ts,tsx}' 'data/**/*.mjs'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
/home/ci/tasenor-qa/tasenor-bookkeeper/packages/tasenor-common-plugins/src/GitBackup/ui/index.tsx
|
|
11
|
-
2:58 warning 'Title' is defined but never used @typescript-eslint/no-unused-vars
|
|
12
|
-
|
|
13
|
-
✖ 1 problem (0 errors, 1 warning)
|
|
14
|
-
|
package/dist/Finnish/ui/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { LanguagePlugin } from '@tasenor/common-ui';
|
|
|
5
5
|
class Finnish extends LanguagePlugin {
|
|
6
6
|
static code = 'Finnish';
|
|
7
7
|
static title = 'Finnish';
|
|
8
|
-
static version = '1.0.
|
|
8
|
+
static version = '1.0.66';
|
|
9
9
|
static icon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12.36 6H7v6h7.24l.4 2H18V8h-5.24z" opacity=".3"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6h-5.6zm3.6 8h-3.36l-.4-2H7V6h5.36l.4 2H18v6z"/></svg>';
|
|
10
10
|
static releaseDate = '2023-06-10';
|
|
11
11
|
static use = 'ui';
|
|
@@ -26,6 +26,9 @@ class Finnish extends LanguagePlugin {
|
|
|
26
26
|
date2str(date) {
|
|
27
27
|
return dayjs(date).format('DD.MM.YYYY');
|
|
28
28
|
}
|
|
29
|
+
time2str(date) {
|
|
30
|
+
return dayjs(date).format('HH.mm.ss');
|
|
31
|
+
}
|
|
29
32
|
str2date(str, sample = null) {
|
|
30
33
|
sample = sample ? new Date(sample) : new Date();
|
|
31
34
|
let year, month, day;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Finnish/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,MAAM,OAAQ,SAAQ,cAAc;IAElC,MAAM,CAAC,IAAI,GAAG,SAAS,CAAA;IACvB,MAAM,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAA;IACzB,MAAM,CAAC,IAAI,GAAG,2SAA2S,CAAA;IACzT,MAAM,CAAC,WAAW,GAAG,YAAY,CAAA;IACjC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAA;IACjB,MAAM,CAAC,IAAI,GAAG,UAAU,CAAA;IACxB,MAAM,CAAC,WAAW,GAAG,yCAAyC,CAAA;IAE9D;QACE,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,SAAS,GAAG;YACf,EAAE,EAAE,EAAE;SACP,CAAA;IACH,CAAC;IAED,YAAY;QACV,OAAO,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACxB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,QAAQ,CAAC,IAAI;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC;IAED,QAAQ,CAAC,GAAG,EAAE,SAAsB,IAAI;QACtC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;QAC/C,IAAI,IAAI,EAAE,KAAK,EAAE,GAAG,CAAA;QACpB,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAClD,OAAO,SAAS,CAAA;SACjB;QACD,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QACnB,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAA;QAClD,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAA;QAC7C,IAAI,IAAI,GAAG,GAAG,EAAE;YACd,IAAI,IAAI,IAAI,CAAA;SACb;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;QAC/D,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC/D,CAAC;;AAGH,eAAe,OAAO,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Finnish/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,MAAM,OAAQ,SAAQ,cAAc;IAElC,MAAM,CAAC,IAAI,GAAG,SAAS,CAAA;IACvB,MAAM,CAAC,KAAK,GAAG,SAAS,CAAA;IACxB,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAA;IACzB,MAAM,CAAC,IAAI,GAAG,2SAA2S,CAAA;IACzT,MAAM,CAAC,WAAW,GAAG,YAAY,CAAA;IACjC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAA;IACjB,MAAM,CAAC,IAAI,GAAG,UAAU,CAAA;IACxB,MAAM,CAAC,WAAW,GAAG,yCAAyC,CAAA;IAE9D;QACE,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,SAAS,GAAG;YACf,EAAE,EAAE,EAAE;SACP,CAAA;IACH,CAAC;IAED,YAAY;QACV,OAAO,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACxB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,QAAQ,CAAC,IAAI;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACzC,CAAC;IAED,QAAQ,CAAC,IAAI;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IACvC,CAAC;IAED,QAAQ,CAAC,GAAG,EAAE,SAAsB,IAAI;QACtC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAA;QAC/C,IAAI,IAAI,EAAE,KAAK,EAAE,GAAG,CAAA;QACpB,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAClD,OAAO,SAAS,CAAA;SACjB;QACD,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QACnB,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAA;QAClD,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAA;QAC7C,IAAI,IAAI,GAAG,GAAG,EAAE;YACd,IAAI,IAAI,IAAI,CAAA;SACb;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;QAC/D,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC/D,CAAC;;AAGH,eAAe,OAAO,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KnexDatabase, ToolPlugin } from '@tasenor/common-node';
|
|
2
|
-
import {
|
|
2
|
+
import { GitBackupCommit } from '../common/types';
|
|
3
3
|
declare class GitBackup extends ToolPlugin {
|
|
4
4
|
constructor();
|
|
5
5
|
/**
|
|
@@ -18,6 +18,10 @@ declare class GitBackup extends ToolPlugin {
|
|
|
18
18
|
* List of the latest backup commits.
|
|
19
19
|
*/
|
|
20
20
|
GET(db: KnexDatabase, data: any): Promise<unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Restore from the backup.
|
|
23
|
+
*/
|
|
24
|
+
PUT(db: KnexDatabase, data: any): Promise<unknown>;
|
|
21
25
|
/**
|
|
22
26
|
* A helper to check settings and set up repository for further use.
|
|
23
27
|
*/
|
|
@@ -25,14 +29,22 @@ declare class GitBackup extends ToolPlugin {
|
|
|
25
29
|
/**
|
|
26
30
|
* Get a list of commits.
|
|
27
31
|
*/
|
|
28
|
-
collectCommits(db: KnexDatabase, limit: number): Promise<
|
|
32
|
+
collectCommits(db: KnexDatabase, limit: number): Promise<GitBackupCommit[]>;
|
|
29
33
|
/**
|
|
30
34
|
* Execute backup making for a database.
|
|
31
35
|
*/
|
|
32
36
|
makeBackup(db: KnexDatabase, message: string): Promise<boolean>;
|
|
37
|
+
/**
|
|
38
|
+
* Read in database from the give giot hash.
|
|
39
|
+
*/
|
|
40
|
+
restoreBackup(db: KnexDatabase, commit: string): Promise<boolean>;
|
|
33
41
|
/**
|
|
34
42
|
* Write the data from the database to the directory.
|
|
35
43
|
*/
|
|
36
|
-
dump
|
|
44
|
+
private dump;
|
|
45
|
+
/**
|
|
46
|
+
* Read the data to the database from the directory.
|
|
47
|
+
*/
|
|
48
|
+
private restore;
|
|
37
49
|
}
|
|
38
50
|
export default GitBackup;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { GitRepo, systemPiped, TasenorExporter, ToolPlugin } from '@tasenor/common-node';
|
|
1
|
+
import { BookkeeperImporter, GitRepo, systemPiped, TasenorExporter, ToolPlugin } from '@tasenor/common-node';
|
|
2
2
|
import { error, log, note, validGitRepoName } from '@tasenor/common';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
// TODO: Master branch should be configurable.
|
|
6
|
+
// Branch.
|
|
7
|
+
const BRANCH = 'main';
|
|
8
|
+
// Mainly for temporary testing with file:/// repository.
|
|
9
|
+
const ALLOW_BAD_REPOSITORY = false;
|
|
5
10
|
class GitBackup extends ToolPlugin {
|
|
6
11
|
constructor() {
|
|
7
12
|
super();
|
|
@@ -49,6 +54,16 @@ class GitBackup extends ToolPlugin {
|
|
|
49
54
|
}
|
|
50
55
|
return { success: false };
|
|
51
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Restore from the backup.
|
|
59
|
+
*/
|
|
60
|
+
async PUT(db, data) {
|
|
61
|
+
if (typeof data === 'object' && data !== null && !!data.commit) {
|
|
62
|
+
const success = await this.restoreBackup(db, data.commit);
|
|
63
|
+
return { success };
|
|
64
|
+
}
|
|
65
|
+
return { success: false };
|
|
66
|
+
}
|
|
52
67
|
/**
|
|
53
68
|
* A helper to check settings and set up repository for further use.
|
|
54
69
|
*/
|
|
@@ -63,7 +78,7 @@ class GitBackup extends ToolPlugin {
|
|
|
63
78
|
return null;
|
|
64
79
|
}
|
|
65
80
|
// Check repo URL.
|
|
66
|
-
if (!validGitRepoName(repository)) {
|
|
81
|
+
if (!ALLOW_BAD_REPOSITORY && !validGitRepoName(repository)) {
|
|
67
82
|
error(`Bad repository address ${JSON.stringify(repository)}.`);
|
|
68
83
|
return null;
|
|
69
84
|
}
|
|
@@ -88,6 +103,7 @@ class GitBackup extends ToolPlugin {
|
|
|
88
103
|
error(`Failed to establish git repository instance '${repository}' into ${workDir}.`);
|
|
89
104
|
return null;
|
|
90
105
|
}
|
|
106
|
+
repo.branch = BRANCH;
|
|
91
107
|
repo.configure({
|
|
92
108
|
name: 'Tasenor',
|
|
93
109
|
email: 'communications.tasenor@gmail.com',
|
|
@@ -108,13 +124,19 @@ class GitBackup extends ToolPlugin {
|
|
|
108
124
|
const { repo } = setup;
|
|
109
125
|
log(`Fetching commit list for DB '${db.client.config.connection.database}'.`);
|
|
110
126
|
await repo.update();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
127
|
+
try {
|
|
128
|
+
const gitLog = await repo.git.log({ maxCount: limit });
|
|
129
|
+
return gitLog.all.map(e => ({
|
|
130
|
+
hash: e.hash,
|
|
131
|
+
date: e.date,
|
|
132
|
+
message: e.message,
|
|
133
|
+
author: `${e.author_name} ${e.author_email ? '<' + e.author_email + '>' : ''}`.trim()
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
error(`Failed to get log from git repository for DB '${db.client.config.connection.database}'.`);
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
118
140
|
}
|
|
119
141
|
/**
|
|
120
142
|
* Execute backup making for a database.
|
|
@@ -126,9 +148,31 @@ class GitBackup extends ToolPlugin {
|
|
|
126
148
|
}
|
|
127
149
|
const { subDirectory, repo, backupDir } = setup;
|
|
128
150
|
log(`Making a backup into '${subDirectory}' of DB '${db.client.config.connection.database}'.`);
|
|
151
|
+
await repo.update();
|
|
129
152
|
await this.dump(db, backupDir);
|
|
130
153
|
return repo.put(message, subDirectory);
|
|
131
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Read in database from the give giot hash.
|
|
157
|
+
*/
|
|
158
|
+
async restoreBackup(db, commit) {
|
|
159
|
+
const setup = await this.setupRepository(db);
|
|
160
|
+
if (!setup) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
const { repo, backupDir } = setup;
|
|
164
|
+
log(`Restoting a backup into '${backupDir}' for DB '${db.client.config.connection.database}' from hash '${commit}'.`);
|
|
165
|
+
await repo.update();
|
|
166
|
+
try {
|
|
167
|
+
await repo.git.checkout(commit);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
error(`Checking out the hash '${commit}' failed: ${err}`);
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
await this.restore(db, backupDir);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
132
176
|
/**
|
|
133
177
|
* Write the data from the database to the directory.
|
|
134
178
|
*/
|
|
@@ -140,6 +184,9 @@ class GitBackup extends ToolPlugin {
|
|
|
140
184
|
}
|
|
141
185
|
const exportDir = path.join(dir, 'export');
|
|
142
186
|
fs.mkdirSync(exportDir, { recursive: true });
|
|
187
|
+
// This dump.sql is not really needed, but it is kind of safety net for failures
|
|
188
|
+
// in export and import code. It helps to rebuild database manually, if all else
|
|
189
|
+
// fails.
|
|
143
190
|
// TODO: Check for pg_dump crash. What if that happens?
|
|
144
191
|
const { host, port, database, user, password } = db.client.config.connection;
|
|
145
192
|
const url = `postgresql://${user}:${password}@${host}:${port}/${database}`;
|
|
@@ -147,6 +194,13 @@ class GitBackup extends ToolPlugin {
|
|
|
147
194
|
const exporter = new TasenorExporter();
|
|
148
195
|
await exporter.dump(db, exportDir);
|
|
149
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Read the data to the database from the directory.
|
|
199
|
+
*/
|
|
200
|
+
async restore(db, dir) {
|
|
201
|
+
const importer = new BookkeeperImporter();
|
|
202
|
+
await importer.restoreUser(db, path.join(dir, 'export'));
|
|
203
|
+
}
|
|
150
204
|
}
|
|
151
205
|
export default GitBackup;
|
|
152
206
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/GitBackup/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgB,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/GitBackup/backend/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/GitBackup/common/types.ts"],"names":[],"mappings":""}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import { Note, IconButton, SubPanel, ToolPlugin, Dialog } from '@tasenor/common-ui';
|
|
2
|
+
import { Note, IconButton, SubPanel, ToolPlugin, Dialog, Localize } from '@tasenor/common-ui';
|
|
3
3
|
import { makeObservable, observable, runInAction } from 'mobx';
|
|
4
4
|
import { Trans, useTranslation } from 'react-i18next';
|
|
5
5
|
import { Box, Table, TableBody, TableCell, TableContainer, TableRow, TextField, Typography } from '@mui/material';
|
|
6
|
+
import { useNavigate } from 'react-router-dom';
|
|
6
7
|
function MakeBackupIcon(props) {
|
|
7
8
|
const { disabled, onMakeBackup } = props;
|
|
8
9
|
const [askMessage, setAskMessage] = useState(false);
|
|
@@ -17,24 +18,60 @@ function MakeBackupIcon(props) {
|
|
|
17
18
|
function BackupCommitList(props) {
|
|
18
19
|
const { store, backups } = props;
|
|
19
20
|
const [commits, setCommits] = useState([]);
|
|
21
|
+
const [fetched, setFetched] = useState(false);
|
|
22
|
+
const [restore, setRestore] = useState(null);
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
// TODO: Use from common-ui once more useful.
|
|
25
|
+
const navigate = useNavigate();
|
|
20
26
|
useEffect(() => {
|
|
21
27
|
if (!store.db) {
|
|
22
28
|
return;
|
|
23
29
|
}
|
|
24
30
|
store.request(`/db/${store.db}/tools/${GitBackup.code}`, 'GET', { type: 'commits', count: 20 }).then((res) => {
|
|
31
|
+
setFetched(true);
|
|
25
32
|
if (res.success) {
|
|
26
33
|
setCommits(res.data.commits);
|
|
27
34
|
}
|
|
28
35
|
});
|
|
29
36
|
}, [store.db, backups]);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const onRestore = (commit) => {
|
|
38
|
+
store.request(`/db/${store.db}/tools/${GitBackup.code}`, 'PUT', { commit: commit.hash }).then((res) => {
|
|
39
|
+
if (res && res.success) {
|
|
40
|
+
store.addMessage(t('Backup restored successfully.'));
|
|
41
|
+
runInAction(() => {
|
|
42
|
+
store.setDb(null).then(() => {
|
|
43
|
+
navigate(`/${store.db}`);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
store.addError(t('Restoring backup failed.'));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
if (fetched && commits.length === 0) {
|
|
53
|
+
return React.createElement(Box, null,
|
|
54
|
+
React.createElement(Trans, null, "Not able to find any commits from the repository."));
|
|
55
|
+
}
|
|
56
|
+
return React.createElement(Box, null,
|
|
57
|
+
React.createElement(TableContainer, null,
|
|
58
|
+
React.createElement(Table, null,
|
|
59
|
+
React.createElement(TableBody, null, commits.map((commit, idx) => React.createElement(TableRow, { key: idx },
|
|
60
|
+
React.createElement(TableCell, null,
|
|
61
|
+
React.createElement(IconButton, { id: "Restore", icon: "update", title: "restore", onClick: () => setRestore(commit) })),
|
|
62
|
+
React.createElement(TableCell, null,
|
|
63
|
+
React.createElement(Typography, { color: "secondary" }, commit.hash),
|
|
64
|
+
React.createElement(Typography, { variant: "body1" }, commit.message),
|
|
65
|
+
React.createElement(Typography, { variant: "caption" }, commit.author)),
|
|
66
|
+
React.createElement(TableCell, null,
|
|
67
|
+
React.createElement(Localize, { date: commit.date, withTime: true }))))))),
|
|
68
|
+
React.createElement(Dialog, { isVisible: !!restore, title: t('Restore this backup?'), wider: true, onClose: () => setRestore(null), onConfirm: () => onRestore(restore) }, restore && React.createElement(Box, null,
|
|
69
|
+
React.createElement(Typography, { variant: "caption" },
|
|
70
|
+
React.createElement(Localize, { date: restore.date, withTime: true }),
|
|
71
|
+
" ",
|
|
72
|
+
restore.hash),
|
|
73
|
+
React.createElement(Typography, { variant: "body1" }, restore.message),
|
|
74
|
+
React.createElement(Typography, { variant: "caption" }, restore.author))));
|
|
38
75
|
}
|
|
39
76
|
class GitBackup extends ToolPlugin {
|
|
40
77
|
busy = false;
|
|
@@ -61,17 +98,25 @@ class GitBackup extends ToolPlugin {
|
|
|
61
98
|
'label-repository': 'Repository URL',
|
|
62
99
|
'label-subDirectory': 'Subdirectory inside the repository',
|
|
63
100
|
'label-sshPrivateKey': 'SSH private key',
|
|
64
|
-
'icon-
|
|
101
|
+
'icon-restore': 'Restore this backup',
|
|
102
|
+
'icon-summarize-make-backup': 'Make a backup',
|
|
65
103
|
},
|
|
66
104
|
fi: {
|
|
67
105
|
'label-repository': 'Git-säilön URL',
|
|
68
106
|
'label-subDirectory': 'Alihakemiston nimi säilön sisällä',
|
|
69
107
|
'label-sshPrivateKey': 'SSH yksityinen avain',
|
|
108
|
+
'icon-restore': 'Palauta tältä varmuuskopiolta',
|
|
70
109
|
'icon-summarize-make-backup': 'Tee varmuuskopio',
|
|
71
110
|
'Backup for Git': 'Git-pohjainen Varmuuskopiointi',
|
|
72
111
|
'Manual backup by GitBackup {version}': 'Ylimääräinen varmuuskopio GitBackup {version}',
|
|
73
112
|
'Backup created successfully.': 'Varmuuskopion luominen onnistui.',
|
|
74
|
-
'Creating backup failed.': 'Varmuuskopion luominen ei onnistunut.'
|
|
113
|
+
'Creating backup failed.': 'Varmuuskopion luominen ei onnistunut.',
|
|
114
|
+
'Not able to find any commits from the repository.': 'Varmuuskopio vaikuttaisi olevan tyhjä.',
|
|
115
|
+
'This tool takes every night automatically one backup.': 'Tämä työkalu tekee yhden varmuuskopion joka yö.',
|
|
116
|
+
'You can also make immediately backup from the icon above.': 'Lisäksi voit tehdä ylimääräisen varmuuskopion halutessasi ylläolevasta ikonista.',
|
|
117
|
+
'Existing backups are listed below and can be restored from the icon next to them.': 'Aiemmat varmuuskopiot ovat alla listattuna. Niistä voi palauttaa minkä tahansa klikkaamalla niiden vieressä olevaa ikonia.',
|
|
118
|
+
'Backup restored successfully.': 'Varmuuskopion palautus onnistui.',
|
|
119
|
+
'Restoring backup failed.': 'Varmuuskopion palauttaminen epäonnistui.'
|
|
75
120
|
}
|
|
76
121
|
};
|
|
77
122
|
}
|
|
@@ -91,10 +136,10 @@ class GitBackup extends ToolPlugin {
|
|
|
91
136
|
this.backups = this.backups + 1;
|
|
92
137
|
});
|
|
93
138
|
if (success) {
|
|
94
|
-
this.store.addMessage(this.t('Backup
|
|
139
|
+
this.store.addMessage(this.t('Backup restored successfully.'));
|
|
95
140
|
}
|
|
96
141
|
else {
|
|
97
|
-
this.store.addError(this.t('
|
|
142
|
+
this.store.addError(this.t('Restoring backup failed.'));
|
|
98
143
|
}
|
|
99
144
|
});
|
|
100
145
|
}
|
|
@@ -114,6 +159,8 @@ class GitBackup extends ToolPlugin {
|
|
|
114
159
|
React.createElement(Trans, null, "This tool takes every night automatically one backup."),
|
|
115
160
|
React.createElement(React.Fragment, null, " "),
|
|
116
161
|
React.createElement(Trans, null, "You can also make immediately backup from the icon above."),
|
|
162
|
+
React.createElement(React.Fragment, null, " "),
|
|
163
|
+
React.createElement(Trans, null, "Existing backups are listed below and can be restored from the icon next to them."),
|
|
117
164
|
React.createElement(React.Fragment, null, " ")),
|
|
118
165
|
React.createElement(Box, { sx: { m: 2 } },
|
|
119
166
|
React.createElement(BackupCommitList, { backups: this.backups, store: this.store })));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/GitBackup/ui/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/GitBackup/ui/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tasenor/common-plugins",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.37",
|
|
4
4
|
"description": "Shared common plugins of Tasenor project",
|
|
5
5
|
"repository": "git@github.com:dataplugoy/tasenor-bookkeeper.git",
|
|
6
6
|
"author": "Tommi Ronkainen <tommi.ronkainen@gmail.com>",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"dayjs": "1.10.8",
|
|
14
14
|
"sprintf-js": "^1.1.2",
|
|
15
15
|
"tsx": "^4.7.0",
|
|
16
|
-
"@tasenor/common": "1.10.
|
|
17
|
-
"@tasenor/common
|
|
18
|
-
"@tasenor/common-ui": "1.10.
|
|
16
|
+
"@tasenor/common-node": "1.10.37",
|
|
17
|
+
"@tasenor/common": "1.10.37",
|
|
18
|
+
"@tasenor/common-ui": "1.10.37"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@mui/icons-material": "^5.14.1",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react-i18next": "^13.0.2",
|
|
32
32
|
"react-router-dom": "^6.14.1",
|
|
33
33
|
"typescript": "^5.1.6",
|
|
34
|
-
"@tasenor/config": "1.10.
|
|
34
|
+
"@tasenor/config": "1.10.37",
|
|
35
35
|
"eslint-config-tasenor": "0.0.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
package/src/Finnish/ui/index.tsx
CHANGED
|
@@ -7,7 +7,7 @@ class Finnish extends LanguagePlugin {
|
|
|
7
7
|
|
|
8
8
|
static code = 'Finnish'
|
|
9
9
|
static title = 'Finnish'
|
|
10
|
-
static version = '1.0.
|
|
10
|
+
static version = '1.0.66'
|
|
11
11
|
static icon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12.36 6H7v6h7.24l.4 2H18V8h-5.24z" opacity=".3"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6h-5.6zm3.6 8h-3.36l-.4-2H7V6h5.36l.4 2H18v6z"/></svg>'
|
|
12
12
|
static releaseDate = '2023-06-10'
|
|
13
13
|
static use = 'ui'
|
|
@@ -33,6 +33,10 @@ class Finnish extends LanguagePlugin {
|
|
|
33
33
|
return dayjs(date).format('DD.MM.YYYY')
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
time2str(date) {
|
|
37
|
+
return dayjs(date).format('HH.mm.ss')
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
str2date(str, sample: null | Date = null) {
|
|
37
41
|
sample = sample ? new Date(sample) : new Date()
|
|
38
42
|
let year, month, day
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { GitRepo, KnexDatabase, systemPiped, TasenorExporter, ToolPlugin } from '@tasenor/common-node'
|
|
2
|
-
import { DirectoryPath, Email, error, FilePath, log, note, PluginCode, Url, validGitRepoName, Version } from '@tasenor/common'
|
|
1
|
+
import { BookkeeperImporter, GitRepo, KnexDatabase, systemPiped, TasenorExporter, ToolPlugin } from '@tasenor/common-node'
|
|
2
|
+
import { DirectoryPath, Email, error, FilePath, log, note, PluginCode, Timestring, Url, validGitRepoName, Version } from '@tasenor/common'
|
|
3
3
|
import fs from 'fs'
|
|
4
4
|
import path from 'path'
|
|
5
|
+
import { GitBackupCommit } from '../common/types'
|
|
6
|
+
|
|
7
|
+
// TODO: Master branch should be configurable.
|
|
8
|
+
// Branch.
|
|
9
|
+
const BRANCH = 'main'
|
|
10
|
+
|
|
11
|
+
// Mainly for temporary testing with file:/// repository.
|
|
12
|
+
const ALLOW_BAD_REPOSITORY = false
|
|
5
13
|
|
|
6
14
|
class GitBackup extends ToolPlugin {
|
|
7
15
|
constructor() {
|
|
@@ -59,6 +67,17 @@ class GitBackup extends ToolPlugin {
|
|
|
59
67
|
return { success: false }
|
|
60
68
|
}
|
|
61
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Restore from the backup.
|
|
72
|
+
*/
|
|
73
|
+
async PUT(db: KnexDatabase, data): Promise<unknown> {
|
|
74
|
+
if (typeof data === 'object' && data !== null && !!data.commit) {
|
|
75
|
+
const success = await this.restoreBackup(db, data.commit)
|
|
76
|
+
return { success }
|
|
77
|
+
}
|
|
78
|
+
return { success: false }
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
/**
|
|
63
82
|
* A helper to check settings and set up repository for further use.
|
|
64
83
|
*/
|
|
@@ -83,7 +102,7 @@ class GitBackup extends ToolPlugin {
|
|
|
83
102
|
}
|
|
84
103
|
|
|
85
104
|
// Check repo URL.
|
|
86
|
-
if (!validGitRepoName(repository)) {
|
|
105
|
+
if (!ALLOW_BAD_REPOSITORY && !validGitRepoName(repository)) {
|
|
87
106
|
error(`Bad repository address ${JSON.stringify(repository)}.`)
|
|
88
107
|
return null
|
|
89
108
|
}
|
|
@@ -114,6 +133,7 @@ class GitBackup extends ToolPlugin {
|
|
|
114
133
|
error(`Failed to establish git repository instance '${repository}' into ${workDir}.`)
|
|
115
134
|
return null
|
|
116
135
|
}
|
|
136
|
+
repo.branch = BRANCH
|
|
117
137
|
repo.configure({
|
|
118
138
|
name: 'Tasenor',
|
|
119
139
|
email: 'communications.tasenor@gmail.com' as Email,
|
|
@@ -128,7 +148,7 @@ class GitBackup extends ToolPlugin {
|
|
|
128
148
|
/**
|
|
129
149
|
* Get a list of commits.
|
|
130
150
|
*/
|
|
131
|
-
async collectCommits(db: KnexDatabase, limit: number): Promise<
|
|
151
|
+
async collectCommits(db: KnexDatabase, limit: number): Promise<GitBackupCommit[]> {
|
|
132
152
|
const setup = await this.setupRepository(db)
|
|
133
153
|
if (!setup) {
|
|
134
154
|
return []
|
|
@@ -137,13 +157,18 @@ class GitBackup extends ToolPlugin {
|
|
|
137
157
|
|
|
138
158
|
log(`Fetching commit list for DB '${db.client.config.connection.database}'.`)
|
|
139
159
|
await repo.update()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
160
|
+
try {
|
|
161
|
+
const gitLog = await repo.git.log({ maxCount: limit })
|
|
162
|
+
return gitLog.all.map(e => ({
|
|
163
|
+
hash: e.hash,
|
|
164
|
+
date: e.date as Timestring,
|
|
165
|
+
message: e.message,
|
|
166
|
+
author: `${e.author_name} ${e.author_email ? '<' + e.author_email + '>' : ''}`.trim()
|
|
167
|
+
}))
|
|
168
|
+
} catch (err) {
|
|
169
|
+
error(`Failed to get log from git repository for DB '${db.client.config.connection.database}'.`)
|
|
170
|
+
return []
|
|
171
|
+
}
|
|
147
172
|
}
|
|
148
173
|
|
|
149
174
|
/**
|
|
@@ -158,14 +183,39 @@ class GitBackup extends ToolPlugin {
|
|
|
158
183
|
const { subDirectory, repo, backupDir } = setup
|
|
159
184
|
|
|
160
185
|
log(`Making a backup into '${subDirectory}' of DB '${db.client.config.connection.database}'.`)
|
|
186
|
+
await repo.update()
|
|
161
187
|
await this.dump(db, backupDir)
|
|
162
188
|
return repo.put(message, subDirectory)
|
|
163
189
|
}
|
|
164
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Read in database from the give giot hash.
|
|
193
|
+
*/
|
|
194
|
+
async restoreBackup(db: KnexDatabase, commit: string): Promise<boolean> {
|
|
195
|
+
|
|
196
|
+
const setup = await this.setupRepository(db)
|
|
197
|
+
if (!setup) {
|
|
198
|
+
return false
|
|
199
|
+
}
|
|
200
|
+
const { repo, backupDir } = setup
|
|
201
|
+
|
|
202
|
+
log(`Restoting a backup into '${backupDir}' for DB '${db.client.config.connection.database}' from hash '${commit}'.`)
|
|
203
|
+
await repo.update()
|
|
204
|
+
try {
|
|
205
|
+
await repo.git.checkout(commit)
|
|
206
|
+
} catch (err) {
|
|
207
|
+
error(`Checking out the hash '${commit}' failed: ${err}`)
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
await this.restore(db, backupDir)
|
|
211
|
+
|
|
212
|
+
return true
|
|
213
|
+
}
|
|
214
|
+
|
|
165
215
|
/**
|
|
166
216
|
* Write the data from the database to the directory.
|
|
167
217
|
*/
|
|
168
|
-
async dump(db: KnexDatabase, dir: DirectoryPath) {
|
|
218
|
+
private async dump(db: KnexDatabase, dir: DirectoryPath) {
|
|
169
219
|
|
|
170
220
|
note(`Creating backup into '${dir}'.`)
|
|
171
221
|
|
|
@@ -175,6 +225,10 @@ class GitBackup extends ToolPlugin {
|
|
|
175
225
|
}
|
|
176
226
|
const exportDir = path.join(dir, 'export') as DirectoryPath
|
|
177
227
|
fs.mkdirSync(exportDir, { recursive: true })
|
|
228
|
+
|
|
229
|
+
// This dump.sql is not really needed, but it is kind of safety net for failures
|
|
230
|
+
// in export and import code. It helps to rebuild database manually, if all else
|
|
231
|
+
// fails.
|
|
178
232
|
// TODO: Check for pg_dump crash. What if that happens?
|
|
179
233
|
const { host, port, database, user, password } = db.client.config.connection
|
|
180
234
|
const url = `postgresql://${user}:${password}@${host}:${port}/${database}`
|
|
@@ -183,6 +237,14 @@ class GitBackup extends ToolPlugin {
|
|
|
183
237
|
const exporter = new TasenorExporter()
|
|
184
238
|
await exporter.dump(db, exportDir)
|
|
185
239
|
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Read the data to the database from the directory.
|
|
243
|
+
*/
|
|
244
|
+
private async restore(db: KnexDatabase, dir: DirectoryPath): Promise<void> {
|
|
245
|
+
const importer = new BookkeeperImporter()
|
|
246
|
+
await importer.restoreUser(db, path.join(dir, 'export') as DirectoryPath)
|
|
247
|
+
}
|
|
186
248
|
}
|
|
187
249
|
|
|
188
250
|
export default GitBackup
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from 'react'
|
|
2
|
-
import { Note, IconButton, SubPanel, ToolPlugin, Dialog,
|
|
2
|
+
import { Note, IconButton, SubPanel, ToolPlugin, Dialog, Localize } from '@tasenor/common-ui'
|
|
3
3
|
import { makeObservable, observable, runInAction } from 'mobx'
|
|
4
4
|
import { Trans, useTranslation } from 'react-i18next'
|
|
5
5
|
import { Box, Table, TableBody, TableCell, TableContainer, TableRow, TextField, Typography } from '@mui/material'
|
|
6
|
-
import { Store
|
|
6
|
+
import { Store } from '@tasenor/common'
|
|
7
|
+
import { GitBackupCommit } from '../common/types'
|
|
8
|
+
import { useNavigate } from 'react-router-dom'
|
|
7
9
|
|
|
8
10
|
interface MakeBackupIconProps {
|
|
9
11
|
disabled: boolean
|
|
@@ -33,13 +35,6 @@ function MakeBackupIcon(props: MakeBackupIconProps): React.ReactNode {
|
|
|
33
35
|
</>
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
interface GitBackupCommit {
|
|
37
|
-
hash: string
|
|
38
|
-
date: Timestring
|
|
39
|
-
message: string
|
|
40
|
-
author: string
|
|
41
|
-
}
|
|
42
|
-
|
|
43
38
|
interface BackupCommitListProps {
|
|
44
39
|
store: Store
|
|
45
40
|
backups: number
|
|
@@ -47,32 +42,75 @@ interface BackupCommitListProps {
|
|
|
47
42
|
|
|
48
43
|
function BackupCommitList(props: BackupCommitListProps): React.ReactNode {
|
|
49
44
|
const { store, backups } = props
|
|
50
|
-
const [commits, setCommits] = useState<GitBackupCommit>([])
|
|
45
|
+
const [commits, setCommits] = useState<GitBackupCommit[]>([])
|
|
46
|
+
const [fetched, setFetched] = useState(false)
|
|
47
|
+
const [restore, setRestore] = useState<GitBackupCommit|null>(null)
|
|
48
|
+
const { t } = useTranslation()
|
|
49
|
+
// TODO: Use from common-ui once more useful.
|
|
50
|
+
const navigate = useNavigate()
|
|
51
51
|
|
|
52
52
|
useEffect(() => {
|
|
53
53
|
if (!store.db) {
|
|
54
54
|
return
|
|
55
55
|
}
|
|
56
56
|
store.request<{ commits: GitBackupCommit[] }>(`/db/${store.db}/tools/${GitBackup.code}`, 'GET', { type: 'commits', count: 20 }).then((res) => {
|
|
57
|
+
setFetched(true)
|
|
57
58
|
if (res.success) {
|
|
58
59
|
setCommits(res.data.commits)
|
|
59
60
|
}
|
|
60
61
|
})
|
|
61
62
|
}, [store.db, backups])
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
const onRestore = (commit: GitBackupCommit) => {
|
|
65
|
+
store.request<{ commits: GitBackupCommit[] }>(`/db/${store.db}/tools/${GitBackup.code}`, 'PUT', { commit: commit.hash }).then((res) => {
|
|
66
|
+
if (res && res.success) {
|
|
67
|
+
store.addMessage(t('Backup restored successfully.'))
|
|
68
|
+
runInAction(() => {
|
|
69
|
+
store.setDb(null).then(() => {
|
|
70
|
+
navigate(`/${store.db}`)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
} else {
|
|
74
|
+
store.addError(t('Restoring backup failed.'))
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (fetched && commits.length === 0) {
|
|
80
|
+
return <Box>
|
|
81
|
+
<Trans>Not able to find any commits from the repository.</Trans>
|
|
82
|
+
</Box>
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return <Box>
|
|
86
|
+
<TableContainer>
|
|
87
|
+
<Table>
|
|
88
|
+
<TableBody>
|
|
89
|
+
{commits.map((commit, idx) => <TableRow key={idx}>
|
|
90
|
+
<TableCell>
|
|
91
|
+
<IconButton id="Restore" icon="update" title="restore" onClick={() => setRestore(commit)}/>
|
|
92
|
+
</TableCell>
|
|
93
|
+
<TableCell>
|
|
94
|
+
<Typography color="secondary">{commit.hash}</Typography>
|
|
95
|
+
<Typography variant="body1">{commit.message}</Typography>
|
|
96
|
+
<Typography variant="caption">{commit.author}</Typography>
|
|
97
|
+
</TableCell>
|
|
98
|
+
<TableCell>
|
|
99
|
+
<Localize date={commit.date} withTime/>
|
|
100
|
+
</TableCell>
|
|
101
|
+
</TableRow>)}
|
|
102
|
+
</TableBody>
|
|
103
|
+
</Table>
|
|
104
|
+
</TableContainer>
|
|
105
|
+
|
|
106
|
+
<Dialog isVisible={!!restore} title={t('Restore this backup?')} wider onClose={() => setRestore(null)} onConfirm={() => onRestore(restore)}>
|
|
107
|
+
{ restore && <Box>
|
|
108
|
+
<Typography variant="caption"><Localize date={restore.date} withTime/> {restore.hash}</Typography>
|
|
109
|
+
<Typography variant="body1">{restore.message}</Typography>
|
|
110
|
+
<Typography variant="caption">{restore.author}</Typography>
|
|
111
|
+
</Box>}
|
|
112
|
+
</Dialog>
|
|
113
|
+
</Box>
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
class GitBackup extends ToolPlugin {
|
|
@@ -105,21 +143,28 @@ class GitBackup extends ToolPlugin {
|
|
|
105
143
|
'label-repository': 'Repository URL',
|
|
106
144
|
'label-subDirectory': 'Subdirectory inside the repository',
|
|
107
145
|
'label-sshPrivateKey': 'SSH private key',
|
|
108
|
-
'icon-
|
|
146
|
+
'icon-restore': 'Restore this backup',
|
|
147
|
+
'icon-summarize-make-backup': 'Make a backup',
|
|
109
148
|
},
|
|
110
149
|
fi: {
|
|
111
150
|
'label-repository': 'Git-säilön URL',
|
|
112
151
|
'label-subDirectory': 'Alihakemiston nimi säilön sisällä',
|
|
113
152
|
'label-sshPrivateKey': 'SSH yksityinen avain',
|
|
153
|
+
'icon-restore': 'Palauta tältä varmuuskopiolta',
|
|
114
154
|
'icon-summarize-make-backup': 'Tee varmuuskopio',
|
|
115
155
|
|
|
116
156
|
'Backup for Git': 'Git-pohjainen Varmuuskopiointi',
|
|
117
157
|
'Manual backup by GitBackup {version}': 'Ylimääräinen varmuuskopio GitBackup {version}',
|
|
118
158
|
'Backup created successfully.': 'Varmuuskopion luominen onnistui.',
|
|
119
|
-
'Creating backup failed.': 'Varmuuskopion luominen ei onnistunut.'
|
|
159
|
+
'Creating backup failed.': 'Varmuuskopion luominen ei onnistunut.',
|
|
160
|
+
'Not able to find any commits from the repository.': 'Varmuuskopio vaikuttaisi olevan tyhjä.',
|
|
161
|
+
'This tool takes every night automatically one backup.': 'Tämä työkalu tekee yhden varmuuskopion joka yö.',
|
|
162
|
+
'You can also make immediately backup from the icon above.': 'Lisäksi voit tehdä ylimääräisen varmuuskopion halutessasi ylläolevasta ikonista.',
|
|
163
|
+
'Existing backups are listed below and can be restored from the icon next to them.': 'Aiemmat varmuuskopiot ovat alla listattuna. Niistä voi palauttaa minkä tahansa klikkaamalla niiden vieressä olevaa ikonia.',
|
|
164
|
+
'Backup restored successfully.': 'Varmuuskopion palautus onnistui.',
|
|
165
|
+
'Restoring backup failed.': 'Varmuuskopion palauttaminen epäonnistui.'
|
|
120
166
|
}
|
|
121
167
|
}
|
|
122
|
-
|
|
123
168
|
}
|
|
124
169
|
|
|
125
170
|
toolMenu() {
|
|
@@ -140,9 +185,9 @@ class GitBackup extends ToolPlugin {
|
|
|
140
185
|
this.backups = this.backups + 1
|
|
141
186
|
})
|
|
142
187
|
if (success) {
|
|
143
|
-
this.store.addMessage(this.t('Backup
|
|
188
|
+
this.store.addMessage(this.t('Backup restored successfully.'))
|
|
144
189
|
} else {
|
|
145
|
-
this.store.addError(this.t('
|
|
190
|
+
this.store.addError(this.t('Restoring backup failed.'))
|
|
146
191
|
}
|
|
147
192
|
})
|
|
148
193
|
}
|
|
@@ -164,6 +209,7 @@ class GitBackup extends ToolPlugin {
|
|
|
164
209
|
<SubPanel>
|
|
165
210
|
<Trans>This tool takes every night automatically one backup.</Trans><> </>
|
|
166
211
|
<Trans>You can also make immediately backup from the icon above.</Trans><> </>
|
|
212
|
+
<Trans>Existing backups are listed below and can be restored from the icon next to them.</Trans><> </>
|
|
167
213
|
</SubPanel>
|
|
168
214
|
<Box sx={{ m: 2 }}>
|
|
169
215
|
<BackupCommitList backups={this.backups} store={this.store}/>
|