adding ability to delete source + associated records.

This commit is contained in:
Jason Kulatunga 2023-10-11 07:54:18 -07:00
parent 8c4759a236
commit c590663537
No known key found for this signature in database
7 changed files with 122 additions and 1 deletions

View File

@ -38,6 +38,7 @@ type DatabaseRepository interface {
GetSourceSummary(context.Context, string) (*models.SourceSummary, error)
GetSources(context.Context) ([]models.SourceCredential, error)
UpdateSource(ctx context.Context, sourceCreds *models.SourceCredential) error
DeleteSource(ctx context.Context, sourceId string) (int64, error)
CreateGlossaryEntry(ctx context.Context, glossaryEntry *models.Glossary) error
GetGlossaryEntry(ctx context.Context, code string, codeSystem string) (*models.Glossary, error)

View File

@ -976,6 +976,62 @@ func (sr *SqliteRepository) GetSources(ctx context.Context) ([]models.SourceCred
return sourceCreds, results.Error
}
func (sr *SqliteRepository) DeleteSource(ctx context.Context, sourceId string) (int64, error) {
currentUser, currentUserErr := sr.GetCurrentUser(ctx)
if currentUserErr != nil {
return 0, currentUserErr
}
if strings.TrimSpace(sourceId) == "" {
return 0, fmt.Errorf("sourceId cannot be blank")
}
//delete all resources for this source
sourceUUID, err := uuid.Parse(sourceId)
if err != nil {
return 0, err
}
rowsEffected := int64(0)
resourceTypes := databaseModel.GetAllowedResourceTypes()
for _, resourceType := range resourceTypes {
tableName, err := databaseModel.GetTableNameByResourceType(resourceType)
if err != nil {
return 0, err
}
results := sr.GormClient.WithContext(ctx).
Where(models.OriginBase{
UserID: currentUser.ID,
SourceID: sourceUUID,
}).
Table(tableName).
Delete(&models.ResourceBase{})
rowsEffected += results.RowsAffected
if results.Error != nil {
return rowsEffected, results.Error
}
}
//delete relatedResources entries
results := sr.GormClient.WithContext(ctx).
Where(models.RelatedResource{ResourceBaseUserID: currentUser.ID, ResourceBaseSourceID: sourceUUID}).
Delete(&models.RelatedResource{})
if results.Error != nil {
return rowsEffected, results.Error
}
//soft delete the source credential
results = sr.GormClient.WithContext(ctx).
Where(models.SourceCredential{
ModelBase: models.ModelBase{
ID: sourceUUID,
},
UserID: currentUser.ID,
}).
Delete(&models.SourceCredential{})
rowsEffected += results.RowsAffected
return rowsEffected, results.Error
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Background Job
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -312,3 +312,16 @@ func ListSource(c *gin.Context) {
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": sourceCreds})
}
func DeleteSource(c *gin.Context) {
logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry)
databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository)
rowsEffected, err := databaseRepo.DeleteSource(c, c.Param("sourceId"))
if err != nil {
logger.Errorln("An error occurred while deleting source credential", err)
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "data": rowsEffected})
}

View File

@ -68,6 +68,7 @@ func (ae *AppEngine) Setup() (*gin.RouterGroup, *gin.Engine) {
secure.POST("/source/manual", handler.CreateManualSource)
secure.GET("/source", handler.ListSource)
secure.GET("/source/:sourceId", handler.GetSource)
secure.DELETE("/source/:sourceId", handler.DeleteSource)
secure.POST("/source/:sourceId/sync", handler.SourceSync)
secure.GET("/source/:sourceId/summary", handler.GetSourceSummary)
secure.GET("/resource/fhir", handler.ListResourceFhir)

View File

@ -45,7 +45,7 @@
<button ngbDropdownItem (click)="sourceSyncHandler(modalSelectedSourceListItem.source)" type="button" class="btn btn-indigo">Sync</button>
<!-- <button ngbDropdownItem (click)="connectHandler($event, modalSelectedSourceListItem.source['source_type'])" type="button" class="btn btn-outline-light">Reconnect</button>-->
<button ngbDropdownItem type="button" class="btn disabled btn-outline-danger">Reconnect</button>
<button ngbDropdownItem type="button" class="btn disabled btn-outline-danger">Delete</button>
<button ngbDropdownItem (click)="sourceDeleteHandler()" type="button" class="btn btn-outline-danger">Delete</button>
</div>
</div>
<button (click)="modal.dismiss('Close click')" type="button" class="btn btn-outline-light">Close</button>

View File

@ -323,6 +323,47 @@ export class MedicalSourcesConnectedComponent implements OnInit {
)
}
public sourceDeleteHandler(){
let source = this.modalSelectedSourceListItem.source
let sourceDisplayName = this.modalSelectedSourceListItem?.metadata?.display || this.modalSelectedSourceListItem?.source?.source_type || 'unknown'
this.status[source.id] = "authorize"
this.modalService.dismissAll()
this.fastenApi.deleteSource(source.id).subscribe(
(respData) => {
delete this.status[source.id]
delete this.status[source.source_type]
//delete this source from the connnected list
let foundIndex = this.connectedSourceList.findIndex((connectedSource) => {
return connectedSource?.source?.id == source.id
}, this)
if(foundIndex > -1){
this.connectedSourceList.splice(foundIndex, 1)
}
console.log("source delete response:", respData)
const toastNotification = new ToastNotification()
toastNotification.type = ToastType.Success
toastNotification.message = `Successfully deleted source: ${sourceDisplayName}, ${respData} row(s) effected`
this.toastService.show(toastNotification)
},
(err) => {
delete this.status[source.id]
delete this.status[source.source_type]
const toastNotification = new ToastNotification()
toastNotification.type = ToastType.Error
toastNotification.message = `An error occurred while deleting source: ${sourceDisplayName}`
this.toastService.show(toastNotification)
console.log(err)
})
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {

View File

@ -137,6 +137,15 @@ export class FastenApiService {
);
}
deleteSource(sourceId: string): Observable<number> {
return this._httpClient.delete<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/source/${sourceId}`)
.pipe(
map((response: ResponseWrapper) => {
return response.data as number
})
);
}
syncSource(sourceId: string): Observable<any> {
return this._httpClient.post<any>(`${GetEndpointAbsolutePath(globalThis.location, environment.fasten_api_endpoint_base)}/secure/source/${sourceId}/sync`, {})
.pipe(