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:
Manuel Bouza
2019-03-22 15:56:24 +01:00
parent cbf79b960c
commit 28a9a86e27
58 changed files with 11017 additions and 47 deletions

42
src/css/_button.scss Normal file
View File

@@ -0,0 +1,42 @@
button.moco-bx-btn {
display: block;
padding: 8px 12px;
margin: 0 auto;
font-weight: normal;
text-align: center;
white-space: nowrap;
color: white;
background-image: none;
background-color: #7dc332;
border-color: #7dc332;
border-radius: 0;
border-style: solid;
box-shadow: none;
font-size: 100%;
cursor: pointer;
&:hover:not(:disabled) {
background-color: #639a28;
border-color: #639a28;
}
&:disabled {
opacity: 0.65;
cursor: default;
}
&.secondary {
color: black;
background-color: #fff;
border-color: #ccc;
&:hover {
background-color: #f4f4f4;
border-color: #ccc;
}
}
& + button {
margin-left: 0.5rem;
}
}

91
src/css/_form.scss Normal file
View File

@@ -0,0 +1,91 @@
@import "button";
input {
border-radius: 0;
height: 20px;
}
.form-group {
width: 100%;
margin: 1rem 0;
label {
display: block;
font-weight: bold;
margin-bottom: 0.25rem;
}
input, textarea {
padding: 6px 12px;
background-color: white;
border-color: #cccccc;
width: 100%;
font-size: 100%;
border-style: solid;
border-width: 1px;
min-height: 20px;
}
.text-muted {
color: #999;
}
&.has-error {
input, textarea {
border-color: #FB3A2F;
}
}
.form-error {
color: #FB3A2F;
}
.input-group {
display: flex;
flex-flow: row nowrap;
input {
flex: 1 1;
}
.input-group-addon {
flex: 0 0 auto;
padding: 6px 12px;
font-weight: normal;
color: #555555;
text-align: center;
background-color: #eeeeee;
border: 1px solid #cccccc;
border-left: none;
line-height: 18px;
}
}
}
.moco-bx-select + .moco-bx-select {
margin-top: 3px;
}
input[name="hours"] {
width: 48px;
outline: 0 !important;
&:focus {
border: 1px solid #38b5eb;
box-shadow: 0 0 0 1px #38b5eb;
}
}
textarea[name="description"] {
font-family: inherit;
box-sizing: border-box;
width: 100%;
resize: none;
outline: 0 !important;
&:focus {
border: 1px solid #38b5eb;
box-shadow: 0 0 0 1px #38b5eb;
}
}

43
src/css/_reset.scss Normal file
View File

@@ -0,0 +1,43 @@
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

24
src/css/_spinner.scss Normal file
View File

@@ -0,0 +1,24 @@
#moco-bx-root {
@keyframes moco-bx-spinner {
to {
transform: rotate(360deg);
}
}
.moco-bx-spinner__container {
width: 100%;
margin-top: 120px;
.moco-bx-spinner {
display: block;
width: 2rem;
height: 2rem;
vertical-align: text-bottom;
border: 2px solid #999;
border-right-color: transparent;
border-radius: 50%;
margin: 0 auto;
animation: moco-bx-spinner .75s linear infinite;
}
}
}

5
src/css/_variables.scss Normal file
View File

@@ -0,0 +1,5 @@
$font-family: Arial, sans-serif;
$font-color: #191919;
$popup-width: 420px;
$popup-height: 463px;

77
src/css/content.scss Normal file
View File

@@ -0,0 +1,77 @@
@import "variables";
@import "button";
#moco-bx-root {
font-family: $font-family;
color: $font-color;
.moco-bx-bubble {
box-sizing: content-box;
position: fixed;
bottom: 2rem;
height: 60px;
width: 60px;
background-color: white;
border-radius: 50%;
box-shadow: -1px -1px 15px 4px rgba(0, 0, 0, 0.05),
2px 2px 15px 4px rgba(0, 0, 0, 0.05);
padding: 5px;
z-index: 9999;
cursor: pointer;
.moco-bx-bubble-inner {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
height: 100%;
img.moco-bx-logo {
width: 30px;
height: 30px;
}
.moco-bx-booked-hours {
display: inline-block;
font-size: 13px;
font-weight: 700;
line-height: 1;
color: black;
text-align: center;
padding: 5px 0 7px;
}
}
}
}
#moco-bx-popup-root {
font-family: $font-family;
color: $font-color;
iframe {
border: 0;
}
h2 {
margin-bottom: 1rem;
}
.moco-bx-popup {
position: fixed; /* Stay in place */
z-index: 2000; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0, 0, 0); /* Fallback color */
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
.moco-bx-popup-content {
background-color: white;
margin: 0 auto;
}
}
}

42
src/css/options.scss Normal file
View File

@@ -0,0 +1,42 @@
@import "variables";
@import "reset";
@import "form";
#moco-bx-root {
font-family: $font-family;
color: $font-color;
font-size: 14px;
line-height: 1.5;
.moco-bx-options {
padding: 0rem 2rem 2rem;
p {
margin: 0.5rem 0;
}
h2 {
font-size: 1.5rem;
margin: 1rem 0 2rem;
}
label {
font-weight: normal;
margin-bottom: 5px;
}
input {
box-sizing: border-box;
padding: 6px 12px;
height: 32px;
}
.text-success {
color: #7DC332;
}
.text-danger {
color: #FB3A2F;
}
}
}

128
src/css/popup.scss Normal file
View File

@@ -0,0 +1,128 @@
@import "form";
@import "spinner";
@import "variables";
html {
overflow: hidden;
body {
font-size: 14px;
margin: 0px;
font-family: $font-family;
color: $font-color;
#moco-bx-root {
min-width: 516px;
.moco-bx-app-container {
width: 324px;
padding: 3rem 6rem;
.moco-bx-logo__container {
display: flex;
justify-content: center;
margin-bottom: 3rem;
text-align: center;
img.moco-bx-logo {
flex: 0 0 48px;
width: 48px;
height: 48px;
}
h1 {
line-height: 48px;
margin: 0;
}
}
.moco-bx-calendar {
display: flex;
justify-content: space-between;
margin-bottom: 3rem;
.moco-bx-calendar__day {
display: flex;
flex-flow: column nowrap;
align-items: center;
flex: 0 0 42px;
width: 42px;
cursor: pointer;
.moco-bx-calendar__day-of-week {
margin-bottom: 5px;
font-size: 12px;
color: hsl(0, 0%, 60%);
}
.moco-bx-calendar__hours {
display: flex;
justify-content: center;
align-items: center;
width: 42px;
height: 42px;
flex: 0 0 42px;
color: white;
background-color: #eee;
}
&.moco-bx-calendar__day--filled {
.moco-bx-calendar__hours {
background-color: #7dc332;
}
}
&.moco-bx-calendar__day--week-day-6,
&.moco-bx-calendar__day--week-day-0 {
.moco-bx-calendar__hours {
background-color: #bbb;
}
}
&.moco-bx-calendar__day--active {
.moco-bx-calendar__hours {
background-color: #38b5eb;
}
}
}
}
}
.moco-bx-error-container {
font-size: 18px;
line-height: 1.5;
width: 420px;
padding: 3rem;
text-align: center;
h1 {
font-size: 35px;
font-weight: normal;
margin-top: 0;
line-height: 1.3;
}
img {
width: auto;
max-width: 100%;
&.moco-bx-logo {
width: 48px;
margin-bottom: 2rem;
}
}
ol {
text-align: left;
}
button {
margin-top: 1.5rem;
}
}
}
}
}