diff --git a/.gitignore b/.gitignore index 490d3c786f55eae73d4a4fb660cb4c866515299e..407747941db2dff5b836e61cd0abf1ff45aa3ed8 100644 --- a/.gitignore +++ b/.gitignore @@ -109,4 +109,4 @@ venv.bak/ ## mypy .mypy_cache/ -reforis_static/reforis_schnapps/js/app.min.js +reforis_static/reforis_snapshots/js/app.min.js diff --git a/MANIFEST.in b/MANIFEST.in index e59109ee7f25ea74e707c9baaa507a2a62114d86..eb4e2287ac2c554c4aec6eff850960e48ca23eb4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -recursive-include reforis_static/schnapps * +recursive-include reforis_static/snapshots * diff --git a/Makefile b/Makefile index d56be0d2ed5412133e7348102715be6255afe94f..a81836715dbe1f132cae96cf652ac8628004c71b 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,11 @@ .PHONY: all venv prepare-dev install install-js install-local-reforis watch-js build-js lint lint-js lint-js-fix lint-web test test-js test-web test-js-update-snapshots create-messages init-langs update-messages compile-messages clean -DEV_PYTHON=python3.7 -ROUTER_PYTHON=python3.6 VENV_NAME?=venv VENV_BIN=$(shell pwd)/$(VENV_NAME)/bin +PYTHON=python3 + JS_DIR=./js LANGS = cs da de el en fi fo fr hr hu it ja ko lt nb nb_NO nl pl ro ru sk sv @@ -40,29 +40,29 @@ all: venv: $(VENV_NAME)/bin/activate $(VENV_NAME)/bin/activate: setup.py - test -d $(VENV_NAME) || $(DEV_PYTHON) -m virtualenv -p $(DEV_PYTHON) $(VENV_NAME) + test -d $(VENV_NAME) || $(PYTHON) -m virtualenv -p $(PYTHON) $(VENV_NAME) # Some problem in latest version of setuptools during extracting translations. - $(VENV_BIN)/$(DEV_PYTHON) -m pip install -U pip setuptools==39.1.0 - $(VENV_BIN)/$(DEV_PYTHON) -m pip install -e .[devel] + $(VENV_BIN)/$(PYTHON) -m pip install -U pip setuptools==39.1.0 + $(VENV_BIN)/$(PYTHON) -m pip install -e .[devel] touch $(VENV_NAME)/bin/activate prepare-env: which npm || curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - which npm || sudo apt install -y nodejs - which $(DEV_PYTHON) || sudo apt install -y $(DEV_PYTHON) $(DEV_PYTHON)-pip - which virtualenv || sudo $(DEV_PYTHON) -m pip install virtualenv + which $(PYTHON) || sudo apt install -y $(PYTHON) $(PYTHON)-pip + which virtualenv || sudo $(PYTHON) -m pip install virtualenv prepare-dev: cd $(JS_DIR); npm install make venv install: - $(ROUTER_PYTHON) -m pip install -e . - ln -sf /tmp/reforis-schnapps/reforis_static/reforis_schnapps /tmp/reforis/reforis_static/ + $(PYTHON) -m pip install -e . + ln -sf /tmp/reforis-snapshots/reforis_static/reforis_snapshots /tmp/reforis/reforis_static/ /etc/init.d/lighttpd restart install-js: js/package.json cd $(JS_DIR); npm install --save-dev install-local-reforis: - $(VENV_BIN)/$(DEV_PYTHON) -m pip install -e ../reforis + $(VENV_BIN)/$(PYTHON) -m pip install -e ../reforis watch-js: cd $(JS_DIR); npm run-script watch @@ -75,33 +75,33 @@ lint-js: lint-js-fix: cd $(JS_DIR); npm run lint:fix lint-web: venv - $(VENV_BIN)/$(DEV_PYTHON) -m pylint --rcfile=pylintrc reforis_schnapps - $(VENV_BIN)/$(DEV_PYTHON) -m pycodestyle --config=pycodestyle reforis_schnapps + $(VENV_BIN)/$(PYTHON) -m pylint --rcfile=pylintrc reforis_snapshots + $(VENV_BIN)/$(PYTHON) -m pycodestyle --config=pycodestyle reforis_snapshots test: test-js test-web test-js: cd $(JS_DIR); npm test test-web: venv - $(VENV_BIN)/$(DEV_PYTHON) -m pytest -vv tests + $(VENV_BIN)/$(PYTHON) -m pytest -vv tests test-js-update-snapshots: cd $(JS_DIR); npm test -- -u create-messages: - $(VENV_BIN)/pybabel extract -F babel.cfg -o ./reforis_schnapps/translations/messages.pot . + $(VENV_BIN)/pybabel extract -F babel.cfg -o ./reforis_snapshots/translations/messages.pot . init-langs: create-messages for lang in $(LANGS); do \ $(VENV_BIN)/pybabel init \ - -i reforis_schnapps/translations/messages.pot \ - -d reforis_schnapps/translations/ -l $$lang \ + -i reforis_snapshots/translations/messages.pot \ + -d reforis_snapshots/translations/ -l $$lang \ ; done update-messages: - $(VENV_BIN)/pybabel update -i ./reforis_schnapps/translations/messages.pot -d ./reforis/translations + $(VENV_BIN)/pybabel update -i ./reforis_snapshots/translations/messages.pot -d ./reforis_snapshots/translations compile-messages: - $(VENV_BIN)/pybabel compile -f -d ./reforis_schnapps/translations + $(VENV_BIN)/pybabel compile -f -d ./reforis_snapshots/translations clean: find . -name '*.pyc' -exec rm -f {} + rm -rf $(VENV_NAME) *.eggs *.egg-info dist build .cache rm -rf dist build *.egg-info - rm -rf $(JS_DIR)/node_modules/ reforis_static/reforis_schnapps/js/app.min.js - $(ROUTER_PYTHON) -m pip uninstall -y reforis_schnapps + rm -rf $(JS_DIR)/node_modules/ reforis_static/reforis_snapshots/js/app.min.js + $(PYTHON) -m pip uninstall -y reforis_snapshots diff --git a/README.md b/README.md index 29489ceee07eab7f9d9f3480bccca8344a30f4a9..5c921b5a18143f88f1178cc53139b83be16079ef 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# reForis Schnapps plugin +# reForis Snapshots plugin To learn more about the plugin system see documentation of [reForis](https://gitlab.labs.nic.cz/turris/reforis). diff --git a/babel.cfg b/babel.cfg index ccb108427c655e848d22e95bfa7daee9070a8c9b..aadf334f55e570ed07fcb3511236de49936bf363 100644 --- a/babel.cfg +++ b/babel.cfg @@ -1,2 +1,2 @@ -[python: reforis_schnapps/**.py] +[python: reforis_snapshots/**.py] [javascript: js/src/**.js] diff --git a/js/package-lock.json b/js/package-lock.json index b2853ff6ee38b1c05dc7a3726da7df817e1bbba9..42eda3fbea4f8a3d9dc0d3f1b9beda59a1c58ffc 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -1,5 +1,5 @@ { - "name": "reforis_schnapps", + "name": "reforis_snapshots", "version": "0.1.0", "lockfileVersion": 1, "requires": true, diff --git a/js/package.json b/js/package.json index b286209682d9db782c848aec9e2122cb4c2a442a..71866bbb4a33bee7a575d5c380c1843737684993 100644 --- a/js/package.json +++ b/js/package.json @@ -1,5 +1,5 @@ { - "name": "reforis_schnapps", + "name": "reforis_snapshots", "author": "CZ.NIC, z.s.p.o.", "license": "GPL-3.0", "version": "0.1.0", diff --git a/js/src/API.js b/js/src/API.js index a66778fee7b0d30d14c41913e627f35d7a1f5aea..e68331db26242c01cab7565b504bbfd4961b3a90 100644 --- a/js/src/API.js +++ b/js/src/API.js @@ -7,11 +7,11 @@ import { REFORIS_URL_PREFIX } from "foris"; -const API_URL_PREFIX = `${REFORIS_URL_PREFIX}/schnapps/api`; +const API_URL_PREFIX = `${REFORIS_URL_PREFIX}/snapshots/api`; const API_URLs = new Proxy( { - example: "/example", + snapshots: "/snapshots", }, { get: (target, name) => `${API_URL_PREFIX}${target[name]}`, diff --git a/js/src/app.js b/js/src/app.js index 6e4c8406b3477e94fc0bf976c9052182e759c933..bc2abc3a028fd693d01d5a96888d7466d06d8a09 100644 --- a/js/src/app.js +++ b/js/src/app.js @@ -5,14 +5,14 @@ * See /LICENSE for more information. */ -import Schnapps from "./schnapps/Schnapps"; +import Snapshots from "./snapshots/Snapshots"; -const SchnappsPlugin = { - name: _("Schnapps"), +const SnapshotsPlugin = { + name: _("Snapshots"), submenuId: "administration", weight: 100, - path: "/schnapps", - component: Schnapps, + path: "/snapshots", + component: Snapshots, }; -ForisPlugins.push(SchnappsPlugin); +ForisPlugins.push(SnapshotsPlugin); diff --git a/js/src/schnapps/Schnapps.js b/js/src/schnapps/Schnapps.js deleted file mode 100644 index 537e5e16bd56e3c46346aa2e75c7c2f3b822f97f..0000000000000000000000000000000000000000 --- a/js/src/schnapps/Schnapps.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) - * - * This is free software, licensed under the GNU General Public License v3. - * See /LICENSE for more information. - */ - -import React, { useEffect } from "react"; - -import { useAPIGet } from "foris"; - -import API_URLs from "API"; - -export default function Schnapps() { - const [, getExample] = useAPIGet(API_URLs.example); - useEffect(() => { - getExample(); - }, [getExample]); - - return ( - <> -

{_("Schnapps")}

-

{_("Add your components here")}

- - ); -} diff --git a/js/src/schnapps/__tests__/Schnapps.test.js b/js/src/schnapps/__tests__/Schnapps.test.js deleted file mode 100644 index b1169e0c771ef42dfc114df4741e041ef2d0d239..0000000000000000000000000000000000000000 --- a/js/src/schnapps/__tests__/Schnapps.test.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) - * - * This is free software, licensed under the GNU General Public License v3. - * See /LICENSE for more information. - */ - -import React from "react"; -import mockAxios from "jest-mock-axios"; -import { render } from "foris/testUtils/customTestRender"; - -import Schnapps from "../Schnapps"; - -describe("", () => { - it("should render component", () => { - const { getByText } = render(); - expect(getByText("Schnapps")).toBeDefined(); - expect(mockAxios.get).toBeCalledWith("/reforis/schnapps/api/example", expect.anything()); - }); -}); diff --git a/js/src/snapshots/CreateSnapshotForm.js b/js/src/snapshots/CreateSnapshotForm.js new file mode 100644 index 0000000000000000000000000000000000000000..589feeebe65c81a28a985d7667739508c9e58b87 --- /dev/null +++ b/js/src/snapshots/CreateSnapshotForm.js @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; + +import { + SubmitButton, SUBMIT_BUTTON_STATES, TextInput, useForm, formFieldsSize, +} from "foris"; + +CreateSnapshotForm.propTypes = { + createSnapshot: PropTypes.func.isRequired, +}; + +export default function CreateSnapshotForm({ createSnapshot }) { + const [formState, formChangeHandler, reloadForm] = useForm(validator); + const formData = formState.data; + const formErrors = formState.errors || {}; + useEffect(() => { + reloadForm({ description: "" }); + }, [reloadForm]); + + function handleSubmit(event) { + event.preventDefault(); + createSnapshot({ data: { description: formState.data.description } }); + } + + if (!formData) { + return null; + } + + return ( +
+
+

{_("Create new snapshot")}

+ ({ description: { $set: value } }))} + /> +
+ 0} + state={SUBMIT_BUTTON_STATES.READY} + /> +
+ +
+ ); +} + +function validator(formData) { + if (!formData.description) { + return { description: _("Description is required.") }; + } + return undefined; +} diff --git a/js/src/snapshots/Snapshots.js b/js/src/snapshots/Snapshots.js new file mode 100644 index 0000000000000000000000000000000000000000..0277c00a7c28f1de775ea1bef9274aead5f14aed --- /dev/null +++ b/js/src/snapshots/Snapshots.js @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React, { useState } from "react"; +import PropTypes from "prop-types"; + +import { API_STATE, Spinner, ErrorMessage } from "foris"; + +import { + useGetSnapshots, useUpdateSnapshotsOnAdd, useCreateSnapshot, useDeleteSnapshot, + useUpdateSnapshotsOnDelete, useRollbackSnapshot, useUpdateSnapshotsOnRollback, +} from "./hooks"; +import CreateSnapshotForm from "./CreateSnapshotForm"; +import SnapshotsTable from "./SnapshotsTable"; + +Snapshots.propTypes = { + ws: PropTypes.object.isRequired, +}; + +export default function Snapshots({ ws }) { + const [snapshots, setSnapshots] = useState([]); + + const [getState, getSnapshots] = useGetSnapshots(setSnapshots); + useUpdateSnapshotsOnAdd(ws, getSnapshots); + + const [createState, createSnapshot] = useCreateSnapshot(); + + const [rollbackState, rollbackSnapshot] = useRollbackSnapshot(); + useUpdateSnapshotsOnRollback(ws, getSnapshots); + + const [deleteState, deleteSnapshot] = useDeleteSnapshot(); + useUpdateSnapshotsOnDelete(ws, setSnapshots); + + let componentContent; + if (getState === API_STATE.INIT + || [getState, createState, rollbackState, deleteState].includes(API_STATE.SENDING)) { + componentContent = ; + } else if (getState === API_STATE.ERROR) { + componentContent = ; + } else { + componentContent = ( + <> + +

{_("Available Snapshots")}

+ + + ); + } + + return ( + <> +

{_("Snapshots")}

+

advanced options.") }} /> + {componentContent} + + ); +} diff --git a/js/src/snapshots/SnapshotsTable.css b/js/src/snapshots/SnapshotsTable.css new file mode 100644 index 0000000000000000000000000000000000000000..1bf25590daf854b27e3675cdceadcaed01ca8798 --- /dev/null +++ b/js/src/snapshots/SnapshotsTable.css @@ -0,0 +1,14 @@ +.snapshots-table td { + vertical-align: middle; +} + +@media (max-width: 1400px) { + .snapshots-table-delete-icon { + display: none; + } +} + +.snaphots-table-created-at { + text-align: center; + min-width: 6rem; +} diff --git a/js/src/snapshots/SnapshotsTable.js b/js/src/snapshots/SnapshotsTable.js new file mode 100644 index 0000000000000000000000000000000000000000..690960aa0fea99e7cf37dc943a65347e78269d75 --- /dev/null +++ b/js/src/snapshots/SnapshotsTable.js @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; +import PropTypes from "prop-types"; + +import { Button } from "foris"; + +import "./SnapshotsTable.css"; + +const snapshotShape = PropTypes.shape({ + number: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + created: PropTypes.string.isRequired, + size: PropTypes.string.isRequired, +}); + +SnapshotsTable.propTypes = { + snapshots: PropTypes.arrayOf(snapshotShape).isRequired, + rollbackSnapshot: PropTypes.func.isRequired, + deleteSnapshot: PropTypes.func.isRequired, +}; + +export default function SnapshotsTable({ snapshots, rollbackSnapshot, deleteSnapshot }) { + return ( +

+ + + + + + + + + + + + {snapshots.map( + (snapshot) => ( + rollbackSnapshot(snapshot.number)} + deleteSnapshot={() => deleteSnapshot({ suffix: snapshot.number })} + /> + ), + )} + +
{_("Number")}{_("Type")}{_("Description")}{_("Created at")}{_("Size")} + +
+
+ ); +} + +SnapshotRow.propTypes = { + snapshot: snapshotShape.isRequired, + rollbackSnapshot: PropTypes.func.isRequired, + deleteSnapshot: PropTypes.func.isRequired, +}; + +function SnapshotRow({ snapshot, rollbackSnapshot, deleteSnapshot }) { + return ( + + {snapshot.number} + {snapshot.type} + {snapshot.description} + {snapshot.created} + {snapshot.size} + + + + + + + + ); +} diff --git a/js/src/snapshots/__tests__/Snapshots.test.js b/js/src/snapshots/__tests__/Snapshots.test.js new file mode 100644 index 0000000000000000000000000000000000000000..98eda682ee234305a3efaf050b30fe37efdbce26 --- /dev/null +++ b/js/src/snapshots/__tests__/Snapshots.test.js @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import React from "react"; +import mockAxios from "jest-mock-axios"; +import { + render, wait, getAllByText, queryByText, getByText, getByLabelText, queryByRole, getByRole, + act, fireEvent, +} from "foris/testUtils/customTestRender"; +import { mockJSONError } from "foris/testUtils/network"; +import { mockSetAlert } from "foris/testUtils/alertContextMock"; +import { WebSockets } from "foris"; + +import Snapshots from "../Snapshots"; + +const SNAPSHOTS = [ + { + number: 1, type: "single", description: "Whatever", created: "2020-01-30T10:27:34Z", size: "808 kB", + }, + { + number: 2, type: "rollback", description: "Something", created: "2020-01-31T10:27:34Z", size: "909 kB", + }, +]; + +function creteSnapshot(number, description) { + return { + number, type: "single", description, created: "2020-01-30T10:27:34Z", size: "808 kB", + }; +} + +describe("", () => { + let container; + let webSockets; + + beforeEach(() => { + webSockets = new WebSockets(); + ({ container } = render()); + }); + + it("should render spinner", () => { + expect(container).toMatchSnapshot(); + }); + + it("should render table", async () => { + expect(mockAxios.get).toBeCalledWith( + "/reforis/snapshots/api/snapshots", expect.anything(), + ); + mockAxios.mockResponse({ data: SNAPSHOTS }); + await wait(() => getByText(container, SNAPSHOTS[0].description)); + expect(container).toMatchSnapshot(); + }); + + it("should handle GET error", async () => { + mockJSONError(); + await wait(() => expect( + getByText(container, "An error occurred while fetching data."), + ).toBeTruthy()); + }); + + it("should display spinner while snapshot is being added", async () => { + // Prepare table + mockAxios.mockResponse({ data: SNAPSHOTS }); + // Initially there's no spinner + await wait(() => expect( + queryByRole(container, "status"), + ).toBeNull()); + + // Create new snapshot + act(() => webSockets.dispatch( + { module: "schnapps", action: "create", data: {} }, + )); + // Spinner should appear + await wait(() => getByRole(container, "status")); + }); + + it("should display spinner when snapshot is being removed", async () => { + // Prepare table + mockAxios.mockResponse({ data: SNAPSHOTS }); + // Initially there's no spinner + await wait(() => expect( + queryByRole(container, "status"), + ).toBeNull()); + + // Delete device + fireEvent.click(getAllByText(container, "Delete")[0]); + // Spinner should appear + await wait(() => getByRole(container, "status")); + }); + + it("should display spinner while rolling back to snapshot", async () => { + // Prepare table + mockAxios.mockResponse({ data: SNAPSHOTS }); + // Initially there's no spinner + await wait(() => expect( + queryByRole(container, "status"), + ).toBeNull()); + + // Delete device + fireEvent.click(getAllByText(container, "Rollback")[0]); + // Spinner should appear + await wait(() => getByRole(container, "status")); + }); + + describe("with table prepared", () => { + beforeEach(async () => { + // Prepare table + mockAxios.mockResponse({ data: SNAPSHOTS }); + await wait(() => getByText(container, SNAPSHOTS[0].description)); + }); + + it("should refresh table after new snapshot is added", async () => { + // Create new snapshot + const newDescription = "Nothing"; + act(() => webSockets.dispatch( + { module: "schnapps", action: "create", data: {} }, + )); + expect(mockAxios.get).toHaveBeenNthCalledWith(2, "/reforis/snapshots/api/snapshots", expect.anything()); + mockAxios.mockResponse({ data: [...SNAPSHOTS, creteSnapshot(3, newDescription)] }); + // New snapshot should appear + await wait(() => getByText(container, newDescription)); + }); + + it("should refresh table after snapshot is removed", async () => { + // Delete snapshot + const deletedNumber = SNAPSHOTS[0].number; + fireEvent.click(getAllByText(container, "Delete")[0]); + expect(mockAxios.delete).toBeCalledWith( + `/reforis/snapshots/api/snapshots/${deletedNumber}`, expect.anything(), + ); + mockAxios.mockResponse({ data: {} }); + + act(() => webSockets.dispatch( + { module: "schnapps", action: "delete", data: { number: deletedNumber } }, + )); + // Device should disappear + await wait(() => expect(queryByText(container, SNAPSHOTS[0].description)).toBeNull()); + }); + + it("should handle error on removal", async () => { + // Delete device + fireEvent.click(getAllByText(container, "Delete")[0]); + // Handle error + const errorMessage = "API didn't handle this well"; + mockJSONError(errorMessage); + await wait(() => { + expect(mockSetAlert).toHaveBeenCalledWith(errorMessage); + }); + }); + + it("should refresh table after rolling back to snapshot", async () => { + // Rollback to snapshot + const rollbackToNumber = SNAPSHOTS[0].number; + fireEvent.click(getAllByText(container, "Rollback")[0]); + expect(mockAxios.put).toBeCalledWith( + `/reforis/snapshots/api/snapshots/${rollbackToNumber}/rollback`, undefined, expect.anything(), + ); + mockAxios.mockResponse({ data: {} }); + + act(() => webSockets.dispatch( + { module: "schnapps", action: "rollback", data: {} }, + )); + + const newDescription = `Rollback to ${rollbackToNumber}`; + expect(mockAxios.get).toHaveBeenNthCalledWith(2, "/reforis/snapshots/api/snapshots", expect.anything()); + mockAxios.mockResponse({ data: [...SNAPSHOTS, creteSnapshot(3, newDescription)] }); + // New snapshot should appear + await wait(() => getByText(container, newDescription)); + }); + + it("should handle error on rollback", async () => { + // Delete device + fireEvent.click(getAllByText(container, "Rollback")[0]); + // Handle error + const errorMessage = "API didn't handle this well"; + mockJSONError(errorMessage); + await wait(() => { + expect(mockSetAlert).toHaveBeenCalledWith(errorMessage); + }); + }); + + describe("create snapshot form", () => { + let descriptionInput; + let submitButton; + + beforeEach(async () => { + descriptionInput = getByLabelText(container, "Description"); + submitButton = getByText(container, "Save"); + }); + + it("should send request to create new snapshot", async () => { + // Prepare form + const description = "Discovery"; + expect(submitButton.disabled).toBe(true); + fireEvent.change(descriptionInput, { target: { value: description } }); + expect(submitButton.disabled).toBe(false); + + // Create new snapshot + fireEvent.click(submitButton); + expect(mockAxios.post).toBeCalledWith( + "/reforis/snapshots/api/snapshots", + { description }, + expect.anything(), + ); + }); + + it("should handle API error on creating snapshot", async () => { + // Request new snapshot + fireEvent.change(descriptionInput, { target: { value: "qwe" } }); + fireEvent.click(submitButton); + + // Handle error + const errorMessage = "API didn't handle this well"; + mockJSONError(errorMessage); + await wait(() => { + expect(mockSetAlert).toHaveBeenCalledWith(errorMessage); + }); + }); + + it("should validate new snapshot description", async () => { + fireEvent.change(descriptionInput, { target: { value: "" } }); + expect(getByText(container, "Description is required.")).toBeDefined(); + expect(submitButton.disabled).toBe(true); + }); + }); + }); +}); diff --git a/js/src/snapshots/__tests__/__snapshots__/Snapshots.test.js.snap b/js/src/snapshots/__tests__/__snapshots__/Snapshots.test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..7a3f545fb4dabb9d7264f7d65d2846de28813f47 --- /dev/null +++ b/js/src/snapshots/__tests__/__snapshots__/Snapshots.test.js.snap @@ -0,0 +1,258 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` should render spinner 1`] = ` +
+

+ Snapshots +

+

+ This is an addition to Schnapps command-line utility which can provide more + + advanced options + + . +

+
+
+ +
+
+
+`; + +exports[` should render table 1`] = ` +
+

+ Snapshots +

+

+ This is an addition to Schnapps command-line utility which can provide more + + advanced options + + . +

+
+
+

+ Create new snapshot +

+
+ +
+ +
+
+ Description is required. +
+
+
+ +
+
+
+

+ Available Snapshots +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Number + + Type + + Description + + Created at + + Size + + +
+ 1 + + single + + Whatever + + 2020-01-30T10:27:34Z + + 808 kB + + + + +
+ 2 + + rollback + + Something + + 2020-01-31T10:27:34Z + + 909 kB + + + + +
+
+
+`; diff --git a/js/src/snapshots/hooks.js b/js/src/snapshots/hooks.js new file mode 100644 index 0000000000000000000000000000000000000000..e2d15e470ae9aaafc0d6d2785652be8b072ca482 --- /dev/null +++ b/js/src/snapshots/hooks.js @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) + * + * This is free software, licensed under the GNU General Public License v3. + * See /LICENSE for more information. + */ + +import { useEffect, useCallback } from "react"; + +import { + useAlert, useWSForisModule, useAPIGet, useAPIPost, useAPIDelete, useAPIPut, API_STATE, +} from "foris"; + +import API_URLs from "API"; + +export function useGetSnapshots(setSnapshots) { + const [getSnapshotsResponse, getSnapshots] = useAPIGet(API_URLs.snapshots); + + // Initial data fetch + useEffect(() => { + getSnapshots(); + }, [getSnapshots]); + + // Update snapshots data + useEffect(() => { + if (getSnapshotsResponse.state === API_STATE.SUCCESS) { + setSnapshots(getSnapshotsResponse.data); + } + }, [getSnapshotsResponse, setSnapshots]); + + return [getSnapshotsResponse.state, getSnapshots]; +} + +export function useUpdateSnapshotsOnAdd(ws, getSnapshots) { + const [addNotification] = useWSForisModule(ws, "schnapps", "create"); + useEffect(() => { + if (!addNotification) { + return; + } + getSnapshots(); + }, [addNotification, getSnapshots]); +} + +export function useCreateSnapshot() { + const [setAlert] = useAlert(); + + // Handle API request + const [postSnapshotResponse, postSnapshot] = useAPIPost(`${API_URLs.snapshots}`); + useEffect(() => { + if (postSnapshotResponse.state === API_STATE.ERROR) { + setAlert(postSnapshotResponse.data); + } + }, [postSnapshotResponse, setAlert]); + + return [postSnapshotResponse.state, postSnapshot]; +} + +export function useDeleteSnapshot() { + const [setAlert] = useAlert(); + + // Handle API request + const [deleteSnapshotResponse, deleteSnapshot] = useAPIDelete(`${API_URLs.snapshots}`); + useEffect(() => { + if (deleteSnapshotResponse.state === API_STATE.ERROR) { + setAlert(deleteSnapshotResponse.data); + } + }, [deleteSnapshotResponse, setAlert]); + + return [deleteSnapshotResponse.state, deleteSnapshot]; +} + +export function useUpdateSnapshotsOnDelete(ws, setSnapshots) { + const [deleteNotification] = useWSForisModule(ws, "schnapps", "delete"); + + // Update devices data + const removeSnapshotFromTable = useCallback((number) => { + setSnapshots((previousDevices) => { + const snapshots = [...previousDevices]; + const deleteIndex = snapshots.findIndex( + (snapshot) => snapshot.number === number, + ); + if (deleteIndex !== -1) { + snapshots.splice(deleteIndex, 1); + } + return snapshots; + }); + }, [setSnapshots]); + + useEffect(() => { + if (!deleteNotification) { + return; + } + removeSnapshotFromTable(deleteNotification.number); + }, [removeSnapshotFromTable, deleteNotification]); +} + +export function useRollbackSnapshot() { + const [setAlert] = useAlert(); + + // Handle API request + const [putSnapshotResponse, putSnapshot] = useAPIPut(`${API_URLs.snapshots}`); + useEffect(() => { + if (putSnapshotResponse.state === API_STATE.ERROR) { + setAlert(putSnapshotResponse.data); + } + }, [putSnapshotResponse, setAlert]); + + function rollbackSnapshot(snapshotNumber) { + return putSnapshot({ suffix: `${snapshotNumber}/rollback` }); + } + + return [putSnapshotResponse.state, rollbackSnapshot]; +} + +export function useUpdateSnapshotsOnRollback(ws, getSnapshots) { + const [addNotification] = useWSForisModule(ws, "schnapps", "rollback"); + useEffect(() => { + if (!addNotification) { + return; + } + getSnapshots(); + }, [addNotification, getSnapshots]); +} diff --git a/js/webpack.config.js b/js/webpack.config.js index 81d1d86fa56eb1c337893a1f90c8468d4f55745d..62ca4e3c7f15a5d178532357dd3310d55d507086 100644 --- a/js/webpack.config.js +++ b/js/webpack.config.js @@ -14,7 +14,7 @@ module.exports = () => ({ // Build js app to ../reforis_static{python_module_name}/app.min.js // See https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils/blob/master/reforis_distutils/__init__.py#L11 filename: "app.min.js", - path: path.join(__dirname, "../reforis_static/reforis_schnapps/js/"), + path: path.join(__dirname, "../reforis_static/reforis_snapshots/js/"), }, resolve: { modules: [ diff --git a/reforis_schnapps/__init__.py b/reforis_schnapps/__init__.py deleted file mode 100644 index 6d4480a72e0bb4c01ef652792640a8fa7f808ce1..0000000000000000000000000000000000000000 --- a/reforis_schnapps/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. - -from pathlib import Path -from http import HTTPStatus - -from flask import Blueprint, current_app, jsonify, request -from flask_babel import gettext as _ - -from reforis.foris_controller_api.utils import log_error, validate_json, APIError - -# pylint: disable=invalid-name -blueprint = Blueprint( - 'Schnapps', - __name__, - url_prefix='/schnapps/api', -) - -BASE_DIR = Path(__file__).parent - -# pylint: disable=invalid-name -schnapps = { - 'blueprint': blueprint, - # Define {python_module_name}/js/app.min.js - # See https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils/blob/master/reforis_distutils/__init__.py#L11 - 'js_app_path': 'reforis_schnapps/js/app.min.js', - 'translations_path': BASE_DIR / 'translations', -} - - -@blueprint.route('/example', methods=['GET']) -def get_example(): - return jsonify(current_app.backend.perform('example_module', 'example_action')) - - -@blueprint.route('/example', methods=['POST']) -def post_example(): - validate_json(request.json, {'modules': list}) - - response = current_app.backend.perform('example_module', 'example_action', request.json) - if response.get('result') is not True: - raise APIError(_('Cannot create entity'), HTTPStatus.INTERNAL_SERVER_ERROR) - - return jsonify(response), HTTPStatus.CREATED diff --git a/reforis_snapshots/__init__.py b/reforis_snapshots/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8003c52084d7925670ba4b29fb5114df91a9c381 --- /dev/null +++ b/reforis_snapshots/__init__.py @@ -0,0 +1,64 @@ +# Copyright (C) 2020 CZ.NIC z.s.p.o. (http://www.nic.cz/) +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. + +from pathlib import Path +from http import HTTPStatus + +from flask import Blueprint, current_app, jsonify, request +from flask_babel import gettext as _ + +from reforis.foris_controller_api.utils import log_error, validate_json, APIError + +# pylint: disable=invalid-name +blueprint = Blueprint( + 'Snapshots', + __name__, + url_prefix='/snapshots/api', +) + +BASE_DIR = Path(__file__).parent + +# pylint: disable=invalid-name +snapshots = { + 'blueprint': blueprint, + # Define {python_module_name}/js/app.min.js + # See https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils/blob/master/reforis_distutils/__init__.py#L11 + 'js_app_path': 'reforis_snapshots/js/app.min.js', + 'translations_path': BASE_DIR / 'translations', +} + + +@blueprint.route('/snapshots', methods=['GET']) +def get_snapshots(): + return jsonify(current_app.backend.perform('schnapps', 'list')['snapshots']) + + +@blueprint.route('/snapshots', methods=['POST']) +def create_snapshot(): + validate_json(request.json, {'description': str}) + + response = current_app.backend.perform('schnapps', 'create', request.json) + if response.get('result') is not True: + raise APIError(_('Cannot create snapshot.'), HTTPStatus.INTERNAL_SERVER_ERROR) + + return jsonify(response), HTTPStatus.ACCEPTED + + +@blueprint.route('/snapshots/', methods=['DELETE']) +def delete_snapshot(snapshot_number): + response = current_app.backend.perform('schnapps', 'delete', {'number': snapshot_number}) + if response.get('result') is not True: + raise APIError(_('Cannot delete snapshot.'), HTTPStatus.INTERNAL_SERVER_ERROR) + + return '', HTTPStatus.NO_CONTENT + + +@blueprint.route('/snapshots//rollback', methods=['PUT']) +def rollback_to_snapshot(snapshot_number): + response = current_app.backend.perform('schnapps', 'rollback', {'number': snapshot_number}) + if response.get('result') is not True: + raise APIError(_('Cannot rollback to snapshot.'), HTTPStatus.INTERNAL_SERVER_ERROR) + + return '', HTTPStatus.NO_CONTENT diff --git a/reforis_schnapps/translations/.gitkeep b/reforis_snapshots/translations/.gitkeep similarity index 100% rename from reforis_schnapps/translations/.gitkeep rename to reforis_snapshots/translations/.gitkeep diff --git a/reforis_snapshots/translations/cs/LC_MESSAGES/messages.po b/reforis_snapshots/translations/cs/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..2249a44a3922b6aa776519bd8a7fb6a877ec8bc6 --- /dev/null +++ b/reforis_snapshots/translations/cs/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Czech translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: cs\n" +"Language-Team: cs \n" +"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/da/LC_MESSAGES/messages.po b/reforis_snapshots/translations/da/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..db7d47c3113393d84cca3ff2ea99cc91647e8105 --- /dev/null +++ b/reforis_snapshots/translations/da/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Danish translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: da\n" +"Language-Team: da \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/de/LC_MESSAGES/messages.po b/reforis_snapshots/translations/de/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..016222a098fd7ce2691fa63c62abac0a3989d692 --- /dev/null +++ b/reforis_snapshots/translations/de/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# German translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: de\n" +"Language-Team: de \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/el/LC_MESSAGES/messages.po b/reforis_snapshots/translations/el/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..96726bc227a53d1bfdb17c96869cdf1ab782a00c --- /dev/null +++ b/reforis_snapshots/translations/el/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Greek translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: el\n" +"Language-Team: el \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/en/LC_MESSAGES/messages.po b/reforis_snapshots/translations/en/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..a7228a0f11cd56a297a4a521bdc68f57531b0c4d --- /dev/null +++ b/reforis_snapshots/translations/en/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# English translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/fi/LC_MESSAGES/messages.po b/reforis_snapshots/translations/fi/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..e31a6438274f9e31ad92ad7b24ae3fe7e0dfad33 --- /dev/null +++ b/reforis_snapshots/translations/fi/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Finnish translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: fi\n" +"Language-Team: fi \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/fo/LC_MESSAGES/messages.po b/reforis_snapshots/translations/fo/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..832383f10d9382512448f384cb4b481876d9cfe9 --- /dev/null +++ b/reforis_snapshots/translations/fo/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Faroese translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: fo\n" +"Language-Team: fo \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/fr/LC_MESSAGES/messages.po b/reforis_snapshots/translations/fr/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..a62d2ac516e5ed1cca45d9814b17627264bf7573 --- /dev/null +++ b/reforis_snapshots/translations/fr/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# French translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: fr\n" +"Language-Team: fr \n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/hr/LC_MESSAGES/messages.po b/reforis_snapshots/translations/hr/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..331b63c9f891e2c326d93835959e341006ed217e --- /dev/null +++ b/reforis_snapshots/translations/hr/LC_MESSAGES/messages.po @@ -0,0 +1,85 @@ +# Croatian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: hr\n" +"Language-Team: hr \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/hu/LC_MESSAGES/messages.po b/reforis_snapshots/translations/hu/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..19a0e040da4774d41a25953b23a56bccce532cd4 --- /dev/null +++ b/reforis_snapshots/translations/hu/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Hungarian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: hu\n" +"Language-Team: hu \n" +"Plural-Forms: nplurals=1; plural=0\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/it/LC_MESSAGES/messages.po b/reforis_snapshots/translations/it/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..502ecc62264d8e14a4dd37e77aea585324474bcd --- /dev/null +++ b/reforis_snapshots/translations/it/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Italian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: it\n" +"Language-Team: it \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/ja/LC_MESSAGES/messages.po b/reforis_snapshots/translations/ja/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..3254ba56ab08ad43b0330a7a10cc93897e4b2eab --- /dev/null +++ b/reforis_snapshots/translations/ja/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Japanese translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: ja\n" +"Language-Team: ja \n" +"Plural-Forms: nplurals=1; plural=0\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/ko/LC_MESSAGES/messages.po b/reforis_snapshots/translations/ko/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..304ff57eecd6e81471855bc2567f932a42eb4dc0 --- /dev/null +++ b/reforis_snapshots/translations/ko/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Korean translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: ko\n" +"Language-Team: ko \n" +"Plural-Forms: nplurals=1; plural=0\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/lt/LC_MESSAGES/messages.po b/reforis_snapshots/translations/lt/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..a1bcba29f6374640da45c659869ae6c7738ecd90 --- /dev/null +++ b/reforis_snapshots/translations/lt/LC_MESSAGES/messages.po @@ -0,0 +1,85 @@ +# Lithuanian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: lt\n" +"Language-Team: lt \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"(n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/messages.pot b/reforis_snapshots/translations/messages.pot new file mode 100644 index 0000000000000000000000000000000000000000..6d04008d6b22a393c82990e4bf4a19998b43b234 --- /dev/null +++ b/reforis_snapshots/translations/messages.pot @@ -0,0 +1,83 @@ +# Translations template for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/nb/LC_MESSAGES/messages.po b/reforis_snapshots/translations/nb/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..1f082a9f0b93e755375b0f974c460d215afb2640 --- /dev/null +++ b/reforis_snapshots/translations/nb/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Norwegian Bokmål translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: nb\n" +"Language-Team: nb \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/nb_NO/LC_MESSAGES/messages.po b/reforis_snapshots/translations/nb_NO/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..3f81eea3a71f78f2af4be8aa26036a7f18e76d19 --- /dev/null +++ b/reforis_snapshots/translations/nb_NO/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Norwegian Bokmål (Norway) translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: nb_NO\n" +"Language-Team: nb_NO \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/nl/LC_MESSAGES/messages.po b/reforis_snapshots/translations/nl/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..a52e1b90af9e01eb1f1adbad5ffeb19a47258b69 --- /dev/null +++ b/reforis_snapshots/translations/nl/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Dutch translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: nl\n" +"Language-Team: nl \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/pl/LC_MESSAGES/messages.po b/reforis_snapshots/translations/pl/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..3f892002cafabfdc89c21301fd93cbf6db918e84 --- /dev/null +++ b/reforis_snapshots/translations/pl/LC_MESSAGES/messages.po @@ -0,0 +1,85 @@ +# Polish translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: pl\n" +"Language-Team: pl \n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && " +"(n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/ro/LC_MESSAGES/messages.po b/reforis_snapshots/translations/ro/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..b341645687260074023c0e5e8c0bca2336cc6845 --- /dev/null +++ b/reforis_snapshots/translations/ro/LC_MESSAGES/messages.po @@ -0,0 +1,85 @@ +# Romanian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: ro\n" +"Language-Team: ro \n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100" +" < 20)) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/ru/LC_MESSAGES/messages.po b/reforis_snapshots/translations/ru/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..86899ecb05c469f273fefd74ac3f06ef6f30d433 --- /dev/null +++ b/reforis_snapshots/translations/ru/LC_MESSAGES/messages.po @@ -0,0 +1,85 @@ +# Russian translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: ru\n" +"Language-Team: ru \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/sk/LC_MESSAGES/messages.po b/reforis_snapshots/translations/sk/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..5fb64ecd469a6670d232a9996389799e854d595b --- /dev/null +++ b/reforis_snapshots/translations/sk/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Slovak translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: sk\n" +"Language-Team: sk \n" +"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_snapshots/translations/sv/LC_MESSAGES/messages.po b/reforis_snapshots/translations/sv/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..8471f4048b73f4d4fc353e7a7959d753f1f703d1 --- /dev/null +++ b/reforis_snapshots/translations/sv/LC_MESSAGES/messages.po @@ -0,0 +1,84 @@ +# Swedish translations for PROJECT. +# Copyright (C) 2020 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2020. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2020-01-31 14:58+0100\n" +"PO-Revision-Date: 2020-01-31 14:58+0100\n" +"Last-Translator: FULL NAME \n" +"Language: sv\n" +"Language-Team: sv \n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.8.0\n" + +#: js/src/app.js:11 js/src/snapshots/Snapshots.js:60 +msgid "Snapshots" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:39 +msgid "Create new snapshot" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:41 +#: js/src/snapshots/SnapshotsTable.js:36 +msgid "Description" +msgstr "" + +#: js/src/snapshots/CreateSnapshotForm.js:60 +msgid "Description is required." +msgstr "" + +#: js/src/snapshots/Snapshots.js:48 +msgid "Available Snapshots" +msgstr "" + +#: js/src/snapshots/Snapshots.js:61 +msgid "" +"This is an addition to Schnapps command-line utility which can provide " +"more advanced options." +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:34 +msgid "Number" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:35 +msgid "Type" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:37 +msgid "Created at" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:38 +msgid "Size" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:39 js/src/snapshots/SnapshotsTable.js:76 +msgid "Rollback" +msgstr "" + +#: js/src/snapshots/SnapshotsTable.js:40 js/src/snapshots/SnapshotsTable.js:82 +msgid "Delete" +msgstr "" + +#: reforis_snapshots/__init__.py:44 +msgid "Cannot create snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:53 +msgid "Cannot delete snapshot." +msgstr "" + +#: reforis_snapshots/__init__.py:62 +msgid "Cannot rollback to snapshot." +msgstr "" + diff --git a/reforis_static/reforis_schnapps/.gitkeep b/reforis_static/reforis_snapshots/.gitkeep similarity index 100% rename from reforis_static/reforis_schnapps/.gitkeep rename to reforis_static/reforis_snapshots/.gitkeep diff --git a/setup.py b/setup.py index 30812379648b04680e5792fc01da4b74d40749be..90169ba13265ad846b46fcca4bab6088084c45cb 100644 --- a/setup.py +++ b/setup.py @@ -11,12 +11,12 @@ import pathlib import setuptools from setuptools.command.build_py import build_py -NAME = 'reforis_schnapps' +NAME = 'reforis_snapshots' BASE_DIR = pathlib.Path(__file__).absolute().parent -class SchnappsBuild(build_py): +class SnapshotsBuild(build_py): def run(self): # build package build_py.run(self) @@ -63,7 +63,7 @@ setuptools.setup( 'git+https://gitlab.labs.nic.cz/turris/reforis/reforis-distutils.git#egg=reforis-distutils', ], entry_points={ - 'foris.plugins': f'{NAME} = {NAME}:schnapps' + 'foris.plugins': f'{NAME} = {NAME}:snapshots' }, classifiers=[ 'Framework :: Flask', @@ -76,7 +76,7 @@ setuptools.setup( 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', ], cmdclass={ - 'build_py': SchnappsBuild, + 'build_py': SnapshotsBuild, }, zip_safe=False, ) diff --git a/tests/test_api.py b/tests/test_api.py index b1a15f95c752c4eb5a8f9e8e93315de1456c6c93..2884e7487f7395e28513e9be3f872b120b05fee2 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -7,22 +7,74 @@ from http import HTTPStatus from reforis.test_utils import mock_backend_response -@mock_backend_response({'example_module': {'example_action': {'key': 'value'}}}) -def test_get_example(client): - response = client.get('/schnapps/api/example') +SNAPSHOTS_URL = '/snapshots/api/snapshots' +SNAPSHOT_URL = f"{SNAPSHOTS_URL}/1234" +ROLLBACK_SNAPSHOT_URL = f"{SNAPSHOTS_URL}/1234/rollback" + + +@mock_backend_response({'schnapps': {'list': {'snapshots': ['foo', 'bar']}}}) +def test_get_snapshots(client): + response = client.get(SNAPSHOTS_URL) assert response.status_code == HTTPStatus.OK - assert response.json['key'] == 'value' + assert response.json == ['foo', 'bar'] + +@mock_backend_response({'schnapps': {'create': {'result': True}}}) +def test_post_snapshot(client): + response = client.post( + SNAPSHOTS_URL, json={'description': 'Lorem ipsum dolor sit amet.'}, + ) + assert response.status_code == HTTPStatus.ACCEPTED + assert response.json == {'result': True} -@mock_backend_response({'example_module': {'example_action': {'result': True}}}) -def test_post_example_invalid_json(client): - response = client.post('/schnapps/api/example', json=False) + +def test_post_snapshot_missing_description(client): + response = client.post( + SNAPSHOTS_URL, json={'foo': 'Lorem ipsum dolor sit amet.'}, + ) assert response.status_code == HTTPStatus.BAD_REQUEST - assert response.json == 'Invalid JSON' + assert response.json == {'description': 'Missing data for required field.'} + + +@mock_backend_response({'schnapps': {'create': {'result': True}}}) +def test_post_snapshot_invalid_json(client): + response = client.post( + SNAPSHOTS_URL, json={'foo': 'Lorem ipsum dolor sit amet.'}, + ) + assert response.status_code == HTTPStatus.BAD_REQUEST + assert response.json == {'description': 'Missing data for required field.'} + + +@mock_backend_response({'schnapps': {'create': {'result': False}}}) +def test_post_snapshot_backend_error(client): + response = client.post( + SNAPSHOTS_URL, json={'description': 'Lorem ipsum dolor sit amet.'}, + ) + assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR + assert response.json == 'Cannot create snapshot.' + + +@mock_backend_response({'schnapps': {'delete': {'result': True}}}) +def test_delete_device(client): + response = client.delete(SNAPSHOT_URL) + assert response.status_code == HTTPStatus.NO_CONTENT + + +@mock_backend_response({'schnapps': {'delete': {'result': False}}}) +def test_delete_device_backend_error(client): + response = client.delete(SNAPSHOT_URL) + assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR + assert response.json == 'Cannot delete snapshot.' + + +@mock_backend_response({'schnapps': {'rollback': {'result': True}}}) +def test_rollback_snapshot(client): + response = client.put(ROLLBACK_SNAPSHOT_URL) + assert response.status_code == HTTPStatus.NO_CONTENT -@mock_backend_response({'example_module': {'example_action': {'key': 'value'}}}) -def test_post_example_backend_error(client): - response = client.post('/schnapps/api/example', json={'modules': []}) +@mock_backend_response({'schnapps': {'rollback': {'result': False}}}) +def test_rollback_snapshot_backend_error(client): + response = client.put(ROLLBACK_SNAPSHOT_URL) assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR - assert response.json == 'Cannot create entity' + assert response.json == 'Cannot rollback to snapshot.'