Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions packages/maker/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 NotificationView from './notification/NotificationView';

interface StateProps {
isOpened: boolean
Expand Down Expand Up @@ -39,20 +40,23 @@ class App extends React.Component<StateProps> {

public render() {
return (
<div className={styles.app}>
<div className={styles.mainToolbar}>
<MainToolbar></MainToolbar>
<>
<NotificationView />
<div className={styles.app}>
<div className={styles.mainToolbar}>
<MainToolbar></MainToolbar>
</div>
<div className={styles.editArea}>
<SplitPane split="horizontal" defaultSize={300} primary="second">
<MapEdit></MapEdit>
<PartsSelect></PartsSelect>
</SplitPane>
</div>
<div className={this.getInfoPanelClassName()}>
<InfoPanel></InfoPanel>
</div>
</div>
<div className={styles.editArea}>
<SplitPane split="horizontal" defaultSize={300} primary="second">
<MapEdit></MapEdit>
<PartsSelect></PartsSelect>
</SplitPane>
</div>
<div className={this.getInfoPanelClassName()}>
<InfoPanel></InfoPanel>
</div>
</div>
</>
);
}
}
Expand Down
10 changes: 7 additions & 3 deletions packages/maker/src/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { 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";
Expand All @@ -21,7 +22,8 @@ export interface StoreType {
objParts: PartsState,
mapParts: PartsState,
imageUrl: string|null,
info: InfoPanelState
info: InfoPanelState,
notification: NotificationState
}

/**
Expand All @@ -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,
notification: NOTIFICATION_INITIAL_STATE
}

const actionCreator = actionCreatorFactory();
Expand Down Expand Up @@ -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: NotificationReducer(state.notification, action)
}))

export const Store = createStore(
Expand Down
4 changes: 4 additions & 0 deletions packages/maker/src/common/MapView/MapCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@ const MapCanvas: React.FC<Props> = 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];
Expand Down
6 changes: 3 additions & 3 deletions packages/maker/src/info/InfoPanelState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import actionCreatorFactory from "typescript-fsa";
import { reducerWithInitialState } from "typescript-fsa-reducers";
import { PartsType } from "../classes/WWAData";
import { showError } from "../notification/types/ErrorNotification";

/**
* InfoPanel のモードです。
Expand Down Expand Up @@ -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("パーツ番号0の物体は編集できません。\nこのパーツはマップの物体を消去するときに指定してください。");
break;
case PartsType.MAP:
alert("パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。");
showError("パーツ番号0の背景は編集できません。\nこのパーツはマップの背景を消去するときに指定してください。");
}
return state;
}
Expand Down
15 changes: 15 additions & 0 deletions packages/maker/src/notification/NotificationItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { ErrorNotificationState } from "./types/ErrorNotification";

/**
* 通知で表示するアイテムです。
*/
export type NotificationItem = ErrorNotificationState;

/**
* types ディレクトリ以降の各通知の内容表示コンポーネントを定義づける型情報です。
* @todo 各通知固有のパラメーターをもたせる場合、どうしたら良いか考える
*/
export type NotificationItemView = React.FC<{

}>;
26 changes: 26 additions & 0 deletions packages/maker/src/notification/NotificationStates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { NotificationItem } from "./NotificationItem";
import actionCreatorFactory from "typescript-fsa";
import { reducerWithInitialState } from "typescript-fsa-reducers";

export type NotificationState = {
items: NotificationItem[]
};

export const INITIAL_STATE: NotificationState = {
items: []
};

const actionCreator = actionCreatorFactory();
/**
* 通知を発生させます。
*/
export const notify = actionCreator<{ content: NotificationItem }>("SHOW_ERROR");

export const NotificationReducer = reducerWithInitialState<NotificationState>(INITIAL_STATE)
.case(notify, (state, params) => {
const newState = Object.assign({}, state);
newState.items = state.items.slice();
newState.items.push(params.content);

return newState;
})
5 changes: 5 additions & 0 deletions packages/maker/src/notification/NotificationView.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.notificationView {
display: absolute;
right: 0;
bottom: 0;
}
28 changes: 28 additions & 0 deletions packages/maker/src/notification/NotificationView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";

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 (
<div className={styles.notificationView}>
{notificationItems.map(notificationItem => {
const NotificationItemComponent = NotificationItemViewTable[notificationItem.type];
return (
<NotificationItemComponent />
)
})}
</div>
);
};

const NotificationItemViewTable: { [type in NotificationItem["type"] ]: NotificationItemView } = {
"ERROR": ErrorNotification
}

export default NotificationView;
31 changes: 31 additions & 0 deletions packages/maker/src/notification/types/ErrorNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import { Message } from "semantic-ui-react";
import { notify } from "../NotificationStates";
import { NotificationItemView } from "../NotificationItem";

export type ErrorNotificationState = {
type: "ERROR",
message: string
};

/**
* エラーを発生させます。
* @param message エラーメッセージ
*/
export const showError = (message: string) => {
notify({
content: {
type: "ERROR",
message
}
});
};

export const ErrorNotification: NotificationItemView = () => {
return (
<Message negative>
<Message.Header>エラー!</Message.Header>
{/*<p>{message}</p>*/}
</Message>
);
};