Skip to content

Commit

Permalink
adding ability to delete source + associated records.
Browse files Browse the repository at this point in the history
  • Loading branch information
AnalogJ committed Oct 11, 2023
1 parent 8c4759a commit c590663
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions backend/pkg/database/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
56 changes: 56 additions & 0 deletions backend/pkg/database/sqlite_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
13 changes: 13 additions & 0 deletions backend/pkg/web/handler/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -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})
}
1 change: 1 addition & 0 deletions backend/pkg/web/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ <h6>Manage Source</h6>
<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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/app/services/fasten-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit c590663

Please sign in to comment.