mirror of
https://github.com/usatiuk/writer.git
synced 2025-10-29 00:17:48 +01:00
deleting documents
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { Position, Toaster } from "@blueprintjs/core";
|
||||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Route, RouteComponentProps, Switch, withRouter } from "react-router";
|
||||
@@ -6,6 +7,11 @@ import { Home } from "~Home/Home";
|
||||
import { Landing } from "~Landing/Landing";
|
||||
import { IAppState } from "~redux/reducers";
|
||||
|
||||
export const AppToaster = Toaster.create({
|
||||
className: "recipe-toaster",
|
||||
position: Position.TOP,
|
||||
});
|
||||
|
||||
interface IAppComponentProps extends RouteComponentProps {
|
||||
loggedIn: boolean;
|
||||
}
|
||||
|
||||
@@ -53,12 +53,15 @@
|
||||
h1 {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
button {
|
||||
.buttons {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
|
||||
@@ -6,8 +6,13 @@ import { connect } from "react-redux";
|
||||
import { RouteComponentProps, withRouter } from "react-router";
|
||||
import { Dispatch } from "redux";
|
||||
import { IDocumentJSON } from "~../../src/entity/Document";
|
||||
import { AppToaster } from "~App";
|
||||
import { LoadingStub } from "~LoadingStub";
|
||||
import { fetchDocsStart } from "~redux/docs/actions";
|
||||
import {
|
||||
deleteDocCancel,
|
||||
deleteDocStart,
|
||||
fetchDocsStart,
|
||||
} from "~redux/docs/actions";
|
||||
import { IAppState } from "~redux/reducers";
|
||||
|
||||
export interface IDocumentEditComponentProps extends RouteComponentProps {
|
||||
@@ -15,7 +20,10 @@ export interface IDocumentEditComponentProps extends RouteComponentProps {
|
||||
|
||||
fetching: boolean;
|
||||
spinner: boolean;
|
||||
|
||||
fetchDocs: () => void;
|
||||
deleteDoc: (id: number) => void;
|
||||
cancelDelete: () => void;
|
||||
}
|
||||
|
||||
export class DocumentEditComponent extends React.PureComponent<
|
||||
@@ -30,13 +38,33 @@ export class DocumentEditComponent extends React.PureComponent<
|
||||
<div className="document">
|
||||
<div className="documentHeader">
|
||||
<H1 contentEditable={true}>{doc.name}</H1>
|
||||
<Button
|
||||
icon="tick"
|
||||
minimal={true}
|
||||
onClick={() =>
|
||||
this.props.history.push(`/docs/${id}`)
|
||||
}
|
||||
/>
|
||||
<div className="buttons">
|
||||
<Button
|
||||
icon="trash"
|
||||
minimal={true}
|
||||
onClick={() => {
|
||||
this.props.history.push(`/`);
|
||||
this.props.deleteDoc(id);
|
||||
AppToaster.show({
|
||||
message: "Document deleted!",
|
||||
intent: "danger",
|
||||
timeout: 1900,
|
||||
action: {
|
||||
text: "Undo",
|
||||
onClick: () =>
|
||||
this.props.cancelDelete(),
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon="tick"
|
||||
minimal={true}
|
||||
onClick={() =>
|
||||
this.props.history.push(`/docs/${id}`)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<TextArea>{doc.content}</TextArea>
|
||||
</div>
|
||||
@@ -59,6 +87,8 @@ function mapStateToProps(state: IAppState) {
|
||||
function mapDispatchToProps(dispatch: Dispatch) {
|
||||
return {
|
||||
fetchDocs: () => dispatch(fetchDocsStart()),
|
||||
cancelDelete: () => dispatch(deleteDocCancel()),
|
||||
deleteDoc: (id: number) => dispatch(deleteDocStart(id)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,15 @@ export class DocumentViewComponent extends React.PureComponent<
|
||||
<div className="document">
|
||||
<div className="documentHeader">
|
||||
<H1>{doc.name}</H1>
|
||||
<Button
|
||||
icon="edit"
|
||||
minimal={true}
|
||||
onClick={() =>
|
||||
this.props.history.push(`/docs/${id}/edit`)
|
||||
}
|
||||
/>
|
||||
<div className="buttons">
|
||||
<Button
|
||||
icon="edit"
|
||||
minimal={true}
|
||||
onClick={() =>
|
||||
this.props.history.push(`/docs/${id}/edit`)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Text>{doc.content}</Text>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,11 @@ export enum DocsTypes {
|
||||
DOC_NEW_SUCCESS = "DOC_NEW_SUCCESS",
|
||||
DOC_NEW_RESET = "DOC_NEW_RESET",
|
||||
|
||||
DOC_DELETE_START = "DOC_DELETE_START",
|
||||
DOC_DELETE_FAIL = "DOC_DELETE_FAIL",
|
||||
DOC_DELETE_SUCCESS = "DOC_DELETE_SUCCESS",
|
||||
DOC_DELETE_CANCEL = "DOC_DELETE_CANCEL",
|
||||
|
||||
DOCS_SHOW_SPINNER = "DOCS_SHOW_SPINNER",
|
||||
}
|
||||
|
||||
@@ -92,6 +97,45 @@ export function newDocReset(): IDocNewResetAction {
|
||||
return { type: DocsTypes.DOC_NEW_RESET };
|
||||
}
|
||||
|
||||
export interface IDocDeleteStartAction extends Action {
|
||||
type: DocsTypes.DOC_DELETE_START;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface IDocDeleteFailAction extends Action {
|
||||
type: DocsTypes.DOC_DELETE_FAIL;
|
||||
payload: {
|
||||
error: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDocDeleteSuccessAction extends Action {
|
||||
type: DocsTypes.DOC_DELETE_SUCCESS;
|
||||
payload: {
|
||||
id: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IDocDeleteCancelAction extends Action {
|
||||
type: DocsTypes.DOC_DELETE_CANCEL;
|
||||
}
|
||||
|
||||
export function deleteDocStart(id: number): IDocDeleteStartAction {
|
||||
return { type: DocsTypes.DOC_DELETE_START, id };
|
||||
}
|
||||
|
||||
export function deleteDocFail(error: string): IDocDeleteFailAction {
|
||||
return { type: DocsTypes.DOC_DELETE_FAIL, payload: { error } };
|
||||
}
|
||||
|
||||
export function deleteDocSuccess(id: number): IDocDeleteSuccessAction {
|
||||
return { type: DocsTypes.DOC_DELETE_SUCCESS, payload: { id } };
|
||||
}
|
||||
|
||||
export function deleteDocCancel(): IDocDeleteCancelAction {
|
||||
return { type: DocsTypes.DOC_DELETE_CANCEL };
|
||||
}
|
||||
|
||||
export type DocsAction =
|
||||
| IDocsFetchStartAction
|
||||
| IDocsFetchFailAction
|
||||
@@ -99,4 +143,9 @@ export type DocsAction =
|
||||
| IDocsShowSpinnerAction
|
||||
| IDocNewFailAction
|
||||
| IDocNewStartAction
|
||||
| IDocNewSuccessAction | IDocNewResetAction;
|
||||
| IDocNewSuccessAction
|
||||
| IDocNewResetAction
|
||||
| IDocDeleteFailAction
|
||||
| IDocDeleteStartAction
|
||||
| IDocDeleteSuccessAction
|
||||
| IDocDeleteCancelAction;
|
||||
|
||||
@@ -45,6 +45,11 @@ export const docsReducer: Reducer<IDocsState, DocsAction> = (
|
||||
case DocsTypes.DOC_NEW_RESET: {
|
||||
return { ...state, newDocumentID: null };
|
||||
}
|
||||
case DocsTypes.DOC_DELETE_SUCCESS: {
|
||||
const all = { ...state.all };
|
||||
delete all[action.payload.id];
|
||||
return { ...state, all };
|
||||
}
|
||||
case DocsTypes.DOCS_FETCH_FAIL:
|
||||
return { ...defaultDocsState, ...action.payload };
|
||||
default:
|
||||
|
||||
@@ -6,14 +6,18 @@ import {
|
||||
fork,
|
||||
put,
|
||||
race,
|
||||
take,
|
||||
takeLatest,
|
||||
} from "redux-saga/effects";
|
||||
import { createNewDoc, fetchAllDocs } from "~redux/api/docs";
|
||||
import { createNewDoc, deleteDoc, fetchAllDocs } from "~redux/api/docs";
|
||||
|
||||
import {
|
||||
deleteDocFail,
|
||||
deleteDocSuccess,
|
||||
DocsTypes,
|
||||
fetchDocsFail,
|
||||
fetchDocsSuccess,
|
||||
IDocDeleteStartAction,
|
||||
IDocNewStartAction,
|
||||
IDocsFetchStartAction,
|
||||
newDocFail,
|
||||
@@ -84,9 +88,41 @@ function* docNewStart(action: IDocNewStartAction) {
|
||||
}
|
||||
}
|
||||
|
||||
function* docDeleteStart(action: IDocDeleteStartAction) {
|
||||
try {
|
||||
const { cancelled } = yield race({
|
||||
timeout: delay(2000),
|
||||
cancelled: take(DocsTypes.DOC_DELETE_CANCEL),
|
||||
});
|
||||
|
||||
if (!cancelled) {
|
||||
const { response, timeout } = yield race({
|
||||
response: call(deleteDoc, action.id),
|
||||
timeout: delay(10000),
|
||||
});
|
||||
|
||||
if (timeout) {
|
||||
yield put(deleteDocFail("Timeout"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response) {
|
||||
if (response.data == null) {
|
||||
yield put(deleteDocFail(response.error));
|
||||
} else {
|
||||
yield put(deleteDocSuccess(action.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
yield put(deleteDocFail("Internal error"));
|
||||
}
|
||||
}
|
||||
|
||||
export function* docsSaga() {
|
||||
yield all([
|
||||
takeLatest(DocsTypes.DOCS_FETCH_START, docsFetchStart),
|
||||
takeLatest(DocsTypes.DOC_NEW_START, docNewStart),
|
||||
takeLatest(DocsTypes.DOC_DELETE_START, docDeleteStart),
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user