mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-03-13 02:53:44 +00:00
Added 'print' button to print the current chart
This commit is contained in:
@@ -133,4 +133,27 @@ export class Chart extends React.PureComponent<ChartProps, {}> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Shows the print dialog to print the currently displayed chart. */
|
||||||
|
print() {
|
||||||
|
const printWindow = document.createElement('iframe');
|
||||||
|
printWindow.style.position = 'absolute';
|
||||||
|
printWindow.style.top = '-1000px';
|
||||||
|
printWindow.style.left = '-1000px';
|
||||||
|
printWindow.onload = () => {
|
||||||
|
const svg = document.getElementById('chart')!.cloneNode(true) as Element;
|
||||||
|
svg.removeAttribute('transform');
|
||||||
|
const contents = svg.outerHTML;
|
||||||
|
printWindow.contentDocument!.open();
|
||||||
|
printWindow.contentDocument!.write(contents);
|
||||||
|
printWindow.contentDocument!.close();
|
||||||
|
// Doesn't work on Firefox without the setTimeout.
|
||||||
|
setTimeout(() => {
|
||||||
|
printWindow.contentWindow!.focus();
|
||||||
|
printWindow.contentWindow!.print();
|
||||||
|
printWindow.parentNode!.removeChild(printWindow);
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
document.body.appendChild(printWindow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ interface State {
|
|||||||
/** The main area of the application dedicated for rendering the family chart. */
|
/** The main area of the application dedicated for rendering the family chart. */
|
||||||
export class ChartView extends React.Component<RouteComponentProps, State> {
|
export class ChartView extends React.Component<RouteComponentProps, State> {
|
||||||
state: State = {loading: false};
|
state: State = {loading: false};
|
||||||
|
chartRef: Chart | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the user clicks an individual box in the chart.
|
* Called when the user clicks an individual box in the chart.
|
||||||
@@ -102,7 +103,8 @@ export class ChartView extends React.Component<RouteComponentProps, State> {
|
|||||||
? 'https://cors-anywhere.herokuapp.com/' + url
|
? 'https://cors-anywhere.herokuapp.com/' + url
|
||||||
: url;
|
: url;
|
||||||
|
|
||||||
window.fetch(urlToFetch)
|
window
|
||||||
|
.fetch(urlToFetch)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
return Promise.reject(new Error(response.statusText));
|
return Promise.reject(new Error(response.statusText));
|
||||||
@@ -237,6 +239,7 @@ export class ChartView extends React.Component<RouteComponentProps, State> {
|
|||||||
data={this.state.data}
|
data={this.state.data}
|
||||||
onSelection={this.onSelection}
|
onSelection={this.onSelection}
|
||||||
selection={this.state.selection}
|
selection={this.state.selection}
|
||||||
|
ref={(ref) => (this.chartRef = ref)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -245,4 +248,11 @@ export class ChartView extends React.Component<RouteComponentProps, State> {
|
|||||||
}
|
}
|
||||||
return <Loader active size="large" />;
|
return <Loader active size="large" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Shows the print dialog to print the currently displayed chart. */
|
||||||
|
print() {
|
||||||
|
if (this.chartRef) {
|
||||||
|
this.chartRef.print();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ import messages_pl from './translations/pl.json';
|
|||||||
import {addLocaleData} from 'react-intl';
|
import {addLocaleData} from 'react-intl';
|
||||||
import {detect} from 'detect-browser';
|
import {detect} from 'detect-browser';
|
||||||
import {ChartView} from './chart_view';
|
import {ChartView} from './chart_view';
|
||||||
import {HashRouter as Router, Route, Switch} from 'react-router-dom';
|
import {
|
||||||
|
HashRouter as Router,
|
||||||
|
Route,
|
||||||
|
RouteComponentProps,
|
||||||
|
Switch,
|
||||||
|
} from 'react-router-dom';
|
||||||
import {IntlProvider} from 'react-intl';
|
import {IntlProvider} from 'react-intl';
|
||||||
import {Intro} from './intro';
|
import {Intro} from './intro';
|
||||||
import {TopBar} from './top_bar';
|
import {TopBar} from './top_bar';
|
||||||
@@ -22,6 +27,8 @@ const language = navigator.language && navigator.language.split(/[-_]/)[0];
|
|||||||
|
|
||||||
const browser = detect();
|
const browser = detect();
|
||||||
|
|
||||||
|
let chartViewRef: ChartView | null = null;
|
||||||
|
|
||||||
if (browser && browser.name === 'ie') {
|
if (browser && browser.name === 'ie') {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<p>
|
<p>
|
||||||
@@ -35,10 +42,23 @@ if (browser && browser.name === 'ie') {
|
|||||||
<IntlProvider locale={language} messages={messages[language]}>
|
<IntlProvider locale={language} messages={messages[language]}>
|
||||||
<Router>
|
<Router>
|
||||||
<div className="root">
|
<div className="root">
|
||||||
<Route component={TopBar} />
|
<Route
|
||||||
|
component={(props: RouteComponentProps) => (
|
||||||
|
<TopBar
|
||||||
|
{...props}
|
||||||
|
onPrint={() => chartViewRef && chartViewRef.print()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={Intro} />
|
<Route exact path="/" component={Intro} />
|
||||||
<Route exact path="/view" component={ChartView} />
|
<Route
|
||||||
|
exact
|
||||||
|
path="/view"
|
||||||
|
component={(props: RouteComponentProps) => (
|
||||||
|
<ChartView {...props} ref={(ref) => (chartViewRef = ref)} />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
@@ -20,7 +20,14 @@ interface State {
|
|||||||
url?: string;
|
url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TopBar extends React.Component<RouteComponentProps, State> {
|
interface Props {
|
||||||
|
onPrint: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TopBar extends React.Component<
|
||||||
|
RouteComponentProps & Props,
|
||||||
|
State
|
||||||
|
> {
|
||||||
state: State = {loadUrlDialogOpen: false};
|
state: State = {loadUrlDialogOpen: false};
|
||||||
inputRef?: Input;
|
inputRef?: Input;
|
||||||
|
|
||||||
@@ -164,6 +171,10 @@ export class TopBar extends React.Component<RouteComponentProps, State> {
|
|||||||
/>
|
/>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</label>
|
</label>
|
||||||
|
<Menu.Item as="a" onClick={() => this.props.onPrint()}>
|
||||||
|
<Icon name="print" />
|
||||||
|
<FormattedMessage id="menu.print" defaultMessage="Print" />
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
as="a"
|
as="a"
|
||||||
href="https://github.com/PeWu/topola-viewer"
|
href="https://github.com/PeWu/topola-viewer"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"menu.load_from_url": "Otwórz URL",
|
"menu.load_from_url": "Otwórz URL",
|
||||||
"menu.load_from_file": "Otwórz plik",
|
"menu.load_from_file": "Otwórz plik",
|
||||||
|
"menu.print": "Drukuj",
|
||||||
"menu.github": "Źródła na GitHub",
|
"menu.github": "Źródła na GitHub",
|
||||||
"intro.title": "Topola Genealogy",
|
"intro.title": "Topola Genealogy",
|
||||||
"intro.description": "Topola Genealogy pozwala przeglądać drzewo genealogiczne w interaktywny sposób.",
|
"intro.description": "Topola Genealogy pozwala przeglądać drzewo genealogiczne w interaktywny sposób.",
|
||||||
|
|||||||
Reference in New Issue
Block a user