From 0763ae94406658aa96e01c884189cf0edf479557 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 08:29:05 +0100 Subject: [PATCH 01/10] Add optional heades for api client push and put --- scm-ui/ui-components/src/apiclient.ts | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/scm-ui/ui-components/src/apiclient.ts b/scm-ui/ui-components/src/apiclient.ts index babb0b64d7..3fb03b067f 100644 --- a/scm-ui/ui-components/src/apiclient.ts +++ b/scm-ui/ui-components/src/apiclient.ts @@ -80,23 +80,24 @@ class ApiClient { return fetch(createUrl(url), applyFetchOptions({})).then(handleFailure); } - post(url: string, payload?: any, contentType = "application/json") { - return this.httpRequestWithJSONBody("POST", url, contentType, payload); + post(url: string, payload?: any, contentType = "application/json", additionalHeaders = new Headers()) { + return this.httpRequestWithJSONBody("POST", url, contentType, additionalHeaders, payload); } - postBinary(url: string, fileAppender: (p: FormData) => void) { + postBinary(url: string, fileAppender: (p: FormData) => void, additionalHeaders = new Headers()) { const formData = new FormData(); fileAppender(formData); const options: RequestInit = { method: "POST", - body: formData + body: formData, + headers: additionalHeaders }; return this.httpRequestWithBinaryBody(options, url); } - put(url: string, payload: any, contentType = "application/json") { - return this.httpRequestWithJSONBody("PUT", url, contentType, payload); + put(url: string, payload: any, contentType = "application/json", additionalHeaders = new Headers()) { + return this.httpRequestWithJSONBody("PUT", url, contentType, additionalHeaders, payload); } head(url: string) { @@ -115,9 +116,16 @@ class ApiClient { return fetch(createUrl(url), options).then(handleFailure); } - httpRequestWithJSONBody(method: string, url: string, contentType: string, payload?: any): Promise { + httpRequestWithJSONBody( + method: string, + url: string, + contentType: string, + additionalHeaders: Headers, + payload?: any + ): Promise { const options: RequestInit = { - method: method + method: method, + headers: additionalHeaders }; if (payload) { options.body = JSON.stringify(payload); From 20659bc32e23950e74f2d7d3c1260d3710044cc3 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 08:59:57 +0100 Subject: [PATCH 02/10] Add post and put with text --- scm-ui/ui-components/src/apiclient.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scm-ui/ui-components/src/apiclient.ts b/scm-ui/ui-components/src/apiclient.ts index 3fb03b067f..4f2a8a735e 100644 --- a/scm-ui/ui-components/src/apiclient.ts +++ b/scm-ui/ui-components/src/apiclient.ts @@ -84,6 +84,14 @@ class ApiClient { return this.httpRequestWithJSONBody("POST", url, contentType, additionalHeaders, payload); } + postText(url: string, payload: string, additionalHeaders = new Headers()) { + return this.httpRequestWithTextBody("POST", url, additionalHeaders, payload); + } + + putText(url: string, payload: string, additionalHeaders = new Headers()) { + return this.httpRequestWithTextBody("PUT", url, additionalHeaders, payload); + } + postBinary(url: string, fileAppender: (p: FormData) => void, additionalHeaders = new Headers()) { const formData = new FormData(); fileAppender(formData); @@ -133,6 +141,15 @@ class ApiClient { return this.httpRequestWithBinaryBody(options, url, contentType); } + httpRequestWithTextBody(method: string, url: string, additionalHeaders: Headers, payload: string) { + const options: RequestInit = { + method: method, + headers: additionalHeaders + }; + options.body = payload; + return this.httpRequestWithBinaryBody(options, url, "text/plain"); + } + httpRequestWithBinaryBody(options: RequestInit, url: string, contentType?: string) { options = applyFetchOptions(options); if (contentType) { From a2474896cc38c7858f9a4dcf036c7dba3a4ef8ed Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 10:44:11 +0100 Subject: [PATCH 03/10] Fix types --- scm-ui/ui-components/src/apiclient.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scm-ui/ui-components/src/apiclient.ts b/scm-ui/ui-components/src/apiclient.ts index 4f2a8a735e..4c1bad8ac1 100644 --- a/scm-ui/ui-components/src/apiclient.ts +++ b/scm-ui/ui-components/src/apiclient.ts @@ -80,19 +80,19 @@ class ApiClient { return fetch(createUrl(url), applyFetchOptions({})).then(handleFailure); } - post(url: string, payload?: any, contentType = "application/json", additionalHeaders = new Headers()) { + post(url: string, payload?: any, contentType = "application/json", additionalHeaders: Record = {}) { return this.httpRequestWithJSONBody("POST", url, contentType, additionalHeaders, payload); } - postText(url: string, payload: string, additionalHeaders = new Headers()) { + postText(url: string, payload: string, additionalHeaders: Record = {}) { return this.httpRequestWithTextBody("POST", url, additionalHeaders, payload); } - putText(url: string, payload: string, additionalHeaders = new Headers()) { + putText(url: string, payload: string, additionalHeaders: Record = {}) { return this.httpRequestWithTextBody("PUT", url, additionalHeaders, payload); } - postBinary(url: string, fileAppender: (p: FormData) => void, additionalHeaders = new Headers()) { + postBinary(url: string, fileAppender: (p: FormData) => void, additionalHeaders: Record = {}) { const formData = new FormData(); fileAppender(formData); @@ -104,7 +104,7 @@ class ApiClient { return this.httpRequestWithBinaryBody(options, url); } - put(url: string, payload: any, contentType = "application/json", additionalHeaders = new Headers()) { + put(url: string, payload: any, contentType = "application/json", additionalHeaders: Record = {}) { return this.httpRequestWithJSONBody("PUT", url, contentType, additionalHeaders, payload); } @@ -128,7 +128,7 @@ class ApiClient { method: string, url: string, contentType: string, - additionalHeaders: Headers, + additionalHeaders: Record, payload?: any ): Promise { const options: RequestInit = { @@ -141,7 +141,12 @@ class ApiClient { return this.httpRequestWithBinaryBody(options, url, contentType); } - httpRequestWithTextBody(method: string, url: string, additionalHeaders: Headers, payload: string) { + httpRequestWithTextBody( + method: string, + url: string, + additionalHeaders: Record = {}, + payload: string + ) { const options: RequestInit = { method: method, headers: additionalHeaders @@ -156,7 +161,7 @@ class ApiClient { if (!options.headers) { options.headers = new Headers(); } - // @ts-ignore + // @ts-ignore We are sure that here we only get headers of type Record options.headers["Content-Type"] = contentType; } From cf17e07cea26b852d2a09d0390e1f20a569729cc Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 11:12:22 +0100 Subject: [PATCH 04/10] Do not overwrite existing headers in applyFetchOptions --- scm-ui/ui-components/src/apiclient.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/scm-ui/ui-components/src/apiclient.ts b/scm-ui/ui-components/src/apiclient.ts index 4c1bad8ac1..473bf3b925 100644 --- a/scm-ui/ui-components/src/apiclient.ts +++ b/scm-ui/ui-components/src/apiclient.ts @@ -27,13 +27,17 @@ const extractXsrfToken = () => { }; const applyFetchOptions: (p: RequestInit) => RequestInit = o => { - const headers: { [key: string]: string } = { - Cache: "no-cache", - // identify the request as ajax request - "X-Requested-With": "XMLHttpRequest", - // identify the web interface - "X-SCM-Client": "WUI" - }; + if (!o.headers) { + o.headers = {}; + } + + // @ts-ignore We are sure that here we only get headers of type Record + const headers: Record = o.headers; + headers["Cache"] = "no-cache"; + // identify the request as ajax request + headers["X-Requested-With"] = "XMLHttpRequest"; + // identify the web interface + headers["X-SCM-Client"] = "WUI"; const xsrf = extractXsrfToken(); if (xsrf) { @@ -159,7 +163,7 @@ class ApiClient { options = applyFetchOptions(options); if (contentType) { if (!options.headers) { - options.headers = new Headers(); + options.headers = {}; } // @ts-ignore We are sure that here we only get headers of type Record options.headers["Content-Type"] = contentType; From 4f43bce90eef4986ecc3a74ed2fb9e092df1eccf Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 11:14:58 +0100 Subject: [PATCH 05/10] Reduce visibility of misleading install function This install function might be mistaken to really install this plugin, whereas it only sets its internal status and does not really do smth. --- scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java b/scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java index db8d96ca15..c05e970e50 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java +++ b/scm-core/src/main/java/sonia/scm/plugin/AvailablePlugin.java @@ -25,7 +25,7 @@ public class AvailablePlugin implements Plugin { return pending; } - public AvailablePlugin install() { + AvailablePlugin install() { Preconditions.checkState(!pending, "installation is already pending"); return new AvailablePlugin(pluginDescriptor, true); } From 5de7d5df94c41b2db572c048f97e1147c4d26674 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 20 Nov 2019 13:40:40 +0100 Subject: [PATCH 06/10] show notification if diff is empty --- scm-ui/ui-components/src/repos/Diff.tsx | 23 +++++++++++-------- .../ui-components/src/repos/LoadingDiff.tsx | 1 + .../main/resources/locales/de/plugins.json | 3 ++- .../main/resources/locales/en/plugins.json | 9 ++++---- .../main/resources/locales/es/plugins.json | 3 ++- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/scm-ui/ui-components/src/repos/Diff.tsx b/scm-ui/ui-components/src/repos/Diff.tsx index cb4ad30f9f..b34c5ae68e 100644 --- a/scm-ui/ui-components/src/repos/Diff.tsx +++ b/scm-ui/ui-components/src/repos/Diff.tsx @@ -1,11 +1,14 @@ import React from "react"; import DiffFile from "./DiffFile"; import { DiffObjectProps, File } from "./DiffTypes"; +import Notification from "../Notification"; +import { WithTranslation, withTranslation } from "react-i18next"; -type Props = DiffObjectProps & { - diff: File[]; - defaultCollapse?: boolean; -}; +type Props = WithTranslation & + DiffObjectProps & { + diff: File[]; + defaultCollapse?: boolean; + }; class Diff extends React.Component { static defaultProps: Partial = { @@ -13,15 +16,17 @@ class Diff extends React.Component { }; render() { - const { diff, ...fileProps } = this.props; + const { diff, t, ...fileProps } = this.props; return ( <> - {diff.map((file, index) => ( - - ))} + {diff.length === 0 ? ( + {t("noDiffFound")} + ) : ( + diff.map((file, index) => ) + )} ); } } -export default Diff; +export default withTranslation("plugins")(Diff); diff --git a/scm-ui/ui-components/src/repos/LoadingDiff.tsx b/scm-ui/ui-components/src/repos/LoadingDiff.tsx index 1cfbc00b14..45b62f9b35 100644 --- a/scm-ui/ui-components/src/repos/LoadingDiff.tsx +++ b/scm-ui/ui-components/src/repos/LoadingDiff.tsx @@ -43,6 +43,7 @@ class LoadingDiff extends React.Component { fetchDiff = () => { const { url } = this.props; + this.setState({loading: true}); apiClient .get(url) .then(response => response.text()) diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json index 3cb6522922..a2cd4530dd 100644 --- a/scm-webapp/src/main/resources/locales/de/plugins.json +++ b/scm-webapp/src/main/resources/locales/de/plugins.json @@ -202,5 +202,6 @@ "CustomNamespaceStrategy": "Benutzerdefiniert", "CurrentYearNamespaceStrategy": "Aktuelles Jahr", "RepositoryTypeNamespaceStrategy": "Repository Typ" - } + }, + "noDiffFound": "Kein Diff zwischen den ausgewählten Branches gefunden." } diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json index 0be1c1f803..271d7e8c20 100644 --- a/scm-webapp/src/main/resources/locales/en/plugins.json +++ b/scm-webapp/src/main/resources/locales/en/plugins.json @@ -198,9 +198,10 @@ } }, "namespaceStrategies": { - "UsernameNamespaceStrategy": "Username", - "CustomNamespaceStrategy": "Custom", - "CurrentYearNamespaceStrategy": "Current year", + "UsernameNamespaceStrategy": "Username", + "CustomNamespaceStrategy": "Custom", + "CurrentYearNamespaceStrategy": "Current year", "RepositoryTypeNamespaceStrategy": "Repository type" - } + }, + "noDiffFound": "No Diff between the selected branches found." } diff --git a/scm-webapp/src/main/resources/locales/es/plugins.json b/scm-webapp/src/main/resources/locales/es/plugins.json index e56973946b..042a6ebc63 100644 --- a/scm-webapp/src/main/resources/locales/es/plugins.json +++ b/scm-webapp/src/main/resources/locales/es/plugins.json @@ -182,5 +182,6 @@ "CustomNamespaceStrategy": "Personalizar", "CurrentYearNamespaceStrategy": "Año actual", "RepositoryTypeNamespaceStrategy": "Tipo de repositorio" - } + }, + "noDiffFound": "No se encontraron diferencias entre las ramas seleccionadas." } From d962265d8dc0423c591f428948bb91e8b467da8a Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 14:47:47 +0100 Subject: [PATCH 07/10] Correct order of exports Without this `yarn run serve` will run on port 8080 serving the scss --- scm-ui/ui-scripts/src/webpack.config.js | 70 ++++++++++++------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/scm-ui/ui-scripts/src/webpack.config.js b/scm-ui/ui-scripts/src/webpack.config.js index 639872c6b8..2dd5b4c470 100644 --- a/scm-ui/ui-scripts/src/webpack.config.js +++ b/scm-ui/ui-scripts/src/webpack.config.js @@ -7,41 +7,6 @@ const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const root = path.resolve(process.cwd(), "scm-ui"); module.exports = [ - { - context: root, - entry: "./ui-styles/src/scm.scss", - module: { - rules: [ - { - test: /\.(css|scss|sass)$/i, - use: [ - { - loader: MiniCssExtractPlugin.loader - }, - "css-loader", - "sass-loader" - ] - }, - { - test: /\.(png|svg|jpg|gif|woff2?|eot|ttf)$/, - use: ["file-loader"] - } - ] - }, - plugins: [ - new MiniCssExtractPlugin({ - filename: "ui-styles.css", - ignoreOrder: false - }) - ], - optimization: { - minimizer: [new OptimizeCSSAssetsPlugin({})] - }, - output: { - path: path.join(root, "target", "assets"), - filename: "ui-styles.bundle.js" - } - }, { context: root, entry: { @@ -142,6 +107,41 @@ module.exports = [ } } }, + { + context: root, + entry: "./ui-styles/src/scm.scss", + module: { + rules: [ + { + test: /\.(css|scss|sass)$/i, + use: [ + { + loader: MiniCssExtractPlugin.loader + }, + "css-loader", + "sass-loader" + ] + }, + { + test: /\.(png|svg|jpg|gif|woff2?|eot|ttf)$/, + use: ["file-loader"] + } + ] + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: "ui-styles.css", + ignoreOrder: false + }) + ], + optimization: { + minimizer: [new OptimizeCSSAssetsPlugin({})] + }, + output: { + path: path.join(root, "target", "assets"), + filename: "ui-styles.bundle.js" + } + }, { context: path.resolve(root), entry: { From ba8c2f4ce734122132ed581daa9412e3d40de012 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 20 Nov 2019 15:23:10 +0000 Subject: [PATCH 08/10] Close branch feature/add_optional_headers_in_apiclient From 793233146b549ac92849dedd5abdeb1572f461fa Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 15:37:42 +0000 Subject: [PATCH 09/10] Close branch bugfix/new_pr_undefined_on_diff From 67c21b18e32f456d269c939526e0ddff33d93275 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 20 Nov 2019 16:50:18 +0100 Subject: [PATCH 10/10] Move translation key to correct file --- scm-ui/ui-components/src/repos/Diff.tsx | 4 ++-- scm-ui/ui-webapp/public/locales/de/repos.json | 3 ++- scm-ui/ui-webapp/public/locales/en/repos.json | 3 ++- scm-ui/ui-webapp/public/locales/es/repos.json | 3 ++- scm-webapp/src/main/resources/locales/de/plugins.json | 3 +-- scm-webapp/src/main/resources/locales/en/plugins.json | 3 +-- scm-webapp/src/main/resources/locales/es/plugins.json | 3 +-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/scm-ui/ui-components/src/repos/Diff.tsx b/scm-ui/ui-components/src/repos/Diff.tsx index b34c5ae68e..d7123903a3 100644 --- a/scm-ui/ui-components/src/repos/Diff.tsx +++ b/scm-ui/ui-components/src/repos/Diff.tsx @@ -20,7 +20,7 @@ class Diff extends React.Component { return ( <> {diff.length === 0 ? ( - {t("noDiffFound")} + {t("diff.noDiffFound")} ) : ( diff.map((file, index) => ) )} @@ -29,4 +29,4 @@ class Diff extends React.Component { } } -export default withTranslation("plugins")(Diff); +export default withTranslation("repos")(Diff); diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json index e156cc903e..4dfba695ab 100644 --- a/scm-ui/ui-webapp/public/locales/de/repos.json +++ b/scm-ui/ui-webapp/public/locales/de/repos.json @@ -177,7 +177,8 @@ }, "diff": { "sideBySide": "Zweispaltig", - "combined": "Kombiniert" + "combined": "Kombiniert", + "noDiffFound": "Kein Diff zwischen den ausgewählten Branches gefunden." }, "fileUpload": { "clickHere": "Klicken Sie hier um Ihre Datei hochzuladen.", diff --git a/scm-ui/ui-webapp/public/locales/en/repos.json b/scm-ui/ui-webapp/public/locales/en/repos.json index 0466bab77f..e2ccf8326e 100644 --- a/scm-ui/ui-webapp/public/locales/en/repos.json +++ b/scm-ui/ui-webapp/public/locales/en/repos.json @@ -184,7 +184,8 @@ "copy": "copied" }, "sideBySide": "side-by-side", - "combined": "combined" + "combined": "combined", + "noDiffFound": "No Diff between the selected branches found." }, "fileUpload": { "clickHere": "Click here to select your file", diff --git a/scm-ui/ui-webapp/public/locales/es/repos.json b/scm-ui/ui-webapp/public/locales/es/repos.json index ef9bd2badc..c3bf57c630 100644 --- a/scm-ui/ui-webapp/public/locales/es/repos.json +++ b/scm-ui/ui-webapp/public/locales/es/repos.json @@ -184,7 +184,8 @@ "copy": "copiado" }, "sideBySide": "dos columnas", - "combined": "combinado" + "combined": "combinado", + "noDiffFound": "No se encontraron diferencias entre las ramas seleccionadas." }, "fileUpload": { "clickHere": "Haga click aquí para seleccionar su fichero", diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json index a2cd4530dd..3cb6522922 100644 --- a/scm-webapp/src/main/resources/locales/de/plugins.json +++ b/scm-webapp/src/main/resources/locales/de/plugins.json @@ -202,6 +202,5 @@ "CustomNamespaceStrategy": "Benutzerdefiniert", "CurrentYearNamespaceStrategy": "Aktuelles Jahr", "RepositoryTypeNamespaceStrategy": "Repository Typ" - }, - "noDiffFound": "Kein Diff zwischen den ausgewählten Branches gefunden." + } } diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json index 271d7e8c20..83b463b8b6 100644 --- a/scm-webapp/src/main/resources/locales/en/plugins.json +++ b/scm-webapp/src/main/resources/locales/en/plugins.json @@ -202,6 +202,5 @@ "CustomNamespaceStrategy": "Custom", "CurrentYearNamespaceStrategy": "Current year", "RepositoryTypeNamespaceStrategy": "Repository type" - }, - "noDiffFound": "No Diff between the selected branches found." + } } diff --git a/scm-webapp/src/main/resources/locales/es/plugins.json b/scm-webapp/src/main/resources/locales/es/plugins.json index 042a6ebc63..e56973946b 100644 --- a/scm-webapp/src/main/resources/locales/es/plugins.json +++ b/scm-webapp/src/main/resources/locales/es/plugins.json @@ -182,6 +182,5 @@ "CustomNamespaceStrategy": "Personalizar", "CurrentYearNamespaceStrategy": "Año actual", "RepositoryTypeNamespaceStrategy": "Tipo de repositorio" - }, - "noDiffFound": "No se encontraron diferencias entre las ramas seleccionadas." + } }