Skip to content

Commit dad978b

Browse files
laksh22ivantha
authored andcommitted
Add Heroku button
1 parent 7b45b15 commit dad978b

File tree

12 files changed

+471
-252
lines changed

12 files changed

+471
-252
lines changed

README.md

+24-13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ LabelLab is an image analyzing and classification platform. It allows users to u
99

1010
See the [LICENSE](https://github.com/scorelab/LabelLab/blob/master/LICENSE) file for details.
1111

12+
#### Deployment
13+
14+
Host your own Labellab server for **FREE** with One-Click Deploy
15+
16+
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
17+
1218
## User Guide
1319

1420
#### How to Setup
@@ -24,56 +30,60 @@ Run `npm install` in `labellab-client` folder.
2430
```
2531
cd labellab-client/
2632
npm install
27-
```
28-
33+
```
34+
2935
#### Set up MongoDB backend
3036

3137
Run `npm install` in `labellab-server` folder.
3238

3339
```
3440
cd labellab-server/
3541
npm install
36-
```
37-
42+
```
43+
3844
#### How to Use
3945

4046
First you need to create a `.env` file in both `labellab-server` folder and `labellab-client` folder following the template provided in the file `.env.example` which is present in both the folders.<br/> <br/>
4147

4248
For client-side `.env` file:
49+
4350
```
4451
REACT_APP_HOST=http://localhost
4552
REACT_APP_SERVER_ENVIORNMENT=dev
4653
REACT_APP_SERVER_PORT=4000
4754
```
4855

4956
For server-side `.env` file:
57+
5058
```
5159
HOST=localhost
5260
PORT=4000
5361
```
54-
`JWT_SECRET` can be any word your choice.
5562

56-
To create a free MongoDB Atlas cloud database, follow the guide at [https://docs.atlas.mongodb.com/getting-started/](https://docs.atlas.mongodb.com/getting-started/). After setting up, find the conection string to your database. It should look like this:
63+
`JWT_SECRET` can be any word your choice.
64+
65+
To create a free MongoDB Atlas cloud database, follow the guide at [https://docs.atlas.mongodb.com/getting-started/](https://docs.atlas.mongodb.com/getting-started/). After setting up, find the conection string to your database. It should look like this:
66+
5767
```
5868
{{DB_HOST}}://{{DB_USERNAME}}:{{DB_PASSWORD}}@{{DB_CLUSTER}}/{{DB_NAME}}
5969
```
70+
6071
You should fill in these values in their relevent fields in the `.env` file.
6172

6273
> **NOTE**: Your IP address may change if you've been disconnected from the internet and reconnected. If that happens, it means that your internet connection doesn't have a static IP. You may no longer be able to access the database if you've whitelisted only your previous IP address. You can allow access from any IP address from the Atlas control panel to overcome this issue.
6374
6475
Both the front-end and the back-end can be run from the `labellab-server` folder using the terminal:
6576

66-
1. To run both the client and server with a single command, run the following:
67-
`$ npm run dev`
77+
1. To run both the client and server with a single command, run the following:
78+
`$ npm run dev`
6879

69-
2. To run the server separately:
70-
`$ npm run server`
80+
2. To run the server separately:
81+
`$ npm run server`
7182

7283
> The server can also be run using `$ npm start`
7384
74-
3. To run the client separately:
75-
`$ npm run client`
76-
85+
3. To run the client separately:
86+
`$ npm run client`
7787

7888
> **NOTE**: Before starting the server create a file named `.env` same as `.env.example` and add your **OAUTH** and **DATABASE** credentials in the file.
7989
@@ -82,6 +92,7 @@ Visit [localhost:3000](http://localhost:3000) to browse.
8292
> **NOTE**: This version only supports Google Chrome and Mozilla Firefox browsers. Make sure to instal the extension [Redux Dev Tools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) if you're using Google Chrome.
8393
8494
#### How to Use (Mobile)
95+
8596
Run the Node server in the `labellab-server` directory (if not already done):
8697

8798
`npm start`

app.json

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"name": "Labellab",
3+
"description": "Machine learning supported web-based image labelling tool for researchers",
4+
"repository": "https://github.com/scorelab/LabelLab",
5+
"logo": "https://media-exp1.licdn.com/dms/image/C511BAQG0CuA8HTmGTA/company-background_10000/0?e=2159024400&v=beta&t=TgDb2TWb3EJWQ0rY6WXZCwMEfcU9jLLSJ2s_H6FQMfs",
6+
"addons": ["mongolab", "cloudinary"],
7+
"env": {
8+
"HOST": {
9+
"description": "Please enter the app name which you entered above"
10+
},
11+
"REACT_APP_HOST": {
12+
"description": "Please enter the app name which you entered above"
13+
},
14+
"JWT_SECRET": {
15+
"description": "A string of random characters"
16+
},
17+
"GOOGLE_CLIENT_ID": {
18+
"description": "Client ID for Google authentication",
19+
"required": false
20+
},
21+
"GOOGLE_CLIENT_SECRET": {
22+
"description": "Client secret for Google authentication",
23+
"required": false
24+
},
25+
"GITHUB_CLIENT_ID": {
26+
"description": "Client ID for Github authentication",
27+
"required": false
28+
},
29+
"GITHUB_CLIENT_SECRET": {
30+
"description": "Client secret for Github authentication",
31+
"required": false
32+
},
33+
"PORT": {
34+
"description": "This should be kept as 4000"
35+
},
36+
"REACT_APP_SERVER_PORT": {
37+
"description": "This should be kept as 4000"
38+
}
39+
},
40+
"scripts": {
41+
"pr-predestroy": "cp .env labellab-server/env && cp .env labellab-client/env"
42+
}
43+
}

labellab-client/src/components/labeller/index.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ class LabelingLoader extends Component {
116116
labels={lab}
117117
labelData={(img && img.labelData) || {}}
118118
imageUrl={
119-
`${process.env.REACT_APP_HOST}:${process.env.REACT_APP_SERVER_PORT}/static/uploads/${image.imageUrl}?${Date.now()}`
119+
process.env.REACT_APP_SERVER_ENVIORNMENT !== 'dev'
120+
? image.imageUrl
121+
: `${process.env.REACT_APP_HOST}:${
122+
process.env.REACT_APP_SERVER_PORT
123+
}/static/uploads/${image.imageUrl}?${Date.now()}`
120124
}
121125
projectUrl={`/project/${match.params.projectId}/images`}
122126
demo={false}
@@ -191,4 +195,7 @@ const mapDispatchToProps = dispatch => {
191195
}
192196
}
193197

194-
export default connect(mapStateToProps, mapDispatchToProps)(LabelingLoader)
198+
export default connect(
199+
mapStateToProps,
200+
mapDispatchToProps
201+
)(LabelingLoader)

labellab-client/src/components/project/images.js

+75-67
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class ImagesIndex extends Component {
122122
maxSizeError: '',
123123
imageUrls: [],
124124
photoIndex: 0,
125-
isOpen: false,
125+
isOpen: false
126126
})
127127
}
128128

@@ -175,14 +175,14 @@ class ImagesIndex extends Component {
175175
nextSrc={imageUrls[(photoIndex + 1) % imageUrls.length]}
176176
prevSrc={
177177
imageUrls[
178-
(photoIndex + imageUrls.length - 1) % imageUrls.length
178+
(photoIndex + imageUrls.length - 1) % imageUrls.length
179179
]
180180
}
181181
onCloseRequest={() => this.setState({ isOpen: false })}
182182
onMovePrevRequest={() =>
183183
this.setState({
184184
photoIndex:
185-
(photoIndex + imageUrls.length - 1) % imageUrls.length,
185+
(photoIndex + imageUrls.length - 1) % imageUrls.length
186186
})
187187
}
188188
onMoveNextRequest={() =>
@@ -288,7 +288,10 @@ const mapDispatchToProps = dispatch => {
288288
}
289289
}
290290

291-
export default connect(mapStateToProps, mapDispatchToProps)(ImagesIndex)
291+
export default connect(
292+
mapStateToProps,
293+
mapDispatchToProps
294+
)(ImagesIndex)
292295

293296
const Row = ({
294297
image,
@@ -298,72 +301,77 @@ const Row = ({
298301
imageId,
299302
onSelect,
300303
selected,
301-
isLast,
304+
isLast
302305
}) => (
303-
<Table.Row
304-
style={{
305-
...style,
306-
display: 'flex',
307-
borderBottom: isLast ? '1px solid rgba(34,36,38,.1)' : '',
308-
}}
309-
>
310-
<Table.Cell width={1}>
311-
{imageId + 1}
312-
{image.labelled ? <Icon name="checkmark green"></Icon> : null}
313-
</Table.Cell>
314-
<Table.Cell width={1}>
315-
<Checkbox
316-
onClick={() => {
317-
onSelect(image._id)
306+
<Table.Row
307+
style={{
308+
...style,
309+
display: 'flex',
310+
borderBottom: isLast ? '1px solid rgba(34,36,38,.1)' : ''
311+
}}
312+
>
313+
<Table.Cell width={1}>
314+
{imageId + 1}
315+
{image.labelled ? <Icon name="checkmark green"></Icon> : null}
316+
</Table.Cell>
317+
<Table.Cell width={1}>
318+
<Checkbox
319+
onClick={() => {
320+
onSelect(image._id)
321+
}}
322+
checked={selected}
323+
/>
324+
</Table.Cell>
325+
<Table.Cell width={11}>
326+
<a
327+
rel={'external'}
328+
href={
329+
process.env.REACT_APP_SERVER_ENVIORNMENT !== 'dev'
330+
? image.imageUrl
331+
: 'http://' +
332+
process.env.REACT_APP_HOST +
333+
':' +
334+
process.env.REACT_APP_SERVER_PORT +
335+
`/static/uploads/${image.imageUrl}?${Date.now()}`
336+
}
337+
>
338+
{image.imageName}
339+
</a>
340+
{image.labelled ? (
341+
<span className="labelDropdown">
342+
<Dropdown text="Labels">
343+
<Dropdown.Menu>
344+
{Object.keys(image.labelData).map((key, index) =>
345+
image.labelData[key].length !== 0 ? (
346+
<Dropdown.Item
347+
text={key + ' ' + image.labelData[key].length}
348+
key={index}
349+
/>
350+
) : null
351+
)}
352+
</Dropdown.Menu>
353+
</Dropdown>
354+
</span>
355+
) : null}
356+
</Table.Cell>
357+
<Table.Cell width={3}>
358+
<div>
359+
<Link to={`/labeller/${projectId}/${image._id}`}>
360+
<Button icon="pencil" label="Edit" size="tiny" />
361+
</Link>
362+
<Button
363+
icon="trash"
364+
label="Delete"
365+
size="tiny"
366+
onClick={async () => {
367+
await onSelect(image._id)
368+
onDelete()
318369
}}
319-
checked={selected}
320370
/>
321-
</Table.Cell>
322-
<Table.Cell width={11}>
323-
<a
324-
href={
325-
process.env.REACT_APP_HOST +
326-
':' +
327-
process.env.REACT_APP_SERVER_PORT +
328-
`/static/uploads/${image.imageUrl}?${Date.now()}`
329-
}
330-
>
331-
{image.imageName}
332-
</a>
333-
{image.labelled ? (
334-
<span className="labelDropdown">
335-
<Dropdown text="Labels">
336-
<Dropdown.Menu>
337-
{Object.keys(image.labelData).map((key, index) =>
338-
image.labelData[key].length !== 0 ?
339-
<Dropdown.Item
340-
text={key + ' ' + image.labelData[key].length}
341-
key={index} />
342-
: null
343-
)}
344-
</Dropdown.Menu>
345-
</Dropdown>
346-
</span>) : null
347-
}
348-
</Table.Cell>
349-
<Table.Cell width={3}>
350-
<div>
351-
<Link to={`/labeller/${projectId}/${image._id}`}>
352-
<Button icon="pencil" label="Edit" size="tiny" />
353-
</Link>
354-
<Button
355-
icon="trash"
356-
label="Delete"
357-
size="tiny"
358-
onClick={async () => {
359-
await onSelect(image._id)
360-
onDelete()
361-
}}
362-
/>
363-
</div>
364-
</Table.Cell>
365-
</Table.Row>
366-
)
371+
</div>
372+
</Table.Cell>
373+
</Table.Row>
374+
)
367375

368376
const AutoSizedList = props => (
369377
<AutoSizer>

0 commit comments

Comments
 (0)