Skip to content

Commit

Permalink
Feature(Delete): "Implement Subject Deletion"
Browse files Browse the repository at this point in the history
- Delete class by passing class id to query

related to : dnd-side-project#149
  • Loading branch information
tmdgh1592 committed Feb 23, 2022
1 parent e9d8a52 commit 8f419f3
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ package com.dnd.sixth.lmsservice.data.network.service
import com.dnd.sixth.lmsservice.data.model.generalclass.GeneralSubjectModel
import com.dnd.sixth.lmsservice.data.model.subject.SubjectModel
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query
import retrofit2.http.*

interface SubjectService {
@POST("subject")
fun createSubject(
@Body subjectModel: SubjectModel
): Call<SubjectModel>

@DELETE("subject")
fun deleteSubject(
@Query("id") subjectId: Int
): Call<SubjectModel>

@GET("subject")
fun getGeneralClassList(
@Query("id") uid: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ class SubjectRepositoryImpl(
it.toEntity()
}
}

override suspend fun deleteSubject(subjectId: Int): SubjectEntity? {
return subjectRemoteDataSource.deleteSubject(remoteErrorEmitter, subjectId)?.toEntity()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ import com.dnd.sixth.lmsservice.domain.entity.SubjectEntity
interface SubjectRemoteDataSource {
suspend fun createSubject(remoteErrorEmitter: RemoteErrorEmitter, subjectEntity: SubjectEntity): SubjectModel?
suspend fun getGeneralClassList(remoteErrorEmitter: RemoteErrorEmitter, uid: Int): List<GeneralSubjectModel>?
suspend fun deleteSubject(remoteErrorEmitter: RemoteErrorEmitter, subjectId: Int): SubjectModel?
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ class SubjectRemoteDataSourceImpl(private val subjectApi: SubjectApi) : SubjectR
// Http 통신 결과 (200 코드대인 경우)
if (response.isSuccessful) {
// 서버 DB로부터 받은 DTO객체
val responseObject = response.body()
val subjectModel = response.body() as SubjectModel
if (BuildConfig.DEBUG) {
Log.d(TAG, response.code().toString())
Log.d(TAG, responseObject.toString())
Log.d(TAG, subjectModel.toString())
}

// 코루틴 재게
cont.resumeWith(Result.success(responseObject))
cont.resumeWith(Result.success(subjectModel))
} else { // 서버로부터 에러 반환
Log.d(TAG, response.errorBody().toString())
}
Expand Down Expand Up @@ -79,15 +79,15 @@ class SubjectRemoteDataSourceImpl(private val subjectApi: SubjectApi) : SubjectR
// Http 통신 결과 (200 코드대인 경우)
if (response.isSuccessful) {
// 서버 DB로부터 받은 DTO객체
val responseObject = response.body() as List<GeneralSubjectModel>
val generalSubjectList = response.body() as List<GeneralSubjectModel>

if (BuildConfig.DEBUG) {
Log.d(TAG, response.code().toString())
Log.d(TAG, responseObject.toString())
Log.d(TAG, generalSubjectList.toString())
}

// 코루틴 재게
cont.resumeWith(Result.success(responseObject))
// 코루틴 재게 (성공 데이터 반환)
cont.resumeWith(Result.success(generalSubjectList))
} else { // 서버로부터 에러 반환
Timber.d(response.errorBody().toString())
}
Expand All @@ -101,4 +101,35 @@ class SubjectRemoteDataSourceImpl(private val subjectApi: SubjectApi) : SubjectR
}
})
}

override suspend fun deleteSubject(
remoteErrorEmitter: RemoteErrorEmitter,
subjectId: Int
) : SubjectModel? = suspendCancellableCoroutine { cont ->
subjectApi.api.deleteSubject(subjectId).enqueue(object : Callback<SubjectModel> {
@SuppressLint("LongLogTag")
override fun onResponse(call: Call<SubjectModel>, response: Response<SubjectModel>) {
if (response.isSuccessful) {
// 삭제한 수업 Subject 모델을 받아온다.
val deletedSubjectModel = response.body() as SubjectModel

if (BuildConfig.DEBUG) {
Log.d(TAG, response.code().toString())
Log.d(TAG, deletedSubjectModel.toString())
}

// 삭제한 수업 Subject Model 반환
cont.resumeWith(Result.success(deletedSubjectModel))
} else { // 서버로부터 에러 반환
Timber.d(response.errorBody().toString())
}
}

@SuppressLint("LongLogTag")
override fun onFailure(call: Call<SubjectModel>, cause: Throwable) {
Log.e(TAG, cause.message.toString())
cont.resumeWithException(cause)
}
})
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dnd.sixth.lmsservice.di.modules

import com.dnd.sixth.lmsservice.domain.useCase.CreateSubjectUseCase
import com.dnd.sixth.lmsservice.domain.useCase.DeleteSubjectUseCase
import com.dnd.sixth.lmsservice.domain.useCase.GetGeneralSubjectListUseCase
import org.koin.dsl.module

Expand All @@ -12,4 +13,7 @@ val useCaseModules = module {
factory {
GetGeneralSubjectListUseCase(get())
}
factory {
DeleteSubjectUseCase(get())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ val viewModelModules = module {
MainViewModel()
}
viewModel {
SubjectViewModel(get(), get())
SubjectViewModel(get(), get(), get())
}
viewModel {
EditResponseViewModel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ interface SubjectRepository {
* @return : List<ClassEntity>
* */
suspend fun getGeneralClassList(uid: Int): List<GeneralSubjectEntity>?

/*
* 수업 지우기
* */
suspend fun deleteSubject(subjectId: Int): SubjectEntity?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dnd.sixth.lmsservice.domain.useCase

import com.dnd.sixth.lmsservice.domain.entity.SubjectEntity
import com.dnd.sixth.lmsservice.domain.repository.SubjectRepository

class DeleteSubjectUseCase(private val subjectRepository: SubjectRepository) {
suspend operator fun invoke(subjectId: Int): SubjectEntity? {
return subjectRepository.deleteSubject(subjectId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import com.google.android.material.snackbar.Snackbar


abstract class BaseFragment<T : ViewDataBinding, S : BaseViewModel> : Fragment() {
Expand Down Expand Up @@ -55,4 +56,9 @@ abstract class BaseFragment<T : ViewDataBinding, S : BaseViewModel> : Fragment()
fun showToast(msg: String) {
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
}

// 스낵바 띄우기
fun showSnackBar(msg: String) {
Snackbar.make(binding.root, msg, Snackbar.LENGTH_LONG).show()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import com.dnd.sixth.lmsservice.presentation.main.classmanage.subject.edit.Subje
import com.dnd.sixth.lmsservice.presentation.utility.UnitConverter
import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.android.synthetic.main.layout_edit_delete_bottom_sheet.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber

Expand Down Expand Up @@ -67,7 +71,7 @@ class SubjectFragment : BaseFragment<FragmentClassBinding, SubjectViewModel>(),
}

// 서버로부터 수업 리스틀를 가져와 업데이트한다.
viewModel?.updateGeneralSubjectList()
//viewModel?.updateGeneralSubjectList()

// 수업 리스트가 변경됨에 따라 화면 크기 조절을 하기 위한 Observer
viewModel?.generalSubjectDataList?.observe(this@SubjectFragment) {
Expand Down Expand Up @@ -201,7 +205,7 @@ class SubjectFragment : BaseFragment<FragmentClassBinding, SubjectViewModel>(),
// 삭제 버튼 클릭시, 하단 Dialog 종료와 함께, 삭제 여부를 묻는 Dialog를 보여준다.
deleteBtn.setOnClickListener {
dialog.dismiss() // 하단 Dialog 종료
showDeleteClassDialog() // 삭제 여부를 묻는 Dialog show
showDeleteClassDialog(position) // 삭제 여부를 묻는 Dialog show
}
// 수정 버튼 클릭시, 수업 정보를 Edit할 수 있는 Activity로 이동
editBtn.setOnClickListener {
Expand Down Expand Up @@ -229,13 +233,27 @@ class SubjectFragment : BaseFragment<FragmentClassBinding, SubjectViewModel>(),


// 클래스 삭제 여부를 묻는 다이얼로그를 보여준다.
private fun showDeleteClassDialog() {
private fun showDeleteClassDialog(position: Int) {
// 삭제를 묻는 Dialog Builder 생성
val builder = AlertDialog.Builder(requireContext()).setMessage("클래스를 삭제하시겠어요?")
.setPositiveButton(
"삭제"
) { _, _ ->
// 수업 삭제 로직 수행
CoroutineScope(Dispatchers.IO).launch {
val isSuccess = viewModel.deleteSubject(position) // 수업 삭제
launch(Dispatchers.Main) {
if(isSuccess) {
showSnackBar(getString(R.string.success_delete_subject))

// viewModel의 List에서 해당 수업 삭제 로직 구현 예정
//
//
} else {
showSnackBar(getString(R.string.failed_delete_subject))
}
}
}
}.setNegativeButton("취소")
{ dialog, _ ->
dialog.dismiss()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.dnd.sixth.lmsservice.data.preference.PreferenceManager
import com.dnd.sixth.lmsservice.domain.entity.GeneralSubjectEntity
import com.dnd.sixth.lmsservice.domain.useCase.DeleteSubjectUseCase
import com.dnd.sixth.lmsservice.domain.useCase.GetGeneralSubjectListUseCase
import com.dnd.sixth.lmsservice.presentation.base.BaseViewModel
import com.dnd.sixth.lmsservice.presentation.utility.SAVED_UID_KEY
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class SubjectViewModel(
private val getGeneralSubjectListUseCase: GetGeneralSubjectListUseCase,
private val deleteSubjectUseCase: DeleteSubjectUseCase,
private val preferenceManager: PreferenceManager
) : BaseViewModel() {
/*
Expand All @@ -28,14 +31,26 @@ class SubjectViewModel(
return _generalSubjectList.value?.get(position) ?: throw Exception("Exist no item")
}

/*
* General SubjectList를 서버 DB로부터 갱신

/* General SubjectList를 서버 DB로부터 갱신
* */
fun updateGeneralSubjectList() {
viewModelScope.launch {
val generalSubjectList = getGeneralSubjectListUseCase(preferenceManager.getString(SAVED_UID_KEY)?.toInt()!!)
val generalSubjectList =
getGeneralSubjectListUseCase(preferenceManager.getString(SAVED_UID_KEY)?.toInt()!!)
_generalSubjectList.value = generalSubjectList

}
}

/* 선택한 수업 삭제
* */
suspend fun deleteSubject(position: Int): Boolean =
withContext(viewModelScope.coroutineContext) {
val deleteSubjectId = _generalSubjectList.value?.get(position)?.classId?.toInt()
val deletedSubjectEntity = deleteSubjectId?.let { deleteSubjectUseCase(it) }
(deletedSubjectEntity == null)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class SubjectCreateActivity : BaseActivity<ActivityCreateSubjectBinding, CreateS
setResult(SubjectFragment.INTENT_CREATE_SUBJECT_ACTIVITY_CODE, resultIntent) // 초대코드 Dialog를 보여주기 위한 결과 반환
finish() //액티비티 종료
} else { // 수업 생성 실패
showToast(getString(R.string.failed_make_class)) // 실패 Toast 출력
showToast(getString(R.string.failed_create_subject)) // 실패 Toast 출력
}
}
}
Expand Down
7 changes: 6 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
<string name="no_class_student">아직 클래스가 없어요😯 \n <br/><b>수업이 생성될 때까지 조금만 기다려주세요!</b></string>
<string name="create_class_text">+ 클래스 만들기</string>

<string name="failed_make_class">알 수 없는 이유로 수업에 실패했어요!</string>
<!-- Success Result Message -->
<string name="success_delete_subject">해당 수업이 삭제되었어요.</string>

<!-- Failed Result Message-->
<string name="failed_create_subject">알 수 없는 이유로 수업에 실패했어요!</string>
<string name="failed_delete_subject">알 수 없는 이유로 수업 삭제에 실패했어요!</string>

</resources>

0 comments on commit 8f419f3

Please sign in to comment.