<file_sep>import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from "@angular/forms";
import { CRUDService } from '../crud.service';

@Component({
  selector: 'app-update',
  templateUrl: './update.component.html',
  styleUrls: ['./update.component.scss']
})
export class UpdateComponent implements OnInit {

  audioType!: string;
  Response: any;

  podcastInfo: FormGroup = new FormGroup({});

  songInfo: FormGroup = new FormGroup({});

  audiobookInfo: FormGroup = new FormGroup({});

  constructor(private flaskServiceApi: CRUDService) { }

  ngOnInit(): void {
    this.podcastInfo = new FormGroup(

      {
        ID: new FormControl('', [Validators.required]),
        Name: new FormControl(''),
        Duration: new FormControl(0),
        Host: new FormControl('', [Validators.maxLength(100)]),
        Participants: new FormControl('')

      }
    )
    this.songInfo = new FormGroup(
      {
        ID: new FormControl('', [Validators.required]),
        Name: new FormControl(''),
        Duration: new FormControl(0),

      }
    )
    this.audiobookInfo = new FormGroup(
      {
        ID: new FormControl('', [Validators.required]),
        Name: new FormControl(''),
        Author: new FormControl(''),
        Duration: new FormControl(0),
        Narrator: new FormControl('')

      }
    )


  }


  ///ID and Type entered + META DATA updated
  onSubmit() {
    let audiofileInfo: any;
    if (this.audioType == 'song') { audiofileInfo = this.songInfo.value }
    if (this.audioType == 'podcast') { audiofileInfo = this.podcastInfo.value }
    if (this.audioType == 'audiobook') { audiofileInfo = this.audiobookInfo.value }
    audiofileInfo['uploadDate'] = new Date();
    console.log(typeof (this.audioType))

    console.log("yay", audiofileInfo)

    this.flaskServiceApi.updateData(this.audioType, audiofileInfo['ID'], audiofileInfo).subscribe(res => {
      console.log(res); this.Response = [res];
    })


  }
}
<file_sep>import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-audiofileui',
  templateUrl: './audiofileui.component.html',
  styleUrls: ['./audiofileui.component.scss']
})
export class AudiofileuiComponent implements OnInit {

  /** id,name,duration,uploaddate-time**/

  /** id,name,duration,uploaddate-time**/

  public song!: boolean;
  podcast!: boolean;
  audiobook!: boolean;

  ngOnInit() {


  }
  Song() {
    this.song = true;
    this.podcast = false;
    this.audiobook = false;
    console.log(this.song)
  }
  Podcast() {
    this.song = false;
    this.podcast = true;
    this.audiobook = false;
  }
  Audiobook() {
    this.song = false;
    this.podcast = false;
    this.audiobook = true;
  }

}
<file_sep># filed-flask-angular
Filed.com: audio file CRUD (flask server + angular UI) 


This test only specified the tech stack for api: flask and Database:Mongodb. I have taken the liberty to use angular for UI.

To run the project:
1. clone the repo
2. run server.py using the given command: "py server.py"
3. start the angular application from FileUI folder using the given command: "npm start"
4. the project will run in http//localhost:4200

There is also a screen recording of the project for a quick look: FiledFlaskAngularMongoDb.webm


Incase of missing packages error:
Please run "npm install" after deleting the node_modules folder
<file_sep>import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AudiofileuiComponent } from './audiofileui.component';

describe('AudiofileuiComponent', () => {
  let component: AudiofileuiComponent;
  let fixture: ComponentFixture<AudiofileuiComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ AudiofileuiComponent ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AudiofileuiComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
<file_sep>import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from "@angular/forms";
import { CRUDService } from 'src/app/crud.service';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.scss']
})
export class CreateComponent implements OnInit {
  audioType!: string;

  podcastInfo: FormGroup = new FormGroup({});

  songInfo: FormGroup = new FormGroup({});

  audiobookInfo: FormGroup = new FormGroup({});
  Response: any;


  constructor(private flaskServiceApi: CRUDService) { }

  ngOnInit(): void {
    this.songInfo = new FormGroup(
      {
        Name: new FormControl('', [Validators.required]),
        Duration: new FormControl(0, [Validators.required, Validators.min(1)]),

      }
    )

    this.podcastInfo = new FormGroup(
      {
        Name: new FormControl('', [Validators.required]),
        Duration: new FormControl(0, [Validators.required, Validators.min(1)]),
        Host: new FormControl('', [Validators.required, Validators.maxLength(100)]),
        Participants: new FormControl('')

      }
    )

    this.audiobookInfo = new FormGroup(
      {
        Name: new FormControl('', [Validators.required]),
        Author: new FormControl('', [Validators.required, Validators.maxLength(100)]),
        Duration: new FormControl(0, [Validators.required, Validators.min(1)]),
        Narrator: new FormControl('', [Validators.required, Validators.maxLength(100)])

      }
    )

  }
  // TYPE AND META-DATA entered ; ID returned
  onSubmit() {
    let audiofileInfo: any;
    let file = {};
    if (this.audioType == 'song') { audiofileInfo = this.songInfo.value }
    if (this.audioType == 'podcast') { audiofileInfo = this.podcastInfo.value }
    if (this.audioType == 'audiobook') { audiofileInfo = this.audiobookInfo.value }
    audiofileInfo['uploadDate'] = new Date();
    file = { 'type': this.audioType, 'metaData': audiofileInfo }
    console.log("yay", audiofileInfo)

    this.flaskServiceApi.createData(file).subscribe(res => {
      console.log(res); this.Response = res;
    })


  }
}<file_sep>import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from "@angular/forms";
import { CRUDService } from '../crud.service';

@Component({
  selector: 'app-delete',
  templateUrl: './delete.component.html',
  styleUrls: ['./delete.component.scss']
})
export class DeleteComponent implements OnInit {

  audiofileInfo: FormGroup = new FormGroup({});
  audioType!: string;
  Response: any;

  constructor(private flaskServiceApi: CRUDService) { }
  audiofileType(event: string) {

    this.audioType = event
    console.log(this.audioType)
  }


  /** The route will be in the following format: “<audioFileType>/<audioFileID>”**/

  ngOnInit() {
    this.audiofileInfo = new FormGroup(
      {
        audiofileID: new FormControl('', [Validators.required]),

      }
    )

  }


  onSubmit() {
    console.log("yay", this.audiofileInfo.value)
    this.flaskServiceApi.deleteData(this.audioType, this.audiofileInfo.value['audiofileID']).subscribe(res => { this.Response = res })
  }

}
<file_sep>import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';


@Injectable({
  providedIn: 'root'
})
export class CRUDService {

  constructor(private http: HttpClient) { }

  ///IF CONNECTION TO SERVER FAILS
  handleError(error: HttpErrorResponse) {
    let errorMessage = 'Unknown error!';
    if (error.error instanceof ErrorEvent) {
      // Client-side errors
      errorMessage = `Error: ${error.error.message}`;
    } else {
      // Server-side errors
      errorMessage = `Error Code: ${error.status}\n Message: ${error.message}. Maybe server.py is not running`;
    }
    window.alert(errorMessage);
    return throwError(errorMessage);
  }

  public server = "http://localhost/audioFile/";

  public getData(audioFileType: string, fileID: string) {
    let data = (fileID != '') ? this.http.get(this.server + `readData/${audioFileType}/${fileID}`).pipe(catchError(this.handleError)) : this.http.get(this.server + `readData/${audioFileType}/empty`).pipe(catchError(this.handleError));
    return data
  }

  public createData(audioFile: any) {
    let response = this.http.post(this.server + `create`, audioFile).pipe(catchError(this.handleError));
    return response
  }
  //audiodileType/audiofileID
  public updateData(audioFileType: string, audiofileID: string, audioFile: any) {
    let response = this.http.patch(this.server + `updateData/${audioFileType}/${audiofileID}`, audioFile)//.pipe(catchError(this.handleError))
    return response

  }
  public deleteData(audioFileType: string, audioFileID: string) {
    let response = this.http.delete(this.server + `delete/${audioFileType}/${audioFileID}`)
    return response

  }
}
<file_sep>import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validator, Validators } from "@angular/forms";
import { CRUDService } from '../crud.service';

@Component({
  selector: 'app-read',
  templateUrl: './read.component.html',
  styleUrls: ['./read.component.scss']
})
export class ReadComponent implements OnInit {
  audiofileInfo: FormGroup = new FormGroup({});
  audioType!: string;
  data: any;

  constructor(private flaskApiService: CRUDService) { }
  audiofileType(event: string) {

    this.audioType = event
    console.log(this.audioType)
  }


  /** The route will be in the following format: “<audioFileType>/<audioFileID>”**/

  ngOnInit() {
    this.audiofileInfo = new FormGroup(
      {
        audiofileID: new FormControl(''),

      }
    )
  }

  onSubmit() {
    console.log(this.audioType)
    this.flaskApiService.getData(this.audioType, this.audiofileInfo.value['audiofileID']).subscribe(res => { console.log(res); this.data = res })

  }


}
<file_sep>from flask import Flask,Response,request,render_template
import pymongo
import json
import bson

app = Flask(__name__)


try:
    mongo=pymongo.MongoClient(
        host="localhost",
        port=27017,
        serverSelectionTimeoutMS=1000
    )
    db=mongo.filed
    mongo.server_info() ##trigger if cannot connect to db
    print("DB CONNECTION---SUCCESS!!")
except Exception as ex:
    print(ex)
    print("ERROR - Cannot connect to  DB")


@app.after_request
def after_request(response):
  response.headers['Access-Control-Allow-Origin']='*'
  response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
  response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS')
  response.headers.add('Access-Control-Allow-Credentials', 'true')
  response.headers['X-Content-Type-Options'] = 'nosniff'
  return response

###################
# READ AUDIOFILE
@app.route("/audioFile/readData/<filetype>/<fileid>",methods=["GET"])
def get_some_file(filetype,fileid):
    try:
        if(fileid=='empty'):
            data =  list(db.audiofiles.find({'type':filetype}))
        else:
            data = list(db.audiofiles.find({'_id':bson.ObjectId(oid=str(fileid)),'type':filetype}))
    
        for file in data:
            file["_id"]=str(file["_id"])

        if(json.dumps(data)=='[]'):
            return Response(
                response=json.dumps({"message":"Sorry file cannot be found.Please check the id and type selected"}),
                status=200,
                mimetype="application/json")
        
        else:    
            return Response(
                response=json.dumps(data),
                status=200,
                mimetype="application/json"
            )
    except Exception as ex:
        print(ex)
        return Response(response=json.dumps({"message":"Can not find file. Please check the id and type selected"}),status=500,mimetype="application/json")

###################
#CREATE NEW AUDIO FILE
@app.route("/audioFile/create",methods=["POST"])
def postAudioFile():
    audiofile=json.loads(request.data.decode())
    print(type(audiofile),audiofile)
    try:
        dbResponse=db.audiofiles.insert_one(audiofile)
        # for attr in dir(dbResponse):
        #     print(attr)
        return Response(
            response=json.dumps(
                {"message":"audio file added to db",
                "id":f"{dbResponse.inserted_id}"
                }),
            status=200,
            mimetype="application/json"
        )
    except Exception as ex:
        print("**************")
        print(ex)        
        print("**************")
        return ex 

###################
#UPDATE NEW AUDIO FILE
@app.route("/audioFile/updateData/<filetype>/<fileid>",methods=["PATCH"])
def update_some_file(filetype,fileid):
    
    # audiofile=request.data.decode()
    
    try:
        jsonMetadata=json.loads(request.data.decode())
        newMetadata={}
        del jsonMetadata['ID']
        currentMetadata=(db.audiofiles.find_one({'type':filetype,'_id':bson.ObjectId(oid=str(fileid))}))
        currentMetadata=currentMetadata['metaData']
        for k in currentMetadata:
            print("JSON DATA:",jsonMetadata[k])
            if(jsonMetadata[k]==''):
                print("in if")
                newMetadata[k]=currentMetadata[k]
            else:
                newMetadata[k]=jsonMetadata[k]
        print(newMetadata)
    
        dbResponse=db.audiofiles.update_one({'type':filetype,'_id':bson.ObjectId(oid=str(fileid))},{'$set':{'metaData':newMetadata
        }})
        if(dbResponse.modified_count==1):
             return Response(
                response=json.dumps({'message':'Update made',"status":200}),
                status=200
                )
        else:
            return Response(response=json.dumps({"message":"Could not make update. Please check Type and ID"}),status=200,headers="application/json")

    except Exception as ex:
        print("**************")
        print(ex)        
        print("**************")
        return Response(
            response=json.dumps(
                {"message":"Sorry could not update.Check id and Type.","status":500}),
            status=200,#actually a status 500 
            mimetype="application/json"
        )


###################
#DELETE NEW AUDIO FILE
@app.route("/audioFile/delete/<filetype>/<fileid>",methods=["DELETE"])
def delete_some_file(filetype,fileid):
    print(fileid,filetype)
    try:
        dbResponse=db.audiofiles.delete_one({'_id':bson.ObjectId(oid=str(fileid)),'type':filetype})
        print(dbResponse.deleted_count)
        if(dbResponse.deleted_count==0):
            return Response(
                response=json.dumps(
                    {"message":"Sorry this file doesn't exist. Cannot delete it.",
                    "id":fileid,
                    "type":filetype
                    }),
                status=200,
                mimetype="application/json"
            )
        else:
             return Response(
                response=json.dumps(
                    {"message":"audio file deleted",
                    "id":fileid,
                    "type":filetype
                    }),
                status=200,
                mimetype="application/json"
            )

    except Exception as ex:
        print("**************")
        print(ex)        
        print("**************")
        return Response(
                response=json.dumps(
                    {"message":"Error. Could not delete file.",
                    "id":fileid,
                    "type":filetype,
                    "status":500
                    }),
                status=200,
                mimetype="application/json"
            )



if(__name__ =="__main__"):
    app.run(port=80,debug=True)