Skip to content

Commit 63796d6

Browse files
authored
Tsakorpus -- #907 (#1150)
* init * next * minor * uploading * correct rerendering * fixed port * minor * cleanup
1 parent c17c426 commit 63796d6

File tree

7 files changed

+243
-3
lines changed

7 files changed

+243
-3
lines changed

src/Layout/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import PlayerModal from "components/PlayerModal";
2121
import RolesModal from "components/RolesModal";
2222
import SaveDictionary from "components/SaveDictionaryModal";
2323
import StatisticsModal from "components/StatisticsModal";
24+
import UploadModal from "components/UploadModal";
2425
import smoothScroll from "utils/smoothscroll";
2526

2627
import NavBar from "./NavBar";
@@ -73,6 +74,7 @@ class Layout extends React.Component {
7374
<PhonologyModal />
7475
<ConvertEafModal />
7576
<StatisticsModal />
77+
<UploadModal />
7678
<BanModal />
7779
<CreateFieldModal />
7880
<RolesModal />

src/components/UploadModal/index.js

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import React, { useContext, useState, useEffect } from "react";
2+
import { connect } from "react-redux";
3+
import { Button, Loader, Message, Modal, Icon } from "semantic-ui-react";
4+
import { gql } from "@apollo/client";
5+
import { graphql } from "@apollo/client/react/hoc";
6+
import PropTypes from "prop-types";
7+
import { branch, compose, renderNothing, withProps } from "recompose";
8+
import { bindActionCreators } from "redux";
9+
10+
import { closeUploadModal, updateUploadModal } from "ducks/upload";
11+
import TranslationContext from "Layout/TranslationContext";
12+
13+
const getUploadDate = gql`
14+
query getUploadDate($id: LingvodocID!) {
15+
perspective(id: $id) {
16+
id
17+
additional_metadata {
18+
uploaded_at
19+
}
20+
}
21+
}
22+
`;
23+
24+
const Upload = props => {
25+
26+
const getTranslation = useContext(TranslationContext);
27+
const { id, title, data, actions, user, uploading, uploadPerspective } = props;
28+
const { loading, error, refetch, perspective } = data;
29+
useEffect(() => { refetch(); }, [uploading]);
30+
if (loading) {
31+
return (
32+
<Modal open dimmer size="fullscreen" closeOnDimmerClick={false} closeIcon className="lingvo-modal2">
33+
<Loader>{`${getTranslation("Loading")}...`}</Loader>
34+
</Modal>
35+
);
36+
} else if (error || uploading === null) {
37+
return (
38+
<Modal closeIcon onClose={actions.closeUploadModal} open className="lingvo-modal2">
39+
<Modal.Header>{title}</Modal.Header>
40+
<Modal.Content>
41+
<Message negative compact>
42+
<Message.Header>{getTranslation("Perspective info loading error")}</Message.Header>
43+
<div style={{ marginTop: "0.25em" }}>
44+
{getTranslation("Try reloading the page; if the error persists, please contact administrators.")}
45+
</div>
46+
</Message>
47+
</Modal.Content>
48+
</Modal>
49+
);
50+
}
51+
52+
const { additional_metadata: { uploaded_at }} = perspective;
53+
54+
return (
55+
<Modal
56+
closeIcon
57+
onClose={actions.closeUploadModal}
58+
open
59+
dimmer
60+
size="50%"
61+
className="lingvo-modal2"
62+
>
63+
<Modal.Header>{title}</Modal.Header>
64+
<Modal.Content>
65+
<p>
66+
{getTranslation("Uploaded at")}
67+
{": "}
68+
{ uploaded_at
69+
? new Date(uploaded_at).toLocaleString()
70+
: "<never>"
71+
}
72+
{ user.id == 1 && (
73+
<Button
74+
content={uploading ? (
75+
<span>
76+
{getTranslation("Uploading")}... <Icon name="spinner" loading />
77+
</span>
78+
) : (
79+
getTranslation(uploaded_at ? "Refresh" : "Upload")
80+
)}
81+
onClick={() => {
82+
actions.updateUploadModal(true);
83+
uploadPerspective();
84+
}}
85+
disabled={uploading}
86+
className="lingvo-button-greenest"
87+
style={{marginLeft: "1.5em"}}
88+
/>
89+
)}
90+
</p>
91+
</Modal.Content>
92+
<Modal.Actions>
93+
{ user.id !== undefined && uploaded_at && (
94+
<Button
95+
content={getTranslation("Uploaded corpora")}
96+
className="lingvo-button-violet"
97+
style={{float: 'left'}}
98+
onClick={()=> window.open(`http://83.149.198.78/${id[0]}_${id[1]}/search`, "_blank")}
99+
/>
100+
)}
101+
<Button
102+
content={getTranslation("Close")}
103+
onClick={actions.closeUploadModal}
104+
className="lingvo-button-basic-black"
105+
/>
106+
</Modal.Actions>
107+
</Modal>
108+
);
109+
};
110+
111+
Upload.propTypes = {
112+
id: PropTypes.array.isRequired,
113+
title: PropTypes.string.isRequired,
114+
uploading: PropTypes.bool.isRequired,
115+
uploadPerspective: PropTypes.func.isRequired,
116+
data: PropTypes.shape({
117+
loading: PropTypes.bool.isRequired
118+
}).isRequired,
119+
actions: PropTypes.shape({
120+
closeUploadModal: PropTypes.func.isRequired,
121+
updateUploadModal: PropTypes.func.isRequired
122+
}).isRequired
123+
};
124+
125+
export default compose(
126+
connect(
127+
state => state.user,
128+
),
129+
connect(
130+
state => state.upload,
131+
dispatch => ({ actions: bindActionCreators({ closeUploadModal, updateUploadModal }, dispatch) })
132+
),
133+
branch(({ upload }) => !upload, renderNothing),
134+
withProps(({ upload: { id, title, uploading, uploadPerspective } }) => ({ id, title, uploading, uploadPerspective })),
135+
graphql(getUploadDate, { options: { fetchPolicy: "network-only" }})
136+
)(Upload);

src/ducks/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import search from "./search";
2929
import snackbar from "./snackbar";
3030
import statistics from "./statistics";
3131
import task from "./task";
32+
import upload from "./upload";
3233
import user from "./user";
3334

3435
export default {
@@ -57,6 +58,7 @@ export default {
5758
phonology,
5859
apolloClient,
5960
statistics,
61+
upload,
6062
ban,
6163
modals,
6264
createOrganization,

src/ducks/upload.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { combineReducers } from "redux";
2+
3+
// Actions
4+
const OPEN_MODAL = "@upload/OPEN_MODAL";
5+
const CLOSE_MODAL = "@upload/CLOSE_MODAL";
6+
const UPDATE_MODAL = "@upload/UPDATE_MODAL";
7+
8+
export const openUploadModal = (id, title, uploading, uploadPerspective) => ({
9+
type: OPEN_MODAL,
10+
payload: {
11+
id,
12+
title,
13+
uploading,
14+
uploadPerspective
15+
}
16+
});
17+
18+
export const updateUploadModal = (uploading) => ({
19+
type: UPDATE_MODAL,
20+
payload: { uploading }
21+
});
22+
23+
export const closeUploadModal = () => ({ type: CLOSE_MODAL });
24+
25+
const upload = (state = null, { type, payload }) => {
26+
switch (type) {
27+
case OPEN_MODAL:
28+
return payload;
29+
case UPDATE_MODAL:
30+
return { ...state, uploading: payload.uploading };
31+
case CLOSE_MODAL:
32+
return null;
33+
default:
34+
return state;
35+
}
36+
};
37+
38+
export default combineReducers({
39+
upload
40+
});

src/pages/Dashboard/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { openPerspectivePropertiesModal } from "ducks/perspectiveProperties";
1616
import { openRoles } from "ducks/roles";
1717
import { openSaveDictionaryModal } from "ducks/saveDictionary";
1818
import { openStatistics } from "ducks/statistics";
19+
import { openUploadModal } from "ducks/upload";
1920
import TranslationContext from "Layout/TranslationContext";
2021
import { dictionaryQuery } from "pages/DialeqtImport";
2122
import { compositeIdToString } from "utils/compositeId";

src/pages/Perspective/PerspectivePath.js

+61-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { openPerspectivePropertiesModal } from "ducks/perspectiveProperties";
1616
import { openRoles } from "ducks/roles";
1717
import { openSaveDictionaryModal } from "ducks/saveDictionary";
1818
import { openStatistics } from "ducks/statistics";
19+
import { openUploadModal, updateUploadModal } from "ducks/upload";
1920
import TranslationContext from "Layout/TranslationContext";
2021

2122
const queryPerspectivePath = gql`
@@ -34,6 +35,7 @@ export const queryAvailablePerspectives = gql`
3435
query availablePerspectives($dictionary_id: LingvodocID!) {
3536
dictionary(id: $dictionary_id) {
3637
id
38+
category
3739
perspectives {
3840
id
3941
parent_id
@@ -46,6 +48,14 @@ export const queryAvailablePerspectives = gql`
4648
}
4749
`;
4850

51+
const uploadPerspective = gql`
52+
mutation uploadPerspective($id: LingvodocID!, $debugFlag: Boolean) {
53+
tsakorpus(perspective_id: $id, debug_flag: $debugFlag) {
54+
triumph
55+
}
56+
}
57+
`;
58+
4959
const license_dict_translator = getTranslation => ({
5060
proprietary: [getTranslation("Proprietary"), null],
5161
"cc-by-4.0": ["CC-BY-4.0", "https://creativecommons.org/licenses/by/4.0/legalcode"],
@@ -57,6 +67,35 @@ const license_dict_translator = getTranslation => ({
5767
* Perspective breadcrumb component.
5868
*/
5969
class PerspectivePath extends React.Component {
70+
constructor(props) {
71+
super(props);
72+
73+
this.state = {
74+
uploading: false
75+
};
76+
77+
this.uploadPerspectiveWrapper = this.uploadPerspectiveWrapper.bind(this);
78+
};
79+
80+
uploadPerspectiveWrapper() {
81+
const {id, actions, uploadPerspective} = this.props;
82+
83+
this.setState({ uploading: true });
84+
85+
uploadPerspective({
86+
variables: { id }
87+
}).then(
88+
({ data }) => {
89+
this.setState({ uploading: false });
90+
actions.updateUploadModal(data.tsakorpus.triumph ? false : null);
91+
},
92+
() => {
93+
this.setState({ uploading: false });
94+
actions.updateUploadModal(null);
95+
}
96+
)
97+
}
98+
6099
render() {
61100
/* eslint-disable no-shadow */
62101
const {
@@ -88,6 +127,7 @@ class PerspectivePath extends React.Component {
88127
const dictionary_id_tree = tree[1].id;
89128

90129
const {
130+
category,
91131
perspectives,
92132
additional_metadata: { license }
93133
} = queryAvailablePerspectives.dictionary;
@@ -108,6 +148,7 @@ class PerspectivePath extends React.Component {
108148
const roles_str = this.context("Roles").toLowerCase();
109149
const properties_str = this.context("Properties").toLowerCase();
110150
const statistics_str = this.context("Statistics").toLowerCase();
151+
const upload_str = this.context("Upload").toLowerCase();
111152

112153
return (
113154
<Header as="h2" className={className}>
@@ -171,6 +212,20 @@ class PerspectivePath extends React.Component {
171212
actions.openStatistics(id, "perspective", `'${T(e.translations)}' ${statistics_str}`)
172213
}
173214
/>
215+
{user.id !== undefined && category == 1 && (
216+
<Dropdown.Item
217+
key="upload"
218+
icon={<i className="lingvo-icon lingvo-icon_published" />}
219+
text={this.context("Upload")}
220+
onClick={() =>
221+
actions.openUploadModal(
222+
id,
223+
`'${T(e.translations)}' ${upload_str}`,
224+
this.state.uploading,
225+
this.uploadPerspectiveWrapper)
226+
}
227+
/>
228+
)}
174229
</Dropdown.Menu>
175230
</Dropdown>
176231
) : index === tree.length - 2 ? (
@@ -285,6 +340,7 @@ PerspectivePath.propTypes = {
285340
dictionary_id: PropTypes.array.isRequired,
286341
queryPerspectivePath: PropTypes.object.isRequired,
287342
queryAvailablePerspectives: PropTypes.object.isRequired,
343+
uploadPerspective: PropTypes.func.isRequired,
288344
mode: PropTypes.string.isRequired,
289345
className: PropTypes.string,
290346
actions: PropTypes.object.isRequired,
@@ -310,7 +366,9 @@ export default compose(
310366
openPerspectivePropertiesModal,
311367
openRoles,
312368
openSaveDictionaryModal,
313-
openStatistics
369+
openStatistics,
370+
openUploadModal,
371+
updateUploadModal
314372
},
315373
dispatch
316374
)
@@ -323,5 +381,6 @@ export default compose(
323381
graphql(queryAvailablePerspectives, {
324382
name: "queryAvailablePerspectives",
325383
options: props => ({ variables: { dictionary_id: props.dictionary_id } })
326-
})
384+
}),
385+
graphql(uploadPerspective, { name: "uploadPerspective" })
327386
)(PerspectivePath);

src/pages/Perspective/component.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,7 @@ const ModeSelector = compose(
12011201
</Menu.Item>
12021202
))}
12031203
{tsakorpusFlag && (
1204-
<Menu.Item key="corpus_search" href={`http://83.149.198.78:8080/${id[0]}_${id[1]}/search`}>
1204+
<Menu.Item key="corpus_search" href={`http://83.149.198.78/${id[0]}_${id[1]}/search`}>
12051205
{getTranslation("Corpus search")}
12061206
</Menu.Item>
12071207
)}

0 commit comments

Comments
 (0)