diff --git a/frontend/src/components/Board/BuyParts/Bom.jsx b/frontend/src/components/Board/BuyParts/Bom.tsx
similarity index 82%
rename from frontend/src/components/Board/BuyParts/Bom.jsx
rename to frontend/src/components/Board/BuyParts/Bom.tsx
index 955942b56f..58298e0446 100644
--- a/frontend/src/components/Board/BuyParts/Bom.jsx
+++ b/frontend/src/components/Board/BuyParts/Bom.tsx
@@ -2,11 +2,10 @@ import React, { useEffect, useState } from 'react'
import { Icon, Table } from 'semantic-ui-react'
import DoubleScrollBar from 'react-double-scrollbar'
-import { array, bool, func, number, string } from 'prop-types'
import styles from './Bom.module.scss'
import TsvTable from './TsvTable'
-const Bom = ({ length, parts, tsv }) => {
+const Bom = ({ length, parts, tsv }: BomProps) => {
const [diff, setDiff] = useState(0)
const [collapsed, setCollapsed] = useState(true)
@@ -32,7 +31,7 @@ const Bom = ({ length, parts, tsv }) => {
)
}
-const ExpandBom = ({ diff, collapsed, setCollapsed }) => {
+const ExpandBom = ({ diff, collapsed, setCollapsed }: ExpandBomProps) => {
const summary =
diff > 0 && collapsed ? (
@@ -71,16 +70,16 @@ const ExpandBom = ({ diff, collapsed, setCollapsed }) => {
)
}
-Bom.propTypes = {
- length: number.isRequired,
- parts: array.isRequired,
- tsv: string.isRequired,
+interface BomProps {
+ length: number
+ parts: Array
+ tsv: string
}
-ExpandBom.propTypes = {
- diff: number.isRequired,
- collapsed: bool.isRequired,
- setCollapsed: func.isRequired,
+interface ExpandBomProps {
+ diff: number
+ collapsed: boolean
+ setCollapsed: (collapsed: boolean) => void
}
export default Bom
diff --git a/frontend/src/components/Board/BuyParts/DirectStores.jsx b/frontend/src/components/Board/BuyParts/DirectStores.tsx
similarity index 95%
rename from frontend/src/components/Board/BuyParts/DirectStores.jsx
rename to frontend/src/components/Board/BuyParts/DirectStores.tsx
index bc3fde2579..e8e5791073 100644
--- a/frontend/src/components/Board/BuyParts/DirectStores.jsx
+++ b/frontend/src/components/Board/BuyParts/DirectStores.tsx
@@ -1,11 +1,10 @@
import React, { useEffect, useState, useCallback } from 'react'
-import { array, number } from 'prop-types'
import DigikeyData from '1-click-bom-minimal/lib/data/digikey.json'
import FarnellData from '1-click-bom-minimal/lib/data/farnell.json'
import countriesData from '1-click-bom-minimal/lib/data/countries.json'
-const DirectStores = ({ items, multiplier }) => {
+const DirectStores = ({ items, multiplier }: DirectStoresProps) => {
const [countryCode, setCountryCode] = useState('Other')
const [digikeyParts, setDigikeyParts] = useState([])
const [farnellParts, setFarnellParts] = useState([])
@@ -132,8 +131,8 @@ const DirectStores = ({ items, multiplier }) => {
)
}
-DirectStores.propTypes = {
- items: array.isRequired,
- multiplier: number.isRequired,
+interface DirectStoresProps {
+ items: Array
+ multiplier: number
}
export default DirectStores
diff --git a/frontend/src/components/Board/BuyParts/InstallPrompt.jsx b/frontend/src/components/Board/BuyParts/InstallPrompt.jsx
deleted file mode 100644
index 13546be102..0000000000
--- a/frontend/src/components/Board/BuyParts/InstallPrompt.jsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import Link from 'next/link'
-
-import { Icon, Message } from 'semantic-ui-react'
-import { func, string } from 'prop-types'
-
-import BrowserVersion from '@utils/getBrowserVersion'
-import styles from './InstallPrompt.module.scss'
-
-export const install1ClickBOM = () => {
- const version = BrowserVersion()
- let onClick
- if (/Chrome/.test(version)) {
- onClick = () => {
- window.plausible('Install Extension')
- window.open(
- 'https://chrome.google.com/webstore/detail/kitspace-1-click-bom/mflpmlediakefinapghmabapjeippfdi',
- )
- }
- } else if (/Firefox/.test(version)) {
- onClick = () => {
- window.plausible('Install Extension')
- window.open('https://addons.mozilla.org/en-US/firefox/addon/1clickbom')
- }
- } else {
- onClick = () => {
- window.plausible('Install Extension')
- window.open('/1-click-bom', '_self')
- }
- }
- return onClick()
-}
-
-const InstallPrompt = ({ extensionPresence }) => {
- const [isCompatible, setIsCompatible] = useState(true)
- const [timedOut, setTimedOut] = useState(false)
-
- const getCompatibility = () => {
- if (typeof navigator === 'undefined') {
- return true
- }
- if (/Mobile/i.test(navigator.userAgent)) {
- return false
- }
- const version = BrowserVersion()
- return /Chrome/.test(version) || /Firefox/.test(version)
- }
-
- useEffect(() => {
- setTimedOut(() => {
- setTimedOut(true)
- setIsCompatible(getCompatibility())
- }, 5000)
- }, [])
-
- if (extensionPresence === 'present') {
- return
- }
- if (timedOut) {
- return isCompatible ? (
-
- ) : (
-
- )
- }
- return null
-}
-
-const PleaseInstall = ({ install1ClickBOMCallback }) => (
-
-
- Please{' '}
- {' '}
- make full use of this feature.
-
-)
-
-const NotCompatible = () => (
-
-
- Sorry, the{' '}
-
- 1-click BOM extension
- {' '}
- is not yet available for your browser. Only the Digikey add-to-cart links work
- fully, Farnell and Newark should work but the references will not be added as
- line-notes.
-
-)
-
-InstallPrompt.propTypes = {
- extensionPresence: string.isRequired,
-}
-
-PleaseInstall.propTypes = {
- install1ClickBOMCallback: func.isRequired,
-}
-
-export default InstallPrompt
diff --git a/frontend/src/components/Board/BuyParts/InstallPrompt.module.scss b/frontend/src/components/Board/BuyParts/InstallPrompt.module.scss
deleted file mode 100644
index 7345ea0159..0000000000
--- a/frontend/src/components/Board/BuyParts/InstallPrompt.module.scss
+++ /dev/null
@@ -1,14 +0,0 @@
-@import '../../colors.scss';
-
-.extensionLinkButton {
- background: none!important;
- border: none;
- padding: 0!important;
- color:$mine-shaft;
- font-weight: bold;
- cursor: pointer;
-}
-
-.extensionLinkButton:hover {
- text-decoration: underline;
-}
\ No newline at end of file
diff --git a/frontend/src/components/Board/BuyParts/index.module.scss b/frontend/src/components/Board/BuyParts/index.module.scss
index d62ee2a050..1e4856d321 100644
--- a/frontend/src/components/Board/BuyParts/index.module.scss
+++ b/frontend/src/components/Board/BuyParts/index.module.scss
@@ -1,6 +1,7 @@
@import '../../breakpoint.scss';
.notSelectable {
+ -webkit-user-select: none;
user-select: none;
cursor: default;
}
diff --git a/frontend/src/components/Board/BuyParts/index.jsx b/frontend/src/components/Board/BuyParts/index.tsx
similarity index 70%
rename from frontend/src/components/Board/BuyParts/index.jsx
rename to frontend/src/components/Board/BuyParts/index.tsx
index 1ddcbab8cf..f5842bbebe 100644
--- a/frontend/src/components/Board/BuyParts/index.jsx
+++ b/frontend/src/components/Board/BuyParts/index.tsx
@@ -1,19 +1,15 @@
import React, { useEffect, useState } from 'react'
-import { array, bool, func, number, string } from 'prop-types'
import OneClickBom from '1-click-bom-minimal'
import { Header, Icon, Segment, Input, Button } from 'semantic-ui-react'
import Bom from './Bom'
-import InstallPrompt, { install1ClickBOM } from './InstallPrompt'
import DirectStores from './DirectStores'
import styles from './index.module.scss'
-const BuyParts = ({ projectFullName, lines, parts }) => {
- const [extensionPresence, setExtensionPresence] = useState('unknown')
+const BuyParts = ({ projectFullName, lines, parts }: BuyPartsProps) => {
const [buyMultiplier, setBuyMultiplier] = useState(1)
const [mult, setMult] = useState(1)
const [buyAddPercent, setBuyAddPercent] = useState(0)
- const [adding, setAdding] = useState({})
const buyParts = distributor => {
window.plausible('Buy Parts', {
@@ -23,17 +19,6 @@ const BuyParts = ({ projectFullName, lines, parts }) => {
multiplier: mult,
},
})
- window.postMessage(
- {
- from: 'page',
- message: 'quickAddToCart',
- value: {
- retailer: distributor,
- multiplier: mult,
- },
- },
- '*',
- )
}
const retailerList = OneClickBom.getRetailers()
@@ -52,10 +37,7 @@ const BuyParts = ({ projectFullName, lines, parts }) => {
return (
buyParts(name)}
- extensionPresence={name === 'Digikey' ? 'absent' : extensionPresence}
- install1ClickBOM={install1ClickBOM}
name={name}
numberOfLines={numberOfLines}
numberOfParts={numberOfParts}
@@ -67,29 +49,6 @@ const BuyParts = ({ projectFullName, lines, parts }) => {
})
.filter(l => l != null)
- useEffect(() => {
- // extension communication
- window.addEventListener(
- 'message',
- event => {
- if (event.source !== window) {
- return
- }
- if (event.data.from === 'extension') {
- setExtensionPresence('present')
- switch (event.data.message) {
- case 'updateAddingState':
- setAdding(event.data.value)
- break
- default:
- break
- }
- }
- },
- false,
- )
- }, [])
-
useEffect(() => {
const multi = buyMultiplier
if (Number.isNaN(multi) || multi < 1) {
@@ -110,6 +69,7 @@ const BuyParts = ({ projectFullName, lines, parts }) => {
return OneClickBom.writeTSV(linesMult)
}
const hasPurchasableParts = retailerButtons.length !== 0
+
return (
@@ -118,7 +78,6 @@ const BuyParts = ({ projectFullName, lines, parts }) => {
{hasPurchasableParts ? (
<>
-
(
+}: AdjustQuantityProps) => (
Adjust quantity:
@@ -207,26 +166,11 @@ const AdjustQuantity = ({
const RetailerButton = ({
name,
buyParts,
- install1ClickBOM,
- extensionPresence,
numberOfLines,
totalLines,
numberOfParts,
- adding,
-}) => {
- let onClick = buyParts
- // if the extension is not here fallback to direct submissions
- if (extensionPresence !== 'present' && typeof document !== 'undefined') {
- onClick = () => {
- const form = document.getElementById(`${name}Form`)
- if (form) {
- form.submit()
- } else {
- install1ClickBOM()
- }
- }
- }
- const color = numberOfLines === totalLines ? 'green' : 'pink'
+}: RetailerButtonProps) => {
+ const color = 'green'
return (
)
}
-const StoreIcon = ({ retailer }) => {
+const StoreIcon = ({ retailer }: StoreIconProps) => {
const imgHref = `/distributor_icons/${retailer.toLowerCase()}.png`
return (
/*
@@ -283,35 +226,29 @@ const StoreIcon = ({ retailer }) => {
)
}
-BuyParts.propTypes = {
- projectFullName: string.isRequired,
- lines: array.isRequired,
- parts: array.isRequired,
+interface BuyPartsProps {
+ projectFullName: string
+ lines: Array
+ parts: Array
}
-AdjustQuantity.propTypes = {
- buyMultiplier: number.isRequired,
- setBuyMultiplier: func.isRequired,
- buyAddPercent: number.isRequired,
- setBuyAddPercent: func.isRequired,
+interface AdjustQuantityProps {
+ buyMultiplier: number
+ setBuyMultiplier: (v: number) => void
+ buyAddPercent: number
+ setBuyAddPercent: (v: number) => void
}
-RetailerButton.propTypes = {
- name: string.isRequired,
- buyParts: func.isRequired,
- install1ClickBOM: func.isRequired,
- extensionPresence: string.isRequired,
- numberOfLines: number.isRequired,
- totalLines: number.isRequired,
- numberOfParts: number.isRequired,
- adding: bool,
-}
-RetailerButton.defaultProps = {
- adding: false,
+interface RetailerButtonProps {
+ name: string
+ buyParts: () => void
+ numberOfLines: number
+ totalLines: number
+ numberOfParts: number
}
-StoreIcon.propTypes = {
- retailer: string.isRequired,
+interface StoreIconProps {
+ retailer: string
}
export default BuyParts
diff --git a/frontend/src/index.d.ts b/frontend/src/index.d.ts
new file mode 100644
index 0000000000..f885d596b6
--- /dev/null
+++ b/frontend/src/index.d.ts
@@ -0,0 +1,10 @@
+export {}
+
+declare global {
+ interface Window {
+ plausible: (
+ tag: string,
+ data: { props: { project: string; vendor: string; multiplier?: number } },
+ ) => void
+ }
+}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index a2916fc8e3..342949cf24 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -24,6 +24,13 @@
"jsx": "preserve",
"incremental": true
},
- "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "next-env.d.ts"],
+ "include": [
+ "**/*.js",
+ "**/*.jsx",
+ "**/*.ts",
+ "**/*.tsx",
+ "next-env.d.ts",
+ "src/index.d.ts"
+ ],
"exclude": ["node_modules"]
}