Update eslint cofig
This commit is contained in:
parent
fd04d6bf6c
commit
8b2e21c3cf
@ -22,6 +22,11 @@
|
|||||||
},
|
},
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"strict": 0,
|
"strict": 0,
|
||||||
"semi": ["error", "never"],
|
"semi": ["error", "never"],
|
||||||
|
@ -3,19 +3,15 @@ import { formatDate } from "utils"
|
|||||||
|
|
||||||
const baseURL = subdomain => {
|
const baseURL = subdomain => {
|
||||||
if (process.env.NODE_ENV === "production") {
|
if (process.env.NODE_ENV === "production") {
|
||||||
return `https://${encodeURIComponent(
|
return `https://${encodeURIComponent(subdomain)}.mocoapp.com/api/browser_extensions`
|
||||||
subdomain
|
|
||||||
)}.mocoapp.com/api/browser_extensions`
|
|
||||||
} else {
|
} else {
|
||||||
return `http://${encodeURIComponent(
|
return `http://${encodeURIComponent(subdomain)}.mocoapp.localhost:3001/api/browser_extensions`
|
||||||
subdomain
|
|
||||||
)}.mocoapp.localhost:3001/api/browser_extensions`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Client {
|
export default class Client {
|
||||||
#client;
|
#client
|
||||||
#apiKey;
|
#apiKey
|
||||||
|
|
||||||
constructor({ subdomain, apiKey, version }) {
|
constructor({ subdomain, apiKey, version }) {
|
||||||
this.#apiKey = apiKey
|
this.#apiKey = apiKey
|
||||||
@ -25,9 +21,9 @@ export default class Client {
|
|||||||
headers: {
|
headers: {
|
||||||
common: {
|
common: {
|
||||||
"x-api-key": apiKey,
|
"x-api-key": apiKey,
|
||||||
"x-extension-version": version
|
"x-extension-version": version,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,29 +31,29 @@ export default class Client {
|
|||||||
this.#client.post("session", {
|
this.#client.post("session", {
|
||||||
api_key: this.#apiKey,
|
api_key: this.#apiKey,
|
||||||
remote_service: service?.name,
|
remote_service: service?.name,
|
||||||
remote_id: service?.id
|
remote_id: service?.id,
|
||||||
});
|
})
|
||||||
|
|
||||||
projects = () => this.#client.get("projects");
|
projects = () => this.#client.get("projects")
|
||||||
|
|
||||||
schedules = (fromDate, toDate) =>
|
schedules = (fromDate, toDate) =>
|
||||||
this.#client.get("schedules", {
|
this.#client.get("schedules", {
|
||||||
params: { date: `${formatDate(fromDate)}:${formatDate(toDate)}` }
|
params: { date: `${formatDate(fromDate)}:${formatDate(toDate)}` },
|
||||||
});
|
})
|
||||||
|
|
||||||
activities = (fromDate, toDate) =>
|
activities = (fromDate, toDate) =>
|
||||||
this.#client.get("activities", {
|
this.#client.get("activities", {
|
||||||
params: { date: `${formatDate(fromDate)}:${formatDate(toDate)}` }
|
params: { date: `${formatDate(fromDate)}:${formatDate(toDate)}` },
|
||||||
});
|
})
|
||||||
|
|
||||||
bookedHours = service => {
|
bookedHours = service => {
|
||||||
if (!service) {
|
if (!service) {
|
||||||
return Promise.resolve({ data: { hours: 0 } })
|
return Promise.resolve({ data: { hours: 0 } })
|
||||||
}
|
}
|
||||||
return this.#client.get("activities/tags", {
|
return this.#client.get("activities/tags", {
|
||||||
params: { selection: [service.id], remote_service: service.name }
|
params: { selection: [service.id], remote_service: service.name },
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
createActivity = activity => this.#client.post("activities", { activity });
|
createActivity = activity => this.#client.post("activities", { activity })
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,11 @@ const Day = ({ date, hours, absence, active, onClick }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn("moco-bx-calendar__day", `moco-bx-calendar__day--week-day-${getDay(date)}`, {
|
||||||
"moco-bx-calendar__day",
|
"moco-bx-calendar__day--active": active,
|
||||||
`moco-bx-calendar__day--week-day-${getDay(date)}`,
|
"moco-bx-calendar__day--filled": hours > 0,
|
||||||
{
|
"moco-bx-calendar__day--absence": absence,
|
||||||
"moco-bx-calendar__day--active": active,
|
})}
|
||||||
"moco-bx-calendar__day--filled": hours > 0,
|
|
||||||
"moco-bx-calendar__day--absence": absence
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<span className="moco-bx-calendar__day-of-week">
|
<span className="moco-bx-calendar__day-of-week">
|
||||||
@ -34,7 +30,7 @@ Day.propTypes = {
|
|||||||
hours: PropTypes.number.isRequired,
|
hours: PropTypes.number.isRequired,
|
||||||
absence: PropTypes.object,
|
absence: PropTypes.object,
|
||||||
active: PropTypes.bool.isRequired,
|
active: PropTypes.bool.isRequired,
|
||||||
onClick: PropTypes.func.isRequired
|
onClick: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Day
|
export default Day
|
||||||
|
@ -35,9 +35,9 @@ Hours.propTypes = {
|
|||||||
hours: PropTypes.number.isRequired,
|
hours: PropTypes.number.isRequired,
|
||||||
absence: PropTypes.shape({
|
absence: PropTypes.shape({
|
||||||
assignment_code: PropTypes.string,
|
assignment_code: PropTypes.string,
|
||||||
assignment_color: PropTypes.string
|
assignment_color: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
active: PropTypes.bool.isRequired
|
active: PropTypes.bool.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Hours
|
export default Hours
|
||||||
|
@ -5,22 +5,14 @@ import { formatDate } from "utils"
|
|||||||
import { eachDay } from "date-fns"
|
import { eachDay } from "date-fns"
|
||||||
import { pathEq } from "lodash/fp"
|
import { pathEq } from "lodash/fp"
|
||||||
|
|
||||||
const findAbsence = (date, schedules) =>
|
const findAbsence = (date, schedules) => schedules.find(pathEq("date", formatDate(date)))
|
||||||
schedules.find(pathEq("date", formatDate(date)))
|
|
||||||
|
|
||||||
const hoursAtDate = (date, activities) =>
|
const hoursAtDate = (date, activities) =>
|
||||||
activities
|
activities
|
||||||
.filter(pathEq("date", formatDate(date)))
|
.filter(pathEq("date", formatDate(date)))
|
||||||
.reduce((acc, activity) => acc + activity.hours, 0)
|
.reduce((acc, activity) => acc + activity.hours, 0)
|
||||||
|
|
||||||
const Calendar = ({
|
const Calendar = ({ fromDate, toDate, selectedDate, activities, schedules, onChange }) => (
|
||||||
fromDate,
|
|
||||||
toDate,
|
|
||||||
selectedDate,
|
|
||||||
activities,
|
|
||||||
schedules,
|
|
||||||
onChange
|
|
||||||
}) => (
|
|
||||||
<div className="moco-bx-calendar">
|
<div className="moco-bx-calendar">
|
||||||
{eachDay(fromDate, toDate).map(date => (
|
{eachDay(fromDate, toDate).map(date => (
|
||||||
<Day
|
<Day
|
||||||
@ -44,17 +36,17 @@ Calendar.propTypes = {
|
|||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
date: PropTypes.string.isRequired,
|
date: PropTypes.string.isRequired,
|
||||||
hours: PropTypes.number.isRequired,
|
hours: PropTypes.number.isRequired,
|
||||||
timer_started_at: PropTypes.string
|
timer_started_at: PropTypes.string,
|
||||||
}).isRequired
|
}).isRequired,
|
||||||
),
|
),
|
||||||
schedules: PropTypes.arrayOf(
|
schedules: PropTypes.arrayOf(
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
date: PropTypes.string,
|
date: PropTypes.string,
|
||||||
assignment_code: PropTypes.string,
|
assignment_code: PropTypes.string,
|
||||||
assignment_color: PropTypes.string
|
assignment_color: PropTypes.string,
|
||||||
})
|
}),
|
||||||
).isRequired,
|
).isRequired,
|
||||||
onChange: PropTypes.func.isRequired
|
onChange: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Calendar
|
export default Calendar
|
||||||
|
@ -15,7 +15,7 @@ const UnknownError = ({ message = "Unbekannter Fehler" }) => (
|
|||||||
)
|
)
|
||||||
|
|
||||||
UnknownError.propTypes = {
|
UnknownError.propTypes = {
|
||||||
message: PropTypes.string
|
message: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UnknownError
|
export default UnknownError
|
||||||
|
@ -7,10 +7,7 @@ const UpgradeRequiredError = () => (
|
|||||||
<div className="moco-bx-error-container">
|
<div className="moco-bx-error-container">
|
||||||
<img className="moco-bx-logo" src={logo} alt="MOCO logo" />
|
<img className="moco-bx-logo" src={logo} alt="MOCO logo" />
|
||||||
<h1>Upgrade erforderlich</h1>
|
<h1>Upgrade erforderlich</h1>
|
||||||
<p>
|
<p>Die installierte MOCO Browser-Erweiterung ist veraltet — bitte aktualisieren.</p>
|
||||||
Die installierte MOCO Browser-Erweiterung ist veraltet — bitte
|
|
||||||
aktualisieren.
|
|
||||||
</p>
|
|
||||||
{isChrome() ? (
|
{isChrome() ? (
|
||||||
<button
|
<button
|
||||||
className="moco-bx-btn"
|
className="moco-bx-btn"
|
||||||
@ -22,11 +19,7 @@ const UpgradeRequiredError = () => (
|
|||||||
<>
|
<>
|
||||||
<br />
|
<br />
|
||||||
<p>Unter folgender URL:</p>
|
<p>Unter folgender URL:</p>
|
||||||
<img
|
<img className="firefox-addons" src={firefoxAddons} alt="about:addons" />
|
||||||
className="firefox-addons"
|
|
||||||
src={firefoxAddons}
|
|
||||||
alt="about:addons"
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,24 +8,24 @@ class Form extends Component {
|
|||||||
changeset: PropTypes.shape({
|
changeset: PropTypes.shape({
|
||||||
project: PropTypes.object,
|
project: PropTypes.object,
|
||||||
task: PropTypes.object,
|
task: PropTypes.object,
|
||||||
hours: PropTypes.string
|
hours: PropTypes.string,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
errors: PropTypes.object,
|
errors: PropTypes.object,
|
||||||
projects: PropTypes.array.isRequired,
|
projects: PropTypes.array.isRequired,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
onSubmit: PropTypes.func.isRequired
|
onSubmit: PropTypes.func.isRequired,
|
||||||
};
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
inline: true
|
inline: true,
|
||||||
};
|
}
|
||||||
|
|
||||||
isValid = () => {
|
isValid = () => {
|
||||||
const { changeset } = this.props
|
const { changeset } = this.props
|
||||||
return ["assignment_id", "task_id", "hours", "description"]
|
return ["assignment_id", "task_id", "hours", "description"]
|
||||||
.map(prop => changeset[prop])
|
.map(prop => changeset[prop])
|
||||||
.every(Boolean)
|
.every(Boolean)
|
||||||
};
|
}
|
||||||
|
|
||||||
handleTextareaKeyDown = event => {
|
handleTextareaKeyDown = event => {
|
||||||
const { onSubmit } = this.props
|
const { onSubmit } = this.props
|
||||||
@ -34,7 +34,7 @@ class Form extends Component {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.isValid() && onSubmit(event)
|
this.isValid() && onSubmit(event)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { projects, changeset, errors, onChange, onSubmit } = this.props
|
const { projects, changeset, errors, onChange, onSubmit } = this.props
|
||||||
@ -44,7 +44,7 @@ class Form extends Component {
|
|||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<div
|
<div
|
||||||
className={cn("form-group", {
|
className={cn("form-group", {
|
||||||
"has-error": errors.assignment_id || errors.task_id
|
"has-error": errors.assignment_id || errors.task_id,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
@ -69,9 +69,7 @@ class Form extends Component {
|
|||||||
{errors.assignment_id ? (
|
{errors.assignment_id ? (
|
||||||
<div className="form-error">{errors.assignment_id.join("; ")}</div>
|
<div className="form-error">{errors.assignment_id.join("; ")}</div>
|
||||||
) : null}
|
) : null}
|
||||||
{errors.task_id ? (
|
{errors.task_id ? <div className="form-error">{errors.task_id.join("; ")}</div> : null}
|
||||||
<div className="form-error">{errors.task_id.join("; ")}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={cn("form-group", { "has-error": errors.hours })}>
|
<div className={cn("form-group", { "has-error": errors.hours })}>
|
||||||
<input
|
<input
|
||||||
@ -83,9 +81,7 @@ class Form extends Component {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{errors.hours ? (
|
{errors.hours ? <div className="form-error">{errors.hours.join("; ")}</div> : null}
|
||||||
<div className="form-error">{errors.hours.join("; ")}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={cn("form-group", { "has-error": errors.description })}>
|
<div className={cn("form-group", { "has-error": errors.description })}>
|
||||||
<textarea
|
<textarea
|
||||||
|
@ -6,10 +6,10 @@ import ApiClient from "api/Client"
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Options extends Component {
|
class Options extends Component {
|
||||||
@observable subdomain = "";
|
@observable subdomain = ""
|
||||||
@observable apiKey = "";
|
@observable apiKey = ""
|
||||||
@observable errorMessage = null;
|
@observable errorMessage = null
|
||||||
@observable isSuccess = false;
|
@observable isSuccess = false
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
getSettings(false).then(({ subdomain, apiKey }) => {
|
getSettings(false).then(({ subdomain, apiKey }) => {
|
||||||
@ -20,7 +20,7 @@ class Options extends Component {
|
|||||||
|
|
||||||
onChange = event => {
|
onChange = event => {
|
||||||
this[event.target.name] = event.target.value.trim()
|
this[event.target.name] = event.target.value.trim()
|
||||||
};
|
}
|
||||||
|
|
||||||
handleSubmit = _event => {
|
handleSubmit = _event => {
|
||||||
this.isSuccess = false
|
this.isSuccess = false
|
||||||
@ -30,7 +30,7 @@ class Options extends Component {
|
|||||||
const apiClient = new ApiClient({
|
const apiClient = new ApiClient({
|
||||||
subdomain: this.subdomain,
|
subdomain: this.subdomain,
|
||||||
apiKey: this.apiKey,
|
apiKey: this.apiKey,
|
||||||
version
|
version,
|
||||||
})
|
})
|
||||||
apiClient
|
apiClient
|
||||||
.login()
|
.login()
|
||||||
@ -39,32 +39,27 @@ class Options extends Component {
|
|||||||
this.closeWindow()
|
this.closeWindow()
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.errorMessage =
|
this.errorMessage = error.response?.data?.message || "Anmeldung fehlgeschlagen"
|
||||||
error.response?.data?.message || "Anmeldung fehlgeschlagen"
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
handleInputKeyDown = event => {
|
handleInputKeyDown = event => {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
this.handleSubmit()
|
this.handleSubmit()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
closeWindow = () => {
|
closeWindow = () => {
|
||||||
isChrome() && window.close()
|
isChrome() && window.close()
|
||||||
};
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="moco-bx-options">
|
<div className="moco-bx-options">
|
||||||
<h2 style={{ textAlign: "center" }}>Einstellungen</h2>
|
<h2 style={{ textAlign: "center" }}>Einstellungen</h2>
|
||||||
{this.errorMessage && (
|
{this.errorMessage && <div className="text-danger">{this.errorMessage}</div>}
|
||||||
<div className="text-danger">{this.errorMessage}</div>
|
{this.isSuccess && <div className="text-success">Anmeldung erfolgreich</div>}
|
||||||
)}
|
|
||||||
{this.isSuccess && (
|
|
||||||
<div className="text-success">Anmeldung erfolgreich</div>
|
|
||||||
)}
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>Internetadresse</label>
|
<label>Internetadresse</label>
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
@ -88,8 +83,7 @@ class Options extends Component {
|
|||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
/>
|
/>
|
||||||
<p className="text-muted">
|
<p className="text-muted">
|
||||||
Den API-Schlüssel findest du in deinem Profil unter
|
Den API-Schlüssel findest du in deinem Profil unter "Integrationen".
|
||||||
"Integrationen".
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button className="moco-bx-btn" onClick={this.handleSubmit}>
|
<button className="moco-bx-btn" onClick={this.handleSubmit}>
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import PropTypes from "prop-types"
|
import PropTypes from "prop-types"
|
||||||
import queryString from "query-string"
|
import queryString from "query-string"
|
||||||
import {
|
import { ERROR_UNKNOWN, ERROR_UNAUTHORIZED, ERROR_UPGRADE_REQUIRED, serializeProps } from "utils"
|
||||||
ERROR_UNKNOWN,
|
|
||||||
ERROR_UNAUTHORIZED,
|
|
||||||
ERROR_UPGRADE_REQUIRED,
|
|
||||||
serializeProps
|
|
||||||
} from "utils"
|
|
||||||
import { isChrome } from "utils/browser"
|
import { isChrome } from "utils/browser"
|
||||||
|
|
||||||
function getStyles(errorType) {
|
function getStyles(errorType) {
|
||||||
@ -21,7 +16,7 @@ function getStyles(errorType) {
|
|||||||
: "461px"
|
: "461px"
|
||||||
: errorType === ERROR_UNKNOWN
|
: errorType === ERROR_UNKNOWN
|
||||||
? "550px"
|
? "550px"
|
||||||
: "558px"
|
: "558px",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,14 +24,14 @@ class Popup extends Component {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
service: PropTypes.object,
|
service: PropTypes.object,
|
||||||
errorType: PropTypes.string,
|
errorType: PropTypes.string,
|
||||||
onRequestClose: PropTypes.func.isRequired
|
onRequestClose: PropTypes.func.isRequired,
|
||||||
};
|
}
|
||||||
|
|
||||||
handleRequestClose = event => {
|
handleRequestClose = event => {
|
||||||
if (event.target.classList.contains("moco-bx-popup")) {
|
if (event.target.classList.contains("moco-bx-popup")) {
|
||||||
this.props.onRequestClose()
|
this.props.onRequestClose()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// Document might lose focus when clicking the browser action.
|
// Document might lose focus when clicking the browser action.
|
||||||
@ -64,7 +59,7 @@ class Popup extends Component {
|
|||||||
"fromDate",
|
"fromDate",
|
||||||
"toDate",
|
"toDate",
|
||||||
"errorType",
|
"errorType",
|
||||||
"errorMessage"
|
"errorMessage",
|
||||||
])(this.props)
|
])(this.props)
|
||||||
|
|
||||||
const styles = getStyles(this.props.errorType)
|
const styles = getStyles(this.props.errorType)
|
||||||
@ -73,9 +68,7 @@ class Popup extends Component {
|
|||||||
<div className="moco-bx-popup" onClick={this.handleRequestClose}>
|
<div className="moco-bx-popup" onClick={this.handleRequestClose}>
|
||||||
<div className="moco-bx-popup-content" style={styles}>
|
<div className="moco-bx-popup-content" style={styles}>
|
||||||
<iframe
|
<iframe
|
||||||
src={chrome.extension.getURL(
|
src={chrome.extension.getURL(`popup.html?${queryString.stringify(serializedProps)}`)}
|
||||||
`popup.html?${queryString.stringify(serializedProps)}`
|
|
||||||
)}
|
|
||||||
width={styles.width}
|
width={styles.width}
|
||||||
height={styles.height}
|
height={styles.height}
|
||||||
/>
|
/>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from "prop-types"
|
||||||
|
|
||||||
const Spinner = ({ style }) => (
|
const Spinner = ({ style }) => (
|
||||||
<div className='moco-bx-spinner__container' style={style}>
|
<div className="moco-bx-spinner__container" style={style}>
|
||||||
<div className='moco-bx-spinner' role='status' />
|
<div className="moco-bx-spinner" role="status" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
Spinner.propTypes = {
|
Spinner.propTypes = {
|
||||||
style: PropTypes.object
|
style: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Spinner
|
export default Spinner
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
import React from 'react'
|
import React from "react"
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from "prop-types"
|
||||||
import logoUrl from "images/logo.png"
|
import logoUrl from "images/logo.png"
|
||||||
|
|
||||||
const Header = ({ subdomain }) => (
|
const Header = ({ subdomain }) => (
|
||||||
<div className="moco-bx-logo__container">
|
<div className="moco-bx-logo__container">
|
||||||
<a href={`https://${subdomain}.mocoapp.com/activities`} target="_blank" rel="noopener noreferrer">
|
<a
|
||||||
<img
|
href={`https://${subdomain}.mocoapp.com/activities`}
|
||||||
className="moco-bx-logo"
|
target="_blank"
|
||||||
src={chrome.extension.getURL(logoUrl)}
|
rel="noopener noreferrer"
|
||||||
/>
|
>
|
||||||
|
<img className="moco-bx-logo" src={chrome.extension.getURL(logoUrl)} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
Header.propTypes = {
|
Header.propTypes = {
|
||||||
subdomain: PropTypes.string
|
subdomain: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Header
|
export default Header
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export default class TimeInputParser {
|
export default class TimeInputParser {
|
||||||
#input;
|
#input
|
||||||
|
|
||||||
constructor(input) {
|
constructor(input) {
|
||||||
this.#input = input.toLowerCase().replace(/[\s()]/g, "")
|
this.#input = input.toLowerCase().replace(/[\s()]/g, "")
|
||||||
@ -25,11 +25,11 @@ export default class TimeInputParser {
|
|||||||
const calculated = hours * 3600 + minutes * 60
|
const calculated = hours * 3600 + minutes * 60
|
||||||
|
|
||||||
return isNegative ? -calculated : calculated
|
return isNegative ? -calculated : calculated
|
||||||
};
|
}
|
||||||
|
|
||||||
#parseDecimal = () => {
|
#parseDecimal = () => {
|
||||||
return this.#input.replace(/[.,]/g, ".")
|
return this.#input.replace(/[.,]/g, ".")
|
||||||
};
|
}
|
||||||
|
|
||||||
#parseTimeAsSeconds = () => {
|
#parseTimeAsSeconds = () => {
|
||||||
const match = this.#isTime()
|
const match = this.#isTime()
|
||||||
@ -39,12 +39,12 @@ export default class TimeInputParser {
|
|||||||
const minutes = parseInt(match[3])
|
const minutes = parseInt(match[3])
|
||||||
|
|
||||||
return this.#calculateFromHoursAndMinutes(hours, minutes, isNegative)
|
return this.#calculateFromHoursAndMinutes(hours, minutes, isNegative)
|
||||||
};
|
}
|
||||||
|
|
||||||
#parseMinutesAsSeconds = () => {
|
#parseMinutesAsSeconds = () => {
|
||||||
const minutes = parseInt(this.#isMinutes()[1])
|
const minutes = parseInt(this.#isMinutes()[1])
|
||||||
return minutes * 60
|
return minutes * 60
|
||||||
};
|
}
|
||||||
|
|
||||||
#parseRange = () => {
|
#parseRange = () => {
|
||||||
const match = this.#isRange()
|
const match = this.#isRange()
|
||||||
@ -54,7 +54,7 @@ export default class TimeInputParser {
|
|||||||
const to_hours = parseInt(match[3])
|
const to_hours = parseInt(match[3])
|
||||||
const to_minutes = parseInt(match[4])
|
const to_minutes = parseInt(match[4])
|
||||||
return (to_hours - from_hours) * 3600 + (to_minutes - from_minutes) * 60
|
return (to_hours - from_hours) * 3600 + (to_minutes - from_minutes) * 60
|
||||||
};
|
}
|
||||||
|
|
||||||
#parseHoursAndMinutes = () => {
|
#parseHoursAndMinutes = () => {
|
||||||
const match = this.#isHoursAndMinutes()
|
const match = this.#isHoursAndMinutes()
|
||||||
@ -64,28 +64,26 @@ export default class TimeInputParser {
|
|||||||
const minutes = parseInt(match[3])
|
const minutes = parseInt(match[3])
|
||||||
|
|
||||||
return this.#calculateFromHoursAndMinutes(hours, minutes, isNegative)
|
return this.#calculateFromHoursAndMinutes(hours, minutes, isNegative)
|
||||||
};
|
}
|
||||||
|
|
||||||
#isDecimal = () => {
|
#isDecimal = () => {
|
||||||
return this.#input.match(/^([-]?[0-9]{0,2})[.,]{1}([0-9]{1,2})$/)
|
return this.#input.match(/^([-]?[0-9]{0,2})[.,]{1}([0-9]{1,2})$/)
|
||||||
};
|
}
|
||||||
|
|
||||||
#isTime = () => {
|
#isTime = () => {
|
||||||
return this.#input.match(/^([-]?)([0-9]{1,2}):([0-9]{2})$/)
|
return this.#input.match(/^([-]?)([0-9]{1,2}):([0-9]{2})$/)
|
||||||
};
|
}
|
||||||
|
|
||||||
#isMinutes = () => {
|
#isMinutes = () => {
|
||||||
return this.#input.match(/^([-]?[0-9]{1,3})(m|mins?)$/)
|
return this.#input.match(/^([-]?[0-9]{1,3})(m|mins?)$/)
|
||||||
};
|
}
|
||||||
|
|
||||||
#isRange = () => {
|
#isRange = () => {
|
||||||
return this.#input.match(
|
return this.#input.match(/^([0-9]{1,2})[:.]{0,1}([0-9]{2})-([0-9]{1,2})[:.]{0,1}([0-9]{2})$/)
|
||||||
/^([0-9]{1,2})[:.]{0,1}([0-9]{2})-([0-9]{1,2})[:.]{0,1}([0-9]{2})$/
|
}
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
#isHoursAndMinutes = () => {
|
#isHoursAndMinutes = () => {
|
||||||
// 1h 14m(in)
|
// 1h 14m(in)
|
||||||
return this.#input.match(/^([-]?)([0-9]{1,2})h([0-9]{1,2})(m|mins?)$/)
|
return this.#input.match(/^([-]?)([0-9]{1,2})h([0-9]{1,2})(m|mins?)$/)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
export class BackgroundMessenger {
|
export class BackgroundMessenger {
|
||||||
#ports = new Map();
|
#ports = new Map()
|
||||||
#handlers = new Map();
|
#handlers = new Map()
|
||||||
#onceHandlers = new Map();
|
#onceHandlers = new Map()
|
||||||
|
|
||||||
#handler = action => {
|
#handler = action => {
|
||||||
const handler = this.#handlers.get(action.type)
|
const handler = this.#handlers.get(action.type)
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler(action)
|
handler(action)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
#onceHandler = action => {
|
#onceHandler = action => {
|
||||||
const handler = this.#onceHandlers.get(action.type)
|
const handler = this.#onceHandlers.get(action.type)
|
||||||
@ -16,7 +16,7 @@ export class BackgroundMessenger {
|
|||||||
if (handler) {
|
if (handler) {
|
||||||
handler(action)
|
handler(action)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
#registerPort = (tabId, port) => {
|
#registerPort = (tabId, port) => {
|
||||||
this.#ports.set(tabId, port)
|
this.#ports.set(tabId, port)
|
||||||
@ -25,14 +25,14 @@ export class BackgroundMessenger {
|
|||||||
port.onDisconnect.addListener(() => {
|
port.onDisconnect.addListener(() => {
|
||||||
this.#unregisterPort(tabId, port)
|
this.#unregisterPort(tabId, port)
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
#unregisterPort = (tabId, port) => {
|
#unregisterPort = (tabId, port) => {
|
||||||
port.onMessage.removeListener(this.#handler)
|
port.onMessage.removeListener(this.#handler)
|
||||||
port.onMessage.removeListener(this.#onceHandler)
|
port.onMessage.removeListener(this.#onceHandler)
|
||||||
port.disconnect()
|
port.disconnect()
|
||||||
this.#ports.delete(tabId)
|
this.#ports.delete(tabId)
|
||||||
};
|
}
|
||||||
|
|
||||||
connectTab = tab => {
|
connectTab = tab => {
|
||||||
const currentPort = this.#ports.get(tab.id)
|
const currentPort = this.#ports.get(tab.id)
|
||||||
@ -40,41 +40,41 @@ export class BackgroundMessenger {
|
|||||||
const port = chrome.tabs.connect(tab.id)
|
const port = chrome.tabs.connect(tab.id)
|
||||||
this.#registerPort(tab.id, port)
|
this.#registerPort(tab.id, port)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
disconnectTab = tabId => {
|
disconnectTab = tabId => {
|
||||||
const port = this.#ports.get(tabId)
|
const port = this.#ports.get(tabId)
|
||||||
if (port) {
|
if (port) {
|
||||||
this.#unregisterPort(tabId, port)
|
this.#unregisterPort(tabId, port)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
postMessage = (tab, action) => {
|
postMessage = (tab, action) => {
|
||||||
const port = this.#ports.get(tab.id)
|
const port = this.#ports.get(tab.id)
|
||||||
if (port) {
|
if (port) {
|
||||||
port.postMessage(action)
|
port.postMessage(action)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
once = (type, handler) => {
|
once = (type, handler) => {
|
||||||
this.#onceHandlers.set(type, handler)
|
this.#onceHandlers.set(type, handler)
|
||||||
};
|
}
|
||||||
|
|
||||||
on = (type, handler) => {
|
on = (type, handler) => {
|
||||||
this.#handlers.set(type, handler)
|
this.#handlers.set(type, handler)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContentMessenger {
|
export class ContentMessenger {
|
||||||
#port;
|
#port
|
||||||
#handlers = new Map();
|
#handlers = new Map()
|
||||||
|
|
||||||
#handler = action => {
|
#handler = action => {
|
||||||
const handler = this.#handlers.get(action.type)
|
const handler = this.#handlers.get(action.type)
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler(action)
|
handler(action)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
constructor(port) {
|
constructor(port) {
|
||||||
this.#port = port
|
this.#port = port
|
||||||
@ -85,15 +85,15 @@ export class ContentMessenger {
|
|||||||
if (this.#port) {
|
if (this.#port) {
|
||||||
this.#port.postMessage(action)
|
this.#port.postMessage(action)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
on = (type, handler) => {
|
on = (type, handler) => {
|
||||||
this.#handlers.set(type, handler)
|
this.#handlers.set(type, handler)
|
||||||
};
|
}
|
||||||
|
|
||||||
stop = () => {
|
stop = () => {
|
||||||
this.#port.onMessage.removeListener(this.#handler)
|
this.#port.onMessage.removeListener(this.#handler)
|
||||||
this.#port = null
|
this.#port = null
|
||||||
this.#handlers.clear()
|
this.#handlers.clear()
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user