MOCO Browser Extension (#2)
* spike * initial draft * updated styling * skeleton * added bubble script to webpack * added linter settings * installs * first implementation * Update webpack config - write bundle to `/build` - add support for SASS - improve options view as a proof o concept for styling * Update es-lint rules to mach mocoapp * Upgrade npm packages * Mount Bubble only for configured services * Update react and babel * Move module resolution config to webpack * Syncrhonize apiClient with chrome storage * Load projects and initialize form with last project and task * Enhance service * Improve handling of changeset with defaults * Create activity * Show error page on missing configuration * Refactor so that changeset can be used as activity params * Show form errors * Fetch and show booked hours for service * Allow to book hours with colon, error handling, spinner * WIP: Shadow DOM * Remove shadow dom * Render App in iframe * Refactor App component to load projects and create activity * Bugsnag integration * Add title to form and timer hint to hours input field * Configure positioning of bubble * Get rid of shared browser instance * Show Calendar and animate buble * Update webpack config * Prevent double animation of bubble * Fix eslint * Add margin to iframe body * Submit form when pressing enter on textarea * Open select on Enter * Use local environment for development * Show upgrade error if version invalid * Add asana service * Add jira and wunderlist services, add better support for query strings * Match urls with hash * Show popup in browser action * Pump version, add version to zip file * Add youtrack service * WIP: always show browserAction * Refactor * Update design * Finalize release 1.0.3 * Fix styles * Add support for Firefox browser * Extract common webpack config * Fix eslint * Close modal with ESC key * Use TimeInputParser to parse hours input * Improve webpack config * Show modal instead of popup when clicking on browser action * Pre-select last booked activities on service * Remove badge from booked hours * Show error and success feedback on options page * Remove updateBrowserActionForTab * Animate Bubble on unmount * Fix select date * Refactor * Fix key shortcut * Show schedule in calendar * Upload source maps to bugsnag * Upload sourcemaps to bugsnag * Define command shortcuts * Fix race condition where both Bubble and content wanted to mount Popup The content script is now the only place, where the Popup is mounted * Replace hash in filename by version * No new line in textarea and updated shortcuts for chrome * Change shortcut to Ctrl+Shift+K * Fix cors issue in new chrome 73 * Style improvements * Only report errors from own sources * Prevent sending messages to browser tabs * Fix scrollbars in iframe * Add error page for unknown error * Add stop propagation to Bubble click event * Update error pages * Remove timeout in tabHandler. The messaging error occurs only when the browser extension is reloaded/updated without refreshing the browser tab. * Refactor messaging * Show spinner in popup * Extract message handler to own module * Update styles and texts of error pages * Ensure focus is on document when opening popup * Find projects by identifier and value, do not highlight selected option in select component * Update docs * Spread match properties on service; improve remote service configuration for jira and wunderlist * Add webpack plugin to remove source mapping url * Bugsnag do not collect user ip * Upload source maps before removing source mapping url in bundles * Add support for regex url patterns, update asana config. * Fix animation Set default transform property via css * Improve config for asana * Change to fad-in/out animation
This commit is contained in:
104
src/js/utils/urlMatcher.js
Normal file
104
src/js/utils/urlMatcher.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import UrlPattern from "url-pattern"
|
||||
import {
|
||||
isFunction,
|
||||
isUndefined,
|
||||
compose,
|
||||
toPairs,
|
||||
map,
|
||||
pipe
|
||||
} from "lodash/fp"
|
||||
import queryString from "query-string"
|
||||
|
||||
const extractQueryParams = (queryParams, query) => {
|
||||
return toPairs(queryParams).reduce((acc, [key, param]) => {
|
||||
acc[key] = query[param]
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
const createEvaluator = args => fnOrValue => {
|
||||
if (isUndefined(fnOrValue)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isFunction(fnOrValue)) {
|
||||
return fnOrValue(...args)
|
||||
}
|
||||
|
||||
return fnOrValue
|
||||
}
|
||||
|
||||
const parseServices = compose(
|
||||
map(([key, config]) => ({
|
||||
...config,
|
||||
key,
|
||||
patterns: config.urlPatterns.map(pattern => {
|
||||
if (Array.isArray(pattern)) {
|
||||
return new UrlPattern(...pattern)
|
||||
}
|
||||
return new UrlPattern(pattern)
|
||||
})
|
||||
})),
|
||||
toPairs
|
||||
)
|
||||
|
||||
export const createEnhancer = document => service => {
|
||||
if (!service) {
|
||||
return
|
||||
}
|
||||
|
||||
const match = service.match
|
||||
const args = [document, service, match]
|
||||
const evaluate = createEvaluator(args)
|
||||
|
||||
return {
|
||||
...service,
|
||||
id: evaluate(service.id),
|
||||
description: evaluate(service.description),
|
||||
projectId: evaluate(service.projectId),
|
||||
taskId: evaluate(service.taskId),
|
||||
position: service.position || { left: "50%", transform: "translateX(-50%)" }
|
||||
}
|
||||
}
|
||||
|
||||
export const createMatcher = remoteServices => {
|
||||
const services = parseServices(remoteServices)
|
||||
return tabUrl => {
|
||||
const { origin, pathname, hash, search } = new URL(tabUrl)
|
||||
const url = `${origin}${pathname}${hash}`
|
||||
const query = queryString.parse(search)
|
||||
const service = services.find(service =>
|
||||
service.patterns.some(pattern => pattern.match(url))
|
||||
)
|
||||
|
||||
if (!service) {
|
||||
return
|
||||
}
|
||||
|
||||
const pattern = service.patterns.find(pattern => pattern.match(url))
|
||||
let match = pattern.match(url)
|
||||
if (service.queryParams) {
|
||||
const extractedQueryParams = extractQueryParams(
|
||||
service.queryParams,
|
||||
query
|
||||
)
|
||||
match = { ...extractedQueryParams, ...match }
|
||||
}
|
||||
|
||||
return {
|
||||
...match,
|
||||
...service,
|
||||
url,
|
||||
match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const createServiceFinder = remoteServices => document => {
|
||||
const matcher = createMatcher(remoteServices)
|
||||
const enhancer = createEnhancer(document)
|
||||
return pipe(
|
||||
matcher,
|
||||
enhancer
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user