mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-06 18:21:12 +00:00
sentence endpoint is paginated now
This commit is contained in:
1 parent
e0d10496c3
commit
9568b8333b
7 files changed
+137
-13
No files matched your search
Generated
+75
@@ -1547,11 +1547,26 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-tag-autocomplete": {
|
||||
"version": "5.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-tag-autocomplete/-/react-tag-autocomplete-5.12.0.tgz",
|
||||
"integrity": "sha512-QvPBUrXnkU5e3EaHiXQcI0oRsV1JwvL2vvgXtY5x7SkW19O3FRGFdcPg4+SA545+pcIsijf1O2wQ/sCCTeEe9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
||||
"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw=="
|
||||
},
|
||||
"@types/tabulator-tables": {
|
||||
"version": "4.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/tabulator-tables/-/tabulator-tables-4.6.7.tgz",
|
||||
"integrity": "sha512-mmPuILf3jdiutn1qbqSAZRVOUPUemsjeTClHC8iwEdi6wjIptz/t5e2xYO+EVlia7XvWAiD00Y+y1iF2cKkxbw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/testing-library__dom": {
|
||||
"version": "6.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-6.11.1.tgz",
|
||||
@@ -4829,6 +4844,12 @@
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
|
||||
"dev": true
|
||||
},
|
||||
"es6-symbol": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
|
||||
@@ -6366,6 +6387,12 @@
|
||||
"resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
|
||||
"integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg="
|
||||
},
|
||||
"html-attributes": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/html-attributes/-/html-attributes-1.1.0.tgz",
|
||||
"integrity": "sha1-ggJ6T6x6YHDqbBjMOIauoY1t6gk=",
|
||||
"dev": true
|
||||
},
|
||||
"html-comment-regex": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
|
||||
@@ -8320,6 +8347,12 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
||||
},
|
||||
"lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
@@ -9520,6 +9553,17 @@
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"pick-react-known-prop": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/pick-react-known-prop/-/pick-react-known-prop-0.1.5.tgz",
|
||||
"integrity": "sha512-SnDf64AVdvqoAFpHeZUKT9kdn40Ellj84CPALRxYWqNJ6r6f44eAAT+Jtkb0Suhiw7yg5BdOFAQ25OJnjG+afw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"html-attributes": "^1.1.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"svg-attributes": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
@@ -11092,6 +11136,26 @@
|
||||
"workbox-webpack-plugin": "4.3.1"
|
||||
}
|
||||
},
|
||||
"react-tabulator": {
|
||||
"version": "0.12.7",
|
||||
"resolved": "https://registry.npmjs.org/react-tabulator/-/react-tabulator-0.12.7.tgz",
|
||||
"integrity": "sha512-PQVdB20yMhtq7tt+tkToZKWEdqNPT3EshGl7E3TX222KKhvLk6hz8saJGvzAgCePYGyKkhpRh2dsbl6KQSj2eA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react-tag-autocomplete": "^5.6.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"es6-promise": "^4.2.8",
|
||||
"pick-react-known-prop": "^0.1.5",
|
||||
"react-tag-autocomplete": "^5.7.1",
|
||||
"tabulator-tables": "^4.6.2"
|
||||
}
|
||||
},
|
||||
"react-tag-autocomplete": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-tag-autocomplete/-/react-tag-autocomplete-5.13.1.tgz",
|
||||
"integrity": "sha512-ECcQnizAxw8VnEDUfCKuA2ZDQ0Fyxds3kVtE4NVAhJvBYOMMgkRNAM3UwyEXAQ0h7nnCwmIA+czJiwso07Mrqw==",
|
||||
"dev": true
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||
@@ -12545,6 +12609,12 @@
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"svg-attributes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/svg-attributes/-/svg-attributes-1.0.0.tgz",
|
||||
"integrity": "sha1-tcWWjzYke32+OFMgfyqcaK2Aa/w=",
|
||||
"dev": true
|
||||
},
|
||||
"svg-parser": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.2.tgz",
|
||||
@@ -12608,6 +12678,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"tabulator-tables": {
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-4.6.3.tgz",
|
||||
"integrity": "sha512-e/SeG1jU5ryg0OlBpKo89ZmKTYdgfRYLRT366Vu17jIrTFxtyaAhgg95N7L0vzvnvQHuSATUY3UynHzYh2iDYw=="
|
||||
},
|
||||
"tapable": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-scripts": "3.3.0",
|
||||
"react-tabulator": "^0.12.7",
|
||||
"tabulator-tables": "^4.6.3",
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -42,6 +44,7 @@
|
||||
"devDependencies": {
|
||||
"@types/howler": "^2.1.2",
|
||||
"@types/react": "^16.9.17",
|
||||
"@types/react-dom": "^16.9.4"
|
||||
"@types/react-dom": "^16.9.4",
|
||||
"@types/tabulator-tables": "^4.6.7"
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ class ApiConfig {
|
||||
case "localhost":
|
||||
switch (url.port) {
|
||||
case "8080":
|
||||
case "7000":
|
||||
console.log('environment', 'localhost_js');
|
||||
environment = Environment.LOCALHOST_JS;
|
||||
break;
|
||||
|
||||
@@ -2,13 +2,18 @@ import React from 'react';
|
||||
import './App.css';
|
||||
import { MainComponent } from './components/MainComponent';
|
||||
import ApiConfig from './ApiConfig';
|
||||
import { SentencesComponent } from './components/sentences/SentencesComponent';
|
||||
|
||||
const App: React.FC = () => {
|
||||
let apiConfig = new ApiConfig();
|
||||
//
|
||||
//<h1>Neural TTS</h1>
|
||||
//<MainComponent apiConfig={apiConfig} />
|
||||
//
|
||||
return (
|
||||
<div className="App">
|
||||
<h1>Neural TTS</h1>
|
||||
<MainComponent apiConfig={apiConfig} />
|
||||
<br />
|
||||
<SentencesComponent />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::database::connector::{DatabaseConnector, MysqlPooledConnection};
|
||||
use crate::schema::sentences;
|
||||
//use crate::schema::sentences::dsl::*;
|
||||
use diesel::prelude::*;
|
||||
use diesel::expression::dsl::count_star;
|
||||
|
||||
#[derive(Queryable, Serialize, Debug)]
|
||||
pub struct Sentence {
|
||||
@@ -35,11 +36,22 @@ impl NewSentence {
|
||||
|
||||
impl Sentence {
|
||||
|
||||
pub fn load(db_connector: &DatabaseConnector, limit: i64) -> AnyhowResult<Vec<Sentence>> {
|
||||
/// Get a count of all sentence records.
|
||||
pub fn count(db_connector: &DatabaseConnector) -> AnyhowResult<i64> {
|
||||
let pooled_connection : MysqlPooledConnection = db_connector.get_pooled_connection()?;
|
||||
let count : i64 = sentences::dsl::sentences
|
||||
.select(count_star())
|
||||
.first(&*pooled_connection)?;
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
/// Load sentence records
|
||||
pub fn load(db_connector: &DatabaseConnector, limit: i64, offset: i64) -> AnyhowResult<Vec<Sentence>> {
|
||||
let pooled_connection : MysqlPooledConnection = db_connector.get_pooled_connection()?;
|
||||
let results = sentences::dsl::sentences
|
||||
.limit(limit)
|
||||
.order(sentences::dsl::id.desc())
|
||||
.offset(offset)
|
||||
.order(sentences::dsl::id.asc())
|
||||
.load::<Sentence>(&pooled_connection)?;
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use actix_web::web::{
|
||||
Data,
|
||||
Json,
|
||||
};
|
||||
use actix_web::web::{Data, Json, Query};
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{HttpRequest, get, HttpResponse, Either};
|
||||
|
||||
@@ -9,20 +6,46 @@ use std::sync::Arc;
|
||||
use crate::AppState;
|
||||
use crate::database::model::Sentence;
|
||||
|
||||
/// Request with pagination from Tabulator.js
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct SentencesRequest {
|
||||
page: Option<i64>,
|
||||
per_page: Option<i64>,
|
||||
}
|
||||
|
||||
/// Paginated responses in the format expected by Tabulator.js
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct SentencesResult {
|
||||
sentences: Vec<Sentence>,
|
||||
record_count: i64, // Added for my own purposes
|
||||
last_page: i64,
|
||||
data: Vec<Sentence>,
|
||||
}
|
||||
|
||||
#[get("/sentences")]
|
||||
pub async fn get_sentences(
|
||||
_request: HttpRequest,
|
||||
query: Query<SentencesRequest>,
|
||||
app_state: Data<Arc<AppState>>
|
||||
) -> Either<Json<SentencesResult>, std::io::Result<HttpResponse>>{
|
||||
|
||||
debug!("SentencesRequest: {:?}", query);
|
||||
|
||||
let app_state = app_state.into_inner();
|
||||
|
||||
let limit = 1000;
|
||||
let sentences = match Sentence::load(&app_state.database_connector, limit) {
|
||||
let sentence_count = Sentence::count(&app_state.database_connector)
|
||||
.ok()
|
||||
.unwrap_or(0);
|
||||
|
||||
debug!("Total Sentence Records: {:?}", sentence_count);
|
||||
|
||||
let page = query.page.unwrap_or(1);
|
||||
let limit = query.per_page.unwrap_or(100);
|
||||
|
||||
let offset = limit * (page - 1);
|
||||
|
||||
debug!("Sentence Query Limit: {}, Offset: {}", limit, offset);
|
||||
|
||||
let sentences = match Sentence::load(&app_state.database_connector, limit, offset) {
|
||||
Err(e) => {
|
||||
error!("Couldn't query database for sentences: {:?}", e);
|
||||
return Either::B(Ok(HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
@@ -32,7 +55,11 @@ pub async fn get_sentences(
|
||||
Ok(results) => results,
|
||||
};
|
||||
|
||||
let last_page = sentence_count / limit;
|
||||
|
||||
Either::A(Json(SentencesResult {
|
||||
sentences: sentences,
|
||||
data: sentences,
|
||||
last_page,
|
||||
record_count: sentence_count,
|
||||
}))
|
||||
}
|
||||
@@ -205,6 +205,7 @@ async fn run_server(app_state: AppState, server_args: ServerArgs) -> std::io::Re
|
||||
.allowed_methods(vec!["GET", "POST", "OPTIONS"])
|
||||
.allowed_headers(vec![
|
||||
http::header::ACCEPT,
|
||||
http::header::ACCESS_CONTROL_ALLOW_ORIGIN, // Tabulator Ajax
|
||||
http::header::CONTENT_TYPE,
|
||||
http::header::HeaderName::from_static("x-requested-with") // Tabulator Ajax sends
|
||||
])
|
||||
|
||||
Reference in new issue
Block a user