diff --git a/client/src/common/Header.tsx b/client/src/common/Header.tsx index 31675b5..deb8a63 100644 --- a/client/src/common/Header.tsx +++ b/client/src/common/Header.tsx @@ -4,6 +4,7 @@ import { Link } from "react-router-dom"; import styled from "styled-components"; import { IUser } from "../../../shared/src"; import { CurrentUser } from "../authentication/CurrentUser"; +import { ItemStore } from "../items/ItemStore"; import { StyleConstants } from "../styling/StyleConstants"; import { StyleUtil } from "../styling/StyleUtil"; import { Typer } from "./Typer"; @@ -52,7 +53,15 @@ export class Header extends React.PureComponent { return ( - {this.state.title} + { + ItemStore.instance.resetAndLoad(); + return true; + }} + > + {this.state.title} + diff --git a/client/src/common/form/Form.StyledComponents.tsx b/client/src/common/form/Form.StyledComponents.tsx index f81a083..ce14931 100644 --- a/client/src/common/form/Form.StyledComponents.tsx +++ b/client/src/common/form/Form.StyledComponents.tsx @@ -83,6 +83,7 @@ export const Button: any = styled.span` min-width: 5rem; cursor: pointer; text-align: center; + border-radius: ${StyleConstants.borderRadius}; ${StyleUtil.normalizeAnchors("inherit")}; &:focus { diff --git a/client/src/common/form/fields/markdown/Markdown.tsx b/client/src/common/form/fields/markdown/Markdown.tsx index 844aeb3..54b6b33 100644 --- a/client/src/common/form/fields/markdown/Markdown.tsx +++ b/client/src/common/form/fields/markdown/Markdown.tsx @@ -1,7 +1,7 @@ import * as MarkdownIt from "markdown-it"; import * as React from "react"; import { ReactNode } from "react"; -import styled, { css } from "styled-components"; +import styled from "styled-components"; import { StyleConstants } from "../../../../styling/StyleConstants"; import { DomUtil } from "../../../DomUtil"; import { If } from "../../../If"; @@ -101,7 +101,11 @@ const TocDiv = styled.div` } `; -const MarkupDiv = styled.div``; +const MarkupDiv = styled.div` + .CodeMirror-gutters { + border-right-color: ${StyleConstants.colors.discreet}; + } +`; export interface IMarkdownProps { markdown: string; diff --git a/client/src/common/form/fields/markdown/MarkdownField.tsx b/client/src/common/form/fields/markdown/MarkdownField.tsx index 98d48de..3231584 100644 --- a/client/src/common/form/fields/markdown/MarkdownField.tsx +++ b/client/src/common/form/fields/markdown/MarkdownField.tsx @@ -31,6 +31,7 @@ const TogglePreviewAnchor = styled.a` font-size: ${StyleConstants.font.small}; cursor: pointer; display: inline-block; + padding-left: 0.7rem; color: ${StyleConstants.colors.accent}; `; diff --git a/client/src/items/ItemStore.ts b/client/src/items/ItemStore.ts index 0737122..fc07174 100644 --- a/client/src/items/ItemStore.ts +++ b/client/src/items/ItemStore.ts @@ -61,7 +61,9 @@ export class ItemStore { }; public deleteItem = (itemId: string): Observable => { - return AuthenticatedServerApi.delete("items/" + itemId).pipe(map((r: AjaxResponse) => null)); + return AuthenticatedServerApi.delete("items/" + itemId).pipe( + map((r: AjaxResponse) => this.deleteFromCache(itemId)) + ); }; public searchKeywords = (searchText: string): Observable => { @@ -113,6 +115,7 @@ export class ItemStore { } return items.map((item: IItem) => { + // todo: consider moving this logic to ItemKindRegistration instead? switch (item.itemKind) { case ItemKind.Note: return new NoteItem(item as INoteItem); @@ -127,17 +130,35 @@ export class ItemStore { }); } + private deleteFromCache(id: string): void { + this.doWithCachedItem(id, (itemIndex: number, newItemsArray: IItem[]) => { + newItemsArray.splice(itemIndex, 1); + return newItemsArray; + }); + } + private updateCache(item: IItem): IItem { - const cachedItems = this.items$.value; - const cachedItemIndex: number = cachedItems.findIndex(i => i._id === item._id); + this.doWithCachedItem( + item._id, + (itemIndex: number, newItemsArray: IItem[]): IItem[] => { + newItemsArray[itemIndex] = item; + return newItemsArray; + } + ); - if (cachedItemIndex > -1) { - const updatedItems = [...cachedItems]; - updatedItems[cachedItemIndex] = item; + return item; + } - this.items$.next([...updatedItems]); - } + private doWithCachedItem( + id: string, + callback: (itemIndex: number, newItemsArray: IItem[]) => IItem[] + ): void { + const cachedItems: IItem[] = this.items$.value; + const cachedItemIndex: number = cachedItems.findIndex(i => i._id === id); - return item; + if (cachedItemIndex > -1) { + const modifiedItems: IItem[] = callback(cachedItemIndex, [...cachedItems]); + this.items$.next(modifiedItems); + } } } diff --git a/client/src/pages/search/GlobalSearchBox.tsx b/client/src/pages/search/GlobalSearchBox.tsx index b744261..135e8a6 100644 --- a/client/src/pages/search/GlobalSearchBox.tsx +++ b/client/src/pages/search/GlobalSearchBox.tsx @@ -2,6 +2,7 @@ import { IKeyword, ItemKind } from "engraved-shared"; import * as React from "react"; import { ReactNode } from "react"; import { Redirect } from "react-router"; +import { Subscription } from "rxjs"; import styled, { css } from "styled-components"; import { ErrorBoundary } from "../../common/ErrorBoundary"; import { IRedirection } from "../../common/IRedirection"; @@ -43,6 +44,8 @@ interface IGlobalSearchBoxState { export class GlobalSearchBox extends React.PureComponent<{}, IGlobalSearchBoxState> { private findOnTypeTimer: any; + private keywordsSubscription: Subscription; + public constructor(props: {}) { super(props); @@ -58,11 +61,17 @@ export class GlobalSearchBox extends React.PureComponent<{}, IGlobalSearchBoxSta } public componentDidMount(): void { - ItemStore.instance.keywords$.subscribe(keywords => + this.keywordsSubscription = ItemStore.instance.keywords$.subscribe(keywords => this.setState({ selectedKeywords: keywords }) ); } + public componentWillUnmount(): void { + if (this.keywordsSubscription) { + this.keywordsSubscription.unsubscribe(); + } + } + public render(): ReactNode { if (this.state.redirectToUrl) { return ;