Skip to content

Commit 59c1789

Browse files
makseqrobot-ci-heartexbmartel
authored andcommitted
feat: LSDV-4974: Add status and debug info to storages (HumanSignal#4059)
* docs: LSDV-4775: Small fixes in storage docs * Revert * feat: LDSV-4979: Add status and debug info to storages * Fix ldclient debug level * Fixes * Fixes with storages * Fix NGINX downloads for export * Add migrations * Fix bug with export annotations and expand_fields in BaseExportSerializer * More feats * Refactoring * Update readme * Add mermaid * Add mermaid * Some * Fix last ping * Fix duration * Add validation on export storage add sync * Add double validation in API * Fix validation api * Rename job_status * Fixes * Fix readme * Add more info for statuses in readme * Fix readme * Add icon * Add more help * Fix texts * Some fixes * Fixes in storage validation * ci: Build frontend * Fix tests in LSE * Fixes for azure export storage validation * Fixed tests and added getLastTraceback * ci: Build frontend * Fixes * Fix pytest * Add migration * Tests * Fix wrong test * Fix update progross in the correct place * Fixes with time_in_progress * Fix frontend * ci: Build frontend * Fixes * ci: Build frontend * fix: Presigned storage tests (HumanSignal#4184) * fix: Presigned storage tests * update all_urls * fix presign url test * Fix azure validation * Update LSP * ci: Build frontend * Remove wrong placeholder in azure * Add migrations * Fix null in total annotations in LSP * Update LSP build * Use timezone.now() instead of datetime * Fix migrations --------- Co-authored-by: robot-ci-heartex <[email protected]> Co-authored-by: bmartel <[email protected]>
1 parent 1ed63d0 commit 59c1789

39 files changed

+1145
-157
lines changed

label_studio/core/settings/base.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
},
6666
'ldclient.util': {
6767
'handlers': ['console'],
68-
'level': 'WARNING',
68+
'level': 'ERROR',
6969
},
7070
},
7171
}
@@ -587,6 +587,9 @@ def collect_versions_dummy(**kwargs):
587587

588588
FUTURE_SAVE_TASK_TO_STORAGE = get_bool_env('FUTURE_SAVE_TASK_TO_STORAGE', default=False)
589589
FUTURE_SAVE_TASK_TO_STORAGE_JSON_EXT = get_bool_env('FUTURE_SAVE_TASK_TO_STORAGE_JSON_EXT', default=True)
590+
STORAGE_IN_PROGRESS_TIMER = get_env('STORAGE_IN_PROGRESS_TIMER', 5.0)
591+
592+
USE_NGINX_FOR_EXPORT_DOWNLOADS = get_bool_env('USE_NGINX_FOR_EXPORT_DOWNLOADS', False)
590593

591594
if get_env('MINIO_STORAGE_ENDPOINT') and not get_bool_env('MINIO_SKIP', False):
592595
CLOUD_FILE_STORAGE_ENABLED = True

label_studio/data_export/api.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -552,14 +552,24 @@ def get(self, request, *args, **kwargs):
552552
url = file.storage.url(file.name, storage_url=True)
553553
protocol = urlparse(url).scheme
554554

555-
# Let NGINX handle it
556-
response = HttpResponse()
557-
# The below header tells NGINX to catch it and serve, see docker-config/nginx-app.conf
558-
redirect = '/file_download/' + protocol + '/' + url.replace(protocol + '://', '')
559-
560-
response['X-Accel-Redirect'] = redirect
561-
response['Content-Disposition'] = 'attachment; filename="{}"'.format(file.name)
562-
return response
555+
# NGINX downloads are a solid way to make uwsgi workers free
556+
if settings.USE_NGINX_FOR_EXPORT_DOWNLOADS:
557+
# let NGINX handle it
558+
response = HttpResponse()
559+
# below header tells NGINX to catch it and serve, see docker-config/nginx-app.conf
560+
redirect = '/file_download/' + protocol + '/' + url.replace(protocol + '://', '')
561+
response['X-Accel-Redirect'] = redirect
562+
response['Content-Disposition'] = 'attachment; filename="{}"'.format(file.name)
563+
response['filename'] = os.path.basename(file.name)
564+
return response
565+
566+
# No NGINX: standard way for export downloads in the community edition
567+
else:
568+
ext = file.name.split('.')[-1]
569+
response = RangedFileResponse(request, file, content_type=f'application/{ext}')
570+
response['Content-Disposition'] = f'attachment; filename="{file.name}"'
571+
response['filename'] = os.path.basename(file.name)
572+
return response
563573
else:
564574
if export_type is None:
565575
file_ = snapshot.file
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 3.2.16 on 2023-04-19 11:36
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('data_export', '0009_alter_convertedformat_traceback'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='convertedformat',
15+
name='export_type',
16+
field=models.CharField(max_length=64),
17+
),
18+
]

label_studio/data_export/models.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,7 @@ class Status(models.TextChoices):
219219
help_text='Traceback report in case of errors'
220220
)
221221
export_type = models.CharField(
222-
max_length=64,
223-
choices=Status.choices,
224-
default=Status.CREATED,
222+
max_length=64
225223
)
226224
created_at = models.DateTimeField(
227225
_('created at'),

label_studio/data_export/serializers.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class Meta:
7777
expandable_fields = {
7878
'drafts': (AnnotationDraftSerializer, {'many': True}),
7979
'predictions': (PredictionSerializer, {'many': True}),
80+
'annotations': (AnnotationSerializer, {'many': True})
8081
}
8182

8283

label_studio/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"truncate-middle": "^1.0.6",
9494
"typescript": "^4.2.2",
9595
"webpack": "^5.80.0",
96-
"webpack-cli": "^5.0.2"
96+
"webpack-cli": "^5.1.1"
9797
},
9898
"babel": {
9999
"presets": [

label_studio/frontend/src/assets/icons/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ export { default as IconTerminal } from './terminal.svg';
2424
export { default as LsThumbsDown } from './thumbs-down.svg';
2525
export { default as LsThumbsUp } from './thumbs-up.svg';
2626
export { default as IconUpload } from './upload.svg';
27-
export { default as LsPencil } from './pencil.svg';
27+
export { default as LsPencil } from './pencil.svg';
28+
export { default as IconInfoOutline } from './info-outline.svg';
Lines changed: 3 additions & 0 deletions
Loading

label_studio/frontend/src/components/Card/Card.styl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.card
22
border-radius 5px
33
background-color rgba(#000, 0.03)
4+
border 1px solid rgba(#000, 0.05)
45

56
&__header
67
display flex
@@ -9,9 +10,9 @@
910
align-items center
1011
font-weight 500
1112
font-size 16px
12-
line-height 22px
13+
line-height 18px
1314
justify-content space-between
14-
box-shadow 0 1px 0 0 rgba(#000, 0.15)
15+
box-shadow 0 1px 0 0 rgba(#000, 0.1)
1516

1617
&-content
1718
display flex

label_studio/frontend/src/components/Columns/Columns.styl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
font-weight 500
1111
font-size 16px
1212
line-height 22px
13-
padding 0 16px
13+
padding 0 16px 0 0

label_studio/frontend/src/components/DescriptionList/DescriptionList.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
22
import { cn } from '../../utils/bem';
33
import './DescriptionList.styl';
4+
import { IconInfoOutline } from '../../assets/icons';
5+
import { Tooltip } from '../../components/Tooltip/Tooltip';
46

57
export const DescriptionList = ({style, className, children}) => {
68
return (
@@ -10,10 +12,16 @@ export const DescriptionList = ({style, className, children}) => {
1012
);
1113
};
1214

13-
DescriptionList.Item = ({ retmClassName, descriptionClassName, term, descriptionStyle, termStyle, children }) => {
15+
DescriptionList.Item = ({ retmClassName, descriptionClassName, term, descriptionStyle, termStyle, children, help }) => {
1416
return (
1517
<>
16-
<dt className={cn('dl').elem('dt').mix(retmClassName)} style={descriptionStyle}>{term}</dt>
18+
<dt className={cn('dl').elem('dt').mix(retmClassName)} style={descriptionStyle}>
19+
{term} {help ? (
20+
<Tooltip style={{ whiteSpace: "pre-wrap" }} title={help}>
21+
<IconInfoOutline className={cn('help-icon')} width="14" height="14" />
22+
</Tooltip>
23+
): "" }
24+
</dt>
1725
<dd className={cn('dl').elem('dd').mix(descriptionClassName)} style={termStyle}>{children}</dd>
1826
</>
1927
);

label_studio/frontend/src/components/DescriptionList/DescriptionList.styl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
font-size 16px
55
line-height 22px
66
color rgba(#000, 0.6)
7-
grid-template-columns 30% 70%
7+
grid-template-columns 40% 60%
88
grid-row-gap 12px
99

1010
&__dt
1111
font-weight 500
12+
min-width 300px
1213

1314
&__dd
1415
margin 0
16+
17+
.help-icon
18+
opacity 0.5
19+
top 1px
20+
position relative

label_studio/frontend/src/components/Tooltip/Tooltip.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import { Children, cloneElement, forwardRef, useCallback, useEffect, useMemo, us
22
import { createPortal } from "react-dom";
33
import { Block, Elem } from "../../utils/bem";
44
import { alignElements } from "../../utils/dom";
5+
import { isDefined } from "../../utils/helpers";
56
import { aroundTransition } from "../../utils/transition";
67
import "./Tooltip.styl";
78

89
export const Tooltip = forwardRef(
9-
({ title, children, defaultVisible, disabled, style }, ref) => {
10+
({ title, children, alignment, defaultVisible, disabled, style }, ref) => {
1011
if (!children || Array.isArray(children)) {
1112
throw new Error("Tooltip does accept a single child only");
1213
}
@@ -18,18 +19,23 @@ export const Tooltip = forwardRef(
1819
defaultVisible ? "visible" : null,
1920
);
2021
const [injected, setInjected] = useState(false);
21-
const [align, setAlign] = useState('top-center');
22+
const [align, setAlign] = useState(alignment ?? 'top-center');
2223

2324
const calculatePosition = useCallback(() => {
24-
const { left, top, align: resultAlign } = alignElements(
25-
triggerElement.current,
26-
tooltipElement.current,
27-
align,
28-
10,
29-
);
25+
const parent = triggerElement.current;
26+
const target = tooltipElement.current;
3027

31-
setOffset({ left, top });
32-
setAlign(resultAlign);
28+
if (isDefined(parent) && isDefined(target)) {
29+
const { left, top, align: resultAlign } = alignElements(
30+
parent,
31+
target,
32+
align,
33+
10,
34+
);
35+
36+
setOffset({ left, top });
37+
setAlign(resultAlign);
38+
}
3339
}, [triggerElement.current, tooltipElement.current]);
3440

3541
const performAnimation = useCallback(

label_studio/frontend/src/pages/Settings/StorageSettings/StorageCard.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ export const StorageCard = ({
4343
setStorageData(storage);
4444
}, [storage]);
4545

46+
const notSyncedYet = synced !== null || ['in_progress', 'queued'].includes(storageData.status);
47+
4648
return (
4749
<Card
48-
header={storageData.title ?? `Untitled ${storageData.type}`}
50+
header={storageData.title.slice(0, 70) ?? `Untitled ${storageData.type}`}
4951
extra={(
5052
<Dropdown.Trigger align="right" content={(
5153
<Menu size="compact" style={{ width: 110 }}>
@@ -58,21 +60,26 @@ export const StorageCard = ({
5860
)}
5961
>
6062
<StorageSummary
63+
target={target}
6164
storage={storageData}
6265
className={rootClass.elem('summary')}
6366
storageTypes={storageTypes}
6467
/>
6568
<div className={rootClass.elem('sync')}>
66-
<Space size="small">
67-
<Button waiting={syncing} onClick={startSync}>
69+
<div>
70+
<Button
71+
waiting={syncing}
72+
onClick={startSync}
73+
disabled={notSyncedYet}
74+
>
6875
Sync Storage
6976
</Button>
70-
{synced !== null ? (
77+
{notSyncedYet && (
7178
<div className={rootClass.elem('sync-count')}>
72-
Synced {synced} task(s)
79+
Syncing may take some time, please refresh the page to see the current status.
7380
</div>
74-
) : null}
75-
</Space>
81+
)}
82+
</div>
7683
</div>
7784
</Card>
7885
);

label_studio/frontend/src/pages/Settings/StorageSettings/StorageSet.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const StorageSet = ({title, target, rootClass, buttonLabel}) => {
2121
target,
2222
},
2323
}).then(types => {
24-
setStorageTypes(types);
24+
setStorageTypes(types ?? []);
2525
});
2626
}, []);
2727

label_studio/frontend/src/pages/Settings/StorageSettings/StorageSettings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Block, cn } from '../../../utils/bem';
55
import { StorageSet } from './StorageSet';
66
import './StorageSettings.styl';
77

8+
89
export const StorageSettings = () => {
910
const rootClass = cn("storage-settings");
1011

label_studio/frontend/src/pages/Settings/StorageSettings/StorageSettings.styl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.storage-settings
22
max-width 680px
3+
padding 40px
34

45
&__description
56
font-size 16px
@@ -48,5 +49,7 @@
4849
align-items center
4950

5051
&__sync-count
52+
margin-top 14px
53+
line-height 18px
5154
font-size 14px
5255
opacity 0.7

0 commit comments

Comments
 (0)