Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distances summary -- https://github.com/ispras/lingvodoc-react/issues/1142 #1143

Merged
merged 10 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Layout/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,22 @@ import DashboardRoute from "pages/DashboardRoute";
import Desktop from "pages/Desktop";
import DialeqtImport from "pages/DialeqtImport";
import DictImport from "pages/DictImport";
import ComplexDistance from "pages/ComplexDistance";
import CorpImport from "pages/CorpImport";
import DictionariesAll from "pages/DictionariesAll";
import DistanceMap from "pages/DistanceMap";
import MapSelectedLanguages from "pages/DistanceMap/map";
import SelectedLanguages from "pages/DistanceMap/selectorLangGroup";
import Docx2Eaf from "pages/Docx2Eaf";
import Docx2Xlsx from "pages/Docx2Xlsx";
import ListCognates from "pages/ListCognates";
import EditTranslations from "pages/EditTranslations";
import Files from "pages/Files";
import Grants from "pages/Grants";
import GrantsRoute from "pages/GrantsRoute";
import Info from "pages/Info";
import Languages from "pages/Languages";
import LanguagesDatabasesRoute from "pages/LanguagesDatabasesRoute";
import ListCognates from "pages/ListCognates";
import Map from "pages/Map";
import NotFound from "pages/NotFound";
import Organizations from "pages/Organizations";
Expand Down Expand Up @@ -81,6 +82,7 @@ const AppRoutes = () => (
<Route path="/valency" element={<Valency />} />
<Route path="/adverb" element={<Adverb />} />
<Route path="/list_cognates" element={<ListCognates />} />
<Route path="/complex_distance" element={<ComplexDistance />} />
<Route element={<NotFound />} />
</Routes>
);
Expand Down
46 changes: 31 additions & 15 deletions src/components/CognateAnalysisModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ const computeCognateAnalysisMutation = gql`
translation_count
result
xlsx_url
json_url
figure_url
minimum_spanning_tree
embedding_2d
Expand Down Expand Up @@ -208,6 +209,7 @@ const computeSwadeshAnalysisMutation = gql`
transcription_count
result
xlsx_url
json_url
minimum_spanning_tree
embedding_2d
embedding_3d
Expand Down Expand Up @@ -236,6 +238,7 @@ const computeMorphCognateAnalysisMutation = gql`
transcription_count
result
xlsx_url
json_url
minimum_spanning_tree
embedding_2d
embedding_3d
Expand Down Expand Up @@ -1260,6 +1263,7 @@ class CognateAnalysisModal extends React.Component {

result: null,
xlsx_url: "",
json_url: "",
figure_url: "",

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

for (const { perspective } of language.perspective_list) {
for (const { perspective, treePathList: [subLanguage,] } of language.perspective_list) {
const p_key = id2str(perspective.id);

if (this.state.perspectiveSelectionMap[p_key]) {
perspectiveInfoList.push([
subLanguage.__typename === "Language" ? subLanguage.id : this.baseLanguageId,
perspective.id,
this.fieldDict[this.state.transcriptionFieldIdStrMap[p_key]].id,
this.fieldDict[this.state.translationFieldIdStrMap[p_key]].id,
Expand All @@ -2138,7 +2143,8 @@ class CognateAnalysisModal extends React.Component {
} else {
perspectiveInfoList = this.perspective_list

.map(({ perspective }, index) => [
.map(({ perspective, treePathList: [subLanguage,] }, index) => [
subLanguage.__typename === "Language" ? subLanguage.id : this.baseLanguageId,
perspective.id,
this.fieldDict[this.state.transcriptionFieldIdStrList[index]].id,
this.fieldDict[this.state.translationFieldIdStrList[index]].id,
Expand Down Expand Up @@ -2798,9 +2804,28 @@ class CognateAnalysisModal extends React.Component {

const { language_list, perspectiveSelectionCountMap } = this.state;

const disabledCompute = (
(!multi && (this.perspective_list.length <= 1 ||
!this.state.perspectiveSelectionList.some(enabled => enabled))) ||
(multi &&
(language_list.length <= 0 ||
(mode === "multi_reconstruction" &&
language_list.filter(language => perspectiveSelectionCountMap[id2str(language.id)] > 0).length <=
1) ||
perspectiveSelectionCountMap[""] <= 0)) ||
this.state.computing
)

return (
<div>
<Modal closeIcon onClose={this.props.closeModal} dimmer open size="fullscreen" className="lingvo-modal2">
<Modal
onKeyDown = { e => {
if (e.key === 'Enter' && !disabledCompute) this.handleCreate(); }}
tabIndex = "0"
closeIcon
onClose={this.props.closeModal}
dimmer open
size="fullscreen" className="lingvo-modal2">
<Modal.Header>
{mode === "acoustic"
? this.context("Cognate acoustic analysis")
Expand Down Expand Up @@ -2839,18 +2864,7 @@ class CognateAnalysisModal extends React.Component {
)
}
onClick={this.handleCreate}
disabled={
(!multi &&
(this.perspective_list.length <= 1 ||
!this.state.perspectiveSelectionList.some(enabled => enabled))) ||
(multi &&
(language_list.length <= 0 ||
(mode === "multi_reconstruction" &&
language_list.filter(language => perspectiveSelectionCountMap[id2str(language.id)] > 0).length <=
1) ||
perspectiveSelectionCountMap[""] <= 0)) ||
this.state.computing
}
disabled={disabledCompute}
className="lingvo-button-violet"
/>
<Button
Expand Down Expand Up @@ -2890,6 +2904,8 @@ class CognateAnalysisModal extends React.Component {
{this.state.result.length > 0 && mode !== "suggestions" && mode !== "multi_suggestions" && (
<div className="lingvo-cognate-text" style={{ paddingTop: "6px", paddingBottom: "3px" }}>
<a href={this.state.xlsx_url}>{this.context("XLSX-exported analysis results")}</a>
<p/>
<a href={this.state.json_url}>{this.context("JSON-exported analysis results")}</a>
</div>
)}

Expand Down
149 changes: 149 additions & 0 deletions src/pages/ComplexDistance/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { connect } from "react-redux";
import { Button, Dimmer, Icon, Input, Label, Loader, Message, Segment } from "semantic-ui-react";
import { gql, useMutation } from "@apollo/client";
import React, { useContext, useState, useEffect } from "react";

import "./style.scss";

import TranslationContext from "Layout/TranslationContext";

const complexDistanceMutation = gql`
mutation complexDistance (
$resultPool: [ObjectVal]!
$debugFlag: Boolean
) {
complex_distance(
result_pool: $resultPool
debug_flag: $debugFlag
) {
result
minimum_spanning_tree
embedding_2d
embedding_3d
language_name_list
message
triumph
}
}
`;

const ComplexDistance = connect(state => state.user)(({user}) => {

const [cleanResult, setCleanResult] = useState(false);
const [fileSuite, setFileSuite] = useState(null);
const [getComplexDistance, { data, error, loading }] = useMutation(complexDistanceMutation);

useEffect(() => setCleanResult(false), [loading, data]);
const getTranslation = useContext(TranslationContext);

const debugFlag = false;

const runMutation = () => {

if (loading)
return;

const resultPool = new Array(fileSuite.length);

for (const [index, file] of fileSuite.entries()) {
const reader = new FileReader();
reader.onload = () => {
resultPool[index] = JSON.parse(reader.result);
if ((index + 1) == fileSuite.length) {
getComplexDistance(
{ variables:
{
resultPool,
debugFlag
}
}
);
}
};
reader.readAsText(file);
}
}

return (
<div className="background-content">
{(user.id === undefined) && !loading ? (
<Message>
<Message.Header>{getTranslation("Please sign in")}</Message.Header>
<p>{getTranslation("This page is available for registered users only")}</p>
</Message>
) : loading ? (
<Segment>
<Loader active inline="centered" indeterminate>
{getTranslation("Loading")}...
</Loader>
</Segment>
) : (
<Segment onKeyDown = {(e) => { if (e.key === 'Enter') document.getElementById("get-result").click(); }} tabIndex="0">
<span>
{ getTranslation(
fileSuite ? "Json file(s) for complex result:" : "Please select result file(s) for calculating."
)}
</span>

{ fileSuite && fileSuite.map(({ name: fileName }) => (
<Label style={{ margin: "0.5em" }}>
<Icon name="file outline" />
{ fileName }
</Label>
))}

<Button style={{ marginLeft: "1em" }} onClick={() => document.getElementById("file-select").click()}>
{`${getTranslation("Browse")}...`}
</Button>

<Input
id="file-select"
type="file"
multiple
style={{ display: "none" }}
onChange={e => setFileSuite(Array.from(e.target.files))}
/>
<p/>
<Button
color={fileSuite ? "green" : "gray"}
id="get-result"
disabled={!fileSuite}
content={getTranslation("Get complex distance")}
onClick={runMutation}
/>
{ error && !cleanResult && (
<Message negative>
<Message.Header>{getTranslation("Request error")}</Message.Header>
<p>
<span>{getTranslation("Please contact developers at")} </span>
<a href="https://t.me/lingvodoc_support" target="_blank" rel="noreferrer">
{getTranslation("Support@Telegram")}
</a>
<span> {getTranslation("or at")} </span>
<a href="https://github.com/ispras/lingvodoc-react/issues">{getTranslation("Lingvodoc Github")}</a>
<span>.</span>
</p>
<p> {error.message} </p>
</Message>
)}
{ data && !data.complex_distance.triumph && !error && !cleanResult && (
<Message negative>
<Message.Header>{getTranslation("Request error")}</Message.Header>
<p> {data.complex_distance.message} </p>
</Message>
)}
{ data && data.complex_distance.triumph && !error && !cleanResult && (
<Message positive>
<Message.Header>{getTranslation("Summary distance matrix grouped and merged by languages:")}</Message.Header>
<div dangerouslySetInnerHTML={{ __html: data.complex_distance.result }}></div>
</Message>
)}
</Segment>
)}
</div>
);
})

ComplexDistance.contextType = TranslationContext;

export default ComplexDistance;
3 changes: 3 additions & 0 deletions src/pages/ComplexDistance/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pre {
white-space: pre-wrap;
}
1 change: 1 addition & 0 deletions src/pages/DistanceMap/getDistancePerspectives.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ const getDistance = async (dictionaries, allField, mainDictionary, computeDistan

const perspectiveInfoList = perspectiveList
.map(({ perspective }, index) => [
null,
perspective.id,
fieldDict[transcriptionFieldIdStrList[index]].id,
fieldDict[translationFieldIdStrList[index]].id,
Expand Down
6 changes: 6 additions & 0 deletions src/pages/ToolsRoute/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ function ToolsRoute(props) {
<img className="card-item__img" src={imageStorage} />
</Link>
)}
{props.user.id !== undefined && (
<Link className="card-item" to="/complex_distance">
<label className="card-item__label">{getTranslation("Get complex distance between languages")}</label>
<img className="card-item__img card-item__img_map" src={imageMap} />
</Link>
)}
</div>
</div>
</div>
Expand Down