@@ -4,11 +4,29 @@ import { csvUtils } from "./csv-utils.ts";
44import type { GenericEntry } from "../orm/entry/entry-base.ts" ;
55import type { Entry } from "../orm/entry/entry.ts" ;
66import { handlePgError , isPgError } from "../orm/db/postgres/pgError.ts" ;
7+ import { dateUtils } from "@inspatial/cloud/utils" ;
78
89export const dataImport = defineEntry ( "dataImport" , {
910 label : "" ,
1011 description : "" ,
12+ titleField : "title" ,
13+ defaultListFields : [
14+ "title" ,
15+ "entryType" ,
16+ "status" ,
17+ "importType" ,
18+ "totalRecords" ,
19+ "successfulRecords" ,
20+ "failedRecords" ,
21+ ] ,
1122 fields : [ {
23+ key : "title" ,
24+ label : "Title" ,
25+ type : "DataField" ,
26+ required : true ,
27+ readOnly : true ,
28+ defaultValue : "" ,
29+ } , {
1230 key : "csv" ,
1331 label : "" ,
1432 type : "FileField" ,
@@ -26,10 +44,12 @@ export const dataImport = defineEntry("dataImport", {
2644 label : "Status" ,
2745 type : "ChoicesField" ,
2846 choices : [
29- { key : "pending" , label : "Pending" } ,
30- { key : "processing" , label : "Processing" } ,
31- { key : "completed" , label : "Completed" } ,
32- { key : "failed" , label : "Failed" } ,
47+ { key : "pending" , label : "Pending" , color : "primary" } ,
48+ { key : "processing" , label : "Processing" , color : "warning" } ,
49+ { key : "readyForImport" , label : "Ready to Import" , color : "info" } ,
50+ { key : "importing" , label : "Importing" , color : "warning" } ,
51+ { key : "completed" , label : "Completed" , color : "success" } ,
52+ { key : "failed" , label : "Failed" , color : "error" } ,
3353 ] ,
3454 defaultValue : "pending" ,
3555 readOnly : true ,
@@ -77,11 +97,20 @@ export const dataImport = defineEntry("dataImport", {
7797 type : "IntField" ,
7898 defaultValue : 0 ,
7999 readOnly : true ,
100+ } , {
101+ key : "sampleData" ,
102+ label : "Sample Data" ,
103+ type : "JSONField" ,
104+ readOnly : true ,
80105 } , {
81106 key : "errorMessage" ,
82107 label : "Error Message" ,
83108 type : "TextField" ,
84109 readOnly : true ,
110+ } , {
111+ key : "importColumns" ,
112+ type : "ListField" ,
113+ readOnly : true ,
85114 } ] ,
86115} ) ;
87116
@@ -92,6 +121,17 @@ dataImport.addHook("validate", {
92121 const result = orm . getEntryType ( entryType as EntryName ) ;
93122 } ,
94123} ) ;
124+ dataImport . addHook ( "beforeUpdate" , {
125+ name : "generateTitle" ,
126+ description : "Generates the title from the create date and entry type" ,
127+ handler ( { dataImport } ) {
128+ const date = dateUtils . getPrettyDate ( dataImport . $createdAt , {
129+ format : "yyyy-mm-dd" ,
130+ showTime : true ,
131+ } ) ;
132+ dataImport . $title = `Import ${ dataImport . $entryType__title } - ${ date } ` ;
133+ } ,
134+ } ) ;
95135dataImport . addChild ( "columnMap" , {
96136 fields : [ {
97137 key : "columnName" ,
@@ -115,6 +155,7 @@ dataImport.addChild("columnMap", {
115155 } ] ,
116156} ) ;
117157dataImport . addAction ( "getContent" , {
158+ private : true ,
118159 async action ( { dataImport, orm } ) {
119160 if ( ! dataImport . $csv ) {
120161 return { success : false , message : "No CSV file provided" } ;
@@ -128,13 +169,29 @@ dataImport.addAction("getContent", {
128169 } ,
129170} ) ;
130171dataImport . addAction ( "processInfo" , {
172+ label : "Process CSV" ,
173+ description :
174+ "Reads the contents of the uploaded CSV and creates the column map and sets the total row count available for import." ,
131175 async action ( { dataImport, orm } ) {
132- const result = await dataImport . runAction ( "getContent" ) as {
176+ dataImport . $errorMessage = "" ;
177+ dataImport . $totalRecords = null ;
178+ dataImport . $successfulRecords = null ;
179+ dataImport . $failedRecords = null ;
180+ dataImport . $status = "processing" ;
181+ await dataImport . save ( ) ;
182+
183+ const result = await dataImport . runAction ( "getContent" ) . catch ( ( e ) => {
184+ return {
185+ success : false ,
186+ message : e instanceof Error ? e . message : "Unknown error" ,
187+ } ;
188+ } ) as {
133189 success : boolean ;
134190 message ?: string ;
135191 headers ?: Array < string > ;
136192 records ?: Array < Record < string , unknown > > ;
137193 } ;
194+
138195 if ( ! result . success ) {
139196 dataImport . $status = "failed" ;
140197 await dataImport . save ( ) ;
@@ -153,6 +210,10 @@ dataImport.addAction("processInfo", {
153210 ) => [ key , `${ dataImport . $entryType } :${ key } ` ] ) ,
154211 ) ;
155212 const firstRecord = new Map < string , any > ( Object . entries ( records [ 0 ] || { } ) ) ;
213+
214+ const sampleData = records . slice ( 0 , 10 ) ;
215+ dataImport . $sampleData = { data : sampleData } ;
216+
156217 const columnMapData = headers . map ( ( header ) => ( {
157218 columnName : header ,
158219 exampleData : ( firstRecord . get ( header ) || "" ) . toString ( ) . slice ( 0 , 255 ) ,
@@ -161,10 +222,14 @@ dataImport.addAction("processInfo", {
161222
162223 dataImport . $columnMap . update ( columnMapData ) ;
163224 dataImport . $totalRecords = records . length ;
225+ dataImport . $status = "readyForImport" ;
226+ dataImport . $importColumns = headers ;
164227 await dataImport . save ( ) ;
165228 } ,
166229} ) ;
167230dataImport . addAction ( "import" , {
231+ label : "Run Import" ,
232+ description : "Imports the data from the CSV based on the current settings." ,
168233 async action ( { dataImport, orm } ) {
169234 const dataMap = dataImport . $columnMap . data . filter ( ( col ) => col . mapTo ) . map (
170235 ( col ) => ( {
0 commit comments