From 691f24695f26bff7165e75ef23d31853afeb1728 Mon Sep 17 00:00:00 2001 From: Aokashi Date: Sat, 15 Aug 2020 10:41:23 +0900 Subject: [PATCH 1/4] =?UTF-8?q?getPartsNumberOnTarget=E3=81=A7=E6=83=B3?= =?UTF-8?q?=E5=AE=9A=E5=A4=96=E3=81=AE=E5=80=A4=E3=81=8C=E5=85=A5=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AE=E5=87=A6=E7=90=86=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/maker/src/common/MapView/MapCanvas.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/maker/src/common/MapView/MapCanvas.tsx b/packages/maker/src/common/MapView/MapCanvas.tsx index 2546760..468b479 100644 --- a/packages/maker/src/common/MapView/MapCanvas.tsx +++ b/packages/maker/src/common/MapView/MapCanvas.tsx @@ -111,8 +111,12 @@ const MapCanvas: React.FC = props => { * 指定した座標から各パーツ種類のパーツ番号を取得します * @param chipX * @param chipY + * @returns その座標にあるパーツ番号 (範囲外の場合は 0) */ const getPartsNumberOnTarget = (chipX: number, chipY: number, type: PartsType) => { + if (chipX < 0 || chipX >= mapWidth || chipY < 0 || chipY >= mapWidth) { + return 0; + } switch (type) { case PartsType.MAP: return map[chipY][chipX]; From afaa191fcdf802146d5c6e4d742603134b9305b7 Mon Sep 17 00:00:00 2001 From: Aokashi Date: Sat, 15 Aug 2020 12:21:27 +0900 Subject: [PATCH 2/4] =?UTF-8?q?modal=20=E3=83=A2=E3=82=B8=E3=83=A5?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=82=92=E6=96=B0=E8=A8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/maker/src/App.tsx | 30 ++++++++++++--------- packages/maker/src/State.ts | 10 ++++--- packages/maker/src/info/InfoPanelState.ts | 6 ++--- packages/maker/src/modal/ModalStates.ts | 26 ++++++++++++++++++ packages/maker/src/modal/ModalView.tsx | 33 +++++++++++++++++++++++ 5 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 packages/maker/src/modal/ModalStates.ts create mode 100644 packages/maker/src/modal/ModalView.tsx diff --git a/packages/maker/src/App.tsx b/packages/maker/src/App.tsx index f54d387..26e4095 100644 --- a/packages/maker/src/App.tsx +++ b/packages/maker/src/App.tsx @@ -8,6 +8,7 @@ import SplitPane from 'react-split-pane'; import './common/SplitPane.scss'; import { connect, MapStateToProps } from 'react-redux'; import { StoreType } from './State'; +import ModalView from './modal/ModalView'; interface StateProps { isOpened: boolean @@ -39,20 +40,23 @@ class App extends React.Component { public render() { return ( -
-
- + <> + +
+
+ +
+
+ + + + +
+
+ +
-
- - - - -
-
- -
-
+ ); } } diff --git a/packages/maker/src/State.ts b/packages/maker/src/State.ts index b36dc9b..3bd9679 100644 --- a/packages/maker/src/State.ts +++ b/packages/maker/src/State.ts @@ -2,6 +2,7 @@ import { LoadState, LoadReducer, INITIAL_STATE as LOAD_INITIAL_STATE } from "./l import { PartsState, INITIAL_STATE as PARTS_INITIAL_STATE, ObjectPartsReducer, MapPartsReducer } from "./parts/PartsState"; import { MapState, INITIAL_STATE as MAP_INITIAL_STATE, MapReducer } from "./map/MapStates"; import { InfoPanelState, INITIAL_STATE as INFOPANEL_INITIAL_STATE, InfoPanelReducer } from "./info/InfoPanelState"; +import { ModalState, INITIAL_STATE as MODAL_INITIAL_STATE, ModalReducer } from "./modal/ModalStates"; import { WWAData } from "@wwawing/common-interface"; import { WWADataReducer } from "./wwadata/WWADataState"; import { createStore, applyMiddleware } from "redux"; @@ -21,7 +22,8 @@ export interface StoreType { objParts: PartsState, mapParts: PartsState, imageUrl: string|null, - info: InfoPanelState + info: InfoPanelState, + modal: ModalState } /** @@ -35,7 +37,8 @@ const INITIAL_STATE: StoreType = { objParts: PARTS_INITIAL_STATE, mapParts: PARTS_INITIAL_STATE, imageUrl: null, - info: INFOPANEL_INITIAL_STATE + info: INFOPANEL_INITIAL_STATE, + modal: MODAL_INITIAL_STATE } const actionCreator = actionCreatorFactory(); @@ -86,7 +89,8 @@ const reducer = reducerWithInitialState(INITIAL_STATE) map: MapReducer(state.map, action), objParts: ObjectPartsReducer(state.objParts, action), mapParts: MapPartsReducer(state.mapParts, action), - info: InfoPanelReducer(state.info, action) + info: InfoPanelReducer(state.info, action), + modal: ModalReducer(state.modal, action) })) export const Store = createStore( diff --git a/packages/maker/src/info/InfoPanelState.ts b/packages/maker/src/info/InfoPanelState.ts index b0c2dfe..e75b9e2 100644 --- a/packages/maker/src/info/InfoPanelState.ts +++ b/packages/maker/src/info/InfoPanelState.ts @@ -1,6 +1,7 @@ import actionCreatorFactory from "typescript-fsa"; import { reducerWithInitialState } from "typescript-fsa-reducers"; import { PartsType } from "../classes/WWAData"; +import { showError } from "../modal/ModalStates"; /** * InfoPanel のモードです。 @@ -49,14 +50,13 @@ export const InfoPanelReducer = reducerWithInitialState(INITIAL_STATE) viewMode: payload.mode })) .case(showPartsEdit, (state, payload) => { - // TODO: Reducer の中にアラートを表示するのはちょっと良くないかもしれない。別の場所に移しておきたい。 if (payload.number === 0) { switch (payload.type) { case PartsType.OBJECT: - alert("パーツ番号0の物体は編集できません。\nこのパーツはマップの物体を消去するときに指定してください。"); + showError({ errorMessage: "パーツ番号0の物体は編集できません。\nこのパーツはマップの物体を消去するときに指定してください。" }); break; case PartsType.MAP: - alert("パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。"); + showError({ errorMessage: "パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。" }) } return state; } diff --git a/packages/maker/src/modal/ModalStates.ts b/packages/maker/src/modal/ModalStates.ts new file mode 100644 index 0000000..0e3f717 --- /dev/null +++ b/packages/maker/src/modal/ModalStates.ts @@ -0,0 +1,26 @@ +import { reducerWithInitialState } from "typescript-fsa-reducers"; +import actionCreatorFactory from "typescript-fsa"; + +export type ModalState = { + type: "NONE" +} | { + type: "ERROR", + message: string +}; + +export const INITIAL_STATE: ModalState = { + type: "NONE" +}; + +const actionCreator = actionCreatorFactory(); +/** + * エラーを発生させます。 + */ +export const showError = actionCreator<{ errorMessage: string }>("SHOW_ERROR"); + +export const ModalReducer = reducerWithInitialState(INITIAL_STATE) + .case(showError, (state, params) => ({ + ...state, + type: "ERROR", + message: params.errorMessage + })) diff --git a/packages/maker/src/modal/ModalView.tsx b/packages/maker/src/modal/ModalView.tsx new file mode 100644 index 0000000..e9f77dc --- /dev/null +++ b/packages/maker/src/modal/ModalView.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { Modal } from "semantic-ui-react"; +import { useSelector } from "react-redux"; +import { ModalState } from "./ModalStates"; + +/** + * Modal の表示について + * Modal の内容は ModalState.type によって大きく異なるため、 type に従って内容を描画するようにしています。 + */ +const ModalView: React.FC<{}> = () => { + const modalType = useSelector(state => state.modal.type); + const ModalContent = ModalContentTable[modalType]; + + return ( + + + + ); +}; + +/** + * Modal の内容表示を定義するコンポーネントの型です。 + */ +type ModalContentComponent = React.FC<{}>; + +const ModalContentTable: { [type in ModalState["type"]]: ModalContentComponent } = { + "NONE": () => <>, + "ERROR": () => <> +}; + +export default ModalView; From f8f0a41e7c1abe9a281a67a146040f01c746f5fe Mon Sep 17 00:00:00 2001 From: Aokashi Date: Sat, 15 Aug 2020 20:55:55 +0900 Subject: [PATCH 3/4] =?UTF-8?q?modal=20=E3=82=92=20notification=20?= =?UTF-8?q?=E3=81=AB=E6=94=B9=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/maker/src/App.tsx | 4 +-- packages/maker/src/State.ts | 8 ++--- packages/maker/src/info/InfoPanelState.ts | 6 ++-- packages/maker/src/modal/ModalStates.ts | 26 --------------- packages/maker/src/modal/ModalView.tsx | 33 ------------------- .../src/notification/NotificationStates.ts | 31 +++++++++++++++++ .../src/notification/NotificationView.tsx | 12 +++++++ .../notification/types/ErrorNotification.tsx | 30 +++++++++++++++++ 8 files changed, 82 insertions(+), 68 deletions(-) delete mode 100644 packages/maker/src/modal/ModalStates.ts delete mode 100644 packages/maker/src/modal/ModalView.tsx create mode 100644 packages/maker/src/notification/NotificationStates.ts create mode 100644 packages/maker/src/notification/NotificationView.tsx create mode 100644 packages/maker/src/notification/types/ErrorNotification.tsx diff --git a/packages/maker/src/App.tsx b/packages/maker/src/App.tsx index 26e4095..61fe8f8 100644 --- a/packages/maker/src/App.tsx +++ b/packages/maker/src/App.tsx @@ -8,7 +8,7 @@ import SplitPane from 'react-split-pane'; import './common/SplitPane.scss'; import { connect, MapStateToProps } from 'react-redux'; import { StoreType } from './State'; -import ModalView from './modal/ModalView'; +import NotificationView from './notification/NotificationView'; interface StateProps { isOpened: boolean @@ -41,7 +41,7 @@ class App extends React.Component { public render() { return ( <> - +
diff --git a/packages/maker/src/State.ts b/packages/maker/src/State.ts index 3bd9679..b21d57e 100644 --- a/packages/maker/src/State.ts +++ b/packages/maker/src/State.ts @@ -2,7 +2,7 @@ import { LoadState, LoadReducer, INITIAL_STATE as LOAD_INITIAL_STATE } from "./l import { PartsState, INITIAL_STATE as PARTS_INITIAL_STATE, ObjectPartsReducer, MapPartsReducer } from "./parts/PartsState"; import { MapState, INITIAL_STATE as MAP_INITIAL_STATE, MapReducer } from "./map/MapStates"; import { InfoPanelState, INITIAL_STATE as INFOPANEL_INITIAL_STATE, InfoPanelReducer } from "./info/InfoPanelState"; -import { ModalState, INITIAL_STATE as MODAL_INITIAL_STATE, ModalReducer } from "./modal/ModalStates"; +import { NotificationState, INITIAL_STATE as NOTIFICATION_INITIAL_STATE, NotificationReducer } from "./notification/NotificationStates"; import { WWAData } from "@wwawing/common-interface"; import { WWADataReducer } from "./wwadata/WWADataState"; import { createStore, applyMiddleware } from "redux"; @@ -23,7 +23,7 @@ export interface StoreType { mapParts: PartsState, imageUrl: string|null, info: InfoPanelState, - modal: ModalState + notification: NotificationState } /** @@ -38,7 +38,7 @@ const INITIAL_STATE: StoreType = { mapParts: PARTS_INITIAL_STATE, imageUrl: null, info: INFOPANEL_INITIAL_STATE, - modal: MODAL_INITIAL_STATE + notification: NOTIFICATION_INITIAL_STATE } const actionCreator = actionCreatorFactory(); @@ -90,7 +90,7 @@ const reducer = reducerWithInitialState(INITIAL_STATE) objParts: ObjectPartsReducer(state.objParts, action), mapParts: MapPartsReducer(state.mapParts, action), info: InfoPanelReducer(state.info, action), - modal: ModalReducer(state.modal, action) + modal: NotificationReducer(state.notification, action) })) export const Store = createStore( diff --git a/packages/maker/src/info/InfoPanelState.ts b/packages/maker/src/info/InfoPanelState.ts index e75b9e2..0a08037 100644 --- a/packages/maker/src/info/InfoPanelState.ts +++ b/packages/maker/src/info/InfoPanelState.ts @@ -1,7 +1,7 @@ import actionCreatorFactory from "typescript-fsa"; import { reducerWithInitialState } from "typescript-fsa-reducers"; import { PartsType } from "../classes/WWAData"; -import { showError } from "../modal/ModalStates"; +import { showError } from "../notification/types/ErrorNotification"; /** * InfoPanel のモードです。 @@ -53,10 +53,10 @@ export const InfoPanelReducer = reducerWithInitialState(INITIAL_STATE) if (payload.number === 0) { switch (payload.type) { case PartsType.OBJECT: - showError({ errorMessage: "パーツ番号0の物体は編集できません。\nこのパーツはマップの物体を消去するときに指定してください。" }); + showError("パーツ番号0の物体は編集できません。\nこのパーツはマップの物体を消去するときに指定してください。"); break; case PartsType.MAP: - showError({ errorMessage: "パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。" }) + showError("パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。"); } return state; } diff --git a/packages/maker/src/modal/ModalStates.ts b/packages/maker/src/modal/ModalStates.ts deleted file mode 100644 index 0e3f717..0000000 --- a/packages/maker/src/modal/ModalStates.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { reducerWithInitialState } from "typescript-fsa-reducers"; -import actionCreatorFactory from "typescript-fsa"; - -export type ModalState = { - type: "NONE" -} | { - type: "ERROR", - message: string -}; - -export const INITIAL_STATE: ModalState = { - type: "NONE" -}; - -const actionCreator = actionCreatorFactory(); -/** - * エラーを発生させます。 - */ -export const showError = actionCreator<{ errorMessage: string }>("SHOW_ERROR"); - -export const ModalReducer = reducerWithInitialState(INITIAL_STATE) - .case(showError, (state, params) => ({ - ...state, - type: "ERROR", - message: params.errorMessage - })) diff --git a/packages/maker/src/modal/ModalView.tsx b/packages/maker/src/modal/ModalView.tsx deleted file mode 100644 index e9f77dc..0000000 --- a/packages/maker/src/modal/ModalView.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; -import { Modal } from "semantic-ui-react"; -import { useSelector } from "react-redux"; -import { ModalState } from "./ModalStates"; - -/** - * Modal の表示について - * Modal の内容は ModalState.type によって大きく異なるため、 type に従って内容を描画するようにしています。 - */ -const ModalView: React.FC<{}> = () => { - const modalType = useSelector(state => state.modal.type); - const ModalContent = ModalContentTable[modalType]; - - return ( - - - - ); -}; - -/** - * Modal の内容表示を定義するコンポーネントの型です。 - */ -type ModalContentComponent = React.FC<{}>; - -const ModalContentTable: { [type in ModalState["type"]]: ModalContentComponent } = { - "NONE": () => <>, - "ERROR": () => <> -}; - -export default ModalView; diff --git a/packages/maker/src/notification/NotificationStates.ts b/packages/maker/src/notification/NotificationStates.ts new file mode 100644 index 0000000..e0a2dfa --- /dev/null +++ b/packages/maker/src/notification/NotificationStates.ts @@ -0,0 +1,31 @@ +import { reducerWithInitialState } from "typescript-fsa-reducers"; +import actionCreatorFactory from "typescript-fsa"; +import { ErrorNotificationState } from "./types/ErrorNotification"; + +export type NotificationState = { + items: NotificationItem[] +}; + +/** + * 通知で表示するアイテムです。 + */ +type NotificationItem = ErrorNotificationState; + +export const INITIAL_STATE: NotificationState = { + items: [] +}; + +const actionCreator = actionCreatorFactory(); +/** + * 通知を発生させます。 + */ +export const notify = actionCreator<{ content: NotificationItem }>("SHOW_ERROR"); + +export const NotificationReducer = reducerWithInitialState(INITIAL_STATE) + .case(notify, (state, params) => { + const newState = Object.assign({}, state); + newState.items = state.items.slice(); + newState.items.push(params.content); + + return newState; + }) diff --git a/packages/maker/src/notification/NotificationView.tsx b/packages/maker/src/notification/NotificationView.tsx new file mode 100644 index 0000000..4220481 --- /dev/null +++ b/packages/maker/src/notification/NotificationView.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +/** + * @todo 実装する + */ +const NotificationView: React.FC<{}> = () => { + return ( + <> + ); +}; + +export default NotificationView; diff --git a/packages/maker/src/notification/types/ErrorNotification.tsx b/packages/maker/src/notification/types/ErrorNotification.tsx new file mode 100644 index 0000000..935d512 --- /dev/null +++ b/packages/maker/src/notification/types/ErrorNotification.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { Message } from "semantic-ui-react"; +import { notify } from "../NotificationStates"; + +export type ErrorNotificationState = { + type: "ERROR", + message: string +}; + +/** + * エラーを発生させます。 + * @param message エラーメッセージ + */ +export const showError = (message: string) => { + notify({ + content: { + type: "ERROR", + message + } + }); +}; + +export const ErrorNotification: React.FC = ({ message }) => { + return ( + + エラー! +

{message}

+
+ ); +}; From afdda5fead8664be4bed9772a8a7e762b8d3179a Mon Sep 17 00:00:00 2001 From: Aokashi Date: Mon, 17 Aug 2020 23:41:00 +0900 Subject: [PATCH 4/4] =?UTF-8?q?NotificationView=E3=82=B3=E3=83=B3=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E3=82=92=E5=AE=9F=E8=A3=85?= =?UTF-8?q?=E3=80=81ErrorNotification=E3=81=AE=E3=83=A1=E3=83=83=E3=82=BB?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=82=92=E4=B8=80=E6=97=A6=E4=BF=9D=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/notification/NotificationItem.ts | 15 ++++++++++++ .../src/notification/NotificationStates.ts | 9 ++----- .../notification/NotificationView.module.scss | 5 ++++ .../src/notification/NotificationView.tsx | 24 +++++++++++++++---- .../notification/types/ErrorNotification.tsx | 5 ++-- 5 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 packages/maker/src/notification/NotificationItem.ts create mode 100644 packages/maker/src/notification/NotificationView.module.scss diff --git a/packages/maker/src/notification/NotificationItem.ts b/packages/maker/src/notification/NotificationItem.ts new file mode 100644 index 0000000..91496c2 --- /dev/null +++ b/packages/maker/src/notification/NotificationItem.ts @@ -0,0 +1,15 @@ +import React from "react"; +import { ErrorNotificationState } from "./types/ErrorNotification"; + +/** + * 通知で表示するアイテムです。 + */ +export type NotificationItem = ErrorNotificationState; + +/** + * types ディレクトリ以降の各通知の内容表示コンポーネントを定義づける型情報です。 + * @todo 各通知固有のパラメーターをもたせる場合、どうしたら良いか考える + */ +export type NotificationItemView = React.FC<{ + +}>; diff --git a/packages/maker/src/notification/NotificationStates.ts b/packages/maker/src/notification/NotificationStates.ts index e0a2dfa..13835d7 100644 --- a/packages/maker/src/notification/NotificationStates.ts +++ b/packages/maker/src/notification/NotificationStates.ts @@ -1,16 +1,11 @@ -import { reducerWithInitialState } from "typescript-fsa-reducers"; +import { NotificationItem } from "./NotificationItem"; import actionCreatorFactory from "typescript-fsa"; -import { ErrorNotificationState } from "./types/ErrorNotification"; +import { reducerWithInitialState } from "typescript-fsa-reducers"; export type NotificationState = { items: NotificationItem[] }; -/** - * 通知で表示するアイテムです。 - */ -type NotificationItem = ErrorNotificationState; - export const INITIAL_STATE: NotificationState = { items: [] }; diff --git a/packages/maker/src/notification/NotificationView.module.scss b/packages/maker/src/notification/NotificationView.module.scss new file mode 100644 index 0000000..4ab97d6 --- /dev/null +++ b/packages/maker/src/notification/NotificationView.module.scss @@ -0,0 +1,5 @@ +.notificationView { + display: absolute; + right: 0; + bottom: 0; +} diff --git a/packages/maker/src/notification/NotificationView.tsx b/packages/maker/src/notification/NotificationView.tsx index 4220481..09c3860 100644 --- a/packages/maker/src/notification/NotificationView.tsx +++ b/packages/maker/src/notification/NotificationView.tsx @@ -1,12 +1,28 @@ import React from "react"; -/** - * @todo 実装する - */ +import { NotificationItem } from "./NotificationItem"; +import styles from "./NotificationView.module.scss"; +import { useSelector } from "react-redux"; +import { NotificationItemView } from "./NotificationItem"; +import { ErrorNotification } from "./types/ErrorNotification"; + const NotificationView: React.FC<{}> = () => { + const notificationItems = useSelector(state => state.notification.items); + return ( - <> +
+ {notificationItems.map(notificationItem => { + const NotificationItemComponent = NotificationItemViewTable[notificationItem.type]; + return ( + + ) + })} +
); }; +const NotificationItemViewTable: { [type in NotificationItem["type"] ]: NotificationItemView } = { + "ERROR": ErrorNotification +} + export default NotificationView; diff --git a/packages/maker/src/notification/types/ErrorNotification.tsx b/packages/maker/src/notification/types/ErrorNotification.tsx index 935d512..6e6745c 100644 --- a/packages/maker/src/notification/types/ErrorNotification.tsx +++ b/packages/maker/src/notification/types/ErrorNotification.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Message } from "semantic-ui-react"; import { notify } from "../NotificationStates"; +import { NotificationItemView } from "../NotificationItem"; export type ErrorNotificationState = { type: "ERROR", @@ -20,11 +21,11 @@ export const showError = (message: string) => { }); }; -export const ErrorNotification: React.FC = ({ message }) => { +export const ErrorNotification: NotificationItemView = () => { return ( エラー! -

{message}

+ {/*

{message}

*/}
); };