Merge branch 'yay-digital-feature/host-overrides' into feature/host-overrides
This commit is contained in:
@@ -38,5 +38,16 @@
|
|||||||
.text-danger {
|
.text-danger {
|
||||||
color: $red;
|
color: $red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.moco-bx-override-hosts {
|
||||||
|
&-container {
|
||||||
|
padding: 0 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,32 +3,58 @@ import { observable } from "mobx"
|
|||||||
import { observer } from "mobx-react"
|
import { observer } from "mobx-react"
|
||||||
import { isChrome, getSettings, setStorage } from "utils/browser"
|
import { isChrome, getSettings, setStorage } from "utils/browser"
|
||||||
import ApiClient from "api/Client"
|
import ApiClient from "api/Client"
|
||||||
|
import remoteServices from "../remoteServices"
|
||||||
|
import { pipe, prop, map, sortedUniqBy, filter } from "lodash/fp"
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Options extends Component {
|
class Options extends Component {
|
||||||
@observable subdomain = ""
|
@observable subdomain = ""
|
||||||
@observable apiKey = ""
|
@observable apiKey = ""
|
||||||
|
@observable hostOverrides = {}
|
||||||
@observable errorMessage = null
|
@observable errorMessage = null
|
||||||
@observable isSuccess = false
|
@observable isSuccess = false
|
||||||
|
@observable servicesHostOverrideList = []
|
||||||
|
@observable showHostOverrideOptions = false
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
getSettings(false).then(({ subdomain, apiKey }) => {
|
this.servicesHostOverrideList = pipe(
|
||||||
this.subdomain = subdomain || ""
|
filter(prop("allowHostOverride")),
|
||||||
this.apiKey = apiKey || ""
|
map((remoteService) => ({
|
||||||
|
name: remoteService.name,
|
||||||
|
host: remoteService.host,
|
||||||
|
})),
|
||||||
|
sortedUniqBy("name"),
|
||||||
|
)(remoteServices)
|
||||||
|
|
||||||
|
getSettings(false).then((storeData) => {
|
||||||
|
this.subdomain = storeData.subdomain || ""
|
||||||
|
this.apiKey = storeData.apiKey || ""
|
||||||
|
this.hostOverrides = storeData.hostOverrides || {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange = event => {
|
onChange = (event) => {
|
||||||
this[event.target.name] = event.target.value.trim()
|
this[event.target.name] = event.target.value.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit = _event => {
|
onChangeHostOverrides = (event) => {
|
||||||
|
// ensure to remove path (and trailing slash) from URL, as this can cause problems otherwise
|
||||||
|
this.hostOverrides[event.target.name] = this.removePathFromUrl(event.target.value.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleHostOverrideOptions = () => {
|
||||||
|
this.showHostOverrideOptions = !this.showHostOverrideOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit = (_event) => {
|
||||||
this.isSuccess = false
|
this.isSuccess = false
|
||||||
this.errorMessage = null
|
this.errorMessage = null
|
||||||
|
|
||||||
setStorage({
|
setStorage({
|
||||||
subdomain: this.subdomain,
|
subdomain: this.subdomain,
|
||||||
apiKey: this.apiKey,
|
apiKey: this.apiKey,
|
||||||
settingTimeTrackingHHMM: false,
|
settingTimeTrackingHHMM: false,
|
||||||
|
hostOverrides: this.hostOverrides,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
const { version } = chrome.runtime.getManifest()
|
const { version } = chrome.runtime.getManifest()
|
||||||
const apiClient = new ApiClient({
|
const apiClient = new ApiClient({
|
||||||
@@ -45,13 +71,17 @@ class Options extends Component {
|
|||||||
this.isSuccess = true
|
this.isSuccess = true
|
||||||
this.closeWindow()
|
this.closeWindow()
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
this.errorMessage = error.response?.data?.message || "Anmeldung fehlgeschlagen"
|
this.errorMessage = error.response?.data?.message || "Anmeldung fehlgeschlagen"
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInputKeyDown = event => {
|
removePathFromUrl = (url) => {
|
||||||
|
return url.replace(/(\.[a-z]+)\/.*$/, "$1")
|
||||||
|
}
|
||||||
|
|
||||||
|
handleInputKeyDown = (event) => {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
this.handleSubmit()
|
this.handleSubmit()
|
||||||
}
|
}
|
||||||
@@ -93,6 +123,27 @@ class Options extends Component {
|
|||||||
Den API-Schlüssel findest du in deinem Profil unter "Integrationen".
|
Den API-Schlüssel findest du in deinem Profil unter "Integrationen".
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<hr />
|
||||||
|
{!this.showHostOverrideOptions && (
|
||||||
|
<div className="moco-bx-override-hosts-container">
|
||||||
|
<span className="moco-bx-override-hosts-btn" onClick={this.toggleHostOverrideOptions}>Zeige Optionen zum Überschreiben<br />der Service Hosts</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{this.showHostOverrideOptions &&
|
||||||
|
this.servicesHostOverrideList.map((remoteService) => (
|
||||||
|
<div className="form-group" key={remoteService.name}>
|
||||||
|
<label>Host URL: {remoteService.name}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name={remoteService.name}
|
||||||
|
value={this.hostOverrides[remoteService.name] || ""}
|
||||||
|
placeholder={remoteService.host}
|
||||||
|
onKeyDown={this.handleInputKeyDown}
|
||||||
|
onChange={this.onChangeHostOverrides}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<hr />
|
||||||
<button className="moco-bx-btn" onClick={this.handleSubmit}>
|
<button className="moco-bx-btn" onClick={this.handleSubmit}>
|
||||||
OK
|
OK
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -8,9 +8,14 @@ import { createServiceFinder } from "utils/urlMatcher"
|
|||||||
import remoteServices from "./remoteServices"
|
import remoteServices from "./remoteServices"
|
||||||
import { ContentMessenger } from "utils/messaging"
|
import { ContentMessenger } from "utils/messaging"
|
||||||
import "../css/content.scss"
|
import "../css/content.scss"
|
||||||
|
import { getSettings } from "./utils/browser"
|
||||||
|
|
||||||
const popupRef = createRef()
|
const popupRef = createRef()
|
||||||
const findService = createServiceFinder(remoteServices)(document)
|
|
||||||
|
let findService
|
||||||
|
getSettings().then((settings) => {
|
||||||
|
findService = createServiceFinder(remoteServices, settings.hostOverrides)(document)
|
||||||
|
})
|
||||||
|
|
||||||
chrome.runtime.onConnect.addListener(function (port) {
|
chrome.runtime.onConnect.addListener(function (port) {
|
||||||
const messenger = new ContentMessenger(port)
|
const messenger = new ContentMessenger(port)
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ const projectIdentifierBySelector = selector => document =>
|
|||||||
export default {
|
export default {
|
||||||
asana: {
|
asana: {
|
||||||
name: "asana",
|
name: "asana",
|
||||||
|
host: "https://app.asana.com",
|
||||||
urlPatterns: [
|
urlPatterns: [
|
||||||
[/^https:\/\/app.asana.com\/0\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
|
[/^__HOST__\/0\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
|
||||||
[/^https:\/\/app.asana.com\/0\/search\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
|
[/^__HOST__\/0\/search\/([^/]+)\/(\d+)/, ["domainUserId", "id"]],
|
||||||
],
|
],
|
||||||
description: document =>
|
description: document =>
|
||||||
document.querySelector(".ItemRow--highlighted textarea")?.textContent?.trim() ||
|
document.querySelector(".ItemRow--highlighted textarea")?.textContent?.trim() ||
|
||||||
@@ -19,32 +20,38 @@ export default {
|
|||||||
document.querySelector(".SingleTaskPane textarea")?.textContent?.trim() ||
|
document.querySelector(".SingleTaskPane textarea")?.textContent?.trim() ||
|
||||||
document.querySelector(".SingleTaskTitleInput-taskName textarea")?.textContent?.trim(),
|
document.querySelector(".SingleTaskTitleInput-taskName textarea")?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector(".TopbarPageHeaderStructure-titleRow h1"),
|
projectId: projectIdentifierBySelector(".TopbarPageHeaderStructure-titleRow h1"),
|
||||||
|
allowHostOverride: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"github-pr": {
|
"github-pr": {
|
||||||
name: "github",
|
name: "github",
|
||||||
urlPatterns: ["https\\://github.com/:org/:repo/pull/:id(/:tab)"],
|
host: "https://github.com",
|
||||||
|
urlPatterns: ["__HOST__/:org/:repo/pull/:id(/:tab)"],
|
||||||
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
|
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
|
||||||
description: document => document.querySelector(".js-issue-title")?.textContent?.trim(),
|
description: document => document.querySelector(".js-issue-title")?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector(".js-issue-title"),
|
projectId: projectIdentifierBySelector(".js-issue-title"),
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"github-issue": {
|
"github-issue": {
|
||||||
name: "github",
|
name: "github",
|
||||||
urlPatterns: ["https\\://github.com/:org/:repo/issues/:id"],
|
host: "https://github.com",
|
||||||
|
urlPatterns: ["__HOST__/:org/:repo/issues/:id"],
|
||||||
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
|
id: (document, service, { org, repo, id }) => [service.key, org, repo, id].join("."),
|
||||||
description: (document, service, { org, repo, id }) =>
|
description: (document, service, { org, repo, id }) =>
|
||||||
document.querySelector(".js-issue-title")?.textContent?.trim(),
|
document.querySelector(".js-issue-title")?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector(".js-issue-title"),
|
projectId: projectIdentifierBySelector(".js-issue-title"),
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
jira: {
|
jira: {
|
||||||
name: "jira",
|
name: "jira",
|
||||||
|
host: "https://:org.atlassian.net",
|
||||||
urlPatterns: [
|
urlPatterns: [
|
||||||
"https\\://:org.atlassian.net/secure/RapidBoard.jspa",
|
"__HOST__/secure/RapidBoard.jspa",
|
||||||
"https\\://:org.atlassian.net/browse/:id",
|
"__HOST__/browse/:id",
|
||||||
"https\\://:org.atlassian.net/jira/software/projects/:projectId/boards/:board",
|
"__HOST__/jira/software/projects/:projectId/boards/:board",
|
||||||
"https\\://:org.atlassian.net/jira/software/projects/:projectId/boards/:board/backlog",
|
"__HOST__/jira/software/projects/:projectId/boards/:board/backlog",
|
||||||
],
|
],
|
||||||
queryParams: {
|
queryParams: {
|
||||||
id: "selectedIssue",
|
id: "selectedIssue",
|
||||||
@@ -59,11 +66,13 @@ export default {
|
|||||||
document.querySelector(".ghx-selected .ghx-summary")?.textContent?.trim()
|
document.querySelector(".ghx-selected .ghx-summary")?.textContent?.trim()
|
||||||
return `#${id} ${title || ""}`
|
return `#${id} ${title || ""}`
|
||||||
},
|
},
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
meistertask: {
|
meistertask: {
|
||||||
name: "meistertask",
|
name: "meistertask",
|
||||||
urlPatterns: ["https\\://www.meistertask.com/app/task/:id/:slug"],
|
host: "https://www.meistertask.com",
|
||||||
|
urlPatterns: ["/app/task/:id/:slug"],
|
||||||
description: document => {
|
description: document => {
|
||||||
const json = document.getElementById("mt-toggl-data")?.dataset?.togglJson || "{}"
|
const json = document.getElementById("mt-toggl-data")?.dataset?.togglJson || "{}"
|
||||||
const data = JSON.parse(json)
|
const data = JSON.parse(json)
|
||||||
@@ -75,30 +84,36 @@ export default {
|
|||||||
const match = data.taskName?.match(projectRegex) || data.projectName?.match(projectRegex)
|
const match = data.taskName?.match(projectRegex) || data.projectName?.match(projectRegex)
|
||||||
return match && match[1]
|
return match && match[1]
|
||||||
},
|
},
|
||||||
|
allowHostOverride: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
trello: {
|
trello: {
|
||||||
name: "trello",
|
name: "trello",
|
||||||
urlPatterns: ["https\\://trello.com/c/:id/:title"],
|
host: "https://trello.com",
|
||||||
|
urlPatterns: ["__HOST__/c/:id/:title"],
|
||||||
description: (document, service, { title }) =>
|
description: (document, service, { title }) =>
|
||||||
document.querySelector(".js-title-helper")?.textContent?.trim() || title,
|
document.querySelector(".js-title-helper")?.textContent?.trim() || title,
|
||||||
projectId: document =>
|
projectId: document =>
|
||||||
projectIdentifierBySelector(".js-title-helper")(document) ||
|
projectIdentifierBySelector(".js-title-helper")(document) ||
|
||||||
projectIdentifierBySelector(".js-board-editing-target")(document),
|
projectIdentifierBySelector(".js-board-editing-target")(document),
|
||||||
|
allowHostOverride: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
youtrack: {
|
youtrack: {
|
||||||
name: "youtrack",
|
name: "youtrack",
|
||||||
urlPatterns: ["https\\://:org.myjetbrains.com/youtrack/issue/:id"],
|
host: "https://:org.myjetbrains.com",
|
||||||
|
urlPatterns: ["__HOST__/youtrack/issue/:id"],
|
||||||
description: document => document.querySelector("yt-issue-body h1")?.textContent?.trim(),
|
description: document => document.querySelector("yt-issue-body h1")?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector("yt-issue-body h1"),
|
projectId: projectIdentifierBySelector("yt-issue-body h1"),
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
wrike: {
|
wrike: {
|
||||||
name: "wrike",
|
name: "wrike",
|
||||||
|
host: "https://www.wrike.com",
|
||||||
urlPatterns: [
|
urlPatterns: [
|
||||||
"https\\://www.wrike.com/workspace.htm#path=mywork",
|
"__HOST__/workspace.htm#path=mywork",
|
||||||
"https\\://www.wrike.com/workspace.htm#path=folder",
|
"__HOST__/workspace.htm#path=folder",
|
||||||
"https\\://app-eu.wrike.com/workspace.htm#path=mywork",
|
"https\\://app-eu.wrike.com/workspace.htm#path=mywork",
|
||||||
"https\\://app-eu.wrike.com/workspace.htm#path=folder",
|
"https\\://app-eu.wrike.com/workspace.htm#path=folder",
|
||||||
],
|
],
|
||||||
@@ -107,39 +122,46 @@ export default {
|
|||||||
},
|
},
|
||||||
description: document => document.querySelector(".title-field-ghost")?.textContent?.trim(),
|
description: document => document.querySelector(".title-field-ghost")?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector(".header-title__main"),
|
projectId: projectIdentifierBySelector(".header-title__main"),
|
||||||
|
allowHostOverride: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
wunderlist: {
|
wunderlist: {
|
||||||
name: "wunderlist",
|
name: "wunderlist",
|
||||||
urlPatterns: ["https\\://www.wunderlist.com/(webapp)#/tasks/:id(/*)"],
|
host: "https://www.wunderlist.com",
|
||||||
|
urlPatterns: ["__HOST__/(webapp)#/tasks/:id(/*)"],
|
||||||
description: document =>
|
description: document =>
|
||||||
document
|
document
|
||||||
.querySelector(".taskItem.selected .taskItem-titleWrapper-title")
|
.querySelector(".taskItem.selected .taskItem-titleWrapper-title")
|
||||||
?.textContent?.trim(),
|
?.textContent?.trim(),
|
||||||
projectId: projectIdentifierBySelector(".taskItem.selected .taskItem-titleWrapper-title"),
|
projectId: projectIdentifierBySelector(".taskItem.selected .taskItem-titleWrapper-title"),
|
||||||
|
allowHostOverride: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
"gitlab-mr": {
|
"gitlab-mr": {
|
||||||
name: "gitlab",
|
name: "gitlab",
|
||||||
|
host: "https://gitlab.com",
|
||||||
urlPatterns: [
|
urlPatterns: [
|
||||||
"https\\://gitlab.com/:org/:group/:projectId/-/merge_requests/:id",
|
"__HOST__/:org/:group/:projectId/-/merge_requests/:id",
|
||||||
"https\\://gitlab.com/:org/:projectId/-/merge_requests/:id",
|
"__HOST__/:org/:projectId/-/merge_requests/:id",
|
||||||
],
|
],
|
||||||
description: (document, service, { id }) => {
|
description: (document, service, { id }) => {
|
||||||
const title = document.querySelector("h2.title")?.textContent?.trim()
|
const title = document.querySelector("h2.title")?.textContent?.trim()
|
||||||
return `#${id} ${title || ""}`.trim()
|
return `#${id} ${title || ""}`.trim()
|
||||||
},
|
},
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"gitlab-issues": {
|
"gitlab-issues": {
|
||||||
name: "gitlab",
|
name: "gitlab",
|
||||||
|
host: "https://gitlab.com",
|
||||||
urlPatterns: [
|
urlPatterns: [
|
||||||
"https\\://gitlab.com/:org/:group/:projectId/-/issues/:id",
|
"__HOST__/:org/:group/:projectId/-/issues/:id",
|
||||||
"https\\://gitlab.com/:org/:projectId/-/issues/:id",
|
"__HOST__/:org/:projectId/-/issues/:id",
|
||||||
],
|
],
|
||||||
description: (document, service, { id }) => {
|
description: (document, service, { id }) => {
|
||||||
const title = document.querySelector("h2.title")?.textContent?.trim()
|
const title = document.querySelector("h2.title")?.textContent?.trim()
|
||||||
return `#${id} ${title || ""}`.trim()
|
return `#${id} ${title || ""}`.trim()
|
||||||
},
|
},
|
||||||
|
allowHostOverride: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { head } from "lodash/fp"
|
import { head } from "lodash/fp"
|
||||||
|
|
||||||
export const isChrome = () => typeof browser === "undefined" && chrome
|
export const isChrome = () => typeof browser === "undefined" && chrome
|
||||||
export const isFirefox = () => typeof browser !== "undefined" && chrome
|
export const isFirefox = () => typeof browser !== "undefined" && chrome
|
||||||
|
|
||||||
const DEFAULT_SUBDOMAIN = "unset"
|
const DEFAULT_SUBDOMAIN = "unset"
|
||||||
|
|
||||||
export const getSettings = (withDefaultSubdomain = true) => {
|
export const getSettings = (withDefaultSubdomain = true) => {
|
||||||
const keys = ["subdomain", "apiKey", "settingTimeTrackingHHMM"]
|
const keys = ["subdomain", "apiKey", "settingTimeTrackingHHMM", "hostOverrides"]
|
||||||
const { version } = chrome.runtime.getManifest()
|
const { version } = chrome.runtime.getManifest()
|
||||||
if (isChrome()) {
|
if (isChrome()) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|||||||
@@ -12,7 +12,15 @@ import { createMatcher } from "utils/urlMatcher"
|
|||||||
import remoteServices from "remoteServices"
|
import remoteServices from "remoteServices"
|
||||||
import { queryTabs, isBrowserTab, getSettings, setStorage } from "utils/browser"
|
import { queryTabs, isBrowserTab, getSettings, setStorage } from "utils/browser"
|
||||||
|
|
||||||
const matcher = createMatcher(remoteServices)
|
let matcher
|
||||||
|
|
||||||
|
const initMatcher = (settings) => {
|
||||||
|
matcher = createMatcher(remoteServices, settings.hostOverrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
getSettings().then((settings) => {
|
||||||
|
initMatcher(settings)
|
||||||
|
})
|
||||||
|
|
||||||
export function tabUpdated(tab, { messenger, settings }) {
|
export function tabUpdated(tab, { messenger, settings }) {
|
||||||
messenger.connectTab(tab)
|
messenger.connectTab(tab)
|
||||||
@@ -54,6 +62,8 @@ export function tabUpdated(tab, { messenger, settings }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function settingsChanged(settings, { messenger }) {
|
export function settingsChanged(settings, { messenger }) {
|
||||||
|
initMatcher(settings)
|
||||||
|
|
||||||
queryTabs({ currentWindow: true })
|
queryTabs({ currentWindow: true })
|
||||||
.then(reject(isBrowserTab))
|
.then(reject(isBrowserTab))
|
||||||
.then(
|
.then(
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import UrlPattern from "url-pattern"
|
import UrlPattern from "url-pattern"
|
||||||
import { isFunction, isUndefined, compose, toPairs, map, pipe, isNil } from "lodash/fp"
|
import { isFunction, isUndefined, compose, toPairs, map, pipe, isNil, convert } from "lodash/fp"
|
||||||
import { asArray } from "./index"
|
import { asArray } from "./index"
|
||||||
import queryString from "query-string"
|
import queryString from "query-string"
|
||||||
|
|
||||||
@@ -39,15 +39,36 @@ const createEvaluator = args => fnOrValue => {
|
|||||||
return fnOrValue
|
return fnOrValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const prepareHostForRegExp = (host) => {
|
||||||
|
if (isUndefined(host)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return host.replace(":", "\\:")
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceHostInPattern = (host, pattern) => {
|
||||||
|
if(typeof pattern === "string") {
|
||||||
|
return pattern.replace("__HOST__", prepareHostForRegExp(host))
|
||||||
|
} else if(pattern instanceof RegExp) {
|
||||||
|
return new RegExp(pattern.source.replace("__HOST__", prepareHostForRegExp(host)))
|
||||||
|
} else {
|
||||||
|
console.error("Invalid type for pattern %v, no host replacement performed", pattern)
|
||||||
|
return pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const parseServices = compose(
|
const parseServices = compose(
|
||||||
map(([key, config]) => ({
|
map(([key, config]) => ({
|
||||||
...config,
|
...config,
|
||||||
key,
|
key,
|
||||||
patterns: config.urlPatterns.map(pattern => {
|
patterns: config.urlPatterns.map(pattern => {
|
||||||
if (Array.isArray(pattern)) {
|
if (Array.isArray(pattern)) {
|
||||||
return new UrlPattern(...pattern)
|
return new UrlPattern(
|
||||||
|
...pattern.map((p, index) => (index === 0 ? replaceHostInPattern(config.host, p) : p)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return new UrlPattern(pattern)
|
return new UrlPattern(replaceHostInPattern(config.host, pattern))
|
||||||
}),
|
}),
|
||||||
})),
|
})),
|
||||||
toPairs,
|
toPairs,
|
||||||
@@ -72,8 +93,28 @@ export const createEnhancer = document => service => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createMatcher = remoteServices => {
|
const applyHostOverrides = (remoteServices, hostOverrides) => {
|
||||||
const services = parseServices(remoteServices)
|
let appliedRemoteServices = Object.assign(remoteServices)
|
||||||
|
if (isUndefined(hostOverrides)) {
|
||||||
|
console.error("No overrides found.")
|
||||||
|
return remoteServices
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(remoteServices).forEach((key) => {
|
||||||
|
const remoteService = remoteServices[key]
|
||||||
|
appliedRemoteServices[key] = {
|
||||||
|
...remoteService,
|
||||||
|
key,
|
||||||
|
host: (hostOverrides && hostOverrides[remoteService.name]) || remoteService.host,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return appliedRemoteServices
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createMatcher = (remoteServices, hostOverrides) => {
|
||||||
|
const services = parseServices(applyHostOverrides(remoteServices, hostOverrides))
|
||||||
|
|
||||||
return tabUrl => {
|
return tabUrl => {
|
||||||
const { origin, pathname, hash, query } = parseUrl(tabUrl)
|
const { origin, pathname, hash, query } = parseUrl(tabUrl)
|
||||||
const url = `${origin}${pathname}${hash}`
|
const url = `${origin}${pathname}${hash}`
|
||||||
@@ -99,8 +140,8 @@ export const createMatcher = remoteServices => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createServiceFinder = remoteServices => document => {
|
export const createServiceFinder = (remoteServices, hostOverrides) => document => {
|
||||||
const matcher = createMatcher(remoteServices)
|
const matcher = createMatcher(remoteServices, hostOverrides)
|
||||||
const enhancer = createEnhancer(document)
|
const enhancer = createEnhancer(document)
|
||||||
return pipe(
|
return pipe(
|
||||||
matcher,
|
matcher,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ describe("utils", () => {
|
|||||||
let matcher
|
let matcher
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
matcher = createMatcher(remoteServices)
|
matcher = createMatcher(remoteServices, {})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("createMatcher", () => {
|
describe("createMatcher", () => {
|
||||||
@@ -162,4 +162,27 @@ describe("utils", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("urlMatcher with overrideHosts", () => {
|
||||||
|
let matcher
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
matcher = createMatcher(remoteServices, {
|
||||||
|
github: "https://my-custom-github-url.com",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("createMatcher", () => {
|
||||||
|
it("matches overridden host and path", () => {
|
||||||
|
const service = matcher("https://my-custom-github-url.com/hundertzehn/mocoapp/pull/123")
|
||||||
|
expect(service.key).toEqual("github-pr")
|
||||||
|
expect(service.name).toEqual("github")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("doesn't match default host and path", () => {
|
||||||
|
const service = matcher("https://github.com/hundertzehn/mocoapp/pull/123")
|
||||||
|
expect(service).toBe(undefined)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user