Enhance service

This commit is contained in:
Manuel Bouza
2019-02-07 18:26:15 +01:00
parent 7ad7cab5c0
commit cef97a5829
15 changed files with 210 additions and 112 deletions

View File

@@ -1,7 +1,8 @@
import DomainCheck from "./services/DomainCheck"
import config from "./config"
import { parseServices, createMatcher } from 'utils/urlMatcher'
import remoteServices from "./remoteServices"
const domainCheck = new DomainCheck(config)
const services = parseServices(remoteServices)
const matcher = createMatcher(services)
const { version } = chrome.runtime.getManifest()
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
@@ -10,14 +11,14 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
return
}
const service = domainCheck.match(tab.url)
const service = matcher(tab.url)
if (service) {
chrome.storage.sync.get(
["subdomain", "apiKey"],
({ subdomain, apiKey }) => {
const settings = { subdomain, apiKey, version }
const payload = { service, settings }
const payload = { serviceKey: service.key, settings }
chrome.tabs.sendMessage(tabId, { type: "mountBubble", payload }, () => {
console.log("bubble mounted")
})

View File

@@ -12,6 +12,14 @@ import { findLastProject, findLastTask, groupedProjectOptions } from "utils"
@observer
class Bubble extends Component {
static propTypes = {
service: PropTypes.shape({
id: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
description: PropTypes.string,
projectId: PropTypes.string,
taskId: PropTypes.string
}).isRequired,
settings: PropTypes.shape({
subdomain: PropTypes.string,
apiKey: PropTypes.string,

View File

@@ -1,12 +0,0 @@
export default {
services: [
{
name: "github",
urlPattern: "https://github.com/:org/:repo/pull/:id(/:tab)",
description: (document, { org, repo, id }) =>
`${org}/${repo}/${id} - ${document
.querySelector(".gh-header-title")
.textContent.trim()}`
}
]
}

View File

@@ -1,8 +1,12 @@
import { createElement } from "react"
import ReactDOM from "react-dom"
import Bubble from "./components/Bubble"
import services from "remoteServices"
import { createEnhancer } from "utils/urlMatcher"
import "../css/main.scss"
const serviceEnhancer = createEnhancer(window.document)(services)
chrome.runtime.onMessage.addListener(({ type, payload }) => {
switch (type) {
case "mountBubble": {
@@ -15,20 +19,24 @@ chrome.runtime.onMessage.addListener(({ type, payload }) => {
}
})
const mountBubble = ({ service, settings }) => {
if (document.getElementById("moco-bx-bubble")) {
return
const mountBubble = ({ serviceKey, settings }) => {
if (!document.getElementById("moco-bx-container")) {
const domContainer = document.createElement("div")
domContainer.setAttribute("id", "moco-bx-container")
document.body.appendChild(domContainer)
}
const domContainer = document.createElement("div")
domContainer.setAttribute("id", "moco-bx-container")
document.body.appendChild(domContainer)
if (!document.getElementById("moco-bx-bubble")) {
const domBubble = document.createElement("div")
domBubble.setAttribute("id", "moco-bx-bubble")
document.body.appendChild(domBubble)
}
const domBubble = document.createElement("div")
domBubble.setAttribute("id", "moco-bx-bubble")
document.body.appendChild(domBubble)
ReactDOM.render(createElement(Bubble, { service, settings }), domBubble)
const service = serviceEnhancer(serviceKey, window.location.href)
ReactDOM.render(
createElement(Bubble, { service, settings }),
document.getElementById("moco-bx-bubble")
)
}
const unmountBubble = () => {

30
src/js/remoteServices.js Normal file
View File

@@ -0,0 +1,30 @@
export default {
"github-pr": {
name: "github",
urlPattern: "https://github.com/:org/:repo/pull/:id(/:tab)",
id: (document, service, { org, repo, id }) =>
[org, repo, service.key, id].join("."),
description: (document, service, { org, repo, id }) =>
`${org}/${repo}/${id} - ${document
.querySelector(".js-issue-title")
?.textContent?.trim()}`,
projectId: document => {
const match = document
.querySelector(".js-issue-title")
?.textContent.trim()
?.match(/^\[(\d+)\]/)
return match && match[1]
}
},
"github-issue": {
name: "github",
urlPattern: "https://github.com/:org/:repo/issues/:id",
id: (document, service, { org, repo, id }) =>
[org, repo, "issue", id].join("."),
description: (document, service, { org, repo, id }) =>
`${org}/${repo}/${id} - ${document
.querySelector(".gh-header-title")
.textContent.trim()}`
}
}

View File

@@ -1,31 +0,0 @@
import Route from "route-parser"
class DomainCheck {
#services;
constructor(config) {
this.#services = config.services.map(service => ({
...service,
route: new Route(service.urlPattern),
}))
}
#findService = url =>
this.#services.find(service => service.route.match(url));
match(url) {
const service = this.#findService(url)
if (!service) {
return false
}
return {
...service,
match: service.route.match(url),
}
}
}
export default DomainCheck

View File

@@ -14,13 +14,13 @@ const nilToArray = input => input || []
export const findLastProject = id =>
compose(
find(pathEq("value", id)),
find(pathEq("value", Number(id))),
flatMap(get("options"))
)
export const findLastTask = id =>
compose(
find(pathEq("value", id)),
find(pathEq("value", Number(id))),
get("tasks")
)

View File

@@ -0,0 +1,45 @@
import Route from "route-parser"
import { isFunction, isUndefined, compose, toPairs, map } from "lodash/fp"
const createEvaluator = args => fnOrValue => {
if (isUndefined(fnOrValue)) {
return
}
if (isFunction(fnOrValue)) {
return fnOrValue(...args)
}
return fnOrValue
}
export const parseServices = compose(
map(([key, config]) => ({
...config,
key,
route: new Route(config.urlPattern)
})),
toPairs
)
export const createEnhancer = document => services => (key, url) => {
const service = services[key]
service.key = key
const route = new Route(service.urlPattern)
const match = route.match(url)
const args = [document, service, match]
const evaluate = createEvaluator(args)
return {
...service,
key,
url,
id: evaluate(service.id),
description: evaluate(service.description),
projectId: evaluate(service.projectId),
taskId: evaluate(service.taskId),
}
}
export const createMatcher = services => url =>
services.find(service => service.route.match(url))