Skip to content

Commit

Permalink
Merge pull request #63 from Jaewoook/feat/developer-contact
Browse files Browse the repository at this point in the history
feat: feedback popover
  • Loading branch information
Jaewoook committed Aug 26, 2020
2 parents 667e52b + 7042e6d commit 2c65f88
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 10 deletions.
12 changes: 12 additions & 0 deletions background.tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"noEmit": false,
"outDir": "./build/background",
"isolatedModules": false
},
"include": [
"background/*"
]
}
6 changes: 6 additions & 0 deletions background/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
extends: "../.eslintrc.js",
parserOptions: {
project: "./background.tsconfig.json",
},
};
1 change: 1 addition & 0 deletions background/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("background test");
3 changes: 2 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
"24": "icons/icon_24.png",
"32": "icons/icon_32.png"
}
}
},
"content_security_policy": "script-src 'self' https://www.google-analytics.com; object-src 'self'"
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"build": "cross-env REACT_APP_ENV=production react-scripts build",
"dev": "cross-env REACT_APP_ENV=development react-scripts start",
"lint": "eslint . --ext .js,.ts,.jsx,.tsx",
"lint": "eslint src --ext .js,.ts,.jsx,.tsx",
"prepackage": "yarn build",
"package": "node scripts/CreatePackage.js",
"postpackage": "node scripts/CreateDistribution.js"
Expand Down
4 changes: 4 additions & 0 deletions public/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500&display=swap');
</style>
<script src="/analytics.js"></script>
</head>
<body>
<div id="root"></div>
Expand Down
9 changes: 8 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const App = (props: Props) => {
setShowLoading(true);
setAddressData([]);

window.ga("send", "event", "address", "search", searchValue);
address.search({
countPerPage: "20",
currentPage: "1",
Expand Down Expand Up @@ -154,18 +155,21 @@ export const App = (props: Props) => {
switch (type) {
case "eng":
setShowEngAddr(!showEngAddr);
window.ga("send", "event", "option", !showEngAddr ? "on" : "off", "영문주소 표시");
await settings?.updateSettings({
searchResult: { showEng: !showEngAddr },
});
break;
case "road":
setShowRoadAddr(!showRoadAddr);
window.ga("send", "event", "option", !showRoadAddr ? "on" : "off", "도로명주소 표시");
await settings?.updateSettings({
searchResult: { showRoad: !showRoadAddr },
});
break;
case "legacy":
setShowLegacyAddr(!showLegacyAddr);
window.ga("send", "event", "option", !showLegacyAddr ? "on" : "off", "지번주소 표시");
await settings?.updateSettings({
searchResult: { showLegacy: !showLegacyAddr },
});
Expand All @@ -187,9 +191,12 @@ export const App = (props: Props) => {
}

setShowLoading(true);
const nextPage = (Number.parseInt(address.previousSearchKey?.currentPage!) + 1).toString();

window.ga("send", "event", "address", "search", "추가 데이터 로드", Number.parseInt(nextPage));
address.search({
...address.previousSearchKey!,
currentPage: (Number.parseInt(address.previousSearchKey?.currentPage!) + 1).toString(),
currentPage: nextPage,
}, true).then((data) => {
setAddressData(data);
}).catch((err) => {
Expand Down
13 changes: 8 additions & 5 deletions src/components/AddressList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable jsx-a11y/accessible-emoji */
import React from "react";
import styled from "styled-components";
import { Collapse, Typography } from "antd";
import { AddressData } from "../../AddressManager";
import { ClickToCopyText } from "../ClickToCopyText";
import { FeedbackPopover } from "../FeedbackPopover";
import "./AddressList.css";

interface Props {
Expand All @@ -28,7 +30,8 @@ export const AddressList = (props: Props) => {
if (!data || !data.length) {
return <EmptyText type="secondary">
검색 결과가 없습니다.<br />
<span>(검색어 예시: 강남대로, 자양동, 초성 검색 가능)</span>
<span>(검색어 예시: 강남대로, 자양동, 초성 검색 가능)</span><br />
<FeedbackPopover />
</EmptyText>;
}
return (
Expand All @@ -38,31 +41,31 @@ export const AddressList = (props: Props) => {
<div>
<Typography.Paragraph className="addr-label">우편번호:</Typography.Paragraph>
<div>
<ClickToCopyText>
<ClickToCopyText analytics="우편번호">
{row.zipNo}
</ClickToCopyText>
</div>
</div>
{showRoadAddr ? <div>
<Typography.Paragraph className="addr-label">도로명주소:</Typography.Paragraph>
<div>
<ClickToCopyText>
<ClickToCopyText analytics="도로명주소">
{row.roadAddr}
</ClickToCopyText>
</div>
</div> : null}
{showLegacyAddr ? <div>
<Typography.Paragraph className="addr-label">지번주소:</Typography.Paragraph>
<div>
<ClickToCopyText>
<ClickToCopyText analytics="지번주소">
{row.jibunAddr}
</ClickToCopyText>
</div>
</div> : null}
{showEngAddr ? <div>
<Typography.Paragraph className="addr-label">영문주소:</Typography.Paragraph>
<div>
<ClickToCopyText>
<ClickToCopyText analytics="영문주소">
{row.engAddr}
</ClickToCopyText>
</div>
Expand Down
6 changes: 4 additions & 2 deletions src/components/ClickToCopyText/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import "./ClickToCopyText.css";

interface ClickToCopyTextProps {
children: string;
analytics?: "우편번호" | "도로명주소" | "지번주소" | "영문주소";
}

export const ClickToCopyText: React.FC<ClickToCopyTextProps> = ({ children }: ClickToCopyTextProps) => {
export const ClickToCopyText: React.FC<ClickToCopyTextProps> = ({ children, analytics }: ClickToCopyTextProps) => {
const [copied, setCopied] = React.useState(false);

const handleCopyClick = React.useCallback(() => {
setCopied(true);
copy(children);
}, [setCopied, children]);
window.ga("send", "event", "address", "copy", `${analytics} 복사`);
}, [setCopied, analytics, children]);

const handleVisibleChange = React.useCallback((visible: boolean) => {
if (!visible) {
Expand Down
75 changes: 75 additions & 0 deletions src/components/FeedbackPopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-disable jsx-a11y/accessible-emoji */
import React from "react";
import styled from "styled-components";
import { Button, Input, Popover, Typography } from "antd";
import axios from "axios";

const EMAIL_API = "https://api.jaewook.me/email/addr-extension-feedback";

const PopoverTitleWrapper = styled.div`
display: flex;
justify-content: center;
`;

const PopoverTitle = (props: { children: React.ReactNode; }) => {
return <PopoverTitleWrapper>{props.children}</PopoverTitleWrapper>;
};

const FeedbackSenderWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
> button.ant-btn {
margin-top: 8px;
width: 100%;
}
`;

const PopoverContentStyle = {
width: "270px",
};

const FeedbackForm = () => {
const [message, setMessage] = React.useState("");
const [sending, setSending] = React.useState(false);
const [sent, setSent] = React.useState(false);

const handleSendClick = React.useCallback(async () => {
if (sent) {
return;
}
setSending(true);
try {
await axios.post(EMAIL_API, { feedbackContent: message });
setSent(true);
} catch (err) {
console.error(err);
} finally {
setSending(false);
}
}, [message, sent, setSent, setSending]);
return <FeedbackSenderWrapper>
<Input.TextArea disabled={sent || sending}
value={message}
rows={3}
placeholder="이곳에 피드백 내용을 입력해주세요.&#10;작성해주신 소중한 피드백이 더 좋은 주소검색을 만들어요!"
onChange={(ev) => setMessage(ev.target.value)} />
<Button disabled={sent || sending} type="primary" onClick={handleSendClick}>
{!sent ? "보내기 🎉" : "피드백 전달 완료! 💛"}
</Button>
</FeedbackSenderWrapper>;
};

export const FeedbackPopover = () => {
return (
<Popover
placement="top"
overlayStyle={PopoverContentStyle}
title={<PopoverTitle>피드백 보내기</PopoverTitle>}
content={<FeedbackForm />}
>
<Typography.Text keyboard>피드백 보내기</Typography.Text>
</Popover>
);
};
7 changes: 7 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ import { getRuntime, isProduction } from "./utils";
import { AddressManager } from "./AddressManager";
import { SettingsManager, Settings, DEFAULT_SETTINGS } from "./SettingsManager";

// inject NODE_ENV variable into window object
window.__ENV__ = {
NODE_ENV: process.env.REACT_APP_ENV as string,
};

if (isProduction()) {
window.ga("create", "UA-108816190-2", "auto");
window.ga("set", "checkProtocolTask", null);
window.ga("send", "pageview", "/");
Sentry.init({ dsn: "https://6b96accd47ff467da8394a51da93d909@o415139.ingest.sentry.io/5305794" });
} else {
console.info("Google Analytics disabled because runtime does not running in production.");
window.ga = function() {};
}

let settings = null;
Expand Down
1 change: 1 addition & 0 deletions src/react-app-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ interface Window {
__ENV__: {
NODE_ENV: string;
};
ga: any;
}

0 comments on commit 2c65f88

Please sign in to comment.