Skip to content

Commit 8899995

Browse files
authored
Distances summary -- #1142 (#1143)
* json result * fixe and refactoring * getting language id * getting language_id * next steps * export html * init frontend * enhanced frontend * debugging * beauty
1 parent 7a79d2a commit 8899995

File tree

6 files changed

+193
-16
lines changed

6 files changed

+193
-16
lines changed

src/Layout/Routes.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,22 @@ import DashboardRoute from "pages/DashboardRoute";
1010
import Desktop from "pages/Desktop";
1111
import DialeqtImport from "pages/DialeqtImport";
1212
import DictImport from "pages/DictImport";
13+
import ComplexDistance from "pages/ComplexDistance";
1314
import CorpImport from "pages/CorpImport";
1415
import DictionariesAll from "pages/DictionariesAll";
1516
import DistanceMap from "pages/DistanceMap";
1617
import MapSelectedLanguages from "pages/DistanceMap/map";
1718
import SelectedLanguages from "pages/DistanceMap/selectorLangGroup";
1819
import Docx2Eaf from "pages/Docx2Eaf";
1920
import Docx2Xlsx from "pages/Docx2Xlsx";
20-
import ListCognates from "pages/ListCognates";
2121
import EditTranslations from "pages/EditTranslations";
2222
import Files from "pages/Files";
2323
import Grants from "pages/Grants";
2424
import GrantsRoute from "pages/GrantsRoute";
2525
import Info from "pages/Info";
2626
import Languages from "pages/Languages";
2727
import LanguagesDatabasesRoute from "pages/LanguagesDatabasesRoute";
28+
import ListCognates from "pages/ListCognates";
2829
import Map from "pages/Map";
2930
import NotFound from "pages/NotFound";
3031
import Organizations from "pages/Organizations";
@@ -81,6 +82,7 @@ const AppRoutes = () => (
8182
<Route path="/valency" element={<Valency />} />
8283
<Route path="/adverb" element={<Adverb />} />
8384
<Route path="/list_cognates" element={<ListCognates />} />
85+
<Route path="/complex_distance" element={<ComplexDistance />} />
8486
<Route element={<NotFound />} />
8587
</Routes>
8688
);

src/components/CognateAnalysisModal/index.js

+31-15
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ const computeCognateAnalysisMutation = gql`
176176
translation_count
177177
result
178178
xlsx_url
179+
json_url
179180
figure_url
180181
minimum_spanning_tree
181182
embedding_2d
@@ -208,6 +209,7 @@ const computeSwadeshAnalysisMutation = gql`
208209
transcription_count
209210
result
210211
xlsx_url
212+
json_url
211213
minimum_spanning_tree
212214
embedding_2d
213215
embedding_3d
@@ -236,6 +238,7 @@ const computeMorphCognateAnalysisMutation = gql`
236238
transcription_count
237239
result
238240
xlsx_url
241+
json_url
239242
minimum_spanning_tree
240243
embedding_2d
241244
embedding_3d
@@ -1260,6 +1263,7 @@ class CognateAnalysisModal extends React.Component {
12601263

12611264
result: null,
12621265
xlsx_url: "",
1266+
json_url: "",
12631267
figure_url: "",
12641268

12651269
minimum_spanning_tree: [],
@@ -2118,11 +2122,12 @@ class CognateAnalysisModal extends React.Component {
21182122
for (const language of this.state.language_list) {
21192123
let p_count = 0;
21202124

2121-
for (const { perspective } of language.perspective_list) {
2125+
for (const { perspective, treePathList: [subLanguage,] } of language.perspective_list) {
21222126
const p_key = id2str(perspective.id);
21232127

21242128
if (this.state.perspectiveSelectionMap[p_key]) {
21252129
perspectiveInfoList.push([
2130+
subLanguage.__typename === "Language" ? subLanguage.id : this.baseLanguageId,
21262131
perspective.id,
21272132
this.fieldDict[this.state.transcriptionFieldIdStrMap[p_key]].id,
21282133
this.fieldDict[this.state.translationFieldIdStrMap[p_key]].id,
@@ -2138,7 +2143,8 @@ class CognateAnalysisModal extends React.Component {
21382143
} else {
21392144
perspectiveInfoList = this.perspective_list
21402145

2141-
.map(({ perspective }, index) => [
2146+
.map(({ perspective, treePathList: [subLanguage,] }, index) => [
2147+
subLanguage.__typename === "Language" ? subLanguage.id : this.baseLanguageId,
21422148
perspective.id,
21432149
this.fieldDict[this.state.transcriptionFieldIdStrList[index]].id,
21442150
this.fieldDict[this.state.translationFieldIdStrList[index]].id,
@@ -2798,9 +2804,28 @@ class CognateAnalysisModal extends React.Component {
27982804

27992805
const { language_list, perspectiveSelectionCountMap } = this.state;
28002806

2807+
const disabledCompute = (
2808+
(!multi && (this.perspective_list.length <= 1 ||
2809+
!this.state.perspectiveSelectionList.some(enabled => enabled))) ||
2810+
(multi &&
2811+
(language_list.length <= 0 ||
2812+
(mode === "multi_reconstruction" &&
2813+
language_list.filter(language => perspectiveSelectionCountMap[id2str(language.id)] > 0).length <=
2814+
1) ||
2815+
perspectiveSelectionCountMap[""] <= 0)) ||
2816+
this.state.computing
2817+
)
2818+
28012819
return (
28022820
<div>
2803-
<Modal closeIcon onClose={this.props.closeModal} dimmer open size="fullscreen" className="lingvo-modal2">
2821+
<Modal
2822+
onKeyDown = { e => {
2823+
if (e.key === 'Enter' && !disabledCompute) this.handleCreate(); }}
2824+
tabIndex = "0"
2825+
closeIcon
2826+
onClose={this.props.closeModal}
2827+
dimmer open
2828+
size="fullscreen" className="lingvo-modal2">
28042829
<Modal.Header>
28052830
{mode === "acoustic"
28062831
? this.context("Cognate acoustic analysis")
@@ -2839,18 +2864,7 @@ class CognateAnalysisModal extends React.Component {
28392864
)
28402865
}
28412866
onClick={this.handleCreate}
2842-
disabled={
2843-
(!multi &&
2844-
(this.perspective_list.length <= 1 ||
2845-
!this.state.perspectiveSelectionList.some(enabled => enabled))) ||
2846-
(multi &&
2847-
(language_list.length <= 0 ||
2848-
(mode === "multi_reconstruction" &&
2849-
language_list.filter(language => perspectiveSelectionCountMap[id2str(language.id)] > 0).length <=
2850-
1) ||
2851-
perspectiveSelectionCountMap[""] <= 0)) ||
2852-
this.state.computing
2853-
}
2867+
disabled={disabledCompute}
28542868
className="lingvo-button-violet"
28552869
/>
28562870
<Button
@@ -2890,6 +2904,8 @@ class CognateAnalysisModal extends React.Component {
28902904
{this.state.result.length > 0 && mode !== "suggestions" && mode !== "multi_suggestions" && (
28912905
<div className="lingvo-cognate-text" style={{ paddingTop: "6px", paddingBottom: "3px" }}>
28922906
<a href={this.state.xlsx_url}>{this.context("XLSX-exported analysis results")}</a>
2907+
<p/>
2908+
<a href={this.state.json_url}>{this.context("JSON-exported analysis results")}</a>
28932909
</div>
28942910
)}
28952911

src/pages/ComplexDistance/index.js

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { connect } from "react-redux";
2+
import { Button, Dimmer, Icon, Input, Label, Loader, Message, Segment } from "semantic-ui-react";
3+
import { gql, useMutation } from "@apollo/client";
4+
import React, { useContext, useState, useEffect } from "react";
5+
6+
import "./style.scss";
7+
8+
import TranslationContext from "Layout/TranslationContext";
9+
10+
const complexDistanceMutation = gql`
11+
mutation complexDistance (
12+
$resultPool: [ObjectVal]!
13+
$debugFlag: Boolean
14+
) {
15+
complex_distance(
16+
result_pool: $resultPool
17+
debug_flag: $debugFlag
18+
) {
19+
result
20+
minimum_spanning_tree
21+
embedding_2d
22+
embedding_3d
23+
language_name_list
24+
message
25+
triumph
26+
}
27+
}
28+
`;
29+
30+
const ComplexDistance = connect(state => state.user)(({user}) => {
31+
32+
const [cleanResult, setCleanResult] = useState(false);
33+
const [fileSuite, setFileSuite] = useState(null);
34+
const [getComplexDistance, { data, error, loading }] = useMutation(complexDistanceMutation);
35+
36+
useEffect(() => setCleanResult(false), [loading, data]);
37+
const getTranslation = useContext(TranslationContext);
38+
39+
const debugFlag = false;
40+
41+
const runMutation = () => {
42+
43+
if (loading)
44+
return;
45+
46+
const resultPool = new Array(fileSuite.length);
47+
48+
for (const [index, file] of fileSuite.entries()) {
49+
const reader = new FileReader();
50+
reader.onload = () => {
51+
resultPool[index] = JSON.parse(reader.result);
52+
if ((index + 1) == fileSuite.length) {
53+
getComplexDistance(
54+
{ variables:
55+
{
56+
resultPool,
57+
debugFlag
58+
}
59+
}
60+
);
61+
}
62+
};
63+
reader.readAsText(file);
64+
}
65+
}
66+
67+
return (
68+
<div className="background-content">
69+
{(user.id === undefined) && !loading ? (
70+
<Message>
71+
<Message.Header>{getTranslation("Please sign in")}</Message.Header>
72+
<p>{getTranslation("This page is available for registered users only")}</p>
73+
</Message>
74+
) : loading ? (
75+
<Segment>
76+
<Loader active inline="centered" indeterminate>
77+
{getTranslation("Loading")}...
78+
</Loader>
79+
</Segment>
80+
) : (
81+
<Segment onKeyDown = {(e) => { if (e.key === 'Enter') document.getElementById("get-result").click(); }} tabIndex="0">
82+
<span>
83+
{ getTranslation(
84+
fileSuite ? "Json file(s) for complex result:" : "Please select result file(s) for calculating."
85+
)}
86+
</span>
87+
88+
{ fileSuite && fileSuite.map(({ name: fileName }) => (
89+
<Label style={{ margin: "0.5em" }}>
90+
<Icon name="file outline" />
91+
{ fileName }
92+
</Label>
93+
))}
94+
95+
<Button style={{ marginLeft: "1em" }} onClick={() => document.getElementById("file-select").click()}>
96+
{`${getTranslation("Browse")}...`}
97+
</Button>
98+
99+
<Input
100+
id="file-select"
101+
type="file"
102+
multiple
103+
style={{ display: "none" }}
104+
onChange={e => setFileSuite(Array.from(e.target.files))}
105+
/>
106+
<p/>
107+
<Button
108+
color={fileSuite ? "green" : "gray"}
109+
id="get-result"
110+
disabled={!fileSuite}
111+
content={getTranslation("Get complex distance")}
112+
onClick={runMutation}
113+
/>
114+
{ error && !cleanResult && (
115+
<Message negative>
116+
<Message.Header>{getTranslation("Request error")}</Message.Header>
117+
<p>
118+
<span>{getTranslation("Please contact developers at")} </span>
119+
<a href="https://t.me/lingvodoc_support" target="_blank" rel="noreferrer">
120+
{getTranslation("Support@Telegram")}
121+
</a>
122+
<span> {getTranslation("or at")} </span>
123+
<a href="https://github.com/ispras/lingvodoc-react/issues">{getTranslation("Lingvodoc Github")}</a>
124+
<span>.</span>
125+
</p>
126+
<p> {error.message} </p>
127+
</Message>
128+
)}
129+
{ data && !data.complex_distance.triumph && !error && !cleanResult && (
130+
<Message negative>
131+
<Message.Header>{getTranslation("Request error")}</Message.Header>
132+
<p> {data.complex_distance.message} </p>
133+
</Message>
134+
)}
135+
{ data && data.complex_distance.triumph && !error && !cleanResult && (
136+
<Message positive>
137+
<Message.Header>{getTranslation("Summary distance matrix grouped and merged by languages:")}</Message.Header>
138+
<div dangerouslySetInnerHTML={{ __html: data.complex_distance.result }}></div>
139+
</Message>
140+
)}
141+
</Segment>
142+
)}
143+
</div>
144+
);
145+
})
146+
147+
ComplexDistance.contextType = TranslationContext;
148+
149+
export default ComplexDistance;

src/pages/ComplexDistance/style.scss

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pre {
2+
white-space: pre-wrap;
3+
}

src/pages/DistanceMap/getDistancePerspectives.js

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const getDistance = async (dictionaries, allField, mainDictionary, computeDistan
100100

101101
const perspectiveInfoList = perspectiveList
102102
.map(({ perspective }, index) => [
103+
null,
103104
perspective.id,
104105
fieldDict[transcriptionFieldIdStrList[index]].id,
105106
fieldDict[translationFieldIdStrList[index]].id,

src/pages/ToolsRoute/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ function ToolsRoute(props) {
7676
<img className="card-item__img" src={imageStorage} />
7777
</Link>
7878
)}
79+
{props.user.id !== undefined && (
80+
<Link className="card-item" to="/complex_distance">
81+
<label className="card-item__label">{getTranslation("Get complex distance between languages")}</label>
82+
<img className="card-item__img card-item__img_map" src={imageMap} />
83+
</Link>
84+
)}
7985
</div>
8086
</div>
8187
</div>

0 commit comments

Comments
 (0)