1- import { InboxOutlined , ReloadOutlined , WarningOutlined } from "@ant-design/icons" ;
1+ import { DownloadOutlined , InboxOutlined , ReloadOutlined } from "@ant-design/icons" ;
22import { createTaskFromNML , createTasks , getTask , updateTask } from "admin/api/tasks" ;
33import {
44 getActiveDatasetsOfMyOrganization ,
@@ -15,11 +15,13 @@ import type {
1515} from "admin/task/task_create_bulk_view" ;
1616import { NUM_TASKS_PER_BATCH , normalizeFileEvent } from "admin/task/task_create_bulk_view" ;
1717import {
18+ Alert ,
1819 App ,
1920 Button ,
2021 Card ,
2122 Col ,
2223 Divider ,
24+ Flex ,
2325 Form ,
2426 Input ,
2527 InputNumber ,
@@ -29,6 +31,7 @@ import {
2931 Select ,
3032 Spin ,
3133 Tooltip ,
34+ Typography ,
3235 Upload ,
3336 type UploadFile ,
3437} from "antd" ;
@@ -37,9 +40,13 @@ import { AsyncButton } from "components/async_clickables";
3740import { formatDateInLocalTimeZone } from "components/formatted_date" ;
3841import SelectExperienceDomain from "components/select_experience_domain" ;
3942import { saveAs } from "file-saver" ;
40- import { coalesce , tryToAwaitPromise } from "libs/utils" ;
43+ import { coalesce , pluralize , tryToAwaitPromise } from "libs/utils" ;
4144import { Vector3Input , Vector6Input } from "libs/vector_input" ;
42- import _ from "lodash" ;
45+ import isEqual from "lodash/isEqual" ;
46+ import isNil from "lodash/isNil" ;
47+ import omit from "lodash/omit" ;
48+ import omitBy from "lodash/omitBy" ;
49+ import uniq from "lodash/uniq" ;
4350import messages from "messages" ;
4451import React , { useEffect , useState } from "react" ;
4552import { useNavigate , useParams } from "react-router-dom" ;
@@ -108,7 +115,7 @@ export function downloadTasksAsCSV(tasks: Array<APITask>) {
108115 const lastCreationTime = Math . max ( ...tasks . map ( ( task ) => task . created ) ) ;
109116 const currentDateAsString = formatDateInLocalTimeZone ( lastCreationTime , "YYYY-MM-DD_HH-mm" ) ;
110117
111- const allProjectNames = _ . uniq ( tasks . map ( ( task ) => task . projectName ) ) . join ( "_" ) ;
118+ const allProjectNames = uniq ( tasks . map ( ( task ) => task . projectName ) ) . join ( "_" ) ;
112119
113120 const allTasksAsStrings = tasks . map ( ( task ) => taskToText ( task ) ) . join ( "\n" ) ;
114121 const csv = [ TASK_CSV_HEADER , allTasksAsStrings ] . join ( "\n" ) ;
@@ -128,9 +135,7 @@ export function handleTaskCreationResponse(
128135 const successfulTasks : APITask [ ] = [ ] ;
129136 const failedTasks : string [ ] = [ ] ;
130137 let teamName : string | null = null ;
131- const subHeadingStyle : React . CSSProperties = {
132- fontWeight : "bold" ,
133- } ;
138+
134139 const displayResultsStyle : React . CSSProperties = {
135140 maxHeight : 300 ,
136141 overflow : "auto" ,
@@ -148,7 +153,7 @@ export function handleTaskCreationResponse(
148153 }
149154 } ) ;
150155
151- const allProjectNames = _ . uniq ( successfulTasks . map ( ( task ) => task . projectName ) ) ;
156+ const allProjectNames = uniq ( successfulTasks . map ( ( task ) => task . projectName ) ) ;
152157
153158 if ( allProjectNames . length > 1 ) {
154159 warnings . push (
@@ -159,73 +164,64 @@ export function handleTaskCreationResponse(
159164 const warningsContent =
160165 warnings . length > 0 ? (
161166 < div >
162- < div style = { subHeadingStyle } >
163- < WarningOutlined
164- style = { {
165- color : "var(--ant-color-warning)" ,
166- } }
167- /> { " " }
168- There were warnings during task creation:
169- </ div >
170- < div
171- style = { {
172- whiteSpace : "pre-line" ,
173- } }
174- >
175- { warnings . join ( "\n" ) }
176- </ div >
167+ < Alert
168+ showIcon
169+ type = "warning"
170+ title = "There were warnings during task creation"
171+ description = { warnings . join ( "\n" ) }
172+ />
177173 </ div >
178174 ) : null ;
179175
180176 const failedTasksAsString = failedTasks . join ( "" ) ;
181177 const successfulTasksContent =
182178 successfulTasks . length <= maxDisplayedTasksCount ? (
183- < pre >
184- taskId,filename,position
185- < br />
186- { successfulTasks . map ( ( task ) => taskToShortText ( task ) ) . join ( "\n" ) }
187- </ pre >
179+ < Typography . Paragraph code >
180+ < pre >
181+ taskId,filename,position
182+ < br />
183+ { successfulTasks . map ( ( task ) => taskToShortText ( task ) ) . join ( "\n" ) }
184+ </ pre >
185+ </ Typography . Paragraph >
188186 ) : (
189187 "Too many tasks to show, please use the CSV download above for a full list."
190188 ) ;
191189 const failedTasksContent =
192190 failedTasks . length <= maxDisplayedTasksCount ? (
193- < pre > { failedTasksAsString } </ pre >
191+ < Typography . Paragraph code copyable >
192+ < pre > { failedTasksAsString } </ pre >
193+ </ Typography . Paragraph >
194194 ) : (
195195 "Too many failed tasks to show, please use the CSV download for a full list."
196196 ) ;
197- const successPlural = successfulTasks . length === 1 ? "" : "s" ;
198- const warningsPlural = warnings . length === 1 ? "" : "s" ;
197+
199198 modal . info ( {
200- title : `${ successfulTasks . length } task ${ successPlural } successfully created, ${ failedTasks . length } failed. ${ warnings . length } warning ${ warningsPlural } .` ,
199+ title : `${ successfulTasks . length } ${ pluralize ( "task" , successfulTasks . length ) } successfully created, ${ failedTasks . length } ${ pluralize ( "task" , failedTasks . length ) } failed. ${ warnings . length } ${ pluralize ( "warning" , warnings . length ) } .` ,
201200 content : (
202201 < div >
203202 { warningsContent }
204203 { successfulTasks . length > 0 ? (
205204 < div >
206- < div
207- style = { {
208- display : "flex" ,
209- justifyContent : "center" ,
210- margin : 20 ,
211- } }
212- >
213- < Button onClick = { ( ) => downloadTasksAsCSV ( successfulTasks ) } type = "primary" >
205+ < Flex justify = "center" style = { { margin : 20 } } >
206+ < Button
207+ onClick = { ( ) => downloadTasksAsCSV ( successfulTasks ) }
208+ type = "primary"
209+ icon = { < DownloadOutlined /> }
210+ >
214211 Download task info as CSV
215212 </ Button >
216- </ div >
217- < div style = { subHeadingStyle } > Successful Tasks: </ div >
213+ </ Flex >
214+ < Typography . Text strong > Successful Tasks:</ Typography . Text >
218215 < div style = { displayResultsStyle } > { successfulTasksContent } </ div >
219216 </ div >
220217 ) : null }
221218 { failedTasks . length > 0 ? (
222219 < React . Fragment >
223220 < Divider />
224221 < div >
225- < div
222+ < Flex
223+ justify = "center"
226224 style = { {
227- display : "flex" ,
228- justifyContent : "center" ,
229225 margin : 20 ,
230226 } }
231227 >
@@ -236,14 +232,13 @@ export function handleTaskCreationResponse(
236232 } ) ;
237233 saveAs ( blob , "failed-tasks.csv" ) ;
238234 } }
235+ icon = { < DownloadOutlined /> }
239236 >
240237 Download failed task info as CSV
241238 </ Button >
242- </ div >
243- < div style = { subHeadingStyle } > Failed Tasks:</ div >
239+ </ Flex >
240+ < Typography . Text strong > Failed Tasks:</ Typography . Text >
244241 < div style = { displayResultsStyle } > { failedTasksContent } </ div >
245- < br />
246- < br />
247242 </ div >
248243 </ React . Fragment >
249244 ) : null }
@@ -255,18 +250,9 @@ export function handleTaskCreationResponse(
255250
256251export function CreateResourceButton ( { text, link } : { text : string ; link : string } ) {
257252 return (
258- < Col span = { 4 } style = { { marginTop : 11 } } >
253+ < Col span = { 4 } style = { { marginBottom : "var(--ant-form-item-margin-bottom)" } } >
259254 < Button block href = { link } target = "_blank" rel = "noreferrer" >
260- < span
261- style = { {
262- display : "block" ,
263- overflow : "hidden" ,
264- whiteSpace : "nowrap" ,
265- textOverflow : "ellipsis" ,
266- } }
267- >
268- { text }
269- </ span >
255+ { text }
270256 </ Button >
271257 </ Col >
272258 ) ;
@@ -280,9 +266,9 @@ export function ReloadResourceButton({
280266 onReload : ( ) => Promise < void > ;
281267} ) {
282268 return (
283- < Col flex = "40px" >
269+ < Col flex = "40px" style = { { marginBottom : "var(--ant-form-item-margin-bottom)" } } >
284270 < Tooltip title = { tooltip } >
285- < AsyncButton style = { { marginTop : 7 } } icon = { < ReloadOutlined /> } onClick = { onReload } />
271+ < AsyncButton icon = { < ReloadOutlined /> } onClick = { onReload } />
286272 </ Tooltip >
287273 </ Col >
288274 ) ;
@@ -349,7 +335,7 @@ function TaskCreateFormView() {
349335 pendingInstances : task . status . pending ,
350336 } ) ;
351337
352- const validFormValues = _ . omitBy ( defaultValues , _ . isNil ) ;
338+ const validFormValues = omitBy ( defaultValues , isNil ) ;
353339
354340 // The task type is not needed for the form and leads to antd errors if it contains null values
355341 const { type, ...neededFormValues } = validFormValues ;
@@ -374,7 +360,7 @@ function TaskCreateFormView() {
374360 if ( taskId != null ) {
375361 // either update an existing task
376362 const newTask = {
377- ..._ . omit ( formValues , "nmlFiles" , "baseAnnotation" ) ,
363+ ...omit ( formValues , "nmlFiles" , "baseAnnotation" ) ,
378364 boundingBox,
379365 } ;
380366 const confirmedTask = await updateTask ( taskId , newTask ) ;
@@ -397,7 +383,7 @@ function TaskCreateFormView() {
397383 const batchOfNmls = nmlFiles . slice ( i , i + NUM_TASKS_PER_BATCH ) ;
398384
399385 const newTask : NewNmlTask = {
400- ..._ . omit ( formValues , "baseAnnotation" ) ,
386+ ...omit ( formValues , "baseAnnotation" ) ,
401387 boundingBox,
402388 } ;
403389 const response = await createTaskFromNML ( newTask , batchOfNmls ) ;
@@ -414,7 +400,7 @@ function TaskCreateFormView() {
414400 : formValues . baseAnnotation ;
415401
416402 const newTask = {
417- ..._ . omit ( formValues , "nmlFiles" , "baseAnnotation" ) ,
403+ ...omit ( formValues , "nmlFiles" , "baseAnnotation" ) ,
418404 boundingBox,
419405 baseAnnotation,
420406 } ;
@@ -426,7 +412,7 @@ function TaskCreateFormView() {
426412
427413 handleTaskCreationResponse ( modal , {
428414 tasks : taskResponses ,
429- warnings : _ . uniq ( warnings ) ,
415+ warnings : uniq ( warnings ) ,
430416 } ) ;
431417 } finally {
432418 setIsUploading ( false ) ;
@@ -503,7 +489,7 @@ function TaskCreateFormView() {
503489
504490 if (
505491 taskResponse ?. datasetId != null &&
506- _ . isEqual ( taskResponse . status , {
492+ isEqual ( taskResponse . status , {
507493 pending : 0 ,
508494 active : 0 ,
509495 finished : 1 ,
@@ -529,7 +515,7 @@ function TaskCreateFormView() {
529515 </ FormItem >
530516 ) : null }
531517
532- < Row gutter = { 8 } align = "middle " wrap = { false } >
518+ < Row gutter = { 8 } align = "bottom " wrap = { false } >
533519 < Col flex = "auto" >
534520 < FormItem
535521 name = "datasetId"
@@ -600,7 +586,6 @@ function TaskCreateFormView() {
600586 const instancesLabel = isEditingMode ? "Remaining Instances" : "Task Instances" ;
601587 return (
602588 < div
603- className = "container"
604589 style = { {
605590 paddingTop : 20 ,
606591 } }
@@ -616,7 +601,7 @@ function TaskCreateFormView() {
616601 editRotation : [ 0 , 0 , 0 ] ,
617602 } }
618603 >
619- < Row gutter = { 8 } align = "middle " wrap = { false } >
604+ < Row gutter = { 8 } align = "bottom " wrap = { false } >
620605 < Col flex = "auto" >
621606 < FormItem
622607 name = "taskTypeId"
@@ -649,7 +634,7 @@ function TaskCreateFormView() {
649634 < CreateResourceButton text = "Create new Task Type" link = "/taskTypes/create" />
650635 </ Row >
651636
652- < Row gutter = { 8 } align = "middle " wrap = { false } >
637+ < Row gutter = { 8 } align = "bottom " wrap = { false } >
653638 < Col span = { 10 } >
654639 < FormItem
655640 name = { [ "neededExperience" , "domain" ] }
@@ -706,7 +691,7 @@ function TaskCreateFormView() {
706691 < InputNumber style = { fullWidth } min = { 0 } />
707692 </ FormItem >
708693
709- < Row gutter = { 8 } align = "middle " wrap = { false } >
694+ < Row gutter = { 8 } align = "bottom " wrap = { false } >
710695 < Col flex = "auto" >
711696 < FormItem
712697 name = "projectName"
@@ -739,7 +724,7 @@ function TaskCreateFormView() {
739724 < CreateResourceButton text = "Create new Project" link = "/projects/create" />
740725 </ Row >
741726
742- < Row gutter = { 8 } align = "middle " wrap = { false } >
727+ < Row gutter = { 8 } align = "bottom " wrap = { false } >
743728 < Col flex = "auto" >
744729 < FormItem name = "scriptId" label = "Script" hasFeedback >
745730 < Select
0 commit comments