Skip to content

Commit

Permalink
Add buttons to individually remove datasets, pron dicts and models (#279
Browse files Browse the repository at this point in the history
)

* Rename delete to filesDelete

* Dataset deletion working

* Finalise dataset deletion and loading logic

* Actually remove dataset, pd and model folders

* Add deletion support for pron dicts

* Add ability to delete models, and remove print logs

* Eslint fix
  • Loading branch information
mattchrlw committed Dec 23, 2021
1 parent 970bf02 commit 862d436
Show file tree
Hide file tree
Showing 22 changed files with 10,994 additions and 11,130 deletions.
55 changes: 41 additions & 14 deletions elpis/endpoints/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,34 @@ def load():
data.update({
"wordlist": wordlist
})
else:
dataset.auto_select_importer()
return jsonify({
"status": 200,
"data": data
})

@bp.route("/delete", methods=['POST'])
def delete():
interface: Interface = app.config['INTERFACE']
dsname = request.json['name']
# Cascade down, first remove models, then pron_dicts
for m in interface.list_models_verbose():
if m['dataset_name'] == dsname:
interface.remove_model(m['name'])
for pd in interface.list_pron_dicts_verbose():
if pd['dataset_name'] == dsname:
interface.remove_pron_dict(pd['name'])
# Then, remove the dataset
interface.remove_dataset(dsname)
data = {
"list": interface.list_datasets(),
"name": ""
}
return jsonify({
"status": 200,
"data": data
})

@bp.route("/list", methods=['GET'])
def list_existing():
Expand Down Expand Up @@ -100,7 +123,7 @@ def files(dataset: Dataset):

@bp.route("/files/delete", methods=['POST'])
@require_dataset
def delete(dataset: Dataset):
def files_delete(dataset: Dataset):
if request.method == 'POST':
dataset.remove_file(request.form["file"])
dataset.refresh_ui()
Expand All @@ -114,22 +137,26 @@ def delete(dataset: Dataset):
@bp.route("/import/settings", methods=['GET', 'POST'])
@require_dataset
def settings(dataset: Dataset):
# Only edit if POST
if request.method == 'POST':
settings = dataset.importer.get_settings()
for key in request.json.keys():
if key in settings.keys():
dataset.importer.set_setting(key, request.json[key])
else:
pass # TODO throw an invalid key error here?

if dataset.importer is not None:
# Only edit if POST
if request.method == 'POST':
settings = dataset.importer.get_settings()
for key in request.json.keys():
if key in settings.keys():
dataset.importer.set_setting(key, request.json[key])
else:
pass # TODO throw an invalid key error here?
# Return imports current/updated settings.
data = {
'settings': dataset.importer.get_settings()
}
data = {
'settings': dataset.importer.get_settings()
}
return jsonify({
"status": 200,
"data": data
})
return jsonify({
"status": 200,
"data": data
"data": {}
})


Expand Down
13 changes: 13 additions & 0 deletions elpis/endpoints/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ def load():
"data": data
})

@bp.route("/delete", methods=['POST'])
def delete():
interface = app.config['INTERFACE']
mname = request.json["name"]
interface.remove_model(mname)
data = {
"list": interface.list_models_verbose(),
"name": ""
}
return jsonify({
"status": 200,
"data": data
})

@bp.route("/list", methods=['GET'])
def list_existing():
Expand Down
19 changes: 18 additions & 1 deletion elpis/endpoints/pron_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def load():
"l2s": pron_dict.get_l2s_content(),
"lexicon": pron_dict.get_lexicon_content()
}
except KaldiError:
except KeyError:
datasets = interface.list_datasets()
dataset = interface.get_dataset(datasets[0])
pron_dict = None
Expand All @@ -55,6 +55,23 @@ def load():
"data": data
})

@bp.route("/delete", methods=['POST'])
def delete():
interface: Interface = app.config['INTERFACE']
pdname = request.json['name']
for m in interface.list_models_verbose():
if m['pron_dict_name'] == pdname:
interface.remove_model(m['name'])
interface.remove_pron_dict(pdname)
data = {
"list": interface.list_pron_dicts_verbose(),
"name": ""
}
return jsonify({
"status": 200,
"data": data
})


@bp.route("/list", methods=['GET'])
def list_existing():
Expand Down
48 changes: 48 additions & 0 deletions elpis/engines/common/objects/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ def get_dataset(self, dsname):
hash_dir = self.config['datasets'][dsname]
return Dataset.load(self.datasets_path.joinpath(hash_dir))

def remove_dataset(self, dsname):
if dsname not in self.list_datasets():
raise InterfaceError(f'Tried to delete a dataset called "{dsname}" that does not exist')
datasets = self.config['datasets']
del datasets[dsname]
self.config['datasets'] = datasets
for hash_dir in os.listdir(f'{self.datasets_path}'):
if not hash_dir.startswith('.'):
names = []
with self.datasets_path.joinpath(hash_dir, "dataset.json").open() as fin:
names.append(json.load(fin)['name'])
for name in names:
if name == dsname:
shutil.rmtree(self.datasets_path.joinpath(hash_dir))
return self.config['datasets']

def list_datasets(self):
names = [name for name in self.config['datasets'].keys()]
return names
Expand All @@ -181,6 +197,22 @@ def get_pron_dict(self, pdname):
pd.dataset = self.get_dataset(pd.config['dataset_name'])
return pd

def remove_pron_dict(self, pdname):
if pdname not in self.list_pron_dicts():
raise InterfaceError(f'Tried to delete a pron dict called "{pdname}" that does not exist')
pron_dicts = self.config['pron_dicts']
del pron_dicts[pdname]
self.config['pron_dicts'] = pron_dicts
for hash_dir in os.listdir(f'{self.pron_dicts_path}'):
if not hash_dir.startswith('.'):
names = []
with self.pron_dicts_path.joinpath(hash_dir, "pron_dict.json").open() as fin:
names.append(json.load(fin)['name'])
for name in names:
if name == pdname:
shutil.rmtree(self.pron_dicts_path.joinpath(hash_dir))
return self.config['pron_dicts']

def list_pron_dicts(self):
names = [name for name in self.config['pron_dicts'].keys()]
return names
Expand Down Expand Up @@ -220,6 +252,22 @@ def get_model(self, mname):
m.pron_dict = self.get_pron_dict(m.config['pron_dict_name'])
return m

def remove_model(self, mname):
if mname not in self.list_models():
raise InterfaceError(f'Tried to delete a model called "{mname}" that does not exist')
models = self.config['models']
del models[mname]
self.config['models'] = models
for hash_dir in os.listdir(f'{self.models_path}'):
if not hash_dir.startswith('.'):
names = []
with self.models_path.joinpath(hash_dir, "model.json").open() as fin:
names.append(json.load(fin)['name'])
for name in names:
if name == mname:
shutil.rmtree(self.models_path.joinpath(hash_dir))
return self.config['models']

def list_models(self):
models = []
for hash_dir in os.listdir(f'{self.models_path}'):
Expand Down
38 changes: 29 additions & 9 deletions elpis/gui/src/components/Dataset/Dashboard.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, {Component} from "react";
import {Button, Grid, Header, Segment, Table} from "semantic-ui-react";
import {Button, Grid, Header, Icon, Label, Segment, Table} from "semantic-ui-react";
import {Link} from "react-router-dom";
import {connect} from "react-redux";
import {withTranslation} from "react-i18next";
import {datasetList, datasetLoad} from "redux/actions/datasetActions";
import {datasetDelete, datasetList, datasetLoad} from "redux/actions/datasetActions";
import arraySort from "array-sort";
import Branding from "../Shared/Branding";
import SideNav from "../Shared/SideNav";
Expand Down Expand Up @@ -43,6 +43,13 @@ class DatasetDashboard extends Component {
datasetLoad(postData);
}

handleDelete = name => {
const {datasetDelete} = this.props;
const postData = {name: name};

datasetDelete(postData);
}

render() {
const {t, currentEngine, name, list} = this.props;
const {column, direction} = this.state;
Expand All @@ -63,17 +70,23 @@ class DatasetDashboard extends Component {
</Table.Header>
<Table.Body>
{list.map(datasetName => {
const className = (datasetName === name) ? "current" : "";
const className = (datasetName === name) ? "dataset-label current" : "dataset-label";

return (
<Table.Row key={datasetName}>
<Table.Cell>
<Button
className={className}
fluid
onClick={() => this.handleLoad(datasetName)}
>
{datasetName}
<Button as="div" labelPosition="left" className="dataset-button">
<Label
as="a"
className={className}
onClick={() => this.handleLoad(datasetName)}
basic
>
<div className="dataset-truncate">{datasetName}</div>
</Label>
<Button icon onClick={() => this.handleDelete(datasetName)}>
<Icon name="trash" />
</Button>
</Button>
</Table.Cell>
</Table.Row>
Expand Down Expand Up @@ -150,6 +163,13 @@ const mapDispatchToProps = dispatch => ({
})
.catch(error => console.log("error", error));
},
datasetDelete: postData => {
dispatch(datasetDelete(postData))
.then(response => {
console.log("Dataset deleted", response);
})
.catch(error => console.log("error", error));
},
});

export default connect(mapStateToProps, mapDispatchToProps)(
Expand Down
8 changes: 4 additions & 4 deletions elpis/gui/src/components/Dataset/Files.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {withRouter} from "react-router-dom";
import {Button, Grid, Header, Icon, List, Message, Segment, Label, Popup} from "semantic-ui-react";
import {connect} from "react-redux";
import {withTranslation} from "react-i18next";
import {datasetSettings, datasetPrepare, datasetDelete} from "redux/actions/datasetActions";
import {datasetSettings, datasetPrepare, datasetFilesDelete} from "redux/actions/datasetActions";
import Branding from "../Shared/Branding";
import SideNav from "../Shared/SideNav";
import FileUpload from "./FileUpload";
Expand All @@ -23,7 +23,7 @@ class DatasetFiles extends Component {
var deleteData = new FormData();

deleteData.append("file", file);
this.props.datasetDelete(deleteData);
this.props.datasetFilesDelete(deleteData);
}

createFilesList = (files) => files.map(file => (
Expand Down Expand Up @@ -196,8 +196,8 @@ const mapDispatchToProps = dispatch => ({
history.push(urls.gui.dataset.prepare);
});
},
datasetDelete: postData => {
dispatch(datasetDelete(postData));
datasetFilesDelete: postData => {
dispatch(datasetFilesDelete(postData));
},
});

Expand Down
40 changes: 30 additions & 10 deletions elpis/gui/src/components/Model/Dashboard.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, {Component} from "react";
import {Button, Grid, Header, Segment, Table} from "semantic-ui-react";
import {Button, Grid, Header, Icon, Label, Segment, Table} from "semantic-ui-react";
import {Link} from "react-router-dom";
import {connect} from "react-redux";
import {withTranslation} from "react-i18next";
import {modelLoad, modelList} from "redux/actions/modelActions";
import {modelDelete, modelLoad, modelList} from "redux/actions/modelActions";
import {datasetLoad} from "redux/actions/datasetActions";
import {pronDictLoad} from "redux/actions/pronDictActions";
import arraySort from "array-sort";
Expand Down Expand Up @@ -47,6 +47,13 @@ class ModelDashboard extends Component {
modelLoad(modelData, datasetData, pronDictData);
}

handleDelete = values => {
const {modelDelete} = this.props;
const modelData = {name: values.name};

modelDelete(modelData);
}

render() {
const {t, engine, engineHumanNames, name, list} = this.props;
const {column, direction} = this.state;
Expand Down Expand Up @@ -94,17 +101,23 @@ class ModelDashboard extends Component {
</Table.Header>
<Table.Body>
{list_sorted.map(model => {
const className = (name === model.name) ? "current" : "";
const className = (name === model.name) ? "model-label current" : "model-label";

return (
<Table.Row key={model.name} className={className}>
<Table.Row key={model.name}>
<Table.Cell>
<Button
className={className}
fluid
onClick={() => this.handleLoad(model)}
>
{model.name}
<Button as="div" labelPosition="left" className="model-button">
<Label
as="a"
className={className}
onClick={() => this.handleLoad(model)}
basic
>
<div className="model-truncate">{model.name}</div>
</Label>
<Button icon onClick={() => this.handleDelete(model)}>
<Icon name="trash" />
</Button>
</Button>
</Table.Cell>
<Table.Cell>
Expand Down Expand Up @@ -205,6 +218,13 @@ const mapDispatchToProps = dispatch => ({
}
});
},
modelDelete: (modelData) => {
dispatch(modelDelete(modelData))
.then(response => {
console.log("Model deleted", response);
})
.catch(error => console.log("error", error));
},
});

export default connect(mapStateToProps, mapDispatchToProps)(
Expand Down

0 comments on commit 862d436

Please sign in to comment.