Skip to content

Commit a70c5d2

Browse files
committed
Initial commit
Bug: T272298 Change-Id: I1bbeaa62a133edb071a67b070a0315b0882c94b1
1 parent e469e76 commit a70c5d2

File tree

25 files changed

+13210
-0
lines changed

25 files changed

+13210
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Bodh - A tool that add sense to lexeme
2+
3+
This tool gives wikidata editor to edit the statement of the lexemes.

package.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "bodh-redux",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@material-ui/core": "^4.11.3",
7+
"@material-ui/icons": "^4.11.2",
8+
"@testing-library/jest-dom": "^5.11.4",
9+
"@testing-library/react": "^11.1.0",
10+
"@testing-library/user-event": "^12.1.10",
11+
"axios": "^0.21.1",
12+
"bootstrap": "^4.6.0",
13+
"react": "^17.0.2",
14+
"react-bootstrap": "^1.5.2",
15+
"react-dom": "^17.0.2",
16+
"react-redux": "^7.2.3",
17+
"react-scripts": "4.0.3",
18+
"react-typeahead": "^2.0.0-alpha.8",
19+
"redux": "^4.0.5",
20+
"redux-thunk": "^2.3.0",
21+
"web-vitals": "^1.0.1"
22+
},
23+
"scripts": {
24+
"start": "react-scripts start",
25+
"build": "react-scripts build",
26+
"test": "react-scripts test",
27+
"eject": "react-scripts eject"
28+
},
29+
"eslintConfig": {
30+
"extends": [
31+
"react-app",
32+
"react-app/jest"
33+
]
34+
},
35+
"browserslist": {
36+
"production": [
37+
">0.2%",
38+
"not dead",
39+
"not op_mini all"
40+
],
41+
"development": [
42+
"last 1 chrome version",
43+
"last 1 firefox version",
44+
"last 1 safari version"
45+
]
46+
}
47+
}

public/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<meta name="theme-color" content="#000000" />
7+
<title>Bodh</title>
8+
</head>
9+
<body>
10+
<noscript>You need to enable JavaScript to run this app.</noscript>
11+
<div id="root"></div>
12+
</body>
13+
</html>

src/App.css

Whitespace-only changes.

src/App.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { useSelector } from 'react-redux'
2+
import Header from './components/Header';
3+
import Main from './components/Main';
4+
import Login from "./components/Login";
5+
6+
import './App.css';
7+
8+
// Material-UI component
9+
import Backdrop from '@material-ui/core/Backdrop';
10+
import CircularProgress from '@material-ui/core/CircularProgress';
11+
import { makeStyles } from '@material-ui/core/styles';
12+
import { Paper, Typography } from '@material-ui/core';
13+
14+
const useStyles = makeStyles((theme) => ({
15+
backdrop: {
16+
zIndex: theme.zIndex.drawer + 1,
17+
color: '#fff',
18+
},
19+
}));
20+
21+
function App() {
22+
const classes = useStyles();
23+
const backdropProgress = useSelector(s => s.backdropProgress)
24+
const isLoggedIn = useSelector( s => s.currentUser ) ? true : false
25+
return (
26+
<>
27+
<Header />
28+
<Paper>
29+
<Typography variant="body1" color="secondary">Currently tool in under development.</Typography>
30+
</Paper>
31+
{ isLoggedIn ? <Main /> : <Login/> }
32+
{ backdropProgress ?
33+
<Backdrop className={classes.backdrop} open={backdropProgress}>
34+
<CircularProgress color="inherit" />
35+
</Backdrop>
36+
:
37+
null
38+
}
39+
</>
40+
);
41+
}
42+
43+
export default App;

src/App.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test('Dummy test pass for jenkin', () => {
2+
// Hack to pass to test
3+
expect( true ).toEqual( true );
4+
});

src/actions/index.js

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
import {
2+
getPropById,
3+
addClaimInState,
4+
editClaimInState,
5+
deleteClaimInState
6+
} from './../util';
7+
import backendApi from './../api/backendApi';
8+
import wdSiteApi from './../api/wikidataSiteApi';
9+
import {
10+
SET_PROFILE,
11+
ADD_PROPCOL,
12+
RESET_PROPCOL,
13+
SET_DT_PROGRESS,
14+
SET_BD_PROGRESS,
15+
SET_LEX_ITEMS,
16+
SET_LEXITEM_DATA
17+
} from './../constants';
18+
19+
20+
export function setBackdrop(bool) {
21+
return (dispatch) => {
22+
dispatch({
23+
type: SET_BD_PROGRESS,
24+
payload: bool
25+
})
26+
}
27+
}
28+
29+
export function setProfile() {
30+
return async (dispatch) => {
31+
// Checking whether user is authencated on backend or not
32+
backendApi.get("/api/profile")
33+
.then(({ data }) => {
34+
if (data.logged) {
35+
dispatch({
36+
type: SET_PROFILE,
37+
payload: data.username
38+
})
39+
}
40+
})
41+
.catch(() => alert("Something went wrong with auth."))
42+
}
43+
}
44+
45+
export function addPropertyCol(pId) {
46+
return async (dispatch) => {
47+
const resp = await getPropById(pId)
48+
if (resp !== false) {
49+
dispatch({
50+
type: ADD_PROPCOL,
51+
payload: resp
52+
});
53+
}
54+
};
55+
}
56+
57+
export function removePropertyCol(pId) {
58+
return (dispatch, getState) => {
59+
const { propCol } = getState();
60+
if (pId !== undefined) {
61+
dispatch({
62+
type: RESET_PROPCOL,
63+
payload: propCol.filter((item, index) => index !== pId)
64+
});
65+
} else {
66+
// if pId is not present then remove every property
67+
dispatch({
68+
type: RESET_PROPCOL,
69+
payload: []
70+
});
71+
}
72+
};
73+
}
74+
75+
export function setDataTableProgress(option) {
76+
return (dispatch) => {
77+
dispatch({
78+
type: SET_DT_PROGRESS,
79+
payload: option
80+
})
81+
}
82+
}
83+
84+
export function setLexItems(item) {
85+
return (dispatch) => {
86+
dispatch({
87+
type: SET_LEX_ITEMS,
88+
payload: item
89+
})
90+
dispatch(setLexItemsData())
91+
}
92+
}
93+
94+
export function setLexItemsData() {
95+
return async (dispatch, getState) => {
96+
const { lexItems } = getState();
97+
console.log(lexItems);
98+
const resp = await wdSiteApi.get('/api.php?action=wbgetentities&format=json&origin=*&ids=' + lexItems.join('|'))
99+
dispatch({
100+
type: SET_LEXITEM_DATA,
101+
payload: Object.values(resp.data.entities)
102+
})
103+
}
104+
}
105+
106+
export function createClaim(itemId, pId, type, value) {
107+
return async (dispatch, getState) => {
108+
const resp = await backendApi.post(
109+
'/api/createclaim',
110+
{
111+
"entity": itemId,
112+
"property": pId,
113+
"value": value,
114+
"type": type
115+
},
116+
{
117+
crossDomain: true,
118+
headers: {
119+
'Accept': 'application/json',
120+
'Content-Type': 'application/json'
121+
}
122+
}
123+
)
124+
125+
dispatch(setBackdrop(false))
126+
127+
if (resp.data["success"]) {
128+
let { lexItemsData } = getState()
129+
130+
// Dispatching action to set new data
131+
dispatch({
132+
type: SET_LEXITEM_DATA,
133+
payload: addClaimInState(lexItemsData, itemId, pId, resp.data.claim)
134+
})
135+
return Promise.resolve({
136+
"status": 1
137+
})
138+
} else {
139+
alert("Failed to add the item :(")
140+
return Promise.resolve({
141+
"status": 0
142+
})
143+
}
144+
}
145+
}
146+
147+
export function editClaim(id, p, newValue) {
148+
return async (dispatch, getState) => {
149+
const resp = await backendApi.post(
150+
'/api/editclaim',
151+
{
152+
"claimId": id,
153+
"claimType": p.type,
154+
"value": typeof (newValue) === "string" ? newValue : newValue.id
155+
},
156+
{
157+
crossDomain: true,
158+
headers: {
159+
'Accept': 'application/json',
160+
'Content-Type': 'application/json'
161+
}
162+
}
163+
)
164+
165+
dispatch(setBackdrop(false))
166+
167+
if (resp.data["success"]) {
168+
let { lexItemsData } = getState()
169+
170+
// Dispatching action to set new data
171+
dispatch({
172+
type: SET_LEXITEM_DATA,
173+
payload: editClaimInState(lexItemsData, id, p, newValue)
174+
})
175+
return Promise.resolve({
176+
"status": 1,
177+
"value": typeof (newValue) === "string" ? newValue : newValue.id
178+
})
179+
} else {
180+
alert("Failed to edit the item :(")
181+
return Promise.resolve({
182+
"status": 0
183+
})
184+
}
185+
}
186+
}
187+
188+
export function deleteClaim(id, p) {
189+
return async (dispatch, getState) => {
190+
const resp = await backendApi.post(
191+
'/api/deleteitem',
192+
{
193+
"itemId": id
194+
},
195+
{
196+
crossDomain: true,
197+
headers: {
198+
'Accept': 'application/json',
199+
'Content-Type': 'application/json'
200+
}
201+
}
202+
)
203+
204+
dispatch(setBackdrop(false))
205+
206+
if (resp.data["success"]) {
207+
let { lexItemsData } = getState()
208+
209+
// Dispatching action to set new data
210+
dispatch({
211+
type: SET_LEXITEM_DATA,
212+
payload: deleteClaimInState(lexItemsData, id, p)
213+
})
214+
return Promise.resolve({
215+
"status": 1
216+
})
217+
} else {
218+
alert("Failed to delete the item :(")
219+
return Promise.resolve({
220+
"status": 0
221+
})
222+
}
223+
}
224+
}

src/api/backendApi.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import axios from 'axios';
2+
3+
export default axios.create({
4+
baseURL: 'https://bodh-backend.toolforge.org',
5+
withCredentials: true,
6+
mode: 'cors'
7+
});
8+

src/api/wikiApi.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
export default function WikiApi() {
2+
this.api = 'https://www.wikidata.org/w/api.php';
3+
this.sparql_url = 'https://query.wikidata.org/sparql';
4+
this.sparql_query = function (text, cb, cb_fail) {
5+
var url = this.sparql_url + "?format=json&query=" + encodeURIComponent(text);
6+
fetch(url)
7+
.then((res) => res.json())
8+
.catch(cb_fail)
9+
.then((d) => cb(d));
10+
}
11+
this.sparql_items = function (text, cb, cb_fail) {
12+
var self = this;
13+
self.sparql_query(text, function (resp) {
14+
if (typeof resp == 'undefined') {
15+
cb_fail();
16+
return;
17+
}
18+
var data = [];
19+
var vars = resp.head.vars[0];
20+
// Make sure only 500 query at a time.
21+
// TODO: Make tool more flexiable to hanle more request
22+
for (let i = 0; i < resp.results.bindings.length; i++) {
23+
if (data.length >= 500) {
24+
break
25+
}
26+
const d = resp.results.bindings[i][vars];
27+
if (d === "" || typeof d == 'undefined') continue;
28+
if (d.type !== 'uri') continue;
29+
const temp = d.value.replace(/^.+\/([L])/, '$1')
30+
// Check whether the item is lexeme or not
31+
if (temp.startsWith('L') === false) {
32+
alert("First column of the query should contain only LXXXX values");
33+
break;
34+
}
35+
// Don't push duplicate item
36+
if (data.indexOf(temp) === -1) {
37+
data.push(temp)
38+
}
39+
};
40+
console.log(data.length)
41+
cb(data);
42+
}, cb_fail);
43+
}
44+
}

0 commit comments

Comments
 (0)